diff --git a/.gitignore b/.gitignore index 5ba3da3148..6db4bf549c 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,7 @@ typings/ # dotenv environment variables file .env .env.test +.envrc # parcel-bundler cache (https://parceljs.org/) .cache diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index a4acd19cf2..621d912844 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -21,7 +21,7 @@ const backend = createBackend(); backend.add(import('@backstage/plugin-auth-backend')); backend.add(import('./authModuleGithubProvider')); backend.add(import('@backstage/plugin-auth-backend-module-guest-provider')); - +backend.add(import('@backstage/plugin-catalog-backend-module-gitlab-org')); backend.add(import('@backstage/plugin-app-backend/alpha')); backend.add(import('@backstage/plugin-catalog-backend-module-unprocessed')); backend.add( diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index 8f56657f68..54c19bd3cc 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -23,6 +23,7 @@ import { LoggerService } from '@backstage/backend-plugin-api'; import { GitLabDescendantGroupsResponse, GitLabGroup, + GitlabGroupMember, GitLabGroupMembersResponse, GitLabProject, GitLabUser, @@ -114,8 +115,19 @@ export class GitLabClient { return response; } + async listGroupMembers( + groupPath: string, + options?: CommonListOptions, + ): Promise> { + return this.pagedRequest( + `/groups/${encodeURIComponent(groupPath)}/members/all`, + options, + ); + } + async listUsers( options?: UserListOptions, + global?: boolean, ): Promise> { return this.pagedRequest(`/users?`, { ...options, @@ -128,6 +140,14 @@ export class GitLabClient { groupPath: string, options?: CommonListOptions, ): Promise> { + return this.listGroupMembers(groupPath, { + ...options, + show_seat_info: true, + }).then(resp => { + resp.items = resp.items.filter(user => user.is_using_seat); + return resp; + }); + /* return this.pagedRequest( `/groups/${encodeURIComponent(groupPath)}/members/all`, { @@ -138,6 +158,7 @@ export class GitLabClient { resp.items = resp.items.filter(user => user.is_using_seat); return resp; }); +*/ } async listGroups( diff --git a/plugins/catalog-backend-module-gitlab/src/lib/types.ts b/plugins/catalog-backend-module-gitlab/src/lib/types.ts index 2857fea162..89d2ceba1b 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/types.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/types.ts @@ -60,6 +60,7 @@ export type GitLabUser = { avatar_url: string; groups?: GitLabGroup[]; group_saml_identity?: GitLabGroupSamlIdentity; + is_using_seat?: boolean; // Only available in responses from the group members endpoint }; /** @@ -149,6 +150,13 @@ export type GitlabProviderConfig = { * Accepts only groups under the provided path (which will be stripped) */ group: string; + + /** + * If true, the provider will only ingest users that are part of the configured group. + * Only valid for self-hosted GitLab instances. + */ + restrictUsersToGroup?: boolean; + /** * ??? */ diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts index e10f9ee313..67a5134f25 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts @@ -356,7 +356,24 @@ export class GitlabOrgDiscoveryEntityProvider implements EntityProvider { let groups; let users; - if (this.gitLabClient.isSelfManaged()) { + // Doesn't matter if we are on SaaS or not, we can either get the users from the defined group or from the root group. + if (this.gitLabClient.isSelfManaged() && this.config.restrictUsersToGroup) { + groups = (await this.gitLabClient.listDescendantGroups(this.config.group)) + .items; + users = paginated( + options => + this.gitLabClient.listGroupMembers(this.config.group, options), + { + page: 1, + per_page: 100, + }, + ); + } + + if ( + this.gitLabClient.isSelfManaged() && + !this.config.restrictUsersToGroup + ) { groups = paginated( options => this.gitLabClient.listGroups(options), { @@ -365,19 +382,19 @@ export class GitlabOrgDiscoveryEntityProvider implements EntityProvider { all_available: true, }, ); - users = paginated( options => this.gitLabClient.listUsers(options), - { - page: 1, - per_page: 100, - active: true, - }, + { page: 1, per_page: 100, active: true }, ); - } else { + } + + // For SaaS, the only difference is the root group + if (!this.gitLabClient.isSelfManaged()) { groups = (await this.gitLabClient.listDescendantGroups(this.config.group)) .items; - const rootGroup = this.config.group.split('/')[0]; + const rootGroup = this.config.restrictUsersToGroup + ? this.config.group + : this.config.group.split('/')[0]; users = paginated( options => this.gitLabClient.listSaaSUsers(rootGroup, options), { diff --git a/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts b/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts index 09b42e6475..f53121e064 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts @@ -61,6 +61,7 @@ describe('config', () => { allowInherited: false, schedule: undefined, skipForkedRepos: false, + restrictUsersToGroup: false, }), ); }); @@ -99,6 +100,7 @@ describe('config', () => { allowInherited: false, schedule: undefined, skipForkedRepos: false, + restrictUsersToGroup: false, }), ); }); @@ -137,6 +139,7 @@ describe('config', () => { orgEnabled: false, allowInherited: false, schedule: undefined, + restrictUsersToGroup: false, skipForkedRepos: true, }), ); @@ -178,6 +181,7 @@ describe('config', () => { orgEnabled: false, allowInherited: false, skipForkedRepos: false, + restrictUsersToGroup: false, schedule: { frequency: Duration.fromISO('PT30M'), timeout: { diff --git a/plugins/catalog-backend-module-gitlab/src/providers/config.ts b/plugins/catalog-backend-module-gitlab/src/providers/config.ts index 8606a525bd..68eba7165a 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/config.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/config.ts @@ -51,6 +51,8 @@ function readGitlabConfig(id: string, config: Config): GitlabProviderConfig { const schedule = config.has('schedule') ? readTaskScheduleDefinitionFromConfig(config.getConfig('schedule')) : undefined; + const restrictUsersToGroup = + config.getOptionalBoolean('restrictUsersToGroup') ?? false; return { id, @@ -66,6 +68,7 @@ function readGitlabConfig(id: string, config: Config): GitlabProviderConfig { orgEnabled, allowInherited, skipForkedRepos, + restrictUsersToGroup, }; }