---
title: OAuth2 ProxyをCloud FoundryのSidecarとしてデプロイする
tags: ["Cloud Foundry", "PAS", "Pivotal Cloud Foundry", "OAuth2 Proxy"]
categories: ["Dev", "PaaS", "CloudFoundry", "PCF"]
date: 2020-04-11T15:16:57Z
updated: 2020-04-11T15:42:56Z
---

前記事、"[Cloud Foundryの複数Portに対するRouting](/entries/516)"で、

> また、Sidecarを使う場合も同じようにRouteをmapできます。

と書いていたので、その例として[OAuth2 Proxy](https://oauth2-proxy.github.io/oauth2-proxy/)をsidecarとして使う例を紹介します。


次の図のような構成を実装します。

![image](https://user-images.githubusercontent.com/106908/79045833-4415f280-7c48-11ea-894b-23e8164bd24c.png)

次のバージョンで確認しました。
```
$ cf -v
cf version 6.50.0+4f0c3a2ce.2020-03-03

$ cf curl /v2/info | jq -r .build
2.8.6-build.15
```

<!-- toc -->

### Main Appの作成

ここではphp buildpackで作ったアプリをUpstreamのMain Appとして扱います。

Main Appは次のように作成します。

```
mkdir -p /tmp/demo-oauth2-proxy/htdocs
cd /tmp/demo-oauth2-proxy
echo 'Hello World!' > htdocs/index.html
```

このMain Appへアクセスする前にGithubで認証させるために[OAuth2 Proxy](https://oauth2-proxy.github.io/oauth2-proxy/)をReverse Proxとして使うことを今回の題材とします。

Main Appへ直接アクセスされることを防ぐため、デフォルトの設定である、Main App(8080ポート)へのRoutingは行いません。
代わりに同一コンテナ内にSidecarとして起動するOAuth2 Proxy(4180ポート)に対してのみRoutingします。

### OAuth2 Proxyのダウンロード

次のコマンドでOAuth2 Proxyの実行可能バイナリをダウンロードしてください。	

```
cd /tmp/demo-oauth2-proxy
curl -Ls https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v5.1.0/oauth2_proxy-v5.1.0.linux-amd64.go1.14.tar.gz | tar xzv && \
  mv oauth2_proxy-*/oauth2_proxy ./ && \
  rm -rf oauth2_proxy-*
```

### Github OAuth2 Appの作成

[https://github.com/settings/developers](https://github.com/settings/developers)からGithub OAuth2 Appを登録します。

"New OAuth App"ボタンをクリックして、`Authorization callback URL`に`https://<TARGET_SUBDOMAIN>.<APPS_DOMAIN>/oauth2/callback`を入力してください。

下図の例では`TARGET_SUBDOMAIN=demo-oauth2-proxy`、`APPS_DOMAIN=apps.pcfone.io`です。
![image](https://user-images.githubusercontent.com/106908/79047738-7711b380-7c53-11ea-8681-dfb5f4a83f61.png)


Client IDとClient Secretをメモしてください。
![image](https://user-images.githubusercontent.com/106908/79046576-c0123980-7c4c-11ea-946d-65c30479b6e1.png)

この値をUser Provider ServiceまたはCredHub Service Brokerに登録します。


User Provided Serviceの場合
```
cf create-user-provided-service github-oauth2-app -p '{"client_id": "3210067a78235e54fa17", "client_secret":"24c06ed8c2d6d7146c28e4cd72c4d18b63ef5bef"}'
```

CredHub Service Brokerの場合
```
cf create-service credhub default github-oauth2-app -c '{"client_id": "3210067a78235e54fa17", "client_secret":"24c06ed8c2d6d7146c28e4cd72c4d18b63ef5bef"}'
```

### Main App及びSidecarのデプロイ

次の`manifest.yml`を作成してください。`OAUTH2_PROXY_EMAIL_DOMAINS`、`OAUTH2_PROXY_COOKIE_SECRET`、`OAUTH2_PROXY_GITHUB_ORG`は自分の環境に合わせて変更してください。

```yaml
applications:
- name: demo-oauth2-proxy
  buildpacks:
  - php_buildpack
  memory: 64M
  services:
  - github-oauth2-app
  env:
    # Configurationの詳細は https://oauth2-proxy.github.io/oauth2-proxy/configuration
    OAUTH2_PROXY_HTTP_ADDRESS: 0.0.0.0:4180
    OAUTH2_PROXY_EMAIL_DOMAINS: .pivotal.io,.vmware.com
    OAUTH2_PROXY_COOKIE_SECURE: true
    # 次のコマンドで生成。 python -c 'import os,base64; print(base64.urlsafe_b64encode(os.urandom(16)).decode())'
    OAUTH2_PROXY_COOKIE_SECRET: 1pNTxc6qvV1rZBYobr0FUQ==
    OAUTH2_PROXY_UPSTREAMS: http://localhost:8080   
    OAUTH2_PROXY_PROVIDER: github
    OAUTH2_PROXY_GITHUB_ORG: pivotal
  sidecars:
  - name: oauth2-proxy
    process_types:
    - web
    command: |
      echo ${VCAP_SERVICES} | grep credhub
      if [ "$?" = "0" ];then
        CREDS=$(echo ${VCAP_SERVICES} | jq '.["credhub"][0].credentials')
      else
        CREDS=$(echo ${VCAP_SERVICES} | jq '.["user-provided"][0].credentials')
      fi
      export OAUTH2_PROXY_CLIENT_ID=$(echo ${CREDS} | jq -r .client_id)
      export OAUTH2_PROXY_CLIENT_SECRET=$(echo ${CREDS} | jq -r .client_secret)
      /home/vcap/app/oauth2_proxy
```

次のコマンドでデプロイしてください。

```
APP_NAME=demo-oauth2-proxy
TARGET_SUBDOMAIN=${APP_NAME}
APPS_DOMAIN=$(cf curl "/v2/shared_domains" | jq -r ".resources[0].entity.name")
CURRENT_SPACE=$(cat ~/.cf/config.json | jq -r ".SpaceFields.Name")

# 1. 
cf v3-create-app ${APP_NAME}
APP_GUID=$(cf app ${APP_NAME} --guid)

# 2.
cf curl "/v2/apps/${APP_GUID}" -X PUT -d "{\"ports\": [8080, 4180]}"

cf create-route ${CURRENT_SPACE} ${APPS_DOMAIN} --hostname ${TARGET_SUBDOMAIN}
ROUTE_GUID=$(cf curl "/v2/routes?q=host:${TARGET_SUBDOMAIN}" | jq -r ".resources[0].metadata.guid")

# 3.
cf curl "/v2/route_mappings" -X POST -d "{\"app_guid\": \"${APP_GUID}\", \"route_guid\": \"${ROUTE_GUID}\", \"app_port\": 4180}"

# 4. 
cf v3-apply-manifest -f manifest.yml 
cf v3-push ${APP_NAME}
```

1. Sidecarを含むmanifestを使ってデプロイする場合は、先にappを作成する必要があります。[[Doc]](https://docs.cloudfoundry.org/devguide/sidecars.html#create)
1. このコンテナが`8080`と`4180`をListenしていることを設定します。ここで設定したポートでヘルスチェックが行われます。通常Main Appはここで指定した一つ目のポートを使用するので、先頭を`8080`にするのが無難です。
1. 作成したRouteにアクセスした場合に、このコンテナ内の4180ポートにマッピングされるように設定します。
1. Sidecarを含むmanifestを適用します。


`cf logs ${APP_NAME}`を確認すると、次のようなログが出力されます。

```
   2020-04-11T23:51:16.84+0900 [API/1] OUT Starting app with guid 5a8769b7-4891-4f57-b6aa-0157f3e945dc
   2020-04-11T23:51:17.06+0900 [CELL/0] OUT Cell eda33d0c-120e-4025-991c-fd5f1c7d1e68 creating container for instance 291d8c06-72f4-4fbc-68ce-59be
   2020-04-11T23:51:17.79+0900 [CELL/0] OUT Cell eda33d0c-120e-4025-991c-fd5f1c7d1e68 successfully created container for instance 291d8c06-72f4-4fbc-68ce-59be
   2020-04-11T23:51:18.06+0900 [CELL/0] OUT Downloading droplet...
   2020-04-11T23:51:22.75+0900 [CELL/0] OUT Downloaded droplet (90.7M)
   2020-04-11T23:51:23.08+0900 [CELL/0] OUT Starting health monitoring of container
   2020-04-11T23:51:24.60+0900 [APP/PROC/WEB/SIDECAR/OAUTH2-PROXY/0] ERR [2020/04/11 14:51:24] [oauthproxy.go:215] mapping path "/" => upstream "http://localhost:8080/"
   2020-04-11T23:51:24.60+0900 [APP/PROC/WEB/SIDECAR/OAUTH2-PROXY/0] ERR [2020/04/11 14:51:24] [http.go:92] HTTP: listening on 0.0.0.0:4180
   2020-04-11T23:51:24.69+0900 [APP/PROC/WEB/0] OUT 14:51:24 httpd   | [Sat Apr 11 14:51:24.685558 2020] [mpm_event:notice] [pid 168:tid 140340045219712] AH00489: Apache/2.4.41 (Unix) configured -- resuming normal operations
   2020-04-11T23:51:24.69+0900 [APP/PROC/WEB/0] OUT 14:51:24 httpd   | [Sat Apr 11 14:51:24.685696 2020] [mpm_event:info] [pid 168:tid 140340045219712] AH00490: Server built: Jan  7 2020 15:08:24
   2020-04-11T23:51:24.69+0900 [APP/PROC/WEB/0] OUT 14:51:24 httpd   | [Sat Apr 11 14:51:24.685704 2020] [core:notice] [pid 168:tid 140340045219712] AH00094: Command line: '/app/httpd/bin/httpd -f /home/vcap/app/httpd/conf/httpd.conf -D FOREGROUND'
   2020-04-11T23:51:24.75+0900 [APP/PROC/WEB/0] OUT 14:51:24 php-fpm | [11-Apr-2020 14:51:24] NOTICE: fpm is running, pid 170
   2020-04-11T23:51:24.75+0900 [APP/PROC/WEB/0] OUT 14:51:24 php-fpm | [11-Apr-2020 14:51:24] NOTICE: ready to handle connections
   2020-04-11T23:51:26.69+0900 [CELL/0] OUT Container became healthy
```

デプロイが成功したら`https://${TARGET_SUBDOMAIN}.${APPS_DOMAIN}`にアクセスしてください。
未ログイン状態では次のようにOAuth2 Proxyの画面が表示されます。

![image](https://user-images.githubusercontent.com/106908/79047384-3022be80-7c51-11ea-9165-9095a07a7338.png)

"Sign in with GitHub"をクリックして、GitHubにログインしてください。

![image](https://user-images.githubusercontent.com/106908/79047134-c9e96c00-7c4f-11ea-8b85-6fc0ee3874b5.png)

"Authorize"をクリック。

![image](https://user-images.githubusercontent.com/106908/79047290-ad016880-7c50-11ea-8a5c-9827aa341d5f.png)

これでMain Appの`Hello World!`が出力されます。

![image](https://user-images.githubusercontent.com/106908/79047388-387af980-7c51-11ea-8849-89c2610a874b.png)

---
SidecarとRoute Mappingの応用を使ってReverse Proxyを同一コンテナ内に立てる方法を紹介しました。色々応用が効くと思います。
