以下に示すステップバイステップの手順に従い、サーバーレスバックエンドを構築します。各ステップの番号をクリックして、セクションを展開してください。

  • ステップ 1:カスタム IAM ロールの IAM ポリシーを作成する

    ウェブサイトのバックエンドリクエストを処理するために Lambda の権限を付与するには、AWS のサービスに次のアクションを実行できる権限を付与するカスタム IAM ポリシーを作成します。

    • AppStream 2.0 がイメージのアクセス許可を更新して事前設定済みイメージを共有します。
    • Amazon SES では、サインアップしてイメージへのアクセス権を受け取る際に、お客様に E メールが送信されます。
    • Amazon CloudWatch のログ記録が有効になります。
       

    カスタム IAM ポリシーを作成するには、次の手順を実行します。
    1.IAM コンソールを https://console.aws.amazon.com/iam/ で開きます。
    2.ナビゲーションペインで、[ Policies] を選択します。
    3.[ Policies] を初めて選択した場合、[ Welcome to Managed Policies] ページが表示されます。[ Get Started] を選択します。
    4.[ Create policy] を選択します。
    5.[ JSON] タブを選択します。
    6.次の JSON ポリシーをコピーして、ポリシードキュメントのフィールドに貼り付けます。
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": "appstream:UpdateImagePermissions",
                "Resource": "arn:aws:appstream:REGION-CODE:ACCOUNT-ID-WITHOUT-HYPHENS:image/IMAGE-NAME"
            },
            {
                "Effect": "Allow",
                "Action": "ses:SendEmail",
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                ],
                "Resource": "*"
            }
        ]
    }

    7.以下の変数を独自の値に置き換えます。

    • REGION-CODE
    • ACCOUNT-ID-WITHOUT-HYPHENS
    • IMAGE-NAME

    各パラメータの意味は次のとおりです。

    • REGION-CODE は、AppStream 2.0 イメージが存在する AWS リージョンです。
    • ACCOUNT-ID-WITHOUT-HYPHENS は、12 桁の AWS アカウント ID です。
    • IMAGE-NAME は、イメージの名前です。

    8.完了したら、[Get Started] をクリックします。 

    9.[Name] には、新しいポリシーの名前として「examplecorp_lambda_si_policy」と入力します。

    10.[Create policy] を選択します。

  • ステップ 2:IAM サービスロールを作成し、Lambda 関数で AWS のサービスを呼び出せるようにする

    Lambda がユーザーに代わって他のサービスのリソースにアクセスできるようにするには、IAM サービスロールが必要です。次の手順を実行して IAM サービスロールを作成し、作成したポリシーをこのロールにアタッチします。

    1.IAM コンソールを https://console.aws.amazon.com/iam/ で開きます。
    2.ナビゲーションペインで [Roles] をクリックしてから [Create role] をクリックします。
    3.[Select type of trusted entity] では、[AWS service] を選択したままにします。
    4.[Lambda] を選択してから [Next: Permissions] をクリックします。
    5.[Filter policies] 検索ボックスに、「examplecorp_lambda_si_policy」と入力します。該当するポリシーがリストに表示されたら、ポリシー名の横のチェックボックスをオンにします。
    6.[Next:Tags] をクリックします。ここではポリシーのタグを指定できますが、この例では不要です。
    7.[Next: Review] を選択します。
    8.[Role name] に「examplecorp_lambda_si_role」と入力します。
    9.[Create role] を選択します。

  • ステップ 3:Lambda 関数を作成および設定する

    以下の手順を実行して Lambda 関数を作成します。

    1.Lambda コンソールを https://console.aws.amazon.com/lambda/ で開きます。
    2.以下のいずれかを行います。
        • 初めて Lambda 関数を作成する場合、[Getting Started] ページが表示されます。[Getting Started] の [Create a function] をクリックします。
        • Lambda 関数を作成したことがある場合、[Functions] ページの右上隅にある [Create a function] をクリックします。
    3.[Create a function] ページでは、[Author from scratch] が選択されていることを確認します。
    4.[Basic information] で以下を実行します。
        • [Name] には「examplecorp_lambda_si_function」と入力します。
        • [Runtime] で [Node.js 8.10] を選択します。
    5.[Permissions] で、[Choose or create an execution role] の横のアイコンをクリックします。次に、以下を実行します。
        • [Execution role] で [Use an existing role] を選択します。
        • [Existing role] で、リストから [examplecorp_lambda_si_role] を選択します。
    6.[Create function] を選択します。
    7.[Function code] セクションの [index.js] タブに、プレースホルダーコードが表示されます。プレースホルダーコードを削除し、次のコードをコピーしてタブに貼り付けます。

    // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
    // SPDX-License-Identifier: Apache-2.0
    
    const AWS = require('aws-sdk');
    const appstream = new AWS.AppStream;
    const ses = new AWS.SES();
    
    exports.handler = (event, context, callback) => { //Event should contain the Name, Email and AWS Account ID
    
        var eventdata = JSON.parse(event.body); //Parses the JSON from the event body 
        var params = {
            ImagePermissions: { /* required */
                allowFleet: true, //Boolean
                allowImageBuilder: true //Boolean
            },
            Name: '<IMAGE_NAME>', /* required */
            SharedAccountId: eventdata.account //AWS Account ID parsed from the JSON body
        };
    
        shareas2image(params, eventdata, context.awsRequestId, callback); //Share image function call
    
    };
    
    function errorResponse(errorMessage, awsRequestId, callback) { //Function for handling error messaging back to client 
        callback(null, {
            statusCode: 500,
            body: JSON.stringify({
                Error: errorMessage, 
                Reference: awsRequestId,
            }),
            headers: {
                'Access-Control-Allow-Origin': '<origin-domain>', //This should be the domain of the website that originated the request, example: amazonaws.com
            },
        });
    }
    
    function shareas2image(params, eventdata, awsRequestId, callback) {
        var request = appstream.updateImagePermissions(params);
        request.
            on('success', function (response) {
                console.log("Success. " + JSON.stringify(response.data));
                sendEmail(eventdata);
                callback(null, {
                    statusCode: 201,
                    body: JSON.stringify({
                        Message: "Success",
                        Reference: awsRequestId,
                    }),
                    headers: {
                        'Access-Control-Allow-Origin': '<origin-domain>', //This should be the domain of the website that originated the request, example: amazonaws.com
                    },
                });
            }).
            on('error', function (response) {
                console.log("error: " + JSON.stringify(response.message));
                errorResponse('Error sharing AS2 Image.', awsRequestId, callback);
    
            }).
            send();
    
    
    }
    
    function sendEmail(data) {
        var sender = "<sender@example.com>"; //Sender needs to be a verified address in SES
        var receiver = data.email.trim(); /*Trim the string of any preceding and trialing whitespaces*/
        var name = data.name.trim();
        var params = {
            Destination: {
                ToAddresses: [receiver]
            },
            Message: {
                Body: {
                    Text: {
                        Data: 'Hello ' + name + ',' + '\n\nThank you for trying Example Corp\'s Application Suite. We have shared a preconfigured AppStream 2.0 image with all of Example Corp\'s applications to your AWS Account.',
                        Charset: 'UTF-8'
                    }
                },
                Subject: {
                    Data: 'Thank you for trying Example Corp ' + name,
                    Charset: 'UTF-8'
                }
            },
            Source: sender
        };
        console.log("Sending Email.");
        ses.sendEmail(params, function (err, data) {
            if (err) console.log(err, err.stack); // an error occurred
            else console.log(data);           // successful response
        });
    }

    重要

    この関数により、自動的に AppStream 2.0 イメージがエンドユーザーの指定した AWS アカウント ID と共有されます。この関数は、アカウントにイメージのアクセス許可を付与する前に AWS アカウント所有権を検証しません。ソリューションを本稼働にデプロイする際には、必要に応じて独自に検証を行うようにすることを推奨します。たとえば、エンドユーザーのアイデンティティまたは AWS アカウント所有権の検証です。

    8.以下の変数を独自の値に置き換えます。

    • <Image-Name>
    • <origin-domain>
    • sender@example.com

    各パラメータの意味は次のとおりです。

    • <Image-Name> は、共有する AppStream 2.0 イメージの名前です。
    • <origin-domain> は、API ゲートウェイにリクエストを送るウェブサイトのドメインです。ここでは、このプロジェクト用に設定した S3 ウェブサイトのフル URL (http://bucket-name.s3-website.region.amazonaws.com) になります。
    • 送信者の E メールアドレスは、Amazon SES に追加した検証済みの E メールアドレスです。

     


    9.関数を保存して Lambda コンソールを閉じます。