botframework-connector
Version:
Bot Connector is autorest generated connector client.
144 lines (131 loc) • 5.7 kB
text/typescript
/**
* @module botframework-connector
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import type { ServiceClientCredentials } from '@azure/core-http';
import { ServiceClientCredentialsFactory } from './serviceClientCredentialsFactory';
import { ok } from 'assert';
import { CertificateAppCredentials } from './certificateAppCredentials';
import { promisify } from 'util';
import * as opensslWrapper from 'openssl-wrapper';
const openssl = promisify(opensslWrapper.default);
/**
* A Certificate implementation of the [ServiceClientCredentialsFactory](xref:botframework-connector.ServiceClientCredentialsFactory) abstract class.
*/
export class CertificateServiceClientCredentialsFactory extends ServiceClientCredentialsFactory {
private readonly appId: string;
private readonly certificateThumbprint: string;
private readonly certificatePrivateKey: string;
private readonly tenantId: string | null;
private readonly x5c: string | null;
/**
* Initializes a new instance of the CertificateServiceClientCredentialsFactory class.
*
* @param appId Microsoft application Id related to the certificate.
* @param certificateThumbprint A hex encoded thumbprint of the certificate.
* @param certificatePrivateKey A PEM encoded certificate private key.
* @param tenantId Tenant ID of the Azure AD tenant where the bot is created.
* - Required for SingleTenant app types.
* - Optional for MultiTenant app types. **Note**: '_botframework.com_' is the default tenant when no value is provided.
*
* More information: https://learn.microsoft.com/en-us/security/zero-trust/develop/identity-supported-account-types.
* @param x5c Optional. Enables application developers to achieve easy certificates roll-over in Azure AD:
* set this parameter to send the public certificate (BEGIN CERTIFICATE) to Azure AD, so that Azure AD can use it to validate the subject name based on a trusted issuer policy.
*/
constructor(
appId: string,
certificateThumbprint: string,
certificatePrivateKey: string,
tenantId?: string,
x5c?: string,
);
/**
* Initializes a new instance of the CertificateServiceClientCredentialsFactory class.
*
* @param appId Microsoft application Id related to the certificate.
* @param x5c Value that enables application developers to achieve easy certificates roll-over in Azure AD
* set this parameter to send the public certificate (BEGIN CERTIFICATE) to Azure AD, so that Azure AD can use it to validate the subject name based on a trusted issuer policy.
* @param certificatePrivateKey A PEM encoded certificate private key.
* @param tenantId Tenant ID of the Azure AD tenant where the bot is created.
* - Required for SingleTenant app types.
* - Optional for MultiTenant app types. **Note**: '_botframework.com_' is the default tenant when no value is provided.
*
* More information: https://learn.microsoft.com/en-us/security/zero-trust/develop/identity-supported-account-types.
*/
constructor(appId: string, x5c: string, certificatePrivateKey: string, tenantId?: string);
/**
* @internal
*/
constructor(
appId: string,
certificateThumbprintOrx5c: string,
certificatePrivateKey: string,
tenantId?: string,
x5c?: string,
) {
super();
ok(appId?.trim(), 'CertificateServiceClientCredentialsFactory.constructor(): missing appId.');
ok(
certificatePrivateKey?.trim(),
'CertificateServiceClientCredentialsFactory.constructor(): missing certificatePrivateKey.',
);
if (certificateThumbprintOrx5c?.includes('-----BEGIN CERTIFICATE-----')) {
this.x5c = certificateThumbprintOrx5c;
} else {
ok(
certificateThumbprintOrx5c?.trim(),
'CertificateServiceClientCredentialsFactory.constructor(): missing certificateThumbprint or x5c value.',
);
this.certificateThumbprint = certificateThumbprintOrx5c;
this.x5c = x5c;
}
this.appId = appId;
this.certificatePrivateKey = certificatePrivateKey;
this.tenantId = tenantId;
}
/**
* @inheritdoc
*/
async isValidAppId(appId: string): Promise<boolean> {
return appId === this.appId;
}
/**
* @param cert Value with the certificate content.
* @returns The thumbprint value calculated from the cert content.
*/
private async getThumbprint(cert) {
const fingerprintResponse = await openssl('x509', Buffer.from(cert), { fingerprint: true, noout: true });
return Buffer.from(fingerprintResponse)
.toString()
.replace(/^.*Fingerprint=/, '')
.replace(/:/g, '')
.trim();
}
/**
* @inheritdoc
*/
async isAuthenticationDisabled(): Promise<boolean> {
// Auth is always enabled for Certificate.
return;
}
/**
* @inheritdoc
*/
async createCredentials(appId: string, audience: string): Promise<ServiceClientCredentials> {
ok(
await this.isValidAppId(appId),
'CertificateServiceClientCredentialsFactory.createCredentials(): Invalid Managed ID.',
);
return new CertificateAppCredentials(
this.appId,
this.certificateThumbprint ?? (await this.getThumbprint(this.x5c)),
this.certificatePrivateKey,
this.tenantId,
audience,
this.x5c,
);
}
}