# # Author:: Marc Paradise () # Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require_relative "base" require "aws-sdk-core" require "aws-sdk-secretsmanager" class Chef # == Chef::SecretFetcher::AWSSecretsManager # A fetcher that fetches a secret from AWS Secrets Manager # In this initial iteration it defaults to authentication via instance profile. # It is possible to pass options that configure it to use alternative credentials. # This implementation supports fetching with version. # # @note ':region' is required configuration. If it is not explicitly provided, # and it is not available via global AWS config, we will pull it from node ohai data by default. # If this isn't correct, you will need to explicitly override it. # If it is not available via ohai data either (such as if you have the AWS plugin disabled) # then the converge will fail with an error. # # @note: This does not yet support automatic retries, which the AWS client does by default. # # For configuration options see https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/SecretsManager/Client.html#initialize-instance_method # # # Usage Example: # # fetcher = SecretFetcher.for_service(:aws_secrets_manager) # fetcher.fetch("secretkey1", "v1") class SecretFetcher class AWSSecretsManager < Base def validate! config[:region] = config[:region] || Aws.config[:region] || run_context.node.dig("ec2", "region") if config[:region].nil? raise Chef::Exceptions::Secret::ConfigurationInvalid.new("Missing required config for AWS secret fetcher: :region") end end # @param identifier [String] the secret_id # @param version [String] the secret version. # @return Aws::SecretsManager::Types::GetSecretValueResponse def do_fetch(identifier, version) client = Aws::SecretsManager::Client.new(config) result = client.get_secret_value(secret_id: identifier, version_stage: version) # These fields are mutually exclusive result.secret_string || result.secret_binary end end end end