diff options
Diffstat (limited to 'lib/api/internal')
-rw-r--r-- | lib/api/internal/base.rb | 62 | ||||
-rw-r--r-- | lib/api/internal/kubernetes.rb | 95 |
2 files changed, 155 insertions, 2 deletions
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb index 6d4a4fc9c8b..17599c72243 100644 --- a/lib/api/internal/base.rb +++ b/lib/api/internal/base.rb @@ -18,6 +18,10 @@ module API UNKNOWN_CHECK_RESULT_ERROR = 'Unknown check result'.freeze + VALID_PAT_SCOPES = Set.new( + Gitlab::Auth::API_SCOPES + Gitlab::Auth::REPOSITORY_SCOPES + Gitlab::Auth::REGISTRY_SCOPES + ).freeze + helpers do def response_with_status(code: 200, success: true, message: nil, **extra_options) status code @@ -67,7 +71,7 @@ module API "uploadpack.allowAnySHA1InWant=true"], gitaly: gitaly_payload(params[:action]), gl_console_messages: check_result.console_messages - } + }.merge!(actor.key_details) # Custom option for git-receive-pack command @@ -92,7 +96,7 @@ module API # If we have created a project directly from a git push # we have to assign its value to both @project and @container - @project = @container = access_checker.project + @project = @container = access_checker.container end end end @@ -194,6 +198,60 @@ module API { success: true, recovery_codes: codes } end + post '/personal_access_token' do + status 200 + + actor.update_last_used_at! + user = actor.user + + if params[:key_id] + unless actor.key + break { success: false, message: 'Could not find the given key' } + end + + if actor.key.is_a?(DeployKey) + break { success: false, message: 'Deploy keys cannot be used to create personal access tokens' } + end + + unless user + break { success: false, message: 'Could not find a user for the given key' } + end + elsif params[:user_id] && user.nil? + break { success: false, message: 'Could not find the given user' } + end + + if params[:name].blank? + break { success: false, message: "No token name specified" } + end + + if params[:scopes].blank? + break { success: false, message: "No token scopes specified" } + end + + invalid_scope = params[:scopes].find { |scope| VALID_PAT_SCOPES.exclude?(scope.to_sym) } + + if invalid_scope + valid_scopes = VALID_PAT_SCOPES.map(&:to_s).sort + break { success: false, message: "Invalid scope: '#{invalid_scope}'. Valid scopes are: #{valid_scopes}" } + end + + begin + expires_at = params[:expires_at].presence && Date.parse(params[:expires_at]) + rescue ArgumentError + break { success: false, message: "Invalid token expiry date: '#{params[:expires_at]}'" } + end + + access_token = nil + + ::Users::UpdateService.new(current_user, user: user).execute! do |user| + access_token = user.personal_access_tokens.create!( + name: params[:name], scopes: params[:scopes], expires_at: expires_at + ) + end + + { success: true, token: access_token.token, scopes: access_token.scopes, expires_at: access_token.expires_at } + end + post '/pre_receive' do status 200 diff --git a/lib/api/internal/kubernetes.rb b/lib/api/internal/kubernetes.rb new file mode 100644 index 00000000000..7f64fd7efe3 --- /dev/null +++ b/lib/api/internal/kubernetes.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +module API + # Kubernetes Internal API + module Internal + class Kubernetes < Grape::API::Instance + helpers do + def agent_token + @agent_token ||= cluster_agent_token_from_authorization_token + end + + def agent + @agent ||= agent_token.agent + end + + def repo_type + Gitlab::GlRepository::PROJECT + end + + def gitaly_info(project) + shard = repo_type.repository_for(project).shard + { + address: Gitlab::GitalyClient.address(shard), + token: Gitlab::GitalyClient.token(shard), + features: Feature::Gitaly.server_feature_flags + } + end + + def gitaly_repository(project) + { + storage_name: project.repository_storage, + relative_path: project.disk_path + '.git', + gl_repository: repo_type.identifier_for_container(project), + gl_project_path: repo_type.repository_for(project).full_path + } + end + + def check_feature_enabled + not_found! unless Feature.enabled?(:kubernetes_agent_internal_api) + end + + def check_agent_token + forbidden! unless agent_token + end + end + + namespace 'internal' do + namespace 'kubernetes' do + before do + check_feature_enabled + check_agent_token + end + + desc 'Gets agent info' do + detail 'Retrieves agent info for the given token' + end + route_setting :authentication, cluster_agent_token_allowed: true + get '/agent_info' do + project = agent.project + + status 200 + { + project_id: project.id, + agent_id: agent.id, + agent_name: agent.name, + gitaly_info: gitaly_info(project), + gitaly_repository: gitaly_repository(project) + } + end + + desc 'Gets project info' do + detail 'Retrieves project info (if authorized)' + end + route_setting :authentication, cluster_agent_token_allowed: true + get '/project_info' do + project = find_project(params[:id]) + + # TODO sort out authorization for real + # https://gitlab.com/gitlab-org/gitlab/-/issues/220912 + if !project || !project.public? + not_found! + end + + status 200 + { + project_id: project.id, + gitaly_info: gitaly_info(project), + gitaly_repository: gitaly_repository(project) + } + end + end + end + end + end +end |