diff --git a/REFERENCE.md b/REFERENCE.md
index 8f2a2319e..fa6cb61e7 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -624,6 +624,7 @@ working with a remote https repository.
The following parameters are available in the `puppet_agent::prepare::package` class:
* [`source`](#-puppet_agent--prepare--package--source)
+* [`package_file_name`](#-puppet_agent--prepare--package--package_file_name)
##### `source`
@@ -632,6 +633,16 @@ Data type: `Variant[String, Array]`
The source file for the puppet-agent package. Can use any of the data types
and protocols that the File resource's source attribute can.
+##### `package_file_name`
+
+Data type: `Optional[String]`
+
+The destination file name for the puppet-agent package. If no destination
+is given, then the basename component of the source will be used as the
+destination filename.
+
+Default value: `undef`
+
### `puppet_agent::prepare::puppet_config`
Private class called from puppet_agent::prepare class.
@@ -993,6 +1004,18 @@ Data type: `Optional[Integer]`
The number of retries in case of network connectivity failures
+##### `username`
+
+Data type: `Optional[String]`
+
+The username to use when downloading from a source location requiring authentication
+
+##### `password`
+
+Data type: `Optional[String]`
+
+The password to use when downloading from a source location requiring authentication
+
### `install_shell`
Install the Puppet agent package
diff --git a/manifests/osfamily/darwin.pp b/manifests/osfamily/darwin.pp
index ab3dfd15c..f55023bca 100644
--- a/manifests/osfamily/darwin.pp
+++ b/manifests/osfamily/darwin.pp
@@ -20,12 +20,20 @@
} else {
$source = "puppet:///pe_packages/${pe_server_version}/${facts['platform_tag']}/${puppet_agent::package_name}-${puppet_agent::prepare::package_version}-1.osx${$productversion_major}.dmg"
}
- } else {
+ } elsif $puppet_agent::collection and $puppet_agent::collection =~ /core/ {
+ if $puppet_agent::prepare::package_version =~ /^\d+\.\d+\.\d+\.\d+\.g([a-f0-9]+)+$/ {
+ $source = "https://artifacts-puppetcore.puppet.com/v1/download?type=native&version=${puppet_agent::prepare::package_version}&os_name=osx&os_version=${productversion_major}&os_arch=${puppet_agent::arch}&dev=true"
+ } else {
+ $source = "https://artifacts-puppetcore.puppet.com/v1/download?type=native&version=${puppet_agent::prepare::package_version}&os_name=osx&os_version=${productversion_major}&os_arch=${puppet_agent::arch}"
+ }
+ $destination_name = "${puppet_agent::package_name}-${puppet_agent::prepare::package_version}-1.osx${productversion_major}.dmg"
+ } else {
$source = "${puppet_agent::mac_source}/mac/${puppet_agent::collection}/${productversion_major}/${puppet_agent::arch}/${puppet_agent::package_name}-${puppet_agent::prepare::package_version}-1.osx${$productversion_major}.dmg"
}
class { 'puppet_agent::prepare::package':
source => $source,
+ destination_name => $destination_name,
}
contain puppet_agent::prepare::package
diff --git a/manifests/osfamily/windows.pp b/manifests/osfamily/windows.pp
index 8114ddeb0..a97bbcd70 100644
--- a/manifests/osfamily/windows.pp
+++ b/manifests/osfamily/windows.pp
@@ -2,6 +2,8 @@
class puppet_agent::osfamily::windows {
assert_private()
+ $destination_name = undef
+
if $puppet_agent::absolute_source {
$source = $puppet_agent::absolute_source
} elsif $puppet_agent::source {
@@ -23,13 +25,17 @@
} else {
if $puppet_agent::collection == 'PC1' {
$source = "${puppet_agent::windows_source}/windows/${puppet_agent::package_name}-${puppet_agent::prepare::package_version}-${puppet_agent::arch}.msi"
+ } elsif $puppet_agent::collection =~ /core/ {
+ $source = 'https://artifacts-puppetcore.puppet.com/v1/download'
+ $destination_name = "${puppet_agent::package_name}-${puppet_agent::prepare::package_version}-${puppet_agent::arch}.msi"
} else {
$source = "${puppet_agent::windows_source}/windows/${puppet_agent::collection}/${puppet_agent::package_name}-${puppet_agent::prepare::package_version}-${puppet_agent::arch}.msi"
}
}
class { 'puppet_agent::prepare::package':
- source => $source,
+ source => $source,
+ destination_name => $destination_name,
}
contain puppet_agent::prepare::package
diff --git a/manifests/prepare/package.pp b/manifests/prepare/package.pp
index dee0afa29..38db02c77 100644
--- a/manifests/prepare/package.pp
+++ b/manifests/prepare/package.pp
@@ -5,8 +5,13 @@
# @param source
# The source file for the puppet-agent package. Can use any of the data types
# and protocols that the File resource's source attribute can.
+# @param destination_name
+# The destination file name for the puppet-agent package. If no destination
+# is given, then the basename component of the source will be used as the
+# destination name.
class puppet_agent::prepare::package (
Variant[String, Array] $source,
+ Optional[String] $destination_name = undef
) {
assert_private()
@@ -14,12 +19,17 @@
ensure => directory,
}
- # In order for the 'basename' function to work correctly we need to change
- # any \s to /s (even for windows UNC paths) so that it will correctly pull off
- # the filename. Since this operation is only grabbing the base filename and not
- # any part of the path this should be safe, since the source will simply remain
- # what it was before and we can still pull off the filename.
- $package_file_name = basename(regsubst($source, "\\\\", '/', 'G'))
+ if $destination_name {
+ $package_file_name = $destination_name
+ } else {
+ # In order for the 'basename' function to work correctly we need to change
+ # any \s to /s (even for windows UNC paths) so that it will correctly pull off
+ # the filename. Since this operation is only grabbing the base filename and not
+ # any part of the path this should be safe, since the source will simply remain
+ # what it was before and we can still pull off the filename.
+ $package_file_name = basename(regsubst($source, "\\\\", '/', 'G'))
+ }
+
if $facts['os']['family'] =~ /windows/ {
$local_package_file_path = windows_native_path("${puppet_agent::params::local_packages_dir}/${package_file_name}")
$mode = undef
@@ -28,12 +38,79 @@
$mode = '0644'
}
- file { $local_package_file_path:
- ensure => file,
- owner => $puppet_agent::params::user,
- group => $puppet_agent::params::group,
- mode => $mode,
- source => $source,
- require => File[$puppet_agent::params::local_packages_dir],
+ # REMIND: redhat/suse with absolute_source
+ # REMIND: debian with absolute_source
+ # REMIND: solaris 10
+ # REMIND: solaris 11 with manage_repo
+ # REMIND: aix
+ # REMIND: darwin
+ # REMIND: suse 11 and PE
+ if $puppet_agent::collection and $puppet_agent::collection =~ /core/ and $facts['os']['family'] =~ /windows/ {
+ $download_username = getvar('puppet_agent::username', 'forge-key')
+ $download_password = unwrap(getvar('puppet_agent::password'))
+
+ $_download_puppet = windows_native_path("${facts['env_temp_variable']}/download_puppet.ps1")
+ file { $_download_puppet:
+ ensure => file,
+ content => Sensitive(epp('puppet_agent/download_puppet.ps1.epp')),
+ }
+
+ exec { 'Download Puppet Agent':
+ command => "${facts['os']['windows']['system32']}\\WindowsPowerShell\\v1.0\\powershell.exe \
+ -ExecutionPolicy Bypass \
+ -NoProfile \
+ -NoLogo \
+ -NonInteractive \
+ ${_download_puppet}",
+ creates => $local_package_file_path,
+ provider => powershell,
+ }
+ } elsif $puppet_agent::collection and $puppet_agent::collection =~ /core/ and $facts['os']['family'] =~ /Darwin/ {
+ $download_username = getvar('puppet_agent::username', 'forge-key')
+ $download_password = unwrap(getvar('puppet_agent::password'))
+
+ $response_file = "${local_package_file_path}.response"
+ $netrc_file = "${facts['env_temp_variable']}/.netrc"
+ file { $netrc_file:
+ ensure => file,
+ content => "machine artifacts-puppetcore.puppet.com\nlogin ${download_username}\npassword ${download_password}\n",
+ mode => '0600',
+ }
+
+ $curl_command = "curl -1 -sL --netrc-file '${netrc_file}' -w '%{http_code}' -o '${local_package_file_path}' '${source}' > '${response_file}'"
+ exec { 'Download Puppet Agent for Darwin':
+ command => $curl_command,
+ creates => $local_package_file_path,
+ path => ['/usr/bin', '/usr/sbin', '/bin', '/sbin'],
+ }
+
+ exec { 'Remove .netrc file':
+ command => "rm -f '${netrc_file}'",
+ path => ['/usr/bin', '/bin'],
+ onlyif => "test -f '${netrc_file}'",
+ require => Exec['Download Puppet Agent for Darwin'],
+ }
+ #
+ # TODO: This is a temporary workaround to get the HTTP response code from the curl command.
+ # For now just outputting the response is good enough.
+ # We need to find a way to interspect this value and fail the catalog if the response
+ # code is not 200, and then logging the output wont be as important.
+ #
+ exec { 'Read HTTP Response Code':
+ command => "cat '${response_file}'",
+ path => ['/usr/bin', '/bin'],
+ onlyif => "test -f '${response_file}'",
+ logoutput => true,
+ require => Exec['Download Puppet Agent for Darwin'],
+ }
+ } else {
+ file { $local_package_file_path:
+ ensure => file,
+ owner => $puppet_agent::params::user,
+ group => $puppet_agent::params::group,
+ mode => $mode,
+ source => $source,
+ require => File[$puppet_agent::params::local_packages_dir],
+ }
}
}
diff --git a/tasks/install_powershell.json b/tasks/install_powershell.json
index 868a95c65..8d64afb07 100644
--- a/tasks/install_powershell.json
+++ b/tasks/install_powershell.json
@@ -42,6 +42,14 @@
"description": "The number of retries in case of network connectivity failures",
"type": "Optional[Integer]",
"default": 5
+ },
+ "username": {
+ "description": "The username to use when downloading from a source location requiring authentication",
+ "type": "Optional[String]"
+ },
+ "password": {
+ "description": "The password to use when downloading from a source location requiring authentication",
+ "type": "Optional[String]"
}
},
"supports_noop": true
diff --git a/tasks/install_powershell.ps1 b/tasks/install_powershell.ps1
index 679baa07b..6aaf26ef8 100644
--- a/tasks/install_powershell.ps1
+++ b/tasks/install_powershell.ps1
@@ -7,11 +7,21 @@ Param(
[String]$install_options = 'REINSTALLMODE="amus"',
[Bool]$stop_service = $False,
[Int]$retry = 5,
- [Bool]$_noop = $False
+ [Bool]$_noop = $False,
+ [String]$username = 'forge-key',
+ [String]$password
)
# If an error is encountered, the script will stop instead of the default of "Continue"
$ErrorActionPreference = "Stop"
+try {
+ $os_version = (Get-WmiObject Win32_OperatingSystem).Version
+}
+catch [System.Management.Automation.CommandNotFoundException] {
+ $os_version = (Get-CimInstance -ClassName win32_OperatingSystem).Version
+}
+$major_os_version = ($os_version -split '\.')[0]
+
try {
if ((Get-WmiObject Win32_OperatingSystem).OSArchitecture -match '^32') {
$arch = "x86"
@@ -27,9 +37,19 @@ catch [System.Management.Automation.CommandNotFoundException] {
}
}
+$fips = 'false'
+try {
+ if ((Get-ItemPropertyValue -Path 'HKLM:\System\CurrentControlSet\Control\Lsa\FipsAlgorithmPolicy' -Name Enabled) -ne 0) {
+ $fips = 'true'
+ }
+}
+catch {
+ Write-Output "Failed to lookup FIPS mode, assuming it is disabled"
+}
+
function Test-PuppetInstalled {
$rootPath = 'HKLM:\SOFTWARE\Puppet Labs\Puppet'
- try {
+ try {
if (Get-ItemProperty -Path $rootPath) { RETURN $true }
}
catch {
@@ -98,12 +118,16 @@ if (Test-RunningServices) {
# Change windows_source only if the collection is a nightly build, and the source was not explicitly specified.
if (($collection -like '*nightly*') -And -Not ($PSBoundParameters.ContainsKey('windows_source'))) {
$windows_source = 'https://nightlies.puppet.com/downloads'
+} elseif (($collection -like '*puppetcore*') -And -Not ($PSBoundParameters.ContainsKey('windows_source'))) {
+ $windows_source = 'https://artifacts-puppetcore.puppet.com/v1/download'
}
if ($absolute_source) {
$msi_source = "$absolute_source"
}
-else {
+elseif ($collection -like '*puppetcore*') {
+ $msi_source = "${windows_source}?version=${version}&os_name=windows&os_version=${major_os_version}&os_arch=${arch}&fips=${fips}"
+} else {
$msi_source = "$windows_source/windows/${collection}/${msi_name}"
}
@@ -125,15 +149,19 @@ function Set-Tls12 {
}
function DownloadPuppet {
- Write-Output "Downloading the Puppet Agent installer on $env:COMPUTERNAME..."
+ Write-Output "Downloading the Puppet Agent installer on $env:COMPUTERNAME from ${msi_source}"
Set-Tls12
$webclient = New-Object system.net.webclient
-
+ if ($password) {
+ $credentials = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${username}:${password}"))
+ $webclient.Headers.Add("Authorization", "Basic ${credentials}")
+ }
try {
$webclient.DownloadFile($msi_source,$msi_dest)
}
catch [System.Net.WebException] {
+ Write-Host "Download exception: $($_.Exception.Message)"
For ($attempt_number = 1; $attempt_number -le $retry; $attempt_number++) {
try {
Write-Output "Retrying... [$attempt_number/$retry]"
@@ -141,6 +169,7 @@ function DownloadPuppet {
break
}
catch [System.Net.WebException] {
+ Write-Host "Download exception: $($_.Exception.Message)"
if($attempt_number -eq $retry) {
# If we can't find the msi, then we may not be configured correctly
if($_.Exception.Response.StatusCode -eq [system.net.httpstatuscode]::NotFound) {
diff --git a/tasks/install_shell.sh b/tasks/install_shell.sh
index 504d7409f..ef46c7f7c 100644
--- a/tasks/install_shell.sh
+++ b/tasks/install_shell.sh
@@ -162,10 +162,18 @@ fi
if [ -n "$PT_mac_source" ]; then
mac_source=$PT_mac_source
else
- if [ "$nightly" = true ]; then
- mac_source='http://nightlies.puppet.com/downloads'
- else
- mac_source='http://downloads.puppet.com'
+ if [[ "$PT_collection" =~ core ]]; then
+ if [ -z "$password" ]; then
+ echo "A password parameter is required to install with puppetcore"
+ exit 1
+ fi
+ mac_source='https://artifacts-puppetcore.puppet.com/v1/download'
+ else
+ if [ "$nightly" = true ]; then
+ mac_source='http://nightlies.puppet.com/downloads'
+ else
+ mac_source='http://downloads.puppet.com'
+ fi
fi
fi
@@ -421,7 +429,11 @@ do_wget() {
# do_curl URL FILENAME
do_curl() {
info "Trying curl..."
- run_cmd "curl -1 -sL -D $tmp_stderr '$1' > '$2'"
+ if [[ -n "$3" && -n "$4" ]]; then
+ run_cmd "curl -1 -sL -u '$3:$4' -D $tmp_stderr '$1' > '$2'"
+ else
+ run_cmd "curl -1 -sL -D $tmp_stderr '$1' > '$2'"
+ fi
rc=$?
# check for 404
@@ -431,6 +443,12 @@ do_curl() {
unable_to_retrieve_package
fi
+ grep "HTTP/2 401" $tmp_stderr 2>&1 >/dev/null
+ if test $? -eq 0; then
+ critical "ERROR 401: Unauthorized access"
+ unable_to_retrieve_package
+ fi
+
# check for bad return status or empty output
if test $rc -ne 0 || test ! -s "$2"; then
capture_tmp_stderr "curl"
@@ -557,7 +575,11 @@ do_download() {
fi
if exists curl; then
- do_curl $1 $2 && return 0
+ if [[ "$collection" =~ core ]]; then
+ do_curl $1 $2 "$username" "$password" && return 0
+ else
+ do_curl $1 $2 && return 0
+ fi
fi
if exists fetch; then
@@ -810,19 +832,31 @@ case $platform in
download_url="${apt_source}/${filename}"
;;
"mac_os_x")
- info "Mac platform! Lets get you a DMG..."
- filetype="dmg"
+ arch="x86_64"
+ if [[ $(uname -p) == "arm" ]]; then
+ arch="arm64"
+ fi
if test "$version" = "latest"; then
filename="puppet-agent-latest.dmg"
else
filename="puppet-agent-${version}-1.osx${platform_version}.dmg"
fi
-
- arch="x86_64"
- if [[ $(uname -p) == "arm" ]]; then
- arch="arm64"
+ info "Mac platform! Lets get you a DMG...!!"
+ if [[ "$collection" =~ core ]]; then
+ if [ -z "$password" ]; then
+ echo "A password parameter is required to install"
+ exit 1
+ fi
+ if [[ "$version" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)\.g([a-f0-9]+)$ ]]; then
+ download_url="${mac_source}/?version=${version}&os_name=osx&os_version=${platform_version}&os_arch=${arch}&fips=false&dev=true"
+ else
+ download_url="${mac_source}/?version=${version}&os_name=osx&os_version=${platform_version}&os_arch=${arch}&fips=false"
+ fi
+ else
+ download_url="${mac_source}/mac/${collection}/${platform_version}/${arch}/${filename}"
fi
- download_url="${mac_source}/mac/${collection}/${platform_version}/${arch}/${filename}"
+ filetype="dmg"
+
;;
*)
critical "Sorry $platform is not supported yet!"
diff --git a/templates/download_puppet.ps1.epp b/templates/download_puppet.ps1.epp
new file mode 100644
index 000000000..bf9ff7077
--- /dev/null
+++ b/templates/download_puppet.ps1.epp
@@ -0,0 +1,19 @@
+$body = @{
+ "version" = "<%= $puppet_agent::prepare::package_version %>"
+ "os_name" = "<%= $facts['os']['family'] %>"
+ "os_version" = "<%= $facts['os']['release']['major'] %>"
+ "os_arch" = "<%= $facts['os']['architecture'] %>"
+ "fips" = "<%= $facts['fips_enabled'] %>"
+}
+$username = "<%= $puppet_agent::prepare::package::download_username %>"
+$password = ConvertTo-SecureString "<%= $puppet_agent::prepare::package::download_password %>" -AsPlainText -Force
+$credential = New-Object System.Management.Automation.PSCredential($username, $password)
+try {
+ Invoke-WebRequest -Uri "<%= $puppet_agent::prepare::package::source %>" `
+ -Body $body `
+ -Credential $credential `
+ -OutFile "<%= $puppet_agent::prepare::package::local_package_file_path %>"
+} catch [System.Net.WebException] {
+ Write-Host "Network-related error: $($_.Exception.Message)"
+ exit 1
+}