OneloginでRedashのSAML設定


f:id:cloudfish:20200629103518p:plain
前回に続いてOneloginネタになります。社内ツールとしてデータの可視化にRedashを使っていますので、今回はOneloginとRedashをSAML連携させてみました。

Redashの構築

まずはRedashを構築しましょう。Redash公式でAMIを用意してくれていますので今回はそれを使います。

構成図

構成については、通常のELB + EC2(Redash)で構築します。
f:id:cloudfish:20200620172432p:plain

ELB

今回は検証のため簡単な構成とするためELBは80番ポートで受けてそのまま80番でインスタンスに流します。本番で使うときはSSLを使うことを検討してください。

Redash

ブログ執筆時点の東京リージョンでのAMIはami-060741a96307668beになりますので、これを起動します。
各リージョンで提供されているAMIは以下を参照してください。正常に起動できればELBにアタッチしておいてください。
redash.io

NATが用意されているのであれば、SSMも使えるのでプライベートサブネットで起動する方がセキュアだと思います。

Onelogin側でSAML設定

「Application」から「Add App」をクリックし、「SAML Test Connector (IdP w/ attr w/ sign response)」を選択します。
Display Nameを入力しSaveします。
f:id:cloudfish:20200620180259p:plain

Configuration

Recipient、ACS (Consumer) URL Validator、ACS (Consumer) URLに以下を設定します。
http://ELB_DNS/saml/callback?org_slug=default

f:id:cloudfish:20200620201751p:plain

Parameter

カスタムパラメータとしてFirstNameとLastNameを追加します

FirstName

f:id:cloudfish:20200620202340p:plain:w300

LastName

f:id:cloudfish:20200620202458p:plain:w300

Metadataの取得

「More Actions」の「SAML Metadata」を右クリックでリンク先のURLをコピーして控えたうえでMetadataをダウンロードする。
f:id:cloudfish:20200621154430p:plain:w300
ダウンロードしたMetadataを開いてentityIDとNameIDFormatの値を控えておきます。

RedashのSAML設定

管理者でSettingから以下の設定を行う。

SAML Enabled チェック
SAML Metadata URL metadataのURLをセット
SAML Entity ID metadata内のentityIDをセット
SAML NameID Format metadata内のNameIDFormatをセット

f:id:cloudfish:20200621155329p:plain:w300

ログイン確認

設定完了後にSAMLでログインすると、以下のようなエラーが発生します。
f:id:cloudfish:20200622120958p:plain:w300

コンテナのログを確認すると以下のようなエラーが発生していました。

server_1            | [2020-06-22 03:08:51,313][PID:9][INFO][saml2.entity] HTTP REDIRECT
server_1            | [2020-06-22 03:08:51,314][PID:9][INFO][metrics] method=GET path=/saml/login endpoint=saml_auth_sp_initiated status=302 content_type=text/html; charset=utf-8 content_length=1723 duration=441.55 query_count=1 query_duration=1.04
nginx_1             | 139.101.233.32 - - [22/Jun/2020:03:08:51 +0000] "GET /saml/login?next=%2Fsettings%2Forganization HTTP/1.1" 302 1723 "http://ec2-54-249-199-98.ap-northeast-1.compute.amazonaws.com/login?next=http%3A%2F%2Fec2-54-249-199-98.ap-northeast-1.compute.amazonaws.com%2Fsettings%2Forganization" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" "-"
server_1            | [2020-06-22 03:08:53,456][PID:10][INFO][saml2.response] status: <?xml version='1.0' encoding='UTF-8'?>
server_1            | <ns0:Status xmlns:ns0="urn:oasis:names:tc:SAML:2.0:protocol"><ns0:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /></ns0:Status>
server_1            | [2020-06-22 03:08:53,458][PID:10][ERROR][saml2.client_base] XML parse error: Signature missing for assertion
server_1            | [2020-06-22 03:08:53,459][PID:10][ERROR][saml_auth] Failed to parse SAML response
server_1            | Traceback (most recent call last):
server_1            |   File "/app/redash/authentication/saml_auth.py", line 73, in idp_initiated
server_1            |     entity.BINDING_HTTP_POST)
server_1            |   File "/usr/local/lib/python2.7/site-packages/saml2/client_base.py", line 702, in parse_authn_request_response
server_1            |     binding, **kwargs)
server_1            |   File "/usr/local/lib/python2.7/site-packages/saml2/entity.py", line 1170, in _parse_response
server_1            |     response = response.verify(keys)
server_1            |   File "/usr/local/lib/python2.7/site-packages/saml2/response.py", line 1018, in verify
server_1            |     if self.parse_assertion(keys):
server_1            |   File "/usr/local/lib/python2.7/site-packages/saml2/response.py", line 930, in parse_assertion
server_1            |     if not self._assertion(assertion, False):
server_1            |   File "/usr/local/lib/python2.7/site-packages/saml2/response.py", line 781, in _assertion
server_1            |     raise SignatureError("Signature missing for assertion")
server_1            | SignatureError: Signature missing for assertion
server_1            | [2020-06-22 03:08:53,465][PID:10][INFO][metrics] method=POST path=/saml/callback endpoint=saml_auth_idp_initiated status=302 content_type=text/html; charset=utf-8 content_length=219 duration=560.91 query_count=1 query_duration=1.02

