Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle request_id variable correctly in auth requests #9219

Merged
merged 4 commits into from
Aug 7, 2023

Conversation

leki75
Copy link
Contributor

@leki75 leki75 commented Oct 26, 2022

What this PR does / why we need it:

Ingress-nginx sets X-Request-ID HTTP header for every proxied request to support distributed tracing. Whenever we use nginx.ingress.kubernetes.io/auth-url with nginx.ingress.kubernetes.io/auth-keepalive the generated LUA-based authentication request will contain a different request-id than the one that reaches the upstream application.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • CVE Report (Scanner found CVE and adding report)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation only

How Has This Been Tested?

Deployed an ingress controller with the modified image. I used the following Kubernetes resources for the test:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/auth-keepalive: "60"
    nginx.ingress.kubernetes.io/auth-response-headers: x-lekitest
    nginx.ingress.kubernetes.io/auth-url: http://lekiauth.staging.svc.cluster.local:8080/auth
  name: lekitest
  namespace: staging
spec:
  ingressClassName: staging
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          service:
            name: lekitest
            port:
              number: 8080
        path: /lekitest
        pathType: Prefix

---
apiVersion: v1
data:
  default.conf: |
    server {
        listen 8080;
        server_name localhost;
        location / {
            content_by_lua_block {
                local hdrs = ngx.req.get_headers()
                ngx.say("x-request-id ", hdrs["x-request-id"])
                ngx.say("x-lekitest ", hdrs["x-lekitest"])
            }
        }
    }
kind: ConfigMap
metadata:
  name: lekitest
  namespace: staging

---
apiVersion: v1
data:
  default.conf: |
    server {
        listen 8080;
        server_name localhost;
        location / {
            content_by_lua_block {
                local req_id = ngx.req.get_headers()["x-request-id"]
                if req_id == nil then
                    ngx.header["x-lekitest"] = "err"
                else
                    ngx.header["x-lekitest"] = req_id .. "-lekitest"
                end
                ngx.say("ok")
            }
        }
    }
kind: ConfigMap
metadata:
  name: lekiauth
  namespace: staging

---
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: lekitest
  name: lekitest
  namespace: staging
spec:
  containers:
  - image: openresty/openresty
    name: lekitest
    resources: {}
    volumeMounts:
    - name: lekitest
      mountPath: /etc/nginx/conf.d
  dnsPolicy: ClusterFirst
  restartPolicy: Always
  volumes:
  - name: lekitest
    configMap:
      name: lekitest
status: {}

---
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: lekiauth
  name: lekiauth
  namespace: staging
spec:
  containers:
  - image: openresty/openresty
    name: lekiauth
    resources: {}
    volumeMounts:
    - name: lekiauth
      mountPath: /etc/nginx/conf.d
  dnsPolicy: ClusterFirst
  restartPolicy: Always
  volumes:
  - name: lekiauth
    configMap:
      name: lekiauth
status: {}

---
apiVersion: v1
kind: Service
metadata:
  name: lekitest
  namespace: staging
spec:
  ports:
  - name: http
    port: 8080
    protocol: TCP
  selector:
    run: lekitest
  type: ClusterIP

---
apiVersion: v1
kind: Service
metadata:
  name: lekiauth
  namespace: staging
spec:
  ports:
  - name: http
    port: 8080
    protocol: TCP
  selector:
    run: lekiauth
  type: ClusterIP

Results without the patch:

❯ curl -i http://example.com/lekitest
HTTP/1.1 200 OK
Date: Wed, 26 Oct 2022 23:49:22 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive
Strict-Transport-Security: max-age=15724800; includeSubDomains

x-request-id 761994d5db3c123bcd92e18ff2967f09
x-lekitest 2751bf4b6374242be1c17bba0d7716c5-lekitest

Results with the patch:

❯ curl -i http://example.com/lekitest
HTTP/1.1 200 OK
Date: Wed, 26 Oct 2022 23:51:32 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive
Strict-Transport-Security: max-age=15724800; includeSubDomains

x-request-id 9bc4b90688a3fd68e9e83c856347a1d7
x-lekitest 9bc4b90688a3fd68e9e83c856347a1d7-lekitest

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I've read the CONTRIBUTION guide
  • I have added unit and/or e2e tests to cover my changes.
  • All new and existing tests passed.
  • Added Release Notes.
Fixed a bug to use the same request-id for authentication requests and upstream requests when `nginx.ingress.kubernetes.io/auth-url` annotation is used with `nginx.ingress.kubernetes.io/auth-keepalive`.

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. labels Oct 26, 2022
@k8s-ci-robot
Copy link
Contributor

@leki75: This issue is currently awaiting triage.

If Ingress contributors determines this is a relevant issue, they will accept it by applying the triage/accepted label and provide further guidance.

The triage/accepted label can be added by org members by writing /triage accepted in a comment.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot
Copy link
Contributor

Hi @leki75. Thanks for your PR.

I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot k8s-ci-robot added needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. needs-priority size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Oct 26, 2022
@ElvinEfendi
Copy link
Member

