diff --git a/.changeset/clean-sloths-grin.md b/.changeset/clean-sloths-grin.md new file mode 100644 index 0000000000..4b3b96d255 --- /dev/null +++ b/.changeset/clean-sloths-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-ldap': patch +--- + +Add TLS support to ingest GSuite LDAP data diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 54ecd7b737..9ef953d625 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -39,8 +39,8 @@ "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/types": "workspace:^", - "@types/ldapjs": "^2.2.0", - "ldapjs": "^2.2.0", + "@types/ldapjs": "^2.2.5", + "ldapjs": "^2.3.3", "lodash": "^4.17.21", "uuid": "^9.0.0", "winston": "^3.2.1" diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index 410318197e..dcd5c1e170 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -15,8 +15,10 @@ */ import { ForwardedError, stringifyError } from '@backstage/errors'; +import * as fs from 'fs'; import ldap, { Client, SearchEntry, SearchOptions } from 'ldapjs'; import { cloneDeep } from 'lodash'; +import tlsLib from 'tls'; import { Logger } from 'winston'; import { BindConfig, TLSConfig } from './config'; import { createOptions, errorString } from './util'; @@ -44,9 +46,28 @@ export class LdapClient { bind?: BindConfig, tls?: TLSConfig, ): Promise { + const readTLSOptionFile = (file?: string) => + file !== undefined ? fs.readFileSync(file).toString() : undefined; + + const getTlsOptions = () => { + const certs = readTLSOptionFile(tls?.certs); + const keys = readTLSOptionFile(tls?.keys); + + if (certs !== undefined || keys !== undefined) { + return { + secureContext: tlsLib.createSecureContext({ + cert: certs, + key: keys, + }), + rejectUnauthorized: tls?.rejectUnauthorized, + }; + } + return tls; + }; + const client = ldap.createClient({ url: target, - tlsOptions: tls, + tlsOptions: getTlsOptions(), }); // We want to have a catch-all error handler at the top, since the default diff --git a/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts index 28c842294f..722625f3ed 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts @@ -80,7 +80,11 @@ describe('readLdapConfig', () => { { target: 'target', bind: { dn: 'bdn', secret: 's' }, - tls: { rejectUnauthorized: false }, + tls: { + rejectUnauthorized: false, + keys: '/tmp/keys.pem', + certs: '/tmp/certs.pem', + }, users: { dn: 'udn', options: { @@ -140,7 +144,11 @@ describe('readLdapConfig', () => { { target: 'target', bind: { dn: 'bdn', secret: 's' }, - tls: { rejectUnauthorized: false }, + tls: { + rejectUnauthorized: false, + keys: '/tmp/keys.pem', + certs: '/tmp/certs.pem', + }, users: { dn: 'udn', options: { diff --git a/plugins/catalog-backend-module-ldap/src/ldap/config.ts b/plugins/catalog-backend-module-ldap/src/ldap/config.ts index 9ae4b9ed8d..08aee5feee 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/config.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/config.ts @@ -49,6 +49,10 @@ export type LdapProviderConfig = { export type TLSConfig = { // Node TLS rejectUnauthorized rejectUnauthorized?: boolean; + // A file containing private keys in PEM format + keys?: string; + // A file containing cert chains in PEM format + certs?: string; }; /** @@ -205,6 +209,8 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] { } return { rejectUnauthorized: c.getOptionalBoolean('rejectUnauthorized'), + keys: c.getOptionalString('keys'), + certs: c.getOptionalString('certs'), }; } diff --git a/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts b/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts index 02329b90b3..9f4e365c38 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts @@ -105,7 +105,7 @@ function decode( function formatGUID(objectGUID: string | Buffer): string { let data: Buffer; if (typeof objectGUID === 'string') { - data = new Buffer(objectGUID, 'binary'); + data = Buffer.from(objectGUID, 'binary'); } else { data = objectGUID; } diff --git a/yarn.lock b/yarn.lock index fafc485f01..28e237a7f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5672,9 +5672,9 @@ __metadata: "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/types": "workspace:^" - "@types/ldapjs": ^2.2.0 + "@types/ldapjs": ^2.2.5 "@types/lodash": ^4.14.151 - ldapjs: ^2.2.0 + ldapjs: ^2.3.3 lodash: ^4.17.21 uuid: ^9.0.0 winston: ^3.2.1 @@ -19193,7 +19193,7 @@ __metadata: languageName: node linkType: hard -"@types/ldapjs@npm:^2.2.0": +"@types/ldapjs@npm:^2.2.5": version: 2.2.5 resolution: "@types/ldapjs@npm:2.2.5" dependencies: @@ -33551,7 +33551,7 @@ __metadata: languageName: node linkType: hard -"ldapjs@npm:^2.2.0": +"ldapjs@npm:^2.3.3": version: 2.3.3 resolution: "ldapjs@npm:2.3.3" dependencies: