Skip to content

Commit 1895147

Browse files
committed
Add infrastructure to configure lints with issuer and pre-existing cert
1 parent 45fdbfb commit 1895147

10 files changed

Lines changed: 454 additions & 59 deletions

File tree

cmd/ceremony/main.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,15 @@ type lintCert *x509.Certificate
4646
// template certificate signed by a given issuer and returns a *lintCert or an
4747
// error. The lint certificate is linted prior to being returned. The public key
4848
// from the just issued lint certificate is checked by the GoodKey package.
49-
func issueLintCertAndPerformLinting(tbs, issuer *x509.Certificate, subjectPubKey crypto.PublicKey, signer crypto.Signer, skipLints []string) (lintCert, error) {
50-
bytes, err := linter.Check(tbs, subjectPubKey, issuer, signer, skipLints)
49+
// When cross-signing, existing is the pre-existing certificate of the CA being
50+
// cross-signed, allowing the CP/CPS profile lints to check correspondence with
51+
// it; it is nil otherwise.
52+
func issueLintCertAndPerformLinting(tbs, issuer *x509.Certificate, subjectPubKey crypto.PublicKey, signer crypto.Signer, existing *x509.Certificate, skipLints []string) (lintCert, error) {
53+
lintConfig, err := linter.Config{}.WithExisting(existing)
54+
if err != nil {
55+
return nil, fmt.Errorf("unable to create lint config: %w", err)
56+
}
57+
bytes, err := linter.Check(tbs, subjectPubKey, issuer, signer, lintConfig, skipLints)
5158
if err != nil {
5259
return nil, fmt.Errorf("certificate failed pre-issuance lint: %w", err)
5360
}
@@ -66,8 +73,10 @@ func issueLintCertAndPerformLinting(tbs, issuer *x509.Certificate, subjectPubKey
6673
// postIssuanceLinting performs post-issuance linting on the raw bytes of a
6774
// given certificate with the same set of lints as
6875
// issueLintCertAndPerformLinting. The public key is also checked by the GoodKey
69-
// package.
70-
func postIssuanceLinting(fc *x509.Certificate, skipLints []string) error {
76+
// package. The issuer and existing certificates, when non-nil, are supplied to
77+
// the CP/CPS profile lints so that they can perform their correspondence
78+
// checks.
79+
func postIssuanceLinting(fc, issuer, existing *x509.Certificate, skipLints []string) error {
7180
if fc == nil {
7281
return fmt.Errorf("certificate was not provided")
7382
}
@@ -77,7 +86,15 @@ func postIssuanceLinting(fc *x509.Certificate, skipLints []string) error {
7786
// lint. This should be treated as ZLint rejecting the certificate
7887
return fmt.Errorf("unable to parse certificate: %s", err)
7988
}
80-
registry, err := linter.NewRegistry(skipLints)
89+
lintConfig, err := linter.Config{}.WithIssuer(issuer)
90+
if err != nil {
91+
return fmt.Errorf("unable to create lint config: %s", err)
92+
}
93+
lintConfig, err = lintConfig.WithExisting(existing)
94+
if err != nil {
95+
return fmt.Errorf("unable to create lint config: %s", err)
96+
}
97+
registry, err := linter.NewRegistryWithConfig(skipLints, lintConfig)
8198
if err != nil {
8299
return fmt.Errorf("unable to create zlint registry: %s", err)
83100
}
@@ -586,15 +603,15 @@ func rootCeremony(configBytes []byte) error {
586603
if err != nil {
587604
return fmt.Errorf("failed to create certificate profile: %s", err)
588605
}
589-
lintCert, err := issueLintCertAndPerformLinting(template, template, keyInfo.key, signer, config.SkipLints)
606+
lintCert, err := issueLintCertAndPerformLinting(template, template, keyInfo.key, signer, nil, config.SkipLints)
590607
if err != nil {
591608
return err
592609
}
593610
finalCert, err := signAndWriteCert(template, template, lintCert, keyInfo.key, signer, config.Outputs.CertificatePath)
594611
if err != nil {
595612
return err
596613
}
597-
err = postIssuanceLinting(finalCert, config.SkipLints)
614+
err = postIssuanceLinting(finalCert, nil, nil, config.SkipLints)
598615
if err != nil {
599616
return err
600617
}
@@ -631,7 +648,7 @@ func intermediateCeremony(configBytes []byte) error {
631648
return fmt.Errorf("failed to create certificate profile: %s", err)
632649
}
633650
template.AuthorityKeyId = issuer.SubjectKeyId
634-
lintCert, err := issueLintCertAndPerformLinting(template, issuer, pub, signer, config.SkipLints)
651+
lintCert, err := issueLintCertAndPerformLinting(template, issuer, pub, signer, nil, config.SkipLints)
635652
if err != nil {
636653
return err
637654
}
@@ -646,7 +663,7 @@ func intermediateCeremony(configBytes []byte) error {
646663
if !bytes.Equal(lintCert.RawTBSCertificate, finalCert.RawTBSCertificate) {
647664
return fmt.Errorf("mismatch between lintCert and finalCert RawTBSCertificate DER bytes: \"%x\" != \"%x\"", lintCert.RawTBSCertificate, finalCert.RawTBSCertificate)
648665
}
649-
err = postIssuanceLinting(finalCert, config.SkipLints)
666+
err = postIssuanceLinting(finalCert, issuer, nil, config.SkipLints)
650667
if err != nil {
651668
return err
652669
}
@@ -687,7 +704,7 @@ func crossCertCeremony(configBytes []byte) error {
687704
return fmt.Errorf("failed to create certificate profile: %s", err)
688705
}
689706
template.AuthorityKeyId = issuer.SubjectKeyId
690-
lintCert, err := issueLintCertAndPerformLinting(template, issuer, pub, signer, config.SkipLints)
707+
lintCert, err := issueLintCertAndPerformLinting(template, issuer, pub, signer, toBeCrossSigned, config.SkipLints)
691708
if err != nil {
692709
return err
693710
}
@@ -748,7 +765,7 @@ func crossCertCeremony(configBytes []byte) error {
748765
if !bytes.Equal(lintCert.RawTBSCertificate, finalCert.RawTBSCertificate) {
749766
return fmt.Errorf("mismatch between lintCert and finalCert RawTBSCertificate DER bytes: \"%x\" != \"%x\"", lintCert.RawTBSCertificate, finalCert.RawTBSCertificate)
750767
}
751-
err = postIssuanceLinting(finalCert, config.SkipLints)
768+
err = postIssuanceLinting(finalCert, issuer, toBeCrossSigned, config.SkipLints)
752769
if err != nil {
753770
return err
754771
}

cmd/ceremony/main_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,7 @@ func TestSignAndWriteNoLintCert(t *testing.T) {
12921292

12931293
func TestPostIssuanceLinting(t *testing.T) {
12941294
clk := clock.New()
1295-
err := postIssuanceLinting(nil, nil)
1295+
err := postIssuanceLinting(nil, nil, nil, nil)
12961296
test.AssertError(t, err, "should have failed because no certificate was provided")
12971297

12981298
testKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
@@ -1306,6 +1306,6 @@ func TestPostIssuanceLinting(t *testing.T) {
13061306
test.AssertNotError(t, err, "unable to create certificate")
13071307
parsedCert, err := x509.ParseCertificate(certDer)
13081308
test.AssertNotError(t, err, "unable to parse DER bytes")
1309-
err = postIssuanceLinting(parsedCert, nil)
1309+
err = postIssuanceLinting(parsedCert, nil, nil, nil)
13101310
test.AssertNotError(t, err, "should not have errored")
13111311
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ require (
2222
github.com/miekg/dns v1.1.62
2323
github.com/miekg/pkcs11 v1.1.2
2424
github.com/nxadm/tail v1.4.11
25+
github.com/pelletier/go-toml v1.9.5
2526
github.com/prometheus/client_golang v1.22.0
2627
github.com/prometheus/client_model v0.6.1
2728
github.com/redis/go-redis/extra/redisotel/v9 v9.5.3
@@ -76,7 +77,6 @@ require (
7677
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
7778
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
7879
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
79-
github.com/pelletier/go-toml v1.9.5 // indirect
8080
github.com/poy/onpar v1.1.2 // indirect
8181
github.com/prometheus/common v0.62.0 // indirect
8282
github.com/prometheus/procfs v0.15.1 // indirect

issuance/cert.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,14 @@ type Profile struct {
7777

7878
maxCertificateSize int
7979

80+
// lints is the registry of lints to run against certificates issued under
81+
// this profile. It carries no lint configuration of its own: at issuance
82+
// time it is combined with a configuration derived from lintConfig.
8083
lints lint.Registry
84+
// lintConfig is the in-memory contents of this profile's zlint config
85+
// file. At issuance time it is augmented with the issuing Issuer's
86+
// certificate via WithIssuer.
87+
lintConfig linter.Config
8188
}
8289

8390
// NewProfile converts the profile config into a usable profile.
@@ -102,11 +109,9 @@ func NewProfile(profileConfig ProfileConfig) (*Profile, error) {
102109

103110
lints, err := linter.NewRegistry(profileConfig.IgnoredLints)
104111
cmd.FailOnError(err, "Failed to create zlint registry")
105-
if profileConfig.LintConfig != "" {
106-
lintconfig, err := lint.NewConfigFromFile(profileConfig.LintConfig)
107-
cmd.FailOnError(err, "Failed to load zlint config file")
108-
lints.SetConfiguration(lintconfig)
109-
}
112+
113+
lintConfig, err := linter.LoadConfigFile(profileConfig.LintConfig)
114+
cmd.FailOnError(err, "Failed to load zlint config file")
110115

111116
sp := &Profile{
112117
omitCommonName: profileConfig.OmitCommonName,
@@ -118,6 +123,7 @@ func NewProfile(profileConfig ProfileConfig) (*Profile, error) {
118123
maxValidity: profileConfig.MaxValidityPeriod.Duration,
119124
maxCertificateSize: profileConfig.MaxCertificateSize,
120125
lints: lints,
126+
lintConfig: lintConfig,
121127
}
122128

123129
return sp, nil
@@ -386,7 +392,11 @@ func (i *Issuer) Prepare(prof *Profile, req *IssuanceRequest) ([]byte, *issuance
386392

387393
// check that the tbsCertificate is properly formed by signing it
388394
// with a throwaway key and then linting it using zlint
389-
lintCertBytes, err := i.Linter.Check(template, req.PublicKey.PublicKey, prof.lints)
395+
lintConfig, err := prof.lintConfig.WithIssuer(i.Cert.Certificate)
396+
if err != nil {
397+
return nil, nil, fmt.Errorf("building lint config: %w", err)
398+
}
399+
lintCertBytes, err := i.Linter.Check(template, req.PublicKey.PublicKey, prof.lints, lintConfig)
390400
if err != nil {
391401
return nil, nil, fmt.Errorf("tbsCertificate linting failed: %w", err)
392402
}

0 commit comments

Comments
 (0)