CloudRunの秘匿情報をSecretManagerで扱ってみる

# 概要

以前、CloudRunで秘匿情報を扱うのにberglas（GCPで秘匿情報を扱うためのOSS）を使用しましたが、2020年1月23日公式にGCPで秘匿情報を扱うためのサービスであるSecretManagerが公開されました。

### 紹介記事

https://cloud.google.com/blog/ja/products/identity-security/introducing-google-clouds-secret-manager

# 制限事項

まだベータ提供です。
東京リージョンもまだありません。（一番近くて台湾）

なので、GAでないと困る人や、秘匿情報を国外に保持したくない人はまだ使えないです。
ただ、今後GCPで秘匿情報を扱うのはこれが標準になっていくと思われます。

# 使い方

## シークレットを作成する

セキュリティ→シークレットマネージャーから作成します。

<img width="792" alt="スクリーンショット 2020-02-11 22.19.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306826/4fc69817-bf24-8268-af91-df1dc00262e9.png">

「sample-secret」というキーで、「usagisan」という文字列を格納しています。

なお、gcloudコマンドで作成する手順は、上記紹介記事の中に記載があります。

## クライアント

シークレットを読み取る例は、下記ドキュメントのCreating and accessing secretsの章が参考になります。

https://cloud.google.com/secret-manager/docs/how-to?hl=ja

### python（Django）での実装例

シークレットを取得して画面に表示するだけのサンプル。
（SecretManagerにアクセスするためのソースはここだけです。他は、Djangoの設定や、コンテナ化、CloudRunへのデプロイ手順です）
views.py

```
from django.shortcuts import render
from google.cloud import secretmanager_v1beta1 as secretmanager

# Create your views here.
from django.http import HttpResponse

def index(request):
    client = secretmanager.SecretManagerServiceClient()
    # プロジェクトID,シークレットID,バージョン番号
    name = client.secret_version_path('xxxx-xxx-xxxxxx', 'sample-secret', 1)
    response = client.access_secret_version(name)
    payload = response.payload.data.decode('UTF-8')
    return HttpResponse("Hello " + payload + "!")

```

urls.py

```
from django.contrib import admin
from django.urls import path
import app.views

urlpatterns = [
    path(r'^admin/', admin.site.urls),
    path(r'', app.views.index, name='index')
]
```

CloudRunで実行するためにイメージを作成します。

requirements.txt

```
django
google-cloud-secret-manager
```

Dockerfile

```
FROM python:3.8.1-slim

ENV PYTHONDONTWRITEBYTECODE 1  
ENV PYTHONUNBUFFERED 1 

RUN apt-get update \
    && apt-get upgrade -y \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* \
    && pip install --upgrade pip

# 作業するディレクトリを変更
WORKDIR /app
# アプリのコピー
COPY . /app

# pythonのパッケージをインストール
RUN pip install -r requirements.txt

EXPOSE 8000

CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]
```

setting.pyの変更（セキュリティは一旦置いといて）

```
#ALLOWED_HOSTS = []
ALLOWED_HOSTS=['*']

# LANGUAGE_CODE = 'en-us'

# TIME_ZONE = 'UTC'

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'
```

## CloudRunにデプロイ

### イメージをContainerRegistoryに保存

```
gcloud auth configure-docker
docker build -t asia.gcr.io/<プロジェクトID>/<イメージ名>:<タグ名> .
docker push asia.gcr.io/<プロジェクトID>/<イメージ名>:<タグ名>
```

### デプロイ

ContainerRegistoryに登録したイメージを選択
![スクリーンショット 2020-02-16 181236.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306826/5e9ff27c-154c-a8c1-6faf-6153ee68b0ce.png)

東京リージョンを選択、未認証の呼び出しを許可をチェック、ポート番号を変更してデプロイ
<img width="469" alt="スクリーンショット 2020-02-16 18.15.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306826/ac15f997-52ce-7a4c-5524-6ed61336e12b.png">

### 動作確認

デプロイが終わるとURLが発行されるので動作確認。
<img width="703" alt="スクリーンショット 2020-02-16 21.30.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306826/2925927a-4205-2e20-de15-d8ba37417d30.png">

きっとエラーになります。
![スクリーンショット 2020-02-16 213255.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306826/fd1c24cd-8a03-f0af-e397-4a824a244e8b.png)

SecretManagerへは明示的にアクセス許可を与えないと権限エラーとなるためですね。

というわけで、IAMに権限を付与します。
<img width="636" alt="スクリーンショット 2020-02-16 21.38.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306826/cd15ec57-8c77-fe4b-fcad-390b980782b7.png">

再度アクセスすると、無事表示されました。
<img width="376" alt="スクリーンショット 2020-02-16 21.38.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306826/bf447918-e700-3cf3-5b6c-4892900c534c.png">

### おわりに

[紹介記事](https://cloud.google.com/blog/ja/products/identity-security/introducing-google-clouds-secret-manager)ではberglasとの関係という内容で、berglasからでもアクセスできる記載がありましたが、これから始める人はSecretManagerを直接使えば良さそうですね。
今すでにberglasで運用している人は格納場所はSecretManagerに寄せてアクセスはberglasのままという使い方もできそうです。