AWS CLIを使ってAWS Secrets Managerと戯れてみた

# About this article

今年の4月に、AWS Secrets Managerというサービスがアナウンスされました。
既に触っている方もいらっしゃるとは思いますが、あまり記事がなかったので、個人的なメモも含めて触ってみたときにやったことをここに記します。

# About AWS Secrets Manager
AWS Secrets Managerは、 データベースの認証情報やAPIのシークレットキーなどの**コードに直接書きたくない**データを簡単に管理できるサービスで、アプリケーションからトークンを叩いてアクセスする際などに使えます。
[クラスメソッドさんの記事](https://dev.classmethod.jp/cloud/aws/secrets-manager-tutorials/)にも詳しく書かれており、以下のような特徴があります(以下抜粋)

>- 各種アプリケーションやITリソースのアクセスに必要なシークレット情報を一元管理
>- ユーザーはAWS Secrets Manager API経由でアクセスするため、各種シークレット情報をプレーンテキストで保持する必要が無い
>- RDS（MySQL、PostgreSQL）、Amazon Auroraに統合されており、シークレット情報の更新とデータベースパスワードの更新を自動化可能
>- APIキーや、OAuthトークンなどのシークレットにも拡張可能
>- IAMポリシーを利用して、シークレット情報へのアクセス制御が可能

手元でDBの認証情報を保存する必要がなくなるため、Webアプリケーションなどに一般的に使われるconfigファイルなどへのべた書きや、envファイルの管理が楽になるのがメリットかと思います(gitにも載せなくて良くなるので便利っぽい)。

ここでは、AWS CLIを使って、シークレットの作成と削除、取得をやってみようと思います。

# 1. AWS CLIでキーを生成する

AWS CLIにおける[Secrets Manager(シークレット作成)](https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/create-secret.html)のマニュアルによると、シークレットの作成で指定できるパラメータは以下のとおりです。

```
  create-secret
--name <value>
[--client-request-token <value>]
[--description <value>]
[--kms-key-id <value>]
[--secret-binary <value>]
[--secret-string <value>]
[--tags <value>]
[--cli-input-json <value>]
[--generate-cli-skeleton <value>]
```

今回は、

- 単なるテキストデータ
- JSONフォーマットを使ったKey-Value形式のデータ
 
をそれぞれ突っ込んでみます。

## 単なるテキストデータ
まず、テキストデータを突っ込むときは以下のように指定します(descriptionとprofileは省略してもいいと思います)。

```console
$ aws secretsmanager create-secret --name SampleTextSecret  --description "Some sample text secert data" --secret-string aaaa (--profile profile)
{
    "ARN": "arn:aws:secretsmanager:xx-xxxx-1:xxxxxxxxxxx:secret:SampleTextSecret-xxxxx",
    "Name": "SampleTextSecret",
    "VersionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
}
```

すると、作成成功のときのみJSON形式でARNとName、VersionIdといったパラメータが返ってきます。

余談ですが、ファイルの中身を突っ込みたいときは以下のような形でファイル指定もできます。

```console
$ echo 'such wow!' > secret.txt
$ aws secretsmanager create-secret --name SampleTextSecretFromFile  --description "Some sample text secert data" --secret-string file://secret.txt --profile profile
{
    "ARN": "arn:aws:secretsmanager:xx-xxxx-1:xxxxxxxxxxx:secret:SampleTextSecretFromFile-xxxxx",
    "Name": "SampleTextSecretFromFile",
    "VersionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
}
```

## JSONフォーマットを使ったKey-Value形式のデータ

このJSONファイルをSecrets Managerに突っ込んでみます。

```json:secret.json
{
  "someKey1": "someValue1",
  "someKey2": "someValue2",
  "someKey3": "someValue3"
}
```

```console
$ aws secretsmanager create-secret --name SampleJSONSecretFromFile --description "Some sample JSON secret data" --secret-string file://secret.json --profile profile
{
    "ARN": "arn:aws:secretsmanager:xx-xxxx-1:xxxxxxxxxxx:secret:SampleJSONSecretFromFile-xxxxx",
    "Name": "SampleJSONSecretFromFile",
    "VersionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
}
```

# 2. AWS CLIでキーを取得する

1と同じ形で、それぞれのデータを取得してみます。

テキストを直接挿入したものはこんなかんじ

```console
$ aws secretsmanager get-secret-value --secret-id SampleTextSecret --profile profile
{
    "ARN": "arn:aws:secretsmanager:xx-xxxx-1:xxxxxxxxxxx:secret:SampleTextSecret-xxxxx",
    "Name": "SampleTextSecret",
    "VersionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
    "SecretString": "aaaa",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1527732816.484
}
```

ファイルで挿入したやつはこんなかんじ(改行コードが入ってますねｗ)

```console
$ aws secretsmanager get-secret-value --secret-id SampleTextSecretFromFile --profile profile
{
    "ARN": "arn:aws:secretsmanager:xx-xxxx-1:xxxxxxxxxxx:secret:SampleTextSecretFromFile-xxxxx",
    "Name": "SampleTextSecretFromFile",
    "VersionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
    "SecretString": "such wow!\n",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1527733153.528
}
```

JSONで入れたものはこんなかんじ(フォーマットがだいぶ崩れてますね)

```console
$ aws secretsmanager get-secret-value --secret-id SampleJSONSecretFromFile --profile profile
{
    "ARN": "arn:aws:secretsmanager:xx-xxxx-1:xxxxxxxxxxx:secret:SampleJSONSecretFromFile-xxxxx",
    "Name": "SampleJSONSecretFromFile",
    "VersionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
    "SecretString": "{\n  \"someKey1\": \"someValue1\",\n  \"someKey2\": \"someValue2\",\n  \"someKey3\": \"someValue3\"\n}",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1527733344.609
}
```

## JSONデータの整形をやってみる
このままだとぐちゃぐちゃだし、取りたいデータが取れません。
そこで、`jq`コマンドを使って取得したJSONデータを整形してみることにします。

取り出したいキーが入っているのは`SecretString`なので

```console
$ aws secretsmanager get-secret-value --secret-id SampleJSONSecretFromFile --profile profile | jq '.SecretString'
"{\n  \"someKey1\": \"someValue1\",\n  \"someKey2\": \"someValue2\",\n  \"someKey3\": \"someValue3\"\n}"
```

お、なんかいい感じだけどあとちょっと！

もう少しだけ`jq`をつかってデータを整形してみます。

## 特定の値だけいい感じに取りたい場合

```console
$ aws secretsmanager get-secret-value --secret-id SampleJSONSecretFromFile --profile profile | jq '.SecretString' | jq -r .
{
  "someKey1": "someValue1",
  "someKey2": "someValue2",
  "someKey3": "someValue3"
}

$ aws secretsmanager get-secret-value --secret-id SampleJSONSecretFromFile --profile profile | jq '.SecretString' | jq -r . | jq .someKey1
"someValue1"

$ aws secretsmanager get-secret-value --secret-id SampleJSONSecretFromFile --profile profile | jq '.SecretString' | jq -r . | jq -r .someKey1
someValue1

$ aws secretsmanager get-secret-value --secret-id SampleJSONSecretFromFile --profile profile | jq '.SecretString' | jq -r . | jq -r '.someKey1, .someKey2'
someValue1
someValue2
```

おー、なんだかいい感じにとってこれましたね！`jq`の使い方の勉強にもなりました。

# Conclusion

というわけで、AWS Secrets Managerでは、リクエストで秘匿情報を渡すこと無く値を生成、取得できることがわかりました。

なお、コマンドラインだけでなく、JavaやPythonなどのコードを使ってデータを取得することもできます。そのへんはAWSのコンソールで直接ポチポチすると解説が出てくるので、実際にシークレットを生成してみるとよいかもしれません。

以上です。ありがとうございました！