使用AWS Cloudformation创建SNS平台应用程序?

时间:2017-10-03 13:30:46

标签: amazon-web-services amazon-cloudformation

是否可以使用Cloudformation模板创建SNS平台应用程序?

支持aws-clihttp://docs.aws.amazon.com/cli/latest/reference/sns/create-platform-application.html。但是没有关于对Cloudformation做同样的事情的信息,它是否得到支持(http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-topic.html)?

2 个答案:

答案 0 :(得分:3)

即可。在AWS中使用CloudFormation创建SNS平台应用程序

我面临同样的问题。在AWS Could Formation docs中,今天只有AWS::SNS::SubscriptionAWS::SNS::TopicAWS::SNS::TopicPolicy。它们都不允许定义平台应用程序。

除非可以在另一个AWS::服务下声明它,否则今天不可能。希望很快就能有这个功能。

解决方案

•由于创建/更新应用程序端点是一个罕见的“事件”,每年一次,我将手动:(创建它们。

awscliaws-sdk似乎支持平台应用程序的创建,但它会增加额外的依赖性或开发

答案 1 :(得分:0)

值得添加一些额外的工作来获得自动化和可重复性的好处。

我使用 AWS::CloudFormation::CustomResource 和 Lambda 函数来完成这项工作。

将此添加到您的 CloudFormation 定义中。

"MyPlatformApplication": {
    Type: "AWS::CloudFormation::CustomResource",
    DependsOn: [ "PlatformApplicationProvisionLambdaFunction" ],
    Properties: {
        ServiceToken: { "Fn::GetAtt", "PlatformApplicationProvisionLambdaFunction.Arn" },
        Name: "MyPlatformApplication",
        Platform: "GCM",
        PlatformCredential: "<Your FCM ServerKey>",
    },
},

并使用您的首选策略定义 Lambda 函数 PlatformApplicationProvisionLambdaFunction。对我来说,我使用无服务器框架,因此我可以将上述自定义资源与 Lambda 函数放在同一个存储库中,并一次性部署所有这些资源。

这是 Typescript 中的 Lambda 代码

import {
    CreatePlatformApplicationCommand,
    DeletePlatformApplicationCommand,
    SetPlatformApplicationAttributesCommand,
    SNSClient,
} from '@aws-sdk/client-sns';
import {
    CloudFormationCustomResourceCreateEvent,
    CloudFormationCustomResourceDeleteEvent,
    CloudFormationCustomResourceEvent,
    CloudFormationCustomResourceUpdateEvent,
    Context,
} from 'aws-lambda';
import response from 'cfn-response';
import middy from '@middy/core';
import middyJsonBodyParser from '@middy/http-json-body-parser';

const snsClient = new SNSClient({});

const parseInput = (event: CloudFormationCustomResourceEvent) => {
    const input = {
        Name: event.ResourceProperties.Name,
        Platform: event.ResourceProperties.Platform,
        PlatformCredential: event.ResourceProperties.PlatformCredential,
    };
    if (input.Name === undefined) {
        throw new Error('Missing parameter: Name');
    }
    if (input.Platform === undefined) {
        throw new Error('Missing parameter: Platform');
    }
    if (input.PlatformCredential === undefined) {
        throw new Error('Missing parameter: PlatformCredential');
    }
    return input;
};

const processCreate = async (event: CloudFormationCustomResourceCreateEvent, context: Context) => {
    const input = parseInput(event);
    const result = await snsClient.send(
        new CreatePlatformApplicationCommand({
            Name: input.Name,
            Platform: input.Platform,
            Attributes: {
                PlatformCredential: input.PlatformCredential,
            },
        }),
    );

    response.send(event, context, 'SUCCESS', {
        Arn: result.PlatformApplicationArn,
    });
};

const processUpdate = async (event: CloudFormationCustomResourceUpdateEvent, context: Context) => {
    const input = parseInput(event);
    const arn = `arn:aws:sns:${process.env.REGION}:${process.env.ACCOUNT_ID}:app/${input.Platform}/${input.Name}`;
    await snsClient.send(
        new SetPlatformApplicationAttributesCommand({
            PlatformApplicationArn: arn,
            Attributes: {
                PlatformCredential: input.PlatformCredential,
            },
        }),
    );
    response.send(event, context, 'SUCCESS', {
        Arn: arn,
    });
};

const processDelete = async (event: CloudFormationCustomResourceDeleteEvent, context: Context) => {
    const input = parseInput(event);
    const arn = `arn:aws:sns:${process.env.REGION}:${process.env.ACCOUNT_ID}:app/${input.Platform}/${input.Name}`;
    await snsClient.send(
        new DeletePlatformApplicationCommand({
            PlatformApplicationArn: arn,
        }),
    );
    response.send(event, context, 'SUCCESS', {
        Arn: arn,
    });
};

const handler = async (event: CloudFormationCustomResourceEvent, context: Context) => {

    try {
        if (event.RequestType === 'Create') {
            await processCreate(event, context);
        } else if (event.RequestType === 'Update') {
            await processUpdate(event, context);
        } else {
            await processDelete(event, context);
        }
    } catch (err) {
        if (err instanceof Error) {
            response.send(event, context, 'FAILED', { message: err.message });
        } else {
            response.send(event, context, 'FAILED', err);
        }
    }
};

export const main = middy(handler).use(middyJsonBodyParser());