the generated LUA-based authentication request will contain a different request-id than the one that reaches the upstream application

This sounds like a feature to me not a bug. The request to the external auth server is an another request, so it should have a different request id.

@leki75
Copy link
Contributor Author

leki75 commented Nov 4, 2022

This sounds like a feature to me not a bug. The request to the external auth server is an another request, so it should have a different request id.

If you remove the nginx.ingress.kubernetes.io/auth-keepalive: "60" annotation (changing back to the auth_request module instead of the LUA version), then the 2 request IDs are the same. I think we should have the same output whether to use keepalives or not.

@leki75
Copy link
Contributor Author

leki75 commented Dec 6, 2022

@ElvinEfendi @strongjz Any updates on this, please?

@leki75
Copy link
Contributor Author

leki75 commented Jan 13, 2023

@ElvinEfendi @strongjz Happy new year! Any updates, please?

@raja
Copy link

raja commented Feb 1, 2023

@tao12345666333 @strongjz @ElvinEfendi Is it possible to get this small change reviewed?

Copy link
Member

@tao12345666333 tao12345666333 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Feb 1, 2023
@ekovacs
Copy link
Contributor

ekovacs commented Feb 8, 2023

@tao12345666333 @strongjz @ElvinEfendi
looks like all the CI has passed. could we get this merged?

@tao12345666333
Copy link
Member

@ekovacs Since we've had some issues recently, we'll work on higher priority things first and pick this up after a new release

@leki75
Copy link
Contributor Author

leki75 commented Mar 6, 2023

@tao12345666333 @strongjz @ElvinEfendi Is it possible to get this change merged?

@leki75
Copy link
Contributor Author

leki75 commented Apr 19, 2023

@tao12345666333 @strongjz @ElvinEfendi Any updates on merging this change, please?

@tao12345666333
Copy link
Member

Sorry for the delay. Let me take a look

Copy link
Member

@tao12345666333 tao12345666333 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why you see different X-Request-ID headers in this scenario is because of how Ingress-nginx handles these requests internally:

  1. When a client sends an HTTP request, Ingress-nginx generates an X-Request-ID header for that incoming request if it doesn't already have one.
  2. Before forwarding the request to your upstream application, Ingress-nginx first sends an internal subrequest (Lua-based) to the specified auth-url for authentication.
  3. This internal subrequest is treated as a separate and independent HTTP transaction by Nginx, so it gets assigned its own unique X-Request-ID header value.

As a result, when comparing both requests (the original client's and Lua-based authentication), they will have different X-Request-ID values since they are considered distinct transactions within Nginx.

I suggest adding a new configuration item to allow users to control whether to merge or separate request-id to avoid confusion

@leki75
Copy link
Contributor Author

leki75 commented Apr 23, 2023

Thanks for your reply @tao12345666333. This is all true, but the X-Request-ID header will be the same whenever you change back to the original ngx_http_auth_request_module (non Lua-based) version. This is confusing that using nginx.ingress.kubernetes.io/auth-keepalive changes the behavior.

@tao12345666333
Copy link
Member

We can list all scenarios and regulate their behavior, right? @leki75

@leki75
Copy link
Contributor Author

leki75 commented Jun 15, 2023

We can list all scenarios and regulate their behavior, right? @leki75

Unfortunately, we cannot regulate the behavior of the non-Lua version. @tao12345666333 Do you think that we should make it configurable on Lua-only?

@tao12345666333
Copy link
Member

Yes. I think that's enough.

@netlify
Copy link

netlify bot commented Aug 2, 2023

Deploy Preview for kubernetes-ingress-nginx canceled.

Name Link
🔨 Latest commit 9066776
🔍 Latest deploy log https://app.netlify.com/sites/kubernetes-ingress-nginx/deploys/64ca3e7ec596f1000807fb5f

@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. area/docs and removed size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. labels Aug 2, 2023
@leki75
Copy link
Contributor Author

leki75 commented Aug 2, 2023

@tao12345666333 could you take a look, please?

@tao12345666333
Copy link
Member

👌 I will add this to my list, will finish on Friday

@tao12345666333 tao12345666333 added the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label Aug 7, 2023
Copy link
Member

@tao12345666333 tao12345666333 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

/retest

Thanks

@@ -33,6 +33,7 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz
|[nginx.ingress.kubernetes.io/auth-cache-key](#external-authentication)|string|
|[nginx.ingress.kubernetes.io/auth-cache-duration](#external-authentication)|string|
|[nginx.ingress.kubernetes.io/auth-keepalive](#external-authentication)|number|
|[nginx.ingress.kubernetes.io/auth-keepalive-share-vars](#external-authentication)|"true" or "false"|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this name

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 7, 2023
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: leki75, tao12345666333

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 7, 2023
@k8s-ci-robot k8s-ci-robot merged commit 5d8185c into kubernetes:main Aug 7, 2023
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/docs cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-priority needs-triage Indicates an issue or PR lacks a `triage/foo` label and requires one. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants