consumer-restriction
The consumer-restriction plugin enables access controls based on consumer name, route ID, service ID, or consumer group ID.
The plugin needs to work with authentication plugins, such as key-auth and jwt-auth, which means you should always create at least one consumer in your use case. See examples below for more details.
Examples
The examples below demonstrate how you can configure consumer-restriction plugin for different scenarios.
While the examples use key-auth as the authentication method, you can easily adjust to other authentication plugins based on your needs.
Restrict Access by Consumers
The example below demonstrates how you can use the consumer-restriction plugin on a route to restrict consumer access by consumer names, where consumers are authenticated with key-auth.
- Admin API
- ADC
- Ingress Controller
Create a consumer JohnDoe:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "JohnDoe"
}'
Create key-auth credential for the consumer:
curl "http://127.0.0.1:9180/apisix/admin/consumers/JohnDoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'
Create a second consumer JaneDoe:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "JaneDoe"
}'
Create key-auth credential for the consumer:
curl "http://127.0.0.1:9180/apisix/admin/consumers/JaneDoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-jane-key-auth",
"plugins": {
"key-auth": {
"key": "jane-key"
}
}
}'
Next, create a route with key authentication enabled, and configure consumer-restriction to allow only consumer JaneDoe:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "consumer-restricted-route",
"uri": "/get",
"plugins": {
"key-auth": {},
"consumer-restriction": {
"whitelist": ["JaneDoe"]
}
},
"upstream" : {
"nodes": {
"httpbin.org":1
}
}
}'
consumers:
- username: JohnDoe
credentials:
- name: cred-john-key-auth
type: key-auth
config:
key: john-key
- username: JaneDoe
credentials:
- name: cred-jane-key-auth
type: key-auth
config:
key: jane-key
services:
- name: consumer-restriction-service
routes:
- name: consumer-restricted-route
uris:
- /get
plugins:
key-auth: {}
consumer-restriction:
whitelist:
- "JaneDoe"
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
When consumers are configured using the Ingress Controller, the consumer name is generated in the format namespace_consumername. For example, a consumer named janedoe in the aic namespace becomes aic_janedoe. Use this format in the whitelist or blacklist of consumer-restriction.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: johndoe
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: john-key-auth
config:
key: john-key
---
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: janedoe
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: jane-key-auth
config:
key: jane-key
---
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: consumer-restriction-plugin-config
spec:
plugins:
- name: key-auth
config:
_meta:
disable: false
- name: consumer-restriction
config:
whitelist:
- "aic_janedoe"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: consumer-restriction-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /get
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: consumer-restriction-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: johndoe
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: john-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: janedoe
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: jane-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: consumer-restriction-route
spec:
ingressClassName: apisix
http:
- name: consumer-restriction-route
match:
paths:
- /get
upstreams:
- name: httpbin-external-domain
plugins:
- name: key-auth
enable: true
- name: consumer-restriction
enable: true
config:
whitelist:
- "aic_janedoe"
Apply the configuration to your cluster:
kubectl apply -f consumer-restriction-ic.yaml
Send a request to the route as consumer JohnDoe:
curl -i "http://127.0.0.1:9080/get" -H 'apikey: john-key'
You should receive an HTTP/1.1 403 Forbidden response with the following message:
{"message":"The consumer_name is forbidden."}
Send another request to the route as consumer JaneDoe:
curl -i "http://127.0.0.1:9080/get" -H 'apikey: jane-key'
You should receive an HTTP/1.1 200 OK response, showing the consumer access is permitted.
Restrict Access by Consumers and HTTP Methods
The example below demonstrates how you can use the consumer-restriction plugin on a route to restrict consumer access by consumer name and HTTP methods, where consumers are authenticated with key-auth.
- Admin API
- ADC
- Ingress Controller
Create a consumer JohnDoe:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "JohnDoe"
}'
Create key-auth credential for the consumer:
curl "http://127.0.0.1:9180/apisix/admin/consumers/JohnDoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'
Create a second consumer JaneDoe:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "JaneDoe"
}'
Create key-auth credential for the consumer:
curl "http://127.0.0.1:9180/apisix/admin/consumers/JaneDoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-jane-key-auth",
"plugins": {
"key-auth": {
"key": "jane-key"
}
}
}'
Next, create a route with key authentication enabled, and use consumer-restriction to allow only the configured HTTP methods by consumers:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "consumer-restricted-route",
"uri": "/anything",
"plugins": {
"key-auth": {},
"consumer-restriction": {
"allowed_by_methods":[
{
"user": "JohnDoe",
"methods": ["GET"]
},
{
"user": "JaneDoe",
"methods": ["POST"]
}
]
}
},
"upstream" : {
"nodes": {
"httpbin.org":1
}
}
}'
consumers:
- username: JohnDoe
credentials:
- name: cred-john-key-auth
type: key-auth
config:
key: john-key
- username: JaneDoe
credentials:
- name: cred-jane-key-auth
type: key-auth
config:
key: jane-key
services:
- name: consumer-restriction-service
routes:
- name: consumer-restricted-route
uris:
- /anything
plugins:
key-auth: {}
consumer-restriction:
allowed_by_methods:
- user: "JohnDoe"
methods:
- "GET"
- user: "JaneDoe"
methods:
- "POST"
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: johndoe
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: john-key-auth
config:
key: john-key
---
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: janedoe
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: jane-key-auth
config:
key: jane-key
---
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: consumer-restriction-methods-config
spec:
plugins:
- name: key-auth
config:
_meta:
disable: false
- name: consumer-restriction
config:
allowed_by_methods:
- user: "aic_johndoe"
methods:
- "GET"
- user: "aic_janedoe"
methods:
- "POST"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: consumer-restriction-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: consumer-restriction-methods-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f consumer-restriction-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: johndoe
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: john-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: janedoe
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: jane-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: consumer-restriction-route
spec:
ingressClassName: apisix
http:
- name: consumer-restriction-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: key-auth
enable: true
- name: consumer-restriction
enable: true
config:
allowed_by_methods:
- user: "aic_johndoe"
methods:
- "GET"
- user: "aic_janedoe"
methods:
- "POST"
Apply the configuration to your cluster:
kubectl apply -f consumer-restriction-ic.yaml
Send a POST request to the route as consumer JohnDoe:
curl -i "http://127.0.0.1:9080/anything" -X POST -H 'apikey: john-key'
You should receive an HTTP/1.1 403 Forbidden response with the following message:
{"message":"The consumer_name is forbidden."}
Now, send a GET request to the route as consumer JohnDoe:
curl -i "http://127.0.0.1:9080/anything" -X GET -H 'apikey: john-key'
You should receive an HTTP/1.1 200 OK response, showing the consumer access is permitted.
You can also verify the configurations by sending requests as consumer JaneDoe and observe the behaviours match up to what was configured in the consumer-restriction plugin on the route.
Restricting by Service ID
The example below demonstrates how you can use the consumer-restriction plugin to restrict consumer access by service ID, where the consumer is authenticated with key-auth.
- Admin API
- ADC
- Ingress Controller
Create two sample services:
curl "http://127.0.0.1:9180/apisix/admin/services" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "srv-1",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org":1
}
}
}'
curl "http://127.0.0.1:9180/apisix/admin/services" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "srv-2",
"upstream": {
"type": "roundrobin",
"nodes": {
"mock.api7.ai":1
}
}
}'
Next, create a consumer with key-auth and configure consumer-restriction to allow only srv-1 service:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "JohnDoe",
"plugins": {
"key-auth": {
"key": "john-key"
},
"consumer-restriction": {
"type": "service_id",
"whitelist": ["srv-1"]
}
}
}'
Finally, create two routes, with each belonging to one of the services created earlier:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "srv-1-route",
"uri": "/anything",
"service_id": "srv-1"
}'
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "srv-2-route",
"uri": "/srv-2",
"service_id": "srv-2"
}'
consumers:
- username: JohnDoe
plugins:
key-auth:
key: john-key
consumer-restriction:
type: service_id
whitelist:
- "srv-1"
services:
- name: srv-1
routes:
- name: srv-1-route
uris:
- /anything
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
- name: srv-2
routes:
- name: srv-2-route
uris:
- /srv-2
upstream:
type: roundrobin
nodes:
- host: mock.api7.ai
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
When routes are configured using the Ingress Controller, APISIX service IDs are auto-generated as the hash of {namespace}_{routeName}_{ruleIndex}. These IDs cannot be easily predetermined. Consider using consumer name-based restriction.
Send a request to the route in the srv-1 service:
curl -i "http://127.0.0.1:9080/anything" -H 'apikey: john-key'
You should receive an HTTP/1.1 200 OK response, showing the consumer access is permitted.
Send a request to the route in the srv-2 service:
curl -i "http://127.0.0.1:9080/srv-2" -H 'apikey: john-key'
You should receive an HTTP/1.1 401 Unauthorized response with the following message:
{"message":"The request is rejected, please check the service_id for this request"}