Puppet Function: conjur::secret
- Defined in:
- lib/puppet/functions/conjur/secret.rb
- Function type:
- Ruby 4.x API
Overview
Function to retrieve a Conjur / DAP secret
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/puppet/functions/conjur/secret.rb', line 8 Puppet::Functions.create_function :'conjur::secret' do # @param variable_id Conjur / DAP variable ID that you want the value of. # @param options Optional parameter specifying server identity overrides # The following keys are supported in the options hash: # - appliance_url: The URL of the Conjur or DAP instance.. # - account: Name of the Conjur account that contains this variable. # - authn_login: The identity you are using to authenticate to the Conjur / DAP instance. # - authn_api_key: The API key of the identity you are using to authenticate with (must be Sensitive type). # - cert_file: The absolute path to CA certificate chain for the DAP instance on the agent. This variable overrides `ssl_certificate`. # - ssl_certificate: The _raw_ PEM-encoded x509 CA certificate chain for the DAP instance. Overwritten by the contents read from `cert_file` when it is present. # - version: Conjur API version, defaults to 5. # @return [Sensitive] Value of the Conjur variable. # @example Agent-based identity invocation # Deferred(conjur::secret, ['production/postgres/password']) # @example Server-based identity invocation # $sslcert = @("EOT") # -----BEGIN CERTIFICATE----- # ... # -----END CERTIFICATE----- # |-EOT # # $dbpass = Deferred(conjur::secret, ['production/postgres/password', { # appliance_url => "https://my.conjur.org", # account => "myaccount", # authn_login => "host/myhost", # authn_api_key => Sensitive("2z9mndg1950gcx1mcrs6w18bwnp028dqkmc34vj8gh2p500ny1qk8n"), # ssl_certificate => $sslcert # }]) dispatch :with_credentials do required_param 'String', :variable_id optional_param 'Hash', :options return_type 'Sensitive' end def authentication_path(account, login) ['authn', account, login, 'authenticate'] .map(&URI.method(:encode_www_form_component)).join('/') end # Authenticates against a Conjur / DAP server returning the API token def authenticate(url, ssl_certificate, account, authn_login, authn_api_key) Conjur::PuppetModule::HTTP.post( url, authentication_path(account, authn_login), ssl_certificate, authn_api_key.unwrap, ) end # Fetches a variable from Conjur / DAP def get_variable(url, ssl_certificate, account, variable_id, token) secrets_path = [ 'secrets', URI.encode_www_form_component(account), 'variable', ERB::Util.url_encode(variable_id), ].join('/') Conjur::PuppetModule::HTTP.get( url, secrets_path, ssl_certificate, token, ) end def with_credentials(id, = {}) # If we got an options hash, it may be frozen so we make a copy that is not since # we will be modifying it opts = .dup if opts['authn_api_key'] raise "Value of 'authn_api_key' must be wrapped in 'Sensitive()'!" \ unless opts['authn_api_key'].is_a? Puppet::Pops::Types::PSensitiveType::Sensitive end opts['version'] ||= 5 # If we didn't get any config from the server, assume it's on the agent if opts['appliance_url'].nil? || opts['appliance_url'].empty? config = Conjur::PuppetModule::Config.load raise 'Conjur configuration not found on system' if config.empty? creds = Conjur::PuppetModule::Identity.load(config) raise 'Conjur identity not found on system' unless creds # Overwrite values in the options hash with the ones from the agent. We may at # some point want to support partial overwrite of only the set values. ['appliance_url', 'account', 'ssl_certificate', 'version'].each do |key| opts[key] = config[key] end opts['authn_login'], authn_api_key = creds opts['authn_api_key'] = Puppet::Pops::Types::PSensitiveType::Sensitive.new(authn_api_key) end # If cert_file is set, use it to override ssl_certificate if opts['cert_file'] raise "Cert file '#{opts['cert_file']}' cannot be found!" unless File.file?(opts['cert_file']) opts['ssl_certificate'] = File.read opts['cert_file'] end Puppet.debug('Instantiating Conjur client...') Puppet.debug('Fetching Conjur token') token = authenticate(opts['appliance_url'], opts['ssl_certificate'], opts['account'], opts['authn_login'], opts['authn_api_key']) Puppet.info('Conjur token retrieved') Puppet.debug("Fetching Conjur secret '#{id}'...") secret = get_variable(opts['appliance_url'], opts['ssl_certificate'], opts['account'], id, token) Puppet.info("Conjur secret #{id} retrieved") Puppet::Pops::Types::PSensitiveType::Sensitive.new(secret) end end |