mirror of
https://github.com/gitlabhq/gitlabhq.git
synced 2025-07-23 00:45:28 +00:00
206 lines
7.5 KiB
Ruby
206 lines
7.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module API
|
|
module Helpers
|
|
module Kubernetes
|
|
module AgentHelpers
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
COUNTERS_EVENTS_MAPPING = {
|
|
'flux_git_push_notifications_total' => 'create_flux_git_push_notification',
|
|
'k8s_api_proxy_request' => 'request_api_proxy_access',
|
|
'k8s_api_proxy_requests_via_ci_access' => 'request_api_proxy_access_via_ci',
|
|
'k8s_api_proxy_requests_via_user_access' => 'request_api_proxy_access_via_user',
|
|
'k8s_api_proxy_requests_via_pat_access' => 'request_api_proxy_access_via_pat'
|
|
}.freeze
|
|
|
|
def agent_token
|
|
cluster_agent_token_from_authorization_token
|
|
end
|
|
strong_memoize_attr :agent_token
|
|
|
|
def agent
|
|
agent_token.agent
|
|
end
|
|
strong_memoize_attr :agent
|
|
|
|
def check_agent_token
|
|
unauthorized! unless agent_token
|
|
|
|
::Clusters::AgentTokens::TrackUsageService.new(agent_token).execute
|
|
end
|
|
|
|
def agent_has_access_to_project?(project)
|
|
::Users::Anonymous.can?(:download_code, project) || agent.has_access_to?(project)
|
|
end
|
|
|
|
def increment_unique_events
|
|
events = params[:unique_counters]&.slice(
|
|
:k8s_api_proxy_requests_unique_agents_via_ci_access,
|
|
:k8s_api_proxy_requests_unique_agents_via_user_access,
|
|
:k8s_api_proxy_requests_unique_agents_via_pat_access,
|
|
:flux_git_push_notified_unique_projects
|
|
)
|
|
|
|
events&.each do |event, entity_ids|
|
|
increment_unique_values(event, entity_ids)
|
|
end
|
|
end
|
|
|
|
def track_events
|
|
event_lists = params[:events]&.slice(
|
|
:k8s_api_proxy_requests_unique_users_via_ci_access,
|
|
:k8s_api_proxy_requests_unique_users_via_user_access,
|
|
:k8s_api_proxy_requests_unique_users_via_pat_access,
|
|
:register_agent_at_kas
|
|
)
|
|
return if event_lists.blank?
|
|
|
|
event_lists[:agent_users_using_ci_tunnel] = event_lists.slice(
|
|
:k8s_api_proxy_requests_unique_users_via_ci_access,
|
|
:k8s_api_proxy_requests_unique_users_via_user_access,
|
|
:k8s_api_proxy_requests_unique_users_via_pat_access
|
|
).values.compact.flatten
|
|
|
|
users, projects = load_users_and_projects(event_lists)
|
|
event_lists.each do |event_name, events|
|
|
track_events_for(event_name, events, users, projects) if events
|
|
end
|
|
end
|
|
|
|
def track_unique_user_events
|
|
events = params[:unique_counters]&.slice(
|
|
:k8s_api_proxy_requests_unique_users_via_ci_access,
|
|
:k8s_api_proxy_requests_unique_users_via_user_access,
|
|
:k8s_api_proxy_requests_unique_users_via_pat_access
|
|
)
|
|
return if events.blank?
|
|
|
|
unique_user_ids = events.values.flatten.uniq
|
|
users = User.id_in(unique_user_ids).index_by(&:id)
|
|
|
|
events.each do |event, user_ids|
|
|
user_ids.each do |user_id|
|
|
user = users[user_id]
|
|
next if user.nil?
|
|
|
|
Gitlab::InternalEvents.track_event(event, user: user)
|
|
end
|
|
end
|
|
end
|
|
|
|
def increment_count_events
|
|
counters = params[:counters]&.slice(*COUNTERS_EVENTS_MAPPING.keys)
|
|
|
|
return unless counters.present?
|
|
|
|
counters.each do |counter, incr|
|
|
next if incr == 0
|
|
|
|
event = COUNTERS_EVENTS_MAPPING[counter]
|
|
|
|
Gitlab::InternalEvents.with_batched_redis_writes do
|
|
incr.times { Gitlab::InternalEvents.track_event(event) }
|
|
end
|
|
end
|
|
end
|
|
|
|
def update_configuration(agent:, config:)
|
|
::Clusters::Agents::Authorizations::CiAccess::RefreshService.new(agent, config: config).execute
|
|
::Clusters::Agents::Authorizations::UserAccess::RefreshService.new(agent, config: config).execute
|
|
end
|
|
|
|
def retrieve_user_from_session_cookie
|
|
# Load session
|
|
public_session_id_string =
|
|
begin
|
|
Gitlab::Kas::UserAccess.decrypt_public_session_id(params[:access_key])
|
|
rescue StandardError
|
|
bad_request!('Invalid access_key')
|
|
end
|
|
|
|
session_id = Rack::Session::SessionId.new(public_session_id_string)
|
|
session = ActiveSession.sessions_from_ids([session_id.private_id]).first
|
|
unauthorized!('Invalid session') unless session
|
|
|
|
# CSRF check
|
|
unless ::Gitlab::Kas::UserAccess.valid_authenticity_token?(session.symbolize_keys, params[:csrf_token])
|
|
unauthorized!('CSRF token does not match')
|
|
end
|
|
|
|
# Load user
|
|
user = Warden::SessionSerializer.new('rack.session' => session).fetch(:user)
|
|
unauthorized!('Invalid user in session') unless user
|
|
user
|
|
end
|
|
|
|
def retrieve_user_from_personal_access_token
|
|
return unless access_token.present?
|
|
|
|
validate_and_save_access_token!(scopes: [Gitlab::Auth::K8S_PROXY_SCOPE])
|
|
|
|
::PersonalAccessTokens::LastUsedService.new(access_token).execute
|
|
|
|
access_token.user || raise(UnauthorizedError)
|
|
end
|
|
|
|
def set_agent_on_context(agent:)
|
|
::Gitlab::ApplicationContext.push(kubernetes_agent: agent)
|
|
end
|
|
|
|
def access_token
|
|
return unless params[:access_key].present?
|
|
|
|
PersonalAccessToken.find_by_token(params[:access_key])
|
|
end
|
|
strong_memoize_attr :access_token
|
|
|
|
private
|
|
|
|
def load_users_and_projects(event_lists)
|
|
all_events = event_lists.values.flatten.compact
|
|
unique_user_ids = all_events.pluck('user_id').compact.uniq # rubocop:disable CodeReuse/ActiveRecord -- this pluck isn't from ActiveRecord, it's from ActiveSupport
|
|
unique_project_ids = all_events.pluck('project_id').compact.uniq # rubocop:disable CodeReuse/ActiveRecord -- this pluck isn't from ActiveRecord, it's from ActiveSupport
|
|
users = User.id_in(unique_user_ids).index_by(&:id)
|
|
projects = Project.id_in(unique_project_ids).index_by(&:id)
|
|
[users, projects]
|
|
end
|
|
|
|
def track_events_for(event_name, events, users, projects)
|
|
events.each do |event|
|
|
next if event.blank?
|
|
|
|
user = users[event[:user_id]]
|
|
project = projects[event[:project_id]]
|
|
next if project.nil?
|
|
|
|
additional_properties = {}
|
|
if event_name.to_sym == :register_agent_at_kas
|
|
additional_properties = {
|
|
# built-in properties
|
|
label: event[:agent_version],
|
|
property: event[:architecture]
|
|
}
|
|
additional_properties[:value] = event[:agent_id] if event[:agent_id].present?
|
|
|
|
# custom properties
|
|
installation_method = event.dig(:extra_telemetry_data, :installation_method)
|
|
helm_chart_version = event.dig(:extra_telemetry_data, :helm_chart_version)
|
|
|
|
if event[:kubernetes_version].present?
|
|
additional_properties[:kubernetes_version] = event[:kubernetes_version]
|
|
end
|
|
|
|
additional_properties[:installation_method] = installation_method if installation_method.present?
|
|
additional_properties[:helm_chart_version] = helm_chart_version if helm_chart_version.present?
|
|
end
|
|
|
|
Gitlab::InternalEvents.track_event(event_name, additional_properties: additional_properties, user: user,
|
|
project: project)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|