selmertsxの素振り日記

ひたすら日々の素振り内容を書き続けるだけの日記

Minikube Tutorial をまるっとやる

最初に

このドキュメントは、このチュートリアルをまるっとやったことの記録。 kubernetes.io

まとめ

  • minikubeはlocalのimageを簡単に参照可能である
  • minikubeが具体的にどこからどこまで担保してくれてるのかよく分かってない。
  • kubectl はcontextを切り替えることで、gkeかminikubeかを選択して操作する
    • kubectl config use-context コマンド
  • kubernetesを使うために、わざわざyamlを使う必要は無かった

minikube

このチュートリアルのゴールは簡単なnode.jsのアプリケーションがkubenetesで動くところまで。 このチュートリアルは、machine上で開発したコードを、Docker imageに落とし込み、Minikube上で動かしていくよ。

Objecitves

  • hello world する簡単なnode.jsアプリを動かす
  • そのアプリケーションを minikubeに乗っける
  • applicationのlogを見る
  • applicationのimageをupdateする

Create a Minikube cluster

このチュートリアルでは、minikubeをlocal clusterで動かしてく。ここでは Docker for Macを使ってると仮定する。

brew cask install minikube
brew install kubernetes-cli

もしkubectlコマンドを、すでにgcloudからinstallしてたら、下記の手順を踏むこと。

gcloud components install kubectl
curl -LO https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-hyperkit \
&& chmod +x docker-machine-driver-hyperkit \
&& sudo mv docker-machine-driver-hyperkit /usr/local/bin/ \
&& sudo chown root:wheel /usr/local/bin/docker-machine-driver-hyperkit \
&& sudo chmod u+s /usr/local/bin/docker-machine-driver-hyperkit

下記URLを実行して、プロセスなしでアクセス可能なのか確認する

curl --proxy "" https://cloud.google.com/container-registry/

もし proxyが必要なければ、minikube start --vm-driver=hyperkit を実行すること。 --vm-driver=hyperkitはDocker for Macを使っているというフラグ。デフォルトはVirtualBox

https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#hyperkit-driver

➜ minikube start --vm-driver=hyperkit
Starting local Kubernetes v1.10.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Downloading kubelet v1.10.0
Downloading kubeadm v1.10.0
Finished Downloading kubeadm v1.10.0
Finished Downloading kubelet v1.10.0

minikube switch

kubectl config use-context minikube

➜ kubectl config get-contexts
CURRENT   NAME                                             CLUSTER                                          AUTHINFO                                         NAMESPACE
          xxx_pomodoro   xxx_pomodoro   xxx_pomodoro pomodoro
*         minikube                                         minikube                                         minikube

minikube dashboard

minikube dashboard

で色々見れる。便利。

f:id:selmertsx:20180720185617p:plain

Create your Node.js application

var http = require('http');
var handleRequest = function(request, response) {
  console.log('Received request for URL: ' + request.url);
  response.writeHead(200);
  response.end('Hello World!');
};
var www = http.createServer(handleRequest);
www.listen(8080);

こんなコードを用意した。

➜  k8s git:(master) node server.js
➜  k8s git:(master) curl localhost:8080
Hello World!%

で動くことを確認。

Create a Docker container image

FROM node:8.11.3
EXPOSE 8080
COPY server.js .
CMD node server.js

node imageはLTSの8.11.3を選択。 このチュートリアルでは、docker image をregistryにpushする代わりにminikubeを利用するので、 Docker hostと同じ場所でimageをbuildする必要がある。

そのため、下記のコマンドを実行する

eval $(minikube docker-env)

その後、docker imageをbuild.

docker build -t hello-node:v1 .

これでminikubeはimageをbuild出来るようになる。

Create a Deployment

kubenets podは、何か1つの目的に合わせてまとめられた、1つ、または複数のコンテナのグループである。 このチュートリアルにおいてPodは一つのコンテナでのみ出来ている。 KubeのDeploymentはPodの健康状態をcheckし、Pod Containerが死んだらrestartする。 Deploymentは、podを作ったりスケールする上で推奨される方法である。

kubectl run commandを使って、podを管理するためのDeploymentを作る。 Podは hello-node:v1 Docker imageを元にしたContainerを実行する。 local imageの利用を優先するために、--image-pull-policyフラグをNeverにセットする。

