Amazon Web Services ブログ

AWS Serverless Application Repository のコンポーネントを使用したサーバーレスアプリの構築

AWS サーバーレスヒーローである Aleksandar Simovic 氏によるゲスト投稿。Aleksandar は、Science Exchange のシニアソフトウェアエンジニアであり、Manning Publications から出版されている Slobodan Stojanovic 氏との「Serverless Applications with Node.js」の共著者です。また、彼はサーバーレスのビジネス面と技術面の両方についてもメディアに寄稿しています。

皆さんの多くは、ユーザーログインまたは認証サービスを一から構築したご経験をお持ちではないでしょうか。そして、おそらく、支払いを処理するサービスや、PDF をエクスポートする別のサービスも何度も構築してきたことでしょう。私たちは皆それを経験しており、多くの場合、何度も行ってきました。AWS Serverless Application Repository を使用すると、より多くの時間とエネルギーをビジネスロジックの開発に費やし、顧客にとって重要な機能をより迅速に提供することができるようになります。

AWS Serverless Application Repository とは?

AWS Serverless Application Repository を使用すると、開発者はチームや組織の間で共通のサーバーレスコンポーネントをデプロイ、公開、共有できます。パブリックライブラリには、カスタマイズ可能なパラメータと事前に定義されたライセンスで即座に検索とデプロイが可能な、コミュニティで構築されたオープンソースのサーバーレスコンポーネントが含まれています。これらは、AWS リソースのテンプレート化に使用されるコードとしてのインフラストラクチャである AWS サーバーレスアプリケーションモデル (AWS SAM)、YAML 言語を使用して構築および公開されています。

本稼働環境で AWS Serverless Application Repository を使用する方法

顧客が製品を選択して代金を払えるようにするアプリケーションを構築したいと考えています。相当な労力のようですね。 AWS Serverless Application Repository を使用すると、実際にはそれほど時間がかかりませんでした。

大まかに言って、以下を作りました。

  • 自動的に Stripe Checkout SDK に関連付けられている [Buy] ボタンがある商品ページ。顧客が [Buy] を選択すると、ページに Stripe Checkout 支払いフォームが表示されます。
  • Stripe からのコールバックを受け入れ、顧客に請求し、取引が成功したことを通知する API エンドポイントを持つ Stripe 支払いサービス。

この記事では、製品の詳細を表示し、そのページに Stripe Checkout JavaScript がある、事前構築済みの静的サンプルページを作成しました。

構築済みのページでも、支払いサービスの統合はまだうまくいきます。しかし、他にも多くの開発者が少なくとも 1 回は支払いアプリケーションを作成しているのに、なぜ同じ機能を作成するのに時間を費やす必要があるでしょうか? これが、AWS Serverless Application Repository が便利であるところです。

コンポーネントを見つけてデプロイする

まず、AWS Serverless Application Repository パブリックライブラリで既存のコンポーネントを検索しました。「stripe」と入力し、カスタム IAM ロールまたはリソースポリシーを作成したアプリケーションを表示することにしました。以下の結果が表示されました:

api-lambda-stripe-charge というアプリケーションを選択し、コンポーネントの詳細ページで [Deploy] を選択しました。

コンポーネントをデプロイする前に、それが安全で本稼働の準備が整っていることを確認するためにコンポーネントを調べました。

コンポーネントを評価する

AWS Serverless Application Repository コンポーネントを評価するための推奨されるアプローチは、次の 4 段階のプロセスです。

  1. コンポーネントのアクセス許可を確認する。
  2. コンポーネントの実装を調べる。
  3. 制限された環境でコンポーネントをデプロイして実行する。
  4. 本稼働環境で使用する前に、コンポーネントの動作とコストを監視する。

これは AWS Serverless Application Repository の短納期のメリットを無効にするように思われるかもしれませんが、実際には、各コンポーネントを一度だけ検証します。そうすると、コンポーネントを会社全体で簡単に再利用、共有することができます。

Stripe コンポーネントを追加しながらこのアプローチを適用する方法は次のとおりです。

