Skip to content

Commit

Permalink
Add tests for jwt jwksuri (#3511)
Browse files Browse the repository at this point in the history
* Add tests for jwt jwksuri
* fix jwks docs
  • Loading branch information
vepatel authored Feb 3, 2023
1 parent 9198212 commit 44bcbf8
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .github/actions/smoke-tests/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ inputs:
nginx-crt:
description: Nginx cert to use
required: false
azure-ad-secret:
description: Azure Active Directory secret for JWKs
required: false

outputs:
test-results-name:
Expand Down Expand Up @@ -113,6 +116,7 @@ runs:
--self-contained-html \
--durations=10 \
--show-ic-logs=yes \
--ad-secret=${{ inputs.azure-ad-secret }} \
-m ${{ inputs.marker != '' && inputs.marker || '""' }}
working-directory: ./tests
shell: bash
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ jobs:
k8s-version: ${{ matrix.k8s }}
nginx-crt: ${{ contains(matrix.images.image, 'nap') && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}
nginx-key: ${{ contains(matrix.images.image, 'nap') && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}
azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
- name: Upload Test Results
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
Expand Down
2 changes: 1 addition & 1 deletion examples/custom-resources/jwks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ In this example, KeyCloak is deployed as a single container for the purpose of e
## Step 1 - Deploy a TLS Secret
Create a secret with the TLS certificate and key that will be used for TLS termination of the web application and Keycloak:
Create a secret with the TLS certificate and key that will be used for TLS termination of the Keycloak application:
```
$ kubectl apply -f tls-secret.yaml
```
Expand Down
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ def pytest_addoption(parser) -> None:
default=NS_COUNT,
help="Number for namespaces to deploy for use in test_multiple_ns_perf.py",
)
parser.addoption(
"--ad-secret",
action="store",
default=os.environ.get("AZURE_AD_AUTOMATION"),
help="Azure active directory secret for JWKs",
)


# import fixtures into pytest global namespace
Expand Down
9 changes: 9 additions & 0 deletions tests/data/jwt-policy-jwksuri/configmap/nginx-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-config
namespace: nginx-ingress
data:
resolver-addresses: "kube-dns.kube-system.svc.cluster.local"
http-snippets: |
subrequest_output_buffer_size 64k;
10 changes: 10 additions & 0 deletions tests/data/jwt-policy-jwksuri/policies/jwt-policy-valid.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: jwt-policy-valid
spec:
jwt:
realm: MyProductAPI
token: $http_token
jwksURI: https://login.microsoftonline.com/dd3dfd2f-6a3b-40d1-9be0-bf8327d81c50/discovery/v2.0/keys
keyCache: 1h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: virtual-server
spec:
host: virtual-server.example.com
upstreams:
- name: backend2
service: backend2-svc
port: 80
- name: backend1
service: backend1-svc
port: 80
routes:
- path: "/backend1"
action:
pass: backend1
policies:
- name: jwt-policy-valid
- path: "/backend2"
action:
pass: backend2
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: virtual-server
spec:
host: virtual-server.example.com
policies:
- name: jwt-policy-valid
upstreams:
- name: backend2
service: backend2-svc
port: 80
- name: backend1
service: backend1-svc
port: 80
routes:
- path: "/backend1"
action:
pass: backend1
- path: "/backend2"
action:
pass: backend2
118 changes: 118 additions & 0 deletions tests/suite/test_jwt_policies_jwksuri.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import time
from unittest import mock

import pytest
import requests
from settings import TEST_DATA
from suite.utils.policy_resources_utils import create_policy_from_yaml, delete_policy
from suite.utils.resources_utils import replace_configmap_from_yaml, wait_before_test
from suite.utils.vs_vsr_resources_utils import delete_and_create_vs_from_yaml, patch_v_s_route_from_yaml

std_vs_src = f"{TEST_DATA}/virtual-server/standard/virtual-server.yaml"
jwt_pol_valid_src = f"{TEST_DATA}/jwt-policy-jwksuri/policies/jwt-policy-valid.yaml"
jwt_vs_spec_src = f"{TEST_DATA}/jwt-policy-jwksuri/virtual-server/virtual-server-policy-spec.yaml"
jwt_vs_route_src = f"{TEST_DATA}/jwt-policy-jwksuri/virtual-server/virtual-server-policy-route.yaml"
jwt_cm_src = f"{TEST_DATA}/jwt-policy-jwksuri/configmap/nginx-config.yaml"
ad_tenant = "dd3dfd2f-6a3b-40d1-9be0-bf8327d81c50"
client_id = "8a172a83-a630-41a4-9ca6-1e5ef03cd7e7"


def get_token(request):
"""
get jwt token from azure ad endpoint
"""
data = {
"client_id": f"{client_id}",
"scope": ".default",
"client_secret": request.config.getoption("--ad-secret"),
"grant_type": "client_credentials",
}
ad_response = requests.post(f"https://login.microsoftonline.com/{ad_tenant}/oauth2/token", data=data)

if ad_response.status_code == 200:
return ad_response.json()["access_token"]
else:
pytest.fail("Unable to request Azure token endpoint")


@pytest.mark.skip_for_nginx_oss
@pytest.mark.policies
@pytest.mark.parametrize(
"crd_ingress_controller, virtual_server_setup",
[
(
{
"type": "complete",
"extra_args": [
f"-enable-custom-resources",
f"-enable-leader-election=false",
],
},
{
"example": "virtual-server",
"app_type": "simple",
},
)
],
indirect=True,
)
class TestJWTPoliciesVsJwksuri:
@pytest.mark.parametrize("jwt_virtual_server", [jwt_vs_spec_src, jwt_vs_route_src])
def test_jwt_policy_jwksuri(
self,
request,
kube_apis,
ingress_controller_prerequisites,
crd_ingress_controller,
virtual_server_setup,
test_namespace,
jwt_virtual_server,
):
"""
Test jwt-policy in Virtual Server (spec and route) with keys fetched form Azure
"""
replace_configmap_from_yaml(
kube_apis.v1,
ingress_controller_prerequisites.config_map["metadata"]["name"],
ingress_controller_prerequisites.namespace,
jwt_cm_src,
)
pol_name = create_policy_from_yaml(kube_apis.custom_objects, jwt_pol_valid_src, test_namespace)
wait_before_test()

print(f"Patch vs with policy: {jwt_virtual_server}")
delete_and_create_vs_from_yaml(
kube_apis.custom_objects,
virtual_server_setup.vs_name,
jwt_virtual_server,
virtual_server_setup.namespace,
)
resp1 = mock.Mock()
resp1.status_code == 502
counter = 0

while resp1.status_code != 401 and counter < 3:
resp1 = requests.get(
virtual_server_setup.backend_1_url,
headers={"host": virtual_server_setup.vs_host},
)
wait_before_test()
counter = +1

token = get_token(request)

resp2 = requests.get(
virtual_server_setup.backend_1_url,
headers={"host": virtual_server_setup.vs_host, "token": token},
)

delete_policy(kube_apis.custom_objects, pol_name, test_namespace)
delete_and_create_vs_from_yaml(
kube_apis.custom_objects,
virtual_server_setup.vs_name,
std_vs_src,
virtual_server_setup.namespace,
)

assert resp1.status_code == 401 and f"Authorization Required" in resp1.text
assert resp2.status_code == 200 and f"Request ID:" in resp2.text

0 comments on commit 44bcbf8

Please sign in to comment.