Skip to content

Commit

Permalink
fixup! Implement Certificate Revocation List
Browse files Browse the repository at this point in the history
  • Loading branch information
Danielius1922 committed Sep 26, 2024
1 parent 68ca5a5 commit 638e663
Show file tree
Hide file tree
Showing 15 changed files with 213 additions and 428 deletions.
16 changes: 4 additions & 12 deletions certificate-authority/service/grpc/getSigningRecords.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package grpc

import (
"context"

"github.com/plgd-dev/hub/v2/certificate-authority/pb"
"github.com/plgd-dev/hub/v2/certificate-authority/store"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
Expand All @@ -14,16 +11,11 @@ func (s *CertificateAuthorityServer) GetSigningRecords(req *pb.GetSigningRecords
if err != nil {
return s.logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, "cannot get signing records: %v", err))
}
err = s.store.LoadSigningRecords(srv.Context(), owner, req, func(ctx context.Context, iter store.SigningRecordIter) (err error) {
for {
var sub pb.SigningRecord
if ok := iter.Next(ctx, &sub); !ok {
return iter.Err()
}
if err = srv.Send(&sub); err != nil {
return err
}
err = s.store.LoadSigningRecords(srv.Context(), owner, req, func(sr *pb.SigningRecord) (err error) {
if err = srv.Send(sr); err != nil {
return err
}
return nil
})
if err != nil {
return s.logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, "cannot get signing records: %v", err))
Expand Down
18 changes: 6 additions & 12 deletions certificate-authority/service/grpc/signCertificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,11 @@ func (s *CertificateAuthorityServer) updateSigningIdentityCertificateRecord(ctx
now := time.Now().UnixNano()
err := s.store.LoadSigningRecords(ctx, updateSigningRecord.GetOwner(), &store.SigningRecordsQuery{
CommonNameFilter: []string{updateSigningRecord.GetCommonName()},
}, func(ctx context.Context, iter store.SigningRecordIter) (err error) {
for {
var signingRecord pb.SigningRecord
ok := iter.Next(ctx, &signingRecord)
if !ok {
break
}
if updateSigningRecord.GetPublicKey() != signingRecord.GetPublicKey() && signingRecord.GetCredential().GetValidUntilDate() > now {
return fmt.Errorf("common name %v with different public key fingerprint exist", signingRecord.GetCommonName())
}
found = true
}, func(sr *store.SigningRecord) (err error) {
if updateSigningRecord.GetPublicKey() != sr.GetPublicKey() && sr.GetCredential().GetValidUntilDate() > now {
return fmt.Errorf("common name %v with different public key fingerprint exist", sr.GetCommonName())
}
found = true
return nil
})
if err != nil {
Expand Down Expand Up @@ -125,13 +118,14 @@ func (s *CertificateAuthorityServer) SignCertificate(ctx context.Context, req *p
logger.With("crt", string(cert)).Debugf("CertificateAuthorityServer.SignCertificate")
replacedCredential := replacedRecord.GetCredential()
if replacedRecord != nil {
err = s.store.AddRevocationListCertificate(ctx, replacedCredential.GetIssuerId(), &store.RevocationListCertificate{
err = s.store.RevokeCertificates(ctx, replacedCredential.GetIssuerId(), &store.RevocationListCertificate{
Serial: replacedCredential.GetSerial(),
Expiration: replacedCredential.GetValidUntilDate(),
Revocation: time.Now().UnixNano(),
})
if err != nil {
// TODO: what to do here? remove the new signing record? restore the original?
panic(err)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,14 @@ func (s *CertificateAuthorityServer) SignIdentityCertificate(ctx context.Context
logger.With("crt", string(cert)).Debugf("CertificateAuthorityServer.SignIdentityCertificate")
replacedCredential := replacedRecord.GetCredential()
if replacedCredential != nil {
err = s.store.AddRevocationListCertificate(ctx, replacedCredential.GetIssuerId(), &store.RevocationListCertificate{
err = s.store.RevokeCertificates(ctx, replacedCredential.GetIssuerId(), &store.RevocationListCertificate{
Serial: replacedCredential.GetSerial(),
Expiration: replacedCredential.GetValidUntilDate(),
Revocation: time.Now().UnixNano(),
})
if err != nil {
// TODO: what to do here? remove the new signing record? restore the original?
panic(err)
}
}

Expand Down
25 changes: 11 additions & 14 deletions certificate-authority/service/http/revocationList.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,25 @@ import (
pkgTime "github.com/plgd-dev/hub/v2/pkg/time"
)

var revocationListNumber = big.NewInt(0)

func (requestHandler *RequestHandler) revocationList(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
issuerID := vars[uri.IssuerIDKey]

var rles []x509.RevocationListEntry
err := requestHandler.store.GetRevokedCertificates(r.Context(), store.CertificatesQuery{
template := &x509.RevocationList{
NextUpdate: time.Now().Add(time.Minute * 10), // TODO: pridat konfiguraciu, default napr. 10min
}
err := requestHandler.store.GetRevocationLists(r.Context(), store.RevocationListsQuery{
IssuerIdFilter: []string{issuerID},
}, func(rl *store.RevocationList) error {
template.Number = big.NewInt(rl.Number)
template.ThisUpdate = pkgTime.Unix(0, rl.UpdatedAt)
for _, c := range rl.Certificates {
var sn big.Int
_, ok := sn.SetString(c.Serial, 10)
if !ok {
panic("invalid serial number string " + c.Serial)
}
rles = append(rles, x509.RevocationListEntry{
template.RevokedCertificateEntries = append(template.RevokedCertificateEntries, x509.RevocationListEntry{
SerialNumber: &sn,
RevocationTime: pkgTime.Unix(0, c.Revocation),
})
Expand All @@ -43,19 +45,14 @@ func (requestHandler *RequestHandler) revocationList(w http.ResponseWriter, r *h
panic(err)
}

if len(template.RevokedCertificateEntries) == 0 {
return
}

issuingCert := requestHandler.cas.GetSigner().GetCertificate()
if issuingCert == nil {
panic("issuer certificate not set")
}
now := time.Now()
template := &x509.RevocationList{
RevokedCertificateEntries: rles,
Number: revocationListNumber,
ThisUpdate: now,
NextUpdate: now.Add(time.Minute * 10), // TODO: pridat konfiguraciu, default napr. 10min
}
// TODO: store CRLs in DB and only increase the number if a new CRL has been generated
revocationListNumber.Add(revocationListNumber, big.NewInt(1))

signer := requestHandler.cas.GetSigner()
crl, err := x509.CreateRevocationList(rand.Reader, template, issuingCert, signer.GetPrivateKey().(*ecdsa.PrivateKey))
Expand Down
5 changes: 1 addition & 4 deletions certificate-authority/service/http/revocationList_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"time"

certAuthURI "github.com/plgd-dev/hub/v2/certificate-authority/service/uri"
"github.com/plgd-dev/hub/v2/certificate-authority/store"
"github.com/plgd-dev/hub/v2/certificate-authority/test"
httpgwTest "github.com/plgd-dev/hub/v2/http-gateway/test"
"github.com/plgd-dev/hub/v2/pkg/config/database"
Expand Down Expand Up @@ -38,8 +37,6 @@ func TestRevocationList(t *testing.T) {
ctx = pkgGrpc.CtxWithToken(ctx, token)

test.AddRevocationListToStore(ctx, t, s, time.Now())
err := s.RevokeCertificates(ctx, store.CertificatesQuery{})
require.NoError(t, err)

request := httpgwTest.NewRequest(http.MethodGet, certAuthURI.SigningRevocationList, nil).Host(config.CERTIFICATE_AUTHORITY_HTTP_HOST).AuthToken(token).AddIssuerID(test.GetIssuerID(2)).Build()
httpResp := httpgwTest.HTTPDo(t, request)
Expand All @@ -51,5 +48,5 @@ func TestRevocationList(t *testing.T) {
_, err = x509.ParseRevocationList(respBody)
require.NoError(t, err)

time.Sleep(time.Minute)
// time.Sleep(time.Minute)
}
16 changes: 2 additions & 14 deletions certificate-authority/store/cqldb/revocationList.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,10 @@ func (s *Store) InsertRevocationLists(context.Context, ...*store.RevocationList)
return store.ErrNotSupported
}

func (s *Store) AddRevocationListCertificate(context.Context, string, *store.RevocationListCertificate) error {
func (s *Store) RevokeCertificates(context.Context, string, ...*store.RevocationListCertificate) error {
return store.ErrNotSupported
}

func (s *Store) RevokeCertificates(context.Context, store.CertificatesQuery) error {
return store.ErrNotSupported
}

func (s *Store) GetExpiredCertificates(context.Context, store.ExpiredCertificatesQuery, store.Process[store.RevocationList]) error {
return store.ErrNotSupported
}

func (s *Store) GetRevokedCertificates(context.Context, store.CertificatesQuery, store.Process[store.RevocationList]) error {
return store.ErrNotSupported
}

func (s *Store) DeleteExpiredCertificates(context.Context) error {
func (s *Store) GetRevocationLists(context.Context, store.RevocationListsQuery, store.Process[store.RevocationList]) error {
return store.ErrNotSupported
}
16 changes: 13 additions & 3 deletions certificate-authority/store/cqldb/signingRecords.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,15 +339,25 @@ func (s *Store) DeleteNonDeviceExpiredRecords(_ context.Context, _ time.Time) (i
return 0, store.ErrNotSupported
}

func (s *Store) LoadSigningRecords(ctx context.Context, owner string, query *store.SigningRecordsQuery, h store.LoadSigningRecordsFunc) error {
func (s *Store) LoadSigningRecords(ctx context.Context, owner string, query *store.SigningRecordsQuery, p store.Process[store.SigningRecord]) error {
i := SigningRecordsIterator{
ctx: ctx,
s: s,
queries: toSigningRecordsQueryFilter(owner, query, true),
provided: make(map[string]struct{}, 32),
}
err := h(ctx, &i)

var err error
for {
var stored store.SigningRecord
if !i.Next(ctx, &stored) {
err = i.Err()
break
}
err = p(&stored)
if err != nil {
break
}
}
errClose := i.close()
if err == nil {
return errClose
Expand Down
20 changes: 7 additions & 13 deletions certificate-authority/store/cqldb/signingRecords_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func TestStoreUpdateSigningRecord(t *testing.T) {
var h testSigningRecordHandler
err = s.LoadSigningRecords(ctx, tt.args.sub.GetOwner(), &pb.GetSigningRecordsRequest{
IdFilter: []string{tt.args.sub.GetId()},
}, h.Handle)
}, h.process)
require.NoError(t, err)
require.Len(t, h.lcs, 1)
hubTest.CheckProtobufs(t, tt.args.sub, h.lcs[0], hubTest.RequireToCheckFunc(require.Equal))
Expand Down Expand Up @@ -345,15 +345,15 @@ func TestStoreDeleteExpiredRecords(t *testing.T) {
})
require.NoError(t, err)
var h testSigningRecordHandler
err = s.LoadSigningRecords(ctx, "owner", nil, h.Handle)
err = s.LoadSigningRecords(ctx, "owner", nil, h.process)
require.NoError(t, err)
require.Len(t, h.lcs, 1)
time.Sleep(time.Second * 3)
_, err = s.DeleteNonDeviceExpiredRecords(ctx, time.Now())
require.Error(t, err)
require.Equal(t, store.ErrNotSupported, err)
var h1 testSigningRecordHandler
err = s.LoadSigningRecords(ctx, "owner", nil, h1.Handle)
err = s.LoadSigningRecords(ctx, "owner", nil, h1.process)
require.NoError(t, err)
require.Empty(t, h1.lcs)
}
Expand All @@ -362,15 +362,9 @@ type testSigningRecordHandler struct {
lcs pb.SigningRecords
}

func (h *testSigningRecordHandler) Handle(ctx context.Context, iter store.SigningRecordIter) (err error) {
for {
var sub store.SigningRecord
if !iter.Next(ctx, &sub) {
break
}
h.lcs = append(h.lcs, &sub)
}
return iter.Err()
func (h *testSigningRecordHandler) process(sr *store.SigningRecord) (err error) {
h.lcs = append(h.lcs, sr)
return nil
}

func TestStoreLoadSigningRecords(t *testing.T) {
Expand Down Expand Up @@ -518,7 +512,7 @@ func TestStoreLoadSigningRecords(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var h testSigningRecordHandler
err := s.LoadSigningRecords(ctx, "owner", tt.args.query, h.Handle)
err := s.LoadSigningRecords(ctx, "owner", tt.args.query, h.process)
if tt.wantErr {
require.Error(t, err)
return
Expand Down
Loading

0 comments on commit 638e663

Please sign in to comment.