UNPKG

@dgac/nmb2b-client

Version:

EUROCONTROL Network Manager B2B SOAP client

1 lines 8.06 kB
{"version":3,"file":"security.mjs","names":[],"sources":["../src/security.ts"],"sourcesContent":["import { assert } from './utils/assert.js';\nimport { createDebugLogger } from './utils/debug.js';\nconst debug = createDebugLogger('security');\nimport type { Config } from './config.js';\nimport type { ISecurity } from 'soap';\nimport {\n ClientSSLSecurity,\n ClientSSLSecurityPFX,\n BasicAuthSecurity,\n} from 'soap';\nimport fs from 'node:fs';\n\n/**\n * Security configuration using a PFX / PKCS #12 certificate.\n * Used to authenticate with the B2B services using a client certificate.\n */\ninterface PfxSecurity {\n /**\n * The content of the PFX / PKCS #12 file.\n */\n pfx: Buffer;\n\n /**\n * The passphrase for the PFX / PKCS #12 container.\n */\n passphrase: string;\n}\n\n/**\n * Security configuration using PEM certificate and key.\n * Used to authenticate with the B2B services using a client certificate.\n */\ninterface PemSecurity {\n /**\n * The content of the PEM certificate file.\n */\n cert: Buffer;\n\n /**\n * The content of the PEM key file.\n */\n key: Buffer;\n\n /**\n * The passphrase for the PEM key.\n * Can be omitted if the key is not encrypted.\n */\n passphrase?: string;\n}\n\n/**\n * Security configuration using API Gateway credentials.\n * Used to authenticate with the B2B services using an API Key ID and Secret Key.\n * These credentials will be sent as Basic Authentication headers.\n */\ninterface ApiGwSecurity {\n /**\n * The API Key ID (used as username for Basic Auth).\n */\n apiKeyId: string;\n\n /**\n * The API Secret Key (used as password for Basic Auth).\n */\n apiSecretKey: string;\n}\n\n/**\n * Supported authentication methods.\n * Used in the `Config` object to specify how the client should authenticate with the B2B services.\n */\nexport type Security = PfxSecurity | PemSecurity | ApiGwSecurity;\n\n/**\n * Asserts that the provided object is a valid {@link Security} configuration.\n * Checks for the presence and validity of required fields for each security type.\n *\n * @param obj - The object to validate.\n * @throws {AssertionError} If the object is not a valid `Security` configuration.\n */\nexport function assertValidSecurity(obj: unknown): asserts obj is Security {\n assert(!!obj && typeof obj === 'object', 'Must be an object');\n\n if ('apiKeyId' in obj) {\n assert(\n !!obj.apiKeyId &&\n typeof obj.apiKeyId === 'string' &&\n obj.apiKeyId.length > 0,\n 'security.apiKeyId must be a string with a length > 0',\n );\n\n assert(\n 'apiSecretKey' in obj &&\n typeof obj.apiSecretKey === 'string' &&\n obj.apiSecretKey.length > 0,\n 'security.apiSecretKey must be defined when using security.apiKeyId',\n );\n\n return;\n }\n\n assert(\n ('pfx' in obj && Buffer.isBuffer(obj.pfx)) ||\n ('cert' in obj && Buffer.isBuffer(obj.cert)),\n 'security.pfx or security.cert must be buffers',\n );\n\n if ('cert' in obj && obj.cert) {\n assert(\n 'key' in obj && obj.key && Buffer.isBuffer(obj.key),\n 'security.key must be a buffer if security.pem is defined',\n );\n }\n}\n\n/**\n * @deprecated Use {@link assertValidSecurity} instead.\n */\nexport function isValidSecurity(obj: unknown): obj is Security {\n assertValidSecurity(obj);\n return true;\n}\n\n/**\n * @internal\n */\nexport function prepareSecurity(config: Config): ISecurity {\n const { security } = config;\n\n if ('apiKeyId' in security) {\n const { apiKeyId, apiSecretKey } = security;\n debug('Using ApiGateway security');\n return new BasicAuthSecurity(apiKeyId, apiSecretKey);\n } else if ('pfx' in security) {\n const { pfx, passphrase } = security;\n debug('Using PFX certificates');\n return new ClientSSLSecurityPFX(pfx, passphrase);\n } else if ('cert' in security) {\n debug('Using PEM certificates');\n const { key, cert, passphrase } = security;\n return new ClientSSLSecurity(\n key,\n cert,\n undefined,\n passphrase ? { passphrase } : null,\n );\n }\n\n throw new Error('Invalid security object');\n}\n\nlet envSecurity: Security | undefined;\n\n/**\n * Create a security objet from environment variables\n *\n * Will cache data for future use.\n *\n * @returns Security configuration\n */\nexport function fromEnv(): Security {\n if (envSecurity) {\n return envSecurity;\n }\n\n envSecurity = fromValues(process.env);\n\n return envSecurity;\n}\n\n/**\n * Convenience function to clear the cached security objet\n */\nexport function clearCache(): void {\n envSecurity = undefined;\n}\n\n/**\n * Create a security objet from an environment-like object\n *\n * @param env Environment variables\n * @returns Security configuration\n */\nexport function fromValues(env: Record<string, string | undefined>): Security {\n const { B2B_CERT, B2B_API_KEY_ID, B2B_API_SECRET_KEY } = env;\n\n if (!B2B_CERT && !B2B_API_KEY_ID) {\n throw new Error(\n 'Please define a B2B_CERT or a B2B_API_KEY_ID environment variable',\n );\n }\n\n if (B2B_API_KEY_ID) {\n if (!B2B_API_SECRET_KEY) {\n throw new Error(\n `When using B2B_API_KEY_ID, a B2B_API_SECRET_KEY must be defined`,\n );\n }\n\n return {\n apiKeyId: B2B_API_KEY_ID,\n apiSecretKey: B2B_API_SECRET_KEY,\n };\n }\n\n if (!B2B_CERT) {\n throw new Error('Should never happen');\n }\n\n if (!fs.existsSync(B2B_CERT)) {\n throw new Error(`${B2B_CERT} is not a valid certificate file`);\n }\n\n const pfxOrPem = fs.readFileSync(B2B_CERT);\n\n if (!env.B2B_CERT_FORMAT || env.B2B_CERT_FORMAT === 'pfx') {\n return {\n pfx: pfxOrPem,\n passphrase: env.B2B_CERT_PASSPHRASE ?? '',\n };\n } else if (env.B2B_CERT_FORMAT === 'pem') {\n if (!env.B2B_CERT_KEY || !fs.existsSync(env.B2B_CERT_KEY)) {\n throw new Error(\n 'Please define a valid B2B_CERT_KEY environment variable',\n );\n }\n\n const security: PemSecurity = {\n cert: pfxOrPem,\n key: fs.readFileSync(env.B2B_CERT_KEY),\n };\n\n if (env.B2B_CERT_PASSPHRASE) {\n security.passphrase = env.B2B_CERT_PASSPHRASE;\n }\n\n return security;\n }\n\n throw new Error('Unsupported B2B_CERT_FORMAT, must be pfx or pem');\n}\n"],"mappings":";;;;;;AAEA,MAAM,QAAQ,kBAAkB,WAAW;;;;;;;;AA8E3C,SAAgB,oBAAoB,KAAuC;AACzE,QAAO,CAAC,CAAC,OAAO,OAAO,QAAQ,UAAU,oBAAoB;AAE7D,KAAI,cAAc,KAAK;AACrB,SACE,CAAC,CAAC,IAAI,YACJ,OAAO,IAAI,aAAa,YACxB,IAAI,SAAS,SAAS,GACxB,uDACD;AAED,SACE,kBAAkB,OAChB,OAAO,IAAI,iBAAiB,YAC5B,IAAI,aAAa,SAAS,GAC5B,qEACD;AAED;;AAGF,QACG,SAAS,OAAO,OAAO,SAAS,IAAI,IAAI,IACtC,UAAU,OAAO,OAAO,SAAS,IAAI,KAAK,EAC7C,gDACD;AAED,KAAI,UAAU,OAAO,IAAI,KACvB,QACE,SAAS,OAAO,IAAI,OAAO,OAAO,SAAS,IAAI,IAAI,EACnD,2DACD;;;;;AAOL,SAAgB,gBAAgB,KAA+B;AAC7D,qBAAoB,IAAI;AACxB,QAAO;;;;;AAMT,SAAgB,gBAAgB,QAA2B;CACzD,MAAM,EAAE,aAAa;AAErB,KAAI,cAAc,UAAU;EAC1B,MAAM,EAAE,UAAU,iBAAiB;AACnC,QAAM,4BAA4B;AAClC,SAAO,IAAI,kBAAkB,UAAU,aAAa;YAC3C,SAAS,UAAU;EAC5B,MAAM,EAAE,KAAK,eAAe;AAC5B,QAAM,yBAAyB;AAC/B,SAAO,IAAI,qBAAqB,KAAK,WAAW;YACvC,UAAU,UAAU;AAC7B,QAAM,yBAAyB;EAC/B,MAAM,EAAE,KAAK,MAAM,eAAe;AAClC,SAAO,IAAI,kBACT,KACA,MACA,QACA,aAAa,EAAE,YAAY,GAAG,KAC/B;;AAGH,OAAM,IAAI,MAAM,0BAA0B;;AAG5C,IAAI;;;;;;;;AASJ,SAAgB,UAAoB;AAClC,KAAI,YACF,QAAO;AAGT,eAAc,WAAW,QAAQ,IAAI;AAErC,QAAO;;;;;AAMT,SAAgB,aAAmB;AACjC,eAAc;;;;;;;;AAShB,SAAgB,WAAW,KAAmD;CAC5E,MAAM,EAAE,UAAU,gBAAgB,uBAAuB;AAEzD,KAAI,CAAC,YAAY,CAAC,eAChB,OAAM,IAAI,MACR,oEACD;AAGH,KAAI,gBAAgB;AAClB,MAAI,CAAC,mBACH,OAAM,IAAI,MACR,kEACD;AAGH,SAAO;GACL,UAAU;GACV,cAAc;GACf;;AAGH,KAAI,CAAC,SACH,OAAM,IAAI,MAAM,sBAAsB;AAGxC,KAAI,CAAC,GAAG,WAAW,SAAS,CAC1B,OAAM,IAAI,MAAM,GAAG,SAAS,kCAAkC;CAGhE,MAAM,WAAW,GAAG,aAAa,SAAS;AAE1C,KAAI,CAAC,IAAI,mBAAmB,IAAI,oBAAoB,MAClD,QAAO;EACL,KAAK;EACL,YAAY,IAAI,uBAAuB;EACxC;UACQ,IAAI,oBAAoB,OAAO;AACxC,MAAI,CAAC,IAAI,gBAAgB,CAAC,GAAG,WAAW,IAAI,aAAa,CACvD,OAAM,IAAI,MACR,0DACD;EAGH,MAAM,WAAwB;GAC5B,MAAM;GACN,KAAK,GAAG,aAAa,IAAI,aAAa;GACvC;AAED,MAAI,IAAI,oBACN,UAAS,aAAa,IAAI;AAG5B,SAAO;;AAGT,OAAM,IAAI,MAAM,kDAAkD"}