Skip to content

Commit

Permalink
fixup! Configurable CRL
Browse files Browse the repository at this point in the history
  • Loading branch information
Danielius1922 committed Oct 2, 2024
1 parent 7cb304c commit 3909233
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 18 deletions.
170 changes: 170 additions & 0 deletions certificate-authority/service/grpc/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package grpc_test

import (
"testing"
"time"

"github.com/plgd-dev/hub/v2/certificate-authority/service/grpc"
"github.com/plgd-dev/hub/v2/pkg/config/property/urischeme"
"github.com/stretchr/testify/require"
)

func TestCRLConfigValidate(t *testing.T) {
tests := []struct {
name string
input grpc.CRLConfig
wantErr bool
}{
{
name: "Disabled CRLConfig",
input: grpc.CRLConfig{
Enabled: false,
},
},
{
name: "Enabled CRLConfig with valid ExternalAddress and ExpiresIn",
input: grpc.CRLConfig{
Enabled: true,
ExternalAddress: "http://example.com/crl",
ExpiresIn: time.Hour,
},
},
{
name: "Enabled CRLConfig with empty ExternalAddress",
input: grpc.CRLConfig{
Enabled: true,
ExternalAddress: "",
ExpiresIn: time.Hour,
},
wantErr: true,
},
{
name: "Enabled CRLConfig with ExpiresIn less than 1 minute",
input: grpc.CRLConfig{
Enabled: true,
ExternalAddress: "http://example.com/crl",
ExpiresIn: 30 * time.Second,
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.input.Validate()
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}

func TestSignerConfigValidate(t *testing.T) {
crl := grpc.CRLConfig{
Enabled: true,
ExternalAddress: "http://example.com/crl",
ExpiresIn: time.Hour,
}
tests := []struct {
name string
input grpc.SignerConfig
wantErr bool
}{
{
name: "Valid SignerConfig",
input: grpc.SignerConfig{
CAPool: []string{"ca1.pem", "ca2.pem"},
KeyFile: urischeme.URIScheme("key.pem"),
CertFile: urischeme.URIScheme("cert.pem"),
ValidFrom: time.Now().Format(time.RFC3339),
ExpiresIn: time.Hour * 24,
CRL: crl,
},
},
{
name: "Invalid CA Pool",
input: grpc.SignerConfig{
CAPool: 42,
KeyFile: urischeme.URIScheme("key.pem"),
CertFile: urischeme.URIScheme("cert.pem"),
ValidFrom: time.Now().Format(time.RFC3339),
ExpiresIn: time.Hour * 24,
CRL: crl,
},
wantErr: true,
},
{
name: "Empty CertFile",
input: grpc.SignerConfig{
CAPool: []string{"ca1.pem"},
KeyFile: urischeme.URIScheme("key.pem"),
CertFile: "",
ValidFrom: time.Now().Format(time.RFC3339),
ExpiresIn: time.Hour * 24,
CRL: crl,
},
wantErr: true,
},
{
name: "Empty KeyFile",
input: grpc.SignerConfig{
CAPool: []string{"ca1.pem"},
KeyFile: "",
CertFile: urischeme.URIScheme("cert.pem"),
ValidFrom: time.Now().Format(time.RFC3339),
ExpiresIn: time.Hour * 24,
CRL: crl,
},
wantErr: true,
},
{
name: "Invalid ExpiresIn",
input: grpc.SignerConfig{
CAPool: []string{"ca1.pem", "ca2.pem"},
KeyFile: urischeme.URIScheme("key.pem"),
CertFile: urischeme.URIScheme("cert.pem"),
ValidFrom: time.Now().Format(time.RFC3339),
ExpiresIn: -1,
CRL: crl,
},
wantErr: true,
},
{
name: "Invalid ValidFrom format",
input: grpc.SignerConfig{
CAPool: []string{"ca1.pem"},
KeyFile: urischeme.URIScheme("key.pem"),
CertFile: urischeme.URIScheme("cert.pem"),
ValidFrom: "invalid-date",
ExpiresIn: time.Hour * 24,
CRL: crl,
},
wantErr: true,
},
{
name: "Invalid CRL",
input: grpc.SignerConfig{
CAPool: []string{"ca1.pem", "ca2.pem"},
KeyFile: urischeme.URIScheme("key.pem"),
CertFile: urischeme.URIScheme("cert.pem"),
ValidFrom: time.Now().Format(time.RFC3339),
ExpiresIn: time.Hour * 24,
CRL: grpc.CRLConfig{
Enabled: true,
},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.input.Validate()
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ func TestCertificateAuthorityServerDeleteSigningRecords(t *testing.T) {
{
name: "missing token with ownerClaim in ctx",
args: args{
req: &pb.DeleteSigningRecordsRequest{
IdFilter: []string{r.GetId()},
},
ctx: context.Background(),
},
wantErr: true,
Expand Down Expand Up @@ -103,7 +106,7 @@ func TestCertificateAuthorityServerDeleteSigningRecords(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := grpcClient.DeleteSigningRecords(ctx, tt.args.req)
got, err := grpcClient.DeleteSigningRecords(tt.args.ctx, tt.args.req)
if tt.wantErr {
require.Error(t, err)
return
Expand Down
20 changes: 10 additions & 10 deletions certificate-authority/service/http/revocationList.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package http
import (
"crypto/rand"
"crypto/x509"
"fmt"
"math/big"
"net/http"
"time"
Expand All @@ -23,12 +22,11 @@ func errCannotGetRevocationList(err error) error {
return pkgGrpc.ForwardErrorf(codes.Internal, "cannot get revocation list: %v", err)
}

func (requestHandler *RequestHandler) revocationList(w http.ResponseWriter, r *http.Request) {
func (requestHandler *RequestHandler) writeRevocationList(w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
issuerID := vars[uri.IssuerIDKey]
if _, err := uuid.Parse(issuerID); err != nil {
serverMux.WriteError(w, errCannotGetRevocationList(fmt.Errorf("invalid issuer's ID(%s): %w", issuerID, err)))
return
return err
}
signer := requestHandler.cas.GetSigner()
_, validFor := signer.GetCRLConfiguation()
Expand All @@ -55,18 +53,20 @@ func (requestHandler *RequestHandler) revocationList(w http.ResponseWriter, r *h
return nil
})
if err != nil {
serverMux.WriteError(w, errCannotGetRevocationList(err))
return
return err
}

crl, err := x509.CreateRevocationList(rand.Reader, template, signer.GetCertificate(), signer.GetPrivateKey())
if err != nil {
serverMux.WriteError(w, errCannotGetRevocationList(err))
return
return err
}
w.Header().Set(pkgHttp.ContentTypeHeaderKey, "application/pkix-crl")
if _, err = w.Write(crl); err != nil {
_, err = w.Write(crl)
return err
}

func (requestHandler *RequestHandler) revocationList(w http.ResponseWriter, r *http.Request) {
if err := requestHandler.writeRevocationList(w, r); err != nil {
serverMux.WriteError(w, errCannotGetRevocationList(err))
return
}
}
58 changes: 58 additions & 0 deletions certificate-authority/store/store_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package store

import (
"testing"

"github.com/google/uuid"
"github.com/stretchr/testify/require"
)

func TestRevocationListsQueryValidate(t *testing.T) {
tests := []struct {
name string
input RevocationListsQuery
wantErr bool
}{
{
name: "Valid query with one valid UUID",
input: RevocationListsQuery{
IssuerIdFilter: []string{uuid.New().String()},
IncludeExpired: true,
},
wantErr: false,
},
{
name: "Valid query with multiple valid UUIDs",
input: RevocationListsQuery{
IssuerIdFilter: []string{uuid.New().String(), uuid.New().String()},
},
wantErr: false,
},
{
name: "Invalid query with an invalid UUID",
input: RevocationListsQuery{
IssuerIdFilter: []string{uuid.New().String(), "invalid-uuid"},
},
wantErr: true,
},
{
name: "Valid query with empty IssuerIdFilter",
input: RevocationListsQuery{
IssuerIdFilter: []string{},
IncludeExpired: true,
},
wantErr: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.input.Validate()
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}
7 changes: 0 additions & 7 deletions coap-gateway/service/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,6 @@ type InjectedCOAPConfig struct {
TLSConfig InjectedTLSConfig `yaml:"tls" json:"tls"`
}

func (c *InjectedCOAPConfig) Validate() error {
return nil
}

type DeviceTwinConfig struct {
MaxETagsCountInRequest uint32 `yaml:"maxETagsCountInRequest" json:"maxETagsCountInRequest"`
UseETags bool `yaml:"useETags" json:"useETags"`
Expand Down Expand Up @@ -183,9 +179,6 @@ func (c *COAPConfigMarshalerUnmarshaler) Validate() error {
if err := c.COAPConfig.Validate(); err != nil {
return err
}
if err := c.InjectedCOAPConfig.Validate(); err != nil {
return err
}
if !c.InjectedCOAPConfig.TLSConfig.IdentityPropertiesRequired && c.Authorization.DeviceIDClaim != "" {
return fmt.Errorf("tls.identityPropertiesRequired('%v') - %w", c.InjectedCOAPConfig.TLSConfig.IdentityPropertiesRequired, errors.New("combination with authorization.deviceIDClaim is not supported"))
}
Expand Down

0 comments on commit 3909233

Please sign in to comment.