This topic shows you how to configure JWT request authentication in Service Mesh to perform source validation, also known as end-user authentication. When receiving a user request, this configuration verifies that the access token in the request header is trusted and authorizes requests from legitimate sources. This topic describes how to configure JWT request authentication for an ingress gateway in ASM to require a trusted access token for service access.
Prerequisites
An ingress gateway is deployed. For more information, see Create an ingress gateway.
Background
This topic uses the httpbin service as an example. You first use a RequestAuthentication policy to restrict requests that access the service through an ingress gateway. This initial policy allows requests with a valid JWT and denies requests with an invalid JWT, but also permits requests that do not have a JWT. Based on this, you can use an authorization policy to further restrict requests in the following two scenarios:
-
Use an authorization policy to require that all requests must contain a JWT to successfully access the service through the ingress gateway.
-
Use an authorization policy to require that all requests must contain a JWT from a specific issuer to successfully access the service through the ingress gateway.
Step 1: Deploy the sample service
-
Enable automatic injection for the default namespace.
-
Log on to the ASM console.
-
In the left-side navigation pane, choose .
-
On the details page of the ASM instance, choose in the left-side navigation pane.
-
On the Global Namespace page, find default and click Enable Automatic Sidecar Proxy Injection in the Automatic Sidecar Injection column.
-
In the Confirm dialog box, click OK.
-
-
Deploy the sample service.
-
Connect to the cluster by using kubectl and the cluster's KubeConfig file.
-
Create a file named httpbin.yaml with the following content.
apiVersion: v1 kind: ServiceAccount metadata: name: httpbin --- apiVersion: v1 kind: Service metadata: name: httpbin labels: app: httpbin service: httpbin spec: ports: - name: http port: 8000 targetPort: 80 selector: app: httpbin --- apiVersion: apps/v1 kind: Deployment metadata: name: httpbin spec: replicas: 1 selector: matchLabels: app: httpbin version: v1 template: metadata: labels: app: httpbin version: v1 spec: serviceAccountName: httpbin containers: - image: docker.io/kennethreitz/httpbin imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 80 -
Run the following command to create the httpbin application.
kubectl apply -f httpbin.yaml -n default
-
Step 2: Create a Gateway and a virtual service
-
Create a Gateway.
-
Log on to the ASM console. In the left-side navigation pane, choose .
-
On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose . On the page that appears, click Create from YAML.
-
Set Namespaces to default, enter the following content into the text box, and then click Create.
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: httpbin-gateway namespace: default spec: selector: istio: ingressgateway servers: - hosts: - '*' port: name: http number: 80 protocol: HTTP
-
-
Create a virtual service.
-
On the details page of the ASM instance, choose in the left-side navigation pane. On the page that appears, click Create from YAML.
-
Set Namespaces to default, enter the following content into the text box, and then click Create.
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: httpbin namespace: default spec: gateways: - httpbin-gateway hosts: - '*' http: - route: - destination: host: httpbin port: number: 8000
-
Step 3: Create a RequestAuthentication policy
-
Create a JWK.
-
In OpenSSL, run the following command to generate a 2048-bit RSA private key.
openssl genrsa -out rsa-private-key.pem 2048 -
Run the following command to generate a public key from the private key.
openssl rsa -in rsa-private-key.pem -pubout -out rsa-public-key.pem -
In an online JWK to PEM Convertor tool, select PEM-to-JWK (RSA Only), enter the public key, and click submit to convert the public key to a JWK.
{"kty":"RSA","e":"AQAB","kid":"59399e22-7a9a-45ed-8c76-7add7863915c","n":"2dnwOlDKEwII9Cyh9w7o59a5y3RS2gWUKYC3HSBJL1FhYIZa7sjTCKxwEuG-vCRQkR6augWxYWseSDfgtyivzi3CxxkF8WnQbECOCGm5xAYKmMcXeOpv0zsJTHN122Tt_tsd6K2OC3yGwKtmp7m-MOpHagqWRqFtvyEOm_1JW1-t0n1VsGSeWww8dvcmnJPKAKHbAU40jdV1hMn9AA3RfSpDY6nfrUkpXA5-aQ6rJRjMn36DatZ5ykVL4LKPOUxZdfK_yNIPkCnwIKesqiOpr4s-iCM8pMiZuejDZ1qoX-uBjggESf4G9_L-laDSeoDmXeOZ9kzN3Jw8ay69ihIFEQ"}
-
-
Create a RequestAuthentication policy.
-
Log on to the ASM console.
-
In the left-side navigation pane, choose .
-
On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column.
-
In the left-side navigation pane of the ASM instance details page, choose . On the page that appears, click Create.
-
On the Create page, configure the parameters and then click Create.
Parameter
Description
Namespaces
Set Namespaces to istio-system.
Name
Enter a name for the policy.
Match Label
Selects the workloads to which the policy applies.
Click Add Matching Label. Set Name to istio and Value to ingressgateway.
JWT Rule Set
Click Add to the right of JWT Rule Set and configure the JWT rule:
-
issuer: The issuer of the JWT. In this topic, set it to testing@asm.test.io.
-
audiences: A list of audiences for the JWT. This specifies which services can use the JWT. Leave this empty to allow access to all services.
-
jwks: The JWT information. Set this to
{"keys":[YOUR_JWK]}. For example, if the JWK from Step 3 is{"kty":"RSA","e":"AQAB","kid":"59399e22-7a9a-45ed-8c76-7add786****"}, setjwksto{"keys":[{"kty":"RSA","e":"AQAB","kid":"59399e22-7a9a-45ed-8c76-7add786****"}]}.
-
-
Step 4: Verify the RequestAuthentication policy
-
Use a tool like JWT.io to encode your JWT request information into a JWT.
In the Decoded section, enter the JWT request information. The tool automatically converts it into a JWT in the Encoded section.
-
HEADER: Set the encryption algorithm to RS256, enter the
kidfrom your JWK, and set the type to JWT. -
PAYLOAD: Set
isstotesting@asm.test.io. You can also add custom information. -
VERIFY SIGNATURE: Enter the public key and private key that you created in Step 3.
In this example, the kid value in the HEADER is
59399e22-7a9a-45ed-8c76-7add7863915c. The PAYLOAD also contains a sub claim with the valuetesting@asm.test.io, an iat claim with the value1623389700, and a custom foo claim with the valuebar. -
-
Access the service through the ingress gateway.
-
Run the following command to send a request with the valid JWT created in the previous step.
curl -I -H "Authorization: Bearer $TOKEN" http://{YOUR_ASM_GATEWAY_ADDRESS}/Expected output:
HTTP/1.1 200 OK server: istio-envoy date: Fri, 18 Mar 2022 07:27:54 GMT -
Run the following command to send a request with an invalid JWT.
curl -I -H "Authorization: Bearer invalidToken" http://{YOUR_ASM_GATEWAY_ADDRESS}/Expected output:
HTTP/1.1 401 Unauthorized www-authenticate: Bearer realm="http://47.98.25*.***/", error="invalid_token" content-length: 79 content-type: text/plain date: Fri, 18 Mar 2022 07:59:00 GMT server: istio-envoy -
Run the following command to send a request without a JWT.
curl -I http://{YOUR_ASM_GATEWAY_ADDRESS}/Expected output:
HTTP/1.1 200 OK server: istio-envoy date: Fri, 18 Mar 2022 07:27:54 GMT
The results confirm the RequestAuthentication policy is working: requests with a valid token or no token succeed, while requests with an invalid token are denied.
-
Step 5: Create an authorization policy
Scenario 1: Restrict service access
Create an authorization policy to require that all requests must contain a JWT to access the service through the ingress gateway.
-
Log on to the ASM console.
-
In the left-side navigation pane, choose .
-
On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column.
-
On the details page of the ASM instance, choose in the left-side navigation pane. On the page that appears, click Create.
-
On the Create page, configure the parameters and then click Create.
In this example, enter
require-jwtfor Name.Parameter
Description
Name
Enter a name for the authorization policy.
Policy Type
Set Policy Type to ALLOW.
Gateway Scope
Click the Gateway Scope tab and set ASM Gateway to ingressgateway. In the Add Request Source section, enable RequestPrincipals and enter * in the text box.
-
Verify the authorization policy.
-
Run the following command to send a request without a JWT.
curl -I http://{YOUR_ASM_GATEWAY_ADDRESS}/Expected output:
HTTP/1.1 401 Unauthorized www-authenticate: Bearer realm="http://47.98.25*.***/", error="invalid_token" content-length: 79 content-type: text/plain date: Fri, 18 Mar 2022 07:59:00 GMT server: istio-envoy -
Run the following command to send a request with a valid JWT.
curl -I -H "Authorization: Bearer $TOKEN" http://{YOUR_ASM_GATEWAY_ADDRESS}/Expected output:
HTTP/1.1 200 OK server: istio-envoy date: Fri, 18 Mar 2022 07:27:54 GMT
The results confirm the authorization policy is working: requests without a JWT are now denied, while requests with a valid token succeed.
-
Scenario 2: Restrict JWT issuers
Create an authorization policy to require that requests must contain a JWT from a specific issuer to access the service through the ingress gateway.
-
Log on to the ASM console.
-
In the left-side navigation pane, choose .
-
On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column.
-
On the details page of the ASM instance, choose in the left-side navigation pane. On the page that appears, click Create.
-
On the Create page, configure the parameters and then click Create.
Parameter
Description
Name
Enter a name for the authorization policy.
Policy Type
Set Policy Type to ALLOW.
Gateway Scope
Click the Gateway Scope tab and set ASM Gateway to ingressgateway. In the Add Request Source section, enable RequestPrincipals and enter testing@asm.test.io/demo@asm.test.io in the text box.
-
Verify that the authorization policy restricts access based on the issuer.
-
Run the following command to send a request with the original JWT.
curl -I -H "Authorization: Bearer $TOKEN" http://{YOUR_ASM_GATEWAY_ADDRESS}/Expected output:
HTTP/1.1 401 Unauthorized www-authenticate: Bearer realm="http://47.98.25*.***/", error="invalid_token" content-length: 79 content-type: text/plain date: Fri, 18 Mar 2022 07:59:00 GMT server: istio-envoyThe request fails because the authorization policy requires the JWT principal to be
testing@asm.test.io/demo@asm.test.io. The principal of the original token, which istesting@asm.test.io/testing@asm.test.io(issuer/subject), does not match. -
Modify the JWT to have a principal of
testing@asm.test.io/demo@asm.test.io.In the JWT tool, set the iss claim to
testing@asm.test.ioand thesubclaim todemo@asm.test.ioin the PAYLOAD section. Keep all other configurations the same as before.// Header { "alg": "RS256", "kid": "59399e22-7a9a-45ed-8c76-7add7863915c", "typ": "JWT" } // Payload { "foo": "bar", "iat": 1623389700, "iss": "testing@asm.test.io", "sub": "demo@asm.test.io" } -
Run the following command to send a request with the newly generated JWT.
curl -I -H "Authorization: Bearer $TOKEN" http://{YOUR_ASM_GATEWAY_ADDRESS}/Expected output:
HTTP/1.1 200 OK server: istio-envoy date: Fri, 18 Mar 2022 07:27:54 GMTThe request succeeds, confirming that the authorization policy correctly restricts access based on the JWT principal.
-