0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AWS CodeStarで作成したAlexa SkillをDynamoDBにつなげてみる

Last updated at Posted at 2023-07-08

はじめに

先日、個人開発で作った Alexa Skill をリリースしました!

開発の中でAWS CodeStarによるAlexa Skillプロジェクトの作成を検討しました。
本記事は、その時のメモになります。

AWS CodeStarを使ったAlexa Skill開発

AWS CodeStarとは

AWS CodeStarは、ボイラープレートによるプロジェクトの立ち上げから、コードの構成管理、CI/CDも含めた開発環境までを簡単に構築してくれるツールです。
サービス名にCodeと付いていることもあり、AWSのCode3兄弟(CodeCommit, CodeDeploy, CodePipeline)を組み合わせてCI/CD環境に自動作成してくれるというのが売りです。

AWS CodeStarによるAlexa Skillの作成

CodeStarのコンソール画面にて「プロジェクトの作成」をクリックすると、テンプレートでAlexa Skillのハローワールドスキルが表示されます。これを選択して、指示に従っていけばNode.jsベースのAlexa Skillプロジェクトを立ち上げられます。

  • ソースコード管理はCodeCommitもGithubも選択可能
  • Alexa Developer Consoleとの連携もGUI上で対応
  • Alexa Developer Console上にhello nodeというスキルが作成される
  • 作成と同時にCloudformationが走るのを確認。プロビジョニングにかなり時間がかかった。
  • CodePipelineが作られていることも確認できる

Tips

  • 最初はAlexa Developer Console上でテストを実行できなかった。
    => スキルの状態を「開発中」に変更すれば、実行可能になった。
  • 公式ドキュメントより、CodeStarプロジェクトの「アプリケーションの表示」ボタンからAlexa Simulatorを起動できるらしい
  1. AWS CodeStar コンソールのプロジェクトで、[アプリケーションを表示] を選択します。Alexa Simulator で新しいタブが開きます
  2. ステップ 1 でプロジェクトに接続したアカウントの Amazon 開発者認証情報を使用してサインインします。
  3. [Test] (テスト) の下で [Development] (開発) を選択してテストを有効にします。

=> 実際にはシミュレータは起動せず、スキルが実装されているLambdaが表示された

いろいろ調べたが、Alexa Developer Consoleのシミュレータが表示する方法は分からなかった。

  • hello nodeというスキル名は、skill.jsonとja-JP.jsonを編集すれば変更できた
  • masterブランチへのマージをトリガーにして、デプロイが実行される

DynamoDBとの接続

ローンチしたサービスでは、DynamoDBからデータを読み込む必要があったので、DynamoDBとの接続方法を試しました。
デプロイされるインフラ設定は、Cloudformationテンプレートとしてtemplate.ymlに記載されています。
ここに記載されているLambdaのIAMポリシーに、DynamoDBへのアクセスを許可する記述を追記。

      ManagedPolicyArns:
        - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      PermissionsBoundary: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/CodeStar_${ProjectId}_PermissionsBoundary"
      Policies:
        - PolicyName: "DndbTableAccessPolicy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "dynamodb:Get*"
                  - "dynamodb:Query"
                  - "dynamodb:Scan"
                Resource:
                  - "Fn::Join":
                      - ":"
                      - - "arn:aws:dynamodb"
                        - Ref: AWS::Region
                        - Ref: AWS::AccountId
                        - "table/MyDndbTable-dev"
                  - "Fn::Join":
                      - ":"
                      - - "arn:aws:dynamodb"
                        - Ref: AWS::Region
                        - Ref: AWS::AccountId
                        - "table/MyDndbTable-dev/index/*"

しかし、これだけだとアクセスに失敗します。

