Skip to content

Commit

Permalink
not_before_duration added to SSH (#15250)
Browse files Browse the repository at this point in the history
* add-not-before-duration-to-ssh

* Missing field

* Adding tests

* changelog file

* Backend test

* Requested changes

* Update builtin/logical/ssh/path_roles.go

Co-authored-by: Alexander Scheel <alexander.m.scheel@gmail.com>
  • Loading branch information
Gabrielopesantos and cipherboy committed May 12, 2022
1 parent a970427 commit 7c72d9d
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 2 deletions.
94 changes: 94 additions & 0 deletions builtin/logical/ssh/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,100 @@ func TestBackend_DefExtTemplatingDisabled(t *testing.T) {
}
}

func TestSSHBackend_ValidateNotBeforeDuration(t *testing.T) {
config := logical.TestBackendConfig()

b, err := Factory(context.Background(), config)
if err != nil {
t.Fatalf("Cannot create backend: %s", err)
}
testCase := logicaltest.TestCase{
LogicalBackend: b,
Steps: []logicaltest.TestStep{
configCaStep(testCAPublicKey, testCAPrivateKey),

createRoleStep("testing", map[string]interface{}{
"key_type": "ca",
"allow_host_certificates": true,
"allowed_domains": "example.com,example.org",
"allow_subdomains": true,
"default_critical_options": map[string]interface{}{
"option": "value",
},
"default_extensions": map[string]interface{}{
"extension": "extended",
},
"not_before_duration": "300s",
}),

signCertificateStep("testing", "vault-root-22608f5ef173aabf700797cb95c5641e792698ec6380e8e1eb55523e39aa5e51", ssh.HostCert, []string{"dummy.example.org", "second.example.com"}, map[string]string{
"option": "value",
}, map[string]string{
"extension": "extended",
},
2*time.Hour+5*time.Minute-30*time.Second, map[string]interface{}{
"public_key": publicKey2,
"ttl": "2h",
"cert_type": "host",
"valid_principals": "dummy.example.org,second.example.com",
}),

createRoleStep("testing", map[string]interface{}{
"key_type": "ca",
"allow_host_certificates": true,
"allowed_domains": "example.com,example.org",
"allow_subdomains": true,
"default_critical_options": map[string]interface{}{
"option": "value",
},
"default_extensions": map[string]interface{}{
"extension": "extended",
},
"not_before_duration": "2h",
}),

signCertificateStep("testing", "vault-root-22608f5ef173aabf700797cb95c5641e792698ec6380e8e1eb55523e39aa5e51", ssh.HostCert, []string{"dummy.example.org", "second.example.com"}, map[string]string{
"option": "value",
}, map[string]string{
"extension": "extended",
},
4*time.Hour-30*time.Second, map[string]interface{}{
"public_key": publicKey2,
"ttl": "2h",
"cert_type": "host",
"valid_principals": "dummy.example.org,second.example.com",
}),
createRoleStep("testing", map[string]interface{}{
"key_type": "ca",
"allow_host_certificates": true,
"allowed_domains": "example.com,example.org",
"allow_subdomains": true,
"default_critical_options": map[string]interface{}{
"option": "value",
},
"default_extensions": map[string]interface{}{
"extension": "extended",
},
"not_before_duration": "30s",
}),

signCertificateStep("testing", "vault-root-22608f5ef173aabf700797cb95c5641e792698ec6380e8e1eb55523e39aa5e51", ssh.HostCert, []string{"dummy.example.org", "second.example.com"}, map[string]string{
"option": "value",
}, map[string]string{
"extension": "extended",
},
2*time.Hour, map[string]interface{}{
"public_key": publicKey2,
"ttl": "2h",
"cert_type": "host",
"valid_principals": "dummy.example.org,second.example.com",
}),
},
}

logicaltest.Test(t, testCase)
}

