From eaf1f8949df5fbc0387456266389731399fcae19 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Fri, 20 Dec 2024 19:21:34 +0000 Subject: [PATCH 01/11] cp and storage creation to main, timesource to opt --- cmd/gcp/main.go | 12 +++++++++++- instance.go | 22 ++++------------------ instance_test.go | 34 ++-------------------------------- 3 files changed, 17 insertions(+), 51 deletions(-) diff --git a/cmd/gcp/main.go b/cmd/gcp/main.go index 27493ad6..b07e4001 100644 --- a/cmd/gcp/main.go +++ b/cmd/gcp/main.go @@ -101,6 +101,15 @@ func main() { corsHandler := cors.AllowAll().Handler(corsMux) http.Handle("/", corsHandler) + timeSource := sctfe.SystemTimeSource{} + cpSigner, err := sctfe.NewCpSigner(signer, vCfg.Origin, timeSource) + if err != nil { + klog.Exitf("failed to create checkpoint Signer: %v", err) + } + storage, err := newGCPStorage(ctx, cpSigner) + if err != nil { + klog.Exitf("failed to initiate storage backend: %v", err) + } // Register handlers for all the configured logs. opts := sctfe.InstanceOptions{ Validated: vCfg, @@ -108,7 +117,8 @@ func main() { MetricFactory: prometheus.MetricFactory{}, RequestLog: new(sctfe.DefaultRequestLog), MaskInternalErrors: *maskInternalErrors, - CreateStorage: newGCPStorage, + Storage: storage, + TimeSource: timeSource, } inst, err := sctfe.SetUpInstance(ctx, opts) diff --git a/instance.go b/instance.go index 636a3108..fde63522 100644 --- a/instance.go +++ b/instance.go @@ -25,7 +25,6 @@ import ( "github.com/google/certificate-transparency-go/asn1" "github.com/google/certificate-transparency-go/x509util" "github.com/google/trillian/monitoring" - "golang.org/x/mod/sumdb/note" ) // InstanceOptions describes the options for a log instance. @@ -33,8 +32,8 @@ type InstanceOptions struct { // Validated holds the original configuration options for the log, and some // of its fields parsed as a result of validating it. Validated *ValidatedLogConfig - // CreateStorage instantiates a Tessera storage implementation with a signer option. - CreateStorage func(context.Context, note.Signer) (*CTStorage, error) + // Storage stores data to implement https://c2sp.org/static-ct-api. + Storage *CTStorage // Deadline is a timeout for HTTP requests. Deadline time.Duration // MetricFactory allows creating metrics. @@ -42,6 +41,7 @@ type InstanceOptions struct { // RequestLog provides structured logging of CTFE requests. RequestLog RequestLog MaskInternalErrors bool + TimeSource TimeSource } // Instance is a set up log/mirror instance. It must be created with the @@ -85,21 +85,7 @@ func SetUpInstance(ctx context.Context, opts InstanceOptions) (*Instance, error) return nil, fmt.Errorf("failed to parse RejectExtensions: %v", err) } - timeSource := new(SystemTimeSource) - cpSigner, err := NewCpSigner(cfg.Signer, cfg.Origin, timeSource) - if err != nil { - return nil, fmt.Errorf("failed to create checkpoint signer: %v", err) - } - - if opts.CreateStorage == nil { - return nil, fmt.Errorf("failed to initiate storage backend: nil createStorage") - } - storage, err := opts.CreateStorage(ctx, cpSigner) - if err != nil { - return nil, fmt.Errorf("failed to initiate storage backend: %v", err) - } - - logInfo := newLogInfo(opts, validationOpts, cfg.Signer, timeSource, storage) + logInfo := newLogInfo(opts, validationOpts, cfg.Signer, opts.TimeSource, opts.Storage) handlers := logInfo.Handlers(opts.Validated.Origin) return &Instance{Handlers: handlers, li: logInfo}, nil diff --git a/instance_test.go b/instance_test.go index 46bc8d1a..674e9460 100644 --- a/instance_test.go +++ b/instance_test.go @@ -27,13 +27,8 @@ import ( ct "github.com/google/certificate-transparency-go" "github.com/google/trillian/crypto/keys/pem" "github.com/google/trillian/monitoring" - "golang.org/x/mod/sumdb/note" ) -func fakeCTStorage(_ context.Context, _ note.Signer) (*CTStorage, error) { - return &CTStorage{}, nil -} - func TestSetUpInstance(t *testing.T) { ctx := context.Background() @@ -49,28 +44,24 @@ func TestSetUpInstance(t *testing.T) { extKeyUsages string rejectExtensions string signer crypto.Signer - ctStorage func(context.Context, note.Signer) (*CTStorage, error) wantErr string }{ { desc: "valid", origin: "log", rootsPemFile: "./testdata/fake-ca.cert", - ctStorage: fakeCTStorage, signer: signer, }, { desc: "no-roots", origin: "log", rootsPemFile: "./testdata/nofile", - ctStorage: fakeCTStorage, wantErr: "failed to read trusted roots", signer: signer, }, { desc: "missing-root-cert", origin: "log", - ctStorage: fakeCTStorage, rootsPemFile: "./testdata/bogus.cert", signer: signer, wantErr: "failed to read trusted roots", @@ -81,7 +72,6 @@ func TestSetUpInstance(t *testing.T) { rootsPemFile: "./testdata/fake-ca.cert", extKeyUsages: "Any", signer: signer, - ctStorage: fakeCTStorage, }, { desc: "valid-ekus-2", @@ -89,7 +79,6 @@ func TestSetUpInstance(t *testing.T) { rootsPemFile: "./testdata/fake-ca.cert", extKeyUsages: "Any,ServerAuth,TimeStamping", signer: signer, - ctStorage: fakeCTStorage, }, { desc: "valid-reject-ext", @@ -97,34 +86,15 @@ func TestSetUpInstance(t *testing.T) { rootsPemFile: "./testdata/fake-ca.cert", rejectExtensions: "1.2.3.4,5.6.7.8", signer: signer, - ctStorage: fakeCTStorage, }, { desc: "invalid-reject-ext", origin: "log", - ctStorage: fakeCTStorage, rootsPemFile: "./testdata/fake-ca.cert", rejectExtensions: "1.2.3.4,one.banana.two.bananas", signer: signer, wantErr: "one", }, - { - desc: "missing-create-storage", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - signer: signer, - wantErr: "failed to initiate storage backend", - }, - { - desc: "failing-create-storage", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - signer: signer, - ctStorage: func(_ context.Context, _ note.Signer) (*CTStorage, error) { - return nil, fmt.Errorf("I failed") - }, - wantErr: "failed to initiate storage backend", - }, } for _, test := range tests { @@ -133,7 +103,7 @@ func TestSetUpInstance(t *testing.T) { if err != nil { t.Fatalf("ValidateLogConfig(): %v", err) } - opts := InstanceOptions{Validated: vCfg, Deadline: time.Second, MetricFactory: monitoring.InertMetricFactory{}, CreateStorage: test.ctStorage} + opts := InstanceOptions{Validated: vCfg, Deadline: time.Second, MetricFactory: monitoring.InertMetricFactory{}, Storage: &CTStorage{}} if _, err := SetUpInstance(ctx, opts); err != nil { if test.wantErr == "" { @@ -208,7 +178,7 @@ func TestSetUpInstanceSetsValidationOpts(t *testing.T) { if err != nil { t.Fatalf("ValidateLogConfig(): %v", err) } - opts := InstanceOptions{Validated: vCfg, Deadline: time.Second, MetricFactory: monitoring.InertMetricFactory{}, CreateStorage: fakeCTStorage} + opts := InstanceOptions{Validated: vCfg, Deadline: time.Second, MetricFactory: monitoring.InertMetricFactory{}, Storage: &CTStorage{}} inst, err := SetUpInstance(ctx, opts) if err != nil { From f7cf17110019c1255a9385cc2037a9ad4fbfd5d3 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Fri, 20 Dec 2024 20:16:45 +0000 Subject: [PATCH 02/11] Reorder main --- cmd/gcp/main.go | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/cmd/gcp/main.go b/cmd/gcp/main.go index b07e4001..c630b0b0 100644 --- a/cmd/gcp/main.go +++ b/cmd/gcp/main.go @@ -76,16 +76,41 @@ func main() { flag.Parse() ctx := context.Background() + timeSource := sctfe.SystemTimeSource{} signer, err := NewSecretManagerSigner(ctx, *signerPublicKeySecretName, *signerPrivateKeySecretName) if err != nil { klog.Exitf("Can't create secret manager signer: %v", err) } + cpSigner, err := sctfe.NewCpSigner(signer, *origin, timeSource) + if err != nil { + klog.Exitf("failed to create checkpoint Signer: %v", err) + } + + storage, err := newGCPStorage(ctx, cpSigner) + if err != nil { + klog.Exitf("failed to initiate storage backend: %v", err) + } vCfg, err := sctfe.ValidateLogConfig(*origin, *rootsPemFile, *rejectExpired, *rejectUnexpired, *extKeyUsages, *rejectExtensions, notAfterStart.t, notAfterLimit.t, signer) if err != nil { klog.Exitf("Invalid config: %v", err) } + opts := sctfe.InstanceOptions{ + Validated: vCfg, + Deadline: *httpDeadline, + MetricFactory: prometheus.MetricFactory{}, + RequestLog: new(sctfe.DefaultRequestLog), + MaskInternalErrors: *maskInternalErrors, + Storage: storage, + TimeSource: timeSource, + } + + inst, err := sctfe.SetUpInstance(ctx, opts) + if err != nil { + klog.Exitf("Failed to set up log instance for %+v: %v", vCfg, err) + } + klog.CopyStandardLogTo("WARNING") klog.Info("**** CT HTTP Server Starting ****") @@ -101,30 +126,7 @@ func main() { corsHandler := cors.AllowAll().Handler(corsMux) http.Handle("/", corsHandler) - timeSource := sctfe.SystemTimeSource{} - cpSigner, err := sctfe.NewCpSigner(signer, vCfg.Origin, timeSource) - if err != nil { - klog.Exitf("failed to create checkpoint Signer: %v", err) - } - storage, err := newGCPStorage(ctx, cpSigner) - if err != nil { - klog.Exitf("failed to initiate storage backend: %v", err) - } // Register handlers for all the configured logs. - opts := sctfe.InstanceOptions{ - Validated: vCfg, - Deadline: *httpDeadline, - MetricFactory: prometheus.MetricFactory{}, - RequestLog: new(sctfe.DefaultRequestLog), - MaskInternalErrors: *maskInternalErrors, - Storage: storage, - TimeSource: timeSource, - } - - inst, err := sctfe.SetUpInstance(ctx, opts) - if err != nil { - klog.Exitf("Failed to set up log instance for %+v: %v", vCfg, err) - } for path, handler := range inst.Handlers { corsMux.Handle(path, handler) } From 8003aa888bac438c294279e773c82129c14898c5 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Fri, 20 Dec 2024 21:57:18 +0000 Subject: [PATCH 03/11] Remove InstanceOption from loginfo --- config.go | 18 +++++++++--------- handlers.go | 25 ++++++++++++++----------- instance_test.go | 2 +- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/config.go b/config.go index 69d05dbf..2b49d8db 100644 --- a/config.go +++ b/config.go @@ -87,6 +87,15 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r return nil, fmt.Errorf("unsupported key type: %v", keyType) } + if rejectExpired && rejectUnexpired { + return nil, errors.New("rejecting all certificates") + } + + // Validate the time interval. + if notAfterStart != nil && notAfterLimit != nil && (notAfterLimit).Before(*notAfterStart) { + return nil, errors.New("limit before start") + } + lExtKeyUsages := []string{} lRejectExtensions := []string{} if extKeyUsages != "" { @@ -107,10 +116,6 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r Signer: signer, } - if rejectExpired && rejectUnexpired { - return nil, errors.New("rejecting all certificates") - } - // Validate the extended key usages list. for _, kuStr := range lExtKeyUsages { if ku, ok := stringToKeyUsage[kuStr]; ok { @@ -127,11 +132,6 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r } } - // Validate the time interval. - if notAfterStart != nil && notAfterLimit != nil && (notAfterLimit).Before(*notAfterStart) { - return nil, errors.New("limit before start") - } - return &vCfg, nil } diff --git a/handlers.go b/handlers.go index 0ac0fdfc..15730aea 100644 --- a/handlers.go +++ b/handlers.go @@ -199,8 +199,10 @@ type logInfo struct { // information. RequestLog RequestLog - // Instance-wide options - instanceOpts InstanceOptions + // maskInternalErrors controls whether to hide internal errors from clients + maskInternalErrors bool + // deadline is a timeout for HTTP requests. + deadline time.Duration // validationOpts contains the certificate chain validation parameters validationOpts CertValidationOpts // storage stores log data @@ -220,13 +222,14 @@ func newLogInfo( cfg := instanceOpts.Validated li := &logInfo{ - Origin: cfg.Origin, - storage: storage, - signer: signer, - TimeSource: timeSource, - instanceOpts: instanceOpts, - validationOpts: validationOpts, - RequestLog: instanceOpts.RequestLog, + Origin: cfg.Origin, + storage: storage, + signer: signer, + TimeSource: timeSource, + maskInternalErrors: instanceOpts.MaskInternalErrors, + deadline: instanceOpts.Deadline, + validationOpts: validationOpts, + RequestLog: instanceOpts.RequestLog, } once.Do(func() { setupMetrics(instanceOpts.MetricFactory) }) @@ -256,7 +259,7 @@ func (li *logInfo) Handlers(prefix string) PathHandlers { // SendHTTPError generates a custom error page to give more information on why something didn't work func (li *logInfo) SendHTTPError(w http.ResponseWriter, statusCode int, err error) { errorBody := http.StatusText(statusCode) - if !li.instanceOpts.MaskInternalErrors || statusCode != http.StatusInternalServerError { + if !li.maskInternalErrors || statusCode != http.StatusInternalServerError { errorBody += fmt.Sprintf("\n%v", err) } http.Error(w, errorBody, statusCode) @@ -419,7 +422,7 @@ func getRoots(_ context.Context, li *logInfo, w http.ResponseWriter, _ *http.Req // deadlineTime calculates the future time a request should expire based on our config. func deadlineTime(li *logInfo) time.Time { - return li.TimeSource.Now().Add(li.instanceOpts.Deadline) + return li.TimeSource.Now().Add(li.deadline) } // verifyAddChain is used by add-chain and add-pre-chain. It does the checks that the supplied diff --git a/instance_test.go b/instance_test.go index 674e9460..e4476fb5 100644 --- a/instance_test.go +++ b/instance_test.go @@ -208,7 +208,7 @@ func TestErrorMasking(t *testing.T) { if got, want := w.Body.String(), fmt.Sprintf("%s\n%v\n", prefix, err); got != want { t.Errorf("SendHTTPError: got %s, want %s", got, want) } - info.instanceOpts.MaskInternalErrors = true + info.maskInternalErrors = true w = httptest.NewRecorder() info.SendHTTPError(w, 500, err) if got, want := w.Body.String(), prefix+"\n"; got != want { From 5979950b2834cfa65ba90732fea9ac54a6480a28 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Tue, 24 Dec 2024 16:32:08 +0000 Subject: [PATCH 04/11] move things out of SetupInstance to ValidateLogConfig --- config.go | 98 +++++++++++++++++++++++++++--------------------- config_test.go | 60 ++++++++++++++++++++++------- instance.go | 53 +------------------------- instance_test.go | 45 +--------------------- 4 files changed, 104 insertions(+), 152 deletions(-) diff --git a/config.go b/config.go index 2b49d8db..a67fdde1 100644 --- a/config.go +++ b/config.go @@ -19,10 +19,13 @@ import ( "crypto/ecdsa" "errors" "fmt" + "strconv" "strings" "time" + "github.com/google/certificate-transparency-go/asn1" "github.com/google/certificate-transparency-go/x509" + "github.com/google/certificate-transparency-go/x509util" "k8s.io/klog/v2" ) @@ -34,31 +37,9 @@ type ValidatedLogConfig struct { Origin string // Used to sign the checkpoint and SCTs. Signer crypto.Signer - // If set, ExtKeyUsages will restrict the set of such usages that the - // server will accept. By default all are accepted. The values specified - // must be ones known to the x509 package. - KeyUsages []x509.ExtKeyUsage - // NotAfterStart defines the start of the range of acceptable NotAfter - // values, inclusive. - // Leaving this unset implies no lower bound to the range. - NotAfterStart *time.Time - // NotAfterLimit defines the end of the range of acceptable NotAfter values, - // exclusive. - // Leaving this unset implies no upper bound to the range. - NotAfterLimit *time.Time - // Path to the file containing root certificates that are acceptable to the - // log. The certs are served through get-roots endpoint. - RootsPemFile string - // If RejectExpired is true then the certificate validity period will be - // checked against the current time during the validation of submissions. - // This will cause expired certificates to be rejected. - RejectExpired bool - // If RejectUnexpired is true then CTFE rejects certificates that are either - // currently valid or not yet valid. - RejectUnexpired bool - // A list of X.509 extension OIDs, in dotted string form (e.g. "2.3.4.5") - // which, if present, should cause submissions to be rejected. - RejectExtensions []string + // CertValidationOpts contains various parameters for certificate chain + // validation. + CertValidationOpts CertValidationOpts } // ValidateLogConfig checks that a single log config is valid. In particular: @@ -73,11 +54,17 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r return nil, errors.New("empty origin") } + // Load the trusted roots. if rootsPemFile == "" { return nil, errors.New("empty rootsPemFile") } + roots := x509util.NewPEMCertPool() + if err := roots.AppendCertsFromPEMFile(rootsPemFile); err != nil { + return nil, fmt.Errorf("failed to read trusted roots: %v", err) + } // Validate signer that only ECDSA is supported. + // TODO(phboneff): if this is a library this should also allow RSA as per RFC6962. if signer == nil { return nil, errors.New("empty signer") } @@ -96,26 +83,19 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r return nil, errors.New("limit before start") } + validationOpts := CertValidationOpts{ + trustedRoots: roots, + rejectExpired: rejectExpired, + rejectUnexpired: rejectUnexpired, + notAfterStart: notAfterStart, + notAfterLimit: notAfterLimit, + } + + // Filter which extended key usages are allowed. lExtKeyUsages := []string{} - lRejectExtensions := []string{} if extKeyUsages != "" { lExtKeyUsages = strings.Split(extKeyUsages, ",") } - if rejectExtensions != "" { - lRejectExtensions = strings.Split(rejectExtensions, ",") - } - - vCfg := ValidatedLogConfig{ - Origin: origin, - RootsPemFile: rootsPemFile, - RejectExpired: rejectExpired, - RejectUnexpired: rejectUnexpired, - RejectExtensions: lRejectExtensions, - NotAfterStart: notAfterStart, - NotAfterLimit: notAfterLimit, - Signer: signer, - } - // Validate the extended key usages list. for _, kuStr := range lExtKeyUsages { if ku, ok := stringToKeyUsage[kuStr]; ok { @@ -123,18 +103,50 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r // just disable EKU checking. if ku == x509.ExtKeyUsageAny { klog.Infof("%s: Found ExtKeyUsageAny, allowing all EKUs", origin) - vCfg.KeyUsages = nil + validationOpts.extKeyUsages = nil break } - vCfg.KeyUsages = append(vCfg.KeyUsages, ku) + validationOpts.extKeyUsages = append(validationOpts.extKeyUsages, ku) } else { return nil, fmt.Errorf("unknown extended key usage: %s", kuStr) } } + // Filter which extensions are rejected. + var err error + if rejectExtensions != "" { + lRejectExtensions := strings.Split(rejectExtensions, ",") + validationOpts.rejectExtIds, err = parseOIDs(lRejectExtensions) + if err != nil { + return nil, fmt.Errorf("failed to parse RejectExtensions: %v", err) + } + } + + vCfg := ValidatedLogConfig{ + Origin: origin, + Signer: signer, + CertValidationOpts: validationOpts, + } return &vCfg, nil } +func parseOIDs(oids []string) ([]asn1.ObjectIdentifier, error) { + ret := make([]asn1.ObjectIdentifier, 0, len(oids)) + for _, s := range oids { + bits := strings.Split(s, ".") + var oid asn1.ObjectIdentifier + for _, n := range bits { + p, err := strconv.Atoi(n) + if err != nil { + return nil, err + } + oid = append(oid, p) + } + ret = append(ret, oid) + } + return ret, nil +} + var stringToKeyUsage = map[string]x509.ExtKeyUsage{ "Any": x509.ExtKeyUsageAny, "ServerAuth": x509.ExtKeyUsageServerAuth, diff --git a/config_test.go b/config_test.go index 0e72dd13..84906d96 100644 --- a/config_test.go +++ b/config_test.go @@ -33,19 +33,20 @@ func TestValidateLogConfig(t *testing.T) { t200 := time.Unix(200, 0) for _, tc := range []struct { - desc string - origin string - projectID string - bucket string - spannerDB string - wantErr string - rootsPemFile string - rejectExpired bool - rejectUnexpired bool - extKeyUsages string - notAfterStart *time.Time - notAfterLimit *time.Time - signer crypto.Signer + desc string + origin string + projectID string + bucket string + spannerDB string + wantErr string + rootsPemFile string + rejectExpired bool + rejectUnexpired bool + extKeyUsages string + rejectExtensions string + notAfterStart *time.Time + notAfterLimit *time.Time + signer crypto.Signer }{ { desc: "empty-origin", @@ -63,6 +64,16 @@ func TestValidateLogConfig(t *testing.T) { spannerDB: "spanner", signer: signer, }, + { + desc: "missing-root-cert", + wantErr: "failed to read trusted roots", + origin: "testlog", + projectID: "project", + bucket: "bucket", + spannerDB: "spanner", + rootsPemFile: "./testdata/bogus.cert", + signer: signer, + }, { desc: "rejecting-all", wantErr: "rejecting all certificates", @@ -108,6 +119,17 @@ func TestValidateLogConfig(t *testing.T) { extKeyUsages: "Any ", signer: signer, }, + { + desc: "unknown-reject-ext", + wantErr: "failed to parse RejectExtensions", + origin: "testlog", + projectID: "project", + bucket: "bucket", + spannerDB: "spanner", + rootsPemFile: "./testdata/fake-ca.cert", + rejectExtensions: "1.2.3.4,one.banana.two.bananas", + signer: signer, + }, { desc: "limit-before-start", wantErr: "limit before start", @@ -139,6 +161,16 @@ func TestValidateLogConfig(t *testing.T) { extKeyUsages: "ServerAuth,ClientAuth,OCSPSigning", signer: signer, }, + { + desc: "ok-reject-ext", + origin: "testlog", + projectID: "project", + bucket: "bucket", + spannerDB: "spanner", + rootsPemFile: "./testdata/fake-ca.cert", + rejectExtensions: "1.2.3.4,5.6.7.8", + signer: signer, + }, { desc: "ok-start-timestamp", origin: "testlog", @@ -172,7 +204,7 @@ func TestValidateLogConfig(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { - vc, err := ValidateLogConfig(tc.origin, tc.rootsPemFile, tc.rejectExpired, tc.rejectUnexpired, tc.extKeyUsages, "", tc.notAfterStart, tc.notAfterLimit, signer) + vc, err := ValidateLogConfig(tc.origin, tc.rootsPemFile, tc.rejectExpired, tc.rejectUnexpired, tc.extKeyUsages, tc.rejectExtensions, tc.notAfterStart, tc.notAfterLimit, signer) if len(tc.wantErr) == 0 && err != nil { t.Errorf("ValidateLogConfig()=%v, want nil", err) } diff --git a/instance.go b/instance.go index fde63522..6b280b26 100644 --- a/instance.go +++ b/instance.go @@ -16,14 +16,8 @@ package sctfe import ( "context" - "crypto" - "fmt" - "strconv" - "strings" "time" - "github.com/google/certificate-transparency-go/asn1" - "github.com/google/certificate-transparency-go/x509util" "github.com/google/trillian/monitoring" ) @@ -51,59 +45,14 @@ type Instance struct { li *logInfo } -// GetPublicKey returns the public key from the instance's signer. -func (i *Instance) GetPublicKey() crypto.PublicKey { - if i.li != nil && i.li.signer != nil { - return i.li.signer.Public() - } - return nil -} - // SetUpInstance sets up a log (or log mirror) instance using the provided // configuration, and returns an object containing a set of handlers for this // log, and an STH getter. func SetUpInstance(ctx context.Context, opts InstanceOptions) (*Instance, error) { cfg := opts.Validated - // Load the trusted roots. - roots := x509util.NewPEMCertPool() - if err := roots.AppendCertsFromPEMFile(cfg.RootsPemFile); err != nil { - return nil, fmt.Errorf("failed to read trusted roots: %v", err) - } - - validationOpts := CertValidationOpts{ - trustedRoots: roots, - rejectExpired: cfg.RejectExpired, - rejectUnexpired: cfg.RejectUnexpired, - notAfterStart: cfg.NotAfterStart, - notAfterLimit: cfg.NotAfterLimit, - extKeyUsages: cfg.KeyUsages, - } - var err error - validationOpts.rejectExtIds, err = parseOIDs(cfg.RejectExtensions) - if err != nil { - return nil, fmt.Errorf("failed to parse RejectExtensions: %v", err) - } - - logInfo := newLogInfo(opts, validationOpts, cfg.Signer, opts.TimeSource, opts.Storage) + logInfo := newLogInfo(opts, cfg.CertValidationOpts, cfg.Signer, opts.TimeSource, opts.Storage) handlers := logInfo.Handlers(opts.Validated.Origin) return &Instance{Handlers: handlers, li: logInfo}, nil } - -func parseOIDs(oids []string) ([]asn1.ObjectIdentifier, error) { - ret := make([]asn1.ObjectIdentifier, 0, len(oids)) - for _, s := range oids { - bits := strings.Split(s, ".") - var oid asn1.ObjectIdentifier - for _, n := range bits { - p, err := strconv.Atoi(n) - if err != nil { - return nil, err - } - oid = append(oid, p) - } - ret = append(ret, oid) - } - return ret, nil -} diff --git a/instance_test.go b/instance_test.go index e4476fb5..576c2134 100644 --- a/instance_test.go +++ b/instance_test.go @@ -52,49 +52,6 @@ func TestSetUpInstance(t *testing.T) { rootsPemFile: "./testdata/fake-ca.cert", signer: signer, }, - { - desc: "no-roots", - origin: "log", - rootsPemFile: "./testdata/nofile", - wantErr: "failed to read trusted roots", - signer: signer, - }, - { - desc: "missing-root-cert", - origin: "log", - rootsPemFile: "./testdata/bogus.cert", - signer: signer, - wantErr: "failed to read trusted roots", - }, - { - desc: "valid-ekus-1", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - extKeyUsages: "Any", - signer: signer, - }, - { - desc: "valid-ekus-2", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - extKeyUsages: "Any,ServerAuth,TimeStamping", - signer: signer, - }, - { - desc: "valid-reject-ext", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - rejectExtensions: "1.2.3.4,5.6.7.8", - signer: signer, - }, - { - desc: "invalid-reject-ext", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - rejectExtensions: "1.2.3.4,one.banana.two.bananas", - signer: signer, - wantErr: "one", - }, } for _, test := range tests { @@ -131,6 +88,8 @@ func equivalentTimes(a *time.Time, b *time.Time) bool { return a.Equal(*b) } +// This tests that the right values of LogInfo are passed through. We can probably delete these tests, or check +// that the whole loginfo is passed through. func TestSetUpInstanceSetsValidationOpts(t *testing.T) { ctx := context.Background() From ceea07873d1e06fe0d1f7af2b504c911e99a92a4 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Tue, 24 Dec 2024 16:32:37 +0000 Subject: [PATCH 05/11] Delete loginfo from instance --- instance.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/instance.go b/instance.go index 6b280b26..19ff80c3 100644 --- a/instance.go +++ b/instance.go @@ -42,7 +42,6 @@ type InstanceOptions struct { // SetUpInstance call. type Instance struct { Handlers PathHandlers - li *logInfo } // SetUpInstance sets up a log (or log mirror) instance using the provided @@ -54,5 +53,5 @@ func SetUpInstance(ctx context.Context, opts InstanceOptions) (*Instance, error) logInfo := newLogInfo(opts, cfg.CertValidationOpts, cfg.Signer, opts.TimeSource, opts.Storage) handlers := logInfo.Handlers(opts.Validated.Origin) - return &Instance{Handlers: handlers, li: logInfo}, nil + return &Instance{Handlers: handlers}, nil } From 5c6ed578c0a563696e32dbc2a7275401494228b0 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Tue, 24 Dec 2024 16:43:57 +0000 Subject: [PATCH 06/11] remove instance.go --- cmd/gcp/main.go | 7 +- handlers.go | 23 ++++++ handlers_test.go | 4 ++ instance.go | 57 --------------- instance_test.go | 177 ----------------------------------------------- 5 files changed, 29 insertions(+), 239 deletions(-) delete mode 100644 instance.go delete mode 100644 instance_test.go diff --git a/cmd/gcp/main.go b/cmd/gcp/main.go index c630b0b0..fa557c84 100644 --- a/cmd/gcp/main.go +++ b/cmd/gcp/main.go @@ -106,10 +106,7 @@ func main() { TimeSource: timeSource, } - inst, err := sctfe.SetUpInstance(ctx, opts) - if err != nil { - klog.Exitf("Failed to set up log instance for %+v: %v", vCfg, err) - } + handlers := sctfe.NewPathHandlers(opts) klog.CopyStandardLogTo("WARNING") klog.Info("**** CT HTTP Server Starting ****") @@ -127,7 +124,7 @@ func main() { http.Handle("/", corsHandler) // Register handlers for all the configured logs. - for path, handler := range inst.Handlers { + for path, handler := range handlers { corsMux.Handle(path, handler) } diff --git a/handlers.go b/handlers.go index 15730aea..dfdd395d 100644 --- a/handlers.go +++ b/handlers.go @@ -211,6 +211,23 @@ type logInfo struct { signer crypto.Signer } +// InstanceOptions describes the options for a log instance. +type InstanceOptions struct { + // Validated holds the original configuration options for the log, and some + // of its fields parsed as a result of validating it. + Validated *ValidatedLogConfig + // Storage stores data to satisfy https://c2sp.org/static-ct-api. + Storage *CTStorage + // Deadline is a timeout for HTTP requests. + Deadline time.Duration + // MetricFactory allows creating metrics. + MetricFactory monitoring.MetricFactory + // RequestLog provides structured logging of CTFE requests. + RequestLog RequestLog + MaskInternalErrors bool + TimeSource TimeSource +} + // newLogInfo creates a new instance of logInfo. func newLogInfo( instanceOpts InstanceOptions, @@ -238,6 +255,12 @@ func newLogInfo( return li } +func NewPathHandlers(opts InstanceOptions) PathHandlers { + cfg := opts.Validated + logInfo := newLogInfo(opts, cfg.CertValidationOpts, cfg.Signer, opts.TimeSource, opts.Storage) + return logInfo.Handlers(opts.Validated.Origin) +} + // Handlers returns a map from URL paths (with the given prefix) and AppHandler instances // to handle those entrypoints. func (li *logInfo) Handlers(prefix string) PathHandlers { diff --git a/handlers_test.go b/handlers_test.go index d89de9f6..1cd57e91 100644 --- a/handlers_test.go +++ b/handlers_test.go @@ -399,6 +399,8 @@ func TestAddChain(t *testing.T) { t.Errorf("resp.Signature=%s; want %s", got, want) } // TODO(phboneff): check that the index is in the SCT + // TODO(phboneff): add a test with a not after range + // TODO(phbpneff): add a test with a start date only } }) } @@ -444,6 +446,8 @@ func TestAddPrechain(t *testing.T) { }, // TODO(phboneff): add a test with an intermediate // TODO(phboneff): add a test with a pre-issuer intermediate cert + // TODO(phboneff): add a test with a not after range + // TODO(phbpneff): add a test with a start date only } signer, err := setupSigner(fakeSignature) diff --git a/instance.go b/instance.go deleted file mode 100644 index 19ff80c3..00000000 --- a/instance.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 Google LLC. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package sctfe - -import ( - "context" - "time" - - "github.com/google/trillian/monitoring" -) - -// InstanceOptions describes the options for a log instance. -type InstanceOptions struct { - // Validated holds the original configuration options for the log, and some - // of its fields parsed as a result of validating it. - Validated *ValidatedLogConfig - // Storage stores data to implement https://c2sp.org/static-ct-api. - Storage *CTStorage - // Deadline is a timeout for HTTP requests. - Deadline time.Duration - // MetricFactory allows creating metrics. - MetricFactory monitoring.MetricFactory - // RequestLog provides structured logging of CTFE requests. - RequestLog RequestLog - MaskInternalErrors bool - TimeSource TimeSource -} - -// Instance is a set up log/mirror instance. It must be created with the -// SetUpInstance call. -type Instance struct { - Handlers PathHandlers -} - -// SetUpInstance sets up a log (or log mirror) instance using the provided -// configuration, and returns an object containing a set of handlers for this -// log, and an STH getter. -func SetUpInstance(ctx context.Context, opts InstanceOptions) (*Instance, error) { - cfg := opts.Validated - - logInfo := newLogInfo(opts, cfg.CertValidationOpts, cfg.Signer, opts.TimeSource, opts.Storage) - - handlers := logInfo.Handlers(opts.Validated.Origin) - return &Instance{Handlers: handlers}, nil -} diff --git a/instance_test.go b/instance_test.go deleted file mode 100644 index 576c2134..00000000 --- a/instance_test.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2016 Google LLC. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package sctfe - -import ( - "context" - "crypto" - "errors" - "fmt" - "net/http/httptest" - "strings" - "testing" - "time" - - ct "github.com/google/certificate-transparency-go" - "github.com/google/trillian/crypto/keys/pem" - "github.com/google/trillian/monitoring" -) - -func TestSetUpInstance(t *testing.T) { - ctx := context.Background() - - signer, err := pem.ReadPrivateKeyFile("./testdata/ct-http-server.privkey.pem", "dirk") - if err != nil { - t.Fatalf("Can't open key: %v", err) - } - - var tests = []struct { - desc string - origin string - rootsPemFile string - extKeyUsages string - rejectExtensions string - signer crypto.Signer - wantErr string - }{ - { - desc: "valid", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - signer: signer, - }, - } - - for _, test := range tests { - t.Run(test.desc, func(t *testing.T) { - vCfg, err := ValidateLogConfig(test.origin, test.rootsPemFile, false, false, test.extKeyUsages, test.rejectExtensions, nil, nil, signer) - if err != nil { - t.Fatalf("ValidateLogConfig(): %v", err) - } - opts := InstanceOptions{Validated: vCfg, Deadline: time.Second, MetricFactory: monitoring.InertMetricFactory{}, Storage: &CTStorage{}} - - if _, err := SetUpInstance(ctx, opts); err != nil { - if test.wantErr == "" { - t.Errorf("SetUpInstance()=_,%v; want _,nil", err) - } else if !strings.Contains(err.Error(), test.wantErr) { - t.Errorf("SetUpInstance()=_,%v; want err containing %q", err, test.wantErr) - } - return - } - if test.wantErr != "" { - t.Errorf("SetUpInstance()=_,nil; want err containing %q", test.wantErr) - } - }) - } -} - -func equivalentTimes(a *time.Time, b *time.Time) bool { - if a == nil && b == nil { - return true - } - if a == nil { - // b can't be nil as it would have returned above. - return false - } - return a.Equal(*b) -} - -// This tests that the right values of LogInfo are passed through. We can probably delete these tests, or check -// that the whole loginfo is passed through. -func TestSetUpInstanceSetsValidationOpts(t *testing.T) { - ctx := context.Background() - - start := time.Unix(10000, 0) - limit := time.Unix(12000, 0) - - signer, err := pem.ReadPrivateKeyFile("./testdata/ct-http-server.privkey.pem", "dirk") - if err != nil { - t.Fatalf("Can't open key: %v", err) - } - - var tests = []struct { - desc string - origin string - rootsPemFile string - notAfterStart *time.Time - notAfterLimit *time.Time - signer crypto.Signer - }{ - { - desc: "no validation opts", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - signer: signer, - }, - { - desc: "notAfterStart only", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - notAfterStart: &start, - }, - { - desc: "notAfter range", - origin: "log", - rootsPemFile: "./testdata/fake-ca.cert", - notAfterStart: &start, - notAfterLimit: &limit, - signer: signer, - }, - } - - for _, test := range tests { - t.Run(test.desc, func(t *testing.T) { - vCfg, err := ValidateLogConfig(test.origin, test.rootsPemFile, false, false, "", "", test.notAfterStart, test.notAfterLimit, signer) - if err != nil { - t.Fatalf("ValidateLogConfig(): %v", err) - } - opts := InstanceOptions{Validated: vCfg, Deadline: time.Second, MetricFactory: monitoring.InertMetricFactory{}, Storage: &CTStorage{}} - - inst, err := SetUpInstance(ctx, opts) - if err != nil { - t.Fatalf("%v: SetUpInstance() = %v, want no error", test.desc, err) - } - addChainHandler, ok := inst.Handlers["/"+test.origin+ct.AddChainPath] - if !ok { - t.Fatal("Couldn't find AddChain handler") - } - gotOpts := addChainHandler.Info.validationOpts - if got, want := gotOpts.notAfterStart, test.notAfterStart; !equivalentTimes(got, want) { - t.Errorf("%v: handler notAfterStart %v, want %v", test.desc, got, want) - } - if got, want := gotOpts.notAfterLimit, test.notAfterLimit; !equivalentTimes(got, want) { - t.Errorf("%v: handler notAfterLimit %v, want %v", test.desc, got, want) - } - }) - } -} - -func TestErrorMasking(t *testing.T) { - info := logInfo{} - w := httptest.NewRecorder() - prefix := "Internal Server Error" - err := errors.New("well that's bad") - info.SendHTTPError(w, 500, err) - if got, want := w.Body.String(), fmt.Sprintf("%s\n%v\n", prefix, err); got != want { - t.Errorf("SendHTTPError: got %s, want %s", got, want) - } - info.maskInternalErrors = true - w = httptest.NewRecorder() - info.SendHTTPError(w, 500, err) - if got, want := w.Body.String(), prefix+"\n"; got != want { - t.Errorf("SendHTTPError: got %s, want %s", got, want) - } - -} From e2f470a5534ab8760ac2ffc99876f2ac7a241564 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Fri, 10 Jan 2025 15:30:24 +0000 Subject: [PATCH 07/11] s/InstanceOptions/HandlerOptions and add comments --- cmd/gcp/main.go | 2 +- handlers.go | 25 ++++++++++++++----------- handlers_test.go | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/cmd/gcp/main.go b/cmd/gcp/main.go index fa557c84..c1f671ae 100644 --- a/cmd/gcp/main.go +++ b/cmd/gcp/main.go @@ -96,7 +96,7 @@ func main() { klog.Exitf("Invalid config: %v", err) } - opts := sctfe.InstanceOptions{ + opts := sctfe.HandlerOptions{ Validated: vCfg, Deadline: *httpDeadline, MetricFactory: prometheus.MetricFactory{}, diff --git a/handlers.go b/handlers.go index dfdd395d..ba1c68c0 100644 --- a/handlers.go +++ b/handlers.go @@ -211,8 +211,8 @@ type logInfo struct { signer crypto.Signer } -// InstanceOptions describes the options for a log instance. -type InstanceOptions struct { +// HandlerOptions describes log handlers options. +type HandlerOptions struct { // Validated holds the original configuration options for the log, and some // of its fields parsed as a result of validating it. Validated *ValidatedLogConfig @@ -223,39 +223,42 @@ type InstanceOptions struct { // MetricFactory allows creating metrics. MetricFactory monitoring.MetricFactory // RequestLog provides structured logging of CTFE requests. - RequestLog RequestLog + RequestLog RequestLog + // MaskInternalErrors indicates if internal server errors should be masked + // or returned to the user containing the full error message. MaskInternalErrors bool - TimeSource TimeSource + // TimeSource indicated the system time and can be injfected for testing. + TimeSource TimeSource } // newLogInfo creates a new instance of logInfo. func newLogInfo( - instanceOpts InstanceOptions, + hOpts HandlerOptions, validationOpts CertValidationOpts, signer crypto.Signer, timeSource TimeSource, storage Storage, ) *logInfo { - cfg := instanceOpts.Validated + cfg := hOpts.Validated li := &logInfo{ Origin: cfg.Origin, storage: storage, signer: signer, TimeSource: timeSource, - maskInternalErrors: instanceOpts.MaskInternalErrors, - deadline: instanceOpts.Deadline, + maskInternalErrors: hOpts.MaskInternalErrors, + deadline: hOpts.Deadline, validationOpts: validationOpts, - RequestLog: instanceOpts.RequestLog, + RequestLog: hOpts.RequestLog, } - once.Do(func() { setupMetrics(instanceOpts.MetricFactory) }) + once.Do(func() { setupMetrics(hOpts.MetricFactory) }) knownLogs.Set(1.0, cfg.Origin) return li } -func NewPathHandlers(opts InstanceOptions) PathHandlers { +func NewPathHandlers(opts HandlerOptions) PathHandlers { cfg := opts.Validated logInfo := newLogInfo(opts, cfg.CertValidationOpts, cfg.Signer, opts.TimeSource, opts.Storage) return logInfo.Handlers(opts.Validated.Origin) diff --git a/handlers_test.go b/handlers_test.go index 1cd57e91..5c625b43 100644 --- a/handlers_test.go +++ b/handlers_test.go @@ -77,7 +77,7 @@ func setupTest(t *testing.T, pemRoots []string, signer crypto.Signer) handlerTes } cfg := &ValidatedLogConfig{Origin: "example.com"} - iOpts := InstanceOptions{Validated: cfg, Deadline: time.Millisecond * 500, MetricFactory: monitoring.InertMetricFactory{}, RequestLog: new(DefaultRequestLog)} + iOpts := HandlerOptions{Validated: cfg, Deadline: time.Millisecond * 500, MetricFactory: monitoring.InertMetricFactory{}, RequestLog: new(DefaultRequestLog)} info.li = newLogInfo(iOpts, vOpts, signer, fakeTimeSource, info.storage) for _, pemRoot := range pemRoots { From a980b466817690152576027c203991a6bd25da4e Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Wed, 15 Jan 2025 16:30:58 +0000 Subject: [PATCH 08/11] comments --- cmd/gcp/main.go | 6 +++--- config.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/gcp/main.go b/cmd/gcp/main.go index c1f671ae..7ace9f9c 100644 --- a/cmd/gcp/main.go +++ b/cmd/gcp/main.go @@ -83,12 +83,12 @@ func main() { } cpSigner, err := sctfe.NewCpSigner(signer, *origin, timeSource) if err != nil { - klog.Exitf("failed to create checkpoint Signer: %v", err) + klog.Exitf("Failed to create checkpoint Signer: %v", err) } storage, err := newGCPStorage(ctx, cpSigner) if err != nil { - klog.Exitf("failed to initiate storage backend: %v", err) + klog.Exitf("Failed to initiate storage backend: %v", err) } vCfg, err := sctfe.ValidateLogConfig(*origin, *rootsPemFile, *rejectExpired, *rejectUnexpired, *extKeyUsages, *rejectExtensions, notAfterStart.t, notAfterLimit.t, signer) @@ -100,7 +100,7 @@ func main() { Validated: vCfg, Deadline: *httpDeadline, MetricFactory: prometheus.MetricFactory{}, - RequestLog: new(sctfe.DefaultRequestLog), + RequestLog: &sctfe.DefaultRequestLog{}, MaskInternalErrors: *maskInternalErrors, Storage: storage, TimeSource: timeSource, diff --git a/config.go b/config.go index a67fdde1..23371886 100644 --- a/config.go +++ b/config.go @@ -75,12 +75,12 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r } if rejectExpired && rejectUnexpired { - return nil, errors.New("rejecting all certificates") + return nil, errors.New("configuration would reject all certificates") } // Validate the time interval. if notAfterStart != nil && notAfterLimit != nil && (notAfterLimit).Before(*notAfterStart) { - return nil, errors.New("limit before start") + return nil, fmt.Errorf("limit %q before start %q", notAfterLimit.Format(time.RFC3339), notAfterStart.Format(time.RFC3339)) } validationOpts := CertValidationOpts{ From 9f7b49b71b44e8a64c08cb147b1dab1b427ae666 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Wed, 15 Jan 2025 16:31:42 +0000 Subject: [PATCH 09/11] rsa --- config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/config.go b/config.go index 23371886..06b4fb6e 100644 --- a/config.go +++ b/config.go @@ -64,7 +64,6 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r } // Validate signer that only ECDSA is supported. - // TODO(phboneff): if this is a library this should also allow RSA as per RFC6962. if signer == nil { return nil, errors.New("empty signer") } From 86f1935c6fb1b6634181aefbfddddca2deca8b35 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Wed, 15 Jan 2025 16:35:03 +0000 Subject: [PATCH 10/11] better error message --- config.go | 2 +- config_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index 06b4fb6e..23d3076a 100644 --- a/config.go +++ b/config.go @@ -79,7 +79,7 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r // Validate the time interval. if notAfterStart != nil && notAfterLimit != nil && (notAfterLimit).Before(*notAfterStart) { - return nil, fmt.Errorf("limit %q before start %q", notAfterLimit.Format(time.RFC3339), notAfterStart.Format(time.RFC3339)) + return nil, fmt.Errorf("not_after limit %q before start %q", notAfterLimit.Format(time.RFC3339), notAfterStart.Format(time.RFC3339)) } validationOpts := CertValidationOpts{ diff --git a/config_test.go b/config_test.go index 84906d96..fff94d9e 100644 --- a/config_test.go +++ b/config_test.go @@ -76,7 +76,7 @@ func TestValidateLogConfig(t *testing.T) { }, { desc: "rejecting-all", - wantErr: "rejecting all certificates", + wantErr: "configuration would reject all certificates", origin: "testlog", projectID: "project", bucket: "bucket", @@ -132,7 +132,7 @@ func TestValidateLogConfig(t *testing.T) { }, { desc: "limit-before-start", - wantErr: "limit before start", + wantErr: "before start", origin: "testlog", projectID: "project", bucket: "bucket", From 3c44c2277dc4654508da842cc534ca75a85337f1 Mon Sep 17 00:00:00 2001 From: Philippe Boneff Date: Fri, 17 Jan 2025 10:02:39 +0000 Subject: [PATCH 11/11] comments --- cmd/gcp/main.go | 2 +- config.go | 2 +- handlers_test.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/gcp/main.go b/cmd/gcp/main.go index 7ace9f9c..8c7437bf 100644 --- a/cmd/gcp/main.go +++ b/cmd/gcp/main.go @@ -83,7 +83,7 @@ func main() { } cpSigner, err := sctfe.NewCpSigner(signer, *origin, timeSource) if err != nil { - klog.Exitf("Failed to create checkpoint Signer: %v", err) + klog.Exitf("Failed to create checkpoint signer: %v", err) } storage, err := newGCPStorage(ctx, cpSigner) diff --git a/config.go b/config.go index 23d3076a..00007f64 100644 --- a/config.go +++ b/config.go @@ -79,7 +79,7 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r // Validate the time interval. if notAfterStart != nil && notAfterLimit != nil && (notAfterLimit).Before(*notAfterStart) { - return nil, fmt.Errorf("not_after limit %q before start %q", notAfterLimit.Format(time.RFC3339), notAfterStart.Format(time.RFC3339)) + return nil, fmt.Errorf("'Not After' limit %q before start %q", notAfterLimit.Format(time.RFC3339), notAfterStart.Format(time.RFC3339)) } validationOpts := CertValidationOpts{ diff --git a/handlers_test.go b/handlers_test.go index 5c625b43..1544bca6 100644 --- a/handlers_test.go +++ b/handlers_test.go @@ -400,7 +400,7 @@ func TestAddChain(t *testing.T) { } // TODO(phboneff): check that the index is in the SCT // TODO(phboneff): add a test with a not after range - // TODO(phbpneff): add a test with a start date only + // TODO(phboneff): add a test with a start date only } }) } @@ -447,7 +447,7 @@ func TestAddPrechain(t *testing.T) { // TODO(phboneff): add a test with an intermediate // TODO(phboneff): add a test with a pre-issuer intermediate cert // TODO(phboneff): add a test with a not after range - // TODO(phbpneff): add a test with a start date only + // TODO(phboneff): add a test with a start date only } signer, err := setupSigner(fakeSignature)