简体   繁体   English

在 Openshift 上保护基于路径的路由

[英]Securing path based routing on Openshift

My application deployed on openshift has url as https://host:port/app/v1/hello/ I am using ServiceAccount as Oauth client and the provider is Openshift, so I should be redirected to Openshift login page for Authorization.我部署在 openshift 上的应用程序的 url 为 https://host:port/app/v1/hello/ 我使用 ServiceAccount 作为 Oauth 客户端,提供程序是 Openshift,所以我应该被重定向到 Openshift 登录页面进行授权。

We have configured openshift/oauth-proxy and it works great.我们已经配置了 openshift/oauth-proxy 并且效果很好。 https://github.com/openshift/oauth-proxy/ https://github.com/openshift/oauth-proxy/

Now further we have requirement of Path based routing, like if URL has /app/v1 then redirect to Service1 and if /app/v2 then to Service2现在进一步我们需要基于路径的路由,比如如果 URL 有 /app/v1 然后重定向到 Service1,如果 /app/v2 然后到 Service2

Here is the working example of my configuration,这是我的配置的工作示例,

`kind: Template
apiVersion: v1
metadata:
  name: deployment-template
objects:
  - apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: my-service-account
      annotations:
        serviceaccounts.openshift.io/oauth-redirectreference.first: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"my-route"}}'
  - apiVersion: v1
    kind: Service
    metadata:
      name: my-service
      annotations:
        service.alpha.openshift.io/serving-cert-secret-name: proxy-tls
    spec:
      selector:
        app: spring-boot-docker-openshift-hello-world
      ports:
        - name: api
          protocol: TCP
          port: 443 #Port the service listens on.
          targetPort: 8443 #Port on the backing pods to which the service forwards connections.
  - apiVersion: v1
    kind: Route
    metadata:
      name: my-route
    spec:
      port:
        targetPort: api
      path: "/"
      to:
        kind: Service
        name: my-service
      tls:
        termination: Reencrypt
  - apiVersion: apps.openshift.io/v1
    kind: DeploymentConfig
    metadata:
      labels:
        app: spring-boot-docker-openshift-hello-world
        version: 0.0.1-SNAPSHOT.1.dev
      name: spring-boot-docker-openshift-hello-world
    spec:
      replicas: 1
      selector:
        app: spring-boot-docker-openshift-hello-world
      strategy:
        rollingParams:
          timeoutSeconds: 3600
        type: Rolling
      template:
        metadata:
          labels:
            app: spring-boot-docker-openshift-hello-world
            version: 0.0.1-SNAPSHOT.1.dev
        spec:
          serviceAccount: my-service-account
          serviceAccountName: my-service-account
          containers:
          - name: spring-boot-docker-openshift-hello-world
            env:
              - name: KUBERNETES_NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
            image: pokarjm/spring-boot-docker-openshift-hello-world:0.0.1-SNAPSHOT.1.dev
            imagePullPolicy: IfNotPresent
            securityContext:
              privileged: false
            ports:
              - containerPort: 8080
                protocol: TCP
          - name: oauth-proxy
            image: openshift/oauth-proxy:latest
            imagePullPolicy: IfNotPresent
            ports:
              - containerPort: 8443
                name: public
            args:
              - --https-address=:8443
              - --provider=openshift
              - --openshift-service-account=my-service-account
              - --upstream=http://localhost:8080
              - --tls-cert=/etc/tls/private/tls.crt
              - --tls-key=/etc/tls/private/tls.key
              - --cookie-secret-file=/etc/proxy/secret/session_secret
              - --openshift-ca=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
              - --openshift-sar={"namespace":"spring-boot-docker-openshift-hello-world","resource":"services","name":"my-service","verb":"get"}
              - --request-logging=true
            volumeMounts:
              - mountPath: /etc/tls/private
                name: proxy-tls
                readOnly: true
              - mountPath: /etc/proxy/secret
                name: oauth-proxy-secret
                readOnly: true
          volumes:
            - name: proxy-tls
              secret:
                defaultMode: 420
                secretName: proxy-tls
            - name: oauth-proxy-secret
              secret:
                defaultMode: 420
                secretName: oauth-proxy-secret
      triggers:
        - type: ConfigChange
`

Now to support path based routing, that is map the request /app/v1 to Service1, I just added the Path in route like below,现在为了支持基于路径的路由,即将请求 /app/v1 映射到 Service1,我只是在路由中添加了路径,如下所示,

- apiVersion: v1
    kind: Route
    metadata:
      name: my-route
    spec:
      port:
        targetPort: api
      path: "/app/v1"
      to:
        kind: Service
        name: my-service
      tls:
        termination: Reencrypt

but with this changes I can see a initial sign in page like below但是通过这些更改,我可以看到如下所示的初始登录页面图片

but after clicking the button above instead of getting the openshift login page, I see below,但是在单击上面的按钮而不是获取 openshift 登录页面后,我看到了下面的内容,

图片

If I change the path in route to path: "/" it works and shows login screen.如果我将路径中的路径更改为路径:“/”,它将起作用并显示登录屏幕。 Appreciate any help on fixing path based routing in openshift/oauth-proxy.感谢有关在 openshift/oauth-proxy 中修复基于路径的路由的任何帮助。

Try adding something like --proxy-prefix=/app/v1 , to your oauth proxy container.尝试将类似--proxy-prefix=/app/v1到您的 oauth 代理容器中。

