From 22f17020d4c397b4f74403faeac9ce9742f5b254 Mon Sep 17 00:00:00 2001 From: Keegan Witt Date: Tue, 28 Nov 2023 18:40:43 -0500 Subject: [PATCH] Remove KMS requiring metadata files (closes #4375) Signed-off-by: Keegan Witt --- doc/plugin_server_keymanager_aws_kms.md | 15 ++++++++------- ...lugin_server_keymanager_azure_key_vault.md | 19 ++++++++++--------- doc/plugin_server_keymanager_gcp_kms.md | 13 +++++++------ pkg/server/plugin/keymanager/awskms/awskms.go | 18 +++++++++++------- .../plugin/keymanager/awskms/awskms_test.go | 4 ++-- .../azurekeyvault/azure_key_vault.go | 16 ++++++++++------ .../azurekeyvault/azure_key_vault_test.go | 4 ++-- pkg/server/plugin/keymanager/gcpkms/gcpkms.go | 19 +++++++++++++------ .../plugin/keymanager/gcpkms/gcpkms_test.go | 2 +- 9 files changed, 64 insertions(+), 46 deletions(-) diff --git a/doc/plugin_server_keymanager_aws_kms.md b/doc/plugin_server_keymanager_aws_kms.md index d76086e4323..6b44024a45a 100644 --- a/doc/plugin_server_keymanager_aws_kms.md +++ b/doc/plugin_server_keymanager_aws_kms.md @@ -6,13 +6,14 @@ 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_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 | | +| 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 | "" | ### 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 464e03b4885..0909da0c139 100644 --- a/doc/plugin_server_keymanager_azure_key_vault.md +++ b/doc/plugin_server_keymanager_azure_key_vault.md @@ -10,15 +10,16 @@ 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_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. See "[Management of keys](#management-of-keys)" for more information. | "" | +| key_metadata_file | 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 diff --git a/doc/plugin_server_keymanager_gcp_kms.md b/doc/plugin_server_keymanager_gcp_kms.md index da2e9fa673f..a8e560bcb5c 100644 --- a/doc/plugin_server_keymanager_gcp_kms.md +++ b/doc/plugin_server_keymanager_gcp_kms.md @@ -10,12 +10,13 @@ SPIRE. 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_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. | +| 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_file | 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. | ### Authenticating with the Cloud KMS API diff --git a/pkg/server/plugin/keymanager/awskms/awskms.go b/pkg/server/plugin/keymanager/awskms/awskms.go index b10484b4df5..d2fbc51cab9 100644 --- a/pkg/server/plugin/keymanager/awskms/awskms.go +++ b/pkg/server/plugin/keymanager/awskms/awskms.go @@ -96,6 +96,7 @@ type Config struct { 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"` } @@ -131,11 +132,14 @@ func (p *Plugin) Configure(ctx context.Context, req *configv1.ConfigureRequest) return nil, err } - serverID, err := loadServerID(config.KeyMetadataFile) - if err != nil { - return nil, err + var serverID = config.KeyMetadata + if config.KeyMetadata == "" { + 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 config.KeyPolicyFile != "" { policyBytes, err := os.ReadFile(config.KeyPolicyFile) @@ -832,8 +836,8 @@ func parseAndValidateConfig(c string) (*Config, error) { return nil, status.Error(codes.InvalidArgument, "configuration is missing a region") } - if config.KeyMetadataFile == "" { - return nil, status.Error(codes.InvalidArgument, "configuration is missing server id file path") + if config.KeyMetadataFile == "" && config.KeyMetadata == "" { + return nil, status.Error(codes.InvalidArgument, "configuration requires server id or server id file path") } return config, nil @@ -923,7 +927,7 @@ func min(x, y time.Duration) time.Duration { return y } -func loadServerID(idPath string) (string, error) { +func getOrCreateServerID(idPath string) (string, error) { // get id from path data, err := os.ReadFile(idPath) switch { diff --git a/pkg/server/plugin/keymanager/awskms/awskms_test.go b/pkg/server/plugin/keymanager/awskms/awskms_test.go index a74bf818a07..2e55fbdeeb1 100644 --- a/pkg/server/plugin/keymanager/awskms/awskms_test.go +++ b/pkg/server/plugin/keymanager/awskms/awskms_test.go @@ -91,7 +91,7 @@ func TestKeyManagerContract(t *testing.T) { func(aws.Config) (stsClient, error) { return fakeSTSClient, nil }, ) km := new(keymanager.V1) - keyMetadataFile := filepath.Join(dir, "metadata.json") + keyMetadataFile := filepath.Join(dir, "metadata") if isWindows { keyMetadataFile = filepath.ToSlash(keyMetadataFile) } @@ -226,7 +226,7 @@ func TestConfigure(t *testing.T) { { name: "missing server id file path", configureRequest: configureRequestWithVars("access_key_id", "secret_access_key", "region", "", ""), - err: "configuration is missing server id file path", + err: "configuration requires server id or server id file path", code: codes.InvalidArgument, }, { diff --git a/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault.go b/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault.go index 7c76ad3d882..d2465524ee2 100644 --- a/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault.go +++ b/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault.go @@ -78,6 +78,7 @@ 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"` @@ -139,11 +140,14 @@ func (p *Plugin) Configure(ctx context.Context, req *configv1.ConfigureRequest) return nil, err } - serverID, err := getOrCreateServerID(config.KeyMetadataFile) - if err != nil { - return nil, err + var serverID = config.KeyMetadata + if config.KeyMetadata == "" { + 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) var client cloudKeyManagementService @@ -685,8 +689,8 @@ func parseAndValidateConfig(c string) (*Config, error) { return nil, status.Error(codes.InvalidArgument, "configuration is missing the Key Vault URI") } - if config.KeyMetadataFile == "" { - return nil, status.Error(codes.InvalidArgument, "configuration is missing server ID file path") + if config.KeyMetadataFile == "" && config.KeyMetadata == "" { + return nil, status.Error(codes.InvalidArgument, "configuration requires server id or server id file path") } 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 04f031ff665..585adcc22b3 100644 --- a/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault_test.go +++ b/pkg/server/plugin/keymanager/azurekeyvault/azure_key_vault_test.go @@ -115,7 +115,7 @@ func TestConfigure(t *testing.T) { { name: "missing key metadata file", configureRequest: configureRequestWithVars("", validKeyVaultURI, "", "", "", validAppSecret, "true"), - err: "configuration is missing server ID file path", + err: "configuration requires server id or server id file path", code: codes.InvalidArgument, }, { @@ -149,7 +149,7 @@ func TestConfigure(t *testing.T) { { name: "missing server id file path", configureRequest: configureRequestWithVars("", validKeyVaultURI, validTenantID, validSubscriptionID, validAppID, validAppSecret, "false"), - err: "configuration is missing server ID file path", + err: "configuration requires server id or server id file path", code: codes.InvalidArgument, }, { diff --git a/pkg/server/plugin/keymanager/gcpkms/gcpkms.go b/pkg/server/plugin/keymanager/gcpkms/gcpkms.go index 69b921aeb54..3c8c88eef84 100644 --- a/pkg/server/plugin/keymanager/gcpkms/gcpkms.go +++ b/pkg/server/plugin/keymanager/gcpkms/gcpkms.go @@ -119,6 +119,9 @@ 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"` + // Key metadata used by the plugin. + KeyMetadata string `hcl:"key_metadata" json:"key_metadata"` + // File path location to a custom IAM Policy (v3) that will be set to // created CryptoKeys. KeyPolicyFile string `hcl:"key_policy_file" json:"key_policy_file"` @@ -167,11 +170,15 @@ func (p *Plugin) Configure(ctx context.Context, req *configv1.ConfigureRequest) return nil, err } - serverID, err := getOrCreateServerID(config.KeyMetadataFile) - if err != nil { - return nil, err + var serverID = config.KeyMetadata + if config.KeyMetadata == "" { + 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) + var customPolicy *iam.Policy3 if config.KeyPolicyFile != "" { if customPolicy, err = parsePolicyFile(config.KeyPolicyFile); err != nil { @@ -1103,8 +1110,8 @@ func parseAndValidateConfig(c string) (*Config, error) { return nil, status.Error(codes.InvalidArgument, "configuration is missing the key ring") } - if config.KeyMetadataFile == "" { - return nil, status.Error(codes.InvalidArgument, "configuration is missing server ID file path") + if config.KeyMetadataFile == "" && config.KeyMetadata == "" { + return nil, status.Error(codes.InvalidArgument, "configuration requires server id or server id file path") } return config, nil diff --git a/pkg/server/plugin/keymanager/gcpkms/gcpkms_test.go b/pkg/server/plugin/keymanager/gcpkms/gcpkms_test.go index 4be5f0e5aa5..1c82304ce22 100644 --- a/pkg/server/plugin/keymanager/gcpkms/gcpkms_test.go +++ b/pkg/server/plugin/keymanager/gcpkms/gcpkms_test.go @@ -236,7 +236,7 @@ func TestConfigure(t *testing.T) { config: &Config{ KeyRing: validKeyRing, }, - expectMsg: "configuration is missing server ID file path", + expectMsg: "configuration requires server id or server id file path", expectCode: codes.InvalidArgument, }, {