この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
AWS Secrets Managerを利用するとシークレットを簡単にローテーション、管理、取得することができます。具体的なユースケースとしてはデータベースの認証情報やAPI キーの管理が挙げられますが、AWS Secrets Managerではこの種のテキストデータの他にバイナリデータを保管することもできます。
バイナリのシークレットを扱う身近なユースケースが思いつかなかったのですが、、、興味があったので試してみました。
目次
前提
- 現時点では、AWSマネージメントコンソールはAWS Secrets Managerへのバイナリデータの保存をサポートしていません。
- このため、今回はAWS CLIとAWS SDK for Golangを使ってAWS Secrets Managerへのバイナリデータの保存と取得を試しました。
- AWS Secrets Managerの基本的な利用方法については以下のブログ記事を参照ください。
新サービス「AWS Secrets Manager」をチュートリアル2種(基本設定、RDSローテーション)で基礎から学ぶ
検証環境
- macOS:Mojave(v10.14.2)
- AWS CLI:v1.16.90
- AWS SDK for Golang:v1.16.25
AWS CLIでのバイナリデータの保存・取得
バイナリデータの保存
バイナリデータをファイルに保存し、そのファイルをcreate-secret
コマンドの引数に渡します。
we recommend that you store your binary data in a file and then use the appropriate technique for your tool to pass the contents of the file as a parameter.
また、リクエストに含めるバイナリデータはBase64でエンコードする必要がありますが、このエンコード処理はAWS CLIが自動的に実行してくれます。単純にバイナリファイルをcreate-secret
コマンドの引数に渡せばOKです。
$ aws secretsmanager create-secret --name my-secret-binary-with-cli \
--description "my secret binary created with the AWS CLI" \
--kms-key-id "XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" \
--secret-binary fileb://<binary file>
{
"ARN": "arn:aws:secretsmanager:ap-northeast-1:XXXXXXXXXXXX:secret:my-secrets-XXXXXX",
"Name": "my-secret-binary",
"VersionId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
バイナリデータの取得
get-secret-value
でデータを取得します。レスポンスのSecretBinary
にバイナリデータがセットされています。バイナリデータはBase64でエンコードされているので、base64
コマンド等でデコードします(お試しということで、以下のコマンド実行例ではバイナリデータをファイルに保存しています)。
$ aws secretsmanager get-secret-value --secret-id my-secret-binary-with-cli \
| jq -r .SecretBinary \
| base64 --decode > <binary file>
AWS SDK for Golangでのバイナリデータの保存・取得
バイナリデータの保存
CreateSecretInput
のSecretBinary
にバイナリデータをセットします。AWS CLI同様、Base64のエンコード処理はAWS SDK側で自動的に行われます。
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/secretsmanager"
)
func main() {
region := "ap-northeast-1"
filePath := "./binary_file"
secretID := "my-secret-binary-with-sdk"
kmsKeyID := "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
file, err := os.Open(filepath.Clean(filePath))
if err != nil {
log.Fatal(err.Error())
}
defer file.Close()
data, err := ioutil.ReadAll(file)
if err != nil {
log.Fatal(err.Error())
}
sess := session.Must(session.NewSession())
svc := secretsmanager.New(sess, aws.NewConfig().WithRegion(region))
input := &secretsmanager.CreateSecretInput{
Description: aws.String("my secret binary created with the AWS SDK"),
Name: aws.String(secretID),
SecretBinary: []byte(data),
KmsKeyId: aws.String(kmsKeyID),
}
result, err := svc.CreateSecret(input)
if err != nil {
log.Fatal(err.Error())
}
fmt.Println(result)
}
バイナリデータの取得
AWS SDK の場合、Base64のデコード処理はAWS SDK側で自動的に行われます(AWS CLIでの実行例と同様に、お試しということでバイナリデータをファイルに保存しています)。
package main
import (
"fmt"
"log"
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/secretsmanager"
)
func main() {
region := "ap-northeast-1"
secretName := "my-secret-binary-with-sdk"
sess := session.Must(session.NewSession())
svc := secretsmanager.New(sess, aws.NewConfig().WithRegion(region))
input := &secretsmanager.GetSecretValueInput{
SecretId: aws.String(secretName),
}
result, err := svc.GetSecretValue(input)
if err != nil {
log.Println(err.Error())
}
file, err := os.Create("binary_file")
if err != nil {
log.Println(err.Error())
}
defer file.Close()
_, err = file.Write(result.SecretBinary)
if err != nil {
log.Println(err.Error())
}
fmt.Println(result)
}
まとめ
ざっと調べた限りではAWS Secrets Managerでバイナリデータを扱うサンプルが見つからなかったので、実際に試してみました。 特にAWS SDKを使う場合はBase64エンコード/デコードが自動的に行われるので、テキストデータのそれとほぼ同様のコードでバイナリデータを扱えることが分かりました。