credential情報を隠蔽して安全にdeployする

[Cloud Foundry Advent Calendar 2017](https://qiita.com/advent-calendar/2017/cloudfoundry)の16日目の記事です。

自分も1ユーザとして、cloudfoundryにアプリケーションをpushしたりしているのですが、credential情報の管理が難しいなと思ったのでここで共有しちゃいたいと思います。

## credential情報とは
![スクリーンショット 2017-12-12 4.29.21.png](https://qiita-image-store.s3.amazonaws.com/0/84299/f49c2697-a3e4-bc08-5a62-2851b618c595.png "スクリーンショット 2017-12-12 4.29.21.png")

DBやAPIの認証に用いるためのID、Passなどをひっくるめて本投稿ではcredential情報と呼ぶことにします。

## モチベーション
**`cf push`ってめちゃくちゃ事故りませんかwww**
pushする際に...

1. ステージング環境にpushしたかったのに、manifestファイル指定ミスって本番環境にpushしたったw
1. ドキュメントが更新されてなくて、`cf set-env`で古い値に上書きしたったw

などなどみなさん一回は経験したことがあるんじゃないかと思います。 

なんでこんな問題が起こるのか自分なりに考えてみました。
単純に **デプロイ時の手順が多いから**なんじゃないでしょうか！

`cf push -f path/to/manifest`で済めば限りなく事故は減らせるはずです。

1については`manifest.yml`という名前のmanifestファイルを置かなければ多少改善されます。(`cf push`での参照されるmanifestファイルのデフォルトが`manifest.yml`だから)

2についてが本投稿のメインになります。
credential情報の持ち方を工夫して、`cf set-env`を撲滅していこうと思います。

## credential情報の持ち方
> `cf push -f path/to/manifest`で済めば限りなく事故は減らせるはずです。

必要な情報をうまくmanifestに落とし込む必要があります。
3つほど手段を考えました。

### githubで管理(ダメ、ゼッタイ。)

```yaml:manifest-stg.yml
---
applications:
- name: app-stg
  buildpack: php_buildpack
  instances: 1
  routes:
  - route: app-stg.hogehoge.com
  env:
    DB_USERNAME: fooooooo
    DB_PASSWORD: damedamedamedame
```

`cf set-env`をしなくて済むようにmanifetで構成管理してみました。
これはBad Practiceですね。
credentialな情報はgithub等にあげちゃだめって小さい頃におばあちゃんから聞いた気がします(privateなリポジトリだからいいやって人にあんまり強く言えないのでぼかしておきます

### concourseで管理
cloudfoundryのCI/CDツールとして[Concourse](https://concourse.ci/)があります。Concourseは各Jobをパイプラインとして管理し、可視化することができて ~~なんかかっこいいから~~好きです。

![スクリーンショット 2017-12-12 4.57.59.png](https://qiita-image-store.s3.amazonaws.com/0/84299/da1a1301-3d26-7640-34ec-6917c4c04de6.png "スクリーンショット 2017-12-12 4.57.59.png")

さて、Concourseの詳細な使い方は割愛しますが、cfへのpushを行うためのResourceとして[cf-resource](https://github.com/concourse/cf-resource)があります。
[README](https://github.com/concourse/cf-resource/blob/master/README.md#pipeline-example)から抜粋しますが、

```yaml:pipeline.yml
- put: resource-deploy-web-app
    params:
      manifest: build-output/manifest.yml
      environment_variables:
        key: value
        key2: value2
```
といった感じでpushを行うことができます。
この`environment_variables`をうまく使ってcredential情報を隠蔽します。

```yaml:pipeline.yml
- put: resource-deploy-web-app
    params:
      manifest: build-output/manifest.yml
      environment_variables:
        key: ((value))
        key2: ((value2))
```
Concourseではパイプラインのset時に別ファイルから値を参照することができます(参考:[Concourse:set-pipeline](https://concourse.ci/single-page.html#fly-set-pipeline))
credential情報を別ファイルにおいておき、githubで管理しないようにしましょう。

じゃあそのファイルはどうやって管理するんや。。。って思いますよね。
~~うまいことチームとかで共有してください。~~

[vault](https://www.vaultproject.io/)や、[credhub](https://docs.cloudfoundry.org/credhub/)と[合わせて使う](https://concourse.ci/creds.html)と別ファイルを持たなくてよくなりますよ。

### Serviceで管理
最後にServiceで管理する方法を書きます。
**が** 、明日の[@legnoh](https://qiita.com/legnoh)さんの記事でServiceについて詳しくやるらしいのでここではさらっとだけ紹介します。

```yaml:manifest-stg.yml
---
applications:
- name: app-stg
  buildpack: php_buildpack
  instances: 1
  routes:
  - route: app-stg.hogehoge.com
  services:
  - dbservice
```

このようにして、対象のappとserviceを紐付けます。
serviceとしてmarket place(`cf market-place`)に存在する場合はそのまま使っちゃってください。
そんなのないわ！って人は[UserProvidedServiceインスタンス](https://docs.cloudfoundry.org/devguide/services/user-provided.html)を作成しちゃいましょう。


```bash:terminalにて
$ cf cups devservice -p "DB_USERNAME, DB_PASSWORD"
## ここらから対話式
DB_USERNAME> gooood
DB_PASSWORD> ariariariari
OK
```

これでおk。


このやり方はConcourseに依存しないので、誰でも実施することができます。
もっと詳しく知りたくなってきましたよね。

なので明日の[@legnoh](https://qiita.com/legnoh)さんの投稿をチェックしましょう！

## さいごに
これがBestなのかはわかないですが、みなさんもcredential情報を隠蔽して安心・安全なcf lifeを送ってください

クリスマスが近いということでテンション高めでお送りいたしました。