mirror of
https://github.com/serverless/serverless.git
synced 2026-01-18 14:58:43 +00:00
123 lines
3.5 KiB
JavaScript
123 lines
3.5 KiB
JavaScript
'use strict';
|
|
|
|
const ApiGateway = require('aws-sdk/clients/apigateway');
|
|
const Iam = require('aws-sdk/clients/iam');
|
|
const { getEnvironment, handlerWrapper, wait } = require('../utils');
|
|
|
|
function handler(event, context) {
|
|
if (event.RequestType === 'Create') {
|
|
return create(event, context);
|
|
} else if (event.RequestType === 'Update') {
|
|
return update(event, context);
|
|
} else if (event.RequestType === 'Delete') {
|
|
return remove(event, context);
|
|
}
|
|
throw new Error(`Unhandled RequestType ${event.RequestType}`);
|
|
}
|
|
|
|
async function create(event, context) {
|
|
const { RoleArn } = event.ResourceProperties;
|
|
const { AccountId: accountId, Region: region } = getEnvironment(context);
|
|
|
|
const apiGateway = new ApiGateway({ region });
|
|
const assignedRoleArn = (await apiGateway.getAccount().promise()).cloudwatchRoleArn;
|
|
|
|
let roleArn = `arn:aws:iam::${accountId}:role/serverlessApiGatewayCloudWatchRole`;
|
|
if (RoleArn) {
|
|
// if there's a roleArn in the Resource Properties, just re-use it here
|
|
roleArn = RoleArn;
|
|
} else {
|
|
// Create an own API Gateway role if the roleArn was not set via Resource Properties
|
|
const apiGatewayPushToCloudWatchLogsPolicyArn =
|
|
'arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs';
|
|
|
|
const roleName = roleArn.slice(roleArn.lastIndexOf('/') + 1);
|
|
|
|
const iam = new Iam();
|
|
|
|
const attachedPolicies = await (async () => {
|
|
try {
|
|
return (await iam.listAttachedRolePolicies({ RoleName: roleName }).promise())
|
|
.AttachedPolicies;
|
|
} catch (error) {
|
|
if (error.code === 'NoSuchEntity') {
|
|
// Role doesn't exist yet, create;
|
|
await iam
|
|
.createRole({
|
|
AssumeRolePolicyDocument: JSON.stringify({
|
|
Version: '2012-10-17',
|
|
Statement: [
|
|
{
|
|
Effect: 'Allow',
|
|
Principal: {
|
|
Service: ['apigateway.amazonaws.com'],
|
|
},
|
|
Action: ['sts:AssumeRole'],
|
|
},
|
|
],
|
|
}),
|
|
Path: '/',
|
|
RoleName: roleName,
|
|
})
|
|
.promise();
|
|
return [];
|
|
}
|
|
throw error;
|
|
}
|
|
})();
|
|
|
|
if (
|
|
!attachedPolicies.some(policy => policy.PolicyArn === apiGatewayPushToCloudWatchLogsPolicyArn)
|
|
) {
|
|
await iam
|
|
.attachRolePolicy({
|
|
PolicyArn: apiGatewayPushToCloudWatchLogsPolicyArn,
|
|
RoleName: roleName,
|
|
})
|
|
.promise();
|
|
}
|
|
}
|
|
|
|
// there's nothing to do if the role is the same
|
|
if (roleArn === assignedRoleArn) return null;
|
|
|
|
const updateAccount = async (counter = 1) => {
|
|
try {
|
|
await apiGateway
|
|
.updateAccount({
|
|
patchOperations: [
|
|
{
|
|
op: 'replace',
|
|
path: '/cloudwatchRoleArn',
|
|
value: roleArn,
|
|
},
|
|
],
|
|
})
|
|
.promise();
|
|
} catch (error) {
|
|
if (counter < 10) {
|
|
// Observed fails with errors marked as non-retryable. Still they're outcome of
|
|
// temporary state where just created AWS role is not being ready for use (yet)
|
|
await wait(10000);
|
|
return updateAccount(++counter);
|
|
}
|
|
throw error;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
return updateAccount();
|
|
}
|
|
|
|
function update() {
|
|
// No actions
|
|
}
|
|
|
|
function remove() {
|
|
// No actions
|
|
}
|
|
|
|
module.exports = {
|
|
handler: handlerWrapper(handler, 'CustomResourceApiGatewayAccountCloudWatchRole'),
|
|
};
|