func getSshCaTestCluster(t *testing.T, userIdentity string) (*vault.TestCluster, string) {
coreConfig := &vault.CoreConfig{
CredentialBackends: map[string]logical.Factory{
Expand Down
1 change: 1 addition & 0 deletions builtin/logical/ssh/path_config_ca_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ func TestSSH_ConfigCAKeyTypes(t *testing.T) {
"allowed_users": "*",
"key_type": "ca",
"ttl": "30s",
"not_before_duration": "2h",
}
roleReq := &logical.Request{
Operation: logical.UpdateOperation,
Expand Down
21 changes: 20 additions & 1 deletion builtin/logical/ssh/path_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const (
// Present version of the sshRole struct; when adding a new field or are
// needing to perform a migration, increment this struct and read the note
// in checkUpgrade(...).
roleEntryVersion = 2
roleEntryVersion = 3
)

// Structure that represents a role in SSH backend. This is a common role structure
Expand Down Expand Up @@ -65,6 +65,7 @@ type sshRole struct {
AllowedUserKeyTypesLengths map[string][]int `mapstructure:"allowed_user_key_types_lengths" json:"allowed_user_key_types_lengths"`
AlgorithmSigner string `mapstructure:"algorithm_signer" json:"algorithm_signer"`
Version int `mapstructure:"role_version" json:"role_version"`
NotBeforeDuration time.Duration `mapstructure:"not_before_duration" json:"not_before_duration"`
}

func pathListRoles(b *backend) *framework.Path {
Expand Down Expand Up @@ -363,6 +364,16 @@ func pathRoles(b *backend) *framework.Path {
Name: "Signing Algorithm",
},
},
"not_before_duration": {
Type: framework.TypeDurationSecond,
Default: 30,
Description: `
The duration that the SSH certificate should be backdated by at issuance.`,
DisplayAttrs: &framework.DisplayAttributes{
Name: "Not before duration",
Value: 30,
},
},
},

Callbacks: map[logical.Operation]framework.OperationFunc{
Expand Down Expand Up @@ -555,6 +566,7 @@ func (b *backend) createCARole(allowedUsers, defaultUser, signer string, data *f
KeyType: KeyTypeCA,
AlgorithmSigner: signer,
Version: roleEntryVersion,
NotBeforeDuration: time.Duration(data.Get("not_before_duration").(int)) * time.Second,
}

if !role.AllowUserCertificates && !role.AllowHostCertificates {
Expand Down Expand Up @@ -672,6 +684,12 @@ func (b *backend) checkUpgrade(ctx context.Context, s logical.Storage, n string,
err = nil
}

if result.Version < 3 {
modified = true
result.NotBeforeDuration = 30 * time.Second
result.Version = 3
}

// Add new migrations just before here.
//
// Condition copied from PKI builtin.
Expand Down Expand Up @@ -739,6 +757,7 @@ func (b *backend) parseRole(role *sshRole) (map[string]interface{}, error) {
"default_extensions_template": role.DefaultExtensionsTemplate,
"allowed_user_key_lengths": role.AllowedUserKeyTypesLengths,
"algorithm_signer": role.AlgorithmSigner,
"not_before_duration": role.NotBeforeDuration,
}
case KeyTypeDynamic:
result = map[string]interface{}{
Expand Down
2 changes: 1 addition & 1 deletion builtin/logical/ssh/path_sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ func (b *creationBundle) sign() (retCert *ssh.Certificate, retErr error) {
Key: b.PublicKey,
KeyId: b.KeyID,
ValidPrincipals: b.ValidPrincipals,
ValidAfter: uint64(now.Add(-30 * time.Second).In(time.UTC).Unix()),
ValidAfter: uint64(now.Add(-b.Role.NotBeforeDuration).In(time.UTC).Unix()),
ValidBefore: uint64(now.Add(b.TTL).In(time.UTC).Unix()),
CertType: b.CertificateType,
Permissions: ssh.Permissions{
Expand Down
3 changes: 3 additions & 0 deletions changelog/15250.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
secrets/ssh: Support for `add_before_duration` in SSH
```
1 change: 1 addition & 0 deletions ui/app/models/role-ssh.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const CA_FIELDS = [
'allowSubdomains',
'allowUserKeyIds',
'keyIdFormat',
'notBeforeDuration'
];

export default Model.extend({
Expand Down
2 changes: 2 additions & 0 deletions website/content/api-docs/secret/ssh.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,8 @@ to the restrictions contained in the role named in the endpoint.
- `extensions` `(map<string|string>: "")` – Specifies a map of the extensions
that the certificate should be signed for. Defaults to none.

- `not_before_duration` `(duration: "30s")` – Specifies the duration by which to backdate the `ValidAfter` property.

### Sample Payload

```json
Expand Down

0 comments on commit 7c72d9d

Please sign in to comment.