diff --git a/GITLAB_OPENBAO_VERSION b/GITLAB_OPENBAO_VERSION index f2679845257387bf208754f75466e93953b2e457..9013470332dc197daacfbec03e5e12402442a6bb 100644 --- a/GITLAB_OPENBAO_VERSION +++ b/GITLAB_OPENBAO_VERSION @@ -1 +1 @@ -beaf1efbbbfcff64c465c19e3c49f1d527572b58 \ No newline at end of file +bf3dc45cc46a7769258dd3b7abb008ddb38536b4 diff --git a/ee/lib/tasks/gitlab/secrets_management/openbao.rake b/ee/lib/tasks/gitlab/secrets_management/openbao.rake index 06d97938816836515e8d6110d9c9472c3fbf5f65..58757954a8fbe693a134e9f7cc652e28e6b3cbb3 100644 --- a/ee/lib/tasks/gitlab/secrets_management/openbao.rake +++ b/ee/lib/tasks/gitlab/secrets_management/openbao.rake @@ -4,7 +4,7 @@ namespace :gitlab do namespace :secrets_management do namespace :openbao do desc 'GitLab | Secrets Management | Clone and checkout OpenBao' - task :clone, [:dir, :repo] => :gitlab_environment do |_, args| + task :download_or_clone, [:dir, :repo] => :gitlab_environment do |_, args| warn_user_is_not_gitlab unless args.dir.present? @@ -15,13 +15,50 @@ Usage: rake "gitlab:secrets_management:openbao:clone[/installation/dir]") args.with_defaults(repo: 'https://gitlab.com/gitlab-org/govern/secrets-management/openbao-internal.git') version = SecretsManagement::SecretsManagerClient.expected_server_version + binary_target_path = "#{args.dir}/bin/bao" - checkout_or_clone_version( + arch_map = { + 'x86_64' => 'amd64' + } + + # As per https://gitlab.com/gitlab-org/govern/secrets-management/openbao-internal/-/packages/ + checksums_sha256 = { + 'bao-darwin-arm64' => 'bf07ea0bb01e18ad6d8a79f2a572eeb14fc91cfb933aa84041d4cdc61ad3afe0', + 'bao-darwin-amd64' => '4459398d7f13c680d09eb956aa3bb87f754ae8cfb7028688c4d1b49c4102cc08', + 'bao-linux-amd64' => '865240e363a34d413c118ccd560ae1d29d6dad126da02a4fe36a2cdf6b19e29d' + } + + os = Gem::Platform.local.os + arch = Gem::Platform.local.cpu + arch = arch_map.fetch(arch, arch) + + package_file = "bao-#{os}-#{arch}" + + puts "Downloading binary `#{package_file}` from #{args.repo}" + + downloaded = download_package_file_version( version: version, repo: args.repo, - target_dir: args.dir, - clone_opts: %w[--depth 1 --recurse-submodules] + package_name: 'openbao-internal', + package_file: package_file, + package_checksums_sha256: checksums_sha256, + target_path: binary_target_path ) + + if downloaded + File.chmod(0o755, binary_target_path) + # Needed for TestEnv#component_needs_update? + File.write("#{args.dir}/VERSION", version) + else + puts "Checkout from #{args.repo}" + + checkout_or_clone_version( + version: version, + repo: args.repo, + target_dir: args.dir, + clone_opts: %w[--depth 1 --recurse-submodules] + ) + end end end end diff --git a/ee/spec/support/helpers/ee/test_env.rb b/ee/spec/support/helpers/ee/test_env.rb index 77bea38113b1811746eb9dee6ba9b0af45d547a9..6c5e9e63b0d426fcf3ed6e9683925895cc6eaf41 100644 --- a/ee/spec/support/helpers/ee/test_env.rb +++ b/ee/spec/support/helpers/ee/test_env.rb @@ -34,7 +34,7 @@ def setup_openbao 'OpenBao', install_dir: SecretsManagement::OpenbaoTestSetup.install_dir, version: SecretsManagement::SecretsManagerClient.expected_server_version, - task: "gitlab:secrets_management:openbao:clone", + task: "gitlab:secrets_management:openbao:download_or_clone", task_args: [SecretsManagement::OpenbaoTestSetup.install_dir] ) do raise ::TestEnv::ComponentFailedToInstallError unless SecretsManagement::OpenbaoTestSetup.build_openbao_binary diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb index a3b060719dbd0b991516f848c4b94ab3a6eac649..4c938702fb280a90bb029216d0471d16373bcdb2 100644 --- a/lib/gitlab/task_helpers.rb +++ b/lib/gitlab/task_helpers.rb @@ -2,6 +2,7 @@ require 'rainbow' require 'gitlab/utils/all' +require 'digest' # rubocop:disable Rails/Output module Gitlab @@ -153,6 +154,62 @@ def user_home Rails.env.test? ? Rails.root.join('tmp/tests') : Gitlab.config.gitlab.user_home end + def download_package_file_version( + version:, repo:, package_name:, package_file:, package_checksums_sha256:, + target_path:) + version = CGI.escape(version) + project_path = repo + .delete_prefix('https://gitlab.com/') + .delete_suffix('.git') + .then { |path| CGI.escape(path) } + package_name = CGI.escape(package_name) + package_file = CGI.escape(package_file) + + uri = URI("https://gitlab.com/api/v4/projects/#{project_path}/packages/generic/#{package_name}/#{version}/#{package_file}") + + success = true + + Tempfile.create(package_file, binmode: true) do |file| + Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http| + request = Net::HTTP::Get.new uri + + http.request(request) do |response| + if response.code == '302' + # Allow redirects + elsif response.code == '200' + response.read_body do |fragment| + file.write(fragment) + end + else + warn "HTTP Code: #{response.code} for #{uri}" + success = false + break + end + end + + file.close + + if success + expected = package_checksums_sha256[package_file] + actual = Digest::SHA256.file(file.path).hexdigest + + unless expected == actual + raise <<~MESSAGE + ERROR: Checksum mismatch for `#{package_file}`: + Expected: #{expected.inspect} + Actual: #{actual.inspect} + MESSAGE + end + + FileUtils.mkdir_p(File.dirname(target_path)) + FileUtils.mv(file, target_path) + end + end + end + + success + end + def checkout_or_clone_version(version:, repo:, target_dir:, clone_opts: []) clone_repo(repo, target_dir, clone_opts: clone_opts) unless Dir.exist?(target_dir) checkout_version(get_version(version), target_dir)