diff --git a/builtin/logical/pki/backend_test.go b/builtin/logical/pki/backend_test.go index 6ddd8b4a7..b77f396fa 100644 --- a/builtin/logical/pki/backend_test.go +++ b/builtin/logical/pki/backend_test.go @@ -172,8 +172,9 @@ func TestPKI_DeviceCert(t *testing.T) { } resp, err := client.Logical().Write("pki/root/generate/internal", map[string]interface{}{ - "common_name": "myvault.com", - "not_after": "9999-12-31T23:59:59Z", + "common_name": "myvault.com", + "not_after": "9999-12-31T23:59:59Z", + "not_before_duration": "2h", }) if err != nil { t.Fatal(err) @@ -194,7 +195,10 @@ func TestPKI_DeviceCert(t *testing.T) { cert := parsedCertBundle.Certificate notAfter := cert.NotAfter.Format(time.RFC3339) if notAfter != "9999-12-31T23:59:59Z" { - t.Fatal(fmt.Errorf("not after from certificate is not matching with input parameter")) + t.Fatalf("not after from certificate: %v is not matching with input parameter: %v", cert.NotAfter, "9999-12-31T23:59:59Z") + } + if math.Abs(float64(time.Now().Add(-2*time.Hour).Unix()-cert.NotBefore.Unix())) > 10 { + t.Fatalf("root/generate/internal did not properly set validity period (notBefore): was %v vs expected %v", cert.NotBefore, time.Now().Add(-2*time.Hour)) } // Create a role which does require CN (default) @@ -583,9 +587,10 @@ func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[s Operation: logical.UpdateOperation, Path: "root/sign-intermediate", Data: map[string]interface{}{ - "common_name": "intermediate.cert.com", - "csr": csrPem2048, - "format": "der", + "common_name": "intermediate.cert.com", + "csr": csrPem2048, + "format": "der", + "not_before_duration": "2h", }, Check: func(resp *logical.Response) error { certString := resp.Data["certificate"].(string) @@ -616,6 +621,10 @@ func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[s return fmt.Errorf("expected\n%#v\ngot\n%#v\n", []string{"intermediate.cert.com"}, cert.DNSNames) } + if math.Abs(float64(time.Now().Add(-2*time.Hour).Unix()-cert.NotBefore.Unix())) > 10 { + t.Fatalf("root/sign-intermediate did not properly set validity period (notBefore): was %v vs expected %v", cert.NotBefore, time.Now().Add(-2*time.Hour)) + } + return nil }, }, diff --git a/builtin/logical/pki/ca_util.go b/builtin/logical/pki/ca_util.go index dd494fe80..9499908e3 100644 --- a/builtin/logical/pki/ca_util.go +++ b/builtin/logical/pki/ca_util.go @@ -63,6 +63,7 @@ func (b *backend) getGenerationParams(ctx context.Context, storage logical.Stora Province: data.Get("province").([]string), StreetAddress: data.Get("street_address").([]string), PostalCode: data.Get("postal_code").([]string), + NotBeforeDuration: time.Duration(data.Get("not_before_duration").(int)) * time.Second, } *role.AllowWildcardCertificates = true diff --git a/builtin/logical/pki/fields.go b/builtin/logical/pki/fields.go index ec7dab86d..22100f388 100644 --- a/builtin/logical/pki/fields.go +++ b/builtin/logical/pki/fields.go @@ -250,12 +250,22 @@ If you want more than one, specify alternative names in the alt_names map using OID 2.5.4.5. This has no impact on the final certificate's Serial Number field.`, } + fields["not_after"] = &framework.FieldSchema{ Type: framework.TypeString, Description: `Set the not after field of the certificate with specified date value. The value format should be given in UTC format YYYY-MM-ddTHH:MM:SSZ`, } + fields["not_before_duration"] = &framework.FieldSchema{ + Type: framework.TypeDurationSecond, + Default: 30, + Description: `The duration before now which the certificate needs to be backdated by.`, + DisplayAttrs: &framework.DisplayAttributes{ + Value: 30, + }, + } + return fields } diff --git a/builtin/logical/pki/path_roles.go b/builtin/logical/pki/path_roles.go index ad351a194..4100f4347 100644 --- a/builtin/logical/pki/path_roles.go +++ b/builtin/logical/pki/path_roles.go @@ -397,7 +397,7 @@ for "generate_lease".`, "not_before_duration": { Type: framework.TypeDurationSecond, Default: 30, - Description: `The duration before now the cert needs to be created / signed.`, + Description: `The duration before now which the certificate needs to be backdated by.`, DisplayAttrs: &framework.DisplayAttributes{ Value: 30, }, diff --git a/builtin/logical/pki/path_root.go b/builtin/logical/pki/path_root.go index 97aa65800..6a8517033 100644 --- a/builtin/logical/pki/path_root.go +++ b/builtin/logical/pki/path_root.go @@ -288,6 +288,7 @@ func (b *backend) pathIssuerSignIntermediate(ctx context.Context, req *logical.R AllowedSerialNumbers: []string{"*"}, AllowedURISANs: []string{"*"}, NotAfter: data.Get("not_after").(string), + NotBeforeDuration: time.Duration(data.Get("not_before_duration").(int)) * time.Second, } *role.AllowWildcardCertificates = true diff --git a/changelog/14178.txt b/changelog/14178.txt new file mode 100644 index 000000000..ef6c355c4 --- /dev/null +++ b/changelog/14178.txt @@ -0,0 +1,3 @@ +```release-note:improvement +secrets/pki: Add not_before_duration to root CA generation, intermediate CA signing paths. +``` diff --git a/website/content/api-docs/secret/pki.mdx b/website/content/api-docs/secret/pki.mdx index 66137ca02..a0211f08d 100644 --- a/website/content/api-docs/secret/pki.mdx +++ b/website/content/api-docs/secret/pki.mdx @@ -548,6 +548,10 @@ when signing an externally-owned intermediate. `alt_names` map using OID 2.5.4.5. Note that this has no impact on the Certificate's serial number field, which Vault randomly generates. +- `not_before_duration` `(duration: "30s")` - Specifies the duration by which to + backdate the NotBefore property. This value has no impact in the validity period + of the requested certificate, specified in the `ttl` field. + - `not_after` `(string)` - Set the Not After field of the certificate with specified date value. The value format should be given in UTC format `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018 @@ -1288,6 +1292,10 @@ use the values set via `config/urls`. `alt_names` map using OID 2.5.4.5. Note that this has no impact on the Certificate's serial number field, which Vault randomly generates. +- `not_before_duration` `(duration: "30s")` - Specifies the duration by which to + backdate the NotBefore property. This value has no impact in the validity period + of the requested certificate, specified in the `ttl` field. + - `not_after` `(string)` - Set the Not After field of the certificate with specified date value. The value format should be given in UTC format `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018