Skip to content

THREESCALE-11887 Add configurable no_match policy option - #1605

Open
borisurbanik wants to merge 1 commit into
3scale:masterfrom
borisurbanik:bu-THREESCALE-11887
Open

THREESCALE-11887 Add configurable no_match policy option#1605
borisurbanik wants to merge 1 commit into
3scale:masterfrom
borisurbanik:bu-THREESCALE-11887

Conversation

@borisurbanik

Copy link
Copy Markdown

Fixes:

Verification:

Deploy 3Scale and Keycloak using the operators.

The default 3Scale configuration comes with API Product and Developer account that has an echo backend mapped to /echo path.

Configure 3Scale OIDC integration for the API Product following the documentation:
https://docs.redhat.com/en/documentation/red_hat_3scale_api_management/2.16/html/administering_the_api_gateway/integrating-threescale-with-an-openid-connect-identity-provider#integrating-threescale-with-rhsso-as-the-openid-connect-identity-provider_oidc

Add new application under Developer account, set client id and client password environment variables:

CLIENT_ID='(your client id)'
CLIENT_SECRET='(your client secret)'
ACCESS_TOKEN="$(curl -k -X POST "https://keycloak-3scale-keycloak.apps.burbanik-3scale2.cp.fyre.ibm.com/auth/realms/apicast/protocol/openid-connect/token"
-u "$CLIENT_ID:$CLIENT_SECRET"
-H "Content-Type: application/x-www-form-urlencoded"
-d "grant_type=client_credentials" | jq -r '.access_token')"

Verify that the integration is setup correctly:

curl -k -i -H "Authorization: Bearer $ACCESS_TOKEN" https://api-3scale-apicast-staging.apps.burbanik-3scale2.cp.fyre.ibm.com/echo

To test authorized user, add another application and assign a role "my-role" to the corresponding client (this will work with configuration below).

Scenarios tested

  1. Test that no_match rule will default to "type_defined" option
details

Configure a keycloak_role_check policy on a standard apicast deployment:

              {
                "name": "keycloak_role_check",
                "version": "builtin",
                "configuration": {
                  "type": "whitelist",
                  "scopes": [
                    {
                      "realm_roles": [],
                      "resource": "/echo/protected",
                      "client_roles": [
                        {
                          "client": "{{ jwt.azp }}",
                          "name": "my-role",
                          "client_type": "liquid",
                          "name_type": "plain"
                        }
                      ],
                      "methods": [
                        "ANY"
                      ],
                      "resource_type": "plain"
                    }
                  ]
                }
              }

Build and push new image

make runtime-image REGISTRY=quay.io/burbanik
make push REGISTRY=quqy.io/burbanik IMAGE_NAME=apicast-runtime-image:latest

Update 3scale deployment to switch to the newly built image

oc patch apimanager 3scale -n 3scale-test --type='json' -p='[{"op": "add", "path": "/spec/apicast/image", "value":"quay.io/burbanik/apicast-runtime-image:latest"}]'

After the apicast-staging pod is re-created by operator, test that the authentication works as expected:

% curl -i -k -H "Authorization: Bearer $ACCESS_TOKEN" 'https://api-3scale-apicast-staging.apps.burbanik-3scale2.cp.fyre.ibm.com/echo/protected'
# return 200 for authorized or 403 for non-authorized application

curl -i -k -H "Authorization: Bearer $ACCESS_TOKEN" 'https://api-3scale-apicast-staging.apps.burbanik-3scale2.cp.fyre.ibm.com/echo/public'
# return 403 in both cases
  1. Test that whitelist + allow no_match combination will allow non-protected endpoints
details

One the image is updated, update (and publish) the policy to include "allow" no_match option:

             {
                "name": "keycloak_role_check",
                "version": "builtin",
                "configuration": {
                  "scopes": [
                    {
                      "client_roles": [
                        {
                          "name": "my-role",
                          "client": "{{ jwt.azp }}",
                          "client_type": "liquid",
                          "name_type": "plain"
                        }
                      ],
                      "realm_roles": [],
                      "resource": "/echo/protected",
                      "methods": [
                        "ANY"
                      ],
                      "resource_type": "plain"
                    }
                  ],
                  "type": "whitelist",
                  "no_match": "allow"
                }
              },

Verify that this works as expected now:

% curl -i -k -H "Authorization: Bearer $ACCESS_TOKEN" 'https://api-3scale-apicast-staging.apps.burbanik-3scale2.cp.fyre.ibm.com/echo/protected'
# return 200 for authorized or 403 for non-authorized application

curl -i -k -H "Authorization: Bearer $ACCESS_TOKEN" 'https://api-3scale-apicast-staging.apps.burbanik-3scale2.cp.fyre.ibm.com/echo/public'
# return 200 in both cases
  1. Test that blacklist + deny no_match combination will deny non-protected endpoints
details

One the image is updated, update (and publish) the policy to include "blacklist" type and "deny" no_match option:

              {
                "name": "keycloak_role_check",
                "version": "builtin",
                "configuration": {
                  "scopes": [
                    {
                      "client_roles": [
                        {
                          "name": "my-role",
                          "client": "{{ jwt.azp }}",
                          "client_type": "liquid",
                          "name_type": "plain"
                        }
                      ],
                      "realm_roles": [],
                      "resource": "/echo/protected",
                      "methods": [
                        "ANY"
                      ],
                      "resource_type": "plain"
                    }
                  ],
                  "type": "blacklist",
                  "no_match": "deny"
                }
              },

Verify that this works as expected now:

% curl -i -k -H "Authorization: Bearer $ACCESS_TOKEN" 'https://api-3scale-apicast-staging.apps.burbanik-3scale2.cp.fyre.ibm.com/echo/protected'
# return 403 for "authorized" or 200 for "non-authorized" application

curl -i -k -H "Authorization: Bearer $ACCESS_TOKEN" 'https://api-3scale-apicast-staging.apps.burbanik-3scale2.cp.fyre.ibm.com/echo/public'
# return 403 in both cases

@borisurbanik
borisurbanik requested a review from a team as a code owner September 7, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant