diff --git a/doc/plugin_server_keymanager_aws_kms.md b/doc/plugin_server_keymanager_aws_kms.md index 6b44024a45a..64ee080a4a2 100644 --- a/doc/plugin_server_keymanager_aws_kms.md +++ b/doc/plugin_server_keymanager_aws_kms.md @@ -6,14 +6,15 @@ The `aws_kms` key manager plugin leverages the AWS Key Management Service (KMS) The plugin accepts the following configuration options: -| Key | Type | Required | Description | Default | -|-------------------|--------|---------------------------------------|-----------------------------------------------------------------------------------------|---------------------------------------------------------| -| access_key_id | string | see [AWS KMS Access](#aws-kms-access) | The Access Key Id used to authenticate to KMS | Value of the AWS_ACCESS_KEY_ID environment variable | -| secret_access_key | string | see [AWS KMS Access](#aws-kms-access) | The Secret Access Key used to authenticate to KMS | Value of the AWS_SECRET_ACCESS_KEY environment variable | -| region | string | yes | The region where the keys will be stored | | -| key_metadata_file | string | yes | A file path location where information about generated keys will be persisted | | -| key_metadata | string | yes | A static identifier for the SPIRE server instance (used instead of `key_metadata_file`) | | -| key_policy_file | string | no | A file path location to a custom key policy in JSON format | "" | +| Key | Type | Required | Description | Default | +|----------------------|--------|---------------------------------------|--------------------------------------------------------------------------------------------|---------------------------------------------------------| +| access_key_id | string | see [AWS KMS Access](#aws-kms-access) | The Access Key Id used to authenticate to KMS | Value of the AWS_ACCESS_KEY_ID environment variable | +| secret_access_key | string | see [AWS KMS Access](#aws-kms-access) | The Secret Access Key used to authenticate to KMS | Value of the AWS_SECRET_ACCESS_KEY environment variable | +| region | string | yes | The region where the keys will be stored | | +| key_metadata_file | string | yes | A file path location where information about generated keys will be persisted (deprecated) | | +| key_identifier_file | string | yes | A file path location where information about generated keys will be persisted | | +| key_identifier_value | string | yes | A static identifier for the SPIRE server instance (used instead of `key_metadata_file`) | | +| key_policy_file | string | no | A file path location to a custom key policy in JSON format | "" | ### Alias and Key Management diff --git a/doc/plugin_server_keymanager_azure_key_vault.md b/doc/plugin_server_keymanager_azure_key_vault.md index 23be12fe1e3..005583f3d0a 100644 --- a/doc/plugin_server_keymanager_azure_key_vault.md +++ b/doc/plugin_server_keymanager_azure_key_vault.md @@ -10,16 +10,17 @@ SPIRE. The plugin accepts the following configuration options: -| Key | Type | Required | Description | Default | -|-------------------|---------|----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|---------| -| key_metadata_file | string | yes | A file path location where key metadata used by the plugin will be persisted. See "[Management of keys](#management-of-keys)" for more information. | "" | -| key_metadata | string | yes | A static identifier for the SPIRE server instance (used instead of `key_metadata_file`) | "" | -| key_vault_uri | string | Yes | The Key Vault URI where the keys managed by this plugin reside. | "" | -| use_msi | boolean | [Deprecated](#authenticating-to-azure) | Whether or not to use MSI to authenticate to Azure Key Vault. | false | -| subscription_id | string | [Optional](#authenticating-to-azure) | The subscription id. | "" | -| app_id | string | [Optional](#authenticating-to-azure) | The application id. | "" | -| app_secret | string | [Optional](#authenticating-to-azure) | The application secret. | "" | -| tenant_id | string | [Optional](#authenticating-to-azure) | The tenant id. | "" | +| Key | Type | Required | Description | Default | +|----------------------|---------|----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------| +| key_metadata_file | string | yes | A file path location where key metadata used by the plugin will be persisted (deprecated). See "[Management of keys](#management-of-keys)" for more information. | "" | +| key_identifier_file | string | yes | A file path location where key metadata used by the plugin will be persisted. See "[Management of keys](#management-of-keys)" for more information. | "" | +| key_identifier_value | string | yes | A static identifier for the SPIRE server instance (used instead of `key_metadata_file`) | "" | +| key_vault_uri | string | Yes | The Key Vault URI where the keys managed by this plugin reside. | "" | +| use_msi | boolean | [Deprecated](#authenticating-to-azure) | Whether or not to use MSI to authenticate to Azure Key Vault. | false | +| subscription_id | string | [Optional](#authenticating-to-azure) | The subscription id. | "" | +| app_id | string | [Optional](#authenticating-to-azure) | The application id. | "" | +| app_secret | string | [Optional](#authenticating-to-azure) | The application secret. | "" | +| tenant_id | string | [Optional](#authenticating-to-azure) | The tenant id. | "" | ### Authenticating to Azure @@ -53,7 +54,7 @@ following table is provided for informational purposes only: | Label | Description | |-----------------|----------------------------------------------------------------------------------------------------------------------------------------| -| spire-server-td | A string representing the trust domain name of the server. | +| spire-server-td | A string representing the trust domain name of the server. | | spire-server-id | Auto-generated ID that is unique to the server and is persisted in the _Key Metadata File_ (see the `key_metadata_file` configurable). | If the _Key Metadata File_ is not found during server startup, the file is diff --git a/doc/plugin_server_keymanager_gcp_kms.md b/doc/plugin_server_keymanager_gcp_kms.md index fd64c2be7f0..24d16c53c6b 100644 --- a/doc/plugin_server_keymanager_gcp_kms.md +++ b/doc/plugin_server_keymanager_gcp_kms.md @@ -13,8 +13,9 @@ The plugin accepts the following configuration options: | Key | Type | Required | Description | Default | |----------------------|--------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------| | key_policy_file | string | no | A file path location to a custom [IAM Policy (v3)](https://cloud.google.com/pubsub/docs/reference/rpc/google.iam.v1#google.iam.v1.Policy) in JSON format to be attached to created CryptoKeys. | "" | -| key_metadata_file | string | yes | A file path location where key metadata used by the plugin will be persisted. See "[Management of keys](#management-of-keys)" for more information. | "" | -| key_metadata | string | yes | A static identifier for the SPIRE server instance (used instead of `key_metadata_file`) | "" | +| key_metadata_file | string | yes | A file path location where key metadata used by the plugin will be persisted (deprecated). See "[Management of keys](#management-of-keys)" for more information. | "" | +| key_identifier_file | string | yes | A file path location where key metadata used by the plugin will be persisted. See "[Management of keys](#management-of-keys)" for more information. | "" | +| key_identifier_value | string | yes | A static identifier for the SPIRE server instance (used instead of `key_metadata_file`) | "" | | key_ring | string | yes | Resource ID of the key ring where the keys managed by this plugin reside, in the format projects/\*/locations/\*/keyRings/\* | "" | | service_account_file | string | no | Path to the service account file used to authenticate with the Cloud KMS API. | Value of `GOOGLE_APPLICATION_CREDENTIALS` environment variable. | @@ -50,12 +51,12 @@ the service. All the labels are named with the `spire-` prefix. Users don't need to interact with the labels managed by the plugin. The following table is provided for informational purposes only: -| Label | Description | -| ----- | ----------- | -| spire-server-td | SHA-1 checksum of the trust domain name of the server. | -| spire-server-id | Auto-generated ID that is unique to the server and is persisted in the _Key Metadata File_ (see the `key_metadata_file` configurable). | -| spire-last-update | Unix time of the last time that the plugin updated the CryptoKey to keep it active. | -| spire-active | Indicates if the CryptoKey is still in use by the plugin. | +| Label | Description | +|-------------------|----------------------------------------------------------------------------------------------------------------------------------------| +| spire-server-td | SHA-1 checksum of the trust domain name of the server. | +| spire-server-id | Auto-generated ID that is unique to the server and is persisted in the _Key Metadata File_ (see the `key_metadata_file` configurable). | +| spire-last-update | Unix time of the last time that the plugin updated the CryptoKey to keep it active. | +| spire-active | Indicates if the CryptoKey is still in use by the plugin. | If the _Key Metadata File_ is not found during server startup, the file is recreated, with a new auto-generated server ID. Consequently, if the file is diff --git a/pkg/server/plugin/keymanager/awskms/awskms.go b/pkg/server/plugin/keymanager/awskms/awskms.go index 8755ad94cb8..374464e1209 100644 --- a/pkg/server/plugin/keymanager/awskms/awskms.go +++ b/pkg/server/plugin/keymanager/awskms/awskms.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "path" + "regexp" "strings" "sync" "time" @@ -92,12 +93,13 @@ type Plugin struct { // Config provides configuration context for the plugin type Config struct { - AccessKeyID string `hcl:"access_key_id" json:"access_key_id"` - SecretAccessKey string `hcl:"secret_access_key" json:"secret_access_key"` - Region string `hcl:"region" json:"region"` - KeyMetadataFile string `hcl:"key_metadata_file" json:"key_metadata_file"` - KeyMetadata string `hcl:"key_metadata" json:"key_metadata"` - KeyPolicyFile string `hcl:"key_policy_file" json:"key_policy_file"` + AccessKeyID string `hcl:"access_key_id" json:"access_key_id"` + SecretAccessKey string `hcl:"secret_access_key" json:"secret_access_key"` + Region string `hcl:"region" json:"region"` + KeyMetadataFile string `hcl:"key_metadata_file" json:"key_metadata_file"` + KeyIdentifierFile string `hcl:"key_identifier_file" json:"key_identifier_file"` + KeyIdentifierValue string `hcl:"key_identifier_value" json:"key_identifier_value"` + KeyPolicyFile string `hcl:"key_policy_file" json:"key_policy_file"` } // New returns an instantiated plugin @@ -132,22 +134,30 @@ func (p *Plugin) Configure(ctx context.Context, req *configv1.ConfigureRequest) return nil, err } - var serverID = config.KeyMetadata - if config.KeyMetadata == "" { + if config.KeyPolicyFile != "" { + policyBytes, err := os.ReadFile(config.KeyPolicyFile) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to read file configured in 'key_policy_file': %v", err) + } + policyStr := string(policyBytes) + p.keyPolicy = &policyStr + } + + var serverID = config.KeyIdentifierValue + if serverID == "" && config.KeyMetadataFile != "" { + p.log.Warn("`key_metadata_file` is deprecated in favor of `key_identifier_file` and will be removed in a future version") serverID, err = getOrCreateServerID(config.KeyMetadataFile) if err != nil { return nil, err } p.log.Debug("Loaded server id", "server_id", serverID) } - - if config.KeyPolicyFile != "" { - policyBytes, err := os.ReadFile(config.KeyPolicyFile) + if serverID == "" && config.KeyIdentifierFile != "" { + serverID, err = getOrCreateServerID(config.KeyIdentifierFile) if err != nil { - return nil, status.Errorf(codes.Internal, "failed to read file configured in 'key_policy_file': %v", err) + return nil, err } - policyStr := string(policyBytes) - p.keyPolicy = &policyStr + p.log.Debug("Loaded server id", "server_id", serverID) } awsCfg, err := newAWSConfig(ctx, config) @@ -836,9 +846,27 @@ func parseAndValidateConfig(c string) (*Config, error) { return nil, status.Error(codes.InvalidArgument, "configuration is missing a region") } - if config.KeyMetadataFile == "" && config.KeyMetadata == "" { + if config.KeyIdentifierValue != "" { + re := regexp.MustCompile(".*[^A-z0-9/_-].*") + if re.MatchString(config.KeyIdentifierValue) { + return nil, status.Error(codes.InvalidArgument, "Key identifier must contain only alphanumeric characters, forward slashes (/), underscores (_), and dashes (-)") + } + if strings.HasPrefix(config.KeyIdentifierValue, "alias/aws/") { + return nil, status.Error(codes.InvalidArgument, "Key identifier must not start with alias/aws/") + } + if len(config.KeyIdentifierValue) > 256 { + return nil, status.Error(codes.InvalidArgument, "Key identifier must not be longer than 256 characters") + } + } + if config.KeyMetadataFile == "" && config.KeyIdentifierFile == "" && config.KeyIdentifierValue == "" { return nil, status.Error(codes.InvalidArgument, "configuration requires server id or server id file path") } + if (config.KeyMetadataFile != "" || config.KeyIdentifierFile != "") && config.KeyIdentifierValue != "" { + return nil, status.Error(codes.InvalidArgument, "configuration must not contain both server id and server id file path") + } + if config.KeyMetadataFile != "" && config.KeyIdentifierFile != "" { + return nil, status.Error(codes.InvalidArgument, "configuration must not contain both `key_identifier_file` and deprecated `key_metadata_file`") + } return config, nil } diff --git a/pkg/server/plugin/keymanager/awskms/awskms_test.go b/pkg/server/plugin/keymanager/awskms/awskms_test.go index 2e55fbdeeb1..4556582e819 100644 --- a/pkg/server/plugin/keymanager/awskms/awskms_test.go +++ b/pkg/server/plugin/keymanager/awskms/awskms_test.go @@ -91,14 +91,14 @@ func TestKeyManagerContract(t *testing.T) { func(aws.Config) (stsClient, error) { return fakeSTSClient, nil }, ) km := new(keymanager.V1) - keyMetadataFile := filepath.Join(dir, "metadata") + keyIdentifierFile := filepath.Join(dir, "metadata") if isWindows { - keyMetadataFile = filepath.ToSlash(keyMetadataFile) + keyIdentifierFile = filepath.ToSlash(keyIdentifierFile) } plugintest.Load(t, builtin(p), km, plugintest.Configuref(` region = "fake-region" key_metadata_file = %q - `, keyMetadataFile)) + `, keyIdentifierFile)) return km } @@ -209,39 +209,77 @@ func TestConfigure(t *testing.T) { name: "pass without keys", configureRequest: configureRequestWithDefaults(t), }, + { + name: "pass with identity file", + configureRequest: configureRequestWithVars("", "secret_access_key", "region", KeyIdentifierFile, getKeyIdentifierFile(t), ""), + }, + { + name: "pass with identity value", + configureRequest: configureRequestWithVars("", "secret_access_key", "region", KeyIdentifierValue, "server-id", ""), + }, { name: "missing access key id", - configureRequest: configureRequestWithVars("", "secret_access_key", "region", getKeyMetadataFile(t), ""), + configureRequest: configureRequestWithVars("", "secret_access_key", "region", KeyMetadataFile, getKeyIdentifierFile(t), ""), }, { name: "missing secret access key", - configureRequest: configureRequestWithVars("access_key", "", "region", getKeyMetadataFile(t), ""), + configureRequest: configureRequestWithVars("access_key", "", "region", KeyMetadataFile, getKeyIdentifierFile(t), ""), }, { name: "missing region", - configureRequest: configureRequestWithVars("access_key_id", "secret_access_key", "", getKeyMetadataFile(t), ""), + configureRequest: configureRequestWithVars("access_key_id", "secret_access_key", "", KeyMetadataFile, getKeyIdentifierFile(t), ""), err: "configuration is missing a region", code: codes.InvalidArgument, }, { name: "missing server id file path", - configureRequest: configureRequestWithVars("access_key_id", "secret_access_key", "region", "", ""), + configureRequest: configureRequestWithVars("access_key_id", "secret_access_key", "region", KeyMetadataFile, "", ""), err: "configuration requires server id or server id file path", code: codes.InvalidArgument, }, + { + name: "key identifier file and key identifier value", + configureRequest: configureRequestWithString(`{"access_key_id":"access_key_id","secret_access_key":"secret_access_key","region":"region","key_identifier_file":"key_identifier_file","key_identifier_value":"key_identifier_value","key_policy_file":""}`), + err: "configuration must not contain both server id and server id file path", + code: codes.InvalidArgument, + }, + { + name: "key metadata file and key identifier file", + configureRequest: configureRequestWithString(`{"access_key_id":"access_key_id","secret_access_key":"secret_access_key","region":"region","key_metadata_file":"key_metadata_file","key_identifier_file":"key_identifier_file","key_policy_file":""}`), + err: "configuration must not contain both `key_identifier_file` and deprecated `key_metadata_file`", + code: codes.InvalidArgument, + }, + { + name: "key metadata value invalid character", + configureRequest: configureRequestWithString(`{"access_key_id":"access_key_id","secret_access_key":"secret_access_key","region":"region","key_identifier_value":"@key_identifier_value@","key_policy_file":""}`), + err: "Key identifier must contain only alphanumeric characters, forward slashes (/), underscores (_), and dashes (-)", + code: codes.InvalidArgument, + }, + { + name: "key metadata value too long", + configureRequest: configureRequestWithString(`{"access_key_id":"access_key_id","secret_access_key":"secret_access_key","region":"region","key_identifier_value":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","key_policy_file":""}`), + err: "Key identifier must not be longer than 256 characters", + code: codes.InvalidArgument, + }, + { + name: "key metadata value starts with illegal alias", + configureRequest: configureRequestWithString(`{"access_key_id":"access_key_id","secret_access_key":"secret_access_key","region":"region","key_identifier_value":"alias/aws/key_identifier_value","key_policy_file":""}`), + err: "Key identifier must not start with alias/aws/", + code: codes.InvalidArgument, + }, { name: "custom policy file does not exists", - configureRequest: configureRequestWithVars("access_key", "secret_access_key", "region", getEmptyKeyMetadataFile(t), "non-existent-file.json"), + configureRequest: configureRequestWithVars("access_key", "secret_access_key", "region", KeyMetadataFile, getEmptyKeyIdentifierFile(t), "non-existent-file.json"), err: fmt.Sprintf("failed to read file configured in 'key_policy_file': open non-existent-file.json: %s", spiretest.FileNotFound()), code: codes.Internal, }, { name: "use custom policy file", - configureRequest: configureRequestWithVars("access_key", "secret_access_key", "region", getEmptyKeyMetadataFile(t), getCustomPolicyFile(t)), + configureRequest: configureRequestWithVars("access_key", "secret_access_key", "region", KeyMetadataFile, getEmptyKeyIdentifierFile(t), getCustomPolicyFile(t)), }, { name: "new server id file path", - configureRequest: configureRequestWithVars("access_key_id", "secret_access_key", "region", getEmptyKeyMetadataFile(t), ""), + configureRequest: configureRequestWithVars("access_key_id", "secret_access_key", "region", KeyMetadataFile, getEmptyKeyIdentifierFile(t), ""), }, { name: "decode error", @@ -382,7 +420,7 @@ func TestGenerateKey(t *testing.T) { KeyId: spireKeyID, KeyType: keymanagerv1.KeyType_EC_P256, }, - configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", getEmptyKeyMetadataFile(t), ""), + configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", KeyMetadataFile, getEmptyKeyIdentifierFile(t), ""), instanceAccountID: "example-account-id", instanceRoleARN: "arn:aws:sts::example-account-id:assumed-role/example-assumed-role-name/example-instance-id", expectedKeyPolicy: &roleBasedPolicy, @@ -393,7 +431,7 @@ func TestGenerateKey(t *testing.T) { KeyId: spireKeyID, KeyType: keymanagerv1.KeyType_EC_P256, }, - configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", getEmptyKeyMetadataFile(t), getCustomPolicyFile(t)), + configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", KeyMetadataFile, getEmptyKeyIdentifierFile(t), getCustomPolicyFile(t)), instanceAccountID: "example-account-id", instanceRoleARN: "arn:aws:sts::example-account-id:assumed-role/example-assumed-role-name/example-instance-id", expectedKeyPolicy: &customPolicy, @@ -665,7 +703,7 @@ func TestGenerateKey(t *testing.T) { KeyId: spireKeyID, KeyType: keymanagerv1.KeyType_EC_P256, }, - configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", getEmptyKeyMetadataFile(t), ""), + configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", KeyMetadataFile, getEmptyKeyIdentifierFile(t), ""), getCallerIdentityErr: "something went wrong", err: "cannot get caller identity: something went wrong", code: codes.Internal, @@ -676,7 +714,7 @@ func TestGenerateKey(t *testing.T) { KeyId: spireKeyID, KeyType: keymanagerv1.KeyType_EC_P256, }, - configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", getEmptyKeyMetadataFile(t), ""), + configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", KeyMetadataFile, getEmptyKeyIdentifierFile(t), ""), instanceRoleARN: "arn:aws:sts::example-account-id", logs: []spiretest.LogEntry{ { @@ -691,7 +729,7 @@ func TestGenerateKey(t *testing.T) { KeyId: spireKeyID, KeyType: keymanagerv1.KeyType_EC_P256, }, - configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", getKeyMetadataFile(t), ""), + configureReq: configureRequestWithVars("access_key_id", "secret_access_key", "region", KeyMetadataFile, getKeyIdentifierFile(t), ""), instanceRoleARN: "arn:aws:sts::example-account-id:user/development", logs: []spiretest.LogEntry{ { @@ -1932,23 +1970,33 @@ func TestDisposeKeys(t *testing.T) { func configureRequestWithString(config string) *configv1.ConfigureRequest { return &configv1.ConfigureRequest{ - HclConfiguration: config, + HclConfiguration: config, + CoreConfiguration: &configv1.CoreConfiguration{TrustDomain: "test.example.org"}, } } -func configureRequestWithVars(accessKeyID, secretAccessKey, region, keyMetadataFile, keyPolicyFile string) *configv1.ConfigureRequest { +type KeyIdentifierConfigName string + +const ( + KeyMetadataFile KeyIdentifierConfigName = "key_metadata_file" + KeyIdentifierFile KeyIdentifierConfigName = "key_identifier_file" + KeyIdentifierValue KeyIdentifierConfigName = "key_identifier_value" +) + +func configureRequestWithVars(accessKeyID, secretAccessKey, region, keyIdentifierConfigName KeyIdentifierConfigName, keyIdentifierConfigValue, keyPolicyFile string) *configv1.ConfigureRequest { return &configv1.ConfigureRequest{ HclConfiguration: fmt.Sprintf(`{ "access_key_id": "%s", "secret_access_key": "%s", "region":"%s", - "key_metadata_file":"%s", + "%s":"%s", "key_policy_file":"%s" }`, accessKeyID, secretAccessKey, region, - keyMetadataFile, + keyIdentifierConfigName, + keyIdentifierConfigValue, keyPolicyFile), CoreConfiguration: &configv1.CoreConfiguration{TrustDomain: "test.example.org"}, } @@ -1956,25 +2004,26 @@ func configureRequestWithVars(accessKeyID, secretAccessKey, region, keyMetadataF func configureRequestWithDefaults(t *testing.T) *configv1.ConfigureRequest { return &configv1.ConfigureRequest{ - HclConfiguration: serializedConfiguration(validAccessKeyID, validSecretAccessKey, validRegion, getKeyMetadataFile(t)), + HclConfiguration: serializedConfiguration(validAccessKeyID, validSecretAccessKey, validRegion, KeyMetadataFile, getKeyIdentifierFile(t)), CoreConfiguration: &configv1.CoreConfiguration{TrustDomain: "test.example.org"}, } } -func serializedConfiguration(accessKeyID, secretAccessKey, region string, keyMetadataFile string) string { +func serializedConfiguration(accessKeyID, secretAccessKey, region string, keyIdentifierConfigName KeyIdentifierConfigName, keyIdentifierConfigValue string) string { return fmt.Sprintf(`{ "access_key_id": "%s", "secret_access_key": "%s", "region":"%s", - "key_metadata_file":"%s" + "%s":"%s" }`, accessKeyID, secretAccessKey, region, - keyMetadataFile) + keyIdentifierConfigName, + keyIdentifierConfigValue) } -func getKeyMetadataFile(t *testing.T) string { +func getKeyIdentifierFile(t *testing.T) string { tempDir := t.TempDir() tempFilePath := path.Join(tempDir, validServerIDFile) err := os.WriteFile(tempFilePath, []byte(validServerID), 0o600) @@ -1987,13 +2036,13 @@ func getKeyMetadataFile(t *testing.T) string { return tempFilePath } -func getEmptyKeyMetadataFile(t *testing.T) string { +func getEmptyKeyIdentifierFile(t *testing.T) string { tempDir := t.TempDir() - keyMetadataFile := path.Join(tempDir, validServerIDFile) + keyIdentifierFile := path.Join(tempDir, validServerIDFile) if isWindows { - keyMetadataFile = filepath.ToSlash(keyMetadataFile) + keyIdentifierFile = filepath.ToSlash(keyIdentifierFile) } - return keyMetadataFile + return keyIdentifierFile } func getCustomPolicyFile(t *testing.T) string { diff --git a/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault.go b/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault.go index f48fba9cb63..3ac518a6716 100644 --- a/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault.go +++ b/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault.go @@ -77,13 +77,14 @@ type pluginHooks struct { // Config provides configuration context for the plugin. type Config struct { - KeyMetadataFile string `hcl:"key_metadata_file" json:"key_metadata_file"` - KeyMetadata string `hcl:"key_metadata" json:"key_metadata"` - KeyVaultURI string `hcl:"key_vault_uri" json:"key_vault_uri"` - TenantID string `hcl:"tenant_id" json:"tenant_id"` - SubscriptionID string `hcl:"subscription_id" json:"subscription_id"` - AppID string `hcl:"app_id" json:"app_id"` - AppSecret string `hcl:"app_secret" json:"app_secret"` + KeyMetadataFile string `hcl:"key_metadata_file" json:"key_metadata_file"` + KeyIdentifierFile string `hcl:"key_identifier_file" json:"key_identifier_file"` + KeyIdentifierValue string `hcl:"key_identifier_value" json:"key_identifier_value"` + KeyVaultURI string `hcl:"key_vault_uri" json:"key_vault_uri"` + TenantID string `hcl:"tenant_id" json:"tenant_id"` + SubscriptionID string `hcl:"subscription_id" json:"subscription_id"` + AppID string `hcl:"app_id" json:"app_id"` + AppSecret string `hcl:"app_secret" json:"app_secret"` // Deprecated: use_msi is deprecated and will be removed in a future release. // Will be used implicitly if other mechanisms to authenticate fail. @@ -140,13 +141,21 @@ func (p *Plugin) Configure(ctx context.Context, req *configv1.ConfigureRequest) return nil, err } - var serverID = config.KeyMetadata - if config.KeyMetadata == "" { + var serverID = config.KeyIdentifierValue + if serverID == "" && config.KeyMetadataFile != "" { + p.log.Warn("`key_metadata_file` is deprecated in favor of `key_identifier_file` and will be removed in a future version") serverID, err = getOrCreateServerID(config.KeyMetadataFile) if err != nil { return nil, err } - p.log.Debug("Loaded server ID", "server_id", serverID) + p.log.Debug("Loaded server id", "server_id", serverID) + } + if serverID == "" && config.KeyIdentifierFile != "" { + serverID, err = getOrCreateServerID(config.KeyIdentifierFile) + if err != nil { + return nil, err + } + p.log.Debug("Loaded server id", "server_id", serverID) } var client cloudKeyManagementService @@ -689,9 +698,15 @@ func parseAndValidateConfig(c string) (*Config, error) { return nil, status.Error(codes.InvalidArgument, "configuration is missing the Key Vault URI") } - if config.KeyMetadataFile == "" && config.KeyMetadata == "" { + if config.KeyMetadataFile == "" && config.KeyIdentifierFile == "" && config.KeyIdentifierValue == "" { return nil, status.Error(codes.InvalidArgument, "configuration requires server id or server id file path") } + if (config.KeyMetadataFile != "" || config.KeyIdentifierFile != "") && config.KeyIdentifierValue != "" { + return nil, status.Error(codes.InvalidArgument, "configuration must not contain both server id and server id file path") + } + if config.KeyMetadataFile != "" && config.KeyIdentifierFile != "" { + return nil, status.Error(codes.InvalidArgument, "configuration must not contain both `key_identifier_file` and deprecated `key_metadata_file`") + } return config, nil } diff --git a/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault_test.go b/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault_test.go index 585adcc22b3..5af7dfee8f0 100644 --- a/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault_test.go +++ b/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault_test.go @@ -66,13 +66,13 @@ func TestKeyManagerContract(t *testing.T) { func(azcore.TokenCredential, string) (cloudKeyManagementService, error) { return kmsClient, nil }, ) km := new(keymanager.V1) - keyMetadataFile := createKeyMetadataFile(t) + keyIdentifierFile := createKeyIdentifierFile(t) plugintest.Load(t, builtin(p), km, plugintest.Configuref(` key_metadata_file = %q key_vault_uri = "https://spire-server.vault.azure.net/" use_msi=true - `, keyMetadataFile)) + `, keyIdentifierFile)) return km } @@ -112,55 +112,75 @@ func TestConfigure(t *testing.T) { name: "pass without keys", configureRequest: configureRequestWithDefaults(t), }, + { + name: "pass with identity file", + configureRequest: configureRequestWithVars(KeyIdentifierFile, createKeyIdentifierFile(t), validKeyVaultURI, "", "", "", validAppSecret, "true"), + }, + { + name: "pass with identity value", + configureRequest: configureRequestWithVars(KeyIdentifierValue, "server-id", validKeyVaultURI, "", "", "", validAppSecret, "true"), + }, { name: "missing key metadata file", - configureRequest: configureRequestWithVars("", validKeyVaultURI, "", "", "", validAppSecret, "true"), + configureRequest: configureRequestWithVars(KeyMetadataFile, "", validKeyVaultURI, "", "", "", validAppSecret, "true"), err: "configuration requires server id or server id file path", code: codes.InvalidArgument, }, + { + name: "key identifier file and key identifier value", + configureRequest: configureRequestWithString("{\"access_key_id\":\"access_key_id\",\"secret_access_key\":\"secret_access_key\",\"region\":\"region\",\"key_identifier_file\":\"key_identifier_file\",\"key_identifier_value\":\"key_identifier_value\",\"key_policy_file\":\"\"}"), + err: "configuration must not contain both server id and server id file path", + code: codes.InvalidArgument, + }, + { + name: "key metadata file and key identifier file", + configureRequest: configureRequestWithString("{\"access_key_id\":\"access_key_id\",\"secret_access_key\":\"secret_access_key\",\"region\":\"region\",\"key_metadata_file\":\"key_metadata_file\",\"key_identifier_file\":\"key_identifier_file\",\"key_policy_file\":\"\"}"), + err: "configuration must not contain both `key_identifier_file` and deprecated `key_metadata_file`", + code: codes.InvalidArgument, + }, { name: "missing client authentication config", - configureRequest: configureRequestWithVars(createKeyMetadataFile(t), validKeyVaultURI, "", "", "", "", "false"), + configureRequest: configureRequestWithVars(KeyMetadataFile, createKeyIdentifierFile(t), validKeyVaultURI, "", "", "", "", "false"), }, { name: "use MSI while app secret is set", - configureRequest: configureRequestWithVars(createKeyMetadataFile(t), validKeyVaultURI, "", "", "", validAppSecret, "true"), + configureRequest: configureRequestWithVars(KeyMetadataFile, createKeyIdentifierFile(t), validKeyVaultURI, "", "", "", validAppSecret, "true"), err: "invalid configuration, cannot use both MSI and app authentication", code: codes.InvalidArgument, }, { name: "missing Key Vault URI", - configureRequest: configureRequestWithVars(createKeyMetadataFile(t), "", validTenantID, validSubscriptionID, validAppID, validAppSecret, "false"), + configureRequest: configureRequestWithVars(KeyMetadataFile, createKeyIdentifierFile(t), "", validTenantID, validSubscriptionID, validAppID, validAppSecret, "false"), err: "configuration is missing the Key Vault URI", code: codes.InvalidArgument, }, { name: "missing tenant ID", - configureRequest: configureRequestWithVars(createKeyMetadataFile(t), validKeyVaultURI, "", validSubscriptionID, validAppID, validAppSecret, "false"), + configureRequest: configureRequestWithVars(KeyMetadataFile, createKeyIdentifierFile(t), validKeyVaultURI, "", validSubscriptionID, validAppID, validAppSecret, "false"), err: "invalid configuration, missing tenant id", code: codes.InvalidArgument, }, { name: "missing subscription ID ", - configureRequest: configureRequestWithVars(createKeyMetadataFile(t), validKeyVaultURI, validTenantID, "", validAppID, validAppSecret, "false"), + configureRequest: configureRequestWithVars(KeyMetadataFile, createKeyIdentifierFile(t), validKeyVaultURI, validTenantID, "", validAppID, validAppSecret, "false"), err: "invalid configuration, missing subscription id", code: codes.InvalidArgument, }, { name: "missing server id file path", - configureRequest: configureRequestWithVars("", validKeyVaultURI, validTenantID, validSubscriptionID, validAppID, validAppSecret, "false"), + configureRequest: configureRequestWithVars(KeyMetadataFile, "", validKeyVaultURI, validTenantID, validSubscriptionID, validAppID, validAppSecret, "false"), err: "configuration requires server id or server id file path", code: codes.InvalidArgument, }, { name: "missing application ID", - configureRequest: configureRequestWithVars(createKeyMetadataFile(t), validKeyVaultURI, validTenantID, validSubscriptionID, "", validAppSecret, "false"), + configureRequest: configureRequestWithVars(KeyMetadataFile, createKeyIdentifierFile(t), validKeyVaultURI, validTenantID, validSubscriptionID, "", validAppSecret, "false"), err: "invalid configuration, missing application id", code: codes.InvalidArgument, }, { name: "missing application secret", - configureRequest: configureRequestWithVars(createKeyMetadataFile(t), validKeyVaultURI, validTenantID, validSubscriptionID, validAppID, "", "false"), + configureRequest: configureRequestWithVars(KeyMetadataFile, createKeyIdentifierFile(t), validKeyVaultURI, validTenantID, validSubscriptionID, validAppID, "", "false"), err: "invalid configuration, missing app secret", code: codes.InvalidArgument, }, @@ -950,7 +970,7 @@ func setupTest(t *testing.T) *pluginTest { func configureRequestWithDefaults(t *testing.T) *configv1.ConfigureRequest { return &configv1.ConfigureRequest{ - HclConfiguration: serializedConfiguration(createKeyMetadataFile(t), validKeyVaultURI, validTenantID, validSubscriptionID, validAppID, validAppSecret, ""), + HclConfiguration: serializedConfiguration(KeyMetadataFile, createKeyIdentifierFile(t), validKeyVaultURI, validTenantID, validSubscriptionID, validAppID, validAppSecret, ""), CoreConfiguration: &configv1.CoreConfiguration{TrustDomain: trustDomain}, } } @@ -961,9 +981,17 @@ func getUUID(t *testing.T) string { return uuid.String() } -func serializedConfiguration(keyMetadataFile, keyVaultURI, tenantID, subscriptionID, appID, appSecret, useMsi string) string { +type KeyIdentifierConfigName string + +const ( + KeyMetadataFile KeyIdentifierConfigName = "key_metadata_file" + KeyIdentifierFile KeyIdentifierConfigName = "key_identifier_file" + KeyIdentifierValue KeyIdentifierConfigName = "key_identifier_value" +) + +func serializedConfiguration(keyIdentifierConfigName KeyIdentifierConfigName, keyIdentifierConfigValue, keyVaultURI, tenantID, subscriptionID, appID, appSecret, useMsi string) string { return fmt.Sprintf(`{ - "key_metadata_file":"%s", + "%s":"%s", "key_vault_uri":"%s", "tenant_id":"%s", "subscription_id":"%s", @@ -971,7 +999,8 @@ func serializedConfiguration(keyMetadataFile, keyVaultURI, tenantID, subscriptio "app_secret":"%s", "use_msi":%s }`, - keyMetadataFile, + keyIdentifierConfigName, + keyIdentifierConfigValue, keyVaultURI, tenantID, subscriptionID, @@ -980,9 +1009,9 @@ func serializedConfiguration(keyMetadataFile, keyVaultURI, tenantID, subscriptio useMsi) } -func configureRequestWithVars(keyMetadataFile, keyVaultURI, tenantID, subscriptionID, appID, appSecret, useMsi string) *configv1.ConfigureRequest { +func configureRequestWithVars(keyIdentifierConfigName KeyIdentifierConfigName, keyIdentifierConfigValue, keyVaultURI, tenantID, subscriptionID, appID, appSecret, useMsi string) *configv1.ConfigureRequest { return &configv1.ConfigureRequest{ - HclConfiguration: serializedConfiguration(keyMetadataFile, keyVaultURI, tenantID, subscriptionID, appID, appSecret, useMsi), + HclConfiguration: serializedConfiguration(keyIdentifierConfigName, keyIdentifierConfigValue, keyVaultURI, tenantID, subscriptionID, appID, appSecret, useMsi), CoreConfiguration: &configv1.CoreConfiguration{TrustDomain: trustDomain}, } } @@ -993,7 +1022,7 @@ func configureRequestWithString(config string) *configv1.ConfigureRequest { } } -func createKeyMetadataFile(t *testing.T) string { +func createKeyIdentifierFile(t *testing.T) string { tempDir := t.TempDir() tempFilePath := filepath.ToSlash(filepath.Join(tempDir, validServerIDFile)) err := os.WriteFile(tempFilePath, []byte(validServerID), 0o600) diff --git a/pkg/server/plugin/keymanager/gcpkms/gcpkms.go b/pkg/server/plugin/keymanager/gcpkms/gcpkms.go index 8f06485d65c..32ea51f4401 100644 --- a/pkg/server/plugin/keymanager/gcpkms/gcpkms.go +++ b/pkg/server/plugin/keymanager/gcpkms/gcpkms.go @@ -117,10 +117,11 @@ type Plugin struct { // Config provides configuration context for the plugin. type Config struct { // File path location where key metadata used by the plugin is persisted. - KeyMetadataFile string `hcl:"key_metadata_file" json:"key_metadata_file"` + KeyMetadataFile string `hcl:"key_metadata_file" json:"key_metadata_file"` + KeyIdentifierFile string `hcl:"key_identifier_file" json:"key_identifier_file"` // Key metadata used by the plugin. - KeyMetadata string `hcl:"key_metadata" json:"key_metadata"` + KeyIdentifierValue string `hcl:"key_identifier_value" json:"key_identifier_value"` // File path location to a custom IAM Policy (v3) that will be set to // created CryptoKeys. @@ -170,13 +171,20 @@ func (p *Plugin) Configure(ctx context.Context, req *configv1.ConfigureRequest) return nil, err } - var serverID = config.KeyMetadata - if config.KeyMetadata == "" { + var serverID = config.KeyIdentifierValue + if serverID == "" && config.KeyMetadataFile != "" { serverID, err = getOrCreateServerID(config.KeyMetadataFile) if err != nil { return nil, err } - p.log.Debug("Loaded server ID", "server_id", serverID) + p.log.Debug("Loaded server id", "server_id", serverID) + } + if serverID == "" && config.KeyIdentifierFile != "" { + serverID, err = getOrCreateServerID(config.KeyIdentifierFile) + if err != nil { + return nil, err + } + p.log.Debug("Loaded server id", "server_id", serverID) } var customPolicy *iam.Policy3 @@ -1110,9 +1118,15 @@ func parseAndValidateConfig(c string) (*Config, error) { return nil, status.Error(codes.InvalidArgument, "configuration is missing the key ring") } - if config.KeyMetadataFile == "" && config.KeyMetadata == "" { + if config.KeyMetadataFile == "" && config.KeyIdentifierFile == "" && config.KeyIdentifierValue == "" { return nil, status.Error(codes.InvalidArgument, "configuration requires server id or server id file path") } + if (config.KeyMetadataFile != "" || config.KeyIdentifierFile != "") && config.KeyIdentifierValue != "" { + return nil, status.Error(codes.InvalidArgument, "configuration must not contain both server id and server id file path") + } + if config.KeyMetadataFile != "" && config.KeyIdentifierFile != "" { + return nil, status.Error(codes.InvalidArgument, "configuration must not contain both `key_identifier_file` and deprecated `key_metadata_file`") + } return config, nil } diff --git a/pkg/server/plugin/keymanager/gcpkms/gcpkms_test.go b/pkg/server/plugin/keymanager/gcpkms/gcpkms_test.go index 1c82304ce22..7929514dee0 100644 --- a/pkg/server/plugin/keymanager/gcpkms/gcpkms_test.go +++ b/pkg/server/plugin/keymanager/gcpkms/gcpkms_test.go @@ -133,7 +133,7 @@ func TestConfigure(t *testing.T) { { name: "pass with keys", config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), KeyRing: validKeyRing, }, fakeCryptoKeys: []*fakeCryptoKey{ @@ -210,14 +210,28 @@ func TestConfigure(t *testing.T) { { name: "pass without keys", config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), KeyRing: validKeyRing, }, }, + { + name: "pass with identity file", + config: &Config{ + KeyIdentifierFile: createKeyIdentifierFile(t, validServerID), + KeyRing: validKeyRing, + }, + }, + { + name: "pass with identity value", + config: &Config{ + KeyIdentifierValue: validServerID, + KeyRing: validKeyRing, + }, + }, { name: "pass without keys - using a service account file", config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), KeyRing: validKeyRing, ServiceAccountFile: "service-account-file", }, @@ -226,7 +240,7 @@ func TestConfigure(t *testing.T) { { name: "missing key ring", config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), }, expectMsg: "configuration is missing the key ring", expectCode: codes.InvalidArgument, @@ -239,10 +253,22 @@ func TestConfigure(t *testing.T) { expectMsg: "configuration requires server id or server id file path", expectCode: codes.InvalidArgument, }, + { + name: "key identifier file and key identifier value", + configureRequest: configureRequestWithString(fmt.Sprintf(`{"access_key_id":"access_key_id","secret_access_key":"secret_access_key","region":"region","key_identifier_file":"key_identifier_file","key_identifier_value":"key_identifier_value","key_policy_file":"","key_ring":"%s"}`, validKeyRing)), + expectMsg: "configuration must not contain both server id and server id file path", + expectCode: codes.InvalidArgument, + }, + { + name: "key metadata file and key identifier file", + configureRequest: configureRequestWithString(fmt.Sprintf(`{"access_key_id":"access_key_id","secret_access_key":"secret_access_key","region":"region","key_metadata_file":"key_metadata_file","key_identifier_file":"key_identifier_file","key_policy_file":"","key_ring":"%s"}`, validKeyRing)), + expectMsg: "configuration must not contain both `key_identifier_file` and deprecated `key_metadata_file`", + expectCode: codes.InvalidArgument, + }, { name: "custom policy file does not exist", config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), KeyPolicyFile: "non-existent-file.json", KeyRing: validKeyRing, }, @@ -252,7 +278,7 @@ func TestConfigure(t *testing.T) { { name: "use custom policy file", config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), KeyPolicyFile: getCustomPolicyFile(t), KeyRing: validKeyRing, }, @@ -260,14 +286,14 @@ func TestConfigure(t *testing.T) { { name: "empty key metadata file", config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, ""), + KeyMetadataFile: createKeyIdentifierFile(t, ""), KeyRing: validKeyRing, }, }, { name: "invalid server ID in metadata file", config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, "invalid-id"), + KeyMetadataFile: createKeyIdentifierFile(t, "invalid-id"), KeyRing: validKeyRing, }, expectMsg: "failed to parse server ID from path: uuid: incorrect UUID length 10 in string \"invalid-id\"", @@ -291,7 +317,7 @@ func TestConfigure(t *testing.T) { { name: "ListCryptoKeys error", config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), KeyRing: validKeyRing, }, expectMsg: "failed to list SPIRE Server keys in Cloud KMS: error listing CryptoKeys", @@ -303,7 +329,7 @@ func TestConfigure(t *testing.T) { expectMsg: "failed to fetch entries: unsupported CryptoKeyVersionAlgorithm: GOOGLE_SYMMETRIC_ENCRYPTION", expectCode: codes.Internal, config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), KeyRing: validKeyRing, }, fakeCryptoKeys: []*fakeCryptoKey{ @@ -331,7 +357,7 @@ func TestConfigure(t *testing.T) { expectMsg: "failed to fetch entries: error getting public key: get public key error", expectCode: codes.Internal, config: &Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), KeyRing: validKeyRing, }, fakeCryptoKeys: []*fakeCryptoKey{ @@ -684,7 +710,7 @@ func TestGenerateKey(t *testing.T) { KeyId: spireKeyID1, KeyType: keymanagerv1.KeyType_EC_P256, }, - configureReq: configureRequestWithVars(createKeyMetadataFile(t, ""), "", validKeyRing, "service_account_file"), + configureReq: configureRequestWithVars(KeyMetadataFile, createKeyIdentifierFile(t, ""), "", validKeyRing, "service_account_file"), }, { name: "success: non existing key with custom policy", @@ -692,7 +718,7 @@ func TestGenerateKey(t *testing.T) { KeyId: spireKeyID1, KeyType: keymanagerv1.KeyType_EC_P256, }, - configureReq: configureRequestWithVars(createKeyMetadataFile(t, ""), getCustomPolicyFile(t), validKeyRing, "service_account_file"), + configureReq: configureRequestWithVars(KeyMetadataFile, createKeyIdentifierFile(t, ""), getCustomPolicyFile(t), validKeyRing, "service_account_file"), }, { name: "success: replace old key", @@ -1413,7 +1439,7 @@ func TestSetIAMPolicy(t *testing.T) { if tt.useCustomPolicy { customPolicyFile := getCustomPolicyFile(t) configureReq = configureRequestFromConfig(&Config{ - KeyMetadataFile: createKeyMetadataFile(t, validServerID), + KeyMetadataFile: createKeyIdentifierFile(t, validServerID), KeyPolicyFile: customPolicyFile, KeyRing: validKeyRing, ServiceAccountFile: "service_account_file", @@ -1662,15 +1688,39 @@ func TestSignData(t *testing.T) { } } +type KeyIdentifierConfigName string + +const ( + KeyMetadataFile KeyIdentifierConfigName = "key_metadata_file" + KeyIdentifierFile KeyIdentifierConfigName = "key_identifier_file" + KeyIdentifierValue KeyIdentifierConfigName = "key_identifier_value" +) + func configureRequestFromConfig(c *Config) *configv1.ConfigureRequest { + keyMetadataFileHcl := fmt.Sprintf(`"key_metadata_file":"%s",`, c.KeyMetadataFile) + if c.KeyMetadataFile == "" { + keyMetadataFileHcl = "" + } + keyIdentifierFileHcl := fmt.Sprintf(`"key_identifier_file":"%s",`, c.KeyIdentifierFile) + if c.KeyIdentifierFile == "" { + keyIdentifierFileHcl = "" + } + keyIdentifierValueHcl := fmt.Sprintf(`"key_identifier_value":"%s",`, c.KeyIdentifierValue) + if c.KeyIdentifierValue == "" { + keyIdentifierValueHcl = "" + } return &configv1.ConfigureRequest{ HclConfiguration: fmt.Sprintf(`{ - "key_metadata_file":"%s", + %s + %s + %s "key_policy_file":"%s", "key_ring":"%s", "service_account_file":"%s" }`, - c.KeyMetadataFile, + keyMetadataFileHcl, + keyIdentifierFileHcl, + keyIdentifierValueHcl, c.KeyPolicyFile, c.KeyRing, c.ServiceAccountFile), @@ -1680,7 +1730,7 @@ func configureRequestFromConfig(c *Config) *configv1.ConfigureRequest { func configureRequestWithDefaults(t *testing.T) *configv1.ConfigureRequest { return &configv1.ConfigureRequest{ - HclConfiguration: serializedConfiguration(createKeyMetadataFile(t, validServerID), validKeyRing), + HclConfiguration: serializedConfiguration(KeyMetadataFile, createKeyIdentifierFile(t, validServerID), validKeyRing), CoreConfiguration: &configv1.CoreConfiguration{TrustDomain: "test.example.org"}, } } @@ -1691,15 +1741,16 @@ func configureRequestWithString(config string) *configv1.ConfigureRequest { } } -func configureRequestWithVars(keyMetadataFile, keyPolicyFile, keyRing, serviceAccountFile string) *configv1.ConfigureRequest { +func configureRequestWithVars(keyIdentifierConfigName KeyIdentifierConfigName, keyIdentifierConfigValue, keyPolicyFile, keyRing, serviceAccountFile string) *configv1.ConfigureRequest { return &configv1.ConfigureRequest{ HclConfiguration: fmt.Sprintf(`{ - "key_metadata_file":"%s", + "%s":"%s", "key_policy_file":"%s", "key_ring":"%s" "service_account_file":"%s" }`, - keyMetadataFile, + keyIdentifierConfigName, + keyIdentifierConfigValue, keyPolicyFile, keyRing, serviceAccountFile), @@ -1707,7 +1758,7 @@ func configureRequestWithVars(keyMetadataFile, keyPolicyFile, keyRing, serviceAc } } -func createKeyMetadataFile(t *testing.T, content string) string { +func createKeyIdentifierFile(t *testing.T, content string) string { tempDir := t.TempDir() tempFilePath := filepath.ToSlash(filepath.Join(tempDir, validServerIDFile)) @@ -1730,12 +1781,13 @@ func getCustomPolicyFile(t *testing.T) string { return tempFilePath } -func serializedConfiguration(keyMetadataFile, keyRing string) string { +func serializedConfiguration(keyIdentifierConfigName KeyIdentifierConfigName, keyIdentifierConfigValue, keyRing string) string { return fmt.Sprintf(`{ - "key_metadata_file":"%s", + "%s":"%s", "key_ring":"%s" }`, - keyMetadataFile, + keyIdentifierConfigName, + keyIdentifierConfigValue, keyRing) }