Skip to content

Deny all HTTP requests

Page as Markdown

For a more secure setup, you can enable a feature gate to deny requests to your HTTP routes by default.

About the feature gate

You can enable the gatewayDefaultDenyAllHTTPRequests feature gate in your Gloo Mesh Gateway installation to automatically deny all requests to your HTTP routes if no ExtAuthPolicy or JwtPolicy is applied to the route.

To deny all requests for a route, you add the gateway.gloo.solo.io/require_auth: "true" to the route that you want to protect. You have the option to protect individual routes, or apply this label to all routes in a route table or delegated route table. Access to the route is granted only if an auth policy is applied to the route, such as an ExtAuthPolicy or JwtPolicy, and the client request can be authenticated successfully.

Without the gateway.gloo.solo.io/require_auth: "true" label, requests to your routes are allowed by default. You can still apply auth policies to protect routes. However, if your auth policies are deleted, misconfigured, or otherwise not persisted in the Envoy proxy, then the route becomes exposed again. By using the gatewayDefaultDenyAllHTTPRequests feature gate, you can safeguard against such accidental exposure.

Feature considerations

Before using this feature, keep in mind the following considerations.

  • Response behavior change: When you enable the feature gate, the gateway denies unauthorized requests with a 403 HTTP response code, even if the route is not found which typically returns a 404 HTTP response code. As such, this response behavior change might affect automation that you have in place, such as to monitor or troubleshoot logs.
  • Ingress gateway only: You can use this feature with an Istio ingress gateway for north-south traffic within the service mesh. This feature does not support east-west gateways or egress gateways for traffic that leaves the service mesh.
  • HTTP routes only: You can use this feature to set up the ingress gateway to deny all requests for HTTP/HTTPS routes only. This feature does not support other types of routes, such as TLS or TCP.
  • Gloo external auth service only: You must use the Gloo external auth service to enforce the auth policies to the routes. You cannot use your own custom external auth service. You can add the gateway.gloo.solo.io/require_auth: "false" label to these routes so that you know that the routes are not protected by the gatewayDefaultDenyAllHTTPRequests feature gate.
  • JwtPolicy cannot allow missing or failed JWT: Your JwtPolicies cannot set the allowMissingOrFailed field or the validationPolicy field to ALLOW_MISSING or ALLOW_MISSING_OR_FAILED JWTs. For the deny all feature gate to work, the gateway needs a valid JWT. Because JwtPolicies with those fields might allow a missing or invalid JWT, the gateway denies requests to the route. Instead, consider these options:
    • You can apply an additional ExtAuthPolicy, so that some type of auth is enforced on the route. This way, you can configure ALLOW_MISSING or ALLOW_MISSING_OR_FAILED JWTs because the request can successfully authenticate via external auth.
    • You can disable this feature for the route that you want to allow a missing or failed JWT by applying the gateway.gloo.solo.io/require_auth: "false" label on that route.
  • JWT must have iss claim: For the gatewayDefaultDenyAllHTTPRequests feature gate to work, JWT claims must include an iss claim. If not, the gateway denies the request. Note that this behavior differs from the regular gateway behavior, which can authenticate JWTs that do not to have the iss claim.
  • Version requirements: To enable this feature, you must use a Solo distribution of Istio (not community Istio) version 1.19.5, 1.20.1, or later.

Deny requests to your routes by default