➜  k8s git:(master) ✗ kubectl run hello-node --image=hello-node:v1 --port=8080 --image-pull-policy=Never
deployment.apps/hello-node created
➜  k8s git:(master) ✗ kubectl get deployments
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-node   1         1         1            1           18s
➜  k8s git:(master) ✗ kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
hello-node-57c6b66f9c-7d26q   1/1       Running   0          31s

何か気になることがあったらkubectlコマンドを実行するとよいよ。 https://kubernetes.io/docs/reference/kubectl/overview/

Create a Service

デフォルトでは、PodはKubenetesクラスタ内の内部IP addressからしかアクセスできません。 K8s Virtual networkの外から、hello-node Containerにアクセス可能にするためには、PodsをServiceとして公開しなければならない。 開発環境においてはkubectl exposeコマンドでそれができる。

➜  k8s git:(master) ✗ kubectl expose deployment hello-node --type=LoadBalancer
service/hello-node exposed
➜  k8s git:(master) ✗ kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-node   LoadBalancer   10.107.74.133   <pending>     8080:32311/TCP   6s
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          45m

--type=LoadBalancerflagはサービスをclusterの外に公開することを示す。 LoadBalancerをサポートしているcloud providersであれば、Serviceにアクセスするためのexternal IP addressが用意される。

Minikubeでは、LoadBalancerタイプのサービスには、minikube service ${service_name} コマンドでアクセスすることが出来る。 このコマンドでブラウザが開かれて、サービスがアクセス可能になる。

podsの情報やlogの内容に関しては下記のコマンドで獲得可能である。

➜  k8s git:(master) ✗ kubectl describe pods
Name:           hello-node-57c6b66f9c-7d26q
Namespace:      default
Node:           minikube/192.168.64.2
Start Time:     Fri, 20 Jul 2018 16:54:31 +0900
Labels:         pod-template-hash=1372622957
                run=hello-node
