Skip to content

Latest commit

 

History

History
153 lines (129 loc) · 4.76 KB

File metadata and controls

153 lines (129 loc) · 4.76 KB

Test OAuth Client

The test OAuth client is a basic pod that contains the curl command line tool, so can make HTTP requests.
The client presents its service account token as an OAuth client credential.

Kubernetes Settings

The client uses a sidecar that is instructed to use an Istio sidecar with a SPIRE identity.
This enables it to call the authorization server using mutual TLS.
It also loads a service account token to present to the OAuth token endpoint:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: oauthclient
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: oauthclient
spec:
  replicas: 1
  selector:
    matchLabels:
      app: oauthclient
  template:
    metadata:
      labels:
        app: oauthclient
        sidecar.istio.io/inject: 'true'
        spire-managed-identity: 'true'
      annotations:
        inject.istio.io/templates: 'sidecar,spire'
    spec:
      serviceAccountName: oauthclient
      containers:
      - name: oauthclient
        image: oauthclient:v1
        volumeMounts:
        - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
          name: client-assertion-location
      volumes:
      - name: client-assertion-location
        projected:
          sources:
          - serviceAccountToken:
              path: token
              expirationSeconds: 3600
              audience: 'https://login.democluster.example'

Get a Shell

Once the client is deployed, get a remote shell to its container:

OAUTHCLIENT=$(kubectl -n applications get pods --selector='app=oauthclient' -o=name)
kubectl -n applications exec -it $OAUTHCLIENT -- bash

View the Service Account Token

From the container, run the following command to see its service account token:

cat /var/run/secrets/kubernetes.io/serviceaccount/token

In a JWT viewer, this is the payload:

{
  "aud": [
    "https://login.democluster.example"
  ],
  "exp": 1724344795,
  "iat": 1724337595,
  "iss": "https://kubernetes.default.svc.cluster.local",
  "jti": "c39a0c1f-e5c9-4617-bc1e-055605c7b491",
  "kubernetes.io": {
    "namespace": "applications",
    "node": {
      "name": "example-worker",
      "uid": "8c948d13-bd4b-4f47-aa67-0c369b885ff1"
    },
    "pod": {
      "name": "oauthclient-5f9d7465d8-g4j88",
      "uid": "5729ec3d-7e40-430f-b043-1e76534f0f29"
    },
    "serviceaccount": {
      "name": "oauthclient",
      "uid": "78e4dd18-ce09-4095-abbd-13c0f8513fe2"
    }
  },
  "nbf": 1724337595,
  "sub": "system:serviceaccount:applications:oauthclient"
}

Act as an OAuth Client

Then run a client credentials request over plain HTTP, supplying the above JWT as a client assertion.
The client's sidecar calls to the authorization server's sidecar, which upgrades the connection to use mutual TLS.
The result should be a response that contains OAuth tokens:

SERVICE_ACCOUNT_TOKEN="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
curl -X POST http://curity-idsvr-runtime-svc.authorizationserver:8443/oauth/v2/oauth-token \
     -H 'Content-Type: application/x-www-form-urlencoded' \
     -d 'grant_type=client_credentials' \
     -d 'client_id=oauthclient' \
     -d "client_assertion=$SERVICE_ACCOUNT_TOKEN" \
     -d 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
     -d 'scope=products'

At the time of writing, the default authorization server implements client assertions according to the OpenID Connect Core specification.
This leads to the error explained in Best Current Practice for OAuth 2.0 Client Authentication in Workload Environments.
There is an active product request to enable usage of the RFC7523 behavior, which will fix this issue.

Using JWT SVIDs

The same pattern can be implemented by SPIRE-issued JWT SVIDs if you prefer.
The SPIFFE helper can be configured with properties like these:

jwt_svids = [{jwt_audience="https://login.democluster.example/oauth/v2/oauth-anonymous", jwt_svid_file_name="jwt_svid.token"}]
jwt_bundle_file_name  = "jwt_bundle.json"

A workload then receives JWT SVID documents with payloads of this form:

{
  "aud": [
    "https://login.democluster.example"
  ],
  "exp": 1722005575,
  "iat": 1722001975,
  "iss": "https://oidc-discovery.democluster.internal",
  "sub": "spiffe://democluster.internal/ns/applications/sa/oauthclient"
}

The authorization server can use the internal SPIRE JWKS URI to validate JWT SVIDs:

curl -i -k https://spire-spiffe-oidc-discovery-provider.spire-server/keys

The dbclient workload is configured to download JWT SVIDs.
Therefore you can use it to view some downloaded JWT SVID documents.