DockerでAuthentikをデプロイ:SSO、MFA、ユーザープロビジョニング対応のセルフホスト型IDプロバイダー

Security tutorial - IT technology blog
Security tutorial - IT technology blog

クイックスタート:5分でAuthentikをデプロイする

社内の多数のダッシュボード、ステージング環境、カスタマーポータルごとに個別の認証情報を管理していると、パスワードの乱立を招きます。また、チームメンバーが退職するたびにエンジニアのリソースが消費されます。Authentikは、OpenID Connect(OIDC)、SAML 2.0、フォワードプロキシ認証、および組み込みLDAPアウトポストをサポートする統合IDプロバイダー(IdP)として機能し、この課題を解決します。

最大500人のアクティブユーザーを持つチームであれば、2 vCPU・4 GB RAM程度の一般的なVPSでAuthentikスタック全体を快適に運用できます。以下に、Docker Composeを使用してUbuntuまたはDebian上で起動する手順を示します。

1. ディレクトリと環境変数の準備

mkdir -p /opt/authentik && cd /opt/authentik

# シークレットキーとデータベース認証情報を生成
PG_PASS=$(openssl rand -base64 36 | tr -d '\n')
AUTH_SECRET=$(openssl rand -base64 60 | tr -d '\n')

cat <<EOF > .env
PG_PASS=${PG_PASS}
AUTHENTIK_SECRET_KEY=${AUTH_SECRET}
AUTHENTIK_ERROR_REPORTING__ENABLED=false
AUTHENTIK_PORT_HTTP=9000
AUTHENTIK_PORT_HTTPS=9443
EOF

ルートデータベースの認証情報や管理者サービストークンには、簡易なコマンドライン生成ツールや信頼性の低いオンラインツールの使用を避けてください。本番環境の機密シークレットには、toolcraft.app/ja/tools/security/password-generator のパスワードジェネレーターを使用しています。ブラウザのクライアントサイドで動作し、ネットワーク経由で文字列を送信しないため、64文字の高エントロピーなシークレットを安全かつ迅速に生成できます。

2. Composeファイルの定義

# docker-compose.yml
services:
  postgresql:
    image: docker.io/library/postgres:16-alpine
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 5s
    volumes:
      - database:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: ${PG_PASS}
      POSTGRES_USER: authentik
      POSTGRES_DB: authentik
    env_file:
      - .env

  redis:
    image: docker.io/library/redis:alpine
    command: --save 60 1 --loglevel warning
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 3s
    volumes:
      - redis:/data

  server:
    image: ghcr.io/goauthentik/server:2024.8.3
    restart: unless-stopped
    command: server
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
    volumes:
      - ./media:/media
      - ./custom-templates:/templates
    env_file:
      - .env
    ports:
      - "${AUTHENTIK_PORT_HTTP}:9000"
      - "${AUTHENTIK_PORT_HTTPS}:9443"
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy

  worker:
    image: ghcr.io/goauthentik/server:2024.8.3
    restart: unless-stopped
    command: worker
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
    volumes:
      - ./media:/media
      - ./custom-templates:/templates
      - /var/run/docker.sock:/var/run/docker.sock
    env_file:
      - .env
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy

volumes:
  database:
    driver: local
  redis:
    driver: local

3. 起動と初期セットアップ

docker compose pull
docker compose up -d

ブラウザを開き、http://<サーバーのIPアドレス>:9000/if/flow/initial-setup/ にアクセスします。セットアップウィザードが表示されるので、メインの管理者アカウント(akadmin)を設定し、マスターリカバリーパスワードを登録してください。

アーキテクチャ、フロー、コアメカニズム

課題:認証のサイロ化

開発チームは多くの場合、混在した環境で運用を行っています。GrafanaやNextcloudのような最新ツールが、レガシーなセルフホスト型ユーティリティと並行して稼働しています。各ツールが個別のローカルユーザーデータベースを保持していると、アカウントの同期が困難になります。従業員が退職しても、社内ダッシュボードへのアクセス権が数週間にわたって放置される事態が頻発します。

根本的なボトルネック

ツールによって要求される認証プロトコルは異なります。モダンなクラウドアプリはOIDC経由のJSON Web Tokensを前提とし、エンタープライズ製品群はSAML 2.0アサーションを要求します。また、古いネットワークストレージやVPNアプライアンスは直接のLDAPバインドにしか対応していません。Authentikは、これら3つの橋渡しを行う変換レイヤーとして機能します。

Authentikの実行パイプライン

Authentikは、すべてのログイン試行を3つのモジュール化された概念を通じて処理します。

  1. Stages(ステージ): パスワードの入力要求、WebAuthnプロンプトの表示、メール検証コードの送信など、単一のアクションステップ。
  2. Flows(フロー): 認証、登録、リカバリー時に実行されるステージの順序付きシーケンス。
  3. Bindings & Policies(バインディングとポリシー): ステージやアプリケーションにアクセス可能かどうかを判定するルール。グループ所属、IPサブネット、GeoIPの位置情報に基づいて適用できます。
flowchart LR
    User[クライアントブラウザ] -->|1. 認証リクエスト| App[サービス / アプリ]
    App -->|2. リダイレクト / OIDC認証| Authentik[Authentik IdP]
    subgraph Pipeline [Authentikパイプラインエンジン]
        Authentik --> Flow[認証フロー]
        Flow --> MFA[MFAステージポリシー]
        MFA --> ClaimMapper[スコープ / クレームマッピング]
    end
    ClaimMapper -->|3. JWT / トークン発行| App
    App -->|4. 認証済みセッション| User

OIDC統合、MFA強制、およびアウトポスト

1. アプリケーションの接続(OIDC経由のGrafana)

まず、Authentikの管理インターフェースで Applications > Providers > Create を開き、OAuth2/OIDCプロバイダーを作成します。

  • Name: Grafana OIDC
  • Authorization Flow: default-provider-authorization-implicit-consent
  • Client Type: Confidential
  • Redirect URI: https://grafana.example.com/login/generic_oauth

次に、grafana.ini 設定ファイル内で認証情報をマッピングします。

[auth.generic_oauth]
enabled = true
name = Authentik
client_id = YOUR_AUTHENTIK_CLIENT_ID
client_secret = YOUR_AUTHENTIK_CLIENT_SECRET
scopes = openid email profile
auth_url = https://auth.example.com/application/o/authorize/
token_url = https://auth.example.com/application/o/token/
api_url = https://auth.example.com/application/o/userinfo/
role_attribute_path = contains(groups[*], 'Grafana Admins') && 'Admin' || 'Editor'

2. フローポリシーによる動的MFAの強制

一般ユーザーの利便性を損なうことなく、機密性の高いロールを持つユーザーに対してハードウェアセキュリティキー(FIDO2/WebAuthn)やTOTPアプリを必須に設定できます。

  1. Flows and Stages > Flows > default-authentication-flow に移動します。
  2. Authenticator Validation Stage を選択します。
  3. 次のPython式を使用して実行ポリシーをアタッチします。
# Authentik内のPythonポリシー
# ユーザーが「Infrastructure-Ops」に所属しているか、オフィスサブネット(10.0.0.0/8)の外部から接続している場合にMFAを要求

user_groups = [group.name for group in request.user.ak_groups.all()]
is_admin_group = "Infrastructure-Ops" in user_groups
is_external_ip = not request.http_request.META.get("REMOTE_ADDR", "").startswith("10.0.")

return is_admin_group or is_external_ip

3. LDAPアウトポスト経由でのレガシーシステム接続

旧式のネットワーク機器やレガシーアプリは、モダンなOAuthに対応していないことがよくあります。AuthentikのLDAPアウトポストはこのギャップを埋める役割を果たします。バックグラウンドでAuthentikのコアAPIと通信しながら、レガシークライアント向けに標準LDAPポートでリッスンします。

# スタンドアロンLDAPアウトポストコンテナをデプロイ
docker run -d \
  --name authentik-ldap-outpost \
  --restart unless-stopped \
  -p 389:3389 -p 636:6636 \
  -e AUTHENTIK_HOST=https://auth.example.com \
  -e AUTHENTIK_TOKEN=your_outpost_service_token \
  -e AUTHENTIK_INSECURE=false \
  ghcr.io/goauthentik/ldap:2024.8.3

トラブルシューティングと本番運用の堅牢化

  • リバースプロキシヘッダー: Nginx、Traefik、Caddyを使用している場合は、X-Forwarded-Proto $scheme と X-Forwarded-For $proxy_add_x_forwarded_for を転送してください。ヘッダーが欠落していると、リダイレクトループやOAuth状態(state)の無効エラーが発生します。
  • クロックドリフト: chrony や systemd-timesyncd を使用して、ホストの時刻を常に同期させてください。わずか15秒の時刻ズレでも、TOTPの検証失敗やJWTトークンの予期せぬ期限切れを引き起こします。
  • 自動データベーススナップショット: Authentikはすべてのフロー定義やトークンをPostgresに保存します。シンプルなcronタスクを設定し、24時間ごとにデータベースをバックアップしてください。
# 本番データベースのバックアップスナップショット
docker compose exec -T postgresql pg_dump -U authentik authentik | gzip > /opt/backups/authentik_$(date +%F_%T).sql.gz
Share: