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:
		
							parent
							
								
									3f3f250212
								
							
						
					
					
						commit
						9ac85891bb
					
				|  | @ -13,6 +13,7 @@ import ( | ||||||
| 	"github.com/zmap/zlint/v3" | 	"github.com/zmap/zlint/v3" | ||||||
| 	"github.com/zmap/zlint/v3/lint" | 	"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/intermediate" | ||||||
| 	_ "github.com/letsencrypt/boulder/linter/lints/root" | 	_ "github.com/letsencrypt/boulder/linter/lints/root" | ||||||
| 	_ "github.com/letsencrypt/boulder/linter/lints/subscriber" | 	_ "github.com/letsencrypt/boulder/linter/lints/subscriber" | ||||||
|  |  | ||||||
|  | @ -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} | ||||||
|  | } | ||||||
|  | @ -14,6 +14,7 @@ const ( | ||||||
| 	DaySeconds time.Duration = 86400 * time.Second | 	DaySeconds time.Duration = 86400 * time.Second | ||||||
| 
 | 
 | ||||||
| 	// Declare our own Sources for use in zlint registry filtering.
 | 	// Declare our own Sources for use in zlint registry filtering.
 | ||||||
|  | 	LetsEncryptCPSAll          lint.LintSource = "LECPSAll" | ||||||
| 	LetsEncryptCPSIntermediate lint.LintSource = "LECPSIntermediate" | 	LetsEncryptCPSIntermediate lint.LintSource = "LECPSIntermediate" | ||||||
| 	LetsEncryptCPSRoot         lint.LintSource = "LECPSRoot" | 	LetsEncryptCPSRoot         lint.LintSource = "LECPSRoot" | ||||||
| 	LetsEncryptCPSSubscriber   lint.LintSource = "LECPSSubscriber" | 	LetsEncryptCPSSubscriber   lint.LintSource = "LECPSSubscriber" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue