packaging 0.88.77 → 0.99.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +128 -74
- data/lib/packaging/artifactory.rb +60 -433
- data/lib/packaging/config/params.rb +7 -28
- data/lib/packaging/config.rb +50 -150
- data/lib/packaging/deb/repo.rb +19 -20
- data/lib/packaging/gem.rb +83 -41
- data/lib/packaging/ips.rb +57 -0
- data/lib/packaging/msi.rb +89 -0
- data/lib/packaging/nuget.rb +1 -1
- data/lib/packaging/osx.rb +36 -0
- data/lib/packaging/paths.rb +87 -225
- data/lib/packaging/platforms.rb +416 -443
- data/lib/packaging/repo.rb +22 -122
- data/lib/packaging/retrieve.rb +7 -36
- data/lib/packaging/rpm/repo.rb +8 -5
- data/lib/packaging/tar.rb +0 -9
- data/lib/packaging/util/date.rb +0 -5
- data/lib/packaging/util/execution.rb +2 -2
- data/lib/packaging/util/git.rb +1 -1
- data/lib/packaging/util/gpg.rb +1 -5
- data/lib/packaging/util/net.rb +37 -79
- data/lib/packaging/util/rake_utils.rb +0 -1
- data/lib/packaging/util/ship.rb +13 -142
- data/lib/packaging/util/tool.rb +1 -1
- data/lib/packaging/util/version.rb +0 -8
- data/lib/packaging/util.rb +2 -2
- data/lib/packaging.rb +3 -3
- data/spec/fixtures/config/params.yaml +2 -0
- data/spec/lib/packaging/artifactory_spec.rb +16 -66
- data/spec/lib/packaging/config_spec.rb +29 -49
- data/spec/lib/packaging/deb/repo_spec.rb +7 -16
- data/spec/lib/packaging/paths_spec.rb +56 -321
- data/spec/lib/packaging/platforms_spec.rb +21 -46
- data/spec/lib/packaging/repo_spec.rb +40 -78
- data/spec/lib/packaging/retrieve_spec.rb +8 -47
- data/spec/lib/packaging/rpm/repo_spec.rb +4 -4
- data/spec/lib/packaging/tar_spec.rb +40 -34
- data/spec/lib/packaging/util/git_tag_spec.rb +1 -1
- data/spec/lib/packaging/util/gpg_spec.rb +1 -1
- data/spec/lib/packaging/util/net_spec.rb +15 -35
- data/spec/lib/packaging/util/ship_spec.rb +63 -145
- data/spec/spec_helper.rb +14 -0
- data/tasks/00_utils.rake +6 -4
- data/tasks/apple.rake +0 -2
- data/tasks/config.rake +0 -5
- data/tasks/education.rake +5 -5
- data/tasks/fetch.rake +14 -17
- data/tasks/gem.rake +121 -134
- data/tasks/jenkins.rake +7 -51
- data/tasks/nightly_repos.rake +69 -20
- data/tasks/pe_ship.rake +11 -16
- data/tasks/retrieve.rake +6 -13
- data/tasks/ship.rake +256 -196
- data/tasks/sign.rake +135 -63
- data/tasks/tar.rake +6 -0
- data/templates/packaging.xml.erb +7 -9
- data/templates/repo.xml.erb +3 -6
- metadata +27 -80
- data/lib/packaging/archive.rb +0 -126
- data/lib/packaging/artifactory/extensions.rb +0 -94
- data/lib/packaging/config/validations.rb +0 -13
- data/lib/packaging/metrics.rb +0 -15
- data/lib/packaging/sign/deb.rb +0 -9
- data/lib/packaging/sign/dmg.rb +0 -41
- data/lib/packaging/sign/ips.rb +0 -57
- data/lib/packaging/sign/msi.rb +0 -124
- data/lib/packaging/sign/rpm.rb +0 -115
- data/lib/packaging/sign.rb +0 -8
- data/spec/lib/packaging/gem_spec.rb +0 -86
- data/spec/lib/packaging/sign_spec.rb +0 -133
- data/tasks/archive.rake +0 -69
data/lib/packaging/archive.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
module Pkg::Archive
|
2
|
-
module_function
|
3
|
-
|
4
|
-
# Array of base paths for foss artifacts on weth
|
5
|
-
def base_paths
|
6
|
-
[Pkg::Config.yum_repo_path, Pkg::Config.apt_repo_staging_path, Pkg::Config.apt_repo_path, '/opt/downloads'].compact.freeze
|
7
|
-
end
|
8
|
-
|
9
|
-
# Array of paths for temporarily staging artifacts before syncing to release-archives on s3
|
10
|
-
def archive_paths
|
11
|
-
[Pkg::Config.yum_archive_path, Pkg::Config.apt_archive_path, Pkg::Config.freight_archive_path, Pkg::Config.downloads_archive_path, '/opt/tmp-apt'].compact.freeze
|
12
|
-
end
|
13
|
-
|
14
|
-
# Move yum directories from repo path to archive staging path
|
15
|
-
def stage_yum_archives(directory)
|
16
|
-
# /opt/repository/yum/#{directory}
|
17
|
-
full_directory = File.join(Pkg::Config.yum_repo_path, directory)
|
18
|
-
archive_path = File.join(Pkg::Config.yum_archive_path, directory)
|
19
|
-
command = <<-CMD
|
20
|
-
if [ ! -d #{full_directory} ]; then
|
21
|
-
if [ -d #{archive_path} ]; then
|
22
|
-
echo "Directory #{full_directory} has already been staged, skipping . . ."
|
23
|
-
exit 0
|
24
|
-
else
|
25
|
-
echo "ERROR: Couldn't find directory #{full_directory}, exiting . . ."
|
26
|
-
exit 1
|
27
|
-
fi
|
28
|
-
fi
|
29
|
-
find #{full_directory} -type l -delete
|
30
|
-
sudo chattr -i -R #{full_directory}
|
31
|
-
sudo mkdir --parents #{File.dirname(archive_path)}
|
32
|
-
sudo chown root:release -R #{Pkg::Config.yum_archive_path}
|
33
|
-
sudo chmod g+w -R #{Pkg::Config.yum_archive_path}
|
34
|
-
mv #{full_directory} #{archive_path}
|
35
|
-
CMD
|
36
|
-
Pkg::Util::Net.remote_execute(Pkg::Config.staging_server, command)
|
37
|
-
end
|
38
|
-
|
39
|
-
# Move directories from freight path (aka repo staging path) to archive staging paths
|
40
|
-
def stage_apt_archives(directory)
|
41
|
-
find_command = "find #{Pkg::Config.apt_repo_staging_path} -type d -name #{directory}"
|
42
|
-
find_command = "find #{Pkg::Config.apt_repo_staging_path} -maxdepth 2 -type f" if directory == 'main'
|
43
|
-
command = <<-CMD
|
44
|
-
for stuff in $(#{find_command}); do
|
45
|
-
find $stuff -type l -delete
|
46
|
-
codename=$(dirname ${stuff##{Pkg::Config.apt_repo_staging_path}/})
|
47
|
-
sudo mkdir --parents #{Pkg::Config.freight_archive_path}/$codename
|
48
|
-
sudo chown root:release -R #{Pkg::Config.freight_archive_path}/$codename
|
49
|
-
sudo chmod g+w -R #{Pkg::Config.freight_archive_path}/$codename
|
50
|
-
mv $stuff #{Pkg::Config.freight_archive_path}/$codename
|
51
|
-
|
52
|
-
pool_directory=#{Pkg::Config.apt_repo_path}/pool/$codename/#{directory}
|
53
|
-
if [ ! -d $pool_directory ]; then
|
54
|
-
echo "Can't find directory $pool_directory, it may have already been archived, skipping . . ."
|
55
|
-
continue
|
56
|
-
fi
|
57
|
-
sudo mkdir --parents /opt/tmp-apt
|
58
|
-
sudo chown root:release -R /opt/tmp-apt
|
59
|
-
sudo chmod g+w -R /opt/tmp-apt
|
60
|
-
mv $pool_directory /opt/tmp-apt
|
61
|
-
done
|
62
|
-
CMD
|
63
|
-
Pkg::Util::Net.remote_execute(Pkg::Config.staging_server, command)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Move downloads directories to archive staging path
|
67
|
-
def stage_downloads_archives(directory)
|
68
|
-
# /opt/downloads/#{directory}
|
69
|
-
full_directory = File.join('/', 'opt', 'downloads', directory)
|
70
|
-
archive_path = File.join(Pkg::Config.downloads_archive_path, directory)
|
71
|
-
command = <<-CMD
|
72
|
-
if [ ! -d #{full_directory} ]; then
|
73
|
-
if [ -d #{archive_path} ]; then
|
74
|
-
echo "Directory #{full_directory} has already been staged, skipping . . ."
|
75
|
-
exit 0
|
76
|
-
else
|
77
|
-
echo "ERROR: Couldn't find directory #{full_directory}, exiting . . ."
|
78
|
-
exit 1
|
79
|
-
fi
|
80
|
-
fi
|
81
|
-
find #{full_directory} -type l -delete
|
82
|
-
sudo chattr -i -R #{full_directory}
|
83
|
-
sudo mkdir --parents #{File.dirname(archive_path)}
|
84
|
-
sudo chown root:release -R #{Pkg::Config.downloads_archive_path}
|
85
|
-
sudo chmod g+w -R #{Pkg::Config.downloads_archive_path}
|
86
|
-
mv #{full_directory} #{archive_path}
|
87
|
-
CMD
|
88
|
-
Pkg::Util::Net.remote_execute(Pkg::Config.staging_server, command)
|
89
|
-
end
|
90
|
-
|
91
|
-
# Delete empty directories from repo paths on weth
|
92
|
-
def remove_empty_directories
|
93
|
-
base_paths.each do |path|
|
94
|
-
command = <<-CMD
|
95
|
-
for directory in $(find #{path} -type d); do
|
96
|
-
if [ ! -d $directory ]; then
|
97
|
-
echo "Can't find directory $directory, it was probably already deleted, skipping . . ."
|
98
|
-
continue
|
99
|
-
fi
|
100
|
-
files=$(find $directory -type f)
|
101
|
-
if [ -z "$files" ]; then
|
102
|
-
echo "No files in directory $directory, deleting . . ."
|
103
|
-
sudo rm -rf $directory
|
104
|
-
fi
|
105
|
-
done
|
106
|
-
CMD
|
107
|
-
Pkg::Util::Net.remote_execute(Pkg::Config.staging_server, command)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Delete broken symlinks from repo paths on weth
|
112
|
-
def remove_dead_symlinks
|
113
|
-
base_paths.each do |path|
|
114
|
-
command = "find #{path} -xtype l -delete"
|
115
|
-
Pkg::Util::Net.remote_execute(Pkg::Config.staging_server, command)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Delete artifacts from archive staging paths (after they've been synced to s3)
|
120
|
-
def delete_staged_archives
|
121
|
-
archive_paths.each do |archive_path|
|
122
|
-
command = "sudo rm -rf #{File.join(archive_path, '*')}"
|
123
|
-
Pkg::Util::Net.remote_execute(Pkg::Config.staging_server, command)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
@@ -1,94 +0,0 @@
|
|
1
|
-
require 'artifactory'
|
2
|
-
|
3
|
-
module ArtifactoryExtensions
|
4
|
-
module ClassMethods
|
5
|
-
#
|
6
|
-
# Search for an artifact in a repo using an Ant-like pattern.
|
7
|
-
# Unlike many Artifactory searches, this one is restricted to a single
|
8
|
-
# repository.
|
9
|
-
#
|
10
|
-
# @example Search in a repository named 'foo_local' for an artifact in a directory containing
|
11
|
-
# the word "recent", named "artifact[0-9].txt"
|
12
|
-
# Artifact.pattern_search(pattern: '*recent*/artifact[0-9].txt',
|
13
|
-
# repo: 'foo_local')
|
14
|
-
#
|
15
|
-
# @param [Hash] options
|
16
|
-
# A hash of options, as follows:
|
17
|
-
#
|
18
|
-
# @option options [Artifactory::Client] :client
|
19
|
-
# the client object to make the request with
|
20
|
-
# @option options [String] :pattern
|
21
|
-
# the Ant-like pattern to use for finding artifacts within the repos. Note that the
|
22
|
-
# Ant pattern '**' is barred in this case by JFrog.
|
23
|
-
# @option options [String] :repo
|
24
|
-
# the repo to search
|
25
|
-
#
|
26
|
-
# @return [Array<Resource::Artifact>]
|
27
|
-
# a list of artifacts that match the query
|
28
|
-
#
|
29
|
-
def pattern_search(options = {})
|
30
|
-
client = extract_client!(options)
|
31
|
-
params = Artifactory::Util.slice(options, :pattern, :repo)
|
32
|
-
pattern_search_parameter = { :pattern => "#{params[:repo]}:#{params[:pattern]}" }
|
33
|
-
response = client.get('/api/search/pattern', pattern_search_parameter)
|
34
|
-
return [] if response['files'].nil? || response['files'].empty?
|
35
|
-
|
36
|
-
# A typical response:
|
37
|
-
# {
|
38
|
-
# "repoUri"=>"https:<artifactory endpoint>/<repo>",
|
39
|
-
# "sourcePattern"=>"<repo>:<provided search pattern>",
|
40
|
-
# "files"=>[<filename that matched pattern>, ...]
|
41
|
-
# }
|
42
|
-
#
|
43
|
-
# Inserting '/api/storage' before the repo makes the 'from_url' call work correctly.
|
44
|
-
#
|
45
|
-
repo_uri = response['repoUri']
|
46
|
-
unless repo_uri.include?('/api/storage/')
|
47
|
-
# rubocop:disable Style/PercentLiteralDelimiters
|
48
|
-
repo_uri.sub!(%r(/#{params[:repo]}$), "/api/storage/#{params[:repo]}")
|
49
|
-
end
|
50
|
-
response['files'].map do |file_path|
|
51
|
-
from_url("#{repo_uri}/#{file_path}", client: client)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# This adds the `exact_match` option to artifactory search, and defaults it
|
56
|
-
# to true. With `exact_match` set to `true` the artifact will only be
|
57
|
-
# returned if the name in the download uri matches the name we're trying to
|
58
|
-
# download
|
59
|
-
def search(options = {})
|
60
|
-
exact_match = options[:exact_match].nil? ? true : options[:exact_match]
|
61
|
-
artifacts = super
|
62
|
-
|
63
|
-
if exact_match
|
64
|
-
artifacts.select! { |artifact| File.basename(artifact.download_uri) == options[:name] }
|
65
|
-
end
|
66
|
-
artifacts
|
67
|
-
end
|
68
|
-
|
69
|
-
# This adds the `name` option to artifactory checksum search. It defaults to
|
70
|
-
# unset. If set, the artifact is only returned if the download uri matches
|
71
|
-
# the passed name
|
72
|
-
def checksum_search(options = {})
|
73
|
-
artifacts = super
|
74
|
-
if options[:name]
|
75
|
-
artifacts.select! { |artifact| File.basename(artifact.download_uri) == options[:name] }
|
76
|
-
end
|
77
|
-
artifacts
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# needed to prepend class methods, see https://stackoverflow.com/questions/18683750/how-to-prepend-classmethods
|
82
|
-
def self.prepended(base)
|
83
|
-
class << base
|
84
|
-
prepend ClassMethods
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
module Artifactory
|
90
|
-
class Resource::Artifact
|
91
|
-
# use prepend instead of monkeypatching so we can call `super`
|
92
|
-
prepend ArtifactoryExtensions
|
93
|
-
end
|
94
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module Pkg
|
2
|
-
class ConfigValidations
|
3
|
-
|
4
|
-
class << self
|
5
|
-
|
6
|
-
# As a validation, this one is kindof lame but is intended as a seed pattern for possibly
|
7
|
-
# more robust ones.
|
8
|
-
def not_empty?(value)
|
9
|
-
value.to_s.empty? ? false : true
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
data/lib/packaging/metrics.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
module Pkg::Metrics
|
2
|
-
module_function
|
3
|
-
|
4
|
-
def update_release_metrics
|
5
|
-
metrics_repo = 'release-metrics'
|
6
|
-
command = <<CMD
|
7
|
-
git clone git@github.com:puppetlabs/#{metrics_repo}.git
|
8
|
-
cd #{metrics_repo}
|
9
|
-
bundle exec add-release --date #{Pkg::Util::Date.today} --project #{Pkg::Config.project} --version #{Pkg::Config.ref}
|
10
|
-
cd ..
|
11
|
-
rm -r #{metrics_repo}
|
12
|
-
CMD
|
13
|
-
Pkg::Util::Execution.capture3(command, true)
|
14
|
-
end
|
15
|
-
end
|
data/lib/packaging/sign/deb.rb
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
module Pkg::Sign::Deb
|
2
|
-
module_function
|
3
|
-
|
4
|
-
def sign_changes(file)
|
5
|
-
# Lazy lazy lazy lazy lazy
|
6
|
-
sign_program = "-p'gpg --use-agent --no-tty'" if ENV['RPM_GPG_AGENT']
|
7
|
-
Pkg::Util::Execution.capture3("debsign #{sign_program} --re-sign -k#{Pkg::Config.gpg_key} #{file}")
|
8
|
-
end
|
9
|
-
end
|
data/lib/packaging/sign/dmg.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
module Pkg::Sign::Dmg
|
2
|
-
module_function
|
3
|
-
|
4
|
-
def sign(target_dir = 'pkg')
|
5
|
-
use_identity = "-i #{Pkg::Config.osx_signing_ssh_key}" unless Pkg::Config.osx_signing_ssh_key.nil?
|
6
|
-
|
7
|
-
if Pkg::Config.osx_signing_server =~ /@/
|
8
|
-
host_string = "#{Pkg::Config.osx_signing_server}"
|
9
|
-
else
|
10
|
-
host_string = "#{ENV['USER']}@#{Pkg::Config.osx_signing_server}"
|
11
|
-
end
|
12
|
-
ssh_host_string = "#{use_identity} #{host_string}"
|
13
|
-
rsync_host_string = "-e 'ssh #{use_identity}' #{host_string}"
|
14
|
-
|
15
|
-
work_dir = "/tmp/#{Pkg::Util.rand_string}"
|
16
|
-
mount = File.join(work_dir, "mount")
|
17
|
-
signed = File.join(work_dir, "signed")
|
18
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "mkdir -p #{mount} #{signed}")
|
19
|
-
dmgs = Dir.glob("#{target_dir}/apple/**/*.dmg")
|
20
|
-
Pkg::Util::Net.rsync_to(dmgs.join(" "), rsync_host_string, work_dir)
|
21
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, %Q[for dmg in #{dmgs.map { |d| File.basename(d, ".dmg") }.join(" ")}; do
|
22
|
-
/usr/bin/hdiutil attach #{work_dir}/$dmg.dmg -mountpoint #{mount} -nobrowse -quiet ;
|
23
|
-
/usr/bin/security -q unlock-keychain -p "#{Pkg::Config.osx_signing_keychain_pw}" "#{Pkg::Config.osx_signing_keychain}" ;
|
24
|
-
for pkg in $(ls #{mount}/*.pkg | xargs -n 1 basename); do
|
25
|
-
if /usr/sbin/pkgutil --check-signature #{mount}/$pkg ; then
|
26
|
-
echo "$pkg is already signed, skipping . . ." ;
|
27
|
-
cp #{mount}/$pkg #{signed}/$pkg ;
|
28
|
-
else
|
29
|
-
/usr/bin/productsign --keychain "#{Pkg::Config.osx_signing_keychain}" --sign "#{Pkg::Config.osx_signing_cert}" #{mount}/$pkg #{signed}/$pkg ;
|
30
|
-
fi
|
31
|
-
done
|
32
|
-
/usr/bin/hdiutil detach #{mount} -quiet ;
|
33
|
-
/bin/rm #{work_dir}/$dmg.dmg ;
|
34
|
-
/usr/bin/hdiutil create -volname $dmg -srcfolder #{signed}/ #{work_dir}/$dmg.dmg ;
|
35
|
-
/bin/rm #{signed}/* ; done])
|
36
|
-
dmgs.each do | dmg |
|
37
|
-
Pkg::Util::Net.rsync_from("#{work_dir}/#{File.basename(dmg)}", rsync_host_string, File.dirname(dmg))
|
38
|
-
end
|
39
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "if [ -d '#{work_dir}' ]; then rm -rf '#{work_dir}'; fi")
|
40
|
-
end
|
41
|
-
end
|
data/lib/packaging/sign/ips.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module Pkg::Sign::Ips
|
2
|
-
module_function
|
3
|
-
|
4
|
-
def sign(target_dir = 'pkg')
|
5
|
-
use_identity = "-i #{Pkg::Config.ips_signing_ssh_key}" unless Pkg::Config.ips_signing_ssh_key.nil?
|
6
|
-
|
7
|
-
ssh_host_string = "#{use_identity} #{ENV['USER']}@#{Pkg::Config.ips_signing_server}"
|
8
|
-
rsync_host_string = "-e 'ssh #{use_identity}' #{ENV['USER']}@#{Pkg::Config.ips_signing_server}"
|
9
|
-
|
10
|
-
p5ps = Dir.glob("#{target_dir}/solaris/11/**/*.p5p")
|
11
|
-
|
12
|
-
p5ps.each do |p5p|
|
13
|
-
work_dir = "/tmp/#{Pkg::Util.rand_string}"
|
14
|
-
unsigned_dir = "#{work_dir}/unsigned"
|
15
|
-
repo_dir = "#{work_dir}/repo"
|
16
|
-
signed_dir = "#{work_dir}/pkgs"
|
17
|
-
|
18
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "mkdir -p #{repo_dir} #{unsigned_dir} #{signed_dir}")
|
19
|
-
Pkg::Util::Net.rsync_to(p5p, rsync_host_string, unsigned_dir)
|
20
|
-
|
21
|
-
# Before we can get started with signing packages we need to create a repo
|
22
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "sudo -E /usr/bin/pkgrepo create #{repo_dir}")
|
23
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "sudo -E /usr/bin/pkgrepo set -s #{repo_dir} publisher/prefix=puppetlabs.com")
|
24
|
-
# And import all the packages into the repo.
|
25
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "sudo -E /usr/bin/pkgrecv -s #{unsigned_dir}/#{File.basename(p5p)} -d #{repo_dir} '*'")
|
26
|
-
# We are going to hard code the values for signing cert locations for now.
|
27
|
-
# This autmation will require an update to actually become reusable, but
|
28
|
-
# for now these values will stay this way so solaris signing will stop
|
29
|
-
# failing. Please update soon. 06/23/16
|
30
|
-
#
|
31
|
-
# - Sean P. McDonald
|
32
|
-
#
|
33
|
-
# We sign the entire repo
|
34
|
-
sign_cmd = "sudo -E /usr/bin/pkgsign -c /root/signing/signing_cert_2020.pem \
|
35
|
-
-i /root/signing/Thawte_SHA256_Code_Signing_CA.pem \
|
36
|
-
-i /root/signing/Thawte_Primary_Root_CA.pem \
|
37
|
-
-k /root/signing/signing_key_2020.pem \
|
38
|
-
-s 'file://#{work_dir}/repo' '*'"
|
39
|
-
puts "About to sign #{p5p} with #{sign_cmd} in #{work_dir}"
|
40
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, sign_cmd.squeeze(' '))
|
41
|
-
# pkgrecv with -a will pull packages out of the repo, so we need to do that too to actually get the packages we signed
|
42
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "sudo -E /usr/bin/pkgrecv -d #{signed_dir}/#{File.basename(p5p)} -a -s #{repo_dir} '*'")
|
43
|
-
begin
|
44
|
-
# lets make sure we actually signed something?
|
45
|
-
# **NOTE** if we're repeatedly trying to sign the same version this
|
46
|
-
# might explode because I don't know how to reset the IPS cache.
|
47
|
-
# Everything is amazing.
|
48
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "sudo -E /usr/bin/pkg contents -m -g #{signed_dir}/#{File.basename(p5p)} '*' | grep '^signature '")
|
49
|
-
rescue RuntimeError
|
50
|
-
raise "Looks like #{File.basename(p5p)} was not signed correctly, quitting!"
|
51
|
-
end
|
52
|
-
# and pull the packages back.
|
53
|
-
Pkg::Util::Net.rsync_from("#{signed_dir}/#{File.basename(p5p)}", rsync_host_string, File.dirname(p5p))
|
54
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "if [ -e '#{work_dir}' ] ; then sudo rm -r '#{work_dir}' ; fi")
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/packaging/sign/msi.rb
DELETED
@@ -1,124 +0,0 @@
|
|
1
|
-
module Pkg::Sign::Msi
|
2
|
-
module_function
|
3
|
-
|
4
|
-
def sign(target_dir = 'pkg')
|
5
|
-
use_identity = "-i #{Pkg::Config.msi_signing_ssh_key}" if Pkg::Config.msi_signing_ssh_key
|
6
|
-
|
7
|
-
ssh_host_string = "#{use_identity} Administrator@#{Pkg::Config.msi_signing_server}"
|
8
|
-
rsync_host_string = "-e 'ssh #{use_identity}' Administrator@#{Pkg::Config.msi_signing_server}"
|
9
|
-
|
10
|
-
work_dir = "Windows/Temp/#{Pkg::Util.rand_string}"
|
11
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "mkdir -p C:/#{work_dir}")
|
12
|
-
msis = Dir.glob("#{target_dir}/windows*/**/*.msi")
|
13
|
-
Pkg::Util::Net.rsync_to(msis.join(" "), rsync_host_string, "/cygdrive/c/#{work_dir}",
|
14
|
-
extra_flags: ["--ignore-existing --relative"])
|
15
|
-
|
16
|
-
# Please Note:
|
17
|
-
# We are currently adding two signatures to the msi.
|
18
|
-
#
|
19
|
-
# Microsoft compatable Signatures are composed of three different
|
20
|
-
# elements.
|
21
|
-
# 1) The Certificate used to sign the package. This is the element that
|
22
|
-
# is attached to organization. The certificate has an associated
|
23
|
-
# algorithm. We recently (February 2016) had to switch from a sha1 to
|
24
|
-
# a sha256 certificate. Sha1 was deprecated by many Microsoft
|
25
|
-
# elements on 2016-01-01, which forced us to switch to a sha256 cert.
|
26
|
-
# This sha256 certificate is recognized by all currently supported
|
27
|
-
# windows platforms (Windows 8/Vista forward).
|
28
|
-
# 2) The signature used to attach the certificate to the package. This
|
29
|
-
# can be a done with a variety of digest algorithms. Older platforms
|
30
|
-
# (i.e., Windows 8 and Windows Vista) don't recognize later
|
31
|
-
# algorithms like sha256.
|
32
|
-
# 3) The timestamp used to validate when the package was signed. This
|
33
|
-
# comes from an external source and can be delivered with a variety
|
34
|
-
# of digest algorithms. Older platforms do not recognize newer
|
35
|
-
# algorithms like sha256.
|
36
|
-
#
|
37
|
-
# We could have only one signature with the Sha256 Cert, Sha1 Signature,
|
38
|
-
# and Sha1 Timestamp, but that would be too easy. The sha256 signature
|
39
|
-
# and timestamp add more security to our packages. We can't have only
|
40
|
-
# sha256 elements in our package signature, though, because Windows 8
|
41
|
-
# and Windows Vista just don't recognize them at all.
|
42
|
-
#
|
43
|
-
# In order to add two signatures to an MSI, we also need to change the
|
44
|
-
# tool we use to sign packages with. Previously, we were using SignTool
|
45
|
-
# which is the Microsoft blessed program used to sign packages. However,
|
46
|
-
# this tool isn't able to add two signatures to an MSI specifically. It
|
47
|
-
# can dual-sign an exe, just not an MSI. In order to get the dual-signed
|
48
|
-
# packages, we decided to switch over to using osslsigncode. The original
|
49
|
-
# project didn't have support to compile on a windows system, so we
|
50
|
-
# decided to use this fork. The binaries on the signer were pulled from
|
51
|
-
# https://sourceforge.net/u/keeely/osslsigncode/ci/master/tree/
|
52
|
-
#
|
53
|
-
# These are our signatures:
|
54
|
-
# The first signature:
|
55
|
-
# * Sha256 Certificate
|
56
|
-
# * Sha1 Signature
|
57
|
-
# * Sha1 Timestamp
|
58
|
-
#
|
59
|
-
# The second signature:
|
60
|
-
# * Sha256 Certificate
|
61
|
-
# * Sha256 Signature
|
62
|
-
# * Sha256 Timestamp
|
63
|
-
#
|
64
|
-
# Once we no longer support Windows 8/Windows Vista, we can remove the
|
65
|
-
# first Sha1 signature.
|
66
|
-
sign_command = <<-CMD
|
67
|
-
for msipath in #{msis.join(" ")}; do
|
68
|
-
msi="$(basename $msipath)"
|
69
|
-
msidir="C:/#{work_dir}/$(dirname $msipath)"
|
70
|
-
if "/cygdrive/c/tools/osslsigncode-fork/osslsigncode.exe" verify -in "$msidir/$msi" ; then
|
71
|
-
echo "$msi is already signed, skipping . . ." ;
|
72
|
-
else
|
73
|
-
tries=5
|
74
|
-
sha1Servers=(http://timestamp.digicert.com/sha1/timestamp
|
75
|
-
http://timestamp.comodoca.com/authenticode)
|
76
|
-
for timeserver in "${sha1Servers[@]}"; do
|
77
|
-
for ((try=1; try<=$tries; try++)) do
|
78
|
-
ret=$(/cygdrive/c/tools/osslsigncode-fork/osslsigncode.exe sign \
|
79
|
-
-n "Puppet" -i "http://www.puppet.com" \
|
80
|
-
-h sha1 \
|
81
|
-
-pkcs12 "#{Pkg::Config.msi_signing_cert}" \
|
82
|
-
-pass "#{Pkg::Config.msi_signing_cert_pw}" \
|
83
|
-
-t "$timeserver" \
|
84
|
-
-in "$msidir/$msi" \
|
85
|
-
-out "$msidir/signed-$msi")
|
86
|
-
if [[ $ret == *"Succeeded"* ]]; then break; fi
|
87
|
-
done;
|
88
|
-
if [[ $ret == *"Succeeded"* ]]; then break; fi
|
89
|
-
done;
|
90
|
-
echo $ret
|
91
|
-
if [[ $ret != *"Succeeded"* ]]; then exit 1; fi
|
92
|
-
sha256Servers=(http://timestamp.digicert.com/sha256/timestamp
|
93
|
-
http://timestamp.comodoca.com?td=sha256)
|
94
|
-
for timeserver in "${sha256Servers[@]}"; do
|
95
|
-
for ((try=1; try<=$tries; try++)) do
|
96
|
-
ret=$(/cygdrive/c/tools/osslsigncode-fork/osslsigncode.exe sign \
|
97
|
-
-n "Puppet" -i "http://www.puppet.com" \
|
98
|
-
-nest -h sha256 \
|
99
|
-
-pkcs12 "#{Pkg::Config.msi_signing_cert}" \
|
100
|
-
-pass "#{Pkg::Config.msi_signing_cert_pw}" \
|
101
|
-
-ts "$timeserver" \
|
102
|
-
-in "$msidir/signed-$msi" \
|
103
|
-
-out "$msidir/$msi")
|
104
|
-
if [[ $ret == *"Succeeded"* ]]; then break; fi
|
105
|
-
done;
|
106
|
-
if [[ $ret == *"Succeeded"* ]]; then break; fi
|
107
|
-
done;
|
108
|
-
echo $ret
|
109
|
-
if [[ $ret != *"Succeeded"* ]]; then exit 1; fi
|
110
|
-
fi
|
111
|
-
done
|
112
|
-
CMD
|
113
|
-
|
114
|
-
Pkg::Util::Net.remote_execute(
|
115
|
-
ssh_host_string,
|
116
|
-
sign_command,
|
117
|
-
{ fail_fast: false }
|
118
|
-
)
|
119
|
-
msis.each do | msi |
|
120
|
-
Pkg::Util::Net.rsync_from("/cygdrive/c/#{work_dir}/#{msi}", rsync_host_string, File.dirname(msi))
|
121
|
-
end
|
122
|
-
Pkg::Util::Net.remote_execute(ssh_host_string, "if [ -d '/cygdrive/c/#{work_dir}' ]; then rm -rf '/cygdrive/c/#{work_dir}'; fi")
|
123
|
-
end
|
124
|
-
end
|
data/lib/packaging/sign/rpm.rb
DELETED
@@ -1,115 +0,0 @@
|
|
1
|
-
module Pkg::Sign::Rpm
|
2
|
-
module_function
|
3
|
-
|
4
|
-
def sign(rpm, sign_flags = nil)
|
5
|
-
# To enable support for wrappers around rpm and thus support for gpg-agent
|
6
|
-
# rpm signing, we have to be able to tell the packaging repo what binary to
|
7
|
-
# use as the rpm signing tool.
|
8
|
-
rpm_command = ENV['RPM'] || Pkg::Util::Tool.find_tool('rpm')
|
9
|
-
|
10
|
-
# If we're using the gpg agent for rpm signing, we don't want to specify the
|
11
|
-
# input for the passphrase, which is what '--passphrase-fd 3' does. However,
|
12
|
-
# if we're not using the gpg agent, this is required, and is part of the
|
13
|
-
# defaults on modern rpm. The fun part of gpg-agent signing of rpms is
|
14
|
-
# specifying that the gpg check command always return true
|
15
|
-
gpg_check_command = ''
|
16
|
-
input_flag = ''
|
17
|
-
if Pkg::Util.boolean_value(ENV['RPM_GPG_AGENT'])
|
18
|
-
gpg_check_command = "--define '%__gpg_check_password_cmd /bin/true'"
|
19
|
-
else
|
20
|
-
input_flag = "--passphrase-fd 3"
|
21
|
-
end
|
22
|
-
|
23
|
-
# Try this up to 5 times, to allow for incorrect passwords
|
24
|
-
Pkg::Util::Execution.retry_on_fail(:times => 5) do
|
25
|
-
# This definition of %__gpg_sign_cmd is the default on modern rpm. We
|
26
|
-
# accept extra flags to override certain signing behavior for older
|
27
|
-
# versions of rpm, e.g. specifying V3 signatures instead of V4.
|
28
|
-
Pkg::Util::Execution.capture3("#{rpm_command} #{gpg_check_command} --define '%_gpg_name #{Pkg::Util::Gpg.key}' --define '%__gpg_sign_cmd %{__gpg} gpg #{sign_flags} #{input_flag} --batch --no-verbose --no-armor --no-secmem-warning -u %{_gpg_name} -sbo %{__signature_filename} %{__plaintext_filename}' --addsign #{rpm}")
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def legacy_sign(rpm)
|
33
|
-
sign(rpm, "--force-v3-sigs --digest-algo=sha1")
|
34
|
-
end
|
35
|
-
|
36
|
-
def has_sig?(rpm)
|
37
|
-
# This should allow the `Pkg::Util::Gpg.key` method to fail if gpg_key is
|
38
|
-
# not set, before shelling out. We also only want the short key, all
|
39
|
-
# lowercase, since that's what the `rpm -Kv` output uses.
|
40
|
-
key = Pkg::Util::Gpg.key.downcase.chars.last(8).join
|
41
|
-
signature_check_output = %x(rpm --checksig --verbose #{rpm})
|
42
|
-
# If the signing key has not been loaded on the system this is running on,
|
43
|
-
# the check will exit 1, even if the rpm is signed, so we can't use capture3,
|
44
|
-
# which bails out with non-0 exit codes. Instead, check that the output
|
45
|
-
# looks more-or-less how we expect it to.
|
46
|
-
fail "Something went wrong checking the signature of #{rpm}." unless signature_check_output.include? "Header"
|
47
|
-
return signature_check_output.include? "key ID #{key}"
|
48
|
-
end
|
49
|
-
|
50
|
-
def sign_all(rpm_directory)
|
51
|
-
# Create a hash mapping full paths to basenames.
|
52
|
-
# This will allow us to keep track of the different paths that may be
|
53
|
-
# associated with a single basename, e.g. noarch packages.
|
54
|
-
all_rpms = {}
|
55
|
-
rpms_to_sign = Dir["#{rpm_directory}/**/*.rpm"]
|
56
|
-
rpms_to_sign.each do |rpm_path|
|
57
|
-
all_rpms[rpm_path] = File.basename(rpm_path)
|
58
|
-
end
|
59
|
-
# Delete a package, both from the signing server and from the rpm array, if
|
60
|
-
# there are other packages with the same basename so that we only sign the
|
61
|
-
# package once.
|
62
|
-
all_rpms.each do |rpm_path, rpm_filename|
|
63
|
-
if rpms_to_sign.map { |rpm| File.basename(rpm) }.count(rpm_filename) > 1
|
64
|
-
FileUtils.rm(rpm_path)
|
65
|
-
rpms_to_sign.delete(rpm_path)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
v3_rpms = []
|
70
|
-
v4_rpms = []
|
71
|
-
rpms_to_sign.each do |rpm|
|
72
|
-
platform_tag = Pkg::Paths.tag_from_artifact_path(rpm)
|
73
|
-
platform, version, _ = Pkg::Platforms.parse_platform_tag(platform_tag)
|
74
|
-
|
75
|
-
# We don't sign AIX rpms
|
76
|
-
next if platform_tag.include?('aix')
|
77
|
-
|
78
|
-
if has_sig? rpm
|
79
|
-
puts "#{rpm} is already signed, skipping . . ."
|
80
|
-
next
|
81
|
-
end
|
82
|
-
|
83
|
-
case Pkg::Platforms.signature_format_for_platform_version(platform, version)
|
84
|
-
when 'v3'
|
85
|
-
v3_rpms << rpm
|
86
|
-
when 'v4'
|
87
|
-
v4_rpms << rpm
|
88
|
-
else
|
89
|
-
fail "Cannot find signature type for package '#{rpm}'"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
unless v3_rpms.empty?
|
94
|
-
puts "Signing legacy (v3) rpms..."
|
95
|
-
legacy_sign(v3_rpms.join(' '))
|
96
|
-
end
|
97
|
-
|
98
|
-
unless v4_rpms.empty?
|
99
|
-
puts "Signing modern (v4) rpms..."
|
100
|
-
sign(v4_rpms.join(' '))
|
101
|
-
end
|
102
|
-
|
103
|
-
# Using the map of paths to basenames, we re-hardlink the rpms we deleted.
|
104
|
-
all_rpms.each do |link_path, rpm_filename|
|
105
|
-
next if File.exist? link_path
|
106
|
-
FileUtils.mkdir_p(File.dirname(link_path))
|
107
|
-
# Find paths where the signed rpm has the same basename, but different
|
108
|
-
# full path, as the one we need to link.
|
109
|
-
paths_to_link_to = rpms_to_sign.select { |rpm| File.basename(rpm) == rpm_filename && rpm != link_path }
|
110
|
-
paths_to_link_to.each do |path|
|
111
|
-
FileUtils.ln(path, link_path, :force => true, :verbose => true)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|