Skip to content

Delete instance.go #89

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 23 additions & 14 deletions cmd/gcp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,38 @@ 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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: "Failed..."

}

storage, err := newGCPStorage(ctx, cpSigner)
if err != nil {
klog.Exitf("failed to initiate storage backend: %v", err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "Failed...

}

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.HandlerOptions{
Validated: vCfg,
Deadline: *httpDeadline,
MetricFactory: prometheus.MetricFactory{},
RequestLog: new(sctfe.DefaultRequestLog),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: match style for MetricFactory:

Suggested change
RequestLog: new(sctfe.DefaultRequestLog),
RequestLog: &sctfe.DefaultRequestLog{},

MaskInternalErrors: *maskInternalErrors,
Storage: storage,
TimeSource: timeSource,
}

handlers := sctfe.NewPathHandlers(opts)

klog.CopyStandardLogTo("WARNING")
klog.Info("**** CT HTTP Server Starting ****")

Expand All @@ -102,20 +124,7 @@ func main() {
http.Handle("/", corsHandler)

// Register handlers for all the configured logs.
opts := sctfe.InstanceOptions{
Validated: vCfg,
Deadline: *httpDeadline,
MetricFactory: prometheus.MetricFactory{},
RequestLog: new(sctfe.DefaultRequestLog),
MaskInternalErrors: *maskInternalErrors,
CreateStorage: newGCPStorage,
}

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 {
for path, handler := range handlers {
corsMux.Handle(path, handler)
}

Expand Down
108 changes: 60 additions & 48 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -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:
Expand All @@ -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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devil's avocado: if it supports ECDSA then that's enough to build RFC6962-compliant logs; there's no requirement to support RSA (or, would we recommend anyone to use RSA for a new log, these days?)

if signer == nil {
return nil, errors.New("empty signer")
}
Expand All @@ -87,54 +74,79 @@ func ValidateLogConfig(origin string, rootsPemFile string, rejectExpired bool, r
return nil, fmt.Errorf("unsupported key type: %v", keyType)
}

lExtKeyUsages := []string{}
lRejectExtensions := []string{}
if extKeyUsages != "" {
lExtKeyUsages = strings.Split(extKeyUsages, ",")
}
if rejectExtensions != "" {
lRejectExtensions = strings.Split(rejectExtensions, ",")
if rejectExpired && rejectUnexpired {
return nil, errors.New("rejecting all certificates")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return nil, errors.New("rejecting all certificates")
return nil, errors.New("configuration would reject all certificates")

}

vCfg := ValidatedLogConfig{
Origin: origin,
RootsPemFile: rootsPemFile,
RejectExpired: rejectExpired,
RejectUnexpired: rejectUnexpired,
RejectExtensions: lRejectExtensions,
NotAfterStart: notAfterStart,
NotAfterLimit: notAfterLimit,
Signer: signer,
// Validate the time interval.
if notAfterStart != nil && notAfterLimit != nil && (notAfterLimit).Before(*notAfterStart) {
return nil, errors.New("limit before start")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: worth doing fmt.Errorf with the dates in?

}

if rejectExpired && rejectUnexpired {
return nil, errors.New("rejecting all certificates")
validationOpts := CertValidationOpts{
trustedRoots: roots,
rejectExpired: rejectExpired,
rejectUnexpired: rejectUnexpired,
notAfterStart: notAfterStart,
notAfterLimit: notAfterLimit,
}

// Filter which extended key usages are allowed.
lExtKeyUsages := []string{}
if extKeyUsages != "" {
lExtKeyUsages = strings.Split(extKeyUsages, ",")
}
// Validate the extended key usages list.
for _, kuStr := range lExtKeyUsages {
if ku, ok := stringToKeyUsage[kuStr]; ok {
// If "Any" is specified, then we can ignore the entire list and
// 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)
}
}

// Validate the time interval.
if notAfterStart != nil && notAfterLimit != nil && (notAfterLimit).Before(*notAfterStart) {
return nil, errors.New("limit before start")
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,
Expand Down
60 changes: 46 additions & 14 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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)
}
Expand Down
Loading
Loading