ask cliからAlexa skillをdeployする

#はじめに
Alexaスキルを開発するときに、対話モデルの作成はAlexa Skills Kit開発者コンソールでビジュアルに作っていくのがとても便利でおすすめですが、AWS Lambdaに置くLambda関数のnode.jsのコーディングとなると、AWSの開発者コンソールではAlexaスキルのテンプレートもないため、何から手をつけたらよいのか途方に暮れてしまいます。

そこでAlexaスキルのコマンドライン開発環境をインストールしておくと、スキルの作成とクラウド上への配置を簡単に行うことができ、格段に開発しやすくなります。

#ask-cliの設定
##手順０：コマンドライン開発環境ask-cliのインストール
コマンドライン開発環境はask-cliというもので、これをインストールします。
インストール手順は公式の[こちらの手順](https://developer.amazon.com/ja/docs/smapi/quick-start-alexa-skills-kit-command-line-interface.html#step-3-install-and-initialize-ask-cli)のとおりです。

コマンドプロンプトから以下のようにバージョンを確認できればインストールは完了です。

```
> ask --version
1.4.4
```

##手順１：AWSでのユーザーの追加とIAMの設定
コンソールからAWS上にLambda関数を作成したり、それを更新したりするために権限（許可）を与える必要があり、その設定はAWS側でおこないます。
まずはAWSの開発者コンソールへサインインし、`IAM`へ移動してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/53e52a53-d758-5b70-6526-97777a73a1eb.png)

###ポリシーの作成
左ペインから「ポリシー」を選択し、続いて「ポリシーの作成」ボタンを押します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/43d6ab39-bd65-cc74-0f6f-19a2c857cf1e.png)

「ポリシーの作成」ページが開きます。
さて、ここではask-cliからのアクセスに対して与える権限をまとめて、それを`ポリシー`としてひとまとめにします。この`ポリシー`を、後ほど作成するask-cli専用のユーザーに付与します
（または、ユーザーグループに対してこのポリシーを付与して、ask-cli専用のユーザーをそのグループに所属させることでも同じ権限を与えることになります）。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/7ed99f82-d403-c7f5-f6ce-6fcc437cf436.png)

