Skip to content

Latest commit

 

History

History
392 lines (321 loc) · 11.7 KB

File metadata and controls

392 lines (321 loc) · 11.7 KB
title jwe-decrypt
keywords
Apache APISIX
API Gateway
Plugin
JWE Decrypt
jwe-decrypt
description The jwe-decrypt Plugin decrypts JWE authorization headers in requests directed to Routes or Services, enhancing API security.

import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';

Description

The jwe-decrypt Plugin decrypts JWE authorization headers in requests sent to APISIX Routes or Services.

This Plugin adds an endpoint /apisix/plugin/jwe/encrypt for JWE encryption. For decryption, the key should be configured in Consumer.

Attributes

Consumer

Name Type Required Default Valid values Description
key string True A unique key that identifies the Credential for a Consumer.
secret string True 32 characters The shared symmetric encryption/decryption key. You can also store it in an environment variable and reference it using the env:// prefix, or in a secret manager such as HashiCorp Vault's KV secrets engine, and reference it using the secret:// prefix.
is_base64_encoded boolean False false Set to true if the secret is base64 encoded. Note that after enabling is_base64_encoded, the secret length may exceed 32 characters. You only need to make sure the decoded length is still 32 characters.

Route or Service

Name Type Required Default Valid values Description
header string True Authorization The header to get the token from.
forward_header string True Authorization Name of the header that passes the plaintext to the Upstream.
strict boolean False true If true, throw a 403 error if JWE token is missing from the request. If false, do not throw an error when JWE token is not found.

Examples

The examples below demonstrate how you can work with the jwe-decrypt Plugin for different scenarios.

:::note

You can fetch the admin_key from config.yaml and save to an environment variable with the following command:

admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')

:::

Expose JWE Encryption Endpoint and Generate JWE Token

The following example demonstrates how to expose the JWE encryption endpoint and generate a JWE token.

The jwe-decrypt Plugin creates an internal endpoint at /apisix/plugin/jwe/encrypt to encrypt JWE. Expose the endpoint with the public-api Plugin:

curl "http://127.0.0.1:9180/apisix/admin/routes/jwe-encrypt-api" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "uri": "/apisix/plugin/jwe/encrypt",
    "plugins": {
      "public-api": {}
    }
  }'

Create a Consumer with jwe-decrypt and configure the decryption key:

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "username": "jack",
    "plugins": {
      "jwe-decrypt": {
        "key": "jack-key",
        "secret": "key-length-should-be-32-chars123"
      }
    }
  }'

Expose the JWE encryption endpoint and create a Consumer with jwe-decrypt Credential:

consumers:
  - username: jack
    plugins:
      jwe-decrypt:
        key: jack-key
        secret: key-length-should-be-32-chars123
services:
  - name: jwe-encrypt-api-service
    routes:
      - name: jwe-encrypt-api-route
        uris:
          - /apisix/plugin/jwe/encrypt
        plugins:
          public-api: {}
    upstream:
      type: roundrobin
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1

Synchronize the configuration to the gateway:

adc sync -f adc.yaml

Create a Consumer with jwe-decrypt and expose the JWE encryption endpoint with the public-api Plugin:

apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
  namespace: aic
  name: jack
spec:
  gatewayRef:
    name: apisix
  plugins:
    - name: jwe-decrypt
      config:
        key: jack-key
        secret: key-length-should-be-32-chars123
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
  namespace: aic
  name: jwe-encrypt-api-plugin-config
spec:
  plugins:
    - name: public-api
      config:
        _meta:
          disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  namespace: aic
  name: jwe-encrypt-api-route
spec:
  parentRefs:
    - name: apisix
  rules:
    - matches:
        - path:
            type: Exact
            value: /apisix/plugin/jwe/encrypt
      filters:
        - type: ExtensionRef
          extensionRef:
            group: apisix.apache.org
            kind: PluginConfig
            name: jwe-encrypt-api-plugin-config

