Skip to content
Snippets Groups Projects
Verified Commit f52fe519 authored by Aboobacker MK's avatar Aboobacker MK :three: Committed by GitLab
Browse files

Merge branch 'tachyons_disable_personal_access_tokens' into 'master'

Disable personal access tokens for enterprise users

See merge request !148415



Merged-by: Aboobacker MK's avatarAboobacker MK <akarakath@gitlab.com>
Approved-by: Imre Farkas's avatarImre Farkas <ifarkas@gitlab.com>
Approved-by: default avatarTiger Watson <twatson@gitlab.com>
Reviewed-by: default avatarDrew Blessing <drew@gitlab.com>
Reviewed-by: Imre Farkas's avatarImre Farkas <ifarkas@gitlab.com>
Reviewed-by: default avatarTiger Watson <twatson@gitlab.com>
Reviewed-by: Aboobacker MK's avatarAboobacker MK <akarakath@gitlab.com>
Co-authored-by: default avatarJon Glassman <jglassman@gitlab.com>
Co-authored-by: default avatarDrew Blessing <drew@gitlab.com>
parents 25d81f88 cbf59303
No related branches found
No related tags found
1 merge request!148415Disable personal access tokens for enterprise users
Pipeline #1250368121 passed
Showing
with 237 additions and 9 deletions
......@@ -74,3 +74,5 @@ def check_personal_access_tokens_enabled
end
end
end
UserSettings::PersonalAccessTokensController.prepend_mod
......@@ -50,6 +50,7 @@
= render 'groups/settings/two_factor_auth', f: f, group: @group
= render_if_exists 'groups/personal_access_token_expiration_policy', f: f, group: @group
= render 'groups/settings/membership', f: f, group: @group
= render_if_exists 'groups/settings/personal_access_tokens', f: f, group: @group
%h5= _('Customer relations')
.form-group.gl-mb-3
......
# frozen_string_literal: true
class AddDisablePersonalAccessTokensToNamespaceSettings < Gitlab::Database::Migration[2.2]
milestone '16.11'
def change
add_column :namespace_settings, :disable_personal_access_tokens, :boolean, default: false, null: false
end
end
bd1e2bdc4fda7c033a3407516450f15b45bfab4d6600a7bc940d10ca38f3e491
\ No newline at end of file
......@@ -11882,6 +11882,7 @@ CREATE TABLE namespace_settings (
lock_math_rendering_limits_enabled boolean DEFAULT false NOT NULL,
duo_features_enabled boolean,
lock_duo_features_enabled boolean DEFAULT false NOT NULL,
disable_personal_access_tokens boolean DEFAULT false NOT NULL,
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT namespace_settings_unique_project_download_limit_alertlist_size CHECK ((cardinality(unique_project_download_limit_alertlist) <= 100)),
CONSTRAINT namespace_settings_unique_project_download_limit_allowlist_size CHECK ((cardinality(unique_project_download_limit_allowlist) <= 100))
......@@ -97,6 +97,7 @@ def group_params_ee
params_ee << { value_stream_dashboard_aggregation_attributes: [:enabled] } if can?(current_user, :modify_value_stream_dashboard_settings, current_group)
params_ee << :experiment_features_enabled if experiment_settings_allowed?
params_ee.push(%i[duo_features_enabled lock_duo_features_enabled]) if licensed_ai_features_available?
params_ee << :disable_personal_access_tokens
end + security_policies_toggle_params
end
......
# frozen_string_literal: true
module EE
module UserSettings
module PersonalAccessTokensController
extend ::Gitlab::Utils::Override
override :check_personal_access_tokens_enabled
def check_personal_access_tokens_enabled
super
return unless current_user.enterprise_user? && current_user.enterprise_group.disable_personal_access_tokens?
render_404
end
end
end
end
......@@ -97,6 +97,8 @@ module Group
delegate :experiment_settings_allowed?, to: :namespace_settings
delegate :user_cap_enabled?, to: :namespace_settings
delegate :disable_personal_access_tokens=, to: :namespace_settings
delegate :wiki_access_level, :wiki_access_level=, to: :group_feature, allow_nil: true
# Use +checked_file_template_project+ instead, which implements important
......@@ -1009,6 +1011,14 @@ def code_suggestions_purchased?
::GitlabSubscriptions::AddOnPurchase.active.for_gitlab_duo_pro.exists?(namespace_id: id)
end
# Disable personal access tokens for enterprise users of this group
def disable_personal_access_tokens?
::Feature.enabled?(:enterprise_disable_personal_access_tokens, self) &&
root? &&
licensed_feature_available?(:disable_personal_access_tokens) &&
namespace_settings.disable_personal_access_tokens?
end
private
def active_project_tokens_of_root_ancestor
......
......@@ -59,6 +59,8 @@ module User
:onboarding_status_registration_type, :onboarding_status_registration_type=,
:onboarding_status_email_opt_in, :onboarding_status_email_opt_in=, :onboarding_status, :onboarding_status=,
:onboarding_status_initial_registration_type, :onboarding_status_initial_registration_type=,
:enterprise_group, :enterprise_group=,
:enterprise_group_id, :enterprise_group_id=,
to: :user_detail, allow_nil: true
delegate :enabled_zoekt?, :enabled_zoekt, :enabled_zoekt=,
......@@ -525,11 +527,13 @@ def authorized_by_provisioning_group?(group)
end
def enterprise_user_of_group?(group)
user_detail.enterprise_group_id == group.id
enterprise_group_id == group.id
end
def enterprise_user?
user_detail.enterprise_group.present?
# NOTE: Double check is added since enterprise_group_id is a lose foreign key and this is a high traffic method
# This would make sure that we don't fire a query in most cases on gitlab.com, as we have more normal users than enterprise users.
enterprise_group_id.present? && enterprise_group.present?
end
def gitlab_employee?
......
- return unless group.root? && group.licensed_feature_available?(:disable_personal_access_tokens)
%h5= _('Personal access tokens')
.form-group.gl-mb-3
= f.gitlab_ui_checkbox_component :disable_personal_access_tokens, checkbox_options: { checked: group.disable_personal_access_tokens? } do |c|
- c.with_label do
= s_('GroupSettings|Disable personal access tokens')
- c.with_help_text do
= s_("GroupSettings|If enabled, enterprise user accounts will not be able to use personal access tokens.")
---
name: enterprise_disable_personal_access_tokens
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369504
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148415
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/455064
milestone: '16.11'
group: group::authentication
type: gitlab_com_derisk
default_enabled: false
......@@ -37,6 +37,17 @@ def find_oauth_access_token
super
end
override :find_user_from_access_token
def find_user_from_access_token
user = super
disable_personal_access_tokens = user&.enterprise_user? &&
user.enterprise_group.disable_personal_access_tokens?
return user unless disable_personal_access_tokens
raise ::Gitlab::Auth::UnauthorizedError
end
def scim_request?
current_request.path.starts_with?("/api/scim/")
end
......
# frozen_string_literal: true
module EE
module Sidebars
module UserSettings
module Menus
module AccessTokensMenu
extend ::Gitlab::Utils::Override
override :render?
def render?
return false if context.current_user&.enterprise_group&.disable_personal_access_tokens?
super
end
end
end
end
end
end
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Auth::AuthFinders do
RSpec.describe Gitlab::Auth::AuthFinders, feature_category: :system_access do
include described_class
include ::EE::GeoHelpers
......@@ -140,7 +140,7 @@
expect(find_user_from_access_token).to eq user
end
context 'when personal access tokens are disabled' do
context 'when personal access tokens are disabled on instance level' do
before do
stub_licensed_features(disable_personal_access_tokens: true)
stub_application_setting(disable_personal_access_tokens: true)
......@@ -150,6 +150,49 @@
expect { find_user_from_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
end
context 'when personal access tokens are disabled for the group for enterprise users' do
let(:user) { create(:enterprise_user) }
before do
user.enterprise_group.update!(disable_personal_access_tokens: true)
stub_licensed_features(disable_personal_access_tokens: true)
end
it 'raised unauthorized error' do
expect { find_user_from_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
end
context 'when personal access tokens are disabled for the group for service accounts' do
let(:user) { create(:service_account, provisioned_by_group: create(:group)) }
before do
user.provisioned_by_group.update!(disable_personal_access_tokens: true)
end
it 'returns user' do
expect(find_user_from_access_token).to eq user
end
end
context 'when the feature flag enterprise_disable_personal_access_tokens is disabled' do
before do
stub_feature_flags(enterprise_disable_personal_access_tokens: false)
end
context 'when personal access tokens are disabled for the group for enterprise users' do
let(:user) { create(:enterprise_user) }
before do
user.enterprise_group.update!(disable_personal_access_tokens: true)
end
it 'returns user' do
expect(find_user_from_access_token).to eq user
end
end
end
end
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::UserSettings::Menus::AccessTokensMenu, feature_category: :system_access do
subject(:sidebar_item) { described_class.new(context) }
let_it_be(:user) { build(:user) }
context 'when personal access tokens are disabled for enterprise users' do
let(:user) { build(:enterprise_user) }
before do
allow(user.enterprise_group).to receive(:disable_personal_access_tokens?).and_return(true)
end
context 'when user is logged in' do
let(:context) { Sidebars::Context.new(current_user: user, container: nil) }
it 'does not render' do
expect(sidebar_item.render?).to be false
end
end
context 'when user is not logged in' do
let(:context) { Sidebars::Context.new(current_user: nil, container: nil) }
subject { described_class.new(context) }
it 'does not render' do
expect(sidebar_item.render?).to be false
end
end
end
end
......@@ -673,6 +673,7 @@
context 'when the request is correct' do
before do
allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(101)
post api(url, user), params: params
end
......@@ -822,6 +823,7 @@
context 'with rate limiter', :freeze_time, :clean_gitlab_redis_rate_limiting do
before do
allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(101)
stub_application_setting(issues_create_limit: 1)
end
......@@ -873,7 +875,7 @@
it 'creates a new epic with labels param as array' do
# TODO: remove threshold after epic-work item sync
# issue: https://gitlab.com/gitlab-org/gitlab/-/issues/438295
allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(135)
allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(136)
params[:labels] = ['label1', 'label2', 'foo, bar', '&,?']
post api(url, user), params: params
......@@ -924,7 +926,7 @@
stub_licensed_features(epics: true, subepics: true)
# TODO: reduce threshold after epic-work item sync
# issue: https://gitlab.com/gitlab-org/gitlab/-/issues/438295
allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(147)
allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(148)
end
it_behaves_like 'PUT request permissions for admin mode' do
......@@ -967,7 +969,7 @@
before do
# TODO: reduce threshold after epic-work item sync
# issue: https://gitlab.com/gitlab-org/gitlab/-/issues/438295
allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(174)
allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(175)
group.add_developer(user)
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe UserSettings::PersonalAccessTokensController, type: :request, feature_category: :shared do
let(:user) { create(:enterprise_user, :with_namespace) }
before do
sign_in(user)
end
subject(:make_request) { get '/-/user_settings/personal_access_tokens' }
context "when personal access tokens are disabled for enterprise users" do
before do
allow(user.enterprise_group).to receive(:disable_personal_access_tokens?).and_return(true)
stub_licensed_features(disable_personal_access_tokens: true)
end
it 'returns not found' do
make_request
expect(response).to have_gitlab_http_status(:not_found)
end
end
context "when personal access tokens are not disabled for enterprise users" do
before do
allow(user.enterprise_group).to receive(:disable_personal_access_tokens?).and_return(false)
stub_licensed_features(disable_personal_access_tokens: true)
end
it 'render page' do
make_request
expect(response).to have_gitlab_http_status(:ok)
end
end
end
......@@ -21,7 +21,10 @@ def sprite_icon
override :render?
def render?
!!context.current_user && !Gitlab::CurrentSettings.personal_access_tokens_disabled?
return false unless context.current_user
return false if Gitlab::CurrentSettings.personal_access_tokens_disabled?
true
end
override :active_routes
......@@ -37,3 +40,5 @@ def extra_container_html_options
end
end
end
Sidebars::UserSettings::Menus::AccessTokensMenu.prepend_mod
......@@ -24809,6 +24809,9 @@ msgstr ""
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr ""
 
msgid "GroupSettings|Disable personal access tokens"
msgstr ""
msgid "GroupSettings|Duo features"
msgstr ""
 
......@@ -24857,6 +24860,9 @@ msgstr ""
msgid "GroupSettings|How do I manage group SSH certificates?"
msgstr ""
 
msgid "GroupSettings|If enabled, enterprise user accounts will not be able to use personal access tokens."
msgstr ""
msgid "GroupSettings|If enabled, individual user accounts will be able to use only issued SSH certificates for Git access. It doesn't apply to service accounts, deploy keys, and other types of internal accounts."
msgstr ""
 
......@@ -36885,6 +36891,9 @@ msgstr ""
msgid "Personal access token"
msgstr ""
 
msgid "Personal access tokens"
msgstr ""
msgid "Personal projects"
msgstr ""
 
......@@ -14,7 +14,7 @@
let_it_be(:user) { build(:user) }
context 'when personal access tokens are disabled' do
context 'when personal access tokens are disabled in the instance' do
before do
allow(::Gitlab::CurrentSettings).to receive_messages(personal_access_tokens_disabled?: true)
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment