docker部署ory hydra

发布于 2022-05-23  1,009 次阅读


我为什么总是浪费时间部署一些我用不到的东西。

ory hydra主页
Github地址

Ory Hydra是一个以性能为重点的Oauth2.0以及OIDC服务,与传统的full stack IAM不同,Hydra不处理或储存identity。

文档比较难理解,也有点小错误,文档也没有提供mariadb的选项,而且似乎对mariadb某些版本支持不佳,姑且是用了mysql,记录一下部署步骤。

官方提供了一个5 Minute Tutorial,可以用来熟悉一下服务的功能。

配置主要来自Run Ory Hydra in Docker

部署服务

docker-compose.yml主要参考官方提供的quickstart.yml以及quickstart-mysql.yml

version: '3.7'
services:
  hydra:
    image: oryd/hydra:v1.11.8
    container_name: hydra
    ports:
      - "127.0.0.1:3000:4444" # Public port
      - "127.0.0.1:3001:4445" # Admin port
    volumes:
        - ./hydra.yml:/etc/config/hydra/hydra.yml
    command: serve -c /etc/config/hydra/hydra.yml --sqa-opt-out all
    environment:
      - DSN=mysql://root:xxxxxxxxxxxx@tcp(hydra-db:3306)/mysql?max_conns=20&max_idle_conns=4
    restart: unless-stopped
    depends_on:
      - hydra-migrate
      - hydra-db
    networks:
      - external_network
      - internal_network
    stdin_open: true # docker run -i
    tty: true        # docker run -t
  hydra-token:
    image: oryd/hydra:v1.11.8
    container_name: hydra-token
    ports:
      - "127.0.0.1:3002:5555" # Port for hydra token user
    volumes:
        - ./hydra.yml:/etc/config/hydra/hydra.yml
    command: token user --skip-tls-verify --port 5555 --auth-url https://example.com/public/oauth2/auth --token-url https://example.com/public/oauth2/token --redirect https://example.com/callback --client-id hydra-login-consent-node --client-secret xxxxxxxxxxxx --scope openid,offline,photos.read
    environment:
      - DSN=mysql://root:xxxxxxxxxxxx@tcp(hydra-db:3306)/mysql?max_conns=20&max_idle_conns=4
    restart: unless-stopped
    depends_on:
      - hydra-migrate
      - hydra-db
      - hydra
    networks:
      - external_network
      - internal_network
    stdin_open: true # docker run -i
    tty: true        # docker run -t
  hydra-migrate:
    image: oryd/hydra:v1.11.8
    container_name: hydra-migrate
    volumes:
        - ./hydra.yml:/etc/config/hydra/hydra.yml
    environment:
      - DSN=mysql://root:xxxxxxxxxxxx@tcp(hydra-db:3306)/mysql?max_conns=20&max_idle_conns=4
    command: migrate -c /etc/config/hydra/hydra.yml sql -e --yes
    restart: on-failure
    depends_on:
      - hydra-db
    networks:
      - external_network
      - internal_network
  consent:
    environment:
      - HYDRA_ADMIN_URL=https://hydra.stsecurity.moe/private
    image: oryd/hydra-login-consent-node:v1.11.8
    container_name: hydra-consent
    ports:
      - "127.0.0.1:3003:3000"
    restart: unless-stopped
    networks:
      - external_network
      - internal_network
  hydra-db:
    image: mysql:5.7
    container_name: hydra-db
    volumes:
        - ./mysql_data:/var/lib/mysql
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=xxxxxxxxxxxx
    networks:
      - internal_network
networks:
  external_network:
  internal_network:
    internal: true

这里需要注意的是,hydra-token和consent服务都是测试用的服务,实际运行时并不需要,hydra-token需要有client,所以在完成下文的创建client步骤前直接注释掉就可以。

创建配置文件hydra.yml,修改自hydra.yml,具体可以参考官方文档或者使用文档里提供的configuration-editor

serve:
  cookies:
    same_site_mode: Lax

urls:
  self:
    public: https://example.com/public
    issuer: https://example.com/public
  consent: https://example.com/consent
  login: https://example.com/login
  logout: https://example.com/logout

secrets:
  system:
    - xxxxxxxxxxxxxxxxxxxxxxxxxx

oidc:
  subject_identifiers:
    supported_types:
      - pairwise
      - public
    pairwise:
      salt: xxxxxxxxxxxxx

配置反代,很多路径需要转发到不同的端口,并且可能需要重写路径,我的相关配置:

  location /public/ {
    rewrite ^/public(.*)$ $1 break;
    try_files $uri @publicproxy;
  }

  location /private/ {
    rewrite ^/private(.*)$ $1 break;
    try_files $uri @privateproxy;
  }

  location /consent {
    try_files $uri @consentproxy;
  }

  location / {
    try_files $uri @proxy;
  }

  location /login {
    try_files $uri @consentproxy;
  }

  location /logout {
    try_files $uri @consentproxy;
  }

  location /callback {
    try_files $uri @tokenproxy;
  }

  location /token {
    rewrite ^/token(.*)$ $1 break;
    try_files $uri @tokenproxy;
  }

  location @proxy {
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_pass https://localhost:3001;

  }

  location @publicproxy {
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_pass https://localhost:3000;

  }

  location @privateproxy {
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_pass https://localhost:3001;

  }

  location @tokenproxy {
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_pass http://localhost:3002;

  }

  location @consentproxy {
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_pass http://localhost:3003;

  }

全部配置完成后可以docker-compose up -d启动服务。

运行服务后访问https://example.com/private/health/ready 可以查看服务是否正常运行。

创建client

运行以下命令创建client

docker-compose run --rm \
hydra \
clients create --skip-tls-verify  \
--endpoint https://example.com/private \
--id hydra-login-consent-node \
--secret G58KziJj98ZEiUg9 \
--grant-types authorization_code,refresh_token,client_credentials,implicit \
--response-types token,code,id_token \
--scope openid,offline,photos.read \
--callbacks https://example.com/callback

创建完client之后可以去掉hydra-token服务的注释并运行hydra-token。

进行Oauth2.0测试

根据之前的配置,访问https://example.com/token/ 并按提示操作即可,如果一切正常即可在最后收到token。

一些问题

client sent an http request to an https server

反代到容器的链接不是https导致的,token和consent只是测试用,没有必要https,public和private的反代路径需要用https。

invalid character 'C' looking for beginning of value on command "hydra clients create"

原因是hydra收到的回复不是json,应该是endpoint设置有问题。

--skip-tls-verify

测试环境因为hydra的用了自签发证书才使用此命令,如果用于生产环境需要去掉这条。


Sup