To deny requests to your routes by default, you enable the gatewayDefaultDenyAllHTTPRequests feature gate in your Gloo Mesh Gateway installation. Then, when you set up routing for your app, add the gateway.gloo.solo.io/require_auth: "true" label to the route that you want to deny requests for. Note that Gloo Mesh Gateway only respects this label when the gatewayDefaultDenyAllHTTPRequests feature gate is enabled.

  1. Install or upgrade Gloo Mesh Gateway with the gatewayDefaultDenyAllHTTPRequests feature gate enabled. In multicluster setups, you must enable this feature gate in the management cluster installation. For more information, see the Feature gate and Helm reference docs.

    
    featureGates:
      gatewayDefaultDenyAllHTTPRequests: true
    --set featureGates.gatewayDefaultDenyAllHTTPRequests=true

    The following example command uses the gloo-gateway-demo installation profile.

    meshctl install --profiles gloo-gateway-demo \
      --set common.cluster=$CLUSTER_NAME \
      --set licensing.glooGatewayLicenseKey=$GLOO_MESH_GATEWAY_LICENSE_KEY \
      --set featureGates.gatewayDefaultDenyAllHTTPRequests=true

  2. Deploy the httpbin sample app.

  3. Configure a virtual gateway with an HTTP or HTTPS listener. The following example creates a sample HTTP listener for the ingress gateway.

    kubectl apply -f- <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: VirtualGateway
    metadata:
      name: istio-ingressgateway
      namespace: httpbin
    spec:
      listeners:
      - http: {}
        port:
          number: 80
      workloads:
      - selector:
          labels:
            istio: ingressgateway
    EOF
  4. Create a route table for the sample httpbin app. Include the gateway.gloo.solo.io/require_auth: "true" label to each route that you want to deny requests to by default. You can apply the label to an entire route table, delegated routes, or individual routes, such as in the following examples.

    Deny requests to all routes in the route table by applying the label to the route table. Note that if you also specify a label at the individual route level, the individual route label takes precedence. For example, you might explicitly set the label to false to allow a more permissive route. The route table in the following example:

    • Has the gateway.gloo.solo.io/require_auth: "true" label in the route table metadata so that all routes in the route table inherit this label by default.
    • Sets up two routes, httpbin-insecure and httpbin-secure. All routes inherit the gateway.gloo.solo.io/require_auth: "true" label from the metadata of the route table. Each route must have an accepted auth policy, or else requests are denied by default.
    • The httpbin-insecure route includes the gateway.gloo.solo.io/require_auth: "false" label. This way, the value inherited from the route table is overridden and the gateway does not deny requests to this individual route by default. You might have an insecure route for quick testing or for use cases where you want to allow a missing or failed JWT.
    kubectl apply -f- <<EOF
    kind: RouteTable
    apiVersion: networking.gloo.solo.io/v2
    metadata:
      name: httpbin
      namespace: httpbin
      labels:
        app: httpbin
        gateway.gloo.solo.io/require_auth: "true"
    spec:
      hosts:
        - '*'
      virtualGateways:
        - name: istio-ingressgateway
          namespace: httpbin
      http:
      - name: httpbin-insecure
        labels:
          route: httpbin
          gateway.gloo.solo.io/require_auth: "false"
        matchers:
        - uri:
            prefix: /insecure
        forwardTo:
          destinations:
          - ref:
              name: httpbin
              namespace: httpbin
            port:
              number: 8000
          pathRewrite: /headers
      - name: httpbin-secure
        labels:
          route: httpbin
        matchers:
        - uri:
            prefix: /secure
        forwardTo:
          destinations:
          - ref:
              name: httpbin
              namespace: httpbin
            port:
              number: 8000
          pathRewrite: /headers
    EOF

    Deny requests to all routes in a delegated route table. This way, you do not have to include the label in the delegated child route table. The delegated child route table inherits its parent route table label. Note that if you specify a label in the delegated child route table, that label takes precedence. For example, you might explicitly set the label to false to allow a more permissive route. For more information about delegation, see Delegate requests to sub-tables.

    The following parent route table:

    • Selects the virtual gateway that you previously created.
    • Delegates the httpbin route to the route table with the app: httpbin label.
    • Includes the gateway.gloo.solo.io/require_auth: "true" label for the delegated httpbin route so that all routes in the delegated child route table inherit the label. This way, the feature to deny all HTTP traffic by default is enabled for all of the routes in the delegated child route table.
    kubectl apply -f- <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: RouteTable
    metadata:
      name: gateway
      namespace: istio-ingress
    spec:
      hosts:
        - '*'
      virtualGateways:
        - name: istio-ingressgateway
          namespace: httpbin
      http:
        - name: httpbin
          labels:
            gateway.gloo.solo.io/require_auth: "true"
        - delegate:
            routeTables:
            - labels:
                app: httpbin
    EOF



    The following delegated child route table:

    • Has the app: httpbin label so that it is selected by the parent route table to get delegated traffic.
    • Sets up two routes, httpbin-insecure and httpbin-secure.
    • The httpbin-insecure route includes the gateway.gloo.solo.io/require_auth: "false" label. This way, it overrides the parent route table setting so that the httpbin-insecure route can get traffic that is not protected by an auth policy. You might have an insecure route for quick testing or for use cases where you want to allow a missing or failed JWT.
    • The httpbin-secure route inherits the gateway.gloo.solo.io/require_auth: "true" label from the parent route table. The route must have an accepted external auth or JWT policy, or else requests are denied by default.
    kubectl apply -f- <<EOF
    kind: RouteTable
    apiVersion: networking.gloo.solo.io/v2
    metadata:
      name: httpbin
      namespace: httpbin
      labels:
        app: httpbin
    spec:
      http:
      - name: httpbin-insecure
        labels:
          route: httpbin
          gateway.gloo.solo.io/require_auth: "false"
        matchers:
        - uri:
            prefix: /insecure
        forwardTo:
          destinations:
          - ref:
              name: httpbin
              namespace: httpbin
            port:
              number: 8000
          pathRewrite: /headers
      - name: httpbin-secure
        labels:
          route: httpbin
        matchers:
        - uri:
            prefix: /secure
        forwardTo:
          destinations:
          - ref:
              name: httpbin
              namespace: httpbin
            port:
              number: 8000
          pathRewrite: /headers
    EOF

    Deny requests for specific routes by applying the label to an individual route in a route table. The route table in the following example:

    • Sets up two routes, httpbin-insecure and httpbin-secure.
    • The httpbin-insecure route includes the gateway.gloo.solo.io/require_auth: "false" label. You might have an insecure route for quick testing or for use cases where you want to allow a missing or failed JWT.
    • The httpbin-secure route includes the gateway.gloo.solo.io/require_auth: "true" label. The route must have an accepted auth policy, or else requests are denied by default.

    Note that individual route labels take precedence over any parent route tables or the label of the route table itself.

    kubectl apply -f- <<EOF
    kind: RouteTable
    apiVersion: networking.gloo.solo.io/v2
    metadata:
      name: httpbin
      namespace: httpbin
      labels:
        app: httpbin
    spec:
      hosts:
        - '*'
      virtualGateways:
        - name: istio-ingressgateway
          namespace: httpbin
      http:
      - name: httpbin-insecure
        labels:
          route: httpbin
          gateway.gloo.solo.io/require_auth: "false"
        matchers:
        - uri:
            prefix: /insecure
        forwardTo:
          destinations:
          - ref:
              name: httpbin
              namespace: httpbin
            port:
              number: 8000
          pathRewrite: /headers
      - name: httpbin-secure
        labels:
          route: httpbin
          gateway.gloo.solo.io/require_auth: "true"
        matchers:
        - uri:
            prefix: /secure
        forwardTo:
          destinations:
          - ref:
              name: httpbin
              namespace: httpbin
            port:
              number: 8000
          pathRewrite: /headers
    EOF

