diff options
Diffstat (limited to 'lib/chef/secret_fetcher/hashi_vault.rb')
-rw-r--r-- | lib/chef/secret_fetcher/hashi_vault.rb | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/lib/chef/secret_fetcher/hashi_vault.rb b/lib/chef/secret_fetcher/hashi_vault.rb index be975fc34f..89dce01b67 100644 --- a/lib/chef/secret_fetcher/hashi_vault.rb +++ b/lib/chef/secret_fetcher/hashi_vault.rb @@ -19,7 +19,6 @@ require_relative "base" require "aws-sdk-core" # Support for aws instance profile auth require "vault" - class Chef class SecretFetcher # == Chef::SecretFetcher::HashiVault @@ -29,32 +28,74 @@ class Chef # In this initial iteration the only supported authentication is IAM role-based # # Required config: + # :auth_method - one of :iam_role, :token. default: :iam_role # :vault_addr - the address of a running Vault instance, eg https://vault.example.com:8200 - # If not explicitly provided, the environment variable VAULT_ADDR will be used. - # :role_name - the name of the role in Vault that was created to support authentication - # via IAM. See the Vault documentation for details[1]. A Terraform example is also available[2] + # + # For `:token` auth: `:token` - a Vault token valid for authentication. + # + # For `:iam_role`: `:role_name` - the name of the role in Vault that was created + # to support authentication via IAM. See the Vault documentation for details[1]. + # A Terraform example is also available[2] + # # # [1] https://www.vaultproject.io/docs/auth/aws#recommended-vault-iam-policy # [2] https://registry.terraform.io/modules/hashicorp/vault/aws/latest/examples/vault-iam-auth # an IAM principal ARN bound to it. # + # Optional config + # :namespace - the namespace under which secrets are kept. Only supported in with Vault Enterprise + # # @example # # fetcher = SecretFetcher.for_service(:hashi_vault, { role_name: "testing-role", vault_addr: https://localhost:8200}, run_context ) # fetcher.fetch("secretkey1") + # + # @example + # + # fetcher = SecretFetcher.for_service(:hashi_vault, { auth_method: :token, token: "s.1234abcdef", vault_addr: https://localhost:8200}, run_context ) + # fetcher.fetch("secretkey1") + SUPPORTED_AUTH_TYPES = %i{iam_role token}.freeze class HashiVault < Base + + # Validate and authenticate the current session using the configurated auth strategy and parameters def validate! - if config[:role_name].nil? - raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide the authenticating Vault role name in the configuration as :role_name ") - end if config[:vault_addr].nil? raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide the Vault address in the configuration as :vault_addr") end - # Note that the token here is cached internal to the Vault implementation. - Vault.auth.aws_iam(config[:role_name], - Aws::InstanceProfileCredentials.new, - config[:vault_addr] || ENV["VAULT_ADDR"]) + Vault.address = config[:vault_addr] + Vault.namespace = config[:namespace] unless config[:namespace].nil? + + case config[:auth_method] + when :token + validate_token_auth!(config[:token]) + when :iam_role, nil + validate_iam_role_auth!(config[:role_name]) + else + raise Chef::Exceptions::Secret::ConfigurationInvalid.new("Invalid :auth_method provided. You gave #{config[:auth_method]}, expected one of :#{SUPPORTED_AUTH_TYPES.join(", :")} ") + end + end + + # Validates IAM role auth configuration and obtains token via IAM auth + # + # @param role_name [String] the name of the Vault role associated with the IAM profile . + def validate_iam_role_auth!(role_name) + if role_name.nil? + raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide the authenticating Vault role name in the configuration as :role_name") + end + + Vault.auth.aws_iam(role_name, Aws::InstanceProfileCredentials.new) + end + + # Validates that a token is provided and authenticates to Hashi Vault using the provided + # token. + # @param token [String] a value Vault token authorized to access the secrets needed. b + def validate_token_auth!(token) + if token.nil? + raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide the token in the configuration as :token") + end + + Vault.auth.token(token) end # @param identifier [String] Identifier of the secret to be fetched, which should |