AWS Secrets Managerでバイナリデータを管理する
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エンコード/デコードが自動的に行われるので、テキストデータのそれとほぼ同様のコードでバイナリデータを扱えることが分かりました。