ForwardAuth 我们使用中经常会遇到一些网页没有登录身份验证,比如prometheus ui 和traefik ui 等,我们通常使用basic-auth 做登陆身份验证,这种虽然简单但是不利于实际使用中我们针对用户做限制,比如不希望某些人访问,basic-auth 无法实现类似的限制功能。
traefik有一个中间件ForwardAuth,ForwardAuth中间件可以将身份验证委派给外部服务。如果服务响应代码为2XX,则将授予访问权限并执行原始请求。否则,将返回来自身份验证服务器的响应。
配置如下:
1 2 3 4 5 6 7 8 9 10 11 apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: test-auth spec: forwardAuth: address: https://example.com/auth authResponseHeaders: - X-Forwarded-User # trustForwardHeader: true
address
选项定义外部身份验证服务器地址。
authResponseHeaders
选项定义要从外部身份验证服务器复制到请求的标头列表
trustForwardHeader
选项设置true
表示信任所有现有的X-Forwarded-*
标头
Traefik Forward Auth 这里外部服务我们使用Traefik Forward Auth,Traefik Forward Auth是一个轻量的前端身份验证服务,为traefik 提供OAuth/SSO登录和身份验证。
用法 traefik-forward-auth支持下列选项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 Usage: traefik-forward-auth [OPTIONS] Application Options: --log-level=[trace|debug|info|warn|error|fatal|panic] Log level (default: warn) [$LOG_LEVEL] --log-format=[text|json|pretty] Log format (default: text) [$LOG_FORMAT] --auth-host= Single host to use when returning from 3rd party auth [$AUTH_HOST] --config= Path to config file [$CONFIG] --cookie-domain= Domain to set auth cookie on, can be set multiple times [$COOKIE_DOMAIN] --insecure-cookie Use insecure cookies [$INSECURE_COOKIE] --cookie-name= Cookie Name (default: _forward_auth) [$COOKIE_NAME] --csrf-cookie-name= CSRF Cookie Name (default: _forward_auth_csrf) [$CSRF_COOKIE_NAME] --default-action=[auth|allow] Default action (default: auth) [$DEFAULT_ACTION] --default-provider=[google|oidc|generic-oauth] Default provider (default: google) [$DEFAULT_PROVIDER] --domain= Only allow given email domains, can be set multiple times [$DOMAIN] --lifetime= Lifetime in seconds (default: 43200) [$LIFETIME] --logout-redirect= URL to redirect to following logout [$LOGOUT_REDIRECT] --url-path= Callback URL Path (default: /_oauth) [$URL_PATH] --secret= Secret used for signing (required) [$SECRET] --whitelist= Only allow given email addresses, can be set multiple times [$WHITELIST] --rule.. = Rule definitions, param can be: "action", "rule" or "provider" Google Provider: --providers.google.client-id= Client ID [$PROVIDERS_GOOGLE_CLIENT_ID] --providers.google.client-secret= Client Secret [$PROVIDERS_GOOGLE_CLIENT_SECRET] --providers.google.prompt= Space separated list of OpenID prompt options [$PROVIDERS_GOOGLE_PROMPT] OIDC Provider: --providers.oidc.issuer-url= Issuer URL [$PROVIDERS_OIDC_ISSUER_URL] --providers.oidc.client-id= Client ID [$PROVIDERS_OIDC_CLIENT_ID] --providers.oidc.client-secret= Client Secret [$PROVIDERS_OIDC_CLIENT_SECRET] --providers.oidc.resource= Optional resource indicator [$PROVIDERS_OIDC_RESOURCE] Generic OAuth2 Provider: --providers.generic-oauth.auth-url= Auth/Login URL [$PROVIDERS_GENERIC_OAUTH_AUTH_URL] --providers.generic-oauth.token-url= Token URL [$PROVIDERS_GENERIC_OAUTH_TOKEN_URL] --providers.generic-oauth.user-url= URL used to retrieve user info [$PROVIDERS_GENERIC_OAUTH_USER_URL] --providers.generic-oauth.client-id= Client ID [$PROVIDERS_GENERIC_OAUTH_CLIENT_ID] --providers.generic-oauth.client-secret= Client Secret [$PROVIDERS_GENERIC_OAUTH_CLIENT_SECRET] --providers.generic-oauth.scope= Scopes (default: profile, email) [$PROVIDERS_GENERIC_OAUTH_SCOPE] --providers.generic-oauth.token-style=[header|query] How token is presented when querying the User URL (default: header) [$PROVIDERS_GENERIC_OAUTH_TOKEN_STYLE] --providers.generic-oauth.resource= Optional resource indicator [$PROVIDERS_GENERIC_OAUTH_RESOURCE] Help Options: -h, --help Show this help message
选项下面几种方式提供,优先级从高到低
命令行参数,例如–auth-host
环境变量,用选项说明中环境变量的值设置,例如 –auth-host 可以用AUTH_HOST这个变量设置
文件,使用--config
标志或$CONFIG
环境变量指定文件位置,文件使用ini格式,例如 auth-host=xxxx.xxx.xx
选项详情 auth-host 设置后,当用户从第三方提供商的身份验证返回时,他们将始终转发到该主机。
config 用于指定配置文件的路径,可以设置多次,每个文件将按照传递的顺序进行读取。选项应以INI格式设置,例如:
insecure-cookie 如果您不在客户端和traefik之间使用HTTPS,则需要传递该insecure-cookie
选项,
cookie-domain 设置时,如果用户成功完成身份验证,且需要身份验证的原始请求的主机是给定cookie域的子域,则将身份验证cookie设置为较高级别的cookie域。这意味着cookie可以允许访问多个子域,而无需重新验证。可指定多次。
例如:
1 --cookie-domain = " example.com " --cookie-domain = " test.org "
例如,如果已经设置了cookie域test.com,并且app1.test.com上有一个请求,验证之后将为整个test.com域设置验证cookie。因此,如果从app2.test.com转发另一个请求进行身份验证,则将发送原始cookie,因此该请求将被允许,而无需进一步的身份验证。
default-action 指定请求不匹配任何规则时的行为。有效选项为auth
或allow
。
默认值:(auth
即所有请求都需要认证)
default-provider 设置用于身份验证的默认提供程序,可以在rules中覆盖它。有效选项当前为google
或oidc
。
默认: google
domain 设置后,仅允许匹配给定域的用户访问。我们可以用来限制允许那些用户访问
例如,设置--domain=example.com --domain=test.org
意味着仅允许example.com或test.org中的用户。所以thom@example.com将被允许,但thom@another.com不会。
lifetime 成功的身份验证会话应持续多长时间(以秒为单位)。
默认值:43200
(12小时)
logout-redirect 设置后,用户将在注销后重定向到该URL。
url-path 自定义此服务用于在身份验证后处理回调的路径。
默认: /_oauth
secret
用于签署Cookie身份验证,应该是随机的(例如openssl rand -hex 16
)
whitelist
设置后,仅允许指定的用户。
例如,设置--whitelist=thom@example.com --whitelist=alice@example.com
将意味着仅允许这两个确切的用户。所以thom@example.com将被允许,但john@example.com不会。
match-whitelist-or-domain 当启用时,如果用户匹配whitelist或
domain参数,则允许他们使用。
注意事项 如果同时设置whitelist
和domain
,则默认仅whitelist
被使用,并且domain
将被忽略。如果需要同时设置whitelist
或domain
则应该设置match-whitelist-or-domain
参数
操作模式 Overlay 模式 Overlay 是默认的操作模式。默认情况下使用/_oauth
路径,可以使用url-path
选项自定义。
用户流程为:
请求 www.myapp.com/home
用户已重定向到Google登录
Google登录后,用户被重定向到 www.myapp.com/_oauth
令牌,用户和CSRF cookie均已验证(此请求已被拦截,并且从未传递给您的应用程序)
用户被重定向到 www.myapp.com/home
请求被允许
由于中的主机名redirect_uri
是根据原始请求动态生成的,因此必须在Google OAuth控制台中允许每个主机名,例如上面的流程需要添加www.myapp.com/_oauth,如果有很多子域名使用这种比较麻烦,推荐使用auth-host
验证主机(auth-host)模式 这是一种可选的操作模式,在处理大量子域时非常有用,可以通过使用--auth-host
选项激活
举例来说,如果你有几个应用:app1.test.com
,app2.test.com
,appN.test.com
,增加每一个域,以谷歌的控制台可以变得费力。要使用身份验证主机,请通过将Cookie域test.com
设置为auth-host
来允许域级别的Cookie,然后将设置为:auth.test.com
。
用户流将为:
请求 app10.test.com/home/page
用户已重定向到Google登录
Google登录后,用户被重定向到 auth.test.com/_oauth
令牌,用户和CSRF cookie已通过验证,auth cookie已设置为 test.com
用户被重定向到 app10.test.com/home/page
请求被允许
使用此设置,只需要配置auth.test.com
在Google控制台中允许。
auth-host
要使用,必须满足两个条件:
请求匹配 cookie-domain
auth-host
和 cookie-domain
相同的子域
身份验证提供者 重定向的url 设置任何身份验证提供程序时,提供程序应配置有效/授权的“重定向URI” 重定向url 应该为要进行身份验证的主机名并加上url-path 定义的路径,例如(https://app.example.com/_oauth
).
默认情况下,不使用验证主机模式时,需要设置每个主机(例如https://app1.example.com/_oauth
,https://app2.example.com/_oauth
)如果正在使用验证主机模式,这将只是你的auth-host
(如https://auth.example.com/_oauth
)
提供者 google 从开发者控制台获取客户端凭据:https : //console.developers.google.com 创建新项目,在搜索栏中选择“credentials”。填写“ OAuth Consent Screen”标签。点击“Create Credentials”>“ OAuth client ID”。选择“Web Application,填写您的应用程序的名称,跳过“Authorized JavaScript origins”,并填写“Authorized redirect URIs”
使用google
提供程序需要设置providers.google.client-id
和providers.google.client-secret
配置选项。
oidc 使用oidc
证明者并设置:
配置选项 值 providers.oidc.issuer-url
oidc issuer-url 地址 providers.oidc.client-id
oidc client id `providers.oidc.client-secret oidc 客户端的secret
k8s中使用 这里使用gitlab 作为oidc提供者,我们在gitlab上创建一个应用
创建一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 # # Traefik Forward Auth Deployment # apiVersion: apps/v1 kind: Deployment metadata: name: traefik-forward-auth labels: app: traefik-forward-auth namespace: kube-system spec: replicas: 1 selector: matchLabels: app: traefik-forward-auth strategy: type: Recreate template: metadata: labels: app: traefik-forward-auth spec: serviceAccountName: traefik-ingress-controller terminationGracePeriodSeconds: 60 containers: - image: thomseddon/traefik-forward-auth:2 name: traefik-forward-auth ports: - containerPort: 4181 protocol: TCP env: - name: CONFIG value: "/config" - name: DOMAIN value: "liangla.mobi" # INSECURE_COOKIE is required if not using a https entrypoint # - name: INSECURE_COOKIE # value: "true" # Remove COOKIE_DOMAIN if not using auth host mode - name: COOKIE_DOMAIN value: "baixue.fun" - name: AUTH_HOST value: "auth.baixue.fun" - name: LOG_LEVEL value: "trace" - name: DEFAULT_PROVIDER value: "oidc" - name: PROVIDERS_OIDC_ISSUER_URL value: "http://gitlab.baixue.fun" - name: PROVIDERS_OIDC_CLIENT_ID value: "94b56383b6xxxxxxxxxxxxxxxxxxxa47430678d45c0e1003bbdcf3989f34ac86" - name: PROVIDERS_OIDC_CLIENT_SECRET value: "f0261fa40d97ffxxxxxxxxxxxxxxxxxxxxxxx1a33eda3ec375a4c3e694bb8e" - name: SECRET value: "2d7194490b3eeb001b5cb9ac8f07d462"
service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # # Auth Service # apiVersion: v1 kind: Service metadata: name: traefik-forward-auth labels: app: traefik namespace: kube-system spec: type: ClusterIP selector: app: traefik-forward-auth ports: - name: auth-http port: 4181 targetPort: 4181
ingress
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: traefik-forward-auth labels: app: traefik namespace: kube-system spec: entryPoints: - websecure routes: - match: Host(`auth.baixue.fun`) kind: Rule services: - name: traefik-forward-auth port: 4181 middlewares: - name: traefik-forward-auth tls: certResolver: myresolver
中间件
1 2 3 4 5 6 7 8 9 10 apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: traefik-forward-auth namespace:kube-system spec: forwardAuth: address: http://traefik-forward-auth.kube-system.svc.cluster.local:4181 authResponseHeaders: - X-Forwarded-User
我们创建一个demo 用于验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 apiVersion: apps/v1 kind: Deployment metadata: name: whoami labels: app: whoami spec: replicas: 1 selector: matchLabels: app: whoami template: metadata: labels: app: whoami spec: containers: - name: whoami image: containous/whoami --- # # Service # apiVersion: v1 kind: Service metadata: name: whoami labels: app: whoami spec: ports: - name: http port: 80 selector: app: whoami --- # # IngressRoute # apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: whoami labels: app: whoami spec: entryPoints: - websecure routes: - match: Host(`jaeger.baixue.fun`) kind: Rule services: - name: whoami port: 80 middlewares: - name: traefik-forward-auth namespace: kube-system tls: certResolver: myresolver
我们访问https:/jaeger.baixue.fun 会自动跳转到gitlab上去验证
这里我们用lishuai 这个gitlab用户登录的,这个用户gitlab上的邮箱为liangla@lishuai.mobi符合我们domain的设置
我们下面用gitlab 中的root 用户登录,这个用户的邮箱为 912988434@qq.com ,不符合domain,所以会被拒绝
访问被限制
查看header如下
点击屏末 | 阅 读 原 文 | 即刻学习