Compute validity periods inclusive of notAfter second (#5494)
In the CA, compute the notAfter timestamp such that the cert is actually valid for the intended duration, not for one second longer. In the Issuance library, compute the validity period by including the full length of the final second indicated by the notAfter date when determining if the certificate request matches our profile. Update tests and config files to match. Fixes #5473
This commit is contained in:
parent
fd7427a243
commit
20f1bf1d0d
4
ca/ca.go
4
ca/ca.go
|
@ -386,10 +386,10 @@ func (ca *certificateAuthorityImpl) generateSerialNumberAndValidity() (*big.Int,
|
||||||
serialBigInt := big.NewInt(0)
|
serialBigInt := big.NewInt(0)
|
||||||
serialBigInt = serialBigInt.SetBytes(serialBytes)
|
serialBigInt = serialBigInt.SetBytes(serialBytes)
|
||||||
|
|
||||||
notBefore := ca.clk.Now().Add(-1 * ca.backdate)
|
notBefore := ca.clk.Now().Add(-ca.backdate)
|
||||||
validity := validity{
|
validity := validity{
|
||||||
NotBefore: notBefore,
|
NotBefore: notBefore,
|
||||||
NotAfter: notBefore.Add(ca.validityPeriod),
|
NotAfter: notBefore.Add(ca.validityPeriod - time.Second),
|
||||||
}
|
}
|
||||||
|
|
||||||
return serialBigInt, validity, nil
|
return serialBigInt, validity, nil
|
||||||
|
|
|
@ -434,7 +434,7 @@ func issueCertificateSubTestIssuePrecertificate(t *testing.T, i *TestCertificate
|
||||||
|
|
||||||
func issueCertificateSubTestValidityUsesCAClock(t *testing.T, i *TestCertificateIssuance) {
|
func issueCertificateSubTestValidityUsesCAClock(t *testing.T, i *TestCertificateIssuance) {
|
||||||
test.AssertEquals(t, i.cert.NotBefore, i.ca.clk.Now().Add(-1*i.ca.backdate))
|
test.AssertEquals(t, i.cert.NotBefore, i.ca.clk.Now().Add(-1*i.ca.backdate))
|
||||||
test.AssertEquals(t, i.cert.NotAfter, i.cert.NotBefore.Add(i.ca.validityPeriod))
|
test.AssertEquals(t, i.cert.NotAfter.Add(time.Second).Sub(i.cert.NotBefore), i.ca.validityPeriod)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test issuing when multiple issuers are present.
|
// Test issuing when multiple issuers are present.
|
||||||
|
|
|
@ -314,7 +314,9 @@ func (p *Profile) requestValid(clk clock.Clock, req *IssuanceRequest) error {
|
||||||
return errors.New("common name cannot be included")
|
return errors.New("common name cannot be included")
|
||||||
}
|
}
|
||||||
|
|
||||||
validity := req.NotAfter.Sub(req.NotBefore)
|
// The validity period is calculated inclusive of the whole second represented
|
||||||
|
// by the notAfter timestamp.
|
||||||
|
validity := req.NotAfter.Add(time.Second).Sub(req.NotBefore)
|
||||||
if validity <= 0 {
|
if validity <= 0 {
|
||||||
return errors.New("NotAfter must be after NotBefore")
|
return errors.New("NotAfter must be after NotBefore")
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,10 +267,23 @@ func TestRequestValid(t *testing.T) {
|
||||||
request: &IssuanceRequest{
|
request: &IssuanceRequest{
|
||||||
PublicKey: &ecdsa.PublicKey{},
|
PublicKey: &ecdsa.PublicKey{},
|
||||||
NotBefore: fc.Now(),
|
NotBefore: fc.Now(),
|
||||||
NotAfter: fc.Now().Add(time.Hour),
|
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||||
},
|
},
|
||||||
expectedError: "validity period is more than the maximum allowed period (1h0m0s>1m0s)",
|
expectedError: "validity period is more than the maximum allowed period (1h0m0s>1m0s)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "validity larger than max due to inclusivity",
|
||||||
|
profile: &Profile{
|
||||||
|
useForECDSALeaves: true,
|
||||||
|
maxValidity: time.Hour,
|
||||||
|
},
|
||||||
|
request: &IssuanceRequest{
|
||||||
|
PublicKey: &ecdsa.PublicKey{},
|
||||||
|
NotBefore: fc.Now(),
|
||||||
|
NotAfter: fc.Now().Add(time.Hour),
|
||||||
|
},
|
||||||
|
expectedError: "validity period is more than the maximum allowed period (1h0m1s>1h0m0s)",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "validity backdated more than max",
|
name: "validity backdated more than max",
|
||||||
profile: &Profile{
|
profile: &Profile{
|
||||||
|
@ -536,7 +549,7 @@ func TestIssue(t *testing.T) {
|
||||||
CommonName: "example.com",
|
CommonName: "example.com",
|
||||||
DNSNames: []string{"example.com"},
|
DNSNames: []string{"example.com"},
|
||||||
NotBefore: fc.Now(),
|
NotBefore: fc.Now(),
|
||||||
NotAfter: fc.Now().Add(time.Hour),
|
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||||
})
|
})
|
||||||
test.AssertNotError(t, err, "Issue failed")
|
test.AssertNotError(t, err, "Issue failed")
|
||||||
cert, err := x509.ParseCertificate(certBytes)
|
cert, err := x509.ParseCertificate(certBytes)
|
||||||
|
@ -569,7 +582,7 @@ func TestIssueRSA(t *testing.T) {
|
||||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8},
|
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8},
|
||||||
DNSNames: []string{"example.com"},
|
DNSNames: []string{"example.com"},
|
||||||
NotBefore: fc.Now(),
|
NotBefore: fc.Now(),
|
||||||
NotAfter: fc.Now().Add(time.Hour),
|
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||||
})
|
})
|
||||||
test.AssertNotError(t, err, "Issue failed")
|
test.AssertNotError(t, err, "Issue failed")
|
||||||
cert, err := x509.ParseCertificate(certBytes)
|
cert, err := x509.ParseCertificate(certBytes)
|
||||||
|
@ -599,7 +612,7 @@ func TestIssueCTPoison(t *testing.T) {
|
||||||
DNSNames: []string{"example.com"},
|
DNSNames: []string{"example.com"},
|
||||||
IncludeCTPoison: true,
|
IncludeCTPoison: true,
|
||||||
NotBefore: fc.Now(),
|
NotBefore: fc.Now(),
|
||||||
NotAfter: fc.Now().Add(time.Hour),
|
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||||
})
|
})
|
||||||
test.AssertNotError(t, err, "Issue failed")
|
test.AssertNotError(t, err, "Issue failed")
|
||||||
cert, err := x509.ParseCertificate(certBytes)
|
cert, err := x509.ParseCertificate(certBytes)
|
||||||
|
@ -631,7 +644,7 @@ func TestIssueSCTList(t *testing.T) {
|
||||||
{},
|
{},
|
||||||
},
|
},
|
||||||
NotBefore: fc.Now(),
|
NotBefore: fc.Now(),
|
||||||
NotAfter: fc.Now().Add(time.Hour),
|
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||||
})
|
})
|
||||||
test.AssertNotError(t, err, "Issue failed")
|
test.AssertNotError(t, err, "Issue failed")
|
||||||
cert, err := x509.ParseCertificate(certBytes)
|
cert, err := x509.ParseCertificate(certBytes)
|
||||||
|
@ -664,7 +677,7 @@ func TestIssueMustStaple(t *testing.T) {
|
||||||
DNSNames: []string{"example.com"},
|
DNSNames: []string{"example.com"},
|
||||||
IncludeMustStaple: true,
|
IncludeMustStaple: true,
|
||||||
NotBefore: fc.Now(),
|
NotBefore: fc.Now(),
|
||||||
NotAfter: fc.Now().Add(time.Hour),
|
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||||
})
|
})
|
||||||
test.AssertNotError(t, err, "Issue failed")
|
test.AssertNotError(t, err, "Issue failed")
|
||||||
cert, err := x509.ParseCertificate(certBytes)
|
cert, err := x509.ParseCertificate(certBytes)
|
||||||
|
@ -690,7 +703,7 @@ func TestIssueBadLint(t *testing.T) {
|
||||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8},
|
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8},
|
||||||
DNSNames: []string{"example.com"},
|
DNSNames: []string{"example.com"},
|
||||||
NotBefore: fc.Now(),
|
NotBefore: fc.Now(),
|
||||||
NotAfter: fc.Now().Add(time.Hour),
|
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||||
})
|
})
|
||||||
test.AssertError(t, err, "Issue didn't fail")
|
test.AssertError(t, err, "Issue didn't fail")
|
||||||
test.AssertEquals(t, err.Error(), "tbsCertificate linting failed: failed lints: w_ct_sct_policy_count_unsatisfied")
|
test.AssertEquals(t, err.Error(), "tbsCertificate linting failed: failed lints: w_ct_sct_policy_count_unsatisfied")
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"maxValidityPeriod": "7775999s",
|
"maxValidityPeriod": "7776000s",
|
||||||
"maxValidityBackdate": "1h5m"
|
"maxValidityBackdate": "1h5m"
|
||||||
},
|
},
|
||||||
"issuers": [
|
"issuers": [
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
],
|
],
|
||||||
"ignoredLints": ["n_subject_common_name_included"]
|
"ignoredLints": ["n_subject_common_name_included"]
|
||||||
},
|
},
|
||||||
"expiry": "7775999s",
|
"expiry": "7776000s",
|
||||||
"backdate": "1h",
|
"backdate": "1h",
|
||||||
"serialPrefix": 255,
|
"serialPrefix": 255,
|
||||||
"maxNames": 100,
|
"maxNames": 100,
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"maxValidityPeriod": "7775999s",
|
"maxValidityPeriod": "7776000s",
|
||||||
"maxValidityBackdate": "1h5m"
|
"maxValidityBackdate": "1h5m"
|
||||||
},
|
},
|
||||||
"issuers": [
|
"issuers": [
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
],
|
],
|
||||||
"ignoredLints": ["n_subject_common_name_included"]
|
"ignoredLints": ["n_subject_common_name_included"]
|
||||||
},
|
},
|
||||||
"expiry": "7775999s",
|
"expiry": "7776000s",
|
||||||
"backdate": "1h",
|
"backdate": "1h",
|
||||||
"serialPrefix": 255,
|
"serialPrefix": 255,
|
||||||
"maxNames": 100,
|
"maxNames": 100,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"maxOpenConns": 10
|
"maxOpenConns": 10
|
||||||
},
|
},
|
||||||
"hostnamePolicyFile": "test/hostname-policy.yaml",
|
"hostnamePolicyFile": "test/hostname-policy.yaml",
|
||||||
"acceptableValidityPeriods": [7775999, 7776000],
|
"acceptableValidityPeriods": [7776000],
|
||||||
"ignoredLints": [
|
"ignoredLints": [
|
||||||
"n_subject_common_name_included"
|
"n_subject_common_name_included"
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"maxOpenConns": 10
|
"maxOpenConns": 10
|
||||||
},
|
},
|
||||||
"hostnamePolicyFile": "test/hostname-policy.yaml",
|
"hostnamePolicyFile": "test/hostname-policy.yaml",
|
||||||
|
"acceptableValidityPeriods": [7775999, 7776000],
|
||||||
"ignoredLints": [
|
"ignoredLints": [
|
||||||
"n_subject_common_name_included"
|
"n_subject_common_name_included"
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue