跳转至

Traefik-sso-authelia

什么是 SSO?

单点登录(SSO)是一种身份验证解决方案,可让用户通过一次性用户身份验证登录多个应用程序和网站。鉴于当今的用户经常直接从其浏览器访问应用程序,因此组织正在优先考虑改善安全性和用户体验的访问管理策略。SSO 兼具这两方面的优点,因为一旦验证身份,用户就可以访问所有受密码保护的资源,而无需重复登录。

  • 几种双因素身份验证方法。
  • 注册第二因素设备时进行身份验证。
  • 自助重置用户密码。
  • 多次尝试后禁止帐户(称为监管)。

1. authelia 相关配置

什么是 authelia ?

Authelia是 Traefik 等反向代理的伴侣( 有关完整列表,请参阅支持的代理)。它可以被视为提供身份验证功能和登录门户的那些代理的扩展。

如下架构图所示,Authelia 直接连接到反向代理,但从未直接连接到应用程序后端,因此受保护 API 的客户端发送的有效负载永远不会到达 Authelia,只有身份验证部分会到达,例如授权标头例如。因此,受保护的 API 可以是 REST、GraphQL 或 HTTP 之上的任何其他类型的 API。

image-20240418104258243

authelia 的工作流程

配置反向代理,以便每个传入请求都会生成发送到 Authelia 的身份验证请求。 Authelia 做出响应,并指示反向代理允许传入请求通过,或者因为用户未经身份验证或没有充分授权而阻止它。

  • 当未经身份验证的用户的第一个请求到达反向代理时,Authelia 会确定该用户未经过身份验证,因为没有随请求一起发送会话 cookie。因此,Authelia 将用户重定向到 Authelia 本身提供的身份验证门户。然后,用户可以使用该门户执行身份验证工作流程,以获得对 Authelia 保护的域的所有子域有效的会话 cookie。

  • 当用户再次访问初始网站时,查询会与会话 cookie 一起发送,会话 cookie 在身份验证请求中转发到 Authelia。这次,Authelia 可以验证用户是否已通过身份验证,并命令反向代理让查询通过。

网站协议只能是 https

Authelia 仅适用于通过 HTTPS 提供服务的网站,因为会话 cookie 只能通过安全连接传输。

2. 部署 authelia

1. docker 部署 Authelia

1. 创建 Authelia 项目目录

1. 创建 Authelia 项目目录
...
mkdir -p /root/authelia/config
...

...
❯ tree authelia
authelia                        # 1. 创建 Authelia 项目数据文件夹
├── docker-compose.yml          # 2. 编写 compose.yml 文件
└── config                      
    ├── configuration.yml       # 3. 编写 configuration.yml 项目配置文件
    ├── users_database.yml      # 4. 编写 users_database.yml 用户数据文件
    └── create-user.sh          # 5. 编写 create-user.sh 创建用户脚本
...

2. 编写 compose 编排文件

2. 编写 /root/authelia/compose.yaml 文件
services:
  authelia:
    container_name: "${AUTHELIA_SERVICE_NAME:-authelia}"
    image: authelia/authelia:v4.38.0-beta3
    restart: unless-stopped
    labels:
      traefik.enable: true
      traefik.http.routers.authelia.entryPoints: https
    ports:
      - "9091:9091"
    user: "${AUTHELIA_RUN_USER:-2000:2000}"
    environment:
      TZ: "${TZ:-Australia/Melbourne}"
    volumes:
      - ./config:/config

3. 编写 configuration 配置

3. 编写 /root/authelia/config/configuration.yml 文件
theme: 'auto'

server:
  timeouts:
    read: '6 seconds'
    write: '6 seconds'
    idle: '30 seconds'
  buffers:
    read: 409600
    write: 409600

log:
  level: debug

telemetry:
  metrics:
    enabled: false

totp:
  disable: false
  issuer: huichengcheng.com
  algorithm: 'SHA1'
  digits: 6
  period: 30
  skew: 1
  secret_size: 32

webauthn:
  disable: false
  timeout: '60 seconds'
  display_name: 'huichengcheng'

identity_validation:
  reset_password:
    jwt_secret: '<secret>'

ntp:
  address: 'udp://ntp.tencent.com:123'
  version: 4
  max_desync: '3 seconds'

# 將用戶資訊(帳號,密碼)存在本地YAML文件中
# Ref: https://www.authelia.com/configuration/first-factor/file/
authentication_backend:
  password_reset:
    disable: false
  file:
    path: /config/users_database.yml
    password:
      algorithm: sha512
      iterations: 50000
      memory: 65536
      parallelism: 4
      key_length: 32
      salt_length: 32

password_policy:
  standard:
    enabled: false
    min_length: 8
    max_length: 0
    require_uppercase: true
    require_lowercase: true
    require_number: true
    require_special: true
  zxcvbn:
    enabled: false
    min_score: 3

privacy_policy:
  enabled: false
  require_user_acceptance: false
  policy_url: ''

# 網域登入認證設定
# Ref: https://www.authelia.com/configuration/security/access-control/
access_control:
  default_policy: deny
  rules:
    - domain_regex: '^.*\.?huichengcheng\.com$'
      policy: 'two_factor' #需要两个验证条件

# Cookie 設置
# Ref: https://www.authelia.com/configuration/session/introduction/
session:
  secret: '<secret>'
  cookies:
    - name: 'authelia_session'
      domain: huichengcheng.com
      authelia_url: 'https://authelia.huichengcheng.com:60000'
  name: authelia_session
  same_site: 'lax'
  inactivity: '5m'
  expiration: '1h'
  remember_me: '1M'
  redis:
    host: <host>
    password: <password>
    port: <port>
    database_index: 0