エラーでググってみたところ以下のような対処方法が見つかりましたのでソースを修正します。
stackoverflow.com

Redashの修正

上記のエラーを回避するためソースを修正する必要があります。そのため、Redashコンテナのイメージを作り直します。

ソースの取得

まずは、Redash用サーバーにsshログインします。公式AMIはv8.0.0がベースになっていますので、v8系のソースを取得します。以下のコマンドでv8.0.2をが取得できます。

git clone https://github.com/getredash/redash.git
git checkout a16f551e22c6288df6f067aa12caa5afd9a8f1dd

saml_auth.pyの修正

以下のソースを修正します。

/redash/redash/authentication/saml_auth.py

以下のオプションをTrueからFalseに修正してください。

'want_assertions_signed': False,

コンテナのビルド

インスタンスタイプがt2.smallだとビルドが途中で失敗しました。t2.mediumかt2.largeくらいあった方がいいかもしれません。

docker build -t redash_onelogin .

docker-composeの修正

以下のファイルのdockerイメージを修正します。
/opt/redash/docker-compose.yml

version: "2"
x-redash-service: &redash-service
  #image: redash/redash:8.0.0.b32245
  image: redash_onelogin
  depends_on:
    - postgres
    - redis
  env_file: /opt/redash/env
  restart: always
services:
  server:
    <<: *redash-service
    command: server
    ports:
      - "5000:5000"
    environment:
      REDASH_WEB_WORKERS: 4
  scheduler:
    <<: *redash-service
    command: scheduler
    environment:
      QUEUES: "celery"
      WORKERS_COUNT: 1
  scheduled_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "scheduled_queries,schemas"
      WORKERS_COUNT: 1
  adhoc_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "queries"
      WORKERS_COUNT: 2
  redis:
    image: redis:5.0-alpine
    restart: always
  postgres:
    image: postgres:9.6-alpine
    env_file: /opt/redash/env
    volumes:
      - /opt/redash/postgres-data:/var/lib/postgresql/data
    restart: always
  nginx:
    image: redash/nginx:latest
    ports:
      - "80:80"
    depends_on:
      - server
    links:
      - server:redash
    restart: always
||< 

以下のコマンドで一旦ストップさせてコンテナを再起動させます。
>|csh|
docker-compose stop
docker-compose up -d

ログイン確認

再度ログイン確認したところ無事ログインできました。
f:id:cloudfish:20200622121830p:plain:w300
f:id:cloudfish:20200622121800p:plain:w400

まとめ

RedashのSAML連携は簡単にできそうでしたが、意外とハマりどころも多く、またOneloginの設定方法もわかっていなかったので思ったより時間がかかりました。もし同じような組み合わせで検討されているようであれば参考にしていただけたらと思います。