From 02ac9501731ff62e00122ad1bef86d6e42f43d08 Mon Sep 17 00:00:00 2001 From: Nicholas Wittstruck <1494491-nwittstruck@users.noreply.gitlab.com> Date: Wed, 8 Jan 2025 16:19:23 +0100 Subject: [PATCH 1/2] Admin Token API: Identify Feature Flags client token This commit adds identification of feature flags client token to the Admin Token API. Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/512283 Changelog: added --- .../client_configuration_entity.rb | 10 +++++++ doc/api/admin/token.md | 2 ++ lib/authn/agnostic_token_identifier.rb | 3 +- .../tokens/feature_flags_client_token.rb | 28 +++++++++++++++++++ .../feature_flags/client_configuration.json | 20 +++++++++++++ .../authn/agnostic_token_identifier_spec.rb | 2 ++ .../tokens/feature_flags_client_token_spec.rb | 28 +++++++++++++++++++ spec/requests/api/admin/token_spec.rb | 4 ++- .../client_configuration_entity_spec.rb | 17 +++++++++++ 9 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 app/serializers/feature_flags/client_configuration_entity.rb create mode 100644 lib/authn/tokens/feature_flags_client_token.rb create mode 100644 spec/fixtures/api/schemas/feature_flags/client_configuration.json create mode 100644 spec/lib/authn/tokens/feature_flags_client_token_spec.rb create mode 100644 spec/serializers/feature_flags/client_configuration_entity_spec.rb diff --git a/app/serializers/feature_flags/client_configuration_entity.rb b/app/serializers/feature_flags/client_configuration_entity.rb new file mode 100644 index 00000000000000..5a4c3e4cd55476 --- /dev/null +++ b/app/serializers/feature_flags/client_configuration_entity.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module FeatureFlags + class ClientConfigurationEntity < Grape::Entity + include RequestAwareEntity + + expose :id + expose :project_id + end +end diff --git a/doc/api/admin/token.md b/doc/api/admin/token.md index 7ec50c8daa4096..782c610f21fcc0 100644 --- a/doc/api/admin/token.md +++ b/doc/api/admin/token.md @@ -32,6 +32,7 @@ Prerequisites: > - [Runner authentication tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173987) in GitLab 17.7. > - [Pipeline trigger tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/174030) in GitLab 17.7. > - [CI/CD Job Tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/175234) in GitLab 17.9. +> - [Feature flags client tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177431) in GitLab 17.8. Gets information for a given token. This endpoint supports the following tokens: @@ -44,6 +45,7 @@ Gets information for a given token. This endpoint supports the following tokens: - [Runner authentication tokens](../../security/tokens/index.md#runner-authentication-tokens) - [Pipeline trigger tokens](../../ci/triggers/index.md#create-a-pipeline-trigger-token) - [CI/CD Job Tokens](../../security/tokens/index.md#cicd-job-tokens) +- [Feature flags client tokens](../../operations/feature_flags.md#get-access-credentials) ```plaintext POST /api/v4/admin/token diff --git a/lib/authn/agnostic_token_identifier.rb b/lib/authn/agnostic_token_identifier.rb index 6d8c7cda707315..e83661cbd356c9 100644 --- a/lib/authn/agnostic_token_identifier.rb +++ b/lib/authn/agnostic_token_identifier.rb @@ -12,7 +12,8 @@ class AgnosticTokenIdentifier ::Authn::Tokens::ClusterAgentToken, ::Authn::Tokens::RunnerAuthenticationToken, ::Authn::Tokens::CiTriggerToken, - ::Authn::Tokens::CiJobToken + ::Authn::Tokens::CiJobToken, + ::Authn::Tokens::FeatureFlagsClientToken ].freeze def self.token_for(plaintext, source) diff --git a/lib/authn/tokens/feature_flags_client_token.rb b/lib/authn/tokens/feature_flags_client_token.rb new file mode 100644 index 00000000000000..f6c6c64a4f9daa --- /dev/null +++ b/lib/authn/tokens/feature_flags_client_token.rb @@ -0,0 +1,28 @@ +# frozen_string_literal:true + +module Authn + module Tokens + class FeatureFlagsClientToken + def self.prefix?(plaintext) + plaintext.start_with?(::Operations::FeatureFlagsClient::FEATURE_FLAGS_CLIENT_TOKEN_PREFIX) + end + + attr_reader :revocable, :source + + def initialize(plaintext, source) + @revocable = ::Operations::FeatureFlagsClient.find_by_token(plaintext) + @source = source + end + + def present_with + ::FeatureFlags::ClientConfigurationEntity + 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/fixtures/api/schemas/feature_flags/client_configuration.json b/spec/fixtures/api/schemas/feature_flags/client_configuration.json new file mode 100644 index 00000000000000..05ffc9a3f85b17 --- /dev/null +++ b/spec/fixtures/api/schemas/feature_flags/client_configuration.json @@ -0,0 +1,20 @@ +{ + "type": "object", + "required": [ + "id", + "project_id" + ], + "properties": { + "id": { + "type": [ + "integer" + ] + }, + "project_id": { + "type": [ + "integer" + ] + } + }, + "additionalProperties": false +} diff --git a/spec/lib/authn/agnostic_token_identifier_spec.rb b/spec/lib/authn/agnostic_token_identifier_spec.rb index 9f28c4931534cf..3a5d98abe418e0 100644 --- a/spec/lib/authn/agnostic_token_identifier_spec.rb +++ b/spec/lib/authn/agnostic_token_identifier_spec.rb @@ -22,6 +22,7 @@ let_it_be(:cluster_agent_token) { create(:cluster_agent_token, token_encrypted: nil).token } let_it_be(:runner_authentication_token) { create(:ci_runner, registration_type: :authenticated_user).token } let_it_be(:ci_trigger_token) { create(:ci_trigger).token } + let_it_be(:feature_flags_client_token) { create(:operations_feature_flags_client).token } subject(:token) { described_class.token_for(plaintext, :group_token_revocation_service) } @@ -35,6 +36,7 @@ ref(:cluster_agent_token) | ::Authn::Tokens::ClusterAgentToken ref(:runner_authentication_token) | ::Authn::Tokens::RunnerAuthenticationToken ref(:ci_trigger_token) | ::Authn::Tokens::CiTriggerToken + ref(:feature_flags_client_token) | ::Authn::Tokens::FeatureFlagsClientToken 'unsupported' | NilClass end diff --git a/spec/lib/authn/tokens/feature_flags_client_token_spec.rb b/spec/lib/authn/tokens/feature_flags_client_token_spec.rb new file mode 100644 index 00000000000000..d7b9527200011f --- /dev/null +++ b/spec/lib/authn/tokens/feature_flags_client_token_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Authn::Tokens::FeatureFlagsClientToken, feature_category: :system_access do + let_it_be(:user) { create(:user) } + + let(:feature_flags_client) { create(:operations_feature_flags_client) } + + subject(:token) { described_class.new(plaintext, :api_admin_token) } + + context 'with valid Feature Flags Client token' do + let(:plaintext) { feature_flags_client.token } + let(:valid_revocable) { feature_flags_client } + + 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 f3f464b5c8999f..32eab9a622b50b 100644 --- a/spec/requests/api/admin/token_spec.rb +++ b/spec/requests/api/admin/token_spec.rb @@ -54,6 +54,7 @@ let(:impersonation_token) { create(:personal_access_token, :impersonation, user: user) } let(:ci_trigger) { create(:ci_trigger) } let(:ci_build) { create(:ci_build, status: :running) } + let(:feature_flags_client) { create(:operations_feature_flags_client) } let(:plaintext) { nil } let(:params) { { token: plaintext } } @@ -73,7 +74,8 @@ [ref(:cluster_agent_token), lazy { cluster_agent_token.token }], [ref(:runner_authentication_token), lazy { runner_authentication_token.token }], [ref(:impersonation_token), lazy { impersonation_token.token }], - [ref(:ci_trigger), lazy { ci_trigger.token }] + [ref(:ci_trigger), lazy { ci_trigger.token }], + [ref(:feature_flags_client), lazy { feature_flags_client.token }] ] end diff --git a/spec/serializers/feature_flags/client_configuration_entity_spec.rb b/spec/serializers/feature_flags/client_configuration_entity_spec.rb new file mode 100644 index 00000000000000..0b7de6c28c9045 --- /dev/null +++ b/spec/serializers/feature_flags/client_configuration_entity_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe FeatureFlags::ClientConfigurationEntity, factory_default: :keep, feature_category: :feature_flags do + let_it_be(:project) { create_default(:project) } + let(:feature_flags_client) { project.create_operations_feature_flags_client! } + let(:entity) { described_class.new(feature_flags_client) } + + describe '#to_json' do + subject(:json) { entity.to_json } + + it 'matches schema' do + expect(json).to match_schema('feature_flags/client_configuration') + end + end +end -- GitLab From c62e13c3cbfc2a392dcf2c668042bcdf0ea57f9d Mon Sep 17 00:00:00 2001 From: Nicholas Wittstruck <1494491-nwittstruck@users.noreply.gitlab.com> Date: Sat, 11 Jan 2025 16:51:37 +0100 Subject: [PATCH 2/2] Admin Token API: Identify Feature Flags client token This commit updates the milestone to 17.9. Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/512283 Changelog: added --- doc/api/admin/token.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/admin/token.md b/doc/api/admin/token.md index 782c610f21fcc0..ad703fde91fe8b 100644 --- a/doc/api/admin/token.md +++ b/doc/api/admin/token.md @@ -32,7 +32,7 @@ Prerequisites: > - [Runner authentication tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173987) in GitLab 17.7. > - [Pipeline trigger tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/174030) in GitLab 17.7. > - [CI/CD Job Tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/175234) in GitLab 17.9. -> - [Feature flags client tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177431) in GitLab 17.8. +> - [Feature flags client tokens added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177431) in GitLab 17.9. Gets information for a given token. This endpoint supports the following tokens: -- GitLab