INFO	Failed to query events;  AccessDeniedException: User: arn:aws:sts::xxxxxxxx:assumed-role/CodeStar-alx-cdstar-test-Execution/awscodestar-alx-cdstar-test-lambda-CustomDefaultFunction is not authorized to perform: dynamodb:Query on resource: arn:aws:dynamodb:ap-northeast-1:xxxxxxxxxx:table/MyDndbTable-dev/index/GSI1 because no permissions boundary allows the dynamodb:Query action
    at Request.extractError (/var/task/node_modules/aws-sdk/lib/protocol/json.js:52:27)
    at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:686:14)
    at Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /var/task/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:688:12)
    at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
  code: 'AccessDeniedException',
  time: 2023-01-30T13:16:51.933Z,
  requestId: 'KN8JIRSGDFKNVKJORPN5KM0T6FVV4KQNSO5AEMVJF66Q9ASUAAJG',
  statusCode: 400,
  retryable: false,
  retryDelay: 18.96747783566036
}

Troubleshooting

原因はLambdaのIAMロールについていた~PermissionsBoundaryという記述。

Permissions Boundaryとはサービスに許可するアクセスに事前に範囲(ロールの境界)を指定できるIAMの機能です。つまり、サービスに紐づけるIAMロール自体に制限を設ける機能です。

このPermissionsBoundaryの記述をtemplate.ymlからコメントアウトしてみましたが、その場合はデプロイができなくなりました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Action": [
                "*"
            ],
            "Resource": [
                "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/awscodestar-alx-cdstar-test-*",
                "arn:aws:codebuild:ap-northeast-1:xxxxxxxxxxxx:project/alx-cdstar-test",
                "arn:aws:codecommit:ap-northeast-1:xxxxxxxxxxxx:alexa-codestar-test",
                "arn:aws:codedeploy:ap-northeast-1:xxxxxxxxxxxx:application:alx-cdstar-test",
                "arn:aws:codedeploy:ap-northeast-1:xxxxxxxxxxxx:deploymentgroup:alx-cdstar-test/*",
                "arn:aws:codepipeline:ap-northeast-1:xxxxxxxxxxxx:alx-cdstar-test-Pipeline",
                "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:awscodestar-alx-cdstar-test-lambda-CustomDefaultFunction",
                "arn:aws:s3:::aws-codestar-ap-northeast-1-xxxxxxxxxxxx-alx-cdstar-test-pipe",
                "arn:aws:s3:::aws-codestar-ap-northeast-1-xxxxxxxxxxxx-alx-cdstar-test-pipe/*",
                "arn:aws:dynamodb:ap-northeast-1:xxxxxxxxxxxx:table/*" // <= 追記★
            ]
        },

そこで上記のように、IAMコンソールからPermissionsBoundaryとして指定されているポリシーにDynamoDBへのアクセスを許可する記述を追記すれば、アクセスできるようになります。

あと、こちらはケアレスミスですが、
最初、IAMポリシー上でのDynamoDBのリソースの記載を以下のように書いてました。

Resource:
    - "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/MyDndbTable-dev"
    - "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/MyDndbTable-dev/index/*"

Serverless Frameworkの場合はこれで通る気がしたのですが、純粋なAWS Cloudformation templateではダメでした。

The policy failed legacy parsing (Service: AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument; Request ID: 0daa4c1a-e614-4550-8a61-696a02a6b73c; Proxy: null)

既に書いたように、Fn::JoinとRefの組み込み関数を使って書いて解決しました。

Alexa Hosted Skillとは異なり、自身のAWSアカウントでAlexa Skillをホスティングすることになるので、上記の設定でDynamoDBからデータを読み込めるようになります。

まとめ

AWS CodeStarを使ってみましたが、小規模な開発で、AWS内でCI/CDを完結させたいなら、利用してみるのもいいかもしれません。

私は、Github Actionsを使いたかったことや、便利な反面、開発の自由度が下がってしまうこと、今回のように全ての設定をプロジェクト内のコード上に記述できない点などを危惧して、今回はCodeStarは使わずにサービスをローンチしました。

しかし、Alexa Skillプロジェクトには、skill.jsonやask-states.jsonといったスキルのステータスを保持するファイルがあり、これにAWSアカウントが記載されてしまいます。
パブリックなレポジトリの場合、AWSアカウントがさらされてしまうので、これらのファイルをGithubリポジトリに格納したくない方はいるでしょう。
その場合、CodeCommitの利用が選択肢に入ってきます。
そしてCodeCommitを使うなら、手軽にCodeCommit上のプロジェクトのセットアップができるCodeStarを検討してみるのがいいでしょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?