Rebase #14178 / Add not_before_duration API parameter to Root/Intermediate CA generation (#15511)

* PKI - Add not_before_duration API parameter to:
  - Root CA generation
  - Intermediate CA generation
  - Intermediate CA signing

* Move not_before_duration to addCACommonFields

This gets applied on both root generation and intermediate signing,
which is the correct place to apply this.

Co-authored-by: guysv <sviryguy@gmail.com>
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add changelog entry

Resolves: #10631

Co-authored-by: guysv <sviryguy@gmail.com>
Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add test case for root/generate, sign-intermediate

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Update path role description

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add new not_before_duration to relevant docs

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

Co-authored-by: guysv <sviryguy@gmail.com>
This commit is contained in:
Alexander Scheel 2022-05-19 12:35:08 -04:00 committed by GitHub
parent f3d52108b4
commit faea196991
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 39 additions and 7 deletions

View File

@ -172,8 +172,9 @@ func TestPKI_DeviceCert(t *testing.T) {
} }
resp, err := client.Logical().Write("pki/root/generate/internal", map[string]interface{}{ resp, err := client.Logical().Write("pki/root/generate/internal", map[string]interface{}{
"common_name": "myvault.com", "common_name": "myvault.com",
"not_after": "9999-12-31T23:59:59Z", "not_after": "9999-12-31T23:59:59Z",
"not_before_duration": "2h",
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -194,7 +195,10 @@ func TestPKI_DeviceCert(t *testing.T) {
cert := parsedCertBundle.Certificate cert := parsedCertBundle.Certificate
notAfter := cert.NotAfter.Format(time.RFC3339) notAfter := cert.NotAfter.Format(time.RFC3339)
if notAfter != "9999-12-31T23:59:59Z" { 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) // 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, Operation: logical.UpdateOperation,
Path: "root/sign-intermediate", Path: "root/sign-intermediate",
Data: map[string]interface{}{ Data: map[string]interface{}{
"common_name": "intermediate.cert.com", "common_name": "intermediate.cert.com",
"csr": csrPem2048, "csr": csrPem2048,
"format": "der", "format": "der",
"not_before_duration": "2h",
}, },
Check: func(resp *logical.Response) error { Check: func(resp *logical.Response) error {
certString := resp.Data["certificate"].(string) 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) 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 return nil
}, },
}, },

View File

@ -63,6 +63,7 @@ func (b *backend) getGenerationParams(ctx context.Context, storage logical.Stora
Province: data.Get("province").([]string), Province: data.Get("province").([]string),
StreetAddress: data.Get("street_address").([]string), StreetAddress: data.Get("street_address").([]string),
PostalCode: data.Get("postal_code").([]string), PostalCode: data.Get("postal_code").([]string),
NotBeforeDuration: time.Duration(data.Get("not_before_duration").(int)) * time.Second,
} }
*role.AllowWildcardCertificates = true *role.AllowWildcardCertificates = true

View File

@ -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 map using OID 2.5.4.5. This has no impact on the final certificate's
Serial Number field.`, Serial Number field.`,
} }
fields["not_after"] = &framework.FieldSchema{ fields["not_after"] = &framework.FieldSchema{
Type: framework.TypeString, Type: framework.TypeString,
Description: `Set the not after field of the certificate with specified date value. 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`, 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 return fields
} }

View File

@ -397,7 +397,7 @@ for "generate_lease".`,
"not_before_duration": { "not_before_duration": {
Type: framework.TypeDurationSecond, Type: framework.TypeDurationSecond,
Default: 30, 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{ DisplayAttrs: &framework.DisplayAttributes{
Value: 30, Value: 30,
}, },

View File

@ -288,6 +288,7 @@ func (b *backend) pathIssuerSignIntermediate(ctx context.Context, req *logical.R
AllowedSerialNumbers: []string{"*"}, AllowedSerialNumbers: []string{"*"},
AllowedURISANs: []string{"*"}, AllowedURISANs: []string{"*"},
NotAfter: data.Get("not_after").(string), NotAfter: data.Get("not_after").(string),
NotBeforeDuration: time.Duration(data.Get("not_before_duration").(int)) * time.Second,
} }
*role.AllowWildcardCertificates = true *role.AllowWildcardCertificates = true

3
changelog/14178.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
secrets/pki: Add not_before_duration to root CA generation, intermediate CA signing paths.
```

View File

@ -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 `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. 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 - `not_after` `(string)` - Set the Not After field of the certificate with
specified date value. The value format should be given in UTC format 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 `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 `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. 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 - `not_after` `(string)` - Set the Not After field of the certificate with
specified date value. The value format should be given in UTC format 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 `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018