From 274e4b93fd2bde33a055202bdf5c742f72bb7575 Mon Sep 17 00:00:00 2001 From: smriti Date: Tue, 13 Sep 2022 11:15:01 +0530 Subject: [PATCH 01/13] API implementation for fetching identities and update extern_uid This API implementation will solve the proble of group owners to update extern_uid for a user without asking the user to re-link their account Changelog: added Restructured specs to use parameterized tables Restructured specs to use parameterized tables Changes for parameterized table Doc issues resolved SAML Doc changes Changes in doc and success entity --- doc/api/saml.md | 77 +++++++++ doc/api/scim.md | 79 ++++++++- ee/lib/api/provider_identity.rb | 70 ++++++++ ee/lib/ee/api/api.rb | 1 + ee/lib/ee/api/entities/identity_detail.rb | 12 ++ .../ee/api/entities/identity_detail_spec.rb | 18 ++ .../requests/api/provider_identity_spec.rb | 154 ++++++++++++++++++ 7 files changed, 407 insertions(+), 4 deletions(-) create mode 100644 doc/api/saml.md create mode 100644 ee/lib/api/provider_identity.rb create mode 100644 ee/lib/ee/api/entities/identity_detail.rb create mode 100644 ee/spec/lib/ee/api/entities/identity_detail_spec.rb create mode 100644 ee/spec/requests/api/provider_identity_spec.rb diff --git a/doc/api/saml.md b/doc/api/saml.md new file mode 100644 index 00000000000000..8bfee4785c14c1 --- /dev/null +++ b/doc/api/saml.md @@ -0,0 +1,77 @@ +--- +type: reference, howto +stage: Manage +group: Authentication and Authorization +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# SAML API **(PREMIUM SAAS)** + +> [Introduced]() in GitLab 15.5. + +## Get SAML identities for a group + +```plaintext +GET /groups/:id/saml/identities +``` + +Fetches SAML identities for a group + +Supported attributes: + +| Attribute | Type | Required | Description | +|:------------------|:--------|:---------|:----------------------| +| `id` | integer | Yes | Return SAML identities for the given group ID. | + +If successful, returns [`200`](index.md#status-codes) and the following +response attributes: + +| Attribute | Type | Description | +| ------------ | ------ | ------------------------- | +| `extern_uid` | string | External UID for the user | +| `user_id` | string | ID for the user | + +Example request: + +```shell +curl --location --request GET "https://gdk.test:3443/api/v4/groups/33/saml/identities" \ +--header "" \ +--form "extern_uid=" \ +``` + +Example response: + +```json +[ + { + "extern_uid": "4", + "user_id": 48 + } +] +``` + +## Update extern_uid field for a SAML identity + +Fields that can be updated are: + +| SAML IdP attribute | GitLab field | +| ------------------ | ------------ | +| `id/externalId` | `extern_uid` | + +```plaintext +PATCH groups/:groups_id/saml/:uid +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ------ | -------- | ------------------------- | +| `uid` | string | yes | External UID of the user. | + +Example request: + +```shell +curl --location --request PATCH "https://gdk.test:3443/api/v4/groups/33/saml/jane_doe_current" \ +--header "" \ +--form "extern_uid=jane_doe_new" \ +``` diff --git a/doc/api/scim.md b/doc/api/scim.md index 9a745776f65290..4cf360f41e5aef 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -210,10 +210,10 @@ DELETE /api/scim/v2/groups/:group_path/Users/:id Parameters: -| Attribute | Type | Required | Description | -|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| -| `id` | string | yes | External UID of the user. | -| `group_path` | string | yes | Full path to the group. | +| Attribute | Type | Required | Description | +| ------------ | ------ | -------- | ------------------------- | +| `id` | string | yes | External UID of the user. | +| `group_path` | string | yes | Full path to the group. | Example request: @@ -252,3 +252,74 @@ Example: ```json { "op": "Add", "path": "name.formatted", "value": "New Name" } ``` + +## SCIM API **(PREMIUM SAAS)** + +### Get SCIM identities for a group + +> [Introduced]() in GitLab 15.5. + +```plaintext +GET /groups/:id/scim/identities +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +|:------------------|:--------|:---------|:----------------------| +| `id` | integer | Yes | Return SAML identities for the given group ID. | + +If successful, returns [`200`](index.md#status-codes) and the following +response attributes: + +| Attribute | Type | Description | +| ------------ | ------ | ------------------------- | +| `extern_uid` | string | External UID for the user | +| `user_id` | string | ID for the user | + +Example response: + +```json +[ + { + "extern_uid": "4", + "user_id": 48 + } +] +``` + +Example request: + +```shell +curl --location --request GET "https://gdk.test:3443/api/v4/groups/33/scim/identities" \ +--header "" \ +--form "extern_uid=" \ +``` + +### Update extern_uid field for a SCIM identity + +> [Introduced]() in GitLab 15.5. + +Fields that can be updated are: + +| SCIM/IdP field | GitLab field | +| --------------- | ------------ | +| `id/externalId` | `extern_uid` | + +```plaintext +PATCH groups/:groups_id/scim/:uid +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | ------ | -------- | ------------------------- | +| `uid` | string | yes | External UID of the user. | + +Example request: + +```shell +curl --location --request PATCH "https://gdk.test:3443/api/v4/groups/33/scim/jane_doe_current" \ +--header "" \ +--form "extern_uid=jane_doe_new" \ +``` diff --git a/ee/lib/api/provider_identity.rb b/ee/lib/api/provider_identity.rb new file mode 100644 index 00000000000000..914fe073188fcf --- /dev/null +++ b/ee/lib/api/provider_identity.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +module API + class ProviderIdentity < ::API::Base + include ::Gitlab::Utils::StrongMemoize + + before { authenticate! } + before { authorize_admin_group } + + feature_category :authentication_and_authorization + + params do + requires :id, type: String, desc: 'The ID of a group' + end + resource :groups do + %w[saml scim].each do |provider_type| + resource ":id/#{provider_type}", requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do + desc 'Get user identities for the provider' do + success EE::API::Entities::IdentityDetail + end + + get "/identities" do + group = find_group(params[:id]) + + case provider_type + when 'saml' + bad_request! unless group.saml_provider + present group.saml_provider.identities, with: EE::API::Entities::IdentityDetail + when 'scim' + present group.scim_identities, with: EE::API::Entities::IdentityDetail + end + end + + desc 'Update extern_uid for the user' do + success EE::API::Entities::IdentityDetail + end + + params do + requires :uid, type: String, desc: "Current external UID of the user" + requires :extern_uid, type: String, desc: "Desired/new external UID of the user" + end + + patch ':uid' do + group = find_group(params[:id]) + identity = find_provider_identity(provider_type, params[:uid], group) + + not_found!('Identity') unless identity + + if identity.update(extern_uid: params[:extern_uid]) + present identity, with: EE::API::Entities::IdentityDetail + else + render_api_error!(identity.errors.full_messages.join(",").to_s, 400) + end + end + end + end + end + + helpers do + def find_provider_identity(provider_type, extern_uid, group) + case provider_type + when 'scim' + group.scim_identities.with_extern_uid(extern_uid).first + when 'saml' + GroupSamlIdentityFinder.find_by_group_and_uid(group: group, uid: extern_uid) + end + end + end + end +end diff --git a/ee/lib/ee/api/api.rb b/ee/lib/ee/api/api.rb index 017d9548a06849..4a3267f8b2ce03 100644 --- a/ee/lib/ee/api/api.rb +++ b/ee/lib/ee/api/api.rb @@ -31,6 +31,7 @@ module API mount ::API::GroupPushRule mount ::API::MergeTrains mount ::API::MemberRoles + mount ::API::ProviderIdentity mount ::API::GroupHooks mount ::API::MergeRequestApprovalSettings mount ::API::Scim diff --git a/ee/lib/ee/api/entities/identity_detail.rb b/ee/lib/ee/api/entities/identity_detail.rb new file mode 100644 index 00000000000000..0b7263c36c8e3d --- /dev/null +++ b/ee/lib/ee/api/entities/identity_detail.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module EE + module API + module Entities + class IdentityDetail < Grape::Entity + expose :extern_uid + expose :user_id + end + end + end +end diff --git a/ee/spec/lib/ee/api/entities/identity_detail_spec.rb b/ee/spec/lib/ee/api/entities/identity_detail_spec.rb new file mode 100644 index 00000000000000..162c20b6f4ebae --- /dev/null +++ b/ee/spec/lib/ee/api/entities/identity_detail_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe EE::API::Entities::IdentityDetail do + describe 'exposes extern_uid and user_id fields' do + let(:user) { create(:user) } + let!(:identity) { create(:group_saml_identity, user: user) } + let(:identity_detail_entity) { described_class.new(identity) } + + subject(:entity) { identity_detail_entity.as_json } + + it 'exposes the attributes' do + expect(entity[:extern_uid]).to eq identity.extern_uid + expect(entity[:user_id]).to eq identity.user_id + end + end +end diff --git a/ee/spec/requests/api/provider_identity_spec.rb b/ee/spec/requests/api/provider_identity_spec.rb new file mode 100644 index 00000000000000..7912457c177dea --- /dev/null +++ b/ee/spec/requests/api/provider_identity_spec.rb @@ -0,0 +1,154 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe API::ProviderIdentity, api: true do + include ApiHelpers + + let_it_be(:owner) { create(:user) } + let_it_be(:user) { create(:user) } + let(:current_user) { nil } + + let_it_be(:group) do + group = create(:group) + group.add_guest(user) + group.add_owner(owner) + group + end + + let_it_be(:saml_provider) { create(:saml_provider, group: group) } + + let_it_be(:saml_identity_one) do + create(:identity, user_id: user.id, provider: 'group_saml', + saml_provider_id: saml_provider.id, extern_uid: 'saml-uid-1') + end + + let_it_be(:saml_identity_two) do + create(:identity, user_id: owner.id, provider: 'group_saml', + saml_provider_id: saml_provider.id, extern_uid: 'saml-uid-2') + end + + let_it_be(:scim_identity_one) do + create(:scim_identity, user: user, group: group, extern_uid: 'scim-uid-1') + end + + let_it_be(:scim_identity_two) do + create(:scim_identity, user: owner, group: group, extern_uid: 'scim-uid-2') + end + + describe "Provider Identity API" do + using RSpec::Parameterized::TableSyntax + + where(:provider_type, :provider_extern_uid_1, :provider_extern_uid_2, :identity_type, :validation_error) do + "saml" | "saml-uid-1" | "saml-uid-2" | Identity | "SAML NameID can't be blank" + "scim" | "scim-uid-1" | "scim-uid-2" | ScimIdentity | "Extern uid can't be blank" + end + + with_them do + context "when GET identities" do + subject(:get_identities) { get api("/groups/#{group.id}/#{provider_type}/identities", current_user) } + + context "when user is not a group owner" do + let(:current_user) { user } + + it "throws unauthorized error" do + get_identities + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context "when user is group owner" do + let(:current_user) { owner } + + it "returns the list of identities" do + get_identities + + expect(json_response).to( + match([ + { "extern_uid" => provider_extern_uid_1, "user_id" => user.id }, + { "extern_uid" => provider_extern_uid_2, "user_id" => owner.id } + ]) + ) + end + end + end + + context "when PATCH uid" do + subject(:patch_identities) do + patch api("/groups/#{group.id}/#{provider_type}/#{uid}", current_user), + params: { extern_uid: extern_uid } + end + + context "when user is not a group owner" do + let(:uid) { provider_extern_uid_1 } + let(:current_user) { user } + let(:extern_uid) { 'updated_uid' } + + it "throws forbidden error" do + patch_identities + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context "when user is a group owner" do + let(:current_user) { owner } + let(:extern_uid) { "updated_uid" } + + context "when invalid uid is passed" do + let(:uid) { "test_uid" } + + it "returns not found error" do + patch_identities + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context "when valid uid is passed" do + let(:uid) { provider_extern_uid_1 } + + it "updates the identity record with extern_uid passed" do + patch_identities + + expect(response).to have_gitlab_http_status(:ok) + + # Check that response is equal to the updated object + expect(json_response['extern_uid']).to eq('updated_uid') + end + + context "when invalid extern_uid to update is passed" do + let(:uid) { provider_extern_uid_1 } + let(:extern_uid) { "" } + + it "throws bad request error" do + patch_identities + + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response['message']).to eq(validation_error) + end + end + end + + context "when params contain attribute other than extern_uid" do + it "does not update any other param" do + expect do + patch api("/groups/#{group.id}/#{provider_type}/#{scim_identity_one.extern_uid}", current_user), + params: { active: false } + + expect(json_response['error']).to eq("extern_uid is missing") + end.not_to change(scim_identity_one, :active) + end + + it "throws error when param is missing" do + patch api("/groups/#{group.id}/#{provider_type}/#{provider_extern_uid_1}", current_user) + + expect(response).to have_gitlab_http_status(:bad_request) + end + end + end + end + end + end +end -- GitLab From 391c5573fc3fe77c176d334ea89510cb8efcb89c Mon Sep 17 00:00:00 2001 From: Marcin Sedlak-Jakubowski Date: Fri, 7 Oct 2022 06:16:56 +0000 Subject: [PATCH 02/13] Documentation suggestion for broken link applied --- doc/api/scim.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/scim.md b/doc/api/scim.md index 4cf360f41e5aef..febe3272190394 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -257,7 +257,7 @@ Example: ### Get SCIM identities for a group -> [Introduced]() in GitLab 15.5. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5. ```plaintext GET /groups/:id/scim/identities @@ -298,7 +298,7 @@ curl --location --request GET "https://gdk.test:3443/api/v4/groups/33/scim/ident ### Update extern_uid field for a SCIM identity -> [Introduced]() in GitLab 15.5. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5. Fields that can be updated are: -- GitLab From ae1a3260d24b53e18abfc938a9ca2453f6e85fee Mon Sep 17 00:00:00 2001 From: smriti Date: Fri, 7 Oct 2022 11:57:15 +0530 Subject: [PATCH 03/13] Changes in description for scim api --- doc/api/scim.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/api/scim.md b/doc/api/scim.md index febe3272190394..2e5018ee50acba 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -255,6 +255,11 @@ Example: ## SCIM API **(PREMIUM SAAS)** +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98354) in GitLab 15.5. + +To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. +This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. + ### Get SCIM identities for a group > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5. -- GitLab From b9a677929e5275aa15786bc3418c2d88d8269184 Mon Sep 17 00:00:00 2001 From: Evan Read Date: Mon, 10 Oct 2022 06:25:34 +0000 Subject: [PATCH 04/13] Documentation updates --- doc/api/saml.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/api/saml.md b/doc/api/saml.md index 8bfee4785c14c1..86a3ec3f7a35d1 100644 --- a/doc/api/saml.md +++ b/doc/api/saml.md @@ -15,13 +15,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w GET /groups/:id/saml/identities ``` -Fetches SAML identities for a group +Fetch SAML identities for a group. Supported attributes: | Attribute | Type | Required | Description | |:------------------|:--------|:---------|:----------------------| -| `id` | integer | Yes | Return SAML identities for the given group ID. | +| `id` | integer | Yes | Group ID for the group to return SAML identities. | If successful, returns [`200`](index.md#status-codes) and the following response attributes: @@ -50,9 +50,9 @@ Example response: ] ``` -## Update extern_uid field for a SAML identity +## Update `extern_uid` field for a SAML identity -Fields that can be updated are: +Update `extern_uid` field for a SAML identity. Field that can be updated are: | SAML IdP attribute | GitLab field | | ------------------ | ------------ | -- GitLab From a0217b4f6cef2308197a7b196608ad821021c5b6 Mon Sep 17 00:00:00 2001 From: smriti Date: Mon, 10 Oct 2022 14:29:39 +0530 Subject: [PATCH 05/13] Moved SCIM Internal only API --- doc/api/scim.md | 255 +------------------------- doc/development/internal_api/index.md | 248 +++++++++++++++++++++++++ 2 files changed, 251 insertions(+), 252 deletions(-) diff --git a/doc/api/scim.md b/doc/api/scim.md index 2e5018ee50acba..8475e37b71cac1 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -4,263 +4,14 @@ stage: Manage group: Authentication and Authorization info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments --- - -# SCIM API (SYSTEM ONLY) **(PREMIUM SAAS)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab 11.10. - -The SCIM API implements the [RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). As this API is for -**system** use for SCIM provider integration, it is subject to change without notice. - -To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. -This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. - -## Get a list of SCIM provisioned users - -This endpoint is used as part of the SCIM syncing mechanism. It only returns -a single user based on a unique ID which should match the `extern_uid` of the user. - -```plaintext -GET /api/scim/v2/groups/:group_path/Users -``` - -Parameters: - -| Attribute | Type | Required | Description | -|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| -| `filter` | string | no | A [filter](#available-filters) expression. | -| `group_path` | string | yes | Full path to the group. | -| `startIndex` | integer | no | The 1-based index indicating where to start returning results from. A value of less than one will be interpreted as 1. | -| `count` | integer | no | Desired maximum number of query results. | - -NOTE: -Pagination follows the [SCIM spec](https://www.rfc-editor.org/rfc/rfc7644#section-3.4.2.4) rather than GitLab pagination as used elsewhere. If records change between requests it is possible for a page to either be missing records that have moved to a different page or repeat records from a previous request. - -Example request: - -```shell -curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20%220b1d561c-21ff-4092-beab-8154b17f82f2%22" \ - --header "Authorization: Bearer " \ - --header "Content-Type: application/scim+json" -``` - -Example response: - -```json -{ - "schemas": [ - "urn:ietf:params:scim:api:messages:2.0:ListResponse" - ], - "totalResults": 1, - "itemsPerPage": 20, - "startIndex": 1, - "Resources": [ - { - "schemas": [ - "urn:ietf:params:scim:schemas:core:2.0:User" - ], - "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", - "active": true, - "name.formatted": "Test User", - "userName": "username", - "meta": { "resourceType":"User" }, - "emails": [ - { - "type": "work", - "value": "name@example.com", - "primary": true - } - ] - } - ] -} -``` - -## Get a single SCIM provisioned user - -```plaintext -GET /api/scim/v2/groups/:group_path/Users/:id -``` - -Parameters: - -| Attribute | Type | Required | Description | -|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| -| `id` | string | yes | External UID of the user. | -| `group_path` | string | yes | Full path to the group. | - -Example request: - -```shell -curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \ - --header "Authorization: Bearer " --header "Content-Type: application/scim+json" -``` - -Example response: - -```json -{ - "schemas": [ - "urn:ietf:params:scim:schemas:core:2.0:User" - ], - "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", - "active": true, - "name.formatted": "Test User", - "userName": "username", - "meta": { "resourceType":"User" }, - "emails": [ - { - "type": "work", - "value": "name@example.com", - "primary": true - } - ] -} -``` - -## Create a SCIM provisioned user - -```plaintext -POST /api/scim/v2/groups/:group_path/Users/ -``` - -Parameters: - -| Attribute | Type | Required | Description | -|:---------------|:----------|:----|:--------------------------| -| `externalId` | string | yes | External UID of the user. | -| `userName` | string | yes | Username of the user. | -| `emails` | JSON string | yes | Work email. | -| `name` | JSON string | yes | Name of the user. | -| `meta` | string | no | Resource type (`User`). | - -Example request: - -```shell -curl --verbose --request POST "https://gitlab.example.com/api/scim/v2/groups/test_group/Users" \ - --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' \ - --header "Authorization: Bearer " --header "Content-Type: application/scim+json" -``` - -Example response: - -```json -{ - "schemas": [ - "urn:ietf:params:scim:schemas:core:2.0:User" - ], - "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", - "active": true, - "name.formatted": "Test User", - "userName": "username", - "meta": { "resourceType":"User" }, - "emails": [ - { - "type": "work", - "value": "name@example.com", - "primary": true - } - ] -} -``` - -Returns a `201` status code if successful. - -## Update a single SCIM provisioned user - -Fields that can be updated are: - -| SCIM/IdP field | GitLab field | -|:---------------------------------|:-----------------------------------------------------------------------------| -| `id/externalId` | `extern_uid` | -| `name.formatted` | `name` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) | -| `emails\[type eq "work"\].value` | `email` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) | -| `active` | Identity removal if `active` = `false` | -| `userName` | `username` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) | - -```plaintext -PATCH /api/scim/v2/groups/:group_path/Users/:id -``` - -Parameters: - -| Attribute | Type | Required | Description | -|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| -| `id` | string | yes | External UID of the user. | -| `group_path` | string | yes | Full path to the group. | -| `Operations` | JSON string | yes | An [operations](#available-operations) expression. | - -Example request: - -```shell -curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \ - --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' \ - --header "Authorization: Bearer " --header "Content-Type: application/scim+json" -``` - -Returns an empty response with a `204` status code if successful. - -## Remove a single SCIM provisioned user - -Removes the user's SSO identity and group membership. - -```plaintext -DELETE /api/scim/v2/groups/:group_path/Users/:id -``` - -Parameters: - -| Attribute | Type | Required | Description | -| ------------ | ------ | -------- | ------------------------- | -| `id` | string | yes | External UID of the user. | -| `group_path` | string | yes | Full path to the group. | - -Example request: - -```shell -curl --verbose --request DELETE "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \ - --header "Authorization: Bearer " --header "Content-Type: application/scim+json" -``` - -Returns an empty response with a `204` status code if successful. - -## Available filters - -They match an expression as specified in [the RFC7644 filtering section](https://www.rfc-editor.org/rfc/rfc7644#section-3.4.2.2). - -| Filter | Description | -| ----- | ----------- | -| `eq` | The attribute matches exactly the specified value. | - -Example: - -```plaintext -id eq a-b-c-d -``` - -## Available operations - -They perform an operation as specified in [the RFC7644 update section](https://www.rfc-editor.org/rfc/rfc7644#section-3.5.2). - -| Operator | Description | -| ----- | ----------- | -| `Replace` | The attribute's value is updated. | -| `Add` | The attribute has a new value. | - -Example: - -```json -{ "op": "Add", "path": "name.formatted", "value": "New Name" } -``` - -## SCIM API **(PREMIUM SAAS)** +# SCIM API **(PREMIUM SAAS)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98354) in GitLab 15.5. To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. -### Get SCIM identities for a group +## Get SCIM identities for a group > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5. @@ -301,7 +52,7 @@ curl --location --request GET "https://gdk.test:3443/api/v4/groups/33/scim/ident --form "extern_uid=" \ ``` -### Update extern_uid field for a SCIM identity +## Update extern_uid field for a SCIM identity > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5. diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md index e7dfcd58af601c..faeac8a9909d1e 100644 --- a/doc/development/internal_api/index.md +++ b/doc/development/internal_api/index.md @@ -965,3 +965,251 @@ Example response: ### Known consumers - CustomersDot + +## SCIM API (SYSTEM ONLY) **(PREMIUM SAAS)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab 11.10. + +The SCIM API implements the [RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). As this API is for +**system** use for SCIM provider integration, it is subject to change without notice. + +To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. +This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. + +## Get a list of SCIM provisioned users + +This endpoint is used as part of the SCIM syncing mechanism. It only returns +a single user based on a unique ID which should match the `extern_uid` of the user. + +```plaintext +GET /api/scim/v2/groups/:group_path/Users +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| +| `filter` | string | no | A [filter](#available-filters) expression. | +| `group_path` | string | yes | Full path to the group. | +| `startIndex` | integer | no | The 1-based index indicating where to start returning results from. A value of less than one will be interpreted as 1. | +| `count` | integer | no | Desired maximum number of query results. | + +NOTE: +Pagination follows the [SCIM spec](https://www.rfc-editor.org/rfc/rfc7644#section-3.4.2.4) rather than GitLab pagination as used elsewhere. If records change between requests it is possible for a page to either be missing records that have moved to a different page or repeat records from a previous request. + +Example request: + +```shell +curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users?filter=id%20eq%20%220b1d561c-21ff-4092-beab-8154b17f82f2%22" \ + --header "Authorization: Bearer " \ + --header "Content-Type: application/scim+json" +``` + +Example response: + +```json +{ + "schemas": [ + "urn:ietf:params:scim:api:messages:2.0:ListResponse" + ], + "totalResults": 1, + "itemsPerPage": 20, + "startIndex": 1, + "Resources": [ + { + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:User" + ], + "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", + "active": true, + "name.formatted": "Test User", + "userName": "username", + "meta": { "resourceType":"User" }, + "emails": [ + { + "type": "work", + "value": "name@example.com", + "primary": true + } + ] + } + ] +} +``` + +## Get a single SCIM provisioned user + +```plaintext +GET /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| +| `id` | string | yes | External UID of the user. | +| `group_path` | string | yes | Full path to the group. | + +Example request: + +```shell +curl "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \ + --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +Example response: + +```json +{ + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:User" + ], + "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", + "active": true, + "name.formatted": "Test User", + "userName": "username", + "meta": { "resourceType":"User" }, + "emails": [ + { + "type": "work", + "value": "name@example.com", + "primary": true + } + ] +} +``` + +## Create a SCIM provisioned user + +```plaintext +POST /api/scim/v2/groups/:group_path/Users/ +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:---------------|:----------|:----|:--------------------------| +| `externalId` | string | yes | External UID of the user. | +| `userName` | string | yes | Username of the user. | +| `emails` | JSON string | yes | Work email. | +| `name` | JSON string | yes | Name of the user. | +| `meta` | string | no | Resource type (`User`). | + +Example request: + +```shell +curl --verbose --request POST "https://gitlab.example.com/api/scim/v2/groups/test_group/Users" \ + --data '{"externalId":"test_uid","active":null,"userName":"username","emails":[{"primary":true,"type":"work","value":"name@example.com"}],"name":{"formatted":"Test User","familyName":"User","givenName":"Test"},"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"meta":{"resourceType":"User"}}' \ + --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +Example response: + +```json +{ + "schemas": [ + "urn:ietf:params:scim:schemas:core:2.0:User" + ], + "id": "0b1d561c-21ff-4092-beab-8154b17f82f2", + "active": true, + "name.formatted": "Test User", + "userName": "username", + "meta": { "resourceType":"User" }, + "emails": [ + { + "type": "work", + "value": "name@example.com", + "primary": true + } + ] +} +``` + +Returns a `201` status code if successful. + +## Update a single SCIM provisioned user + +Fields that can be updated are: + +| SCIM/IdP field | GitLab field | +|:---------------------------------|:-----------------------------------------------------------------------------| +| `id/externalId` | `extern_uid` | +| `name.formatted` | `name` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) | +| `emails\[type eq "work"\].value` | `email` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) | +| `active` | Identity removal if `active` = `false` | +| `userName` | `username` ([Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/363058)) | + +```plaintext +PATCH /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| +| `id` | string | yes | External UID of the user. | +| `group_path` | string | yes | Full path to the group. | +| `Operations` | JSON string | yes | An [operations](#available-operations) expression. | + +Example request: + +```shell +curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \ + --data '{ "Operations": [{"op":"Add","path":"name.formatted","value":"New Name"}] }' \ + --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +Returns an empty response with a `204` status code if successful. + +## Remove a single SCIM provisioned user + +Removes the user's SSO identity and group membership. + +```plaintext +DELETE /api/scim/v2/groups/:group_path/Users/:id +``` + +Parameters: + +| Attribute | Type | Required | Description | +| ------------ | ------ | -------- | ------------------------- | +| `id` | string | yes | External UID of the user. | +| `group_path` | string | yes | Full path to the group. | + +Example request: + +```shell +curl --verbose --request DELETE "https://gitlab.example.com/api/scim/v2/groups/test_group/Users/f0b1d561c-21ff-4092-beab-8154b17f82f2" \ + --header "Authorization: Bearer " --header "Content-Type: application/scim+json" +``` + +Returns an empty response with a `204` status code if successful. + +## Available filters + +They match an expression as specified in [the RFC7644 filtering section](https://www.rfc-editor.org/rfc/rfc7644#section-3.4.2.2). + +| Filter | Description | +| ----- | ----------- | +| `eq` | The attribute matches exactly the specified value. | + +Example: + +```plaintext +id eq a-b-c-d +``` + +## Available operations + +They perform an operation as specified in [the RFC7644 update section](https://www.rfc-editor.org/rfc/rfc7644#section-3.5.2). + +| Operator | Description | +| ----- | ----------- | +| `Replace` | The attribute's value is updated. | +| `Add` | The attribute has a new value. | + +Example: + +```json +{ "op": "Add", "path": "name.formatted", "value": "New Name" } +``` \ No newline at end of file -- GitLab From 2b6808a3939fbbb5e9e813509ab6919430f348b8 Mon Sep 17 00:00:00 2001 From: smriti Date: Mon, 10 Oct 2022 14:33:19 +0530 Subject: [PATCH 06/13] Index file trailing character --- doc/development/internal_api/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md index faeac8a9909d1e..788dea6d3d25bd 100644 --- a/doc/development/internal_api/index.md +++ b/doc/development/internal_api/index.md @@ -1212,4 +1212,4 @@ Example: ```json { "op": "Add", "path": "name.formatted", "value": "New Name" } -``` \ No newline at end of file +``` -- GitLab From bc94ef4dd7b52e99e2159ecf1e180c08ab546e94 Mon Sep 17 00:00:00 2001 From: smriti Date: Mon, 10 Oct 2022 16:45:17 +0530 Subject: [PATCH 07/13] Fixed broken links --- doc/development/internal_api/index.md | 4 ++-- doc/user/group/saml_sso/troubleshooting_scim.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md index 788dea6d3d25bd..cc7aeebd1b804f 100644 --- a/doc/development/internal_api/index.md +++ b/doc/development/internal_api/index.md @@ -973,8 +973,8 @@ Example response: The SCIM API implements the [RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). As this API is for **system** use for SCIM provider integration, it is subject to change without notice. -To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. -This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. +To use this API, [Group SSO](../../user/group/saml_sso/index.md) must be enabled for the group. +This API is only in use where [SCIM for Group SSO](../../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. ## Get a list of SCIM provisioned users diff --git a/doc/user/group/saml_sso/troubleshooting_scim.md b/doc/user/group/saml_sso/troubleshooting_scim.md index f98b6c61e11c36..479e18bbf7de86 100644 --- a/doc/user/group/saml_sso/troubleshooting_scim.md +++ b/doc/user/group/saml_sso/troubleshooting_scim.md @@ -34,7 +34,7 @@ Administrators can use the Admin Area to [list SCIM identities for a user](../.. Group owners can see the list of users and the `externalId` stored for each user in the group SAML SSO Settings page. -A possible alternative is to use the [SCIM API](../../../api/scim.md#get-a-list-of-scim-provisioned-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`. +A possible alternative is to use the [SCIM API](../../../development/internal_api/index.md#get-a-list-of-scim-provisioned-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`. To see how the `external_uid` compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](troubleshooting.md#saml-debugging-tools). @@ -53,7 +53,7 @@ you can address the problem in the following ways: - You can have users unlink and relink themselves, based on the ["SAML authentication failed: User has already been taken"](troubleshooting.md#message-saml-authentication-failed-user-has-already-been-taken) section. - You can unlink all users simultaneously, by removing all users from the SAML app while provisioning is turned on. -- It may be possible to use the [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) to manually correct the `externalId` stored for users to match the SAML `NameId`. +- It may be possible to use the [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) to manually correct the `externalId` stored for users to match the SAML `NameId`. To look up a user, you need to know the desired value that matches the `NameId` as well as the current `externalId`. It is important not to update these to incorrect values, since this causes users to be unable to sign in. It is also important not to assign a value to the wrong user, as this causes users to get signed into the wrong account. -- GitLab From c8a4bbe30b0268dad550302bebc24d6464f52ef8 Mon Sep 17 00:00:00 2001 From: smriti Date: Mon, 10 Oct 2022 18:42:24 +0530 Subject: [PATCH 08/13] Updated scim api references --- doc/user/group/saml_sso/scim_setup.md | 4 ++-- doc/user/group/saml_sso/troubleshooting_scim.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md index 6b64288f5af7a9..b2f0bcc64ecbc1 100644 --- a/doc/user/group/saml_sso/scim_setup.md +++ b/doc/user/group/saml_sso/scim_setup.md @@ -15,7 +15,7 @@ GitLab SAML SSO SCIM doesn't support updating users. When SCIM is enabled for a GitLab group, membership of that group is synchronized between GitLab and an identity provider. -The GitLab [SCIM API](../../../api/scim.md) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). +The GitLab [SCIM API](../../../development/internal_api/index.md#scim-api) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). ## Configure GitLab @@ -121,7 +121,7 @@ attributes and modify them accordingly. In particular, the `objectId` source att target attribute. If a mapping is not listed in the table, use the Azure Active Directory defaults. For a list of required attributes, -refer to the [SCIM API documentation](../../../api/scim.md). +refer to the [SCIM API documentation](../../../development/internal_api/index.md#scim-api). ### Configure Okta diff --git a/doc/user/group/saml_sso/troubleshooting_scim.md b/doc/user/group/saml_sso/troubleshooting_scim.md index 479e18bbf7de86..cbc33d85c666c0 100644 --- a/doc/user/group/saml_sso/troubleshooting_scim.md +++ b/doc/user/group/saml_sso/troubleshooting_scim.md @@ -71,11 +71,11 @@ Changing the SAML or SCIM configuration or provider can cause the following prob | Problem | Solution | | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | SAML and SCIM identity mismatch. | First [verify that the user's SAML NameId matches the SCIM externalId](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid) and then [update or fix the mismatched SCIM externalId and SAML NameId](#update-or-fix-mismatched-scim-externalid-and-saml-nameid). | -| SCIM identity mismatch between GitLab and the identity provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) to update the SCIM `id` for the user on GitLab.com. | +| SCIM identity mismatch between GitLab and the identity provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) to update the SCIM `id` for the user on GitLab.com. | ## Search Rails logs for SCIM requests -GitLab.com administrators can search for SCIM requests in the `api_json.log` using the `pubsub-rails-inf-gprd-*` index in [Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html#using-kibana). Use the following filters based on the [SCIM API](../../../api/scim.md): +GitLab.com administrators can search for SCIM requests in the `api_json.log` using the `pubsub-rails-inf-gprd-*` index in [Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html#using-kibana). Use the following filters based on the [SCIM API](../../../development/internal_api/index.md#scim-api): - `json.path`: `/scim/v2/groups/` - `json.params.value`: `` -- GitLab From 514e29b013381657120216be13d4b47a257a0345 Mon Sep 17 00:00:00 2001 From: smriti Date: Mon, 10 Oct 2022 21:06:20 +0530 Subject: [PATCH 09/13] Fixed broken link and other doc updates --- doc/api/saml.md | 6 +++--- doc/api/scim.md | 4 ++-- doc/user/group/saml_sso/scim_setup.md | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/api/saml.md b/doc/api/saml.md index 86a3ec3f7a35d1..7aa4e2ba604a1a 100644 --- a/doc/api/saml.md +++ b/doc/api/saml.md @@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # SAML API **(PREMIUM SAAS)** -> [Introduced]() in GitLab 15.5. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5. ## Get SAML identities for a group @@ -71,7 +71,7 @@ Parameters: Example request: ```shell -curl --location --request PATCH "https://gdk.test:3443/api/v4/groups/33/saml/jane_doe_current" \ +curl --location --request PATCH "https://gdk.test:3443/api/v4/groups/33/saml/sydney_jones" \ --header "" \ ---form "extern_uid=jane_doe_new" \ +--form "extern_uid=sydney_jones_new" \ ``` diff --git a/doc/api/scim.md b/doc/api/scim.md index 8475e37b71cac1..53b1bd081da700 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -75,7 +75,7 @@ Parameters: Example request: ```shell -curl --location --request PATCH "https://gdk.test:3443/api/v4/groups/33/scim/jane_doe_current" \ +curl --location --request PATCH "https://gdk.test:3443/api/v4/groups/33/scim/sydney_jones" \ --header "" \ ---form "extern_uid=jane_doe_new" \ +--form "extern_uid=sydney_jones_new" \ ``` diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md index b2f0bcc64ecbc1..0dbff1cc9985b2 100644 --- a/doc/user/group/saml_sso/scim_setup.md +++ b/doc/user/group/saml_sso/scim_setup.md @@ -15,7 +15,7 @@ GitLab SAML SSO SCIM doesn't support updating users. When SCIM is enabled for a GitLab group, membership of that group is synchronized between GitLab and an identity provider. -The GitLab [SCIM API](../../../development/internal_api/index.md#scim-api) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). +The GitLab [SCIM API](../../../development/internal_api/index.md#scim-api-system-only) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). ## Configure GitLab @@ -121,7 +121,7 @@ attributes and modify them accordingly. In particular, the `objectId` source att target attribute. If a mapping is not listed in the table, use the Azure Active Directory defaults. For a list of required attributes, -refer to the [SCIM API documentation](../../../development/internal_api/index.md#scim-api). +refer to the [SCIM API documentation](../../../development/internal_api/index.md#scim-api-system-only). ### Configure Okta -- GitLab From f9854e266ee54463bbdfee14f3b817b6c72c648f Mon Sep 17 00:00:00 2001 From: Evan Read Date: Tue, 11 Oct 2022 05:05:57 +0000 Subject: [PATCH 10/13] Documentation suggestions for scim api refactor --- doc/api/saml.md | 3 ++- doc/api/scim.md | 2 ++ doc/development/internal_api/index.md | 16 +++++++++------- doc/user/group/saml_sso/scim_setup.md | 4 ++-- doc/user/group/saml_sso/troubleshooting_scim.md | 10 ++++++---- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/doc/api/saml.md b/doc/api/saml.md index 7aa4e2ba604a1a..810ed382d4937e 100644 --- a/doc/api/saml.md +++ b/doc/api/saml.md @@ -1,5 +1,4 @@ --- -type: reference, howto stage: Manage group: Authentication and Authorization info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments @@ -9,6 +8,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5. +API for accessing SAML features. + ## Get SAML identities for a group ```plaintext diff --git a/doc/api/scim.md b/doc/api/scim.md index 53b1bd081da700..88ca43b651293e 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -11,6 +11,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. +Not to be confused with the [internal SCIM API](../doc/development/internal_api/index.md#scim-api). + ## Get SCIM identities for a group > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227841) in GitLab 15.5. diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md index cc7aeebd1b804f..515684e1683d60 100644 --- a/doc/development/internal_api/index.md +++ b/doc/development/internal_api/index.md @@ -966,7 +966,7 @@ Example response: - CustomersDot -## SCIM API (SYSTEM ONLY) **(PREMIUM SAAS)** +## SCIM API **(PREMIUM SAAS)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab 11.10. @@ -976,7 +976,9 @@ The SCIM API implements the [RFC7644 protocol](https://www.rfc-editor.org/rfc/rf To use this API, [Group SSO](../../user/group/saml_sso/index.md) must be enabled for the group. This API is only in use where [SCIM for Group SSO](../../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. -## Get a list of SCIM provisioned users +Not to be confused with the [main SCIM API](../../api/scim.md). + +### Get a list of SCIM provisioned users This endpoint is used as part of the SCIM syncing mechanism. It only returns a single user based on a unique ID which should match the `extern_uid` of the user. @@ -1037,7 +1039,7 @@ Example response: } ``` -## Get a single SCIM provisioned user +### Get a single SCIM provisioned user ```plaintext GET /api/scim/v2/groups/:group_path/Users/:id @@ -1127,7 +1129,7 @@ Example response: Returns a `201` status code if successful. -## Update a single SCIM provisioned user +### Update a single SCIM provisioned user Fields that can be updated are: @@ -1161,7 +1163,7 @@ curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/te Returns an empty response with a `204` status code if successful. -## Remove a single SCIM provisioned user +### Remove a single SCIM provisioned user Removes the user's SSO identity and group membership. @@ -1185,7 +1187,7 @@ curl --verbose --request DELETE "https://gitlab.example.com/api/scim/v2/groups/t Returns an empty response with a `204` status code if successful. -## Available filters +### Available filters They match an expression as specified in [the RFC7644 filtering section](https://www.rfc-editor.org/rfc/rfc7644#section-3.4.2.2). @@ -1199,7 +1201,7 @@ Example: id eq a-b-c-d ``` -## Available operations +### Available operations They perform an operation as specified in [the RFC7644 update section](https://www.rfc-editor.org/rfc/rfc7644#section-3.5.2). diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md index 0dbff1cc9985b2..71e612712720cc 100644 --- a/doc/user/group/saml_sso/scim_setup.md +++ b/doc/user/group/saml_sso/scim_setup.md @@ -15,7 +15,7 @@ GitLab SAML SSO SCIM doesn't support updating users. When SCIM is enabled for a GitLab group, membership of that group is synchronized between GitLab and an identity provider. -The GitLab [SCIM API](../../../development/internal_api/index.md#scim-api-system-only) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). +The internal GitLab [SCIM API](../../../development/internal_api/index.md#scim-api) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). ## Configure GitLab @@ -121,7 +121,7 @@ attributes and modify them accordingly. In particular, the `objectId` source att target attribute. If a mapping is not listed in the table, use the Azure Active Directory defaults. For a list of required attributes, -refer to the [SCIM API documentation](../../../development/internal_api/index.md#scim-api-system-only). +refer to the [internal SCIM API](../../../development/internal_api/index.md#scim-api) documentation. ### Configure Okta diff --git a/doc/user/group/saml_sso/troubleshooting_scim.md b/doc/user/group/saml_sso/troubleshooting_scim.md index cbc33d85c666c0..de336e5aa1f39c 100644 --- a/doc/user/group/saml_sso/troubleshooting_scim.md +++ b/doc/user/group/saml_sso/troubleshooting_scim.md @@ -34,7 +34,7 @@ Administrators can use the Admin Area to [list SCIM identities for a user](../.. Group owners can see the list of users and the `externalId` stored for each user in the group SAML SSO Settings page. -A possible alternative is to use the [SCIM API](../../../development/internal_api/index.md#get-a-list-of-scim-provisioned-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`. +A possible alternative is to use the internal [SCIM API](../../../development/internal_api/index.md#get-a-list-of-scim-provisioned-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`. To see how the `external_uid` compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](troubleshooting.md#saml-debugging-tools). @@ -53,7 +53,7 @@ you can address the problem in the following ways: - You can have users unlink and relink themselves, based on the ["SAML authentication failed: User has already been taken"](troubleshooting.md#message-saml-authentication-failed-user-has-already-been-taken) section. - You can unlink all users simultaneously, by removing all users from the SAML app while provisioning is turned on. -- It may be possible to use the [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) to manually correct the `externalId` stored for users to match the SAML `NameId`. +- It may be possible to use the internal [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) to manually correct the `externalId` stored for users to match the SAML `NameId`. To look up a user, you need to know the desired value that matches the `NameId` as well as the current `externalId`. It is important not to update these to incorrect values, since this causes users to be unable to sign in. It is also important not to assign a value to the wrong user, as this causes users to get signed into the wrong account. @@ -71,11 +71,13 @@ Changing the SAML or SCIM configuration or provider can cause the following prob | Problem | Solution | | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | SAML and SCIM identity mismatch. | First [verify that the user's SAML NameId matches the SCIM externalId](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid) and then [update or fix the mismatched SCIM externalId and SAML NameId](#update-or-fix-mismatched-scim-externalid-and-saml-nameid). | -| SCIM identity mismatch between GitLab and the identity provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) to update the SCIM `id` for the user on GitLab.com. | +| SCIM identity mismatch between GitLab and the identity provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using the internal [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same internal [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) to update the SCIM `id` for the user on GitLab.com. | ## Search Rails logs for SCIM requests -GitLab.com administrators can search for SCIM requests in the `api_json.log` using the `pubsub-rails-inf-gprd-*` index in [Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html#using-kibana). Use the following filters based on the [SCIM API](../../../development/internal_api/index.md#scim-api): +GitLab.com administrators can search for SCIM requests in the `api_json.log` using the `pubsub-rails-inf-gprd-*` index in +[Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html#using-kibana). Use the following filters based on the internal +[SCIM API](../../../development/internal_api/index.md#scim-api): - `json.path`: `/scim/v2/groups/` - `json.params.value`: `` -- GitLab From f823d1ce3fc7cc4ed7432fbe07c2fc74b73e8a14 Mon Sep 17 00:00:00 2001 From: smriti Date: Tue, 11 Oct 2022 12:00:01 +0530 Subject: [PATCH 11/13] Fixed link on scim page --- doc/api/scim.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/scim.md b/doc/api/scim.md index 88ca43b651293e..b1763a44fc4883 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. -Not to be confused with the [internal SCIM API](../doc/development/internal_api/index.md#scim-api). +Not to be confused with the [internal SCIM API](../development/internal_api/index.md#scim-api). ## Get SCIM identities for a group -- GitLab From 5c06b763d2a327b1bfb3284e42064c6716e6a74a Mon Sep 17 00:00:00 2001 From: Evan Read Date: Tue, 11 Oct 2022 07:24:02 +0000 Subject: [PATCH 12/13] Suggestion for text alignment done --- doc/development/internal_api/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md index 515684e1683d60..755a7918111e7c 100644 --- a/doc/development/internal_api/index.md +++ b/doc/development/internal_api/index.md @@ -1081,7 +1081,7 @@ Example response: } ``` -## Create a SCIM provisioned user +### Create a SCIM provisioned user ```plaintext POST /api/scim/v2/groups/:group_path/Users/ -- GitLab From bd57002a4438b9897d8ce32c08e702484d332649 Mon Sep 17 00:00:00 2001 From: "Cynthia \"Arty\" Ng" Date: Wed, 12 Oct 2022 05:42:42 +0000 Subject: [PATCH 13/13] Cynthia Documentation Suggestions Applied --- doc/user/group/saml_sso/scim_setup.md | 2 +- doc/user/group/saml_sso/troubleshooting_scim.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md index 71e612712720cc..7fd335257aabb2 100644 --- a/doc/user/group/saml_sso/scim_setup.md +++ b/doc/user/group/saml_sso/scim_setup.md @@ -15,7 +15,7 @@ GitLab SAML SSO SCIM doesn't support updating users. When SCIM is enabled for a GitLab group, membership of that group is synchronized between GitLab and an identity provider. -The internal GitLab [SCIM API](../../../development/internal_api/index.md#scim-api) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). +The [internal GitLab SCIM API](../../../development/internal_api/index.md#scim-api) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). ## Configure GitLab diff --git a/doc/user/group/saml_sso/troubleshooting_scim.md b/doc/user/group/saml_sso/troubleshooting_scim.md index de336e5aa1f39c..6f8aed4b386a83 100644 --- a/doc/user/group/saml_sso/troubleshooting_scim.md +++ b/doc/user/group/saml_sso/troubleshooting_scim.md @@ -34,7 +34,7 @@ Administrators can use the Admin Area to [list SCIM identities for a user](../.. Group owners can see the list of users and the `externalId` stored for each user in the group SAML SSO Settings page. -A possible alternative is to use the internal [SCIM API](../../../development/internal_api/index.md#get-a-list-of-scim-provisioned-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`. +A possible alternative is to use the [SCIM API](../../../api/scim.md) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`. To see how the `external_uid` compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](troubleshooting.md#saml-debugging-tools). @@ -53,7 +53,7 @@ you can address the problem in the following ways: - You can have users unlink and relink themselves, based on the ["SAML authentication failed: User has already been taken"](troubleshooting.md#message-saml-authentication-failed-user-has-already-been-taken) section. - You can unlink all users simultaneously, by removing all users from the SAML app while provisioning is turned on. -- It may be possible to use the internal [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) to manually correct the `externalId` stored for users to match the SAML `NameId`. +- Use the [SCIM API](../../../api/scim.md) to manually correct the `externalId` stored for users to match the SAML `NameId`. To look up a user, you need to know the desired value that matches the `NameId` as well as the current `externalId`. It is important not to update these to incorrect values, since this causes users to be unable to sign in. It is also important not to assign a value to the wrong user, as this causes users to get signed into the wrong account. @@ -71,7 +71,7 @@ Changing the SAML or SCIM configuration or provider can cause the following prob | Problem | Solution | | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | SAML and SCIM identity mismatch. | First [verify that the user's SAML NameId matches the SCIM externalId](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid) and then [update or fix the mismatched SCIM externalId and SAML NameId](#update-or-fix-mismatched-scim-externalid-and-saml-nameid). | -| SCIM identity mismatch between GitLab and the identity provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using the internal [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same internal [SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user) to update the SCIM `id` for the user on GitLab.com. | +| SCIM identity mismatch between GitLab and the identity provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using the [SCIM API](../../../api/scim.md) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../api/scim.md) to update the SCIM `id` for the user on GitLab.com. | ## Search Rails logs for SCIM requests -- GitLab