ポリシーの作成は、みてのとおり「ビジュアルエディタ」と「JSON」の2つの方法がありますが、ここは公式の[こちらのページ](https://developer.amazon.com/ja/docs/smapi/set-up-credentials-for-an-amazon-web-services-account.html)にあるJSONを使った作成方法をとることにします。
間違いないですからね。

JSONを観てみると、ask-cliからのawsの操作に必要な権限、ロールが書いてあります。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:CreateRole",
        "iam:GetRole",
        "iam:AttachRolePolicy",
        "iam:PassRole"
      ],
      "Resource": "arn:aws:iam::*:role/ask-*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "lambda:AddPermission",
        "lambda:CreateFunction",
        "lambda:GetFunction",
        "lambda:UpdateFunctionCode",
        "lambda:ListFunctions"
      ],
      "Resource": "arn:aws:lambda:*:*:function:ask-*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "logs:FilterLogEvents",
        "logs:getLogEvents",
        "logs:describeLogStreams"
      ],
      "Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/ask-*"
    }
  ]
}
```
これを以下のように貼り付けて、右下の「Review Policy」ボタンを押します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/bcd6434e-5bdc-b073-97ea-b5c37194a32d.png)


「ポリシーの確認」ページが表示されるので、ここでこのポリシーに含まれる権限を確認し、ポリシーの名前を付けたら右下の「Create Policy」ボタンを押すと、ポリシーの作成が完了します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/c71b4e52-50da-7fff-385e-eaf6e18aff9d.png)

ポリシーのフィルタ欄に先ほど作成したポリシー名の一部の入力し、作成したポリシーが一覧に表示されることを確認してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/8d4090b1-a7b3-a363-7cda-39919d8a72fe.png)



###ユーザーの追加
ポリシーを作成したら次はユーザーです。
左ペインから「ユーザー」を選択して、「ユーザーを追加」ボタンを押します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/11aeb9be-c987-baab-7e51-7a7669e15289.png)

ユーザー名を入力し、「プログラムによるアクセス」「AWSマネジメントコンソールへのアクセス」にチェックを付けます。
パスワードは自分で設定することもできますが、「自動生成」でよいでしょう。
「パスワードのリセットが必要」はよくわかりませんでした。とりあえずそのままでよいでしょう。
では右下の「次のステップ：アクセス権限」ボタンを押します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/184fea53-359c-af17-6251-8b417b952f72.png)


ユーザーに与える権限を選択します。
ここで先ほど作成したポリシーを使います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/fc933fd8-b5b7-920d-89dc-7f28f16c94d6.png)
権限の与え方は画像のとおり、3通りあります。

1. ユーザーをグループに追加する
2. 既存のユーザーのアクセス権限と同じものを与える
3. 既存のポリシーをユーザーに直接つける

1については上でも少し述べたとおりで、グループにつけたポリシーをユーザーに適用するものです。2、3はそのままの意味です。
今回は3の「既存のポリシーを直接アタッチ」を使います。

「既存のポリシーを直接アタッチ」を選択してポリシーを検索し、適用するポリシーにチェックをつけて右下の「次のステップ：確認」を押します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/8ba30dac-381e-e28e-a520-4f37d7d2d07f.png)

次に表示される確認画面でユーザーの設定内容を確認して右下の「ユーザーの作成」ボタンを押し、ユーザーの作成を完了します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/8bd77fd3-2e12-6a91-8769-633bf30a83c6.png)


ユーザーの作成が完了すると以下のようなユーザーについての認証情報が表示されます。
これはask-cliからアクセスするために必要な情報ですし、そもそも自分のAWSリソースに対する操作を許可したユーザー情報ですので、絶対に公開したり紛失したりしないでください。
CSVファイルをダウンロードして、厳重に保管してください。

![fajkdhfaksjfh.png](https://qiita-image-store.s3.amazonaws.com/0/245438/fa47f14e-d83d-1951-4a36-8375167e9aec.png)

以上でAWS側での作業は終了です。

###AWS側での作業まとめ
最初にポリシーを作り、ポリシーをユーザーに直接つけるか、グループにポリシーをつけて、そのグループにユーザーを所属させることで、ユーザーにポリシーを適用できる。


##手順２：ask-cliでawsの認証情報の設定
次はask-cliの設定作業になります。コマンドプロンプトで行います。

###ask-cliの初期設定
初期設定は`ask init`コマンドを使い、手順に従って行います。
コマンドプロンプトで`ask init`コマンドを入力すると、以下のように選択肢が表示されるので、カーソルキーで`default`を選び、`Enter`キーを押します。

```
> ask init
-------------------- Initialize CLI --------------------
Setting up ask profile: [default]
? Please choose one from the following AWS profiles for skill's Lambda function deployment.
 (Use arrow keys)
> default
  ──────────────
  Skip AWS credential for ask-cli.
  Use the AWS environment variables.
  ──────────────
```

何も設定されていない状態であれば、以下のように表示されると思います。

```
> ask init
-------------------- Initialize CLI --------------------
? There is no AWS credentials file found in .aws directory, do you want to set up the credenti
als right now? (for lambda function deployment)
> Yes. Set up the AWS credentials.
  No. Use the AWS environment variables.
  No. Skip AWS credentials association step.
  Abort the initialization process.
```

「`.aws`ディレクトリ内にAWS credentialsファイルがありません。ここでcredentialsをセットアップしますか（Lambda関数をデプロイするために）」
と訊かれるので、カーソルキーで「Yes. Set up the AWS credentials.」を選択します。

以下のようにアクセスキーとシークレットアクセスキーの入力を求められるので、AWSでユーザーを追加したときに発行されたものを入力します。

```
Please follow the instruction from https://developer.amazon.com/docs/smapi/set-up-credentials-for-an-amazon-web-services-account.html
Fill in the AWS Access Key ID and AWS Secret Access Key below. CLI will generate/modify the AWS credential file for you.
? AWS Access Key ID:
```

すると、コンソール上に以下のように表示され、ブラウザが開いてログインを求められます。
ブラウザ側ではAWS開発者アカウントでログインしてください。

```
Switch to 'Login with Amazon' page...
  |  Listening on http://localhost:9090
