Authelia 项目说明

Authelia 是一个开源的认证系统,目前支持双因素认证和单点登陆 SSO 认证,SSO 登陆是有 Web 界面支持的。它可以很好的与反向代理进行集成,比如 nginxTraefikHAProxy 等,对于通过这些反向代理的服务,如果没有通过认证将会把页面重定向到登陆页面。

Authelia 项目架构

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

Authelia 主要功能

  • 几种第二因素方法:
  • 使用电子邮件确认通过身份验证重置密码。
  • 仅单因素身份验证方法可用。
  • 尝试过多身份验证后的访问限制。
  • 每个子域,用户,资源和网络的细粒度访问控制。
  • 支持受单一因素保护的端点的基本身份验证。
  • Beta对OpenID Connect的支持。
  • 使用远程数据库具有很高的可用性,Redis可作为高可用性KV存储使用。
  • 开箱即用与Kubernetes ingress-nginx控制器兼容。

K8S部署

使用容器化部署Authelia是比较简单快捷的方法,在部署之前,我们来看下不同的环境对组件的要求。

  • 生产环境:LDAP (auth), PostgreSQL (storage), SMTP (notification), and Redis ( session)
  • 测试环境:file (auth), SQLite3 (storage), filesystem (notification), and memory ( session)

这里我们根据生产环境的规格进行相关组件部署。

单节点 redis 部署

这里我简单部署个基于k8s的单节点redis,有资源和需要的同学,可以部署集群环境。

cd ./plugins/redis
kubectl apply -f config.yaml
kubectl apply -f redis-deployment.yaml

查看pod、svc状态

kubectl get pod,svc -n middle|grep redis

单节点 postgresql 部署

这里我简单部署个基于k8s的单节点postgresql,有资源和需要的同学,可以部署集群环境。

cd ./plugins/postgresql
kubectl apply -f postgres-pvc.yaml
kubectl apply -f postgres-configmap.yaml
kubectl apply -f postgres-deploy.yaml

查看pod、svc状态

kubectl get pod,svc -n middle|grep postgres

部署 Authelia

这里我将部署的yaml文件贴出来,大家参考下。

authelia-configmap.yaml

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: authelia-conf
  namespace: middle
data:
  configuration.yml: |-
    theme: light
    jwt_secret: test#888
    ## 更改为真实的
    default_redirection_url: https://devops-ci.test.com
    default_2fa_method: ""
    server:
      host: 0.0.0.0
      port: 9091
      path: ""
      read_buffer_size: 4096
      write_buffer_size: 4096
      enable_pprof: false
      enable_expvars: false
      disable_healthcheck: false
      tls:
        key: ""
        certificate: ""
        client_certificates: []
      headers:
        csp_template: ""
    log:
      level: debug
    ntp:
      address: "time.cloudflare.com:123"
      version: 4
      max_desync: 3s
      disable_startup_check: false
      disable_failure: false
    authentication_backend:
      disable_reset_password: false
      password_reset:
        custom_url: ""
      refresh_interval: 5m
      ldap:
        implementation: custom
        ## 更改为真实的
        url: ldap://192.168.1.1
        timeout: 5s
        start_tls: false
        tls:
          ## 更改为真实的
          server_name: test.com
          skip_verify: true
          minimum_version: TLS1.2
        ## 更改为真实的
        base_dn: DC=test,DC=com
        username_attribute: sAMAccountName
        users_filter: (&({username_attribute}={input})(objectClass=person))
        groups_filter: (&(member={dn})(objectClass=groupOfNames))
        group_name_attribute: cn
        mail_attribute: mail
        permit_referrals: false
        ## 更改为真实的
        user: CN=test,OU=公共账户,OU=上海分部,DC=test,DC=com
        ## 更改为真实的
        password: test123

    access_control:
      default_policy: deny
      rules:
        ## 更改为真实的
        - domain: '*.devops-ci.test.com'
          policy: one_factor 
        ## 更改为真实的
        - domain: 'secure.devops-ci.test.com'
          policy: two_factor 

    session:
      name: authelia_session
      ## 更改为真实的
      domain: devops-ci.test.com  

      same_site: lax

      secret: insecure_session_secret

      expiration: 1h

      inactivity: 5m

      remember_me_duration: 1M

      redis:
        host: redis.middle.svc.cluster.local
        port: 6379
        ## 更改为真实的
        password: test#888
        database_index: 0
        maximum_active_connections: 8
        minimum_idle_connections: 0

    regulation:
      max_retries: 3
      find_time: 2m
      ban_time: 5m
    storage:
      encryption_key: thisisjustatesthahaha
      postgres:
        host: postgres.middle.svc.cluster.local
        port: 5432
        database: authelia
        schema: public
        username: authelia
        ## 更改为真实的
        password: test#888
        timeout: 5s
    notifier:
      disable_startup_check: true
      smtp:
        host: smtp.163.com
        port: 25
        timeout: 5s
        ## 更改为真实的
        username: 17521561234@163.com
        password: test#123
        sender: "17521561234@163.com"
        identifier: localhost
        subject: "[Authelia] {title}"
        startup_check_address: 17521561234@163.com
        disable_require_tls: true
        disable_html_emails: true
        tls:
          skip_verify: false
          ## Minimum TLS version for either StartTLS or SMTPS.
          minimum_version: TLS1.2