# 暫時禁止登入密碼錯誤且嘗試過多的帳號
# Ref: https://www.authelia.com/configuration/security/regulation/
regulation:
  max_retries: 3
  find_time: '2 minutes'
  ban_time: '5 minutes'

# 本地資料庫 
# Ref: https://www.authelia.com/configuration/storage/sqlite/
storage:
  encryption_key: <encryption_key>
  postgres:
    host: <host>
    port: <port>
    database: <database>
    username: <username>
    password: <password>

#Ref: https://www.authelia.com/configuration/notifications/introduction/
notifier:
  smtp: 
    username: <username>
    password: <password>
    host: smtp.feishu.cn
    port: 465
    sender: totp@EXAMPLE.com
    identifier: localhost
    subject: "[Authelia] {title}"
    startup_check_address: <smtp>
    disable_require_tls: false
    disable_html_emails: false

4. 编写 users_database 文件

4. 编写 /root/authelia/config/users_database.yml 文件
users:
    admin:
        password: <password>            # authelia crypto hash generate argon2 --password "$password"|awk '{print $NF}'
        displayname: admin User
        email: <email>
        groups:
            - admin
        disabled: false
    test:
        password: <password>            # authelia crypto hash generate argon2 --password "$password"|awk '{print $NF}'
        displayname: test User
        email: <email>
        groups:
            - admin
        disabled: false

5. create-user 创建用户脚本

5. 编写 /root/authelia/config/create-user.sh 文件
#!/bin/bash
authelia_dir="/root/authelia/"

# 检查参数数量
if [[ $# -ne 4 ]]; then
  echo "使用方法:create.sh <用户名> <密码> <邮箱> <角色>"
  exit 1
fi

# 提取参数
username=$1
password=$2
email=$3
role=$4

# 检查用户是否存在
if grep -q "^    $username:" ${authelia_dir}config/users_database.yml; then
  echo "用户 $username 已存在"
  exit 1
fi

# 生成密码
generated_password=$(docker exec authelia authelia crypto hash generate argon2 --password "$password"|awk '{print $NF}')

password=$(echo "$password_result" | sed -n 's/^Digest: \(.*\)$/\1/p')

# 构建用户条目
cat << EOF >> ${authelia_dir}config/users_database.yml
    $username:
        password: $generated_password
        displayname: $username User
        email: $email
        groups:
            - $role
        disabled: false
EOF
echo "用户 $username 创建成功" && docker compose -f ${authelia_dir}docker-compose.yml up -d --force-recreate authelia

6. 启动 Authelia 服务

docker compose up -d

7. Authelia 服务暴露

1. 编写 Caddyfile 规则
(authelia) {
        forward_auth 192.168.1.99:9091 {
                uri /api/verify?rd=https://authelia.huichengcheng.com:60000/
                copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
        }
}

authelia.huichengcheng.com {
        import dnspod 
        reverse_proxy 192.168.1.99:9091
}

tencent.k8s.huichengcheng.com {
       import authelia
       reverse_proxy 192.168.1.99
}
1. 自定义 endpoints 与 service 服务 auth.endpoint.yaml 文件
apiVersion: v1
kind: Endpoints
metadata: 
  name: authelia
  namespace: default
#指定自定义的point的目标地址
subsets:
- addresses:
  #外部的 authelia ip
  - ip: 192.168.1.99
  # 外部 authelia 的真实的工作端口
  ports:
   - port: 9091
     # 定义端口的名称,必须与 service 中的 ports.name 一致
     name: autheliaport
---
#这里的service配置大家都熟悉了,主要就是上面的endpoint而已
kind: Service
apiVersion: v1
metadata:
  name: sso-authelia
  namespace: default
spec:
  ports:
  - port: 9091
    protocol: TCP
    name: autheliaport
    targetPort: 9091
  type: ClusterIP
2. 创建 endpoints 与 service
kubectl apply -f auth.endpoint.yaml
1. 自定义 endpoints 与 service
kubectl describe svc sso-authelia |grep Endpoints
# Endpoints:         192.168.1.99:9091

2. 部署 Authelia Pod 至 k8s

> 选择 configmap 的方式,来部署 Authelia pod ,因为当前这个配置当中涉及的,配置项较多,有 config ,有用户列表,有 db

2. 在 traefik 当中定义 Middleware

注意 address 中:
1. https://authelia.huichengcheng.com:60000/ # 跳转至这个外部地址去进行验证(authelia)
2. http://sso-authelia.default:9091 # 通过svc地址获得进一步验证信息

1. 编写 003-traefik-Middleware.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: authelia
spec:
  forwardAuth:
    address: http://sso-authelia.default:9091/api/verify?rd=https://authelia.huichengcheng.com:60000/
    trustForwardHeader: true
    authResponseHeaders:
      - "Remote-User"
      - "Remote-Groups"
      - "Remote-Name"
      - "Remote-Email"
2. 创建资源
kubectl apply -f 003-traefik-Middleware.yaml

3. 在 traefik 当中调用 Middleware

1. 编写 004-traefik-Middleware-ingressroute.yaml

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: ingressroutetls
  namespace: default
spec:
  entryPoints:
    - websecure
  routes:
  - match: Host(`tencent.k8s.huichengcheng.com`)
    kind: Rule
    services:
    - name: service-middle
      port: 80
      namespace: default
    middlewares:
    - name: authelia-ip
    - name: authelia
  tls:
    secretName: tencent-tls
2. 创建资源
kubectl apply -f 004-traefik-Middleware-ingressroute.yaml

4. 测试跳转验证

1. 访问:测试 https://tencent.k8s.huichengcheng.com:50000 访问后自动跳转至验证页面

image-20240418115214759

image-20240418115902653