```

![oaijdfadfjlksdafj.png](https://qiita-image-store.s3.amazonaws.com/0/245438/f68e7e05-d485-441a-0c6c-60353c594c74.png)

ブラウザ側でログインすると以下のように表示され、認証が完了します。このページは閉じてしまってOKです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/4db97c4a-2e57-7742-6175-a15a522dd3cd.png)

コンソールのほうも以下のように表示されます。初期設定完了です。

```
Tokens fetched and recorded in ask-cli config.
Vendor ID set as **********（禁則事項）

Profile [default] initialized successfully.
```

ユーザーフォルダに`.ask`と`.aws`というフォルダが作成されています。
`ls`コマンドで確認できます。

```
> ls


    ディレクトリ: C:\Users\hoge


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2018/09/25     17:22                .android
d-----       2018/10/19     10:27                .ask
d-----       2018/10/19     10:31                .aws
d-----       2018/08/16     11:55                .azurefunctions
d-----       2018/10/04     14:53                .config
```
`.ask`フォルダの中には`cli_config`ファイルが、`.aws`フォルダの中には`credentials`ファイルができています。

`cli_config`ファイルの中はこんな感じです。

```:.ask/cli_config
{
  "profiles": {
    "default": {
      "aws_profile": "default",
      "token": {
        "access_token": "禁則事項",
        "refresh_token": "禁則事項",
        "token_type": "bearer",
        "expires_in": 3600,
        "expires_at": "2018-10-19T02:41:34.737Z"
      },
      "vendor_id": "禁則事項"
    }
  }
}
```

`credentials`ファイルの中身は以下のとおりです。
先ほど入力したアクセスキーとシークレットアクセスキーが入っていることが確認できます。

```:.aws/credentials
[default]
aws_access_key_id=禁則事項
aws_secret_access_key=禁則事項
```

#Skillの作成
`ask new`コマンドでスキルを作成できます。公式の説明は[こちら](https://developer.amazon.com/ja/docs/smapi/ask-cli-command-reference.html#new-command)。

`ask new`コマンドにはいろいろなオプションがあります。

テンプレートからスキルを作りたい場合は`ask new --template テンプレート名`とします。
テンプレート名は[こちら](https://s3.amazonaws.com/ask-cli/templates.json)。

スキル作成時にスキル名を設定することでができ、ここで設定したスキル名がフォルダ名として使われ、Alexa Skills Kit開発者コンソールで表示されるスキル名となります。

```
ask new --skill-name スキル名
```

**注意**：コマンドラインからはスキル名に日本語を使えませんでした。`-`になってしまいました。
後で好きなように変更したらいいと思いますので、英数字を使います。

AWS Lambdaに配置するLambda関数の名前も設定できます。
オプションとして`--lambda-name Lambda関数名`とします。
指定しない場合は、スキル名と各種設定から適当な文字列が作成され、それが使用されます。

それではやってみましょう。
スキル名を`MyFirstSkill`とし、Lambda関数名を`alexa-skill-MyFirstSkill`としました。

```
> ask new --skill-name MyFirstSkill --lambda-name alexa-skill-MyFirstSkill
```
これで、コマンドを実行したフォルダにスキル名のフォルダが作成されます。
このフォルダに対話モデルのデータと、Lambda関数のデータが入っています。
次に説明する`デプロイ`によって、対話モデルがAlexa音声サービスに、Lambda関数がAWS Lambda上に配置されるとともに、両者が結び付けられます。

#スキルのデプロイ
さて、このスキルのフォルダに移動して`ask deploy`コマンドと入力すると、このスキルを配置できます。
コマンドを実行して以下のように表示されればデプロイ成功です。

```
> ask deploy
-------------------- Create Skill Project --------------------
Profile for the deployment: [default]
Skill Id: 禁則事項
Skill deployment finished.
Model deployment finished.
Lambda deployment finished.
Lambda function(s) created:
  [Lambda ARN] 禁則事項