Annotations:    <none>
Status:         Running
IP:             172.17.0.4
Controlled By:  ReplicaSet/hello-node-57c6b66f9c
Containers:
  hello-node:
    Container ID:   docker://5333602c10e2b6ef2677125996cf7ccd51db23946a7b085b85354fc0c30516f8
    Image:          hello-node:v1
    Image ID:       docker://sha256:80bf931ffb07668a2ef31dd3e5c08350ed5d64477ba424a847bb29b5b1eef0a7
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Fri, 20 Jul 2018 16:54:32 +0900
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-shf7x (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-shf7x:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-shf7x
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              14m   default-scheduler  Successfully assigned hello-node-57c6b66f9c-7d26q to minikube
  Normal  SuccessfulMountVolume  14m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-shf7x"
  Normal  Pulled                 14m   kubelet, minikube  Container image "hello-node:v1" already present on machine
  Normal  Created                14m   kubelet, minikube  Created container
  Normal  Started                14m   kubelet, minikube  Started container
➜  k8s git:(master) ✗ kubectl logs hello-node-57c6b66f9c-7d26q
Received request for URL: /
Received request for URL: /favicon.ico

Clean up

➜ kubectl delete service hello-node
service "hello-node" deleted

➜ kubectl delete deployment hello-node
deployment.extensions "hello-node" deleted

➜ docker rmi hello-node:v1 hello-node:v2 -f
Untagged: hello-node:v1
Deleted: sha256:80bf931ffb07668a2ef31dd3e5c08350ed5d64477ba424a847bb29b5b1eef0a7
Deleted: sha256:05f6355afc692766f99575564dd9d8e32917779c91285e8ddbadd615eb528bab
Deleted: sha256:137c95a151503aaa351d3430fa2ca089e28487516a7cbe61af318b2717cce6af
Deleted: sha256:1725ca28b86411d20d508a8275129fe68e68e4a6d32fd5a0c7d453a0de544f07
Error: No such image: hello-node:v2
➜ minikube stop
eval $(minikube docker-env -u)
Stopping local Kubernetes cluster...
Machine stopped.

CloudSQL をRailsで使ってみる

モチベーション

  • 今、個人で作ってるプロダクトを試しに GKEで動かしてみたい
  • GCPだと、RDBはCloudSQLを利用した方が良さそう
  • GKEの前に、CloudSQLを触ってみる

今日の学び

  • CloudSQLは、Globalからアクセス可能であるが、IPのホワイトリストかProxyを利用する必要がある
  • 開発時には固定IPを取得することが難しいので、Proxyを利用するのが良い

概要

下記2つのドキュメントを見て作業した

インスタンス作成

gcloud sql instances create pomodoro-dev-db --tier=db-f1-micro --region=asia-northeast1
gcloud sql users set-password root % --instance pomodoro-dev-db --password [PASSWORD]

接続名の取得

shuhei_morioka@cloudshell:~ (speee-dev-optim)$ gcloud sql instances describe pomodoro-dev-db | grep connectionName
connectionName: xxx:asia-northeast1:pomodoro-dev-db

このconnectionNameを Proxyにも利用する

Cloud SQL Proxyの利用

curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
chmod +x cloud_sql_proxy
bin/cloud_sql_proxy -instances=xxx:asia-northeast1:pomodoro-dev-db=tcp:3307
mysql -u root --host 127.0.0.1 --port 3307 -p

https://cloud.google.com/sql/images/proxyconnection.svg

今日覚えたコマンド

gcloud sql instances describe pomodoro-dev-db
backendType: SECOND_GEN
connectionName: xxx:asia-northeast1:pomodoro-dev-db
databaseVersion: MYSQL_5_7
etag: '"xxxx/Mw"'
gceZone: asia-northeast1-a
instanceType: CLOUD_SQL_INSTANCE
ipAddresses:

次回の対応

GKE動かしてき Connecting from Kubernetes Engine  |  Cloud SQL for MySQL  |  Google Cloud

GCPエンタープライズ設計ガイドの読書メモ

はじめに

業務でGCPの一部を利用することになったため、概要を把握するためにこれをサラッと読んだ。 この本はGCPの様々な機能に関する概要をまとめたもので、これを読むだけでGCPがガンガン使えるようになるものではない。 あくまでGCP全体の概要を把握するために読むものである。 本の中では、AWSの機能のこれにあたるという説明が多くされているため、AWS経験者なら頭に入りやすいのではないだろうか。

この記事では、僕が必要としていた部分だけ抽出して文書にしている。

AWSGCPの違い

  • AWSはCloudのサービスをリードしている
  • GCPはCloudのテクノロジーをリードしている
  • AWSは多機能
  • GCPはシンプル
  • AWSは従来のITインフラをそのまま抽象化した
    • VPCなどなど
  • Googleはソフトウェアエンジニアが基盤を意識しなくても作れるようになっている
    • ITインフラの内部が隠蔽されている
  • AWSは休日も含む24時間365日の日本語サポートがある
  • GCPの日本語サポートは、平日9~17時

Computing Service

  • GCPサービス => AWSで該当するもの
  • Google Compute Engine => AWS EC2
  • Google App Engine => AWS Elastic Beanstalk
    • スケールアウト時にはコンテナのプロセスを起動する
    • Standard EnvironmentとFlexible Environmentの2つのタイプが存在する
    • SE版は機能が制限されているが、めちゃくちゃ早い
    • FE版はDockerで動くので自由度が高いが、まぁまぁ遅い
    • 新しいバージョンの環境へのアクセスについては、柔軟に振り分けられる
    • ABテストなどにも使える
    • cronで定期実行も可能
  • Google K8s Engine => AWS EKS
  • Google Cloud Functions => AWS Lambda

Cloud SQL

  • Cloud SQLは、ストレージの自動拡張、Failover Replica機能、Read Replicaの作成の機能を持ち、耐障害性・スケール性能に優れている。
  • Cloud SQLにアクセスする場合は、Cloud SQL Proxyを利用して、IAMを利用したプロジェクトレベル・インスタンスレベルでのアクセス制御を行うこと。
  • Cloud SQLでは転送中・保存済みのデータはすべて暗号化されている。

ID管理

  • GCPではClod IAMを利用して、リソースの権限制御をしている
  • Cloud IAMは下記のIDに対して設定が可能である
    • Googleアカウント
    • サービスアカウント
      • 利用するアプリケーションに紐づくアカウント
    • Googleグループ
    • G Suiteドメイン
    • Cloud Identityドメイン
      • GmailやドライブなどのG Suiteのサービスを必要としないユーザー向けのドメイン

Cloud IAMでのRole

<service>.<resource>.<verb> といった形式で定義する。

  • Primitive roles: プロジェクトレベルで設定する Owner, Editer, Viewerの権限
  • Predefined Roles: GCPのリソース単位で設定できる役割。App Engine管理者はApp Engineのすべての設定が可能
  • Custom roles: 個別に作成するrole. メンバーやサービスアカウント毎に付与可能.
  • Cloud IAMのアクセス制御ポリシーは、Organization/Folder/Project/Resourceという階層になっている
  • 上の階層で定められた権限が、下位の階層に継承される

KubernetesとGKEの学習

最初に

この記事は、下記の書籍を読んだ上で自分の理解を整理するためにまとめたものです。

マルチホストでDockerを動かそう

GCPでのk8s活用について

  • GKEを利用する上で必要なサービスは下記の通り

Google Container Build

  • Docker Imageを作成するためのコマンドツール
  • Imageを作るためのソースリポジトリは色々選べる

Google Kubernetes Engine

  • Dockerコンテナを管理するフルマネージドサービス
  • k8sを利用しているので、kubectlコマンドなどで操作可能

Google Container Registry

Kubernetesの概要

アプリケーションの構成管理

Pod

  • 複数のコンテナをまとめたもの
  • アプリケーションデプロイの単位
  • 適切にスケールできるように、役割の異なるものは別ポッドにすること
  • Podは必ず同じノード上にデプロイされる

ReplicaSet

  • Kubernetesクラスタ上であらかじめ指定された数のPodを作成/起動しておくこと
  • 何か問題が起きても、ここで指定した個数分Podが立ち上がるように動き続ける

Deployment

  • ReplicaSetの履歴を管理するもの
  • 定義されたレプリカの数を維持する役目を負うのがReplicaSet
  • ReplicaSetの作成や更新を定義するのがDeployment

Service

  • K8sのネットワークを管理する機能
  • Podに対して、外部からアクセスするときに必要。
  • Load Balancerは、Serviceに対応するIPアドレス+ポート番号にアクセスすると、複数のPodに対するレイヤー4レベルの負荷分散をする
    • トランスポートレイヤー
    • Borgとかと同じ話かな
  • Cluster IP => クラスタ内のPod同士で通信するためのプライベートIPアドレス
  • External IP => 外部のクライアントから接続するためのパブリックIPアドレス

K8sの構成要素

マスター

データストア etcd

クラスタ構成を保持するKVS

Node

  • 実際にDockerコンテナを動作させるサーバ
  • kubelet というエージェントが動いてる
  • kubeletは、Podの定義ファイルに従ってDockerコンテナを実行したり、ストレージをマウントしたりする
  • ノードのステータスを監視して、APIサーバーに通知する機能も持つ

manifestファイル

  • k8sでは、クラスタの構成情報をYAMLまたはJSONで記述する
  • この定義ファイルをmanifestファイルと呼ぶ

docker-compose.yml とか task definitionを思い出すなぁ。

Local環境のアプリケーションに対してAzure ADでOpenID Connectの認証をしてみる (その2)

TL;DR

  • Azure ADでOpenID Connectの認証ができるか確認をした
  • 確認環境は森岡がテスト用に作ったアプリケーション
  • 上記環境はLocal環境で動いていて、Dockerで構成されている
  • lua-resty-openidcを使ってnginxレイヤーだけで認証ができた
  • まだ本番への反映をしていないので、完成度は30%くらい
    • sessionが切れたときに、/login に強制的にredirectさせる方法
    • dockerでない環境での反映手順も考えられていない
  • Azure AD側にアプリケーションを登録しなければ使えないので、ある程度セキュアではなかろうか

Azure ADの設定

Azure AD側の設定は、基本的にAzure AD公式ドキュメントの方法に従う。

  • Azure Potalにサインインする
  • Azure Active Directoryからアプリの登録を行う
  • サインオンURLの設定をする
    • 今回はlocalで確認するので http://127.0.0.1:8080 とした
  • アプリケーションのプロパティから、アプリケーションIDを確認し控えておく
  • 「キー」から鍵を作成して控えておく
  • このアプリケーションにアクセス可能な人をAzure AD上で設定しておく

f:id:selmertsx:20180710140021p:plain

アプリの登録

f:id:selmertsx:20180710140036p:plain

鍵の登録

実装

Docker Build

今回、サクッと確認するためにDockerで環境を構築。 nginxのlua pluginでOIDCができるやつがいたので、こいつを利用させて貰う。

FROM openresty/openresty:1.13.6.2-0-centos
ADD conf.d/app.conf /etc/nginx/conf.d/app.conf
ADD nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
ADD src /usr/local/openresty/nginx/src
RUN opm install zmartzone/lua-resty-openidc
CMD ["/usr/bin/openresty", "-g", "daemon off;"]

openrestyのdocker imageには、opm(openresty package manager)がデフォルトで入っているので、そのopmを使ってlua-resty-openidcをinstallすることができる。

証明書の設定

luasslを利用する際は、lua_ssl_trusted_certificate ディレクティブに証明書の設定をする必要がある。この証明書だけれども、実はopenrestyのdocker imageの中にデフォルトで入っているので、今回はそれを利用する。

➜  pomodoro git:(master) ✗ docker exec -it pomodoro-web /bin/bash
[root@bba9dae7baca /]# ls -al /etc/ssl/certs/
total 8
drwxr-xr-x 2 root root 4096 Apr  2 18:38 .
drwxr-xr-x 5 root root 4096 Apr  2 18:38 ..
lrwxrwxrwx 1 root root   49 Apr  2 18:38 ca-bundle.crt -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
lrwxrwxrwx 1 root root   55 Apr  2 18:38 ca-bundle.trust.crt -> /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt

これをnginxの設定に記載して終了。実際のコードはここ を参照

Luaコードの設定

-- https://github.com/selmertsx/pomodoro/blob/master/docker/nginx/src/test.lua
local opts = {
  redirect_uri_path = "/",
  discovery = os.getenv("DISCOVERY"),
  client_id = os.getenv("CLIENT_ID"),
  client_secret = os.getenv("CLIENT_SECRET"),
}

local res, err = require("resty.openidc").authenticate(opts)

if err then
  ngx.status = 500
  ngx.say(err)
  ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

ngx.req.set_header("X-USER", res.id_token.sub)

環境変数の渡し方

discovery, client_id, client_secretはシークレットな情報なので環境変数で渡す。 nginxでは環境変数luaに渡すためには、env directiveを利用する必要がある。

The NGINX environment variable is used internally by nginx and should not be set directly by the user.

公式ドキュメントには上記のように記載されているので、nginx.confの一番上でenv directiveを利用する。

worker_processes  1;
env DISCOVERY;
env CLIENT_ID;
env CLIENT_SECRET;
events {
  worker_connections  1024;
}

なお CLIENT_IDやCLIENT_SECRETはAzure AD設定時に取得したアプリケーションIDや鍵を設定すれば良い。

環境変数DISCOVERYの設定

discovery urlの取得方法については、公式ドキュメントに記載されている通りであるが、少しばかりハマりポイントがあるので解説。ここだけはちゃんと読んでほしい。

  • https://login.microsoftonline.com/{tanent_name}/.well-known/openid-configuration でアクセスし、tanent_idを取得
  • https://login.microsoftonline.com/{tanent_id}/.well-known/openid-configuration の文字列をnginxに設定する

上記設定の理由

ここは興味があれば見るくらいで良い。

まず前提として、Azure ADにおいて、Discoveryは下記2つのフォーマットで取得することができる

  1. https://login.microsoftonline.com/{tanent_name}/.well-known/openid-configuration
  2. https://login.microsoftonline.com/{tanent_id}/.well-known/openid-configuration

lua-resty-openidcを利用する場合、2番のフォーマットでDiscoveryを指定しなければならない。その理由は、lua-resty-openidcの実装上の問題である。上記ライブラリにおいて、openidcの認証は下記のような実装になっている。

-- https://github.com/zmartzone/lua-resty-openidc/blob/master/lib/resty/openidc.lua#L469-L509
      ngx.log(ngx.DEBUG, "response data: "..res.body)
      json, err = openidc_parse_json_response(res)
      if json then
        if string.sub(url, 1, string.len(json['issuer'])) == json['issuer'] then
          openidc_cache_set("discovery", url, cjson.encode(json), exptime or 24 * 60 * 60)
        else
          err = "issuer field in Discovery data does not match URL"
          ngx.log(ngx.ERR, err)
          json = nil
        end
      end

DiscoveryのURLと、discovery urlから返されるissuerのURLの一部が一致しているか見ている。Discoveryから得られるissuerのURLは、https://sts.windows.net/{tanent_id}/ という値になる。そのため、tanent_nameでURLを指定すると一致しないという問題が起きる。よって、Discovery取得用のURLは、tanent_idで指定する必要がある。

認証結果

http://127.0.0.1:8080/test にアクセスすると下記のページにredirectされる

f:id:selmertsx:20180710135840p:plain

認証が終わるとこんな感じ

f:id:selmertsx:20180710135916p:plain

lua-nginx-moduleをdockerで動かす

TL;DR

  • imageの指定方法は、下記のフォーマット
    • openresty/openresty:<openresty-version>-<image-version>-<flavor>
    • flavorとはosのことでcentos, alpine などが入る
    • 今回はこんな感じになった openresty/openresty:1.13.6.2-0-centos
  • 上記方法でイメージを作れば、すぐにluaを実行可能

github.com

設定方法

nginxでluaを実行するために必要な部分のみ抜粋。全体は下記のurlから探してほしい。

https://github.com/selmertsx/pomodoro/blob/29872473c7cbc6c6cbf1fe27bc8d9a9434ae80ba/docker-compose.yml#L43-L52

docker-compose.yml

volumesで自分の手元のnginx設定をcontainerにマウントした。

version: '3'
services:
  nginx:
    build: ./docker/nginx
    container_name: pomodoro-web
    image: pomodoro-web
    volumes:
      - ./docker/nginx/conf.d:/etc/nginx/conf.d
    ports:
      - 8080:80

Dockerfile

手元のnginx設定をaddしている。 この設定ファイルはdocker-composeでmountしているから、開発環境ではいらないかも。

FROM openresty/openresty:1.13.6.2-0-centos
ADD conf.d/app.conf /etc/nginx/conf.d/app.conf
CMD ["/usr/bin/openresty", "-g", "daemon off;"]

nginx app.conf

普通に hello world

server {
  listen 80;
  server_name localhost; 
  keepalive_timeout 5;
  location /hellolua {
    content_by_lua '
        ngx.header["Content-Type"] = "text/plain";
        ngx.say("hello world");
    ';
  }
}

実行確認

➜  pomodoro git:(master) ✗ curl http://127.0.0.1:8080/hellolua
hello world

ということで、問題なく動作していることを確認したぞ!!

Local環境のアプリケーションに対してAzure ADでOpenID Connectの認証をしてみる (その1)

Motivation

Azure ADをIDaaSとして、社内サービスと連携したい。 弊社の社内サービスはPHPJavaRubyと多種多様な言語で書かれており、 またインフラもGCP,AWSと利用されているので、 それらすべてで動くようにnginxレイヤーでIDaaS連携をするようにする必要がある。 ということで、今回はnginxでIDaaS連携ができるライブラリを調査することにする。

AWS のみならば、ALBレイヤーでAzure ADと連携することが可能である。 社内サービスがAWSのみであれば、これを利用するのが最も楽だと思う。

Application Load Balancer 組み込み認証によりログインを簡略化 | Amazon Web Services ブログ

OpenID ConnectとSAML

Azure ADにおいてフェデレーションアクセスをする際のプロトコルとして、OpenID ConnectとSAMLが存在する。 SAMLはIdP側だけでなくSP側もメタデータの登録などが必要であり、設定コストが非常に高い。 そのためOpenID Connectで、求める水準のID管理が出来るのであれば、それにこしたことはない。 なので、一旦OpenID Connectでどこまでできるのか検証を進めていく。

用語の確認

OpenID Connect

  • RP (Relying Party) : SSO対象のアプリケーション
  • OP (OpenID Provider ) : IDの認証を行う機能を有するサーバー

その他、OpenID Connectに関する基礎的な知識は、下記URLを参照。

OpenID Connectまとめ - selmertsxの素振り日記

SAML (Security Assertion Markup Language)

  • SP (Service Provider) : SSO対象のアプリケーション. OpenID Connectで言うRP
  • IdP (Identity Provider) : IDの認証を行うサーバー. OpenID Connetで言うOP

nginx library

github.com

OpenID ConnectのRPに使うための nginx lua library. OpenID Connect DiscoveryとAuthorization code flowを使って、OPとユーザー認証を行う。 セッションはブラウザのcookieか、redis, memcacheで持つ。

使い方

local opts = {
  redirect_uri_path ="",
  discovery = ""
  -- ... その他args
}

local res, err = require("resty.openidc").authenticate(opts)

if err then
  ngx.status = 500
  ngx.say(err)
  ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

こんな感じ。opsに必要なパラメータを入れた後、require("resty.openidc").authenticate(opts) で認証を実行する。 どんなパラメータが必要なのかはAzure ADと連携するときにでも諸々確認していく

現状の懸念点

  • OpenID Connectで認証した場合、IDaaSでは認証はできるが認可はできないのではないだろうか

www.slideshare.net