From 03d29026859baf18bd94024ecfde45cce90736ce Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 08:04:57 +0200 Subject: [PATCH 1/6] Add support for FreeIPA as an LDAP vendor Signed-off-by: Marc Rooding --- docs/integrations/ldap/org.md | 8 ++++++++ plugins/catalog-backend-module-ldap/src/ldap/client.ts | 3 +++ .../catalog-backend-module-ldap/src/ldap/vendors.ts | 10 ++++++++++ 3 files changed, 21 insertions(+) diff --git a/docs/integrations/ldap/org.md b/docs/integrations/ldap/org.md index e7028f34f1..5b49e762a7 100644 --- a/docs/integrations/ldap/org.md +++ b/docs/integrations/ldap/org.md @@ -12,6 +12,14 @@ groups - directly from an LDAP compatible service. The result is a hierarchy of [`Group`](../../features/software-catalog/descriptor-format.md#kind-group) kind entities that mirror your org setup. +## Suported vendors + +Currently, Backstage only supports the following LDAP vendors: + +1. OpenLDAP (default) +2. Active Directory +3. FreeIPA + ## Installation This guide will use the Entity Provider method. If you for some reason prefer diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index a9283ecb94..d9d0faf9a2 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -23,6 +23,7 @@ import { errorString } from './util'; import { ActiveDirectoryVendor, DefaultLdapVendor, + FreeIpaVendor, LdapVendor, } from './vendors'; @@ -199,6 +200,8 @@ export class LdapClient { .then(root => { if (root && root.raw?.forestFunctionality) { return ActiveDirectoryVendor; + } else if (root && root.raw?.ipaDomainLevel) { + return FreeIpaVendor; } return DefaultLdapVendor; }) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts b/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts index 447df8aaa5..d2df250638 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts @@ -63,6 +63,16 @@ export const ActiveDirectoryVendor: LdapVendor = { }, }; +export const FreeIpaVendor: LdapVendor = { + dnAttributeName: 'dn', + uuidAttributeName: 'ipaUniqueID', + decodeStringAttribute: (entry, name) => { + return decode(entry, name, value => { + return value.toString(); + }); + }, +}; + // Decode an attribute to a consumer function decode( entry: SearchEntry, From f7f29dbf0e5df219d8708398431e100a87c4c03a Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 08:39:49 +0200 Subject: [PATCH 2/6] Add test case for reading an LDAP user from FreeIPA Signed-off-by: Marc Rooding --- .../src/ldap/read.test.ts | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts index 49803b9c39..53f2d33794 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts @@ -32,7 +32,7 @@ import { resolveRelations, } from './read'; import { RecursivePartial } from './util'; -import { ActiveDirectoryVendor, DefaultLdapVendor } from './vendors'; +import { ActiveDirectoryVendor, DefaultLdapVendor, FreeIpaVendor } from './vendors'; function user(data: RecursivePartial): UserEntity { return merge( @@ -195,8 +195,65 @@ describe('readLdapUsers', () => { new Map([['dn-value', new Set(['x', 'y', 'z'])]]), ); }); + + it('transfers all attributes from FreeIPA', async () => { + client.getVendor.mockResolvedValue(FreeIpaVendor); + client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => { + await fn( + searchEntry({ + uid: ['uid-value'], + description: ['description-value'], + cn: ['cn-value'], + mail: ['mail-value'], + avatarUrl: ['avatarUrl-value'], + memberOf: ['x', 'y', 'z'], + dn: ['dn-value'], + ipaUniqueID: ['uuid-value'], + }), + ); + }); + const config: UserConfig = { + dn: 'ddd', + options: {}, + map: { + rdn: 'uid', + name: 'uid', + description: 'description', + displayName: 'cn', + email: 'mail', + picture: 'avatarUrl', + memberOf: 'memberOf', + }, + }; + const { users, userMemberOf } = await readLdapUsers(client, config); + expect(users).toEqual([ + expect.objectContaining({ + metadata: { + name: 'uid-value', + description: 'description-value', + annotations: { + [LDAP_DN_ANNOTATION]: 'dn-value', + [LDAP_RDN_ANNOTATION]: 'uid-value', + [LDAP_UUID_ANNOTATION]: 'uuid-value', + }, + }, + spec: { + profile: { + displayName: 'cn-value', + email: 'mail-value', + picture: 'avatarUrl-value', + }, + memberOf: [], + }, + }), + ]); + expect(userMemberOf).toEqual( + new Map([['dn-value', new Set(['x', 'y', 'z'])]]), + ); + }); }); + describe('readLdapGroups', () => { const client: jest.Mocked = { searchStreaming: jest.fn(), From ddfd566606f0ca398dcf93fa58df819bf65c31d5 Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 08:47:57 +0200 Subject: [PATCH 3/6] Add changeset Signed-off-by: Marc Rooding --- .changeset/hungry-cougars-press.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/hungry-cougars-press.md diff --git a/.changeset/hungry-cougars-press.md b/.changeset/hungry-cougars-press.md new file mode 100644 index 0000000000..c99e1f4c76 --- /dev/null +++ b/.changeset/hungry-cougars-press.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-ldap': patch +--- + +Fix mapping between users and groups for FreeIPA when using the LdapOrgProcessor From 545db2ba6c4e91cf3cb3b9544acca57a3987e510 Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 08:56:02 +0200 Subject: [PATCH 4/6] Fix typo in docs Signed-off-by: Marc Rooding --- docs/integrations/ldap/org.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/ldap/org.md b/docs/integrations/ldap/org.md index 5b49e762a7..010f46832d 100644 --- a/docs/integrations/ldap/org.md +++ b/docs/integrations/ldap/org.md @@ -12,7 +12,7 @@ groups - directly from an LDAP compatible service. The result is a hierarchy of [`Group`](../../features/software-catalog/descriptor-format.md#kind-group) kind entities that mirror your org setup. -## Suported vendors +## Supported vendors Currently, Backstage only supports the following LDAP vendors: From 0acd49fb5c29575970a7f6c30d7c4d53aefd424f Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 09:27:03 +0200 Subject: [PATCH 5/6] Formatting Signed-off-by: Marc Rooding --- plugins/catalog-backend-module-ldap/src/ldap/read.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts index 53f2d33794..fc451fde97 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts @@ -32,7 +32,11 @@ import { resolveRelations, } from './read'; import { RecursivePartial } from './util'; -import { ActiveDirectoryVendor, DefaultLdapVendor, FreeIpaVendor } from './vendors'; +import { + ActiveDirectoryVendor, + DefaultLdapVendor, + FreeIpaVendor, +} from './vendors'; function user(data: RecursivePartial): UserEntity { return merge( @@ -253,7 +257,6 @@ describe('readLdapUsers', () => { }); }); - describe('readLdapGroups', () => { const client: jest.Mocked = { searchStreaming: jest.fn(), From faf37e12a8d87859428bbf5418a77f0faf9c6943 Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 15:33:35 +0200 Subject: [PATCH 6/6] Reworded the supported vendors Signed-off-by: Marc Rooding --- docs/integrations/ldap/org.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/integrations/ldap/org.md b/docs/integrations/ldap/org.md index 010f46832d..dbd3f4ff43 100644 --- a/docs/integrations/ldap/org.md +++ b/docs/integrations/ldap/org.md @@ -14,11 +14,7 @@ entities that mirror your org setup. ## Supported vendors -Currently, Backstage only supports the following LDAP vendors: - -1. OpenLDAP (default) -2. Active Directory -3. FreeIPA +Backstage in general supports OpenLDAP compatible vendors, as well as Active Directory and FreeIPA. If you are using a vendor that does not seem to be supported, please [file an issue](https://github.com/backstage/backstage/issues/new?assignees=&labels=enhancement&template=feature_template.md). ## Installation