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

Settings status code for ExtAuth when used with SecurityPolicy #5214

Closed
zilinjak opened this issue Feb 5, 2025 · 5 comments
Closed

Settings status code for ExtAuth when used with SecurityPolicy #5214

zilinjak opened this issue Feb 5, 2025 · 5 comments
Labels

Comments

@zilinjak
Copy link

zilinjak commented Feb 5, 2025

Hi,
Im using SecurityPolicy with ExtAuth ref to our GRPC service. We would like to return to the users status code 401.

The filter which is used by Envoy Proxy has that option to set - status_on_error - docs, which default to 403.

The SecurityPolicy seems to be lacking this settings, which means that I can't set the status code returned by Envoy Proxy. Hence is there any other way how to set the status_on_error + I need the ext auth to be enabled on whole Gateway and all routes created in it. If not are there any plans on creating this option ?

Thanks

@zilinjak zilinjak added the triage label Feb 5, 2025
@arkodg
Copy link
Contributor

arkodg commented Feb 5, 2025

hey closing this one as a dup of #5180, lets discuss this issue there

@arkodg arkodg closed this as completed Feb 5, 2025
@zilinjak
Copy link
Author

zilinjak commented Feb 6, 2025

@arkodg

Just to make sure if I was understood correctly, since I think I didnt discribe it well.

We are using ext auth on gateway to decode JWTs and want to return 401 when the JWT is invalid. According to the GRPC spec, this should work since:

Im returning the response for 401 like this:

CheckResponse.newBuilder()
    .setStatus(
        Status.newBuilder()
            .setCode(Code.UNAUTHENTICATED_VALUE)
            .setMessage("Permission denied")
            .build(),
    )
    .build()

where Code.UNAUTHENTICATED_VALUE has documentation like:

  /**
   *
   *
   * <pre>
   * The request does not have valid authentication credentials for the
   * operation.
   *
   * HTTP Mapping: 401 Unauthorized
   * </pre>
   *
   * <code>UNAUTHENTICATED = 16;</code>
   */
  public static final int UNAUTHENTICATED_VALUE = 16;

The HTTP Mapping seems like the 401 should be returned to the user no?

@zilinjak
Copy link
Author

zilinjak commented Feb 6, 2025

I have just tested it using envoy proxy locally with these steps:

  1. Start ExtAuth on http://localhost:8080
  2. Start HTTPBIN on http://localhost:36000
docker run -p 36000:80 kennethreitz/httpbin
  1. Start proxy with this configuration
envoy -c envoy_test_config.yaml --log-level debug
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 127.0.0.1, port_value: 8081 }
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          codec_type: AUTO
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route: { cluster: some_service }
          http_filters:
          - name: envoy.filters.http.ext_authz
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
              grpc_service:
                envoy_grpc:
                  cluster_name: ext-authz
                timeout: 600s
              status_on_error:
                code: 401
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
  - name: some_service
    connect_timeout: 600s
    type: STATIC
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: some_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 36000
  - name: ext-authz
    type: static
    typed_extension_protocol_options:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicit_http_config:
          http2_protocol_options: {}
    load_assignment:
      cluster_name: ext-authz
      endpoints:
        - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: 127.0.0.1
                    port_value: 8080
    # This timeout controls the initial TCP handshake timeout - not the timeout for the
    # entire request.
    connect_timeout: 600s
  1. Test it

Now when I curl the httpbin which is proxied by EnvoyProxy

curl -v localhost:8081/api/foo -H "Token: Foo-bar"
*   Trying [::1]:8081...
* connect to ::1 port 8081 failed: Connection refused
*   Trying 127.0.0.1:8081...
* Connected to localhost (127.0.0.1) port 8081
> GET /api/foo HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/8.4.0
> Accept: */*
> Token: Foo-bar
> 
< HTTP/1.1 403 Forbidden
< date: Thu, 06 Feb 2025 10:33:29 GMT
< server: envoy
< content-length: 0
< 

the response is still 403, even tho I have returned the code: 16 which has mapping to 401

I can see in extAuth log

status {
  code: 16
  message: "Permission denied"
}

@arkodg this leads me that its problem of EnvoyProxy ?

@arkodg
Copy link
Contributor

arkodg commented Feb 6, 2025

hey @zilinjak can you raise an issue in https://github.com/envoyproxy/envoy/issues if this is specific to envoy proxy ?

@zilinjak
Copy link
Author

zilinjak commented Feb 7, 2025

Nevermind, sorry for spam, with envoy proxy this seems to be working ->

            CheckResponse.newBuilder().setDeniedResponse(
                DeniedHttpResponse.newBuilder()
                    .setStatus(
                        io.envoyproxy.envoy.type.v3.HttpStatus.newBuilder().setCode(
                            io.envoyproxy.envoy.type.v3.StatusCode.Unauthorized
                        )
                    )
                    .setBody("Unauthorized")
                    .build()
            ).build()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants