Pomeriumを導入してアクセスコントロールを行えるようにした話

こんにちは,ICTSCのインフラチームの竹村です.
普段は監視基盤の構築や運用を行っています.

ICTSCのインフラチームでは,使用しているサービスに対してアクセス制御を行うためにPomeriumと呼ばれるID認識型プロキシを使用しています. 本記事ではICTSCがPomeriumを導入した経緯とPomeriumの構築手順,最後に正常に構築できているかを確認します.

Pomeriumについて

Home – Pomerium

Pomeriumは,内部のアプリケーションの前段にプロキシとして存在し,
外部のIDプロバイダーを用いてユーザを識別します.識別したユーザやユーザが所属するグループごとにポリシーを適用して,アクセスコントロールを行うことができます.
他のID認証型プロキシとしては,GoogleのIdentity-Aware ProxyやAkamaiのEnterprise Application Accessがあります.
公式の動画を見てもらえると,大体のイメージをつかんでもらえると思います.

Pomerium demo

今までのアクセスコントロール方法について

今までのアプリケーションへのアクセスコントロールの方針としては,認証が組み込まれていないアプリケーションはBasic認証を使用していました.例えばインフラチームでは,監視に使っているPrometheusに認証の仕組みがないため,Basic認証を使用していました.

認証が組み込まれているアプリケーションではadminアカウントを作成し,そのアカウントをチーム内で共有して運用を行っていました.

一方で,各アプリケーションごとに作成された管理用のユーザのパスワードを探す必要があるという問題や管理用のアカウントを複数人で共有しているためアクセスコントロールができないという問題がありました.

Pomeriumの導入

今までのアクセスコントロールの問題を解決するために,Pomeriumを導入しました.また,ICTSCではGitHub Organizationを使用しています.GitHub Organizationでのチームやメンバーに関しては,Terraformを使って管理しています.Pomeriumでは,IDプロバイダーとしてGitHubを使用することができます.また,GitHubのチームごとにアクセスコントロールの設定を簡単に行うことができます.

Pomeriumの構築手順

Pomeriumの構築手順を示します.インフラチームでは,HelmfileとArgo CDを使いデプロイの自動化を行っています.ここでは,Helmfileを使用したPomeriumの構築方法を示します.
Helmfileの書き方や使い方に関しては,以下のスライドに詳しくまとめられています.

Kubernetes Dashboard | Pomerium
Helm/Helmfileについて

以下のバージョンのソフトウェアを使用しています.

  • Helm v3.4.1
  • Helmfile v0.135.0
  • Kubernetes v1.19.3
  • Pomerium v0.12.1

IDプロバイダーとしては,GitHubを利用しています.

NGINX Ingress ControllerとCert-managerの構築とPomeriumでアクセスコントロールを行いたい内部のアプリケーションの用意が終わっていることが前提となります.今回の例では,内部のアプリケーションとして,Prometheusを使用しています.

次に,Pomeriumの構築を行っていきます.
まず,helmfile.yaml を用意します.

environments:
workspace:
values:
- environment/workspace/values.yaml
develop:
values:
- environment/develop/values.yaml
production:
values:
- environment/production/values.yaml
repositories:
- name: pomerium
url: https://helm.pomerium.io
releases:
- name: helm-pomerium
namespace: monitoring
chart: pomerium/pomerium
values:
- environment/{{ .Environment.Name}}/values.yaml

次に,各enviromentに対応したvalues.yamlのファイルを用意します.

authenticate:
idp:
provider: "github"
clientID: GitHub_CLIENT_ID
clientSecret: GitHub_CLIENT_SECRET
serviceAccount: "ewogICJ1c2VybmFtZSI6ICJZT1VSX0dJVEhVQl9VU0VSTkFNRSIsCiAgInBlcnNvbmFsX2FjY2Vzc190b2tlbiI6ICJHRU5FUkFURURfR0lUSFVCX0FDQ0VTU19UT0tFTiIKfQo="

forwardAuth:
enabled: true

config:
sharedSecret: YOUR_SHARED_SECRET
cookieSecret: YOUR_COOKIE_SECRET
rootDomain: dev.example.com

policy:
- from: https://dashboard-proxied.dev.example.com
to:  http://prometheus.monitoring.svc.cluster.local:9090
allowed_groups: ["ictsc_infra"]
tls_skip_verify: true

- from: https://kibana.dev.example.com
to:  http://kibana.monitoring.svc.cluster.local:5601
allowed_groups: ["ictsc_infra"]
tls_skip_verify: true

ingress:
hosts:
- dashboard-proxied.dev.example.com
- kibana.dev.example.com
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod" # see `le.issuer.yaml`
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
secretName: pomerium-ingress-tls

IDプロバイダーがGitHubの場合は,clientIDとclientSecret,serviceAccountの3つのトークンが必要になります.
これらのトークンの取得方法は,この後に説明します.

rootDomainを定義することにより,rootDomainを起点としてPrometheusの各コンポーネントのIngressが作成されます.
policyでは,該当するURLに対してアクセスしてきたユーザを識別しポリシーにマッチした場合,どのアプリケーションにルーティングするかを定義します.

policyの1つ目の例だと,ictsc_infraという名前のチームに所属しているユーザを http://dashboar-proxied.dev.example.com から,内部のサービスのPrometheusにルーティングされます.

次に,GitHubでOAuth2を行うためのアプリケーションを作成します.

GitHub | Pomerium

[Settings] →[Developer settings] → [New OAuth App]の順番にボタンを押し,新しくOAuthアプリケーションを作成します.

HomepageURLには,Pomeriumと統合するアプリケーションのホームページURLを入力します.Authorization callback URLにはPomeriumのauthenticate_service_urlを入力します.先ほどのvalues.yamlの例だと, https://authenticate.dev.example.com/oauth2/callback になります.

Client IDとClient Secretsが作成されるので,その値を values.yaml のclientIDとclientSecretに貼り付けます.

最後に,policyでallowed_groupを使用するために,サービスアカウントを設定します.GitHubのサービスアカウントは,github.com/settings/tokens/new から新しく取得できます.

GitHub | Pomerium

取得したアクセストークンを以下のJSONに貼り付け,base64でエンコードします.
エンコードした結果を,values.yamlに貼り付けます.

{
"username": "YOUR_GITHUB_USERNAME",
"personal_access_token": "GENERATED_GITHUB_ACCESS_TOKEN"
}
$ base64 service_account.json
ewogICJ1c2VybmFtZSI6ICJZT1VSX0dJVEhVQl9VU0VSTkFNRSIsCiAgInBlcnNvbmFsX2FjY2Vzc190b2tlbiI6ICJHRU5FUkFURURfR0lUSFVCX0FDQ0VTU19UT0tFTiIKfQo=

あとは,設定をもとにPomeriumを立ち上げます.
以下のコマンドを実行します.

$ helmfile -e develop apply

サービスが起動しているを確認するために,以下のコマンドを実行します.

$ helm ls -n monitoring
NAME                            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
helm-pomerium                   monitoring      2               2021-02-22 09:08:06.869077288 +0900 JST deployed        pomerium-15.0.0         0.12.1

$ kubectl -n monitoring get ing

NAME              CLASS    HOSTS                                                                                        ADDRESS           PORTS     AGE
helm-pomerium     <none>   dashboard-proxied.dev.example.com,kibana.dev.example.com,forwardauth.dev.example.com + 1 more...       80, 443   28h

Ingressのhostに定義したドメインにアクセスをすると,GitHubのログイン画面にリダイレクトされます.今回はICTSC Pomerium(dev)という名前のOAtuh アプリケーションで認可を行っています.

GitHubのユーザでログインを行います.policyのallowed_groupsで設定したチームに所属するユーザが,内部のサービスにアクセスできれば成功です.下の図では,内部サービスのPrometheusにアクセスできています.

最後に

インフラチームでPomeriumを利用することにより,GitHubのチームに基づいてアプリケーションのアクセスコントロールをできるようになりました.
後日にインフラチームが運用しているKubernetesの記事も公開されるので,楽しみにしてください!