lint: check that cert doesn't have extra +1s (#5677)

Add a new lint, which applies to all certs, not just one kind of
root/intermediate/subscriber cert, which checks that the validity
period is a round number of minutes; i.e. that it doesn't have an
extra second of validity, like 90d+1s.

In general, if all certs are issued with validities much less than
the limits imposed by root program requirements, being off by one
second one way or another shouldn't matter much. But since it is
easy to mistakenly configure a cert to have notBefore and notAfter
timestamps with the exact same second value, this lint will force
people configuring profiles to think critically about their cert
lifetimes.

Fixes #5669
This commit is contained in:
Aaron Gable 2021-09-30 11:00:56 -07:00 committed by GitHub
parent 3f3f250212
commit 9ac85891bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 0 deletions

View File

@ -13,6 +13,7 @@ import (
"github.com/zmap/zlint/v3"
"github.com/zmap/zlint/v3/lint"
_ "github.com/letsencrypt/boulder/linter/lints/all"
_ "github.com/letsencrypt/boulder/linter/lints/intermediate"
_ "github.com/letsencrypt/boulder/linter/lints/root"
_ "github.com/letsencrypt/boulder/linter/lints/subscriber"

View File

@ -0,0 +1,43 @@
package subscriber
import (
"time"
"github.com/zmap/zcrypto/x509"
"github.com/zmap/zlint/v3/lint"
"github.com/letsencrypt/boulder/linter/lints"
)
type anyCertValidityNotRound struct{}
func init() {
lint.RegisterLint(&lint.Lint{
Name: "w_validity_period_has_extra_second",
Description: "Let's Encrypt Certificates have Validity Periods that are a round number of seconds",
Citation: "CPS: 7.1",
Source: lints.LetsEncryptCPSAll,
EffectiveDate: lints.CPSV33Date,
Lint: &anyCertValidityNotRound{},
})
}
func (l *anyCertValidityNotRound) Initialize() error {
return nil
}
func (l *anyCertValidityNotRound) CheckApplies(c *x509.Certificate) bool {
return true
}
func (l *anyCertValidityNotRound) Execute(c *x509.Certificate) *lint.LintResult {
// RFC 5280 4.1.2.5: "The validity period for a certificate is the period
// of time from notBefore through notAfter, inclusive."
certValidity := c.NotAfter.Add(time.Second).Sub(c.NotBefore)
if certValidity%60 == 0 {
return &lint.LintResult{Status: lint.Pass}
}
return &lint.LintResult{Status: lint.Error}
}

View File

@ -14,6 +14,7 @@ const (
DaySeconds time.Duration = 86400 * time.Second
// Declare our own Sources for use in zlint registry filtering.
LetsEncryptCPSAll lint.LintSource = "LECPSAll"
LetsEncryptCPSIntermediate lint.LintSource = "LECPSIntermediate"
LetsEncryptCPSRoot lint.LintSource = "LECPSRoot"
LetsEncryptCPSSubscriber lint.LintSource = "LECPSSubscriber"