gitlab-ce/lib/api/terraform/modules/v1/project_packages.rb

201 lines
7.6 KiB
Ruby

# frozen_string_literal: true
module API
module Terraform
module Modules
module V1
class ProjectPackages < ::API::Base
include ::API::Helpers::Authentication
helpers ::API::Helpers::PackagesHelpers
helpers ::API::Helpers::Packages::BasicAuthHelpers
feature_category :package_registry
urgency :low
after_validation do
require_packages_enabled!
end
helpers do
params :terraform_get do
optional 'terraform-get', type: String, values: %w[1], desc: 'Terraform get redirection flag'
end
def present_package_file
authorize_read_package!(authorized_user_project)
if declared_params[:'terraform-get'] == '1'
header 'X-Terraform-Get', "#{request.url.split('?').first}?archive=tgz"
return no_content!
end
package = ::Packages::TerraformModule::PackagesFinder
.new(authorized_user_project, finder_params)
.execute
.first
not_found! unless package
track_package_event('pull_package', :terraform_module, project: authorized_user_project,
namespace: authorized_user_project.namespace)
present_package_file!(package.installable_package_files.first)
end
def finder_params
{ package_name: package_name }.tap do |finder_params|
finder_params[:package_version] = params[:module_version] if params.key?(:module_version)
end
end
def package_name
"#{params[:module_name]}/#{params[:module_system]}"
end
def authorize_workhorse_params
{
subject: authorized_user_project,
maximum_size: authorized_user_project.actual_limits.terraform_module_max_file_size,
use_final_store_path: true
}
end
end
params do
requires :id, types: [String, Integer], allow_blank: false, desc: 'The ID or full path of a project'
with(type: String, allow_blank: false, regexp: API::NO_SLASH_URL_PART_REGEX) do
requires :module_name, desc: 'Module name', documentation: { example: 'infra-registry' }
requires :module_system, desc: 'Module system', documentation: { example: 'aws' }
end
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
namespace ':id/packages/terraform/modules/:module_name/:module_system' do
authenticate_with do |accept|
accept.token_types(
:personal_access_token_with_username,
:deploy_token_with_username,
:job_token_with_username
).sent_through(:http_basic_auth)
end
desc 'Download the latest version of a module' do
detail 'This feature was introduced in GitLab 16.7'
success code: 204
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not found' }
]
tags %w[terraform_registry]
end
params do
use :terraform_get
end
get do
present_package_file
end
params do
requires :module_version, type: String, allow_blank: false, desc: 'Module version',
regexp: Gitlab::Regex.semver_regex
end
namespace '*module_version' do
desc 'Download a specific version of a module' do
detail 'This feature was introduced in GitLab 16.7'
success code: 204
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not found' }
]
tags %w[terraform_registry]
end
params do
use :terraform_get
end
get format: false do
present_package_file
end
namespace :file do
authenticate_with do |accept|
accept.token_types(:deploy_token).sent_through(:http_deploy_token_header)
accept.token_types(:job_token).sent_through(:http_job_token_header)
accept.token_types(:personal_access_token).sent_through(:http_private_token_header)
end
desc 'Workhorse authorize Terraform Module package file' do
detail 'This feature was introduced in GitLab 13.11'
success code: 200
failure [
{ code: 403, message: 'Forbidden' }
]
tags %w[terraform_registry]
end
put :authorize do
authorize_workhorse!(**authorize_workhorse_params)
end
desc 'Upload Terraform Module package file' do
detail 'This feature was introduced in GitLab 13.11'
success code: 201
failure [
{ code: 400, message: 'Invalid file' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not found' }
]
consumes %w[multipart/form-data]
tags %w[terraform_registry]
end
params do
requires :file, type: ::API::Validations::Types::WorkhorseFile,
desc: 'The package file to be published (generated by Multipart middleware)',
documentation: { type: 'file' }
end
put do
authorize_upload!(authorized_user_project)
bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(
:terraform_module_max_file_size, params[:file].size
)
create_package_file_params = {
module_name: params['module_name'],
module_system: params['module_system'],
module_version: params['module_version'],
file: params['file'],
build: current_authenticated_job
}
result = ::Packages::TerraformModule::CreatePackageService
.new(authorized_user_project, current_user, create_package_file_params)
.execute
render_api_error!(result.message, result.reason) if result.error?
track_package_event('push_package', :terraform_module, project: authorized_user_project,
namespace: authorized_user_project.namespace)
created!
rescue ObjectStorage::RemoteStoreError => e
Gitlab::ErrorTracking.track_exception(e,
extra: { file_name: params[:file_name], project_id: authorized_user_project.id })
forbidden!
end
end
end
end
end
end
end
end
end
end