Skip to content

Commit

Permalink
feat: Use nodejs18 in custom-resources and aws-sdk v3
Browse files Browse the repository at this point in the history
  • Loading branch information
quy-ho-dh committed Apr 23, 2024
1 parent d09dc65 commit b30da10
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 121 deletions.
2 changes: 1 addition & 1 deletion lib/plugins/aws/custom-resources/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ async function addCustomResourceToService(awsProvider, resourceName, iamRoleStat
FunctionName: absoluteFunctionName,
Handler,
MemorySize: 1024,
Runtime: 'nodejs16.x',
Runtime: 'nodejs18.x',
Timeout: 180,
},
DependsOn: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

const { awsRequest, wait } = require('../utils');
const { getEnvironment, handlerWrapper } = require('../utils');
const {
APIGatewayClient,
GetAccountCommand,
UpdateAccountCommand,
} = require('@aws-sdk/client-api-gateway');
const {
IAMClient,
ListAttachedRolePoliciesCommand,
CreateRoleCommand,
AttachRolePolicyCommand,
} = require('@aws-sdk/client-iam');

async function handler(event, context) {
if (event.RequestType === 'Create') {
Expand All @@ -18,9 +29,9 @@ async function create(event, context) {
const { RoleArn } = event.ResourceProperties;
const { Partition: partition, AccountId: accountId, Region: region } = getEnvironment(context);

const assignedRoleArn = (
await awsRequest({ name: 'APIGateway', params: { region } }, 'getAccount')
).cloudwatchRoleArn;
const apiGatewayClient = new APIGatewayClient({ region });
const assignedRoleArn = (await awsRequest(() => apiGatewayClient.send(new GetAccountCommand())))
.cloudwatchRoleArn;

let roleArn = `arn:${partition}:iam::${accountId}:role/serverlessApiGatewayCloudWatchRole`;
if (RoleArn) {
Expand All @@ -32,14 +43,18 @@ async function create(event, context) {

const roleName = roleArn.slice(roleArn.lastIndexOf('/') + 1);

const iamClient = new IAMClient({ region });
const attachedPolicies = await (async () => {
try {
return (await awsRequest('IAM', 'listAttachedRolePolicies', { RoleName: roleName }))
.AttachedPolicies;
return (
await awsRequest(() =>
iamClient.send(new ListAttachedRolePoliciesCommand({ RoleName: roleName }))
)
).AttachedPolicies;
} catch (error) {
if (error.code === 'NoSuchEntity') {
// Role doesn't exist yet, create;
await awsRequest('IAM', 'createRole', {
const createRoleCommand = new CreateRoleCommand({
AssumeRolePolicyDocument: JSON.stringify({
Version: '2012-10-17',
Statement: [
Expand All @@ -55,6 +70,7 @@ async function create(event, context) {
Path: '/',
RoleName: roleName,
});
await awsRequest(() => iamClient.send(createRoleCommand));
return [];
}
throw error;
Expand All @@ -66,10 +82,11 @@ async function create(event, context) {
(policy) => policy.PolicyArn === apiGatewayPushToCloudWatchLogsPolicyArn
)
) {
await awsRequest('IAM', 'attachRolePolicy', {
const attachRoleCommand = new AttachRolePolicyCommand({
PolicyArn: apiGatewayPushToCloudWatchLogsPolicyArn,
RoleName: roleName,
});
await awsRequest(() => iamClient.send(attachRoleCommand));
}
}

Expand All @@ -78,7 +95,7 @@ async function create(event, context) {

const updateAccount = async (counter = 1) => {
try {
await awsRequest({ name: 'APIGateway', params: { region } }, 'updateAccount', {
const command = new UpdateAccountCommand({
patchOperations: [
{
op: 'replace',
Expand All @@ -87,6 +104,8 @@ async function create(event, context) {
},
],
});

await awsRequest(() => apiGatewayClient.send(command));
} catch (error) {
if (counter < 10) {
// Observed fails with errors marked as non-retryable. Still they're outcome of
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
'use strict';

const { awsRequest } = require('../../utils');
const {
LambdaClient,
AddPermissionCommand,
RemovePermissionCommand,
} = require('@aws-sdk/client-lambda');

function getStatementId(functionName, userPoolName) {
const normalizedUserPoolName = userPoolName.toLowerCase().replace(/[.:*\s]/g, '');
Expand All @@ -13,23 +18,25 @@ function getStatementId(functionName, userPoolName) {

async function addPermission(config) {
const { functionName, userPoolName, partition, region, accountId, userPoolId } = config;
const payload = {
const addPermissionCommand = new AddPermissionCommand({
Action: 'lambda:InvokeFunction',
FunctionName: functionName,
Principal: 'cognito-idp.amazonaws.com',
StatementId: getStatementId(functionName, userPoolName),
SourceArn: `arn:${partition}:cognito-idp:${region}:${accountId}:userpool/${userPoolId}`,
};
return awsRequest({ name: 'Lambda', params: { region } }, 'addPermission', payload);
});
const lambdaClient = new LambdaClient({ region });
return await awsRequest(() => lambdaClient.send(addPermissionCommand));
}

async function removePermission(config) {
const { functionName, userPoolName, region } = config;
const payload = {
const removePermissionCommand = new RemovePermissionCommand({
FunctionName: functionName,
StatementId: getStatementId(functionName, userPoolName),
};
return awsRequest({ name: 'Lambda', params: { region } }, 'removePermission', payload);
});
const lambdaClient = new LambdaClient({ region });
return awsRequest(() => lambdaClient.send(removePermissionCommand));
}

module.exports = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
'use strict';

const { awsRequest } = require('../../utils');
const {
CognitoIdentityProviderClient,
ListUserPoolsCommand,
DescribeUserPoolCommand,
UpdateUserPoolCommand,
} = require('@aws-sdk/client-cognito-identity-provider');

const customSenderSources = ['CustomSMSSender', 'CustomEmailSender'];

Expand Down Expand Up @@ -33,17 +39,11 @@ function getUpdateConfigFromCurrentSetup(currentSetup) {
async function findUserPoolByName(config) {
const { userPoolName, region } = config;

const payload = {
MaxResults: 60,
};
const cognitoClient = new CognitoIdentityProviderClient({ region });

async function recursiveFind(nextToken) {
if (nextToken) payload.NextToken = nextToken;
return awsRequest(
{ name: 'CognitoIdentityServiceProvider', params: { region } },
'listUserPools',
payload
).then((result) => {
const listUserPoolsCommand = new ListUserPoolsCommand({ MaxResults: 60, NextToken: nextToken });
return awsRequest(() => cognitoClient.send(listUserPoolsCommand)).then((result) => {
const matches = result.UserPools.filter((pool) => pool.Name === userPoolName);
if (matches.length) {
return matches.shift();
Expand All @@ -58,12 +58,13 @@ async function findUserPoolByName(config) {

async function getConfiguration(config) {
const { region } = config;
const cognitoClient = new CognitoIdentityProviderClient({ region });

return findUserPoolByName(config).then((userPool) =>
awsRequest({ name: 'CognitoIdentityServiceProvider', params: { region } }, 'describeUserPool', {
UserPoolId: userPool.Id,
})
const userPool = await findUserPoolByName(config);
const response = await cognitoClient.send(
new DescribeUserPoolCommand({ UserPoolId: userPool.Id })
);
return response.UserPool;
}

async function updateConfiguration(config) {
Expand Down Expand Up @@ -94,11 +95,10 @@ async function updateConfiguration(config) {
LambdaConfig,
});

return awsRequest(
{ name: 'CognitoIdentityServiceProvider', params: { region } },
'updateUserPool',
updatedConfig
);
const cognitoIdentityProvider = new CognitoIdentityProviderClient({ region });
const updateUserPoolCommand = new UpdateUserPoolCommand(updatedConfig);

return awsRequest(() => cognitoIdentityProvider.send(updateUserPoolCommand));
});
}

Expand All @@ -118,11 +118,10 @@ async function removeConfiguration(config) {
LambdaConfig,
});

return awsRequest(
{ name: 'CognitoIdentityServiceProvider', params: { region } },
'updateUserPool',
updatedConfig
);
const client = new CognitoIdentityProviderClient({ region });
const updateUserPoolCommand = new UpdateUserPoolCommand(updatedConfig);

return awsRequest(() => client.send(updateUserPoolCommand));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

const { awsRequest } = require('../../utils');
const { getEventBusName, getEventBusTargetId } = require('./utils');
const {
EventBridgeClient,
CreateEventBusCommand,
DeleteEventBusCommand,
PutRuleCommand,
DeleteRuleCommand,
PutTargetsCommand,
RemoveTargetsCommand,
} = require('@aws-sdk/client-eventbridge');

async function createEventBus(config) {
const { eventBus, region } = config;
Expand All @@ -10,9 +19,8 @@ async function createEventBus(config) {
if (eventBus.startsWith('arn')) {
return Promise.resolve();
}
return awsRequest({ name: 'EventBridge', params: { region } }, 'createEventBus', {
Name: eventBus,
});
const client = new EventBridgeClient({ region });
return awsRequest(() => client.send(new CreateEventBusCommand({ Name: eventBus })));
}
return Promise.resolve();
}
Expand All @@ -25,9 +33,8 @@ async function deleteEventBus(config) {
return Promise.resolve();
}

return awsRequest({ name: 'EventBridge', params: { region } }, 'deleteEventBus', {
Name: eventBus,
});
const client = new EventBridgeClient({ region });
return awsRequest(() => client.send(new DeleteEventBusCommand({ Name: eventBus })));
}
return Promise.resolve();
}
Expand All @@ -37,24 +44,34 @@ async function updateRuleConfiguration(config) {

const EventBusName = getEventBusName(eventBus);

return awsRequest({ name: 'EventBridge', params: { region } }, 'putRule', {
Name: ruleName,
EventBusName,
EventPattern: JSON.stringify(pattern),
ScheduleExpression: schedule,
State: state,
});
const client = new EventBridgeClient({ region });
return awsRequest(() =>
client.send(
new PutRuleCommand({
Name: ruleName,
EventBusName,
EventPattern: JSON.stringify(pattern),
ScheduleExpression: schedule,
State: state,
})
)
);
}

async function removeRuleConfiguration(config) {
const { ruleName, eventBus, region } = config;

const EventBusName = getEventBusName(eventBus);

return awsRequest({ name: 'EventBridge', params: { region } }, 'deleteRule', {
Name: ruleName,
EventBusName,
});
const client = new EventBridgeClient({ region });
return awsRequest(() =>
client.send(
new DeleteRuleCommand({
Name: ruleName,
EventBusName,
})
)
);
}

async function updateTargetConfiguration(config) {
Expand All @@ -75,12 +92,18 @@ async function updateTargetConfiguration(config) {
target = Object.assign(target, { InputTransformer: inputTransformer });
}

const client = new EventBridgeClient({ region });

return removeTargetConfiguration(config).then(() =>
awsRequest({ name: 'EventBridge', params: { region } }, 'putTargets', {
Rule: ruleName,
EventBusName,
Targets: [target],
})
awsRequest(() =>
client.send(
new PutTargetsCommand({
Rule: ruleName,
EventBusName,
Targets: [target],
})
)
)
);
}

Expand All @@ -89,11 +112,16 @@ async function removeTargetConfiguration(config) {

const EventBusName = getEventBusName(eventBus);

return awsRequest({ name: 'EventBridge', params: { region } }, 'removeTargets', {
Ids: [getEventBusTargetId(ruleName)],
Rule: ruleName,
EventBusName,
});
const client = new EventBridgeClient({ region });
return awsRequest(() =>
client.send(
new RemoveTargetsCommand({
Ids: [getEventBusTargetId(ruleName)],
Rule: ruleName,
EventBusName,
})
)
);
}

module.exports = {
Expand Down

0 comments on commit b30da10

Please sign in to comment.