diff --git a/api/credentiallibraries/option.gen.go b/api/credentiallibraries/option.gen.go index 4f14dcf4b..37deb83dd 100644 --- a/api/credentiallibraries/option.gen.go +++ b/api/credentiallibraries/option.gen.go @@ -78,6 +78,30 @@ func WithFilter(filter string) Option { } } +func WithVaultSSHCertificateCredentialLibraryAdditionalValidPrincipals(inAdditionalValidPrincipals []string) Option { + return func(o *options) { + raw, ok := o.postMap["attributes"] + if !ok { + raw = interface{}(map[string]interface{}{}) + } + val := raw.(map[string]interface{}) + val["additional_valid_principals"] = inAdditionalValidPrincipals + o.postMap["attributes"] = val + } +} + +func DefaultVaultSSHCertificateCredentialLibraryAdditionalValidPrincipals() Option { + return func(o *options) { + raw, ok := o.postMap["attributes"] + if !ok { + raw = interface{}(map[string]interface{}{}) + } + val := raw.(map[string]interface{}) + val["additional_valid_principals"] = nil + o.postMap["attributes"] = val + } +} + func WithAttributes(inAttributes map[string]interface{}) Option { return func(o *options) { o.postMap["attributes"] = inAttributes diff --git a/api/credentiallibraries/vault_ssh_certificate_credential_library_attributes.gen.go b/api/credentiallibraries/vault_ssh_certificate_credential_library_attributes.gen.go index 6316ec158..8f524c9ad 100644 --- a/api/credentiallibraries/vault_ssh_certificate_credential_library_attributes.gen.go +++ b/api/credentiallibraries/vault_ssh_certificate_credential_library_attributes.gen.go @@ -11,14 +11,15 @@ import ( ) type VaultSSHCertificateCredentialLibraryAttributes struct { - Path string `json:"path,omitempty"` - Username string `json:"username,omitempty"` - KeyType string `json:"key_type,omitempty"` - KeyBits uint32 `json:"key_bits,omitempty"` - Ttl string `json:"ttl,omitempty"` - KeyId string `json:"key_id,omitempty"` - CriticalOptions map[string]string `json:"critical_options,omitempty"` - Extensions map[string]string `json:"extensions,omitempty"` + Path string `json:"path,omitempty"` + Username string `json:"username,omitempty"` + KeyType string `json:"key_type,omitempty"` + KeyBits uint32 `json:"key_bits,omitempty"` + Ttl string `json:"ttl,omitempty"` + KeyId string `json:"key_id,omitempty"` + CriticalOptions map[string]string `json:"critical_options,omitempty"` + Extensions map[string]string `json:"extensions,omitempty"` + AdditionalValidPrincipals []string `json:"additional_valid_principals,omitempty"` } func AttributesMapToVaultSSHCertificateCredentialLibraryAttributes(in map[string]interface{}) (*VaultSSHCertificateCredentialLibraryAttributes, error) { diff --git a/api/sessionrecordings/vault_ssh_certificate_credential_library_attributes.gen.go b/api/sessionrecordings/vault_ssh_certificate_credential_library_attributes.gen.go index 4b6034889..07985386e 100644 --- a/api/sessionrecordings/vault_ssh_certificate_credential_library_attributes.gen.go +++ b/api/sessionrecordings/vault_ssh_certificate_credential_library_attributes.gen.go @@ -11,13 +11,14 @@ import ( ) type VaultSSHCertificateCredentialLibraryAttributes struct { - Path string `json:"path,omitempty"` - Username string `json:"username,omitempty"` - KeyType string `json:"key_type,omitempty"` - KeyBits uint32 `json:"key_bits,omitempty"` - Ttl string `json:"ttl,omitempty"` - CriticalOptions map[string]string `json:"critical_options,omitempty"` - Extensions map[string]string `json:"extensions,omitempty"` + Path string `json:"path,omitempty"` + Username string `json:"username,omitempty"` + KeyType string `json:"key_type,omitempty"` + KeyBits uint32 `json:"key_bits,omitempty"` + Ttl string `json:"ttl,omitempty"` + CriticalOptions map[string]string `json:"critical_options,omitempty"` + Extensions map[string]string `json:"extensions,omitempty"` + AdditionalValidPrincipals []string `json:"additional_valid_principals,omitempty"` } func AttributesMapToVaultSSHCertificateCredentialLibraryAttributes(in map[string]interface{}) (*VaultSSHCertificateCredentialLibraryAttributes, error) { diff --git a/internal/cmd/commands/credentiallibrariescmd/vault-ssh-certificate_funcs.go b/internal/cmd/commands/credentiallibrariescmd/vault-ssh-certificate_funcs.go index 9a109b88a..ce2fc5825 100644 --- a/internal/cmd/commands/credentiallibrariescmd/vault-ssh-certificate_funcs.go +++ b/internal/cmd/commands/credentiallibrariescmd/vault-ssh-certificate_funcs.go @@ -19,28 +19,30 @@ func init() { } const ( - usernameName = "username" - keyTypeName = "key-type" - keyBitsName = "key-bits" - ttlName = "ttl" - keyIdName = "key-id" - criticalOptionsName = "critical-options" - piecewiseCriticalOptionsName = "critical-option" - extensionsName = "extensions" - piecewiseExtensionName = "extension" + usernameName = "username" + keyTypeName = "key-type" + keyBitsName = "key-bits" + ttlName = "ttl" + keyIdName = "key-id" + criticalOptionsName = "critical-options" + piecewiseCriticalOptionsName = "critical-option" + extensionsName = "extensions" + piecewiseExtensionName = "extension" + additionalValidPrincipalsName = "additional-valid-principal" ) type extraVaultSshCertificateCmdVars struct { - flagPath string - flagUsername string - flagKeyType string - flagKeyBits string - flagTtl string - flagKeyId string - flagCriticalOptions string - flagCriticalOpts []base.CombinedSliceFlagValue - flagExtensions string - flagExtens []base.CombinedSliceFlagValue + flagPath string + flagUsername string + flagKeyType string + flagKeyBits string + flagTtl string + flagKeyId string + flagCriticalOptions string + flagCriticalOpts []base.CombinedSliceFlagValue + flagExtensions string + flagExtens []base.CombinedSliceFlagValue + flagAdditionalValidPrincipals []base.CombinedSliceFlagValue } func extraVaultSshCertificateActionsFlagsMapFuncImpl() map[string][]string { @@ -56,6 +58,7 @@ func extraVaultSshCertificateActionsFlagsMapFuncImpl() map[string][]string { piecewiseCriticalOptionsName, extensionsName, piecewiseExtensionName, + additionalValidPrincipalsName, }, "update": { pathFlagName, @@ -68,6 +71,7 @@ func extraVaultSshCertificateActionsFlagsMapFuncImpl() map[string][]string { piecewiseCriticalOptionsName, extensionsName, piecewiseExtensionName, + additionalValidPrincipalsName, }, } return flags @@ -114,6 +118,12 @@ func extraVaultSshCertificateFlagsFuncImpl(c *VaultSshCertificateCommand, set *b Target: &c.flagKeyId, Usage: "The key id that the created certificate should have.", }) + case additionalValidPrincipalsName: + f.CombinationSliceVar(&base.CombinationSliceVar{ + Name: additionalValidPrincipalsName, + Target: &c.flagAdditionalValidPrincipals, + Usage: "Principals to be signed as \"valid_principles\" in addition to username.", + }) } } criticalOptsInput := common.CombinedSliceFlagValuePopulationInput{ @@ -185,6 +195,22 @@ func extraVaultSshCertificateFlagHandlingFuncImpl(c *VaultSshCertificateCommand, default: *opts = append(*opts, credentiallibraries.WithVaultSSHCertificateCredentialLibraryKeyId(c.flagKeyId)) } + // the weird formatting of this switch is to determine if there was only 0 or 1 principals passed, and if that signifies using default (nil) + switch len(c.flagAdditionalValidPrincipals) { + case 0: + case 1: + if len(c.flagAdditionalValidPrincipals[0].Keys) == 1 && c.flagAdditionalValidPrincipals[0].Keys[0] == "null" && c.flagAdditionalValidPrincipals[0].Value == nil { + *opts = append(*opts, credentiallibraries.DefaultVaultSSHCertificateCredentialLibraryAdditionalValidPrincipals()) + break + } + fallthrough + default: + avp := make([]string, len(c.flagAdditionalValidPrincipals)) + for i, p := range c.flagAdditionalValidPrincipals { + avp[i] = p.Value.GetValue() + } + *opts = append(*opts, credentiallibraries.WithVaultSSHCertificateCredentialLibraryAdditionalValidPrincipals(avp)) + } if err := common.HandleAttributeFlags( c.Command, diff --git a/internal/credential/vault/fields.go b/internal/credential/vault/fields.go index c8f207f04..35805e884 100644 --- a/internal/credential/vault/fields.go +++ b/internal/credential/vault/fields.go @@ -23,6 +23,9 @@ const ( // ExtensionsField represents the field mask indicating an extension // update has been requested. ExtensionsField = "Extensions" + // AdditionalValidPrincipalsField represents the field mask indicating a valid + // principal update has been requested. + AdditionalValidPrincipalsField = "AdditionalValidPrincipals" certificateField = "Certificate" certificateKeyField = "CertificateKey" diff --git a/internal/credential/vault/options.go b/internal/credential/vault/options.go index 0c6752d0e..7f26578f6 100644 --- a/internal/credential/vault/options.go +++ b/internal/credential/vault/options.go @@ -38,12 +38,13 @@ type options struct { withOverridePrivateKeyPassphraseAttribute string withMappingOverride MappingOverride - withKeyType string - withKeyBits uint32 - withTtl string - withKeyId string - withCriticalOptions string - withExtensions string + withKeyType string + withKeyBits uint32 + withTtl string + withKeyId string + withCriticalOptions string + withExtensions string + withAdditionalValidPrincipals []string } func getDefaultOptions() options { @@ -229,3 +230,11 @@ func WithExtensions(s string) Option { o.withExtensions = s } } + +// WithAdditionalValidPrincipals adds principals to be signed for as +// "valid_principles" in addition to username. +func WithAdditionalValidPrincipals(p []string) Option { + return func(o *options) { + o.withAdditionalValidPrincipals = p + } +} diff --git a/internal/credential/vault/private_library.go b/internal/credential/vault/private_library.go index aeb7405c5..e4f492d74 100644 --- a/internal/credential/vault/private_library.go +++ b/internal/credential/vault/private_library.go @@ -210,6 +210,7 @@ type genericIssuingCredentialLibrary struct { PrivateKeyAttribute string PrivateKeyPassphraseAttribute string Purpose credential.Purpose + AdditionalValidPrincipals string } func (pl *genericIssuingCredentialLibrary) clone() *genericIssuingCredentialLibrary { @@ -490,6 +491,7 @@ type privateCredentialLibraryAllTypes struct { CriticalOptions []byte Extensions []byte CredLibType string + AdditionalValidPrincipals string } func (pl *privateCredentialLibraryAllTypes) GetPublicId() string { return pl.PublicId } @@ -570,6 +572,7 @@ func (pl *privateCredentialLibraryAllTypes) clone() *privateCredentialLibraryAll CriticalOptions: pl.CriticalOptions, Extensions: pl.Extensions, CredLibType: pl.CredLibType, + AdditionalValidPrincipals: pl.AdditionalValidPrincipals, } } @@ -577,38 +580,39 @@ func (pl *privateCredentialLibraryAllTypes) toTypedIssuingCredentialLibrary() is switch pl.CredLibType { case "ssh-signed-cert": return &sshCertIssuingCredentialLibrary{ - PublicId: pl.PublicId, - StoreId: pl.StoreId, - CredType: pl.CredType, - Username: pl.Username, - Name: pl.Name, - Description: pl.Description, - CreateTime: pl.CreateTime, - UpdateTime: pl.UpdateTime, - Version: pl.Version, - ProjectId: pl.ProjectId, - VaultPath: pl.VaultPath, - VaultAddress: pl.VaultAddress, - Namespace: pl.Namespace, - CaCert: pl.CaCert, - TlsServerName: pl.TlsServerName, - TlsSkipVerify: pl.TlsSkipVerify, - WorkerFilter: pl.WorkerFilter, - TokenHmac: pl.TokenHmac, - Token: pl.Token, - CtToken: pl.CtToken, - TokenKeyId: pl.TokenKeyId, - ClientCert: pl.ClientCert, - ClientKey: pl.ClientKey, - CtClientKey: pl.CtClientKey, - ClientKeyId: pl.ClientKeyId, - Purpose: pl.Purpose, - KeyType: pl.KeyType, - KeyBits: pl.KeyBits, - Ttl: pl.Ttl, - KeyId: pl.KeyId, - CriticalOptions: pl.CriticalOptions, - Extensions: pl.Extensions, + PublicId: pl.PublicId, + StoreId: pl.StoreId, + CredType: pl.CredType, + Username: pl.Username, + Name: pl.Name, + Description: pl.Description, + CreateTime: pl.CreateTime, + UpdateTime: pl.UpdateTime, + Version: pl.Version, + ProjectId: pl.ProjectId, + VaultPath: pl.VaultPath, + VaultAddress: pl.VaultAddress, + Namespace: pl.Namespace, + CaCert: pl.CaCert, + TlsServerName: pl.TlsServerName, + TlsSkipVerify: pl.TlsSkipVerify, + WorkerFilter: pl.WorkerFilter, + TokenHmac: pl.TokenHmac, + Token: pl.Token, + CtToken: pl.CtToken, + TokenKeyId: pl.TokenKeyId, + ClientCert: pl.ClientCert, + ClientKey: pl.ClientKey, + CtClientKey: pl.CtClientKey, + ClientKeyId: pl.ClientKeyId, + Purpose: pl.Purpose, + KeyType: pl.KeyType, + KeyBits: pl.KeyBits, + Ttl: pl.Ttl, + KeyId: pl.KeyId, + CriticalOptions: pl.CriticalOptions, + Extensions: pl.Extensions, + AdditionalValidPrincipals: pl.AdditionalValidPrincipals, } default: return &genericIssuingCredentialLibrary{ @@ -643,6 +647,7 @@ func (pl *privateCredentialLibraryAllTypes) toTypedIssuingCredentialLibrary() is CtClientKey: pl.CtClientKey, ClientKeyId: pl.ClientKeyId, Purpose: pl.Purpose, + AdditionalValidPrincipals: pl.AdditionalValidPrincipals, } } } @@ -691,38 +696,39 @@ func (m *requestMap) get(libraryId string) []credential.Purpose { } type sshCertIssuingCredentialLibrary struct { - PublicId string - StoreId string - Name string - Description string - CreateTime *timestamp.Timestamp - UpdateTime *timestamp.Timestamp - Version uint32 - VaultPath string - CredType string - ProjectId string - VaultAddress string - Namespace string - CaCert []byte - TlsServerName string - TlsSkipVerify bool - WorkerFilter string - Token TokenSecret - CtToken []byte - TokenHmac []byte - TokenKeyId string - ClientCert []byte - ClientKey KeySecret - CtClientKey []byte - ClientKeyId string - Username string - KeyType string - KeyBits int - KeyId string - Ttl string - CriticalOptions []byte - Extensions []byte - Purpose credential.Purpose + PublicId string + StoreId string + Name string + Description string + CreateTime *timestamp.Timestamp + UpdateTime *timestamp.Timestamp + Version uint32 + VaultPath string + CredType string + ProjectId string + VaultAddress string + Namespace string + CaCert []byte + TlsServerName string + TlsSkipVerify bool + WorkerFilter string + Token TokenSecret + CtToken []byte + TokenHmac []byte + TokenKeyId string + ClientCert []byte + ClientKey KeySecret + CtClientKey []byte + ClientKeyId string + Username string + KeyType string + KeyBits int + KeyId string + Ttl string + CriticalOptions []byte + Extensions []byte + Purpose credential.Purpose + AdditionalValidPrincipals string } func (lib *sshCertIssuingCredentialLibrary) GetPublicId() string { return lib.PublicId } @@ -906,8 +912,13 @@ func (lib *sshCertIssuingCredentialLibrary) retrieveCredential(ctx context.Conte } } + validPrincipals := username + if lib.AdditionalValidPrincipals != "" { + validPrincipals = fmt.Sprintf("%s,%s", username, lib.AdditionalValidPrincipals) + } + payload := sshCertVaultBody{ - ValidPrincipals: username, + ValidPrincipals: validPrincipals, CertType: "user", CriticalOptions: criticalOptions, Extensions: extensions, diff --git a/internal/credential/vault/private_library_test.go b/internal/credential/vault/private_library_test.go index 3ffcc59f4..6c79c837d 100644 --- a/internal/credential/vault/private_library_test.go +++ b/internal/credential/vault/private_library_test.go @@ -20,6 +20,7 @@ import ( "github.com/hashicorp/boundary/internal/util/template" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/crypto/ssh" ) func TestRepository_getPrivateLibraries(t *testing.T) { @@ -1270,7 +1271,7 @@ func TestRepository_sshCertIssuingCredentialLibrary_retrieveCredential(t *testin vaulthPath string opts []Option retOpts []credential.Option - expected map[string]string + expected map[string]any }{ { name: "vault sign boundary ed25519 key", @@ -1323,8 +1324,9 @@ func TestRepository_sshCertIssuingCredentialLibrary_retrieveCredential(t *testin { name: "vault issue ec(256) cert with template username", username: "username-8-{{ .User.Name }}", - expected: map[string]string{ - "username": "username-8-revenge-of-the-template", + expected: map[string]any{ + "username": "username-8-revenge-of-the-template", + "valid_principals": []string{"username-8-revenge-of-the-template"}, }, vaulthPath: "ssh/issue/boundary", opts: []Option{WithKeyType(KeyTypeEcdsa), WithKeyBits(256)}, @@ -1333,12 +1335,21 @@ func TestRepository_sshCertIssuingCredentialLibrary_retrieveCredential(t *testin { name: "vault issue ec(384) cert with disallowed extension", username: "username-10-because-789", - expected: map[string]string{ + expected: map[string]any{ "error": "extensions [permit-port-forwarding] are not on allowed list", }, vaulthPath: "ssh/issue/boundary", opts: []Option{WithKeyType(KeyTypeEcdsa), WithKeyBits(384), WithExtensions("{ \"permit-port-forwarding\": \"\" }")}, }, + { + name: "vault issue ed25519 cert with additional valid principals", + username: "no-one-expects-the-spanish-inquisition", + expected: map[string]any{ + "valid_principals": []string{"no-one-expects-the-spanish-inquisition", "test-principal"}, + }, + vaulthPath: "ssh/issue/boundary", + opts: []Option{WithKeyType(KeyTypeEd25519), WithAdditionalValidPrincipals([]string{"test-principal"})}, + }, } for _, tt := range tests { @@ -1371,21 +1382,34 @@ func TestRepository_sshCertIssuingCredentialLibrary_retrieveCredential(t *testin cred, err := libs[0].retrieveCredential(ctx, "op", tt.retOpts...) if retErr, ok := tt.expected["error"]; ok { - require.ErrorContains(err, retErr) + require.ErrorContains(err, retErr.(string)) return // retrieveCredential failed (as expected) don't do the rest of the checks } require.NoError(err) - cert, ok := cred.(*sshCertCred) + sshCert, ok := cred.(*sshCertCred) require.True(ok) if usr, ok := tt.expected["username"]; ok { - require.Equal(usr, cert.username) + require.Equal(usr, sshCert.username) } // TODO: somehow check that the ssh cert matches the private key // for now, manually check that private key and cert match and that sign/issue both return correct formats - fmt.Printf("test: %s\npriv:\n%s\ncert:\n%s\n", tt.name, string(cert.privateKey), string(cert.certificate)) + fmt.Printf("test: %s\npriv:\n%s\ncert:\n%s\n", tt.name, string(sshCert.privateKey), string(sshCert.certificate)) + pub, _, _, _, err := ssh.ParseAuthorizedKey(sshCert.certificate) + require.NoError(err) + priv, err := ssh.ParsePrivateKey(sshCert.privateKey) + require.NoError(err) + cert, ok := pub.(*ssh.Certificate) + require.True(ok) + + // ensure both keys are the same type + require.Equal(priv.PublicKey().Type(), cert.Key.Type()) + + if vp, ok := tt.expected["valid_principals"]; ok { + require.Equal(vp, cert.ValidPrincipals) + } // ensure credential matches expected SshCertificate _, ok = cred.(credential.SshCertificate) diff --git a/internal/credential/vault/repository_ssh_certificate_credential_library.go b/internal/credential/vault/repository_ssh_certificate_credential_library.go index c5b8f20c3..08d41506b 100644 --- a/internal/credential/vault/repository_ssh_certificate_credential_library.go +++ b/internal/credential/vault/repository_ssh_certificate_credential_library.go @@ -157,7 +157,7 @@ func (r *Repository) UpdateSSHCertificateCredentialLibrary(ctx context.Context, case strings.EqualFold(keyIdField, f): case strings.EqualFold(CriticalOptionsField, f): case strings.EqualFold(ExtensionsField, f): - + case strings.EqualFold(AdditionalValidPrincipalsField, f): default: return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidFieldMask, op, f) } @@ -186,16 +186,17 @@ func (r *Repository) UpdateSSHCertificateCredentialLibrary(ctx context.Context, var dbMask, nullFields []string dbMask, nullFields = dbw.BuildUpdatePaths( map[string]any{ - nameField: l.Name, - descriptionField: l.Description, - vaultPathField: l.VaultPath, - usernameField: l.Username, - keyTypeField: l.KeyType, - keyBitsField: l.KeyBits, - ttlField: l.Ttl, - keyIdField: l.KeyId, - CriticalOptionsField: l.CriticalOptions, - ExtensionsField: l.Extensions, + nameField: l.Name, + descriptionField: l.Description, + vaultPathField: l.VaultPath, + usernameField: l.Username, + keyTypeField: l.KeyType, + keyBitsField: l.KeyBits, + ttlField: l.Ttl, + keyIdField: l.KeyId, + CriticalOptionsField: l.CriticalOptions, + ExtensionsField: l.Extensions, + AdditionalValidPrincipalsField: l.AdditionalValidPrincipals, }, fieldMaskPaths, []string{keyBitsField}, diff --git a/internal/credential/vault/ssh_certificate_credential_library.go b/internal/credential/vault/ssh_certificate_credential_library.go index 96bbc8290..a40cd5e3e 100644 --- a/internal/credential/vault/ssh_certificate_credential_library.go +++ b/internal/credential/vault/ssh_certificate_credential_library.go @@ -4,6 +4,8 @@ package vault import ( + "strings" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/credential" "github.com/hashicorp/boundary/internal/credential/vault/store" @@ -45,18 +47,19 @@ func NewSSHCertificateCredentialLibrary(storeId string, vaultPath string, userna l := &SSHCertificateCredentialLibrary{ SSHCertificateCredentialLibrary: &store.SSHCertificateCredentialLibrary{ - StoreId: storeId, - Name: opts.withName, - Description: opts.withDescription, - VaultPath: vaultPath, - Username: username, - KeyType: opts.withKeyType, - KeyBits: opts.withKeyBits, - Ttl: opts.withTtl, - KeyId: opts.withKeyId, - CriticalOptions: opts.withCriticalOptions, - Extensions: opts.withExtensions, - CredentialType: string(globals.SshCertificateCredentialType), + StoreId: storeId, + Name: opts.withName, + Description: opts.withDescription, + VaultPath: vaultPath, + Username: username, + KeyType: opts.withKeyType, + KeyBits: opts.withKeyBits, + Ttl: opts.withTtl, + KeyId: opts.withKeyId, + CriticalOptions: opts.withCriticalOptions, + Extensions: opts.withExtensions, + CredentialType: string(globals.SshCertificateCredentialType), + AdditionalValidPrincipals: strings.Join(opts.withAdditionalValidPrincipals, ","), }, } diff --git a/internal/credential/vault/store/vault.pb.go b/internal/credential/vault/store/vault.pb.go index 8a64e297a..e60ea214e 100644 --- a/internal/credential/vault/store/vault.pb.go +++ b/internal/credential/vault/store/vault.pb.go @@ -690,6 +690,10 @@ type SSHCertificateCredentialLibrary struct { // credential_type is always ssh_certificate // @inject_tag: `gorm:"default:null"` CredentialType string `protobuf:"bytes,16,opt,name=credential_type,json=credentialType,proto3" json:"credential_type,omitempty" gorm:"default:null"` + // additional_valid_principals are strings that will be sent to vault in the "valid_principles" + // api field in addition to the username. + // @inject_tag: `gorm:"default:null"` + AdditionalValidPrincipals string `protobuf:"bytes,17,opt,name=additional_valid_principals,json=additionalValidPrincipals,proto3" json:"additional_valid_principals,omitempty" gorm:"default:null"` } func (x *SSHCertificateCredentialLibrary) Reset() { @@ -836,6 +840,13 @@ func (x *SSHCertificateCredentialLibrary) GetCredentialType() string { return "" } +func (x *SSHCertificateCredentialLibrary) GetAdditionalValidPrincipals() string { + if x != nil { + return x.AdditionalValidPrincipals + } + return "" +} + type Credential struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1353,7 +1364,7 @@ var file_controller_storage_credential_vault_store_v1_vault_proto_rawDesc = []by 0x0f, 0x68, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x22, 0xaa, 0x07, 0x0a, 0x1f, 0x53, 0x53, + 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x22, 0xb4, 0x08, 0x0a, 0x1f, 0x53, 0x53, 0x48, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, @@ -1412,72 +1423,81 @@ var file_controller_storage_credential_vault_store_v1_vault_proto_rawDesc = []by 0x73, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x22, 0xc3, 0x04, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, - 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x12, - 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, - 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, - 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x49, 0x64, 0x12, 0x56, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x6e, - 0x65, 0x77, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x87, 0x01, 0x0a, 0x1b, 0x61, 0x64, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6e, + 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x42, 0x47, 0xc2, 0xdd, + 0x29, 0x43, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x26, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x63, + 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x19, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, + 0x22, 0xc3, 0x04, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, + 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, + 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, + 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x56, + 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x6e, 0x65, 0x77, + 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x53, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x6c, 0x61, 0x73, - 0x74, 0x52, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x53, 0x0a, 0x0f, - 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, - 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, - 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x62, 0x6c, - 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x52, 0x65, 0x6e, 0x65, 0x77, - 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0c, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x97, 0x01, 0x0a, - 0x18, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, - 0x64, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x62, - 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, - 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, - 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x70, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x11, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x22, 0xe2, 0x01, 0x0a, 0x15, 0x53, 0x73, 0x68, 0x50, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x64, 0x12, - 0x2d, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x65, - 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x32, - 0x0a, 0x15, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, - 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x12, 0x47, 0x0a, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1d, 0x70, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, - 0x73, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x42, 0x45, 0x5a, 0x43, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x78, 0x70, + 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, + 0x73, 0x5f, 0x72, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0b, 0x69, 0x73, 0x52, 0x65, 0x6e, 0x65, 0x77, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x97, 0x01, 0x0a, 0x18, 0x55, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, + 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, + 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x70, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x22, 0xe2, 0x01, 0x0a, 0x15, 0x53, 0x73, 0x68, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, + 0x65, 0x79, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, + 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x75, 0x73, 0x65, + 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x47, 0x0a, 0x20, + 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, 0x73, 0x73, + 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1d, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, + 0x65, 0x79, 0x50, 0x61, 0x73, 0x73, 0x70, 0x68, 0x72, 0x61, 0x73, 0x65, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x42, 0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, + 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, + 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go index 85d493059..e12447baa 100644 --- a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go +++ b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go @@ -740,6 +740,13 @@ func toProto(ctx context.Context, in credential.Library, opt ...handlers.Option) json.Unmarshal([]byte(vaultIn.GetExtensions()), &e) attrs.Extensions = e } + if vaultIn.GetAdditionalValidPrincipals() != "" { + avp := strings.Split(vaultIn.GetAdditionalValidPrincipals(), ",") + attrs.AdditionalValidPrincipals = make([]*wrapperspb.StringValue, len(avp)) + for i, p := range avp { + attrs.AdditionalValidPrincipals[i] = &wrapperspb.StringValue{Value: p} + } + } out.Attrs = &pb.CredentialLibrary_VaultSshCertificateCredentialLibraryAttributes{ VaultSshCertificateCredentialLibraryAttributes: attrs, } @@ -850,6 +857,13 @@ func toStorageVaultSSHCertificateLibrary(ctx context.Context, storeId string, in } opts = append(opts, vault.WithExtensions(string(e))) } + if attrs.GetAdditionalValidPrincipals() != nil { + avp := make([]string, len(attrs.GetAdditionalValidPrincipals())) + for i, p := range attrs.GetAdditionalValidPrincipals() { + avp[i] = p.GetValue() + } + opts = append(opts, vault.WithAdditionalValidPrincipals(avp)) + } cs, err := vault.NewSSHCertificateCredentialLibrary(storeId, attrs.GetPath().GetValue(), attrs.GetUsername().GetValue(), opts...) if err != nil { diff --git a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service_test.go b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service_test.go index dff5255be..f00212920 100644 --- a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service_test.go +++ b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service_test.go @@ -2062,7 +2062,7 @@ func TestCreate_SSHCertificateCredentialLibrary(t *testing.T) { req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{ CredentialStoreId: store.GetPublicId(), Type: vault.SSHCertificateLibrarySubtype.String(), - Name: &wrapperspb.StringValue{Value: "name"}, + Name: &wrapperspb.StringValue{Value: "name1"}, Description: &wrapperspb.StringValue{Value: "desc"}, Attrs: &pb.CredentialLibrary_VaultSshCertificateCredentialLibraryAttributes{ VaultSshCertificateCredentialLibraryAttributes: &pb.VaultSSHCertificateCredentialLibraryAttributes{ @@ -2079,7 +2079,7 @@ func TestCreate_SSHCertificateCredentialLibrary(t *testing.T) { CredentialStoreId: store.GetPublicId(), CreatedTime: store.GetCreateTime().GetTimestamp(), UpdatedTime: store.GetUpdateTime().GetTimestamp(), - Name: &wrapperspb.StringValue{Value: "name"}, + Name: &wrapperspb.StringValue{Value: "name1"}, Description: &wrapperspb.StringValue{Value: "desc"}, Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()}, Version: 1, @@ -2134,6 +2134,47 @@ func TestCreate_SSHCertificateCredentialLibrary(t *testing.T) { }, }, }, + { + name: "valid vault SSHCertificateCredentialLibrary with AdditionalValidPrincipals", + req: &pbs.CreateCredentialLibraryRequest{Item: &pb.CredentialLibrary{ + CredentialStoreId: store.GetPublicId(), + Type: vault.SSHCertificateLibrarySubtype.String(), + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Attrs: &pb.CredentialLibrary_VaultSshCertificateCredentialLibraryAttributes{ + VaultSshCertificateCredentialLibraryAttributes: &pb.VaultSSHCertificateCredentialLibraryAttributes{ + Path: wrapperspb.String("/ssh/sign/foo"), + Username: wrapperspb.String("username"), + AdditionalValidPrincipals: []*wrapperspb.StringValue{wrapperspb.String("testprincipal")}, + }, + }, + }}, + idPrefix: globals.VaultSshCertificateCredentialLibraryPrefix + "_", + res: &pbs.CreateCredentialLibraryResponse{ + Uri: fmt.Sprintf("credential-libraries/%s_", globals.VaultSshCertificateCredentialLibraryPrefix), + Item: &pb.CredentialLibrary{ + Id: store.GetPublicId(), + CredentialStoreId: store.GetPublicId(), + CreatedTime: store.GetCreateTime().GetTimestamp(), + UpdatedTime: store.GetUpdateTime().GetTimestamp(), + Name: &wrapperspb.StringValue{Value: "name"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Scope: &scopepb.ScopeInfo{Id: prj.GetPublicId(), Type: prj.GetType(), ParentScopeId: prj.GetParentId()}, + Version: 1, + Type: vault.SSHCertificateLibrarySubtype.String(), + Attrs: &pb.CredentialLibrary_VaultSshCertificateCredentialLibraryAttributes{ + VaultSshCertificateCredentialLibraryAttributes: &pb.VaultSSHCertificateCredentialLibraryAttributes{ + Path: wrapperspb.String("/ssh/sign/foo"), + Username: wrapperspb.String("username"), + KeyType: wrapperspb.String(vault.KeyTypeEd25519), + AdditionalValidPrincipals: []*wrapperspb.StringValue{wrapperspb.String("testprincipal")}, + }, + }, + AuthorizedActions: testAuthorizedActions, + CredentialType: string(globals.SshCertificateCredentialType), + }, + }, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { diff --git a/internal/db/schema/migrations/oss/postgres/78/01_ssh_signed_certs_additional_valid_principals.up.sql b/internal/db/schema/migrations/oss/postgres/78/01_ssh_signed_certs_additional_valid_principals.up.sql new file mode 100644 index 000000000..12507b861 --- /dev/null +++ b/internal/db/schema/migrations/oss/postgres/78/01_ssh_signed_certs_additional_valid_principals.up.sql @@ -0,0 +1,118 @@ +-- Copyright (c) HashiCorp, Inc. +-- SPDX-License-Identifier: BUSL-1.1 + +begin; + + alter table credential_vault_ssh_cert_library add column additional_valid_principals text null; + + -- Replaces view from 63/02_add_ssh_cert_to_vault_cred_library_view.up.sql + drop view credential_vault_library_issue_credentials; + create view credential_vault_library_issue_credentials as + with + password_override (library_id, username_attribute, password_attribute) as ( + select library_id, + nullif(username_attribute, wt_to_sentinel('no override')), + nullif(password_attribute, wt_to_sentinel('no override')) + from credential_vault_library_username_password_mapping_override + ), + ssh_private_key_override (library_id, username_attribute, private_key_attribute, private_key_passphrase_attribute) as ( + select library_id, + nullif(username_attribute, wt_to_sentinel('no override')), + nullif(private_key_attribute, wt_to_sentinel('no override')), + nullif(private_key_passphrase_attribute, wt_to_sentinel('no override')) + from credential_vault_library_ssh_private_key_mapping_override + ) + select library.public_id as public_id, + library.store_id as store_id, + library.name as name, + library.description as description, + library.create_time as create_time, + library.update_time as update_time, + library.version as version, + library.vault_path as vault_path, + library.http_method as http_method, + library.http_request_body as http_request_body, + library.credential_type as credential_type, + null as key_type, + null as key_bits, + null as username, + null as ttl, + null as key_id, + null as critical_options, + null as extensions, + store.project_id as project_id, + store.vault_address as vault_address, + store.namespace as namespace, + store.ca_cert as ca_cert, + store.tls_server_name as tls_server_name, + store.tls_skip_verify as tls_skip_verify, + store.worker_filter as worker_filter, + store.ct_token as ct_token, -- encrypted + store.token_hmac as token_hmac, + store.token_status as token_status, + store.token_key_id as token_key_id, + store.client_cert as client_cert, + store.ct_client_key as ct_client_key, -- encrypted + store.client_key_id as client_key_id, + coalesce(upasso.username_attribute,sshpk.username_attribute) + as username_attribute, + upasso.password_attribute as password_attribute, + sshpk.private_key_attribute as private_key_attribute, + sshpk.private_key_passphrase_attribute as private_key_passphrase_attribute, + 'generic' as cred_lib_type, -- used to switch on + null as additional_valid_principals + from credential_vault_library library + join credential_vault_store_client store + on library.store_id = store.public_id + left join password_override upasso + on library.public_id = upasso.library_id + left join ssh_private_key_override sshpk + on library.public_id = sshpk.library_id + union + select library.public_id as public_id, + library.store_id as store_id, + library.name as name, + library.description as description, + library.create_time as create_time, + library.update_time as update_time, + library.version as version, + library.vault_path as vault_path, + null as http_method, + null as http_request_body, + library.credential_type as credential_type, + library.key_type as key_type, + library.key_bits as key_bits, + library.username as username, + library.ttl as ttl, + library.key_id as key_id, + library.critical_options as critical_options, + library.extensions as extensions, + store.project_id as project_id, + store.vault_address as vault_address, + store.namespace as namespace, + store.ca_cert as ca_cert, + store.tls_server_name as tls_server_name, + store.tls_skip_verify as tls_skip_verify, + store.worker_filter as worker_filter, + store.ct_token as ct_token, -- encrypted + store.token_hmac as token_hmac, + store.token_status as token_status, + store.token_key_id as token_key_id, + store.client_cert as client_cert, + store.ct_client_key as ct_client_key, -- encrypted + store.client_key_id as client_key_id, + null as username_attribute, + null as password_attribute, + null as private_key_attribute, + null as private_key_passphrase_attribute, + 'ssh-signed-cert' as cred_lib_type, -- used to switch on + additional_valid_principals as additional_valid_principals + from credential_vault_ssh_cert_library library + join credential_vault_store_client store + on library.store_id = store.public_id; + comment on view credential_vault_library_issue_credentials is + 'credential_vault_library_issue_credentials is a view where each row contains a credential library and the credential library''s data needed to connect to Vault. ' + 'This view should only be used when issuing credentials from a Vault credential library. Each row may contain encrypted data. ' + 'This view should not be used to retrieve data which will be returned external to boundary.'; + +commit; diff --git a/internal/proto/controller/api/resources/credentiallibraries/v1/credential_library.proto b/internal/proto/controller/api/resources/credentiallibraries/v1/credential_library.proto index 9b251f86a..565723d3b 100644 --- a/internal/proto/controller/api/resources/credentiallibraries/v1/credential_library.proto +++ b/internal/proto/controller/api/resources/credentiallibraries/v1/credential_library.proto @@ -200,4 +200,13 @@ message VaultSSHCertificateCredentialLibraryAttributes { that: "Extensions" } ]; // @gotags: `class:"public"` + + // Principals to be signed as "valid_principles" in addition to username. + repeated google.protobuf.StringValue additional_valid_principals = 90 [ + (custom_options.v1.generate_sdk_option) = true, + (custom_options.v1.mask_mapping) = { + this: "attributes.additional_valid_principals" + that: "AdditionalValidPrincipals" + } + ]; // @gotags: `class:"public"` } diff --git a/internal/proto/controller/api/resources/sessionrecordings/v1/session_recording.proto b/internal/proto/controller/api/resources/sessionrecordings/v1/session_recording.proto index b22210c32..e8a170c27 100644 --- a/internal/proto/controller/api/resources/sessionrecordings/v1/session_recording.proto +++ b/internal/proto/controller/api/resources/sessionrecordings/v1/session_recording.proto @@ -410,6 +410,9 @@ message VaultSSHCertificateCredentialLibraryAttributes { // The extensions that the certificate should be signed for. map extensions = 7; // @gotags: class:"public" + + // Principals to be signed as "valid_principles" in addition to username. + repeated string additional_valid_principals = 8; // @gotags: class:"public" } // ValuesAtTime contain information about other Boundary resources as they diff --git a/internal/proto/controller/storage/credential/vault/store/v1/vault.proto b/internal/proto/controller/storage/credential/vault/store/v1/vault.proto index b02c6a3e1..e9e4bfef2 100644 --- a/internal/proto/controller/storage/credential/vault/store/v1/vault.proto +++ b/internal/proto/controller/storage/credential/vault/store/v1/vault.proto @@ -367,6 +367,14 @@ message SSHCertificateCredentialLibrary { // credential_type is always ssh_certificate // @inject_tag: `gorm:"default:null"` string credential_type = 16; + + // additional_valid_principals are strings that will be sent to vault in the "valid_principles" + // api field in addition to the username. + // @inject_tag: `gorm:"default:null"` + string additional_valid_principals = 17 [(custom_options.v1.mask_mapping) = { + this: "AdditionalValidPrincipals" + that: "attributes.additional_valid_principals" + }]; } message Credential { diff --git a/internal/tests/cli/boundary/credential_libraries.bats b/internal/tests/cli/boundary/credential_libraries.bats index 794288e76..d83d8a4e4 100644 --- a/internal/tests/cli/boundary/credential_libraries.bats +++ b/internal/tests/cli/boundary/credential_libraries.bats @@ -100,7 +100,8 @@ export NEW_VAULT_LIB="test_vault" run create_vault_ssh_certificate_library \ -name $NEW_VAULT_LIB -credential-store-id $csid \ -vault-path /ssh/sign/foo \ - -username foo + -username foo \ + -additional-valid-principal test-principal echo "$output" [ "$status" -eq 0 ] } @@ -538,6 +539,42 @@ export NEW_VAULT_LIB="test_vault" [ "$status" -eq 0 ] } +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library one additional-valid-principal" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -additional-valid-principal test-principal-0 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.additional_valid_principals" '["test-principal-0"]' + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library many additional-valid-principals" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -additional-valid-principal test-principal-1 -additional-valid-principal test-principal-2 -additional-valid-principal test-principal-3 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.additional_valid_principals" '["test-principal-1","test-principal-2","test-principal-3"]' + [ "$status" -eq 0 ] +} + @test "boundary/credential-libraries: can delete $NEW_VAULT_LIB vault-ssh-certificate library" { skip_if_no_vault diff --git a/sdk/pbs/controller/api/resources/credentiallibraries/credential_library.pb.go b/sdk/pbs/controller/api/resources/credentiallibraries/credential_library.pb.go index 7f5247a2c..c11242dc7 100644 --- a/sdk/pbs/controller/api/resources/credentiallibraries/credential_library.pb.go +++ b/sdk/pbs/controller/api/resources/credentiallibraries/credential_library.pb.go @@ -339,6 +339,8 @@ type VaultSSHCertificateCredentialLibraryAttributes struct { CriticalOptions map[string]string `protobuf:"bytes,70,rep,name=critical_options,json=criticalOptions,proto3" json:"critical_options,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" class:"public"` // @gotags: `class:"public"` // The extensions that the certificate should be signed for. Extensions map[string]string `protobuf:"bytes,80,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" class:"public"` // @gotags: `class:"public"` + // Principals to be signed as "valid_principles" in addition to username. + AdditionalValidPrincipals []*wrapperspb.StringValue `protobuf:"bytes,90,rep,name=additional_valid_principals,json=additionalValidPrincipals,proto3" json:"additional_valid_principals,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *VaultSSHCertificateCredentialLibraryAttributes) Reset() { @@ -429,6 +431,13 @@ func (x *VaultSSHCertificateCredentialLibraryAttributes) GetExtensions() map[str return nil } +func (x *VaultSSHCertificateCredentialLibraryAttributes) GetAdditionalValidPrincipals() []*wrapperspb.StringValue { + if x != nil { + return x.AdditionalValidPrincipals + } + return nil +} + var File_controller_api_resources_credentiallibraries_v1_credential_library_proto protoreflect.FileDescriptor var file_controller_api_resources_credentiallibraries_v1_credential_library_proto_rawDesc = []byte{ @@ -567,7 +576,7 @@ var file_controller_api_resources_credentiallibraries_v1_credential_library_prot 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x0f, 0x48, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x11, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x22, 0xf1, 0x08, 0x0a, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x53, + 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x9d, 0x0a, 0x0a, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x53, 0x48, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, @@ -630,22 +639,33 @@ var file_controller_api_resources_credentiallibraries_v1_credential_library_prot 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x23, 0x0a, 0x15, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x0a, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, - 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x42, 0x0a, 0x14, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, - 0x61, 0x6c, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3d, 0x0a, 0x0f, 0x45, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x68, 0x5a, 0x66, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x70, - 0x62, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x72, 0x65, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x3b, - 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, - 0x69, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xa9, 0x01, 0x0a, 0x1b, 0x61, 0x64, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6e, + 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x18, 0x5a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x4b, 0xa0, 0xda, 0x29, 0x01, + 0xc2, 0xdd, 0x29, 0x43, 0x0a, 0x26, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x2e, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x19, 0x41, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x72, 0x69, + 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x52, 0x19, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, + 0x6c, 0x73, 0x1a, 0x42, 0x0a, 0x14, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3d, 0x0a, 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x68, 0x5a, 0x66, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x62, 0x73, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x3b, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -695,11 +715,12 @@ var file_controller_api_resources_credentiallibraries_v1_credential_library_prot 6, // 18: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.key_id:type_name -> google.protobuf.StringValue 3, // 19: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.critical_options:type_name -> controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.CriticalOptionsEntry 4, // 20: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.extensions:type_name -> controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.ExtensionsEntry - 21, // [21:21] is the sub-list for method output_type - 21, // [21:21] is the sub-list for method input_type - 21, // [21:21] is the sub-list for extension type_name - 21, // [21:21] is the sub-list for extension extendee - 0, // [0:21] is the sub-list for field type_name + 6, // 21: controller.api.resources.credentiallibraries.v1.VaultSSHCertificateCredentialLibraryAttributes.additional_valid_principals:type_name -> google.protobuf.StringValue + 22, // [22:22] is the sub-list for method output_type + 22, // [22:22] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name } func init() { file_controller_api_resources_credentiallibraries_v1_credential_library_proto_init() } diff --git a/sdk/pbs/controller/api/resources/session_recordings/session_recording.pb.go b/sdk/pbs/controller/api/resources/session_recordings/session_recording.pb.go index d021d4e49..7aa2c6233 100644 --- a/sdk/pbs/controller/api/resources/session_recordings/session_recording.pb.go +++ b/sdk/pbs/controller/api/resources/session_recordings/session_recording.pb.go @@ -1718,6 +1718,8 @@ type VaultSSHCertificateCredentialLibraryAttributes struct { CriticalOptions map[string]string `protobuf:"bytes,6,rep,name=critical_options,json=criticalOptions,proto3" json:"critical_options,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" class:"public"` // @gotags: class:"public" // The extensions that the certificate should be signed for. Extensions map[string]string `protobuf:"bytes,7,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" class:"public"` // @gotags: class:"public" + // Principals to be signed as "valid_principles" in addition to username. + AdditionalValidPrincipals []string `protobuf:"bytes,8,rep,name=additional_valid_principals,json=additionalValidPrincipals,proto3" json:"additional_valid_principals,omitempty" class:"public"` // @gotags: class:"public" } func (x *VaultSSHCertificateCredentialLibraryAttributes) Reset() { @@ -1801,6 +1803,13 @@ func (x *VaultSSHCertificateCredentialLibraryAttributes) GetExtensions() map[str return nil } +func (x *VaultSSHCertificateCredentialLibraryAttributes) GetAdditionalValidPrincipals() []string { + if x != nil { + return x.AdditionalValidPrincipals + } + return nil +} + // ValuesAtTime contain information about other Boundary resources as they // were at a certain time through the lifetime of the Session Recording. type ValuesAtTime struct { @@ -2485,7 +2494,7 @@ var file_controller_api_resources_sessionrecordings_v1_session_recording_proto_r 0x68, 0x6f, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x68, 0x74, 0x74, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x22, - 0xdb, 0x04, 0x0a, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x53, 0x48, 0x43, 0x65, 0x72, 0x74, + 0x9b, 0x05, 0x0a, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x53, 0x48, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, @@ -2514,7 +2523,11 @@ var file_controller_api_resources_sessionrecordings_v1_session_recording_proto_r 0x61, 0x74, 0x65, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, - 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x42, 0x0a, 0x14, 0x43, 0x72, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3e, 0x0a, 0x1b, 0x61, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x70, + 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x19, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x1a, 0x42, 0x0a, 0x14, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, diff --git a/website/content/docs/concepts/domain-model/credential-libraries.mdx b/website/content/docs/concepts/domain-model/credential-libraries.mdx index 8967ded7d..979f962ec 100644 --- a/website/content/docs/concepts/domain-model/credential-libraries.mdx +++ b/website/content/docs/concepts/domain-model/credential-libraries.mdx @@ -80,6 +80,10 @@ For more information, refer to the [list of critical options](https://github.com For more information, refer to the [list of extensions](https://github.com/openssh/openssh-portable/blob/5f93c4836527d9fda05de8944a1c7b4a205080c7/PROTOCOL.certkeys#L270-L319) supported by OpenSSH. Note that the `permit-pty` value should be set for an interactive shell to function properly. +- `additional_valid_principals` - (optional) Valid Principals that the certificate should be signed for in addition to the provided username. +For more information, refer to OpenSSH's ["valid principals" definition](https://github.com/openssh/openssh-portable/blob/5f93c4836527d9fda05de8944a1c7b4a205080c7/PROTOCOL.certkeys#L176-L181) as well as Vault's documentation for the [SSH Secrets Engine](https://developer.hashicorp.com/vault/api-docs/secret/ssh#valid_principals). +Note that all SSH certificates issued by a Vault SSH certificate credential library use the `SSH_CERT_TYPE_USER` certificate type mentioned in the OpenSSH definition link. + ### Vault credential library parameter templating Sometimes it can be useful to provide information about a Boundary user or account when making a call to Vault. For example, this can allow picking the correct role when asking for database credentials (if roles are separated per-user), or providing a value to encode in an X.509 certificate generated by Vault. As of Boundary 0.11.1, you can template user and account information into either the path in Vault, the `POST` request body, or both.