本日も乙

ただの自己満足な備忘録。

Spinnaker で Google OAuth 認証によるログイン機能を有効化する

久しぶりの Spinnaker ネタです。
Spinnaker をインストールして、ブラウザから GUI を見るとき、以下のようにポートフォワードしていたかと思います。

$ gcloud compute ssh dev-spinnaker -- -L 9000:localhost:9000 -L 8084:localhost:8084

外部から見れないのでセキュアなのですが、毎回コマンド打つのが面倒ですし、複数人だとこの方法は使えません。
そこで本記事は nginx でリバースプロキシを設定し、Spinnaker 画面を見れるようにします。さらに Google OAuth 認証を設定することで、Google アカウントでログインできるようにします。

構成

https://spinnaker.example.com でアクセスして、Google アカウント認証できるようにします。
そのためには以下の設定を行います。

  • GCLB ・・・ マネージド SSL/TLS 証明書を設定するため
  • マネージドSSL/TLS証明書 ・・・ GCP から提供されている無料の証明書
  • nginx ・・・ リバースプロキシとして、Spinnaker にリクエストを流す
  • Google OAuth
  • Spinnaker ・・・ Google OAuth の設定を有効化する

では、順にやっていきます。

GCLB の作成

作成方法は以下の記事をご参照ください。本記事では GCLB が作成されているとして進めます。

blog.jicoman.info

SSL/TLS 証明書の設定

GCP から提供されているマネージドの SSL/TLS 証明書を設定します。設定方法は以下の記事をご参照ください。

blog.jicoman.info

nginxのインストール、設定

リバースプロキシとなる nginx を入れます。

% export REPO="$(lsb_release -c -s)"
% cat <<EOF>/etc/apt/sources.list.d/nginx.list
deb http://nginx.org/packages/ubuntu/ $REPO nginx
deb-src http://nginx.org/packages/ubuntu/ $REPO nginx
EOF

% curl http://nginx.org/keys/nginx_signing.key | apt-key add -
% apt-get update
% apt-get install nginx
% nginx -V
nginx version: nginx/1.14.2
built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
built with OpenSSL 1.0.2g  1 Mar 2016
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

設定はこんな感じにします。spinnaker.conf は Spinnaker の GitHub issue にあるものを参考にしました。

# /etc/nginx/nginx.conf
user  nginx;
worker_processes  <CPUコア数>;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    set_real_ip_from 130.211.0.0/22;
    set_real_ip_from 35.191.0.0/16;
    # ip addr of gclb
    set_real_ip_from <ロードバランサのIPアドレス>;
    real_ip_header   X-Forwarded-For;
    real_ip_recursive on;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush      on;

    keepalive_timeout  65;

    gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
# /etc/nginx/conf.d/spinnaker.conf
upstream deck {
    server 127.0.0.1:9000 fail_timeout=3;
}

upstream gate {
    server 127.0.0.1:8084 fail_timeout=3;
}

server {
    listen       80 default;

    server_name  spinnaker.crwdwork.com;

    access_log  /var/log/nginx/spinnaker.log  main if=$log_ua;

    location /login {
        add_header ServerHostname $hostname;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass_header Server;
        proxy_redirect off;

        # We match = "http" rather than != "https" because we don't want it
        # to redirect if you're running docker locally.  And '=', not '=='
        # because nginx.
        if ($http_x_forwarded_proto = "http") {
            rewrite ^(.*)$ https://$http_host$1 permanent;
        }

        proxy_pass http://gate/login;
    }

    location /auth/redirect {
         rewrite ^(.*)$ https://$http_host permanent;
    }

    location ~ /gate/(?<gate_path>.+) {
        add_header ServerHostname $hostname;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass_header Server;
        proxy_redirect off;

        proxy_pass http://gate/$gate_path$is_args$args;
    }

    location / {
        add_header ServerHostname $hostname;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass_header Server;
        proxy_redirect off;

        # We match = "http" rather than != "https" because we don't want it
        # to redirect if you're running docker locally.  And '=', not '=='
        # because nginx.
        if ($http_x_forwarded_proto = "http") {
            rewrite ^(.*)$ https://$http_host$1 permanent;
        }

        proxy_pass http://deck;
    }
}
% nginx -t
% systemctl enable nginx.service
$ systemctl start nginx.service

Google アカウント認証

Google OAuth の設定

https://console.developers.google.com/apis/credentials に飛んで、GCPプロジェクトを選択します。
「OAuth同意画面」タブをクリックし、下図のように設定していきます。

google-oauth

認証情報を作成 -> OAuthクライアントIDを選択します。

google-oauth

「承認済みのリダイレクト URI」で https://spinnaker.example.com/login を指定します。

google-oauth

作成すると、クライアントIDとクライアントシークレットが表示されるので控えておいてください。

google-oauth

Spinnaker の設定

$ hal config security authn oauth2 edit \
    --pre-established-redirect-uri https://spinnaker.example.com/login

$ hal config security ui edit \
    --override-base-url https://spinnaker.example.com

$ hal config security api edit \
    --override-base-url https://spinnaker.example.com/gate

# 先ほど控えたクライアントIDとクライアントシークレットを利用する
$ CLIENT_ID=xxxxxxxxxx
$ CLIENT_SECRET=XXXXXXXXXXX
$ PROVIDER=google
$ hal config security authn oauth2 edit \
  --client-id $CLIENT_ID \
  --client-secret $CLIENT_SECRET \
  --provider $PROVIDER
$ hal config security authn oauth2 enable
# ~/.hal/default/profiles/gate-local.yml
server:
  tomcat:
    protocolHeader: X-Forwarded-Proto
    remoteIpHeader: X-Forwarded-For
    internalProxies: .*
    httpsServerPort: X-Forwarded-Port

デプロイ

$ sudo hal deploy apply
$ sudo systemctl daemon-reload

動作確認

https://spinnaker.example.com にアクセスして Google ログイン画面が表示され、ログイン後TOPページに遷移できれば完了です。

参考