Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update AWS Lambda runtime to nodejs18.x #12311

Open
wants to merge 10 commits into
base: v2
Choose a base branch
from
2 changes: 1 addition & 1 deletion lib/plugins/aws/customResources/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,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,7 +82,7 @@ async function create(event, context) {
(policy) => policy.PolicyArn === apiGatewayPushToCloudWatchLogsPolicyArn
)
) {
await awsRequest('IAM', 'attachRolePolicy', {
const attachRoleCommand = new AttachRolePolicyCommand({
PolicyArn: apiGatewayPushToCloudWatchLogsPolicyArn,
RoleName: roleName,
});
Expand All @@ -78,7 +94,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 +103,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');

function getUpdateConfigFromCurrentSetup(currentSetup) {
const updatedConfig = Object.assign({}, currentSetup);
Expand Down Expand Up @@ -29,17 +35,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 @@ -54,12 +54,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 All @@ -83,12 +84,10 @@ async function updateConfiguration(config) {
UserPoolId,
LambdaConfig,
});
const cognitoIdentityProvider = new CognitoIdentityProviderClient({ region });
const updateUserPoolCommand = new UpdateUserPoolCommand(updatedConfig);

return awsRequest(
{ name: 'CognitoIdentityServiceProvider', params: { region } },
'updateUserPool',
updatedConfig
);
return awsRequest(() => cognitoIdentityProvider.send(updateUserPoolCommand));
});
}

Expand All @@ -109,12 +108,10 @@ async function removeConfiguration(config) {
UserPoolId,
LambdaConfig,
});
const client = new CognitoIdentityProviderClient({ region });
const updateUserPoolCommand = new UpdateUserPoolCommand(updatedConfig);

return awsRequest(
{ name: 'CognitoIdentityServiceProvider', params: { region } },
'updateUserPool',
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