A Service has its configuration which includes the information about its upstream as well as the application-layer specific configurations (e.g. HTTP-based configurations such as manipulating headers and injecting the upstream credentials) for various widely used L-7 protocols and supported by Octelium (read more about Service modes here). Here is an example:
1kind: Service2metadata:3name: svc14spec:5mode: HTTP6config:7upstream:8url: https://api.example.com9http:10auth:11bearer:12fromSecret: apikey1
The above configuration is the default
configuration which is used globally for all the Service requests by default. However, in many cases, you might want to make this configuration dynamic depending on the request's context. For instance, you might want to route to a certain upstream depending on the identity of the User or the L-7 specific context (e.g. HTTP paths, headers, request body, etc...). For such cases, Octelium provides you a very flexible way to apply dynamic configuration where you can define multiple configurations and choose one of them on a per-request basis via rules that are defined exactly the same way as Policy rules (read more about Policies and access control here).
Here is an example where we can provide smart routing based on the User identity to route to additional upstreams. We now have 2 additional configs (i.e. config-1
and config-2
) to the default
configuration, each having a different credential representing maybe a different account and/or privileges for the upstream. If no rules match or if there are no rules, then the default
config is used as a fallback config.
1kind: Service2metadata:3name: svc14spec:5mode: HTTP6# This is our typical static configuration used by default if no rules match7config:8upstream:9url: https://api.example.com10http:11auth:12bearer:13fromSecret: apikey014dynamicConfig:15# we define a list of named configs that could override the global config16configs:17- name: config-118upstream:19url: https://api-01.example.com20http:21auth:22bearer:23fromSecret: apikey124- name: config-225upstream:26url: https://api-02.example.com27http:28auth:29bearer:30fromSecret: apikey231rules:32# Use the Config `config-1` for Users belonging to the Group `group-1`33- condition:34match: '"group-1" in ctx.user.spec.groups'35configName: config-136# Use the Config `config-2` for Users belonging to the Group `group-2`37- condition:38match: '"group-2" in ctx.user.spec.groups'39configName: config-2
As shown in the example above, the dynamicConfig
has 2 lists: one for the named dynamic configs represented by the configs
list and another, rules
, for the rules that are checked upon each request to choose one of these configs when matched. Each rule has a condition that can be defined in the exact same way as Policy rule conditions (read more here). A rule matches if its condition is met and in such case its corresponding named config, represented by the configName
field, is chosen to be the configuration for that particular request overriding the default Service configuration.
Dynamic configuration is not restricted to a certain Service mode. The above example can be generalized to any other mode where you can override the default configuration based on whatever dynamic rules you wish to define. For example, you can use it for the POSTGRES
and MYSQL
modes to route to specific upstreams and/or use specific usernames and passwords as well as databases depending on the identity and/or context of the request. For the case of SSH, you can route to different usernames and passwords/private keys depending on the identity or the request's User. You can explore more mode-specific examples here:
Also, you are not really required to define a default
configuration when you have one or more named configurations unless with working with certain situations (e.g. buffering request body in HTTP
-based Services (read more here)). Here is an example of a Service that acts as an API gateway:
1kind: Service2metadata:3name: my-api4spec:5mode: HTTP6dynamicConfig:7configs:8- name: v19upstream:10url: https://apiv1.example.com11http:12auth:13bearer:14fromSecret: apikey115path:16removePrefix: /v117- name: v218upstream:19url: https://apiv2.example.com20http:21auth:22bearer:23fromSecret: apikey224path:25removePrefix: /v226rules:27# Use the Config `config-1` for Users belonging to the Group `group-1`28- condition:29match: ctx.request.http.path.startsWith("/v1")30configName: v131# Use the Config `config-2` for Users belonging to the Group `group-2`32- condition:33match: ctx.request.http.path.startsWith("/v2")34configName: v235# Fallback to v1 when nothing matches36- condition:37matchAny: true38configName: v1
However, in such case, you need to be careful that your rules cover all the possible conditions.