Good job! Now, routes with the gateway.gloo.solo.io/require_auth: "true" label are protected by default. Any traffic requests sent to these routes are automatically denied with a 403 response. To allow traffic, you must apply an auth policy, such as an ExtAuthPolicy or JwtPolicy. For an example, continue to the next step to verify your setup.

Verify your secured routes

To verify your secured routes, send a series of requests to the routes. For requests to succeed, the routes must have an external auth or JWT policy that is applied to the routes and in an Accepted state. The following example sets up various JWT policies to demonstrate the feature.

  1. Save the external address of the ingress gateway.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n istio-ingress istio-ingressgateway -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS

    In another tab in your terminal, port-forward the istio-ingressgateway pod on port 8080. Note that if you are testing on a local network such as kind on macOS, you might have to configure a load balancer such as metallb.

    kubectl port-forward pod/$(kubectl get pod -l istio=ingressgateway -A -o jsonpath='{.items[0].metadata.name}') -n istio-ingress 8080:8080

  2. Send a request to the httpbin-secure route. The request is denied with a 403 response because the route does not have an attached auth policy.

    curl -vik http://$INGRESS_GW_ADDRESS:80/secure
    curl -vik localhost:8080/secure

    Example output:

    HTTP/2 403
  3. Send a request to the httpbin-insecure route. The request succeeds with a 200 response even though the route does not have an attached auth policy. The gateway does not deny requests by default because you included the gateway.gloo.solo.io/require_auth: "false" label to allow a more permissive route

    curl -vik http://$INGRESS_GW_ADDRESS:80/insecure
    curl -vik localhost:8080/insecure

    Example output:

    HTTP/2 200
  4. Apply a JWT policy to the route. The following example uses sample keys and a dev-example JWT. For more details about the sample JWT, see the GitHub readme.

    kubectl apply -f https://gist.githubusercontent.com/artberger/674bab05350c9a048303cc7daaffe730/raw/daf7d9b64e5e9ecf309f17123e01f5a6cbb6c7eb/jwt-policy-basic.yaml
  5. Get a sample JWT that is preconfigured to meet the validation requirements that you set in the JWT policy for the dev-example provider.

    TOKEN=$(curl https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/gloo-gateway/jwt/dev-example.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode

    Example output:

    {"iss":"https://dev.example.com","exp":4804324736,"iat":1648651136,"org":"internal","email":"dev1@solo.io","group":"engineering","scope":"is:developer%
  6. Repeat the request to the httpbin-secure route, this time with your valid JWT. The request now succeeds with a 200 response because the route has an attached auth JWT policy and you included a valid JWT in your request.

    curl -vik -H "X-Auth: Bearer ${TOKEN}" http://$INGRESS_GW_ADDRESS:80/secure
    curl -vik -H "X-Auth: Bearer ${TOKEN}" localhost:8080/secure

    Example output with a valid JWT:

    HTTP/2 200

    Example output with an invalid JWT:

    HTTP/2 401
  7. Delete the JWT policy that secures the httpbin-secure route and repeat the request. Notice that the request is denied again because the feature gate denies requests to the route by default. This way, the route stays protected in cases where the policy is accidentally deleted or misconfigured.

    kubectl delete JwtPolicy -n httpbin jwt-policy
    curl -vik -H "X-Auth: Bearer ${TOKEN}" http://$INGRESS_GW_ADDRESS:80/secure
    curl -vik -H "X-Auth: Bearer ${TOKEN}" localhost:8080/secure

    Example output:

    HTTP/2 403

Cleanup

You can optionally remove the resources that you set up as part of this guide.
  1. Delete the routing and policy resources that you created.

    kubectl delete VirtualGateway -n httpbin istio-ingressgateway
    kubectl delete RouteTable -n httpbin httpbin
    kubectl delete RouteTable -n istio-ingress gateway #for delegated example
    kubectl delete JwtPolicy -n httpbin jwt-policy
  2. If you do not want to use this feature anymore, you can disable the feature gate. Upgrade Gloo Mesh Gateway and disable the gatewayDefaultDenyAllHTTPRequests feature gate. In multicluster setups, disable this feature gate in the management cluster. For more information, see the Feature gate and Helm reference docs.

    
    featureGates:
      gatewayDefaultDenyAllHTTPRequests: false
    --set featureGates.gatewayDefaultDenyAllHTTPRequests=false