Your skill is now deployed and enabled in the development stage.
Try invoking the skill by saying “Alexa, open {your_skill_invocation_name}” or simulate an invocation via the `ask simulate` command.
```

##Alexa Skills Kit開発者コンソール側の確認
[Alexa Skills Kit開発者コンソール](https://developer.amazon.com/alexa/console/ask#/skill/create/)に移動してみましょう。
ビルドが正常に完了した旨のメッセージが表示されていて、「MyFirstSkill」がリストに入っています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/ae672649-b97a-8603-6320-1ce334025758.png)

しかし、言語が「英語（米国）」になっていますね。
日本語で動作しているAlexa端末でこのスキルを使うには「日本語」が含まれていなければなりません。
この言語の追加・削除はAlexa Skills Kit開発者コンソールからも行えるので[こちら](https://qiita.com/shuhey/items/295aa1448e5e64528bf8)の記事を参照してください。



##AWSコンソール側の確認
次に、[AWSコンソール](https://console.aws.amazon.com/console/)に移動してみましょう。
「Lambda」を検索するか、最近アクセスしたサービスなどから「AWS Lambda」へ移動します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/dd55b5e8-2cd9-ccfb-847b-3a2075de9ddd.png)

ここで関数の一覧を見ることができるのですが、先ほどデプロイしたはずのLambda関数が見当たりません。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/7ffe1683-289f-0ebd-8851-9615627b6935.png)
なぜかというと、Ask Cliを使ってコンソールからスキルをデプロイした場合、デフォルトでは「米国東部（バージニア北部）」リージョンにデプロイされるためです。
これはおそらくAWSのアカウント作成時の情報によって決まるのかなと思います。
ですので、人によってはAWSコンソールにログインしたときにデフォルトで「米国東部（バージニア北部）」リージョンになっていて、デプロイしたLambda関数が見えているかもしれません。

それでは、リージョンを「米国東部（バージニア北部）」に変更して確認してみましょう。
AWS Lambdaのページの右上にリージョンを選択するドロップダウンリストがあるのでそこから「米国東部（バージニア北部）」を選択します。
![kldjflkasjfda.png](https://qiita-image-store.s3.amazonaws.com/0/245438/9de66223-a696-4361-140a-43b2de3c1ee1.png)

すると、以下のように「米国東部（バージニア北部）」リージョンに配置されたLambda関数のリストが表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/c9a6a58b-c02f-e8a9-2d81-35417399554e.png)

Lambda関数が置かれているリージョンはどこであろうとAlexaスキルの実行には問題ありません。
特に問題なければこのままにしておきましょう。


もう一つ。
関数名がなんだかおかしいですね。
コマンドラインからスキルのプロジェクトを作成するときにオプションでLambda関数名を`alexa-skill-MyFirstSkill`としましたが、それ以外の文字列が付加されているようです。
どうやら、この関数をデプロイするときの環境情報が足されるようです。
これでよければこのままでいきましょう。

デプロイ時のLambda関数名を変更する方法がありますが、また別の記事で書きたいと思います。

以上で、ask-cliからAlexaスキルをデプロイする方法の説明は終わります。


#おまけ

##Lambda関数のデフォルトのデプロイ先リージョンを変更する。
Lambda関数がどこのリージョンに配置されていようとスキルの実行については何も問題はないのですが、いつも使っているリージョンに配置されたほうがわかりやすいし、気持ち的に落ち着くのではないでしょうか。

そこで、Ask Cliのほうで、デフォルトでLambda関数をデプロイするリージョンを変更できたら素晴らしいですね。

結論から言って、ask cliの通常の使い方では目的のリージョン**のみ**にデプロイすることは、現状できないようです。
`skill.json`に変更を加えることで、「米国東部（バージニア北部）」に加えて任意のデプロイ先を加えることはできるようですが。

@snufkon さんの[こちらの記事](https://qiita.com/snufkon/items/a9db3d001f7df3797952)の方法で目的を達成することはできるそうです。
つ、強い。