From f81fd250372e5d9659e2a4bee9e7cb3c620d20ca Mon Sep 17 00:00:00 2001 From: Aliaksei Sarychau Date: Thu, 30 Mar 2023 16:39:14 +0300 Subject: [PATCH 1/2] artifactory auth for latest url and checksum --- REFERENCE.md | 16 ++++++++++++++-- .../functions/archive/artifactory_checksum.rb | 8 ++++++-- .../functions/archive/artifactory_latest_url.rb | 12 ++++++++---- lib/puppet_x/bodeco/util.rb | 5 +++++ manifests/artifactory.pp | 4 ++-- spec/defines/artifactory_spec.rb | 2 +- spec/functions/artifactory_checksum_spec.rb | 10 ++++++++-- 7 files changed, 44 insertions(+), 13 deletions(-) diff --git a/REFERENCE.md b/REFERENCE.md index 4c026b6c..8431e5ff 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -1094,7 +1094,7 @@ Type: Ruby 4.x API A function that returns the checksum value of an artifact stored in Artifactory -#### `archive::artifactory_checksum(Stdlib::HTTPUrl $url, Optional[Enum['sha1','sha256','md5']] $checksum_type)` +#### `archive::artifactory_checksum(Stdlib::HTTPUrl $url, Optional[Enum['sha1','sha256','md5']] $checksum_type, Optional[Array] $headers)` The archive::artifactory_checksum function. @@ -1113,13 +1113,19 @@ Data type: `Optional[Enum['sha1','sha256','md5']]` The checksum type. Note the function will raise an error if you ask for sha256 but your artifactory instance doesn't have the sha256 value calculated. +##### `headers` + +Data type: `Optional[Array]` + +Array of headers to pass source, like an authentication token + ### `archive::artifactory_latest_url` Type: Ruby 4.x API The archive::artifactory_latest_url function. -#### `archive::artifactory_latest_url(Variant[Stdlib::HTTPUrl, Stdlib::HTTPSUrl] $url, Hash $maven_data)` +#### `archive::artifactory_latest_url(Variant[Stdlib::HTTPUrl, Stdlib::HTTPSUrl] $url, Hash $maven_data, Optional[Array ] $headers)` The archive::artifactory_latest_url function. @@ -1137,6 +1143,12 @@ Data type: `Hash` +##### `headers` + +Data type: `Optional[Array ]` + + + ### `archive::parse_artifactory_url` Type: Ruby 4.x API diff --git a/lib/puppet/functions/archive/artifactory_checksum.rb b/lib/puppet/functions/archive/artifactory_checksum.rb index ff699619..46a9560d 100644 --- a/lib/puppet/functions/archive/artifactory_checksum.rb +++ b/lib/puppet/functions/archive/artifactory_checksum.rb @@ -8,17 +8,21 @@ # @param url The URL of the artifact. # @param checksum_type The checksum type. # Note the function will raise an error if you ask for sha256 but your artifactory instance doesn't have the sha256 value calculated. + # @param headers Array of headers to pass source, like an authentication token # @return [String] Returns the checksum. dispatch :artifactory_checksum do param 'Stdlib::HTTPUrl', :url optional_param "Enum['sha1','sha256','md5']", :checksum_type + optional_param 'Array', :headers return_type 'String' end - def artifactory_checksum(url, checksum_type = 'sha1') + def artifactory_checksum(url, checksum_type = 'sha1', headers = []) uri = URI(url.sub('/artifactory/', '/artifactory/api/storage/')) - response = PuppetX::Bodeco::Util.content(uri) + options = {} + options[:headers] = headers if headers != [] + response = PuppetX::Bodeco::Util.content(uri, options) content = JSON.parse(response) checksum = content['checksums'] && content['checksums'][checksum_type] diff --git a/lib/puppet/functions/archive/artifactory_latest_url.rb b/lib/puppet/functions/archive/artifactory_latest_url.rb index b5e04e5e..f5dc4bce 100644 --- a/lib/puppet/functions/archive/artifactory_latest_url.rb +++ b/lib/puppet/functions/archive/artifactory_latest_url.rb @@ -7,13 +7,17 @@ dispatch :artifactory_latest_url do param 'Variant[Stdlib::HTTPUrl, Stdlib::HTTPSUrl]', :url param 'Hash', :maven_data + optional_param 'Array ', :headers end - def artifactory_latest_url(url, maven_data) - # Turn provided artifactory URL into the fileinfo API endpoint of the parent directory + def artifactory_latest_url(url, maven_data, headers = []) + # Turn provided artifactory URL into the fileinfo API endpoint of the parent directory. uri = URI(url.sub('/artifactory/', '/artifactory/api/storage/')[%r{^(.*)/.*$}, 1]) - response = PuppetX::Bodeco::Util.content(uri) + options = {} + options[:headers] = headers if headers != [] + + response = PuppetX::Bodeco::Util.content(uri, options) content = JSON.parse(response) uris = if maven_data['classifier'] @@ -33,7 +37,7 @@ def artifactory_latest_url(url, maven_data) # Now GET the fileinfo endpoint of the resolved latest version file uri = URI("#{content['uri']}#{latest}") - response = PuppetX::Bodeco::Util.content(uri) + response = PuppetX::Bodeco::Util.content(uri, options) content = JSON.parse(response) url = content['downloadUri'] diff --git a/lib/puppet_x/bodeco/util.rb b/lib/puppet_x/bodeco/util.rb index e6d04f88..fb040bd1 100644 --- a/lib/puppet_x/bodeco/util.rb +++ b/lib/puppet_x/bodeco/util.rb @@ -72,6 +72,7 @@ def initialize(_url, options) @password = options[:password] @cookie = options[:cookie] @insecure = options[:insecure] + @headers = options[:headers].nil? ? [] : options[:headers] if options[:proxy_server] uri = URI(options[:proxy_server]) @@ -87,6 +88,10 @@ def generate_request(uri) header = @cookie && { 'Cookie' => @cookie } request = Net::HTTP::Get.new(uri.request_uri, header) + @headers.each do |h| + h_split = h.split(':') + request[h_split[0].strip] = h_split[1].strip if h_split.length == 2 + end request.basic_auth(@username, @password) if @username && @password request end diff --git a/manifests/artifactory.pp b/manifests/artifactory.pp index 3649bc06..9c74bc8f 100644 --- a/manifests/artifactory.pp +++ b/manifests/artifactory.pp @@ -84,13 +84,13 @@ # Only Artifactory Pro downloads this directly but the corresponding file endpoint (where the sha1 checksum is published) doesn't exist # This means we can't use the artifactory_sha1 function - $latest_url_data = archive::artifactory_latest_url($url, $maven2_data) + $latest_url_data = archive::artifactory_latest_url($url, $maven2_data, $headers) $file_url = $latest_url_data['url'] $sha1 = $latest_url_data['sha1'] } else { $file_url = $url - $sha1 = archive::artifactory_checksum($url,'sha1') + $sha1 = archive::artifactory_checksum($url,'sha1', $headers) } archive { $file_path: diff --git a/spec/defines/artifactory_spec.rb b/spec/defines/artifactory_spec.rb index 2c3f3ed2..2c84f4dc 100644 --- a/spec/defines/artifactory_spec.rb +++ b/spec/defines/artifactory_spec.rb @@ -7,7 +7,7 @@ # Mock Puppet V4 API ruby function with a puppet language function equivalent let(:pre_condition) do - 'function archive::artifactory_checksum($url,$type) { return \'0d4f4b4b039c10917cfc49f6f6be71e4\' }' + 'function archive::artifactory_checksum($url,$type,$headers) { return \'0d4f4b4b039c10917cfc49f6f6be71e4\' }' end context 'artifactory archive with defaults' do diff --git a/spec/functions/artifactory_checksum_spec.rb b/spec/functions/artifactory_checksum_spec.rb index 3fc89645..6afd0fd0 100644 --- a/spec/functions/artifactory_checksum_spec.rb +++ b/spec/functions/artifactory_checksum_spec.rb @@ -6,18 +6,24 @@ let(:example_json) { File.read(fixtures('checksum', 'artifactory.json')) } let(:url) { 'https://repo.jfrog.org/artifactory/distributions/images/Artifactory_120x75.png' } let(:uri) { URI(url.sub('/artifactory/', '/artifactory/api/storage/')) } + let(:headers) { ['X-JFrog-Art-Api: ABC123'] } it { is_expected.not_to be_nil } it { is_expected.to run.with_params.and_raise_error(ArgumentError) } it { is_expected.to run.with_params('not_a_url').and_raise_error(ArgumentError) } it 'defaults to and parses sha1' do - allow(PuppetX::Bodeco::Util).to receive(:content).with(uri).and_return(example_json) + allow(PuppetX::Bodeco::Util).to receive(:content).with(uri, {}).and_return(example_json) expect(subject).to run.with_params(url).and_return('a359e93636e81f9dd844b2dfb4b89fa876e5d4fa') end it 'parses md5' do - allow(PuppetX::Bodeco::Util).to receive(:content).with(uri).and_return(example_json) + allow(PuppetX::Bodeco::Util).to receive(:content).with(uri, {}).and_return(example_json) expect(subject).to run.with_params(url, 'md5').and_return('00f32568be85929fe95be38f9f5f3519') end + + it 'uses auth headers' do + allow(PuppetX::Bodeco::Util).to receive(:content).with(uri, { headers: headers }).and_return(example_json) + expect(subject).to run.with_params(url, 'sha1', headers).and_return('a359e93636e81f9dd844b2dfb4b89fa876e5d4fa') + end end From 6149f5a3cf66f9592430cdcd35eb453f398d373d Mon Sep 17 00:00:00 2001 From: Alexei Sarychev Date: Mon, 17 Apr 2023 09:25:20 +0300 Subject: [PATCH 2/2] Update lib/puppet_x/bodeco/util.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Romain Tartière --- lib/puppet_x/bodeco/util.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet_x/bodeco/util.rb b/lib/puppet_x/bodeco/util.rb index fb040bd1..46b4c126 100644 --- a/lib/puppet_x/bodeco/util.rb +++ b/lib/puppet_x/bodeco/util.rb @@ -89,7 +89,7 @@ def generate_request(uri) request = Net::HTTP::Get.new(uri.request_uri, header) @headers.each do |h| - h_split = h.split(':') + h_split = h.split(':', 2) request[h_split[0].strip] = h_split[1].strip if h_split.length == 2 end request.basic_auth(@username, @password) if @username && @password