diff options
Diffstat (limited to 'lib/api/terraform/state.rb')
-rw-r--r-- | lib/api/terraform/state.rb | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/lib/api/terraform/state.rb b/lib/api/terraform/state.rb index 577d011ebad..bdc9f975970 100644 --- a/lib/api/terraform/state.rb +++ b/lib/api/terraform/state.rb @@ -20,6 +20,8 @@ module API render_api_error!(e.message, 422) end + STATE_NAME_URI_REQUIREMENTS = { name: API::NO_SLASH_URL_PART_REGEX }.freeze + before do authenticate! authorize! :read_terraform_state, user_project @@ -45,7 +47,7 @@ module API end resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do - namespace ':id/terraform/state/:name' do + namespace ':id/terraform/state/:name', requirements: STATE_NAME_URI_REQUIREMENTS do params do requires :name, type: String, desc: 'The name of a Terraform state' optional :ID, type: String, limit: 255, desc: 'Terraform state lock ID' @@ -55,6 +57,17 @@ module API def remote_state_handler ::Terraform::RemoteStateHandler.new(user_project, current_user, name: params[:name], lock_id: params[:ID]) end + + def not_found_for_dots? + Feature.disabled?(:allow_dots_on_tf_state_names) && params[:name].include?(".") + end + + # Change the state name to behave like before, https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105674 + # has been introduced. This behavior can be controlled via `allow_dots_on_tf_state_names` FF. + # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106861 + def legacy_state_name! + params[:name] = params[:name].split('.').first + end end desc 'Get a Terraform state by its name' do @@ -72,6 +85,8 @@ module API end route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth get do + legacy_state_name! if not_found_for_dots? + remote_state_handler.find_with_lock do |state| no_content! unless state.latest_file && state.latest_file.exists? @@ -88,17 +103,22 @@ module API ] failure [ { code: 403, message: 'Forbidden' }, - { code: 422, message: 'Validation failure' } + { code: 422, message: 'Validation failure' }, + { code: 413, message: 'Request Entity Too Large' } ] tags %w[terraform_state] end route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth post do authorize! :admin_terraform_state, user_project + legacy_state_name! if not_found_for_dots? data = request.body.read no_content! if data.empty? + max_state_size = Gitlab::CurrentSettings.max_terraform_state_size_bytes + file_too_large! if max_state_size > 0 && data.size > max_state_size + remote_state_handler.handle_with_lock do |state| state.update_file!(CarrierWaveStringFile.new(data), version: params[:serial], build: current_authenticated_job) end @@ -120,6 +140,7 @@ module API route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth delete do authorize! :admin_terraform_state, user_project + legacy_state_name! if not_found_for_dots? remote_state_handler.find_with_lock do |state| ::Terraform::States::TriggerDestroyService.new(state, current_user: current_user).execute @@ -151,6 +172,8 @@ module API requires :Path, type: String, desc: 'Terraform path' end post '/lock' do + not_found! if not_found_for_dots? + authorize! :admin_terraform_state, user_project status_code = :ok @@ -194,6 +217,8 @@ module API optional :ID, type: String, limit: 255, desc: 'Terraform state lock ID' end delete '/lock' do + not_found! if not_found_for_dots? + authorize! :admin_terraform_state, user_project remote_state_handler.unlock! |