Eg:例如:

[...]
        args:
          - --https-address=:8443
          - --provider=openshift
          - --proxy-prefix=/app/v1
          - --openshift-service-account=my-service-account
[...]

Otherwise, the oauth-proxy would assume the application it is serving lies at the root of your Route, breaking the login callback redirection.否则,oauth-proxy 会假设它所服务的应用程序位于您的 Route 的根目录,从而破坏登录回调重定向。


Now, regarding your question in comments, I'm no sure I got it all myself, I don't have an OpenShift cluster to test this with, ... take it with a pinch of salt, edits welcome, if anyone can get this right.现在,关于您在评论中的问题,我不确定我自己是否已经掌握了所有内容,我没有一个 OpenShift 集群来测试这个,......加一点盐,欢迎编辑,如果有人能得到这个权利。

As far as I understand and recall:据我了解和回忆:

  • Client connect to your app, going through your oauth-proxy.客户端连接到您的应用程序,通过您的 oauth-proxy。
  • The proxy sees your client is unauthenticated and requests a token from the Oauth portal, using its client ID and secret (having set openshift-service-account , reads those out of /var/run/secrets/kubernetes.io/serviceaccount/ ).代理发现您的客户端未经身份验证,并使用其客户端 ID 和密码(已设置openshift-service-account ,从/var/run/secrets/kubernetes.io/serviceaccount/读取这些/var/run/secrets/kubernetes.io/serviceaccount/ )从 Oauth 门户请求令牌。 You could instead use client-id=system:serviceaccount:$ns:$sa and client-secret-file=/var/run/secrets/kubernetes.io/serviceaccount/token , if detection somehow doesn't work.您可以改为使用client-id=system:serviceaccount:$ns:$saclient-secret-file=/var/run/secrets/kubernetes.io/serviceaccount/token ,如果检测不知何故不起作用。
  • The Oauth SP checks for our ServiceAccount with an serviceaccounts.openshift.io/oauth-redirectreference annotation (though there's another way to do this, with OauthClient , which I'm less familiar with), matching the client requested application URL. Oauth SP serviceaccounts.openshift.io/oauth-redirectreference 注释检查我们的 ServiceAccount(尽管还有另一种方法可以做到这一点,使用OauthClient ,我不太熟悉),匹配客户端请求的应用程序 URL。 On successful match, SP replies to oauth-proxy with some ephemeral token成功匹配后,SP 用一些临时令牌回复 oauth-proxy
  • Knowing that token, and the proxy-prefix , the oauth-proxy redirects unauthenticated users to the Oauth login portal, with some encoded callback URL as a GET param知道该令牌和proxy-prefix ,oauth-proxy 会将未经身份验证的用户重定向到 Oauth 登录门户,并将一些编码的回调 URL 作为 GET 参数
  • User logs in against OpenShift users base用户根据 OpenShift 用户群登录
  • On successful login, the Oauth Portal redirects you to the oauth-proxy, using the callback URL it received from your proxy成功登录后,Oauth 门户使用从代理接收的回调 URL 将您重定向到 oauth-proxy
  • the oauth-proxy redeems its token oauth-proxy 赎回它的令牌
  • If openshift-sar was defined, oauth-proxy proceeds with some additional check ensuring client is authorized, otherwise any user may log in如果定义了openshift-sar ,oauth-proxy 会进行一些额外的检查以确保客户端获得授权,否则任何用户都可以登录
  • User optionally consent in granting some permissions用户可选择同意授予某些权限

In OpenShift context, the initial token requests is done using the login-url param, which defaults to kubernetes.default.svc/oauth/authorize , though in some cases (not sure to remember, some unusual networkpolicies), you may want to force use your OpenShift console FQDN instead.在 OpenShift 上下文中,初始令牌请求是使用login-url参数完成的,该参数默认为kubernetes.default.svc/oauth/authorize ,但在某些情况下(不确定记得,一些不寻常的网络策略),您可能想要强制请改用您的 OpenShift 控制台 FQDN。

The token redemption is done through the redeem-url which defaults to kubernetes.default.svc/oauth/token .令牌赎回是通过默认为kubernetes.default.svc/oauth/token redeem-url完成的。 Again, you could use your public console FQDN here, if SDN otherwise denies this traffic.同样,如果 SDN 拒绝此流量,您可以在此处使用公共控制台 FQDN。

So , how is proxy-prefix coming into the picture: only required for your oauth-proxy to build the proper callback URL, for the login form to send you back to the proper sub-path of your application.那么,proxy-prefix 是如何出现的:只有您的 oauth-proxy 需要构建正确的回调 URL,登录表单才能将您发送回应用程序的正确子路径。

And the OAuthRedirectReference is mainly used by OpenShift making sure the client requesting a token is indeed meant to authenticated clients for a given Route. OAuthRedirectReference 主要由 OpenShift 使用,以确保请求令牌的客户端确实是针对给定路由的经过身份验证的客户端。 In your case, only matching a FQDN, although I think that in addition to serviceaccounts.openshift.io/oauth-redirectreference.$name: {"kind": ...} , you may also set something like serviceaccounts.openshift.io/oauth-redirecturi.name: my-path在您的情况下,仅匹配 FQDN,尽管我认为除了serviceaccounts.openshift.io/oauth-redirectreference.$name: {"kind": ...} ,您还可以设置类似serviceaccounts.openshift.io/oauth-redirecturi.name: my-path

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM