フリーランチ食べたい

No Free Lunch in ML and Life. Pythonや機械学習のことを書きます。

AWS Secrets Managerを使って安全で簡単にGCPの秘密鍵JSONファイルなどの秘匿情報を取り扱う

TL;DR

  • AWS Secrets Managerで秘密鍵JSONファイルなどを簡単に扱うことができます。
  • 1つのユースケースとしてこの記事ではGCPの秘密鍵を扱います。
  • GCPのSDKに読み込む方法も解説します。

f:id:ikedaosushi:20190404130208p:plain

はじめに

CI/CDでアクセスキー/シークレットキーなどの秘匿情報を扱う際に環境変数を使っている方も多いと思います。しかし、GCPの認証キーはjson形式で環境変数として扱うのが大変です。

そういった場合、AWS Secrets Managerを使うことで簡単に様々なデータ形式の秘匿情報を扱うことができます。また暗号化も行ってくれるので環境変数を用いるより安全に管理できます。

この記事ではAWS Secrets Managerの設定方法とPythonのSDKから呼び出し、GCPのSDKに設定する方法を紹介します。GCPのSDKにどう読み込ませたらいいのか、迷ったのでそのメモでもあります 😅

解決したい課題

ウェブアプリケーション開発において秘密鍵やシークレットキーを用いてなんらかのAPIを使いたい場面は良くあり、シークレットキーのような文字列の場合、環境変数を使う場合も多いと思います。 しかしGCPの秘密鍵は次のようなjson形式になっています。

f:id:ikedaosushi:20190404115115p:plain
GCPの秘密鍵を含むjsonファイル

こういったjsonを文字列として環境変数として保存するのは、あまり適しているとは言えません。 できればjsonのまま管理したいですよね。また根本的なことを言えば環境変数というのは平文なのでちゃんと暗号化したいところでもあります。

AWS Secrets Managerを使う

この問題はAWS Secrets Managerを使って簡単に解決することができます。

f:id:ikedaosushi:20190404123538p:plain
AWS Secrets Manager

AWS Secrets Managerは2018年に発表された認証情報やAPIキー、秘密鍵などの保存に特化したAWSのサービスです。 詳しい説明はクラスメソッドさんのブログを見ていただくのが一番早いと思います。

dev.classmethod.jp

ここではjsonの保存/利用に関して簡単な使い方を書きます。

保存する

まず保存です。下の画像のように「Other type」の「plaintext」を選択することでjsonをそのまま保存することができます。

f:id:ikedaosushi:20190404120516p:plain
jsonファイルを保存する

名前をつける

保存ができたら名前を付けます。この名前を元にSDKなどから呼び出すことになるのでメモしておきましょう。

f:id:ikedaosushi:20190404120216p:plain
secretに名前をつける

Python SDKから呼び出す

それでは保存したSecretをPythonのSDKから呼び出してみます。

import boto3

client = boto3.client(
    service_name="secretsmanager",
    region_name="secretを保存したregion"
)

secret = client.get_secret_value(SecretId="設定したSecretの名前")
print(secret)

中身は次のようになっています。 SecretString に保存したjsonファイルが入っていることがわかります。

{'ARN': 'arn:aws:secretsmanager:...',
 'Name': '...',
 'VersionId': '13f7bbaa-...',
 'SecretString': '{"type":"service_account","project_id":"...

簡単ですね!

GCPのSDKに入力する

それではこれをGCPのSDKに入力してみます。なぜわざわざこんなことを書いているかと言うと、GCPのSDKが公式のサンプルにはファイルパスしか入力形式として受け取る例しかないからです。

最初は悩んだのですが、SDKのソースなども見つつ次の方法でできることがわかりました。 まずGCPのcredentialオブジェクトを作成します。

import json 
from google.oauth2.service_account import Credentials

# SecretStringを取り出す
secret_string =  client.get_secret_value(SecretId=secret_name)['SecretString']

# SecretStringはstring形式なのでdict型に変換
credential_dic = json.loads(secret_string)

# Credentials.from_service_account_infoを使ってdict型からcredentialオブジェクトに変換
credentials = Credentials.from_service_account_info(credential_dic)

作成したら、あとは使いたいサービスのクライアントに credentials 引数に今作成したcredentialオブジェクトを渡すだけです。試しに2つのクライアントを作成してみます。

# BigQuery
from google.cloud import bigquery
client = bigquery.Client(project="project_name", credentials=credentials)

# Natural Language API
from google.cloud import language
client = language.LanguageServiceClient(credentials=credentials)

こんな感じでどのクライアントにも認証情報を渡すことができます。 こちらもできてしまえば簡単ですね!

まとめ

  • AWS Secrets Managerを使ったjson形式の秘密鍵の取扱い方法と、それをGCPのSDKから使う方法を紹介しました。
  • もし、「もっと簡単な方法があるよ」という方がいたら是非教えてください🙋‍♂️