1.コンポーネントのアクセス許可を確認する

コンポーネントには、パブリックとプライベートの 2 種類があります。パブリックコンポーネントはオープンソースですが、プライベートコンポーネントは必ずしもそうではありません。この場合、Stripe コンポーネントはパブリックです。コードを見直して、セキュリティを危険にさらす可能性がある不要なアクセス許可が与えられていないことを確認しました。

この場合、Stripe コンポーネントは GitHub にあります。コンポーネントページで、template.yaml ファイルを開きました。そこには AWS Lambda 関数は 1 つしかなかったので、Policies 属性を見つけて、それが使用するポリシーを確認しました。

  CreateStripeCharge:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs8.10
      Timeout: 10
      Policies:
        - SNSCrudPolicy:
          TopicName: !GetAtt SNSTopic.TopicName
        - Statement:
          Effect: Allow
          Action:
            - ssm:GetParameters
          Resource: !Sub
arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${SSMParameterPrefix}/*

コンポーネントは、事前定義済みの AWS SAM ポリシーテンプレートとカスタムのテンプレートを使用していました。これらの事前定義済みポリシーテンプレートは、AWS セキュリティチームによって検証および推奨されている一連の AWS アクセス許可です。これらのポリシーを使用してリソースに対するアクセス許可を指定することは、AWS Serverless Application Repository のサーバーレスコンポーネントに推奨される方法の 1 つです。他のカスタム IAM ポリシーを使用すると、この機能で AWS System Manager のパラメータを取得できます。これは、Stripe シークレットキーなどの保護される値を保存するためのベストプラクティスです。

2.コンポーネントの実装を調べる

コンポーネントの主要なビジネスロジックが、意図していることだけを実行するようにしたいと考えました。それは、Stripe charge を作成することでした。また、リークを防ぐために、未知のサードパーティの HTTP 呼び出しを探すことも重要です。そこで、このプロジェクトの依存関係を見直しました。この検査には PureSec を使用しましたが、Protego が提供しているようなツールも別の選択肢です。

主要なビジネスロジックは charge-customer.js ファイルにありました。それは、単に Stripe create charge を呼び出してから作成された charge で通知を発行するという単純なロジックを明らかにしました。これが次のコードに反映されているのが分かります。

return paymentProcessor.createCharge(token, amount, currency, description)
    .then(chargeResponse => {
      createdCharge = chargeResponse;
      return pubsub.publish(createdCharge, TOPIC_ARN);
    })
    .then(() => createdCharge)
    .catch((err) => {
      console.log(err);
      throw err;
    });

paymentProcessor および pubsub の値は、それぞれ Stripe および Amazon SNS との通信用のアダプターです。いつもそれらがどのように機能するかを見るのが好きです。

3.制限された環境でコンポーネントをデプロイして実行する

サーバーレスアプリケーションをテストするための制限付き AWS アカウントを別に維持することは、サーバーレス開発のベストプラクティスです。私は、自分のテストアカウントに厳密な AWS 請求と Amazon CloudWatch のアラームが設定されていることを常に確認しています。

この別のアカウントにサインインし、Stripe コンポーネントのページを開いて手動でデプロイしました。デプロイした後、実行方法を確認する必要がありました。このコンポーネントには Lambda 関数が 1 つしかないため、Lambda コンソールでその関数を探し、コードを確認できるようにその詳細ページを開きました。

4.本稼働環境でコンポーネントを使用する前に、動作とコストを監視する

テストアカウントですべてが期待どおりに機能する場合は、通常、インシデントの診断とコンポーネントのパフォーマンスの評価に役立つように、コンポーネントに監視ツールとパフォーマンスツールを追加します。私はこのためによく Epsagon と Lumigo を使いますが、それらの手順を追加するとこの記事が長くなりすぎるでしょう。

また、コンポーネントのコストも追跡したいと考えました。これを行うために、コンポーネントのコストとその中の各 AWS リソースのコストを追跡する厳密な請求アラームを追加しました。

コンポーネントがこれら 4 つのテストに合格した後、既存の製品選択アプリケーションに追加することによってそれをデプロイする準備ができました。

コンポーネントを既存のアプリケーションにデプロイする

Stripe コンポーネントを既存のアプリケーションに追加するために、コンポーネントの [Review, Configure, and Deploy] ページを再度開き、[Copy as SAM Resource] を選択しました。それにより、必要なテンプレートコードをクリップボードにコピーしました。次に、[Resources] の下にある既存の AWS SAM テンプレートに貼り付けて、既存のサーバーレスアプリケーションに追加しました。これは、以下のようになります。

Resources:
  ShowProduct:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs8.10
      Timeout: 10
      Events:
        Api:
          Type: Api
          Properties:
            Path: /product/:productId
            Method: GET
  apilambdastripecharge:
    Type: AWS::Serverless::Application
    Properties:
      Location:
        ApplicationId: arn:aws:serverlessrepo:us-east-1:375983427419:applications/api-lambda-stripe-charge
        SemanticVersion: 3.0.0
      Parameters:
        # (オプション) クロスオリジンリソースシェア (CORS) オリジン。単一のオリジン、すべてのオリジンを「*」で指定するか、空のままにして CORS を適用しないようにすることができます。
        CorsOrigin: YOUR_VALUE
        # このコンポーネントは、Stripe Charge API を使用するために必要な Stripe シークレットキーが、このパラメータで定義されるプレフィックスの下で、SecureStrings として Parameter Store に保存されていることを前提としています。コンポーネントの README を参照してください。
       # SSMParameterPrefix: lambda-stripe-charge # Uncomment to override the default value
Outputs:
  ApiUrl:
    Value: !Sub https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Stage/product/123
    Description: The URL of the sample API Gateway

AWS::Serverless::Application AWS SAM リソースをコピーして貼り付けました。これは、ApplicationId とその SemanticVersion によってコンポーネントを指しています。次に、コンポーネントのパラメータを定義しました。

  • デモ用に、CorsOrigin を「*」に設定しました。
  • デフォルト値を採用するため、SSMParameterPrefix の値は設定する必要はありませんでした。ただし、次のコマンドを実行して、Systems Manager Parameter Store で Stripe シークレットキーを設定しました。

aws ssm put-parameter --name lambda-stripe-charge/stripe-secret-key --value --type SecureString --overwrite

パラメータに加えて、コンポーネントは出力も含みます。出力は、他のアプリケーションまたはコンポーネントとともに使用できる外部化されたコンポーネントリソースまたは値です。たとえば、api-lambda-stripe-charge コンポーネントの出力は、Amazon SNS トピックの SNSTopic です。これにより、支払いが成功したときに通知を受け取る別のコンポーネントまたはビジネスロジックをアタッチすることができます。たとえば、支払いが成功したときに E メールを送信する lambda-send-email-ses コンポーネントをアタッチすることもできます。

最後に、次の 2 つのコマンドを実行しました。

aws cloudformation package --template-file template.yaml --output-template-file output.yaml --s3-bucket YOUR_BUCKET_NAME

aws cloudformation deploy --template-file output.yaml --stack-name product-show-n-pay --capabilities CAPABILITY_IAM

2 番目のコマンドでは、必要に応じてパラメータの上書きを追加することができます。

これで、製品選択および支払いアプリケーションが正常にデプロイされました!

まとめ

AWS Serverless Application Repository を使用すると、共通のコンポーネント、サービス、アプリケーションを共有および再利用することができるため、コアビジネス価値の構築に専念できます。

いくつかの手順で、顧客が製品を選択して支払いを行えるアプリケーションを作成しました。数時間ではなく、数分で済みました! コンポーネントを慎重に分析して確認するのにそれほど時間はかかりません。コンポーネントを会社の他のチームと共有することができるので、無駄を排除することもできます。

これで、AWS Serverless Application Repository を使用して、チームが製品を開発し、機能を提供し、本稼働対応のアプリケーションを構築して共有する方法を加速する準備が整いました。