Apply the configuration to your cluster:

kubectl apply -f jwe-encrypt-api-ic.yaml

ApisixConsumer only supports authentication plugins via the authParameter field, and jwe-decrypt is not among the supported types. This example cannot be completed using the APISIX Ingress Controller.

Send a request to the encryption endpoint with Consumer key to encrypt some sample data in the payload:

curl "http://127.0.0.1:9080/apisix/plugin/jwe/encrypt?key=jack-key" \
  --data-urlencode 'payload={"uid":10000,"uname":"test"}' -G

You should see a response similar to the following, with the JWE encrypted data in the response body:

eyJraWQiOiJqYWNrLWtleSIsImFsZyI6ImRpciIsImVuYyI6IkEyNTZHQ00ifQ..MTIzNDU2Nzg5MDEy.IUFW_q4igO_wvf63i-3VwV0MEetPL9C20tlgcQ.fveViMUi0ijJlQ19D7kDrg

Decrypt Data with JWE

The following example demonstrates how to decrypt the previously generated JWE token.

Create a Route with jwe-decrypt to decrypt the authorization header:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "jwe-decrypt-route",
    "uri": "/anything/jwe",
    "plugins": {
      "jwe-decrypt": {
        "header": "Authorization",
        "forward_header": "Authorization"
      }
    },
    "upstream": {
      "type": "roundrobin",
      "nodes": {
        "httpbin.org:80": 1
      }
    }
  }'
services:
  - name: jwe-decrypt-service
    routes:
      - name: jwe-decrypt-route
        uris:
          - /anything/jwe
        plugins:
          jwe-decrypt:
            header: Authorization
            forward_header: Authorization
    upstream:
      type: roundrobin
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1

Synchronize the configuration to the gateway:

adc sync -f adc.yaml
apiVersion: v1
kind: Service
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  type: ExternalName
  externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
  namespace: aic
  name: jwe-decrypt-plugin-config
spec:
  plugins:
    - name: jwe-decrypt
      config:
        header: Authorization
        forward_header: Authorization
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  namespace: aic
  name: jwe-decrypt-route
spec:
  parentRefs:
    - name: apisix
  rules:
    - matches:
        - path:
            type: Exact
            value: /anything/jwe
      filters:
        - type: ExtensionRef
          extensionRef:
            group: apisix.apache.org
            kind: PluginConfig
            name: jwe-decrypt-plugin-config
      backendRefs:
        - name: httpbin-external-domain
          port: 80

Apply the configuration to your cluster:

kubectl apply -f jwe-decrypt-ic.yaml

ApisixConsumer only supports authentication plugins via the authParameter field, and jwe-decrypt is not among the supported types. This example cannot be completed using the APISIX Ingress Controller.

Send a request to the Route with the JWE encrypted data in the Authorization header:

curl "http://127.0.0.1:9080/anything/jwe" -H 'Authorization: eyJraWQiOiJqYWNrLWtleSIsImFsZyI6ImRpciIsImVuYyI6IkEyNTZHQ00ifQ..MTIzNDU2Nzg5MDEy.IUFW_q4igO_wvf63i-3VwV0MEetPL9C20tlgcQ.fveViMUi0ijJlQ19D7kDrg'

You should see a response similar to the following, where the Authorization header shows the plaintext of the payload:

{
  "args": {},
  "data": "",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Authorization": "{\"uid\":10000,\"uname\":\"test\"}",
    "Host": "127.0.0.1",
    "User-Agent": "curl/8.1.2",
    "X-Amzn-Trace-Id": "Root=1-6510f2c3-1586ec011a22b5094dbe1896",
    "X-Forwarded-Host": "127.0.0.1"
  },
  "json": null,
  "method": "GET",
  "origin": "127.0.0.1, 119.143.79.94",
  "url": "http://127.0.0.1/anything/jwe"
}