/usr/lib/ruby/vendor_ruby/octocatalog-diff/catalog/puppetmaster.rb is in octocatalog-diff 1.5.3-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 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 125 126 127 128 | # frozen_string_literal: true
require_relative '../catalog'
require_relative '../catalog-util/facts'
require_relative '../external/pson/pure'
require_relative '../util/httparty'
require 'json'
require 'securerandom'
require 'stringio'
module OctocatalogDiff
class Catalog
# Represents a Puppet catalog that is obtained by contacting the Puppet Master.
class PuppetMaster < OctocatalogDiff::Catalog
# Defaults
DEFAULT_PUPPET_PORT_NUMBER = 8140
DEFAULT_PUPPET_SERVER_API = 3
PUPPET_MASTER_TIMEOUT = 60
# Constructor
# @param :node [String] Node name
# @param :retry_failed_catalog [Integer] Number of retries, if fetch fails
# @param :branch [String] Environment to fetch from Puppet Master
# @param :puppet_master [String] Puppet server and port number (assumed to be DEFAULT_PUPPET_PORT_NUMBER if not given)
# @param :puppet_master_api_version [Integer] Puppet server API (default DEFAULT_PUPPET_SERVER_API)
# @param :puppet_master_ssl_ca [String] Path to file used to sign puppet master's certificate
# @param :puppet_master_ssl_verify [Boolean] Override the CA verification setting guessed from parameters
# @param :puppet_master_ssl_client_pem [String] PEM-encoded client key and certificate
# @param :puppet_master_ssl_client_p12 [String] pkcs12-encoded client key and certificate
# @param :puppet_master_ssl_client_password [String] Path to file containing password for SSL client key (any format)
# @param :puppet_master_ssl_client_auth [Boolean] Override the client-auth that is guessed from parameters
# @param :timeout [Integer] Connection timeout for Puppet master (default=PUPPET_MASTER_TIMEOUT seconds)
def initialize(options)
super
unless @options[:node].is_a?(String) && @options[:node] != ''
raise ArgumentError, 'node must be a non-empty string'
end
unless @options[:branch].is_a?(String) && @options[:branch] != ''
raise ArgumentError, 'Environment must be a non-empty string'
end
unless @options[:puppet_master].is_a?(String) && @options[:puppet_master] != ''
raise ArgumentError, 'Puppet Master must be a non-empty string'
end
@timeout = options.fetch(:puppet_master_timeout, options.fetch(:timeout, PUPPET_MASTER_TIMEOUT))
@retry_failed_catalog = options.fetch(:retry_failed_catalog, 0)
@options[:puppet_master] += ":#{DEFAULT_PUPPET_PORT_NUMBER}" unless @options[:puppet_master] =~ /\:\d+$/
end
private
# Build method
def build_catalog(logger = Logger.new(StringIO.new))
facts_obj = OctocatalogDiff::CatalogUtil::Facts.new(@options, logger)
logger.debug "Start retrieving facts for #{@node} from #{self.class}"
@facts = facts_obj.facts
logger.debug "Success retrieving facts for #{@node} from #{self.class}"
fetch_catalog(logger)
end
# Returns a hash of parameters for each supported version of the Puppet Server Catalog API.
# @return [Hash] Hash of parameters
#
# Note: The double escaping of the facts here is implemented to correspond to a long standing
# bug in the Puppet code. See https://github.com/puppetlabs/puppet/pull/1818 and
# https://docs.puppet.com/puppet/latest/http_api/http_catalog.html#parameters for explanation.
def puppet_catalog_api
{
2 => {
url: "https://#{@options[:puppet_master]}/#{@options[:branch]}/catalog/#{@node}",
parameters: {
'facts_format' => 'pson',
'facts' => CGI.escape(@facts.fudge_timestamp.without('trusted').to_pson),
'transaction_uuid' => SecureRandom.uuid
}
},
3 => {
url: "https://#{@options[:puppet_master]}/puppet/v3/catalog/#{@node}",
parameters: {
'environment' => @options[:branch],
'facts_format' => 'pson',
'facts' => CGI.escape(@facts.fudge_timestamp.without('trusted').to_pson),
'transaction_uuid' => SecureRandom.uuid
}
}
}
end
# Fetch catalog by contacting the Puppet master, sending the facts, and asking for the catalog. When the
# catalog is returned in PSON format, parse it to JSON and then set appropriate variables.
def fetch_catalog(logger)
api_version = @options[:puppet_master_api_version] || DEFAULT_PUPPET_SERVER_API
api = puppet_catalog_api[api_version]
raise ArgumentError, "Unsupported or invalid API version #{api_version}" unless api.is_a?(Hash)
more_options = { headers: { 'Accept' => 'text/pson' }, timeout: @timeout }
post_hash = api[:parameters]
response = nil
0.upto(@retry_failed_catalog) do |retry_num|
@retries = retry_num
logger.debug "Retrieve catalog from #{api[:url]} environment #{@options[:branch]}"
response = OctocatalogDiff::Util::HTTParty.post(api[:url], @options.merge(more_options), post_hash, 'puppet_master')
logger.debug "Response from #{api[:url]} environment #{@options[:branch]} was #{response[:code]}"
break if response[:code] == 200
end
unless response[:code] == 200
@error_message = "Failed to retrieve catalog from #{api[:url]}: #{response[:code]} #{response[:body]}"
@catalog = nil
@catalog_json = nil
return
end
@catalog = response[:parsed]
@catalog_json = ::JSON.generate(@catalog)
@error_message = nil
end
end
end
end
|