Create and Secure an API with Tyk Operator
Last updated:
Introduction
Tyk Operator allows you to manage your Tyk APIs, policies, and other configurations using Kubernetes Custom Resource Definitions (CRDs). This page will help you create an API using Tyk Operator.
Set Up Tyk OAS API
Setting up OpenAPI Specification (OAS) APIs with Tyk involves preparing an OAS-compliant API definition and configuring it within your Kubernetes cluster using Tyk Operator. This process allows you to streamline API management by storing the OAS definition in a Kubernetes ConfigMap and linking it to Tyk Gateway through a TykOasApiDefinition resource.
Create your Tyk OAS API
Prepare the Tyk OAS API Definition
First, you need to have a complete Tyk OAS API definition file ready. This file will contain all the necessary configuration details for your API in OpenAPI Specification (OAS) format.
Here is an example of what the Tyk OAS API definition might look like. Note that Tyk extension x-tyk-api-gateway
section should be present.
|
|
Save this API definition file (e.g., oas-api-definition.json
) locally.
Tips
You can create and configure your API easily using Tyk Dashboard in a developer environment, and then obtain the Tyk OAS API definition following these instructions:
- Open the Tyk Dashboard
- Navigate to the API you want to manage with the Tyk Operator
- Click on the “Actions” menu button and select “View API Definition.”
- This will display the raw Tyk OAS API definition of your API, which you can then copy and save locally.
Create a ConfigMap for the Tyk OAS API Definition
You need to create a ConfigMap in Kubernetes to store your Tyk OAS API definition. The Tyk Operator will reference this ConfigMap to retrieve the API configuration.
To create the ConfigMap, run the following command:
kubectl create configmap tyk-oas-api-config --from-file=oas-api-definition.json -n tyk
This command creates a ConfigMap named tyk-oas-api-config
in the tyk
namespace (replace tyk
with your actual namespace if different).
Notes
There is inherent size limit to a ConfigMap. The data stored in a ConfigMap cannot exceed 1 MiB. In case your OpenAPI document exceeds this size limit, it is recommended to split your API into smaller sub-APIs for easy management. For details, please consult Best Practices for Describing Large APIs from the OpenAPI initiative.
Notes
If you prefer to create ConfigMap with a manifest using kubectl apply
command, you may get an error that the annotation metadata cannot exceed 256KB. It is because by using kubectl apply
, kubectl
automatically saves the whole configuration in the annotation kubectl.kubernetes.io/last-applied-configuration for tracking changes. Your Tyk OAS API Definition may easily exceed the size limit of annotations (256KB). Therefore, kubectl create
is used here to get around the problem.
Create a TykOasApiDefinition Custom Resource
Now, create a TykOasApiDefinition
resource to tell the Tyk Operator to use the Tyk OAS API definition stored in the ConfigMap.
Create a manifest file named tyk-oas-api-definition.yaml
with the following content:
apiVersion: tyk.tyk.io/v1alpha1
kind: TykOasApiDefinition
metadata:
name: petstore
spec:
tykOAS:
configmapRef:
name: tyk-oas-api-config # Metadata name of the ConfigMap resource that stores the Tyk OAS API Definition
namespace: tyk # Metadata namespace of the ConfigMap resource
keyName: oas-api-definition.json # Key for retrieving Tyk OAS API Definition from the ConfigMap
Apply the TykOasApiDefinition Manifest
Use kubectl
to apply the TykOasApiDefinition
manifest to your cluster:
kubectl apply -f tyk-oas-api-definition.yaml
This command creates a new TykOasApiDefinition
resource in your cluster. The Tyk Operator will watch for this resource and configures Tyk Gateway or Tyk Dashboard with a new API using the provided Tyk OAS API definition.
Verify the Tyk OAS API Creation
To verify that the API has been successfully created, check the status of the TykOasApiDefinition resource:
kubectl get tykoasapidefinition petstore
You should see the status of the resource, which will indicate if the API creation was successful.
NAME DOMAIN LISTENPATH PROXY.TARGETURL ENABLED SYNCSTATUS INGRESSTEMPLATE
petstore /petstore/ https://petstore.swagger.io/v2 true Successful
Test the Tyk OAS API
After the Tyk OAS API has been successfully created, you can test it by sending a request to the API endpoint defined in your OAS file.
For example, if your API endpoint is /store/inventory"
, you can use curl
or any API client to test it:
curl "TYK_GATEWAY_URL/petstore/store/inventory"
Replace TYK_GATEWAY_URL with a URL of Tyk Gateway.
Manage and Update the Tyk OAS API
To make any changes to your API configuration, update the OAS file in your ConfigMap and then re-apply the ConfigMap using kubectl replace
:
kubectl create configmap tyk-oas-api-config --from-file=oas-api-definition.json -n tyk --dry-run=client -o yaml | kubectl replace -f -
The Tyk Operator will automatically detect the change and update the API in the Tyk Gateway.
Notes
kubectl replace
without --save-config
option is used here instead of kubectl apply
because we do not want to save the Tyk OAS API definition in its annotation. If you want to enable --save-config
option or use kubectl apply
, the Tyk OAS API definition size would be further limited to at most 262144 bytes.
Tyk OAS API Example
This example shows the minimum resources and fields required to define a Tyk OAS API using Tyk Operator.
|
|
Here, a ConfigMap
is created that contains the Tyk OAS API Definition with the data
field with key test_oas.json
. This is linked to from a TykOasApiDefinition
resource via spec.tykOAS.configmapRef
.
To apply it, simply save the manifest into a file (e.g., tyk-oas-api.yaml
) and use kubectl apply -f tyk-oas-api.yaml
to create the required resources in your Kubernetes cluster. This command will create the necessary ConfigMap and TykOasApiDefinition resources in the default
namespace.
Secure your Tyk OAS API
Update your Tyk OAS API Definition
First, you’ll modify your existing Tyk OAS API Definition to include the API key authentication configuration.
When creating the Tyk OAS API, you stored your OAS definition in a file named oas-api-definition.json
and created a ConfigMap named tyk-oas-api-config
in the tyk
namespace.
Modify your Tyk OAS API Definition oas-api-definition.json
as follow.
|
|
In this example, we added the following sections to configure key authentication for this API.
components.securitySchemes
defines the authentication method (in this case,apiKey
in the header).security
: Applies the authentication globally to all endpoints.x-tyk-api-gateway.server.authentication
: Tyk-specific extension to enable the authentication scheme.
You can configure your API for any Tyk supported authentication method by following the Client Authentication documentation.
Save your updated API definition in the same file, oas-api-definition.json
.
Update the ConfigMap with the new Tyk OAS API Definition
Update the existing ConfigMap that contains your Tyk OAS API Definition with the following command:
kubectl create configmap tyk-oas-api-config --from-file=oas-api-definition.json -n tyk --dry-run=client -o yaml | kubectl replace -f -
This command updates the existing ConfigMap named tyk-oas-api-config
in the tyk
namespace (replace tyk
with your actual namespace if different) with the new Tyk OAS API Definition stored in oas-api-definition.json
.
Since a TykOasApiDefinition
resource has been created with reference to this ConfigMap in the previous tutorial:
apiVersion: tyk.tyk.io/v1alpha1
kind: TykOasApiDefinition
metadata:
name: petstore
spec:
tykOAS:
configmapRef:
name: tyk-oas-api-config # Metadata name of the ConfigMap resource that stores the Tyk OAS API Definition
namespace: tyk # Metadata namespace of the ConfigMap resource
keyName: oas-api-definition.json # Key for retrieving Tyk OAS API Definition from the ConfigMap
Any changes in the ConfigMap would be detected by Tyk Operator. Tyk Operator will then automatically reconcile the changes and update the API configuration at Tyk.
Verify the changes
Verify that the TykOasApiDefinition
has been updated successfully:
kubectl get tykoasapidefinition petstore -o yaml
Look for the latestTransaction
field in status
:
status:
latestTransaction:
status: Successful
time: "2024-09-16T11:48:20Z"
The Successful status shows that Tyk Operator has reconciled the API with Tyk successfully. The last update time is shown in the time
field.
Test the API Endpoint
Now, test your API endpoint to confirm that it requires an API key.
For example, if your API endpoint is /store/inventory"
, you can use curl
or any API client to test it:
curl -v "TYK_GATEWAY_URL/petstore/store/inventory"
Replace TYK_GATEWAY_URL with a URL of Tyk Gateway.
Request should fail with a 401 Unauthorized
response now as an API key is required for access. Your API has been secured by Tyk Gateway.
Set Up Tyk Classic API
Create a Tyk Classic API
First, specify the details of your API using the ApiDefinition CRD, then deploy it to create the corresponding Kubernetes resource. Tyk Operator will take control of the CRD and create the actual API in the Tyk data plane.
Create an ApiDefinition resource in YAML format
Create a file called httpbin.yaml
, then add the following:
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: true
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
You can also use other sample files from the following pages:
Deploy the ApiDefinition resource
We are going to create an ApiDefinition from the httpbin.yaml file, by running the following command:
$ kubectl apply -f httpbin.yaml
Or, if you don’t have the manifest with you, you can run the following command:
cat <<EOF | kubectl apply -f -
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: true
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
EOF
The ApiDefinition resource is created. You can verify by the following command:
$ kubectl get tykapis
NAME DOMAIN LISTENPATH PROXY.TARGETURL ENABLED
httpbin /httpbin http://httpbin.org true
You can make a request to verify that your API is working:
$ curl -i localhost:8080/httpbin/get
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Host": "httpbin.org",
"User-Agent": "curl/7.77.0",
"X-Amzn-Trace-Id": "Root=1-62161e8c-2a1ece436633f2e42129be2a"
},
"origin": "127.0.0.1, 176.88.45.17",
"url": "http://httpbin.org/get"
}
Understanding the ApiDefinition CRD
We have an ApiDefinition called httpbin
, as specified in spec.name
field, which listens to path /httpbin
and proxies requests to http://httpbin.org, as specified under spec.proxy
field. Now, any requests coming to the /httpbin
endpoint will be proxied to the target URL that we defined in spec.proxy.target_url
, which is http://httpbin.org in our example.
You can visit the ApiDefinition CRD page to see all the latest API Definitions fields and features we support.
Configure Kubernetes service as an upstream target
Tyk Gateway deployed in your Kubernetes cluster can easily access other Kubernetes services as an upstream proxy target.
In the ApiDefinition manifest, set the proxy.target_url
as a Kubernetes Service following DNS for Services and Pods guideline, so that the requests will be proxied to your service.
In general, Kubernetes Services have a <service-name>.<namespace-name>
.svc.cluster.local DNS entry once they are created.
For example, if you have a service called httpbin
in default
namespace, you can contact httpbin
service with httpbin.default.svc
DNS record in the cluster, instead of IP addresses.
Please visit the official Kubernetes documentation for more details.
Suppose you want to create a Deployment of httpbin service using ci/upstreams/httpbin.yaml file. You are going to expose the application through port 8000
as described under the Service specification.
You can create Service and Deployment by either applying the manifest defined in our repository:
$ kubectl apply -f ci/upstreams/httpbin.yaml
Or, if you don’t have the manifest with you, you can run the following command:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: 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:
containers:
- image: docker.io/kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80
EOF
You need to wait until all pods reach READY 1/1
and STATUS Running
state.
Once the pod is ready, you can update your httpbin
API’s target_url
field to proxy your requests to the Service that you created above.
You can check all services in the <ns>
namespace as follows:
$ kubectl get service -n <ns>
You can update your httpbin
as follows:
cat <<EOF | kubectl apply -f -
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: true
protocol: http
active: true
proxy:
target_url: http://httpbin.default.svc:8000
listen_path: /httpbin
strip_listen_path: true
Pay attention to the value of the spec.proxy.target_url
field.
It is set to http://httpbin.default.svc:8000
by following the convention described above (<service_name>.<namespace>.svc:<service_port>
).
Now, if you send your request to the /httpbin
endpoint of the Tyk Gateway, the request will be proxied to the httpbin Service
:
curl -sS http://localhost:8080/httpbin/headers
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Host": "httpbin.default.svc:8000",
"User-Agent": "curl/7.68.0"
}
}
As you can see from the response, the host that your request should be proxied to is httpbin.default.svc:8000
.
Secure your Classic API
Update your API to Require a Key
You might already have realized that our httpbin
API is keyless. If you check the APIDefinition’s specification, the use_keyless
field is set to true
.
Tyk keyless access represents completely open access for your API and causes Tyk to bypass any session-based middleware (middleware that requires access to token-related metadata). Keyless access will enable all requests through.
You can disable keyless access by setting use_keyless
to false.
- Update your
httpbin.yaml
file
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: false
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
- Apply the changes
kubectl apply -f httpbin.yaml
Or, if you don’t have the manifest with you, you can run the following command:
cat <<EOF | kubectl apply -f -
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: false
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
EOF
If you have set use_keyless
to false, the default authentication mode is Authentication token.
Now, to access httpbin
API, you need to include a key to the header. Otherwise, you will get a HTTP 401 Unauthorized
response.
curl -i localhost:8080/httpbin/get
HTTP/1.1 401 Unauthorized
Content-Type: application/json
X-Generator: tyk.io
Date: Thu, 03 Mar 2022 15:47:30 GMT
Content-Length: 46
{
"error": "Authorization field missing"
}
Note
Tyk Operator supported authentication types are listed in the API Definition features section.
Create an API key
You need to generate a key to access the httpbin
API now. Follow this guide to see how to create an API key for your installation.
You can obtain the API name and API ID of our example httpbin
API by following command:
kubectl describe tykapis httpbin
Name: httpbin
Namespace: default
Labels: <none>
Annotations: <none>
API Version: tyk.tyk.io/v1alpha1
Kind: ApiDefinition
Metadata:
...
Spec:
...
Name: httpbin
...
Status:
api_id: ZGVmYXVsdC9odHRwYmlu
Events: <none>
You can obtain the API name and API ID from name
and status.api_id
field.
In our example, it is as follows:
- {API-NAME}: httpbin
- {API-ID}: ZGVmYXVsdC9odHRwYmlu
When you have successfully created a key, you can use it to access the httpbin
API.
curl -H "Authorization: Bearer {Key ID}" localhost:8080/httpbin/get
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Authorization": "Bearer {Key ID}",
"Host": "httpbin.org",
"User-Agent": "curl/7.77.0",
"X-Amzn-Trace-Id": "Root=1-6221de2a-01aa10dd56f6f13f420ba313"
},
"origin": "127.0.0.1, 176.42.143.200",
"url": "http://httpbin.org/get"
}
Since you have provided a valid key along with your request, you do not get a HTTP 401 Unauthorized
response.
Set Up Tyk Classic API Authentication
Client to Gateway Authentication in Tyk ensures secure communication between clients and the Tyk Gateway. Tyk supports various authentication methods to authenticate and authorize clients before they can access your APIs. These methods include API keys, Static Bearer Tokens, JWT, mTLS, Basic Authentication, and more. This document provides example manifests for each authentication method supported by Tyk.
Keyless (Open)
This configuration allows keyless (open) access to the API without any authentication.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin-keyless
spec:
name: httpbin-keyless
use_keyless: true
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
Auth Token (Bearer Token)
This setup requires a bearer token for access.
In the below example, the authentication token is set by default to the Authorization
header of the request. You can customize this behavior by configuring the following fields:
use_cookie
: Set to true to use a cookie value for the token.cookie_name
: Specify the name of the cookie if use_cookie is enabled.use_param
: Set to true to allow the token to be passed as a query parameter.param_name
: Specify the parameter name if use_param is enabled.use_certificate
: Enable client certificate. This allows you to create dynamic keys based on certificates.validate_signature
: Enable signature validation.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin-auth-token
spec:
name: httpbin-auth-token
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
use_standard_auth: true
auth_configs:
authToken:
# Auth Key Header Name
auth_header_name: Authorization
# Use cookie value
use_cookie: false
# Cookie name
cookie_name: ""
# Allow query parameter as well as header
use_param: false
# Parameter name
param_name: ""
# Enable client certificate
use_certificate: false
# Enable Signature validation
validate_signature: false
signature:
algorithm: ""
header: ""
secret: ""
allowed_clock_skew: 0
error_code: 0
JWT
This configuration uses JWT tokens for authentication.
Users can configure JWT authentication by defining the following fields:
jwt_signing_method
: Specify the method used to sign the JWT. Refer to the documentation on JWT Signatures for supported methods.jwt_source
: Specify the public key used for verifying the JWT.jwt_identity_base_field
: Define the identity source, typically set tosub
(subject), which uniquely identifies the user or entity.jwt_policy_field_name
: Specify the claim within the JWT payload that indicates the policy ID to apply.jwt_default_policies
(Optional): Define default policies to apply if no policy claim is found in the JWT payload.
The following example configures an API to use JWT authentication. It specifies the ECDSA signing method and public key, sets the sub
claim as the identity source, uses the pol
claim for policy ID, and assigns a default policy (jwt-policy
SecurityPolicy in default
namespace) if no policy is specified in the token.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin-jwt1
spec:
name: httpbin-jwt1
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin-jwt1
strip_listen_path: true
enable_jwt: true
strip_auth_data: true
jwt_signing_method: ecdsa
# ecdsa pvt: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ2V2WnpMMWdkQUZyODhoYjIKT0YvMk54QXBKQ3pHQ0VEZGZTcDZWUU8zMGh5aFJBTkNBQVFSV3oram42NUJ0T012ZHlIS2N2akJlQlNEWkgycgoxUlR3am1ZU2k5Ui96cEJudVE0RWlNbkNxZk1QV2lacUI0UWRiQWQwRTdvSDUwVnB1WjFQMDg3RwotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0t
# ecdsa pub: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFRVZzL281K3VRYlRqTDNjaHluTDR3WGdVZzJSOQpxOVVVOEk1bUVvdlVmODZRWjdrT0JJakp3cW56RDFvbWFnZUVIV3dIZEJPNkIrZEZhYm1kVDlQT3hnPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t
jwt_source: LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFRVZzL281K3VRYlRqTDNjaHluTDR3WGdVZzJSOQpxOVVVOEk1bUVvdlVmODZRWjdrT0JJakp3cW56RDFvbWFnZUVIV3dIZEJPNkIrZEZhYm1kVDlQT3hnPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0t
jwt_identity_base_field: sub
jwt_policy_field_name: pol
jwt_default_policies:
- default/jwt-policy
---
apiVersion: tyk.tyk.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-policy
spec:
access_rights_array:
- name: httpbin-jwt1
namespace: default
versions:
- Default
active: true
name: jwt-policy
state: active
You can verify the API is properly authenticated with following command:
- JWT with default policy
curl http://localhost:8080/httpbin-jwt1/get -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNTE2MjM5MDIyfQ.rgPyrCJYs2im7zG6im5XUqsf_oAf_Kqk-F6IlLb3yzZCSZvrQObhBnkLKgfmVTbhQ5El7Q6KskXPal5-eZFuTQ'
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Host": "httpbin.org",
"Traceparent": "00-d2b93d763ca27f29181c8e508b5ac0c9-a446afa3bd053617-01",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-6696f0bf-1d9e532c6a2eb3a709e7086b"
},
"origin": "127.0.0.1, 178.128.43.98",
"url": "http://httpbin.org/get"
}
- JWT with explicit policy
curl http://localhost:8080/httpbin-jwt1/get -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0IiwiaWF0IjoxNTE2MjM5MDIyLCJwb2wiOiJaR1ZtWVhWc2RDOXFkM1F0Y0c5c2FXTjUifQ.7nY9TvYgsAZqIHLhJdUPqZtzqU_5T-dcNtCt4zt8YPyUj893Z_NopL6Q8PlF8TlMdxUq1Ff8rt4-p8gVboIqlA'
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip",
"Host": "httpbin.org",
"Traceparent": "00-002adf6632ec20377cb7ccf6c3037e78-3c4cb97c70d790cb-01",
"User-Agent": "curl/8.6.0",
"X-Amzn-Trace-Id": "Root=1-6696f1dd-7f9de5f947c8c73279f7cca6"
},
"origin": "127.0.0.1, 178.128.43.98",
"url": "http://httpbin.org/get"
}
Basic Authentication
This configuration uses Basic Authentication, requiring a username and password for access.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin-basic-auth
spec:
name: Httpbin Basic Authentication
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
use_basic_auth: true
Custom Plugin Auth (go)
This configuration uses a Golang plugin for custom authentication. The following example shows how to create an API definition with a Golang custom plugin for httpbin-go-auth
.
For an example of Golang authentication middleware, see Performing custom authentication with a Golang plugin.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin-go-auth
spec:
name: httpbin-go-auth
use_go_plugin_auth: true # Turn on GO auth
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
custom_middleware:
driver: goplugin
pre:
- name: "AddFooBarHeader"
path: "/mnt/tyk-gateway/example-go-plugin.so"
auth_check:
name: "MyPluginCustomAuthCheck"
path: "/mnt/tyk-gateway/example-go-plugin.so"
Custom Plugin Auth (gRPC)
This configuration uses a gRPC plugin for custom authentication. The following example shows how to create an API definition with a gRPC custom plugin for httpbin-grpc-auth
.
For a detailed walkthrough on setting up Tyk with gRPC authentication plugins, refer to Extending Tyk with gRPC Authentication Plugins.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin-grpc-auth
spec:
name: httpbin-grpc-auth
protocol: http
active: true
enable_coprocess_auth: true
proxy:
target_url: http://httpbin.default.svc:8000
listen_path: /httpbin-grpc-auth
strip_listen_path: true
custom_middleware:
driver: grpc
post_key_auth:
- name: "HelloFromPostKeyAuth"
path: ""
auth_check:
name: foo
path: ""
id_extractor:
extract_from: header
extract_with: value
extractor_config:
header_name: Authorization
Multiple (Chained) Auth
This setup allows for multiple authentication methods to be chained together, requiring clients to pass through each specified authentication provider.
To enable multiple (chained) auth, you should set base_identity_provided_by
field to one of the supported chained enums. Consult the Multi (Chained) Authentication section for the supported auths.
In this example, we are creating an API definition with basic authentication and mTLS with basic authentication as base identity for httpbin-multiple-authentications
.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin-multiple-authentications
spec:
name: Httpbin Multiple Authentications
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
version_data:
default_version: Default
not_versioned: true
versions:
Default:
name: Default
base_identity_provided_by: basic_auth_user
use_basic_auth: true
use_mutual_tls_auth: true
IP Allowlist
To enable IP Allowlist, set the following fields:
enable_ip_whitelisting
: Enables IPs allowlist. When set totrue
, only requests coming from the explicit list of IP addresses defined in (allowed_ips
) are allowed through.allowed_ips
: A list of strings that defines the IP addresses (in CIDR notation) that are allowed access via Tyk.
In this example, only requests coming from 127.0.0.2 is allowed.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: true
protocol: http
active: true
enable_ip_whitelisting: true
allowed_ips:
- 127.0.0.2
proxy:
target_url: http://httpbin.default.svc:8000
listen_path: /httpbin
strip_listen_path: true
IP Blocklist
To enable IP Blocklist, set the following fields:
enable_ip_blacklisting
: Enables IPs blocklist. If set totrue
, requests coming from the explicit list of IP addresses (blacklisted_ips) are not allowed through.blacklisted_ips
: A list of strings that defines the IP addresses (in CIDR notation) that are blocked access via Tyk. This list is explicit and wildcards are currently not supported.
In this example, requests coming from 127.0.0.2 will be forbidden (403
).
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: true
protocol: http
active: true
enable_ip_blacklisting: true
blacklisted_ips:
- 127.0.0.2
proxy:
target_url: http://httpbin.default.svc:8000
listen_path: /httpbin
strip_listen_path: true
Set Up Manifest for GraphQL
In the example below we can see that the configuration is contained within the graphql
configuration object. A GraphQL schema is specified within the schema
field and the execution mode is set to proxyOnly
. The GraphQL public playground is enabled with the path set to /playground
.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: trevorblades
spec:
name: trevorblades
use_keyless: true
protocol: http
active: true
proxy:
target_url: https://countries.trevorblades.com
listen_path: /trevorblades
strip_listen_path: true
graphql:
enabled: true
version: "2"
execution_mode: proxyOnly
schema: |
directive @cacheControl(maxAge: Int, scope: CacheControlScope) on FIELD_DEFINITION | OBJECT | INTERFACE
enum CacheControlScope {
PUBLIC
PRIVATE
}
type Continent {
code: ID!
name: String!
countries: [Country!]!
}
input ContinentFilterInput {
code: StringQueryOperatorInput
}
type Country {
code: ID!
name: String!
native: String!
phone: String!
continent: Continent!
capital: String
currency: String
languages: [Language!]!
emoji: String!
emojiU: String!
states: [State!]!
}
input CountryFilterInput {
code: StringQueryOperatorInput
currency: StringQueryOperatorInput
continent: StringQueryOperatorInput
}
type Language {
code: ID!
name: String
native: String
rtl: Boolean!
}
input LanguageFilterInput {
code: StringQueryOperatorInput
}
type Query {
continents(filter: ContinentFilterInput): [Continent!]!
continent(code: ID!): Continent
countries(filter: CountryFilterInput): [Country!]!
country(code: ID!): Country
languages(filter: LanguageFilterInput): [Language!]!
language(code: ID!): Language
}
type State {
code: String
name: String!
country: Country!
}
input StringQueryOperatorInput {
eq: String
ne: String
in: [String]
nin: [String]
regex: String
glob: String
}
"""The `Upload` scalar type represents a file upload."""
scalar Upload
playground:
enabled: true
path: /playground
Set Up Manifest for HTTP
HTTP Proxy
This example creates a basic API definition that routes requests to listen path /httpbin
to target URL http://httpbin.org
.
Traffic routing can be configured under spec.proxy
:
target_url
defines the upstream address (or target URL) to which requests should be proxied.listen_path
is the base path on Tyk to which requests for this API should be sent. Tyk listens out for any requests coming into the host at this path, on the port that Tyk is configured to run on and processes these accordingly. For example,/api/
or/
or/httpbin/
.strip_listen_path
removes the inbound listen path (as accessed by the client) when generating the outbound request for the upstream service. For example, consider the scenario where the Tyk base address ishttp://acme.com/
, the listen path isexample/
and the upstream URL ishttp://httpbin.org/
: If the client application sends a request tohttp://acme.com/example/get
then the request will be proxied tohttp://httpbin.org/example/get
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: true
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
HTTP Host-based Proxy
spec.domain
is the domain to bind this API to. This enforces domain matching for client requests.
In this example, requests to httpbin.tyk.io
will be proxied to upstream URL http://httpbin.org
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: true
protocol: http
active: true
domain: httpbin.tyk.io
proxy:
target_url: http://httpbin.org
listen_path: /
strip_listen_path: true
HTTPS Proxy
This example creates a API definition that routes requests to a http://httpbin.org via port 8443.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: { }
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-test-cert
spec:
secretName: my-test-tls
dnsNames:
- foo.com
- bar.com
privateKey:
rotationPolicy: Always
issuerRef:
name: selfsigned-issuer
# We can reference ClusterIssuers by changing the kind here.
# The default value is Issuer (i.e. a locally namespaced Issuer)
kind: Issuer
# This is optional since cert-manager will default to this value however
# if you are using an external issuer, change this to that issuer group.
group: cert-manager.io
---
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: httpbin
spec:
name: httpbin
use_keyless: true
protocol: https
listen_port: 8443
certificate_secret_names:
- my-test-tls
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
Set Up Manifest for TCP
This example creates a API definition that proxies request from TCP port 6380
to tcp://localhost:6379
.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: redis-tcp
spec:
name: redis-tcp
active: true
protocol: tcp
listen_port: 6380
proxy:
target_url: tcp://localhost:6379
Set Up Manifest for UDG
UDG v2 (Tyk 3.2 and above)
If you are on Tyk 3.2 and above, you can use the following manifest to create an UDG API. This example configures a Universal Data Graph from a GraphQL datasource and a REST Datasource.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: udg
spec:
name: Universal Data Graph v2a
use_keyless: true
protocol: http
active: true
proxy:
target_url: ""
listen_path: /udg
strip_listen_path: true
version_data:
default_version: Default
not_versioned: true
versions:
Default:
name: Default
graphql:
enabled: true
execution_mode: executionEngine
schema: |
type Country {
name: String
code: String
restCountry: RestCountry
}
type Query {
countries: [Country]
}
type RestCountry {
altSpellings: [String]
subregion: String
population: Int
}
version: "2"
last_schema_update: "2022-10-12T14:27:55.511+03:00"
type_field_configurations: []
playground:
enabled: true
path: /playground
engine:
field_configs:
- disable_default_mapping: false
field_name: countries
path:
- "countries"
type_name: Query
- disable_default_mapping: true #very important for rest APIs
field_name: restCountry
path: []
type_name: Country
data_sources:
- kind: "GraphQL"
name: "countries"
internal: false
root_fields:
- type: Query
fields:
- "countries"
config:
url: "https://countries.trevorblades.com/"
method: "POST"
headers: {}
body: ""
- kind: "REST"
internal: false
name: "restCountries"
root_fields:
- type: "Country"
fields:
- "restCountry"
config:
url: "https://restcountries.com/v2/alpha/{{ .object.code }}"
method: "GET"
body: ""
headers: {}
UDG v1 (Tyk 3.1 or before)
If you are on Tyk 3.1, you can use the following manifest to create an UDG API. This example creates a Universal Data Graph with GraphQL datasource and HTTP JSON datasource.
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: udg
spec:
name: Universal Data Graph Example
use_keyless: true
protocol: http
active: true
proxy:
target_url: ""
listen_path: /udg
strip_listen_path: true
graphql:
enabled: true
execution_mode: executionEngine
schema: |
type Country {
name: String
code: String
restCountry: RestCountry
}
type Query {
countries: [Country]
}
type RestCountry {
altSpellings: [String]
subregion: String
population: String
}
type_field_configurations:
- type_name: Query
field_name: countries
mapping:
disabled: false
path: countries
data_source:
kind: GraphQLDataSource
data_source_config:
url: "https://countries.trevorblades.com"
method: POST
status_code_type_name_mappings: []
- type_name: Country
field_name: restCountry
mapping:
disabled: true
path: ""
data_source:
kind: HTTPJSONDataSource
data_source_config:
url: "https://restcountries.com/v2/alpha/{{ .object.code }}"
method: GET
default_type_name: RestCountry
status_code_type_name_mappings:
- status_code: 200
playground:
enabled: true
path: /playground
Set Up Tyk Streams API
Tyk Streams integrates natively with Tyk OpenAPI Specification (OAS), allowing you to manage APIs as code and automate processes in Kubernetes using Tyk Operator. Setting up Tyk Streams API is similar to configuring a standard Tyk OAS API. You can store the Tyk Streams OAS definition in a Kubernetes ConfigMap and connect it to Tyk Gateway through a TykStreamsApiDefinition
resource.
Create your Tyk Streams API
Prepare the Tyk Streams API Definition
To create a Tyk Streams API, start by preparing a complete Tyk Streams API definition in the OpenAPI Specification (OAS) format. This file must include:
- The
x-tyk-api-gateway
extension for Tyk-specific settings. - The
x-tyk-streaming
extension for Tyk Streams configuration.
Here’s an example of a Tyk Streams API definition:
|
|
Create a TykStreamsApiDefinition Custom Resource
Once your Tyk Streams API definition is ready, use a Kubernetes ConfigMap to store the definition and link it to a TykStreamsApiDefinition
custom resource.
Example manifest:
apiVersion: tyk.tyk.io/v1alpha1
kind: TykStreamsApiDefinition
metadata:
name: simple-stream
spec:
tykStreams:
configmapRef:
name: simple-stream-cm #k8s resource name of configmap
namespace: default #The k8s namespace of the resource being targeted. If Namespace is not provided,
#we assume that the ConfigMap is in the same namespace as TykStreamsApiDefinition resource.
keyName: test_stream.json
---
apiVersion: v1
kind: ConfigMap
metadata:
name: simple-stream-cm
data:
test_stream.json: |-
{
"components": {},
"info": {
"title": "Simple streaming demo",
"version": "1.0.0"
},
"openapi": "3.0.3",
"paths": {},
"x-tyk-api-gateway": {
"info": {
"name": "Simple streaming demo",
"state": {
"active": true
}
},
"server": {
"detailedTracing": {
"enabled": true
},
"listenPath": {
"strip": true,
"value": "/streams/"
}
},
"upstream": {
"url": "https://not-needed"
}
},
"x-tyk-streaming": {
"streams": {
"example-publisher": {
"input": {
"http_server": {
"path": "/pub",
"allowed_verbs": ["POST"],
"timeout": "1s"
}
},
"output": {
"http_server": {
"ws_path": "/ws"
}
}
}
}
}
}
Apply the TykStreamsApiDefinition Manifest
Use the kubectl
command to apply the TykStreamsApiDefinition
manifest to your Kubernetes cluster:
kubectl apply -f tyk-streams-api-definition.yaml
This will create a new TykStreamsApiDefinition
resource. The Tyk Operator watches this resource and configures the Tyk Gateway or Tyk Dashboard with the new API.
Verify the Tyk Streams API Creation
Check the status of the TykStreamsApiDefinition
resource to ensure that the API has been successfully created:
kubectl get tykstreamsapidefinitions simple-stream
You should see output similar to this:
NAME DOMAIN LISTENPATH ENABLED SYNCSTATUS
simple-stream /streams/ true Successful
Manage and Update the Tyk Streams API
To update your API configuration, modify the linked ConfigMap
. The Tyk Operator will automatically detect changes and update the API in the Tyk Gateway.
Secure your Tyk Streams API
To secure your Tyk Streams API, configure security fields in the OAS definition just as you would for a standard Tyk OAS API. For more details, refer to the Secure your Tyk OAS API guide.
Add a Security Policy to your API
To further protect access to your APIs, you will want to add a security policy. Below, we take you through how to define the security policy but you can also find Security Policy Example below.
Define the Security Policy manifest
To create a security policy, you must define a Kubernetes manifest using the SecurityPolicy
CRD. The following example illustrates how to configure a default policy for trial users for a Tyk Classic API named httpbin
, a Tyk OAS API named petstore
, and a Tyk Streams API named http-to-kafka
.
apiVersion: tyk.tyk.io/v1alpha1
kind: SecurityPolicy
metadata:
name: trial-policy # Unique Kubernetes name
spec:
name: Default policy for trial users # Descriptive name for the policy
state: active
active: true
access_rights_array:
- name: httpbin # Kubernetes name of referenced API
namespace: default # Kubernetes namespace of referenced API
kind: ApiDefinition # Omit this field or use `ApiDefinition` if you are referencing Tyk Classic API
versions:
- Default # The default version of Tyk Classic API is "Default"
- name: petstore
namespace: default
kind: TykOasApiDefinition # Use `TykOasApiDefinition` if you are referencing Tyk OAS API
versions:
- "" # The default version of Tyk OAS API is ""
- name: http-to-kafka
namespace: default
kind: TykStreamsApiDefinition # Use `TykStreamsApiDefinition` if you are referencing Tyk Streams API
versions:
- "" # The default version of Tyk Streams API is ""
quota_max: 1000
quota_renewal_rate: 3600
rate: 120
per: 60
throttle_interval: -1
throttle_retry_limit: -1
Save the manifest locally in a file, e.g. trial-policy.yaml
In this example, we have defined a security policy as described below:
Define Security Policy status and metadata
-
name
: A descriptive name for the security policy. -
active
: Marks the policy as active (true or false). -
state
: The current state of the policy. It can have one of three values:active
: Keys connected to this policy are enabled and new keys can be created.draft
: Keys connected to this policy are disabled; no new keys can be created.deny
: Policy is not published to Gateway; no keys can be created.
-
tags
: A list of tags to categorize or label the security policy, e.g.tags: - Hello - World
-
meta_data
: Key-value pairs for additional metadata related to the policy, e.g.meta_data: key: value hello: world
Define Access Lists for APIs
access_rights_array
: Defines the list of APIs that the security policy applies to and the versions of those APIs.name
: The Kubernetes metadata name of the API resource to which the policy grants access.namespace
: The Kubernetes namespace where the API resource is deployed.kind
: Tyk OAS APIs (TykOasApiDefinition
), Tyk Streams (TykStreamsApiDefinition
) and Tyk Classic APIs (ApiDefinition
) can be referenced here. The API format can be specified bykind
field. If omitted,ApiDefinition
is assumed.versions
: Specifies the API versions the policy will cover. If the API is not versioned, include the default version here. The default version of a Classic API is “Default”. The default version of a Tyk OAS API is “”.
In this example, the security policy will apply to an ApiDefinition
resource named httpbin
in the default
namespace, a TykOasApiDefinition
resource named petstore
in the default
namespace, and a TykStreamsApiDefinition
resource named http-to-kafka
in the default
namespace. Note that with Tyk Operator, you do not need to specify API ID as in the raw Policy definition. Tyk Operator will automatically retrieve the API ID of referenced API Definition resources for you.
Define Rate Limits, Usage Quota, and Throttling
rate
: The maximum number of requests allowed per time period (Set to-1
to disable).per
: The time period (in seconds) for the rate limit (Set to-1
to disable).throttle_interval
: The interval (in seconds) between each request retry (Set to-1
to disable).throttle_retry_limit
: The maximum number of retry attempts allowed (Set to-1
to disable).quota_max
: The maximum number of requests allowed over a quota period (Set to-1
to disable).quota_renewal_rate
: The time, in seconds, after which the quota is renewed.
In this example, trial users under this security policy can gain access to the httpbin
API at a rate limit of maximum 120 times per 60 seconds ("rate": 120, "per": 60
), with a usage quota of 1000 every hour ("quota_max": 1000, "quota_renewal_rate": 3600
), without any request throttling (throttle_interval: -1, throttle_retry_limit: -1
).
Apply the Security Policy manifest
Once you have defined your security policy manifest, apply it to your Kubernetes cluster using the kubectl apply
command:
kubectl apply -f trial-policy.yaml
Verify the Security Policy
After applying the manifest, you can verify that the security policy has been created successfully by running:
kubectl describe securitypolicy trial-policy
...
Status:
Latest CRD Spec Hash: 901732141095659136
Latest Tyk Spec Hash: 5475428707334545086
linked_apis:
Kind: ApiDefinition
Name: httpbin
Namespace: default
Kind: TykOasApiDefinition
Name: petstore
Namespace: default
Kind: TykStreamsApiDefinition
Name: http-to-kafka
Namespace: default
pol_id: 66e9a27bfdd3040001af6246
Events: <none>
From the status
field, you can see that this security policy has been linked to httpbin
, petstore
, and http-to-kafka
APIs.
Security policy example
Key-level per-API rate limits and quota
By configuring per-API limits, you can set specific rate limits, quotas, and throttling rules for each API in the access rights array. When these per-API settings are enabled, the API inherits the global limit settings unless specific limits and quotas are set in the limit
field for that API.
The following manifest defines a security policy with per-API rate limits and quotas for two APIs: httpbin
and petstore
.
|
|
With this security policy applied:
For the httpbin
API:
- The rate limit allows a maximum of 10 requests per 60 seconds.
- The quota allows a maximum of 100 requests per hour (3600 seconds).
- There is no throttling or retry limit (throttle_interval and throttle_retry_limit are set to -1).
For the petstore
API:
- The rate limit allows a maximum of 5 requests per 60 seconds.
- The quota allows a maximum of 100 requests per hour (3600 seconds).
- There is no throttling or retry limit (throttle_interval and throttle_retry_limit are set to -1).
Global Rate Limits and Quota:
- All global limits (rate, quota, and throttling) are disabled (-1), so they do not apply.
By setting per-API rate limits and quotas, you gain granular control over how each API is accessed and used, allowing you to apply different limits for different APIs as needed. This configuration is particularly useful when you want to ensure that critical APIs have stricter controls while allowing more flexibility for others. Use this example as a guideline to tailor your security policies to your specific requirements.
Key-level per-endpoint rate limits
By configuring key-level per-endpoint limits, you can restrict the request rate for specific API clients to a specific endpoint of an API.
The following manifest defines a security policy with per-endpoint rate limits for two APIs: httpbin
and petstore
.
|
|
Path based permissions
You can secure your APIs by specifying allowed URLs (methods and paths) for each API within a security policy. This is done using the allowed_urls
field under access_rights_array
.
The following manifest defines a security policy that allows access only to specific URLs and HTTP methods for two APIs: httpbin
(a Tyk Classic API) and petstore
(a Tyk OAS API).
|
|
With this security policy applied:
-
Allowed access:
curl -H "Authorization: Bearer $KEY_AUTH" http://tyk-gw.org/petstore/pet/10
returns a200 OK
response.curl -H "Authorization: Bearer $KEY_AUTH" http://tyk-gw.org/httpbin/get
returns a200 OK
response.
-
Restricted access:
curl -H "Authorization: Bearer $KEY_AUTH" http://tyk-gw.org/petstore/pet
returns a403 Forbidden
response with the message:
{ "error": "Access to this resource has been disallowed" }
curl -H "Authorization: Bearer $KEY_AUTH" http://tyk-gw.org/httpbin/anything
returns a403 Forbidden
response with the message:
{ "error": "Access to this resource has been disallowed" }
Partitioned policies
Partitioned policies allow you to selectively enforce different segments of a security policy, such as quota, rate limiting, access control lists (ACL), and GraphQL complexity rules. This provides flexibility in applying different security controls as needed.
To configure a partitioned policy, set the segments you want to enable in the partitions
field:
apiVersion: tyk.tyk.io/v1alpha1
kind: SecurityPolicy
metadata:
name: partitioned-policy-example
spec:
name: Partitioned Policy Example
state: active
active: true
access_rights_array:
- name: httpbin # Kubernetes name of referenced API
namespace: default # Kubernetes namespace of referenced API
kind: ApiDefinition # `ApiDefinition` (Default), `TykOasApiDefinition` or `TykStreamsApiDefinition`
versions:
- Default # The default version of Tyk Classic API is "Default"
- name: petstore
namespace: default
kind: TykOasApiDefinition # Use `TykOasApiDefinition` if you are referencing Tyk OAS API
versions:
- "" # The default version of Tyk OAS API is ""
partitions:
quota: false # Do not enforce quota rules
rate_limit: false # Do not enforce rate limiting rules
acl: true # Enforce access control rules
complexity: false # Do not enforce GraphQL complexity rules
quota
: Set to true to enforce quota rules (limits the number of requests allowed over a period).rate_limit
: Set to true to enforce rate limiting rules (limits the number of requests per second or minute).acl
: Set to true to enforce access control rules (controls which APIs or paths can be accessed).complexity
: Set to true to enforce GraphQL complexity rules (limits the complexity of GraphQL queries to prevent resource exhaustion).
Migrate Existing APIs to Tyk Operator
If you have existing APIs and Policies running on your Tyk platform, and you want to start using Tyk Operator to manage them, you probably would not want to re-create the APIs and Policies on the platform using Operator CRDs. It is because you will lose keys, policies, and analytics linked to the APIs. You can instead link existing APIs and Policies to a CRD by specifying the API ID or Policy ID in the CRD spec. This way, Operator will update the existing API or Policy according to the CRD spec. Any keys, policies and analytics linked to the API will continue to operate the same. This is great for idempotency.
Export existing configurations to CRDs
Instead of creating the API and Policy CRDs from scratch, you can try exporting them from Dashboard using a snapshot tool. You can find the detail usage guide here. This is great if you want to have a quick start. However, this is still a PoC feature so we recommend you to double check the output files before applying them to your cluster.
Migration of existing API
If there are existing APIs that you want to link to a CRD, it’s very easy to do so. You need to simply add the api_id
from your API Definition to the YAML of your ApiDefinition
type. Then, the Operator will take care of the rest.
Example:
- From the existing API Definition, grab the following field:
"api_id": "5e0fac4845bb46c77543be28300fd9d7"
- Simply add this value to your YAML, in the
spec.api_id
field:
apiVersion: tyk.tyk.io/v1alpha1
kind: ApiDefinition
metadata:
name: my-existing-api
spec:
api_id: 5e0fac4845bb46c77543be28300fd9d7
name: existing API
protocol: http
active: true
proxy:
target_url: http://httpbin.org
listen_path: /httpbin
strip_listen_path: true
- Then apply your changes:
$ kubectl apply -f config/samples/httpbin_protected.yaml
apidefinition.tyk.tyk.io/my-existing-api created
Note
The source of truth for the API definition is now the CRD, meaning it will override any differences in your existing API definition.
Migration of existing Policy
If you have existing pre-Operator policies, you can easily link them to a CRD, which will allow you to modify them through the YAML moving forward. Simply set the id field in the SecurityPolicy YAML to the _id field in the existing Policy’s JSON. This will allow the Operator to make the link. Note that the YAML becomes the source of truth and will overwrite any changes between it and the existing Policy.
Example:
-
Find out your existing Policy ID, e.g.
5f8f3933f56e1a5ffe2cd58c
-
Stick the policy ID
5f8f3933f56e1a5ffe2cd58c
into the YAML’sspec.id
field like below
my-security-policy.yaml:
apiVersion: tyk.tyk.io/v1alpha1
kind: SecurityPolicy
metadata:
name: new-httpbin-policy
spec:
id: 5f8f3933f56e1a5ffe2cd58c
name: My New HttpBin Policy
state: active
active: true
access_rights_array:
- name: new-httpbin-api # name of your ApiDefinition object.
namespace: default # namespace of your ApiDefinition object.
versions:
- Default
The spec.access_rights_array
field of the YAML must refer to the ApiDefinition object that the policy identified by the id will affect.
To find available ApiDefinition objects:
$ kubectl get tykapis -A
NAMESPACE NAME DOMAIN LISTENPATH PROXY.TARGETURL ENABLED
default new-httpbin-api /httpbin http://httpbin.org true
- And then apply this file:
$ kubectl apply -f my-security-policy.yaml
securitypolicy.tyk.tyk.io/new-httpbin-policy created
Now the changes in the YAML were applied to the existing Policy. You can now manage this policy through the CRD moving forward.
Note, if this resource is unintentionally deleted, the Operator will recreate it with the same id
field as above, allowing keys to continue to work as before the delete event.
Idempotency
Because of the ability to declaratively define the api_id
, this gives us the ability to preserve Keys that are tied to APIs or policies which are tied to APIs.
Imagine any use case where you have keys tied to policies, and policies tied to APIs.
Now imagine that these resources are unintentionally destroyed. Our database goes down, or our cluster, or something else.
Well, using the Tyk Operator, we can easily re-generate all our resources in a non-destructive fashion. That’s because the operator intelligently constructs the unique ID using the unique namespaced name of our CRD resources. For that reason.
Alternatively, if you don’t explicitly state it, it will be hard-coded for you by Base64 encoding the namespaced name of the CRD.
For example:
- we have keys tied to policies tied to APIs in production.
- Our production DB gets destroyed, all our Policies and APIs are wiped
- The Tyk Operator can resync all the changes from our CRDs into a new environment, by explicitly defining the Policy IDs and API IDs as before.
- This allows keys to continue to work normally as Tyk resources are generated idempotently through the Operator.