Configuration
IBM Application Gateway (IAG) uses YAML documents for all configuration data. When the container starts, it will look for a Kubernetes custom object (if specified), or failing this it will look in the /var/iag/config
directory of the container for YAML documents.
Depending on your container environment, the files within the configuration directory can be bind mounted in, provided via a ConfigMap or any other mechanism which places the files in the configuration directory.
To get started with authoring IAG configuration YAML, refer to the Examples and YAML Reference.
Using Multiple Configuration YAML Documents
If a Kubernetes custom object is not being used the IAG configuration contained within the configuration directory can span multiple YAML documents. This is useful for simplifying the management of configuration data.
IAG combines all YAML documents found in /var/iag/config
using the following rules:
- IAG configuration documents must have the file extension
.yaml
or.yml
. - Each file which contains IAG configuration must contain the
version
indicator. Documents which do not include theversion
indicator are not parsed as IAG configuration. - All documents must have the same
version
. Mixing different configuration versions is not supported and IAG will not start when it discovers more than one version. Refer to Versioning for further information. - Each top-level key (
secrets
,server
,identity
,policies
,authorization
,services
,logging
,advanced
,) can only be defined once across all configuration YAML documents, with the exception of theresource_servers
key. - The top-level key
resource_servers
can be defined more than once. When this occurs IAG will combine all of theresource_servers
values.
Example of Multiple Configuration YAML Documents
This example illustrates how multiple configuration YAML documents can be provided to IAG. The following files are provided to the /var/iag/config
path within the container.
iag.yaml
resource-servers-1.yaml
resource-servers-2.yaml
logging.yaml
iag.yaml - This file contains the top level server
and identity
keys. Each document can provide more than one top level key, provided they are only defined once across the entire set of configuration documents.
version: "23.04"
server:
ssl:
front_end:
certificate:
- $CERT_PEM
- $KEY_PEM
identity:
oidc:
client_id: $CLIENT_ID
client_secret: $CLIENT_SECRET
discovery_endpoint: "https://ibm-app-gw.verify.ibm.com/oidc/endpoint/default/.well-known/openid-configuration"
resource-servers-1.yaml - This file contains the resource_servers
key and a single entry defining one resource server. The resource_servers
key is exceptional and can be defined more than once.
version: "23.04"
resource_servers:
- virtual_host: iag-demo.ibm.com
servers:
- host: 10.10.10.200
port: 80
resource-servers-2.yaml - This file contains a second resource_servers
key and the definition for an additional resource server. Partitioning each resource server into its own YAML file makes it easy to add or remove resource servers by simply adding or removing the corresponding file containing the resource server definition and recreating the container.
version: "23.04"
resource_servers:
- path: /
servers:
- host: 10.10.10.201
port: 8080
logging.yaml - This file contains the logging
key and sets a tracing entry useful for debugging. When debugging is completed, this file can be removed and the container restarted to disable tracing.
version: "23.04"
logging:
json_logging: false
tracing:
- file_name: /var/tmp/snoop.log
component: pdweb.snoop
level: 9
These separate documents are equivalent to providing the following as a single YAML document:
version: "23.04"
server:
ssl:
front_end:
certificate:
- $CERT_PEM
- $KEY_PEM
identity:
oidc:
client_id: $CLIENT_ID
client_secret: $CLIENT_SECRET
redirect_uri_host: iag-demo.ibm.com
discovery_endpoint: "https://ibm-app-gw.verify.ibm.com/oidc/endpoint/default/.well-known/openid-configuration"
resource_servers:
- virtual_host: iag-demo.ibm.com
servers:
- host: 10.10.10.200
port: 80
- path: /
servers:
- host: 10.10.10.201
port: 8080
logging:
json_logging: false
tracing:
- file_name: /var/tmp/snoop.log
component: pdweb.snoop
level: 9
Special Types
There are three special types which can used in addition to plain text within the YAML file. These special types can be used to substitute values from alternative sources.
Type | Syntax |
---|---|
Environment Variable | $<environment variable> |
External File | "@<file name>" |
Base 64 Data | B64:<base64 encoded string> |
Obfuscated (Encrypted with Shared Secret) String | OBF:<obfuscated string> |
Encrypted (Encrypted with RSA) String | ENC:<encrypted string> |
Special Types Available in Kubernetes
In addition to the standard special types, there are Kubernetes specific special types available when IAG is running in a Kubernetes environment.
Type | Syntax |
---|---|
Kubernetes ConfigMap | configmap:<config map name>/<config map field> |
Kubernetes Secret | secret:<secret name>/<secret field> |
Example Environment Variable
The following example shows how a value stored in an environment variable can be used in the configuration YAML. Environment variables are useful when used in conjunction with Kubernetes secrets to hide sensitive data. In this example, the failover cookie key is loaded from an environment variable.
The environment variable MY_FAILOVER_SECRET
is set in the container context:
MY_FAILOVER_SECRET=exampleOnlyDoNotUseThisValue
An IAG configuration YAML document can indicate that this value should loaded from the the environment variable by specifying $MY_FAILOVER_SECRET
as a value.
version: "23.04"
server:
...
failover:
key: $MY_FAILOVER_SECRET
cookie_name: IAG-FAILOVER-COOKIE
...
This is equivalent to specifying the value as-is within the YAML configuration data.
version: "23.04"
server:
...
failover:
key: exampleOnlyDoNotUseThisValue
cookie_name: IAG-FAILOVER-COOKIE
...
Example File Reference
The following example shows how a file reference can be used to source content from an external file (please note that file references are not supported when a Kubernetes custom object is being used to store the configuration information). In this example, a rate limiting rule will be loaded from an external file.
The following two files are present in the configuration directory /var/iag/config
:
config.yaml
rate_limiting.yaml
In this example, rate_limiting.yaml
is a simple YAML file with the content:
ip: true
capacity: 3
interval: 60
reaction: TEMPLATE
In the IAG configuration file config.yaml
, the content of rate_limiting.yaml
is included by specifying "@rate\_limiting.yaml"
as a value.
version: "23.04"
policies:
...
rate_limiting:
- name: "limited_by_ip"
methods:
- "*"
paths:
- "/my_app*"
rule: "@rate_limiting.yaml"
...
This is equivalent to including the text content as-is within the YAML configuration data.
version: "23.04"
policies:
...
rate_limiting:
- name: "limited_by_ip"
methods:
- "*"
paths:
- "/my_app*"
rule: |
ip: true
capacity: 3
interval: 60
reaction: TEMPLATE
...
Note
Note that a file reference must always be surrounded by quotes as the
@
character can not appear at the beginning of an unquoted YAML value.
Example Base 64 Data
For some types of data, it is not practical to store these as text within the configuration YAML and in some scenarios it is useful to be able to embed all data within a single configuration YAML document. In these cases, the values can be base 64 encoded and embedded as values within the configuration YAML.
The following example shows how a transformation rule can be embedded in the configuration YAML as base 64 encoded data.
First, generate the base 64 representation of the file. On macOS and other UNIX-like systems this can be achieved with the base64
command.
$ base64 Req-AddStaticHeader.xsl
PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHhzbDpzdHlsZXNoZWV0IHht
...
In the IAG configuration YAML, this can be placed on a single line preceded by the B64:
prefix.
version: "23.04"
policies:
...
http_transformations:
request:
- name: req-static-headers
method: GET
url: "*"
rule: B64:PD94bWwgdmVyc2lvbj0i...
...
This is equivalent to including the text content as-is within the YAML configuration data.
version: "23.04"
policies:
...
http_transformations:
request:
- name: req-static-headers
method: GET
url: "*"
rule: |
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*" />
<xsl:template match="/">
...
...
Example Obfuscated (Encrypted with Shared Secret) String
Configuration data can also be provided as encrypted entries which are obfuscated using a shared secret/password. The shared secret is provided in the secrets
section of the YAML and will be used to decrypt all OBF:
prefixed entries found within the configuration YAML.
The following example shows the data wPP8rM8N0d
being encrypted with the shared secret myIAGExampleSecret
:
echo -n "wPP8rM8N0d" | openssl enc -aes256 \
-pbkdf2 -md sha512 -pass pass:"myIAGExampleSecret" \
-base64
Note that OpenSSL 1.1.1 or newer is required for the above command.
This command will produce a base 64 string similar to U2FsdGVkX1+UHIKgqQOgjyqY2ANixZs2sW+b1Nr7fcg=
. Note that due to salting, you should expect that this command will produce a different encrypted representation of the input data each time it is executed.
Entire files can also be obfuscated with a similar command:
openssl enc -aes256 -pbkdf2 -md sha512 -pass pass:"myIAGExampleSecret" \
-base64 -in myLocalPages.zip
The resulting encrypted base 64 string can be provided to IAG using the OBF:
prefix:
version: "23.04"
secrets:
obf_key: "myIAGExampleSecret"
...
identity:
oidc:
client_secret: "OBF:U2FsdGVkX1+UHIKgqQOgjyqY2ANixZs2sW+b1Nr7fcg="
Note that any number of values in the configuration YAML can be obfuscated, however they must all use the same shared secret. Only a single shared secret/password can be provided per IAG instance.
version: "23.04"
secrets:
obf_key: "myIAGExampleSecret"
...
identity:
oidc:
client_secret: "OBF:U2FsdGVkX1+UHIKgqQOgjyqY2ANixZs2sW+b1Nr7fcg="
client_id: "OBF:U2FsdGVkX1/OHj8jarx2+yzaFICy+z5ZDIDFXEMtVR/oLaafLtjVi9u+huCwZhnD5/aMWEm7h1G1cgtJE/yu3w=="
...
server:
local_pages:
content: "OBF:U2FsdGVkX19nCQVvJZtKatPZE/TEDEYlYMpak7hAZJoC..."
type: zip
Reversing an Obfuscated String
An obfuscated string can be reversed using a technique similar to the one used to create it:
echo "U2FsdGVkX1+UHIKgqQOgjyqY2ANixZs2sW+b1Nr7fcg=" | openssl enc -d -aes256 \
-pbkdf2 -md sha512 -pass pass:"myIAGExampleSecret" \
-base64
Detailed description of the expected format for encrypted data
The requirements for an obfuscated entry are:
- The data must be encrypted with the AES-256 cipher
-aes256
- The key used to encrypt the data must:
- be derived from a passphrase which can be supplied in the YAML
-pass pass:<passphrase>
- have been derived using the PBKDF2 algorithm
-pbkdf2
- use SHA-512 message digest
-md sha152
- perform 10,000 iterations
-iter 10000
(note that this is the current default for OpenSSL)
- be derived from a passphrase which can be supplied in the YAML
- The data must be base64 encoded
-base64
- When base64 decoded, the data must be in OpenSSL format:
- Bytes 0-7 is
Salted__
- Bytes 8-15 is the salt used while deriving the key
- Byte 16 onwards is the encrypted data
- Bytes 0-7 is
Example Encrypted (Encrypted with RSA) String
Configuration data can also be provided as RSA encrypted entries. The private key required to decrypt the entry is provided in the secrets
section of the YAML and will be used to decrypt all ENC:
prefixed entries found within the configuration YAML.
To use RSA encryption, generate a private certificate:
openssl genrsa -out private.pem 2048
This private certificate will be used to decrypt the entries and must be provided in the configuration YAML. To create encrypted entries, generate a corresponding public key which will be used for the encryption operations:
openssl rsa -pubout -in private.pem -out public.pem
The following example shows the data wPP8rM8N0d
being encrypted with the public key public.pem
and base64 encoded:
echo -n "wPP8rM8N0d" | openssl rsautl -encrypt -inkey public.pem -pubin | base64
This command will produce a base 64 encoded string. The encrypted base 64 encoded string can be provided to IAG using the ENC:
prefix:
version: "23.04"
secrets:
enc_key: "@private.pem"
...
identity:
oidc:
client_secret: "ENC:gg05Dn9WnV13OPpkwxszzlxQQG3WM1N88BHggtb2JbNI..."
Note that any number of values in the configuration YAML can be encrypted, however they must all require the same private key for decryption. Only a single RSA private key can be provided per IAG instance.
version: "23.04"
secrets:
obf_key: "myIAGExampleSecret"
...
identity:
oidc:
client_secret: "ENC:gg05Dn9WnV13OPpkwxszzlxQQG3WM1N88BHggtb2JbNI..."
client_id: "ENC:PS56fPQGSg/LPT2mgktLw1T2YMuBxaaQMM5AZMq06xEs..."
Reversing an Obfuscated String
An obfuscated string can be reversed using a technique similar to the one used to create it:
echo -n "PS56fPQGSg/LPT2mgktLw1T2YMuBxaaQMM5AZMq06xEs..." \
| base64 -d | openssl rsautl -decrypt -inkey private.pem
Using the Encrypted and Obfuscated Types Together
The amount of data which can be encrypted using this technique is limited by the size of the RSA private key. To protect entries which are too large for RSA encryption, it is recommended that the following pattern using both encryption and obfuscation is adopted:
- Entries are obfuscated using the
OBF:<value>
technique - The obfuscation key/shared secret is encrypted using the
ENC:<value>
technique
version: "23.04"
secrets:
enc_key: "@private.pem"
obf_key: "ENC:OsG1/Aw5iNpP/AutK9q0bVF5z1sO/psBvpY7zpRpd8V..."
identity:
oidc:
client_secret: "OBF:U2FsdGVkX1+UHIKgqQOgjyqY2ANixZs2sW+b1Nr7fcg="
client_id: "OBF:U2FsdGVkX1/OHj8jarx2+yzaFICy+z5ZDIDFXEMtVR/o..."
...
server:
local_pages:
content: "OBF:U2FsdGVkX19nCQVvJZtKatPZE/TEDEYlYMpak7hAZJoC..."
type: zip
Example Kubernetes ConfigMap
The Kubernetes ConfigMap type can be used to directly reference a field from a particular ConfigMap within the IAG configuration YAML. During bootstrapping, the IAG container will use the Kubernetes REST API endpoints to retrieve the ConfigMap and substitute the value into the configuration YAML.
Consider the following secret named verify-endpoint
containing the fields discovery_url
and proxy_server
:
apiVersion: v1
kind: ConfigMap
metadata:
name: verify-endpoint
...
data:
discovery_url: https://ibm-app-gw.verify.ibm.com/oidc/endpoint/default/.well-known/openid-configuration
proxy_server: https://proxy.ibm.com:3128
To reference these values within the configuration YAML, use the syntax for the Kubernetes ConfigMap type:
version: "23.04"
identity:
oidc:
discovery_endpoint: "configmap:verify-endpoint/discovery_url"
proxy: "configmap:verify-endpoint/proxy_server"
...
During bootstrapping, IAG will retrieve the ConfigMap and substitute it into the configuration YAML:
version: "23.04"
identity:
oidc:
discovery_endpoint: https://ibm-app-gw.verify.ibm.com/oidc/endpoint/default/.well-known/openid-configuration
proxy: https://proxy.ibm.com:3128
...
Example Kubernetes Secret
The Kubernetes Secret type can be used to directly reference a field from a particular secret within the IAG configuration YAML. During bootstrapping, the IAG container will use the Kubernetes REST API endpoints to retrieve the secret and substitute the secret value into the configuration YAML.
Consider the following secret named verify-oidc
containing the fields client_id
and client_secret
:
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: verify-oidc
...
data:
client_id: ZTdiMzA0ZWItYTU1NC00MzQ5LTlhODAtNTA1Y2IzZGRmMTBi
client_secret: Z2VSVEY0RldSWA==
To reference these values within the configuration YAML, use the syntax for the Kubernetes Secret type:
version: "23.04"
identity:
oidc:
client_id: "secret:verify-oidc/client_id"
client_secret: "secret:verify-oidc/client_secret"
...
During bootstrapping, IAG will retrieve the secret, base64 decode the data and substitute it into the configuration YAML:
version: "23.04"
identity:
oidc:
client_id: e7b304eb-a554-4349-9a80-505cb3ddf10b
client_secret: geRTF4FWRX
...
Kubernetes TLS Secrets
This mechanism can also be used with the Kubernetes TLS Secret type kubernetes.io/tls
. Consider the following TLS Secret named iag-tls-secret
which contains the fields tls.crt
and tls.key
:
apiVersion: v1
kind: Secret
type: kubernetes.io/tls
metadata:
name: iag-tls-secret
...
data:
tls.crt: LS0t...Cg==
tls.key: LS0t...LS0K
This TLS Secret can be specified using the Kubernetes Secret syntax:
version: "23.04"
server:
ssl:
certificate:
- "secret:iag-tls-secret/tls.key"
- "secret:iag-tls-secret/tls.crt"
...
Updated 5 months ago