authelia-deploy.yaml

apiVersion: v1
kind: Service
metadata:
  labels:
    app: sso-authelia
  name: sso-authelia
  namespace: middle
spec:
  ports:
  - name: http
    port: 9091
    protocol: TCP
    targetPort: 9091
  selector:
    app: sso-authelia
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: sso-authelia
  name: sso-authelia
  namespace: middle
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sso-authelia
  template:
    metadata:
      labels:
        app: sso-authelia
    spec:
      containers:
      - image: authelia/authelia
        name: sso-authelia
        #args:
        #- "--config=/config/config.yml"
        volumeMounts:
        - name: authelia-configmap
          mountPath: /config/
        ports:
        - containerPort: 9091
          protocol: TCP
      imagePullSecrets:
        - name: IfNotPresent
      volumes:
        - name: authelia-configmap
          configMap:
            name: authelia-conf

进行authelia服务部署

kubectl apply -f authelia-configmap.yaml
kubectl apply -f authelia-deploy.yaml

查看authelia的pod,svc

kubectl get pod,svc -n middle|grep authelia

最佳实践

我们现在做个简单的测试,给prometheus添加authelia登录页面。

生成证书

# CN地址更改成自己的
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=*.devops-ci.test.com"
# 创建secret
kubectl create secret tls middle-tls --cert=tls.crt --key=tls.key -n middle
# 查看secret
kubectl get secret -n middle|grep tls

login-dashboard-route.yaml

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: login-dashboard-route
  namespace: middle
spec:
  entryPoints:
  - websecure 
  routes:
  - match: Host(`login.devops-ci.test.com`)
    kind: Rule 
    services:
      - name: sso-authelia
        port: 9091
  tls:
    secretName: middle-tls

kubectl apply -f login-dashboard-route.yaml

login-Middleware.yaml

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: authelia
  namespace: middle
spec:
  forwardAuth:
    address: http://sso-authelia.middle:9091/api/verify?rd=https://login.devops-ci.test.com

kubectl apply -f login-Middleware.yaml

login-prometheus.yaml

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: prometheus-route
  namespace: monitoring 
spec:
  entryPoints:
    - websecure
  routes:
  - match: HostRegexp(`prometheus.devops-ci.test.com`) 
    kind: Rule 
    services:
    - name: prometheus-k8s
      port: 9090 
    middlewares:
    - name: authelia
      namespace: middle
  tls:
    secretName: middle-tls

kubectl apply -f login-prometheus.yaml

浏览器访问测试

在浏览器中输入https://prometheus.devops-ci.test.com,页面此时会跳转到https://login.devops-ci.test.com

输入账号密码(接入的是ldap)之后,认证通过会跳转到https://prometheus.devops-ci.test.com

上面基本上实现了给prometheus添加login页面的功能。