From 401f5a1f70ca1d021c953eccb2f1e33c49b9ae71 Mon Sep 17 00:00:00 2001 From: Nicholas Wittstruck <1494491-nwittstruck@users.noreply.gitlab.com> Date: Fri, 15 Nov 2024 17:01:11 +0100 Subject: [PATCH] Admin Token API: Cluster Agent Tokens This commit adds support for cluster agent tokens to the Admin Token API. Changelog: added --- doc/api/admin/token.md | 2 ++ lib/authn/agnostic_token_identifier.rb | 3 +- lib/authn/tokens/cluster_agent_token.rb | 28 +++++++++++++++++++ .../authn/agnostic_token_identifier_spec.rb | 2 ++ .../authn/tokens/cluster_agent_token_spec.rb | 28 +++++++++++++++++++ spec/requests/api/admin/token_spec.rb | 4 ++- 6 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 lib/authn/tokens/cluster_agent_token.rb create mode 100644 spec/lib/authn/tokens/cluster_agent_token_spec.rb diff --git a/doc/api/admin/token.md b/doc/api/admin/token.md index 74c8c31b2302ae..d801666497576e 100644 --- a/doc/api/admin/token.md +++ b/doc/api/admin/token.md @@ -15,6 +15,7 @@ DETAILS: > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165157) in GitLab 17.5 [with a flag](../../administration/feature_flags.md) named `admin_agnostic_token_finder`. Disabled by default. > - [Feed tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169821) in GitLab 17.6. > - [OAuth application secrets added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/172985) in GitLab 17.7. +> - [Cluster agent tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/172932) in GitLab 17.7. FLAG: The availability of this feature is controlled by a feature flag. @@ -39,6 +40,7 @@ Supported tokens: - [Deploy tokens](../../user/project/deploy_tokens/index.md) - [Feed tokens](../../security/tokens/index.md#feed-token) - [OAuth application secrets](../../integration/oauth_provider.md) +- [Cluster agent tokens](../../security/tokens/index.md#gitlab-cluster-agent-tokens) ```plaintext POST /api/v4/admin/token diff --git a/lib/authn/agnostic_token_identifier.rb b/lib/authn/agnostic_token_identifier.rb index 7f04f75e1bcc72..148d974693c739 100644 --- a/lib/authn/agnostic_token_identifier.rb +++ b/lib/authn/agnostic_token_identifier.rb @@ -8,7 +8,8 @@ class AgnosticTokenIdentifier ::Authn::Tokens::DeployToken, ::Authn::Tokens::FeedToken, ::Authn::Tokens::PersonalAccessToken, - ::Authn::Tokens::OauthApplicationSecret + ::Authn::Tokens::OauthApplicationSecret, + ::Authn::Tokens::ClusterAgentToken ].freeze def self.token_for(plaintext, source) diff --git a/lib/authn/tokens/cluster_agent_token.rb b/lib/authn/tokens/cluster_agent_token.rb new file mode 100644 index 00000000000000..d507a3dacace6b --- /dev/null +++ b/lib/authn/tokens/cluster_agent_token.rb @@ -0,0 +1,28 @@ +# frozen_string_literal:true + +module Authn + module Tokens + class ClusterAgentToken + def self.prefix?(plaintext) + plaintext.start_with?(::Clusters::AgentToken::TOKEN_PREFIX) + end + + attr_reader :revocable, :source + + def initialize(plaintext, source) + @revocable = ::Clusters::AgentToken.find_by_token(plaintext) + @source = source + end + + def present_with + ::API::Entities::Clusters::AgentToken + end + + def revoke!(_current_user) + raise ::Authn::AgnosticTokenIdentifier::NotFoundError, 'Not Found' if revocable.blank? + + raise ::Authn::AgnosticTokenIdentifier::UnsupportedTokenError, 'Unsupported token type' + end + end + end +end diff --git a/spec/lib/authn/agnostic_token_identifier_spec.rb b/spec/lib/authn/agnostic_token_identifier_spec.rb index 386b91894c2194..424cc75729d3cb 100644 --- a/spec/lib/authn/agnostic_token_identifier_spec.rb +++ b/spec/lib/authn/agnostic_token_identifier_spec.rb @@ -10,6 +10,7 @@ let_it_be(:feed_token) { user.feed_token } let_it_be(:personal_access_token) { create(:personal_access_token, user: user).token } let_it_be(:oauth_application_secret) { create(:oauth_application).plaintext_secret } + let_it_be(:cluster_agent_token) { create(:cluster_agent_token, token_encrypted: nil).token } subject(:token) { described_class.token_for(plaintext, :group_token_revocation_service) } @@ -19,6 +20,7 @@ ref(:feed_token) | ::Authn::Tokens::FeedToken ref(:deploy_token) | ::Authn::Tokens::DeployToken ref(:oauth_application_secret) | ::Authn::Tokens::OauthApplicationSecret + ref(:cluster_agent_token) | ::Authn::Tokens::ClusterAgentToken 'unsupported' | NilClass end diff --git a/spec/lib/authn/tokens/cluster_agent_token_spec.rb b/spec/lib/authn/tokens/cluster_agent_token_spec.rb new file mode 100644 index 00000000000000..4f93ad537ca7e4 --- /dev/null +++ b/spec/lib/authn/tokens/cluster_agent_token_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Authn::Tokens::ClusterAgentToken, feature_category: :system_access do + let_it_be(:user) { create(:user) } + + let(:cluster_agent_token) { create(:cluster_agent_token, token_encrypted: nil) } + + subject(:token) { described_class.new(plaintext, :api_admin_token) } + + context 'with valid cluster agent token' do + let(:plaintext) { cluster_agent_token.token } + let(:valid_revocable) { cluster_agent_token } + + it_behaves_like 'finding the valid revocable' + + describe '#revoke!' do + it 'does not support revocation yet' do + expect do + token.revoke!(user) + end.to raise_error(::Authn::AgnosticTokenIdentifier::UnsupportedTokenError, 'Unsupported token type') + end + end + end + + it_behaves_like 'token handling with unsupported token type' +end diff --git a/spec/requests/api/admin/token_spec.rb b/spec/requests/api/admin/token_spec.rb index 2f411f6aab1a34..60b6dda764af23 100644 --- a/spec/requests/api/admin/token_spec.rb +++ b/spec/requests/api/admin/token_spec.rb @@ -11,6 +11,7 @@ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) } let_it_be(:deploy_token) { create(:deploy_token) } let_it_be(:oauth_application) { create(:oauth_application) } + let_it_be(:cluster_agent_token) { create(:cluster_agent_token, token_encrypted: nil) } let(:plaintext) { nil } let(:params) { { token: plaintext } } @@ -25,7 +26,8 @@ [ref(:personal_access_token), lazy { personal_access_token.token }], [ref(:deploy_token), lazy { deploy_token.token }], [ref(:user), lazy { user.feed_token }], - [ref(:oauth_application), lazy { oauth_application.plaintext_secret }] + [ref(:oauth_application), lazy { oauth_application.plaintext_secret }], + [ref(:cluster_agent_token), lazy { cluster_agent_token.token }] ] end -- GitLab