Repository navigation
Expand file tree
/
Copy pathbotSecrets.ts
More file actions
88 lines (74 loc) · 2.72 KB
/
Copy pathbotSecrets.ts
File metadata and controls
88 lines (74 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import {
CognitoIdentityProviderClient,
AddUserPoolClientSecretCommand,
ListUserPoolClientSecretsCommand,
DeleteUserPoolClientSecretCommand,
ClientSecretDescriptorType,
} from '@aws-sdk/client-cognito-identity-provider';
const REGION = 'us-east-1';
const cognitoClient = new CognitoIdentityProviderClient({ region: REGION });
function getUserPoolId(): string {
const userPoolId = process.env.BOTPOOL_ID;
if (!userPoolId) {
throw new Error('BOTPOOL_ID environment variable is not set');
}
return userPoolId;
}
function sortSecretsByCreateDate(secrets: ClientSecretDescriptorType[]): ClientSecretDescriptorType[] {
return [...secrets].sort((a, b) => {
const aTime = a.ClientSecretCreateDate?.getTime() ?? 0;
const bTime = b.ClientSecretCreateDate?.getTime() ?? 0;
return aTime - bTime;
});
}
export async function listBotClientSecrets(clientId: string): Promise<ClientSecretDescriptorType[]> {
const response = await cognitoClient.send(new ListUserPoolClientSecretsCommand({
UserPoolId: getUserPoolId(),
ClientId: clientId,
}));
return sortSecretsByCreateDate(response.ClientSecrets ?? []);
}
export async function beginBotSecretRotation(clientId: string): Promise<{ clientSecretId: string; clientSecret: string }> {
const secrets = await listBotClientSecrets(clientId);
if (secrets.length === 0) {
throw new Error('No client secrets found');
}
if (secrets.length === 2) {
const newest = secrets[1];
if (!newest.ClientSecretId) {
throw new Error('Pending client secret is missing an identifier');
}
await cognitoClient.send(new DeleteUserPoolClientSecretCommand({
UserPoolId: getUserPoolId(),
ClientId: clientId,
ClientSecretId: newest.ClientSecretId,
}));
}
const response = await cognitoClient.send(new AddUserPoolClientSecretCommand({
UserPoolId: getUserPoolId(),
ClientId: clientId,
}));
const descriptor = response.ClientSecretDescriptor;
if (!descriptor?.ClientSecretId || !descriptor.ClientSecretValue) {
throw new Error('Cognito did not return ClientSecretId or ClientSecret');
}
return {
clientSecretId: descriptor.ClientSecretId,
clientSecret: descriptor.ClientSecretValue,
};
}
export async function finalizeBotSecretRotation(clientId: string): Promise<void> {
const secrets = await listBotClientSecrets(clientId);
if (secrets.length !== 2) {
throw new Error('No secret rotation in progress');
}
const oldest = secrets[0];
if (!oldest.ClientSecretId) {
throw new Error('Oldest client secret is missing an identifier');
}
await cognitoClient.send(new DeleteUserPoolClientSecretCommand({
UserPoolId: getUserPoolId(),
ClientId: clientId,
ClientSecretId: oldest.ClientSecretId,
}));
}