🤐

【Go】AWS Secrets Managerの値をGoで取得する

2021/11/15に公開

はじめに

Localでは.envからsecretを取得する事が大半なのですが、Secrets Managerから取得する事がありましたので、記事にしてみます。

環境

go 1.17
github.com/aws/aws-sdk-go v1.42.4

Secretを作成する

まず最初にAWS Secrets Managerでsecretを作成します。

  1. AWS Secrets Managerにアクセスし、作成ボタンをタップするとこのような画面に来ます。

こちらでKeyとValueを設定します。
今回は、SAMPLE_KEYSAMPLE_INTという雑なkEYにしてます。

  1. Secretの名前をつけます。

今回はsample-secret-nameという名前にしました。

  1. ローテーションの設定をします。

不要であれば、不要で登録します。

  1. 確認画面が出て登録完了

登録出来ています。

サンプルコードの確認

secretの登録が出来たら、サンプルコードを確認しましょう。

secretの名前をタップして詳細画面に飛ぶと、secretの値など確認出来るのですが、
その一番下にサンプルコードが書いてあります。

実はこれをコピーするだけで、secretの値が取得出来ます!!簡単ですね!!
ありがとう!AWS!!

という訳でコピペしました。こんな感じになりました。

ソースコード

package main

import (
	"encoding/base64"
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/secretsmanager"
)

func main() {

	//名前とリージョンの定義
	secretName := "sample-secrets-name"
	region := "ap-northeast-1"

	//Secrets Manager clientを作成します
	svc := secretsmanager.New(session.New(),
		aws.NewConfig().WithRegion(region))
	input := &secretsmanager.GetSecretValueInput{
		SecretId:     aws.String(secretName),
		VersionStage: aws.String("AWSCURRENT"), // VersionStage デフォルトは、AWSCURRENTらしい。
	}

	result, err := svc.GetSecretValue(input)
	// たくさんエラーハンドリングされています。
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			switch aerr.Code() {
			case secretsmanager.ErrCodeDecryptionFailure:
				// Secrets Manager can't decrypt the protected secret text using the provided KMS key.
				fmt.Println(secretsmanager.ErrCodeDecryptionFailure, aerr.Error())

			case secretsmanager.ErrCodeInternalServiceError:
				// An error occurred on the server side.
				fmt.Println(secretsmanager.ErrCodeInternalServiceError, aerr.Error())

			case secretsmanager.ErrCodeInvalidParameterException:
				// You provided an invalid value for a parameter.
				fmt.Println(secretsmanager.ErrCodeInvalidParameterException, aerr.Error())

			case secretsmanager.ErrCodeInvalidRequestException:
				// You provided a parameter value that is not valid for the current state of the resource.
				fmt.Println(secretsmanager.ErrCodeInvalidRequestException, aerr.Error())

			case secretsmanager.ErrCodeResourceNotFoundException:
				// We can't find the resource that you asked for.
				fmt.Println(secretsmanager.ErrCodeResourceNotFoundException, aerr.Error())
			}
		} else {
			// Print the error, cast err to awserr.Error to get the Code and
			// Message from an error.
			fmt.Println(err.Error())
		}
		return
	}
	fmt.Println("result", result)

	//取得したsecretが文字列化バイナリかを判断します
	var secretString, decodedBinarySecret string
	if result.SecretString != nil {
		secretString = *result.SecretString
	} else {
		decodedBinarySecretBytes := make([]byte, base64.StdEncoding.DecodedLen(len(result.SecretBinary)))
		len, err := base64.StdEncoding.Decode(decodedBinarySecretBytes, result.SecretBinary)
		if err != nil {
			fmt.Println("Base64 Decode Error:", err)
			return
		}
		decodedBinarySecret = string(decodedBinarySecretBytes[:len])
	}

	fmt.Println("secretString:", secretString)
	fmt.Println("decodedBinarySecret", decodedBinarySecret)
}

出力結果

result {
  ARN: "arn:aws:secretsmanager:xxxxxxxxxxxxxxxxxxxxxxxxxx",
  CreatedDate: 2021-11-14 14:01:09.747 +0000 UTC,
  Name: "sample-secrets-name",
  SecretString: <sensitive>,
  VersionId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  VersionStages: ["AWSCURRENT"]
}
secretString: {"SAMPLE_KEY":"SAMPLE_VALUE","SAMPLE_INT":"100"}
decodedBinarySecret 

fmt.Printlnだけ足しました。
AWSのアクセスキーやシークレットアクセスキーが必要かと思ってましたが、いらないようです。
注意点として、Stringで出力されますので、Keyに対してのValueを取り辛いです。

さいごに

サンプルコード載せてくれるAWS優しい。
でも、どーせなら、mapで出力してくれたら、もっと嬉しい。

Discussion