API
Manage APIs with Traefik Hub.
Introduction
APIs, or Application Programming Interfaces, serve as the foundational components of contemporary technology and business frameworks. Essentially, an API functions as a software intermediary facilitating communication between two distinct applications. This communication spans various connections: between servers themselves, applications and servers, between end-users and servers. Traefik Hub API management provides a set of tools and processes for managing these APIs effectively and at scale.
The implementation of an API is served by a Kubernetes Service and exposed by a Kubernetes Ingress, HTTPRoute, (or Traefik IngressRoute) object, which allows broad access to the API. However, most APIs require more precise control over access and usage. API owners need to regulate who can use their API and how much they can utilize it. They also need tools to monitor usage, identify patterns, and effectively manage the API's lifecycle.
In such cases, the API can be elevated to a managed status.
This is achieved by creating an API object, which is then linked to the API exposure object (Ingress
, IngressRoute
or HTTPRoute
).
Once promoted, the API can be controlled through other objects:
- APIPlan to control usage limits, regulating how much of the API can be utilized.
- APIBundle to group one or more APIs together, enabling efficient management through plans.
- APIVersion to manage multiple versions of the API.
- Managed Subscription to allow API managers to grant access to APIs for specific applications based on pre-negotiated agreements with API consumers.
The API Object
The API object serves as the foundation for managing an API. It defines the specification or the versions of your API. Since APIs can evolve and sometimes require multiple versions, API objects are categorized into two groups:
- Standalone API: Contains the definition of a single version.
- Versioned API: References APIVersion objects, each providing the definition of a separate version.
The definition of an API is provided by its OpenAPI specification document. This document is served either by the Kubernetes Service or at a remote location. When configured, the specification is used by the APIPortal for displaying the documentation of the API and used for advance access management.
Traefik Hub regularly fetches your OpenAPI specification to ensure that your definition remains aligned with your implementation.
The APIPortal dynamically renders documentation based on your API specification.
When testing endpoints via the "Send API Request" button, the call is made in accordance with the OpenAPI servers
field specified in your API specification.
You have the option to override this value within the API object by providing a new list of servers in the override
field:
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: hello-api
namespace: apps
spec:
openApiSpec:
path: /openapi.yaml
override:
servers:
- url: https://api.example.com/hello
The OpenAPI specification can be omitted when no such document exists. In this case, some of the Traefik Hub features won't be available.
The resource defining the API specification (API or APIVersion object) is then linked to the resource responsible for exposing the API's implementation. This link is established by adding an annotation to the Ingress object, as shown in the following section.
Once an API becomes managed by Traefik Hub, access needs to be granted using APIAccess objects.
Middlewares can be added to Ingress, IngressRoute, and HTTPRoute in a similar manner as in Traefik.
API authentication occurs prior to the execution of any configured middlewares. Advanced operation filtering is performed after all the configured middlewares have been executed.
Standalone API
This example presents how an existing API exposed by an Ingress can be promoted into a managed API:
- Ingress
- IngressRoute
- HTTPRoute
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-api-ingress
namespace: apps
spec:
rules:
- host: api.example.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: hello-api-service
port:
number: 8080
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: hello-api-ingress
namespace: apps
spec:
routes:
- match: Host(`api.example.com`)
kind: Rule
services:
- name: hello-api-service
port: 8080
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: hello-api-httproute
namespace: apps
spec:
parentRefs:
- name: your-gateway
hostnames:
- "api.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: "/"
backendRefs:
- name: hello-api-service
port: 8080
Let's promote this API. The first thing to do is to create a new API object:
- Local OpenAPI specification
- Remote OpenAPI specification
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: hello-api
namespace: apps
spec:
openApiSpec:
# This is the path, within the hello-api-service, where Hub can find the Open API specification
path: /openapi.yaml
This path indicates where to find the OpenAPI specification document. The Kubernetes Service referenced in the Ingress object where the API is attached will be called on this exact path. It directly accesses the Service without considering any middlewares defined on the Ingress object. If the Ingress object includes multiple rules, only the Kubernetes Service defined in the first rule will be accessed.
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: hello-api
namespace: apps
spec:
openApiSpec:
# This is the remote URL where Hub can find the OpenAPI specification
url: https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.yaml
Finally, we can complete the promotion by linking the API object to the Ingress, IngressRoute or HTTPRoute, object. This is done using
the hub.traefik.io/api
annotation.
- Ingress
- IngressRoute
- HTTPRoute
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-api-ingress
namespace: apps
annotations:
hub.traefik.io/api: hello-api # Name of the API object
spec:
rules:
- host: api.example.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: hello-api-service
port:
number: 8080
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: hello-api-ingress
namespace: apps
annotations:
hub.traefik.io/api: hello-api # Name of the API object
spec:
routes:
- match: Host(`api.example.com`)
kind: Rule
services:
- name: hello-api-service
port: 8080
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: hello-api-httproute
namespace: apps
annotations:
hub.traefik.io/api: hello-api # Name of the API object
spec:
parentRefs:
- name: your-gateway
hostnames:
- "api.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: "/"
backendRefs:
- name: hello-api-service
port: 8080
Please note that the API was created in the same namespace as the Ingress. It's possible to reference an API that is in a different namespace using the following syntax:
annotations:
hub.traefik.io/api: api-name@api-namespace # In our example it would be "hello-api@apps"
Cross-namespace reference support depends on the Ingress object used and therefore depends on the Traefik providers enabled:
- Ingress object, controlled by the Traefik provider
kubernetesIngress
, supports cross-namespace, this capability can't be turned off. - IngressRoute object, controlled by the Traefik provider
kubernetesCRD
, supports cross-namespace but the capability needs to be enabled. - HTTPRoute object, controlled by the Traefik provider
kubernetesGateway
, supports cross-namespace references as per Gateway API specifications.
You can enable cross-namespace support on IngressRoute resources using the following static configuration:
- YAML
- CLI
providers:
kubernetesCRD:
allowCrossNamespace: true
--providers.kubernetescrd.allowCrossNamespace=true
Versioned API
To configure a versioned API, please refer to the documentation page for APIVersion.
Operation filtering
If you version your APIs with the APIVersion CRD, you only need to configure operation filtering there.
Operation filtering is a way to restrict user groups to a specific set of OpenAPI operations.
Imagine you have an API with the following use case:
- Only members of the
admin
group are allowed to delete customers. - Only members of the
admin
group are allowed to retrieve customer statistics - Members of the
support
group are allowed to retrieve a list with all customers
Configuring operation filtering is done in two steps.
You have to configure operationSets
on your APIs, and reference these in your APIAccess.
OperationSets
An operationSet
is a named entity that selects one or many OpenAPI operations using matchers
. These can then be referenced in APIAccesses
to grant access to specific operations to some user groups.
- Path
- Path Prefix
- Path Regex
- Only HTTP Method(s)
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: my-api
spec:
openApiSpec:
path: /api/v3/openapi.json
operationSets:
- name: pets-operations # The name that will be used when referenced
matchers:
- path: /pets # The matcher `path` option defines the exact path of the spec operations to select
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: my-api
spec:
openApiSpec:
path: /api/v3/openapi.json
operationSets:
- name: pets-operations # The name that will be used when referenced
matchers:
- pathPrefix: /pets # The matcher `pathPrefix` option defines the path prefix of the spec operations to select
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: my-api
spec:
openApiSpec:
path: /api/v3/openapi.json
operationSets:
- name: pets-operations # The name that will be used when referenced
matchers:
- pathRegex: "/customers/.*/address" # The matcher `pathRegex` option defines the path regex of the matching spec operations to select
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: my-api
spec:
openApiSpec:
path: /api/v3/openapi.json
operationSets:
- name: read-only # The name that will be used when referenced
matchers:
methods: # All operations with the following methods will be selected
- GET
- POST
- Only one of the following path settings is allowed:
path
,pathPrefix
, orpathRegex
. - You can use the
methods
option without using a path setting (path
,pathPrefix
, orpathRegex
). - It is possible to combine a path setting with the
methods
option. - The
pathRegex
must match both the OpenAPI specification and the request. For example, the request to/customers/:id
shouldn't be expressed by/customers/[0-9]+
but by/customers/.+
to satisfy both/customers/{flightID}
in the OAS specification and/customers/2
in the actual request made by the user.
Please be aware that the difference between configuring one matcher with multiple options or configuring multiple matchers is subtle. The examples below show the difference in the syntax.
- One Matcher
- Two Matchers
operationSets:
- name: read-pets
matchers:
- pathPrefix: /pets
methods:
- GET
operationSets:
- name: read-or-path
matchers:
- pathPrefix: /pets
- methods:
- GET
Without a Defined HTTP Method
The following shows an API CRD using an operation matcher with pathPrefix
, without any HTTP method defined.
This allows all operations on the /pets
path prefix.
For example, GET /pets
, GET /pets/{id}
, POST /pets
, PUT /pets/{id}
.
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: my-api
spec:
openApiSpec:
path: /api/v3/openapi.json
operationSets:
- name: pets-operations
matchers:
- pathPrefix: /pets
Every Matcher Option Must Align
The following example shows an API CRD using one matcher
with two options.
One doing path prefix filtering and one doing method filtering.
Both options must be fulfilled.
Setting a matcher with two options, such as pathPrefix
and methods
(acts as a logical AND).
This allows GET
for all operations matching the /pets
path prefix.
For example, GET /pets
, GET /pets/{id}
, GET /pets/findByStatus
.
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: my-api
spec:
openApiSpec:
path: /api/v3/openapi.json
operationSets:
- name: read-pets
matchers:
- pathPrefix: /pets
methods:
- GET
One of the Two Matchers Must Match
The following example shows an API CRD using a combination of two matchers
.
One doing path prefix filtering and one doing method filtering.
One of the matchers must fulfil.
Setting two matchers, one with pathPrefix
and the other with methods
(act as a logical OR).
This allows all operations on the /pets
path prefix.
This allows GET
operations on all endpoints of the API.
For example, GET /pets
, GET /pets/{id}
, GET /pets/findByStatus
, POST /pets
, PUT /pets
, DELETE /pets/{id}
, GET /dogs
, GET /dogs/{id}
.
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: my-api
spec:
openApiSpec:
path: /api/v3/openapi.json
operationSets:
- name: read-or-path
matchers:
- pathPrefix: /pets
- methods:
- GET