Hi :wave: Does anyone have experience setting up ...
# talk-oathkeeper
f
Hi šŸ‘‹ Does anyone have experience setting up
ingress-nginx
and
oathkeeper
for external authorization in a k8s cluster? The idea is to not have any routing happening in oathkeeper but pass on the headers appended in oathkeeper downstream to my services. Any pointers, references, configs would be highly appreciated. Cheers Daniel
i
Take a look here: https://github.com/ory/oathkeeper/issues/521#issuecomment-1164331727, or also here https://ory-community.slack.com/archives/C01340V8KSM/p1686376234942799 Don't use
<http://nginx.ingress.kubernetes.io/auth-signin|nginx.ingress.kubernetes.io/auth-signin>
as it will not work
Ignore the
<http://nginx.ingress.kubernetes.io/auth-method|nginx.ingress.kubernetes.io/auth-method>: GET
part and update the
<http://nginx.ingress.kubernetes.io/auth-response-headers|nginx.ingress.kubernetes.io/auth-response-headers>: Authorization
to your needs (if you use another header)
If you want to use oathkeeper to manage the oauth2/oidc flows - this is not possible.
f
Thank you very much! That is incredibly helpful!
I'm gonna drop a couple lines of my journey with my config files and findings from moving from oathkeeper reverse proxy to decision engine + ingress-nginx once I'm done. Information was a little difficult to come by in the research stage.
a
@fresh-byte-82421 I'd be interested in your findings as I'm currently setting up the same. I'm especially interested whether mutators work at all šŸ¤”
f
So this is not really cleaned up yet, but I am essentially just setting up 2 endpoints for the ory controller authn: • /authn • /guest And then let the downstream services decide which endpoints should be authenticated. In development certain static files are going to served from services and authenticating every request is nonsensical. In production these files are likely going to be stored on a public fileserver somewhere, but it makes sense to have the
guest
option. Here's the oathkeeper controller config file with values from the ory reference documentation:
Copy code
oathkeeper:
  accessRules: |
    [
      {
        "id": "rule-authenticate",
        "upstream": {
          "url": "<https://httpbin.org/anything>"
        },
        "match": {
          "url": "http://<[^/]+>/authn",
          "methods": [
            "GET",
            "POST",
            "PUT",
            "DELETE",
            "PATCH"
          ]
        },
        "authenticators": [
          {
            "handler": "bearer_token"
          },
          {
            "handler": "cookie_session"
          }
        ],
        "authorizer": {
          "handler": "allow"
        },
        "mutators": [
        {
          "handler": "id_token",
        },
        {
          "handler": "header",
        }
        ]
      },
      {
        "id": "rule-guest",
        "upstream": {
          "url": "<https://httpbin.org/anything>"
        },
        "match": {
          "url": "http://<[^/]+>/guest",
          "methods": [
            "GET",
            "POST",
            "PUT",
            "DELETE",
            "PATCH"
          ]
        },
        "authenticators": [
          {
            "handler": "noop"
          }
        ],
        "authorizer": {
          "handler": "allow"
        },
        "mutators": [
        {
          "handler": "header",
        }
        ]
      }
    ]
  mutatorIdTokenJWKs: |
    {
      "keys": [
        {
          "use": "sig",
          "kty": "RSA",
          "kid": "67bf0153-a6dc-4f06-9ce4-2f203b79adc8",
          "alg": "RS256",
          "n": "z59MFx8ntDR5j_XhETXVJ-e2lYHOJx9jMouhAwqTMQXg07BiHLcLzIGjhPIhQTKdO4BpAbu84Ceg3W-fVmK8-yrnPch-4cgi6UktIxL--iV4yj1p5FSInbBBm1oFJcmn8jqf0picWwRlDUv92cJKblDE1ZdGjO6HqOvGZAZFr-w4xT_jBsQRBCLspZ0_mWDHWsrjFcvZ3AgmERm5kwmJ-YSSeU-v08twcwVkA9UdAgeHgw5Z9vascy1tsrokvsI7Qktk867SL-BJZJ4FWn8lAJCdxOMFGdXyGthr2d9kZqzNBc0Isoay1NtM0K0gt_27jZc456w9-enkEMIu9bM4HYiX3T9i6N2LjnNj2hdARg9WODFj01LCOb240_boXO_iHQU69SCKi6tvQNUw7lf7TapD1Dsz4OZ0tsbAVY5HKRZH-CIo6cseVaaloFI7PYPnRW3gXyOUxfQCIWpg8v6TPNPrNIbwH-gXiUd6-Mngj-MX-CWenuin-Y_-KYYOS880vlOfBGUVTSkpPBnHW4-a2DZLcjyxv2uUsKksFmDqPEQVrugXZQQ6mUGHQNXxOWqJ211kf6SNo0pv9mcLAo07rkPy3Ujqq96C3G_l74c2t2gfXYCv0vYvHQ5E726gf-7H3YK5NO0jH_0EvCMVD25L7eXVuITxaZdxpn3InrK_i2s",
          "e": "AQAB",
          "d": "ZygstChEn-Kaq45tHxHyMHuOWkY-WW3c6ZY6j7pHW8oh5Mv0U3QXJqsaxclQAIbXXGL2yWev9md6I8t8DX3Ni7XLYwUlFaVMw0AabxzXFw5bL5DH9iySHFcgocFeYWIKUe4Szp4IwagzVSH2pKVGOf1jbwRUh11UhfdvgO8k3L2vj0Go2Qm9sqJvlfHFUb2mD1RS89dvDUX3M_PmIkpRBWp7JE8Ve1PPMTbydH0EhqebCuCsjmoNUMS3hl-6NhVnQA8Zv4GS6Tq0_IsO-eHGTruLx_FL7YRBYFk7bOrzhZhB3an7skf-voefaOc8JG6rKzSBj4oi2PL-39y7XFSJgi1Ss9NHZsdUQvQUD6nsaXM0epouPCakekYo_jAR-v_of4UBNpodR5nMvXMxXheXg2uz-UiWAzZ9lC1fX0C9IN9XSV99ep_DimqfjYY3ikkhwgUa8UCizL5Tln67HC7hY1ucpfxGZ8D5m_eCtg8fIx8TgCSxbYce2bYIc0jdcGcuEQPoNZbSJgEgNxrNX653MzxGtnLaXafF1uyaszN4FjFX8ToEOOSrKC1fLZSSifMMKv4yNP7BeNL_op1TkMAYa1CTrxgFeUL3ckBmF3sV8guAEDM3aiYX77NZAXk_lX3vxk4BUYQayJxEwH8oyDFB-ZOnEJheuIdUUZZOzRwPfSE",
          "p": "1miNrKrNkJbyLkh5nZfSi7GtzmyOOGm0oCcpe3jh4zJnBNU34kOV5fCsK1ekEBEV0oEdCp4dqGVnWYoa7Kw9o04aeebSHMtBOZoVnQOIe8usm2xiD_y11uepRmGb1UNT_52PrCwFMsqtuupEJIJtKUFINq0KGtrnfM6UeA7cqVhZ8EDPNjL4c9iJ2JOzPa4jqPmyWe2Ypp_lMyG56yxZemUxZiX9sXqC89F1m0DNQ6Ny-VhWOYlkrTNT5kO17mgpru5yLmfklZhMSBOaKg7qdEmJB8HTlgMl40ulEnjRNLxoFNPboEwkXunFo6MMjEI35rcMDnr-LrIwZ06ia6fiEw",
          "q": "9-W-4eUTjwjgUfICak-Zxftyo21WdIRh35Ncg9SnvNQx3LrfCgMVGcGB375kbBEwiZIW9Zg7nsllkvPelT5DGxwjYuzOMZH5SQmnX9AhVQ9a0O-fVZIj0pHaod600A0c2gbXtsVkuakmMnZXExxcYjRoU0_4RMfL7IUH8EIf8Safdn6KObA-cvFwfVN2iiFl897lmFK3MRvc8Ul2ZyfV-jZPvFyF5i1ATDy2dcNBavOxsUoSrHytRmPyi6x5S2bq-9PhpeHx4JU8ZVSjUEAt7QKhK86mMaDjwSmWchjhbJhHlIxO9VmUXdTMC0yH2_ebMLk4sUZwZKszpkyshQIcSQ",
          "dp": "hJSATq4LkQYV2VLNiQqRkfobvJJZ2z5aB9JPj18vZvsKwu1JsisSrO4GuIJoG9tEwDdAiwk8051oq_B_N6xGLQ4lxw1ZDZ8NxR2nkcDWi55lLHJ3rOUaWDpF7RR8dQI-FckLR26tBDxZ80PbQSw5bhJFIjIcFoEYNY_UNO0Tu8-7RZn9x8j64z-Z9YdXhaOBv4Ivq_YEt7wV0WlgerCg39NlGYISfsV_5l62N3t5sgKHHPJn1wpDa-paTf--px5X8CjYCCQMMAjN2p_sa2dvyNqT1m0fdhqaOhPTjjmRO-fpAEAFBfkvYFVz9fzjzHNB9_NmjCm3tY5P6gGw45sbaw",
          "dq": "cSuadAgfYLo9pktknOIQIplDYaaFxJW3FNlyb-DCXutEhC9vqWN025hC0UFbGRbT4Mon3yELftcUnvzkTZ_qBNNYuE3BaFHqy1Qz7ALZZLqozB_Izsjzv6rEdAd25lBGLqbXDeKZtESrYngyElBtQIwKYJZukf_gce7di-q0KGRogjEMq39xUwo0P5K92BudLrNAf8SrSykcOa8-9aLzBdKLnkNjAY0BAIzrA2ILWGc-ZOCbG9GjTTJNxUQM78ZhWmwFZLR8tvmKY_w6vmU-UihUKeqiZp-7ujBhNV90ch4m94MCfPHTUO7X5AShNWOZnqnAXvX4U4zw_Geeju5CuQ",
          "qi": "OdvyakUl-NZ2PZHi5N_vDTdC4Ad4LI6JP4InVW-33kGySQom264eZ-nwBFVlZeCx2qgFE0iuRtS1plmZdEMP_cc8kW-PDtTDg3i_8rWutkmX13FThHXpT9M3iTU8qxeizRuvXaHIayplgZT6W8iIl4JWp1lWfLK85jTmsuX2mF-I0E56VOGOy7xlBEnyrrskXgyiOcjFgNy2UTaCNvfUrLxhiWAU-ZoqyEaj4t5bYdcu_xkuwDvdHea9RgHOMve9UoSPsSIAoev1HeTdIrWLOyUEenGqhUAkneRqTDuXkzUYFreV63nhqiHU3WUGKBbJ-4Dgl7kl0FxH7w98WuKscg"
        }
      ]
    }
  config:
    mutators:
      header:
        enabled: true
        config:
          headers:
            X-COMPANYNAME-Id: "{{ randAlphaNum 16 }}-{{ randAlpha 4 }}"
            X-COMPANYNAME-Hop: "0"
      noop:
        enabled: true
      id_token:
        enabled: true
        config:
          issuer_url: "<host>"
          ttl: 60s
          claims: |
            {
              "session": {{ .Extra | toJson }}
            }
    authorizers:
      allow:
        enabled: true
      deny:
        enabled: true
    authenticators:
      noop:
        enabled: true
      anonymous:
        enabled: true
        config:
          subject: guest
      cookie_session:
        enabled: true
        config:
          check_session_url: https://<host>/sessions/whoami
          preserve_path: true
          extra_from: "@this"
          subject_from: "identity.id"
          only:
            - <host>
      bearer_token:
        enabled: true
        config:
          check_session_url: https://<host>/sessions/whoami
          preserve_path: true
          extra_from: "@this"
          subject_from: "identity.id"
          token_from:
            header: X-Session-Token
          forward_http_headers:
            - Authorization
            - X-Session-Token
I then set up my k8s services as follows:
Copy code
apiVersion: <http://networking.k8s.io/v1|networking.k8s.io/v1>
kind: Ingress
metadata:
  name: hello-world-ingress
  annotations:
    <http://nginx.ingress.kubernetes.io/rewrite-target|nginx.ingress.kubernetes.io/rewrite-target>: /$2
    <http://nginx.ingress.kubernetes.io/auth-url|nginx.ingress.kubernetes.io/auth-url>: <http://oathkeeper-api.default.svc.cluster.local:4456/decisions/authn>
    <http://nginx.ingress.kubernetes.io/auth-response-headers|nginx.ingress.kubernetes.io/auth-response-headers>: "X-COMPANYNAME-Id, X-COMPANYNAME-Hop, Authorization"

spec:
  ingressClassName: nginx # use only with k8s version >= 1.18.0
  tls:
  rules:
  - http:
      paths:
      - path: /test(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: hello-world
            port:
              number: 3012

---

apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-world
  name: hello-world
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: hello-world
  ports:
  - port: 3012
    protocol: TCP
    targetPort: 3012