diff --git a/lib/puppet/parser/functions/oracle_sso.rb b/lib/puppet/parser/functions/oracle_sso.rb new file mode 100644 index 0000000..5679de7 --- /dev/null +++ b/lib/puppet/parser/functions/oracle_sso.rb @@ -0,0 +1,92 @@ +module Puppet::Parser::Functions + require 'puppet_x/util.rb' + + newfunction(:oracle_sso, :type => :rvalue) do |args| + fileuri = args[0] + ssousername = args[1] + password = args[2] + + cookies = ['oraclelicense=accept-securebackup-cookie'] + auth_required = false + + # + # Step 1: try unauthenticated download from given URI + # Success: URI contains AuthParam parameter and HEAD request returns 200 + # Failure: 404 or redirect to Oracle SSO + # + + begin + response, _ = PuppetX::Util.request(fileuri, 'HEAD', cookies) + if response.uri.host == 'login.oracle.com' + debug("Authentication required for #{fileuri}") + elsif response.uri.request_uri.include?('AuthParam=') + debug("Authentication not required for #{fileuri}") + return response.uri.to_s + else + raise "Unknown failure while fetching #{fileuri}" + end + rescue Net::HTTPServerException => e + debug("File not found at #{fileuri}") + debug('Trying authenticated download...') + auth_required = true + fileuri = fileuri.gsub!('otn-pub', 'otn') + end + + # + # Step 2: authenticate against Oracle SSO + # Success: requested form contains OAM_REQ parameter and POST returns a redirect + # Failure: POST returns 200 or http error + # + + # retrieve SSO form and read OAM_REQ parameter value + debug('Retrieving Oracle.com SSO form.') + response, cookies = PuppetX::Util.request(fileuri, 'GET', cookies) + matchdata = /name="OAM_REQ" value="(.+?)"/.match(response.body) + if matchdata and !matchdata.captures.nil? + oamreq = matchdata[1] + debug('Found OAM_REQ parameter from Oracle.com SSO form.') + else + raise 'Could not retrieve OAM_REQ parameter from Oracle.com SSO form.' + end + + # submit authentication form + debug('Submitting Oracle.com SSO form.') + ssouri = URI('https://login.oracle.com/oam/server/sso/auth_cred_submit') + cookies.push('s_cc=true') + + request = Net::HTTP::Post.new(ssouri, {'user-agent' => 'Mozilla/5.0 (Puppet)', 'cookie' => cookies.join('; ')}) + request.set_form_data('ssousername' => ssousername, 'password' => password) + request.body += "&OAM_REQ=#{oamreq}" + + response = Net::HTTP.start(ssouri.host, ssouri.port, :use_ssl => true) { |http| http.request(request) } + case response + when Net::HTTPRedirection + location = response['location'] + if URI(location).request_uri.start_with?('/osso_login_success') + debug('Sign-on success.') + response.get_fields('set-cookie').each { |c| cookies.push(c.split('; ')[0]) } + else + raise 'Sign-on failed. Check your Oracle.com credentials.' + end + else + raise 'Sign-on failed. Check your Oracle.com credentials.' + end + + # + # Step 3: try authenticated download from transformed URI + # Success: URI contains AuthParam parameter and HEAD request returns 200 + # Failure: 404 or redirect to Oracle SSO + # + + begin + response, _ = PuppetX::Util.request(location, 'HEAD', cookies) + if response.uri.request_uri.include?('AuthParam=') + return response.uri.to_s + else + raise "Unknown failure while fetching #{fileuri}" + end + rescue Net::HTTPServerException => e + raise "File not found at #{fileuri}" + end + end +end diff --git a/lib/puppet_x/util.rb b/lib/puppet_x/util.rb new file mode 100644 index 0000000..631bdc3 --- /dev/null +++ b/lib/puppet_x/util.rb @@ -0,0 +1,45 @@ +module PuppetX + + module Util + + require 'net/http' + + def self.request(uri_str, method = nil, cookies = [], limit = 10) + raise ArgumentError, 'too many HTTP redirects' if limit == 0 + + uri = URI(uri_str) + + case method + when 'POST' then + reqmethod = Net::HTTP::Post + when 'HEAD' then + reqmethod = Net::HTTP::Head + else + reqmethod = Net::HTTP::Get + end + + request = reqmethod.new(uri, {'user-agent' => 'Mozilla/5.0 (Puppet)', 'cookie' => cookies.join('; ')}) + response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http| + http.request(request) + end + + # cache cookies for subsequent requests + response_cookies = response.get_fields('set-cookie') + if !response_cookies.nil? + response_cookies.each { |c| cookies.push(c.split('; ')[0]) } + end + + case response + when Net::HTTPSuccess then + return response, cookies + when Net::HTTPRedirection then + location = response['location'] + request(location, method = method, cookies, limit - 1) + else + return response.value, nil + end + end + + end + +end diff --git a/manifests/download.pp b/manifests/download.pp index cb88621..752ed2e 100644 --- a/manifests/download.pp +++ b/manifests/download.pp @@ -22,13 +22,22 @@ } Archive { - cookie => 'oraclelicense=accept-securebackup-cookie', - source => "${oracle_java::download_url_real}/${oracle_java::filename_real}", proxy_server => $oracle_java::proxy_server, proxy_type => $oracle_java::proxy_type, require => File[$oracle_java::install_path] } + # pass credentials to Oracle SSO for authenticated downloads + if $oracle_java::oracle_url { + Archive { + source => oracle_sso("${oracle_java::download_url_real}/${oracle_java::filename_real}", $oracle_java::ssousername, $oracle_java::ssopassword) + } + } else { + Archive { + source => "${oracle_java::download_url_real}/${oracle_java::filename_real}" + } + } + # with checksum check if $oracle_java::check_checksum { Archive { diff --git a/manifests/init.pp b/manifests/init.pp index 20ea358..ff89321 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -12,6 +12,10 @@ # envionment type to install (valid: 'jre'|'jdk') # [*format*] # archive format (valid: 'rpm'|'tar.gz') +# [*ssousername*] +# user name of oracle.com account +# [*ssopassword*] +# password of oracle.com account # [*install_path*] # defines the root path where the Java archives are extracted. Requires 'tar.gz' format # [*check_checksum*] @@ -56,6 +60,8 @@ $build = undef, $type = 'jre', $format = undef, + $ssousername = undef, + $ssopassword = undef, $check_checksum = true, $checksum = undef, $add_alternative = false, @@ -178,8 +184,10 @@ # define download URL if !$download_url { $download_url_real = "http://download.oracle.com/otn-pub/java/jdk/${version_final}${build_real}${urlcode_real}" + $oracle_url = true } else { $download_url_real = $download_url + $oracle_url = false } # define package name diff --git a/manifests/installation.pp b/manifests/installation.pp index 5a97791..55a6a9f 100644 --- a/manifests/installation.pp +++ b/manifests/installation.pp @@ -125,9 +125,9 @@ # associate build number to release version case $maj_version { '9' : { - case $oracle_java::min_version { + case $min_version { '0' : { $buildnumber = '+181' } - default : { fail("Unreleased Java SE version ${oracle_java::version_real}") } + default : { fail("Unreleased Java SE version ${version_real}") } } } '8' : { @@ -224,8 +224,10 @@ # define download URL if !$download_url { $download_url_real = "http://download.oracle.com/otn-pub/java/jdk/${version_final}${build_real}${urlcode_real}" + $oracle_url = true } else { $download_url_real = $download_url + $oracle_url = false } # -------------# @@ -552,13 +554,22 @@ } Archive { - cookie => 'oraclelicense=accept-securebackup-cookie', - source => "${download_url_real}/${filename_real}", proxy_server => $proxy_server, proxy_type => $proxy_type, require => File[$install_path] } + # pass credentials to Oracle SSO for authenticated downloads + if $oracle_url { + Archive { + source => oracle_sso("${download_url_real}/${filename_real}", $oracle_java::ssousername, $oracle_java::ssopassword) + } + } else { + Archive { + source => "${download_url_real}/${filename_real}", + } + } + # download archive if $maj_version == '6' { archive { "${install_path}/${filename_real}":