Skip to main content

Kubernetes

IBM Application Gateway Sidecar

A Kubernetes application may consist of a number of different components. These may include:

  • Main application
  • Security
  • Logging
  • Monitoring
  • etc

Separating these components into their own container provides isolation and encapsulation. Each container provides a single capability without needing to know the intricate details of the other components.

In Kubernetes this pattern is known as a sidecar. Each sidecar container is attached to the main application and provides a specific function.

The IBM Application Gateway supports the sidecar pattern such that it can be configured to run alongside the main application providing authorization capabilities without the application needing to know the details.

Admission Controller

To allow the IBM Application Gateway to be used as an application sidecar the admission controller first needs to be deployed. The admission controller handles the management of the sidecar container in any application deployments that specify references to IBM Application Gateway.

For more information on Kubernetes admission controllers see A guide to Kubernetes Admission Controllers or search the Kubernetes documentation.

There are a series of steps that need to be followed to deploy the admission controller in Kubernetes:

  1. Configure the Kubernetes cluster to enable the MutatingAdmissionWebhook admission plugin.
  2. Create the certificate for communication between Kubernetes and the webhook server.
  3. Start the webhook server. This is a RESTful web server that handles requests to patch deployment requests prior to Kubernetes handling the requests.
  4. Create a service to allow the webhook server to be accessed.
  5. Deploy the webhook configuration. This registers the IBM Application Gateway admission controller with Kubernetes such that it will be called for each deployment request prior to Kubernetes handling the request.

Enabling the MutatingAdmissionWebhook admission plugin

The IBM Application Gateway admission controller is a mutating admission webhook and requires the MutatingAdmissionWebhook plugin to be enabled.

To enable the plugin pass the flag to the Kubernetes API server.

kube-apiserver --enable-admission-plugins=MutatingAdmissionWebhook

Depending on the environment the exact way to enable the plugin may differ. For example to enable the plugin in a Minikube cluster:

minikube start --extra-config=apiserver.enable-admission-plugins="MutatingAdmissionWebhook"

Create server certificate

The Kubernetes admission controller makes HTTPS calls to a webhook server to validate or patch the request object. This means that the admission controller client and the server need a set of predefined certificates to allow communication. See TLS Certificates for a short description of the requirements for the certificates.

The main requirement is that the common name (CN) of the must match the server name used by the Kubernetes API server. This will be of the form:

<service-name>.<namespace>.svc

where service-name is the name of the Kubernetes service that is created to access the webhook server and namespace is the Kubernetes namespace that the admission controller is deployed in.

The following sections show how to create a server certificate, which can be a certificate signed by Kubernetes or a self signed certificate.

Create Kubernetes Signed Certificate

The following steps describe how to create a certificate signed by the Kubernetes CA.

  1. Generate the CA key
openssl genrsa -out webhook-server-tls-key.pem 2048
  1. Generate a certificate signing request

Copy the following into a file named csr.conf and replace the values in brackets (<>) with the correct values:

  • k8s_namespace is the Kubernetes namespace (eg: default)
  • webhook_service_name is the name of the webhook service defined in Create the webhook service (eg: ibm-application-gateway-injector-webhook-svc)
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = <webhook_service_name>
DNS.2 = <webhook_service_name>.<k8s_namespace>
DNS.3 = <webhook_service_name>.<k8s_namespace>.svc
openssl req -new -key webhook-server-tls-key.pem -subj "/CN=ibm-application-gateway-injector-webhook-svc.default.svc" -out server.csr -config csr.conf
  1. Create a Certificate Signing Request object to send to the Kubernetes API

Replace the values in brackets (<>) with the correct values:

  • k8s_namespace is the Kubernetes namespace (eg: default)
  • webhook_service_name is the name of the webhook service defined in Create the webhook service (eg: ibm-application-gateway-injector-webhook-svc)
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: <webhook_service_name>.<k8s_namespace>
spec:
  request: $(cat server.csr | base64 | tr -d '\n')
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF
  1. Approve the certificate signing request

Replace <csr_name> with the name of the Kubernetes Certificate Signing Request in the previous step.

kubectl certificate approve <csr_name>
  1. Create the base64 encoded server certificate file

Replace <csr_name> with the name of the Kubernetes Certificate Signing Request in step 3.

kubectl get csr <csr_name> -o jsonpath='{.status.certificate}' | openssl base64 -d -A -out webhook-server-tls-crt.pem
  1. Create the Kubernetes secret
kubectl create secret generic ibm-application-gateway-webhook-certs --from-file=key.pem=webhook-server-tls-key.pem --from-file=cert.pem=webhook-server-tls-crt.pem --dry-run -o yaml | kubectl apply -f -

Create Self Signed Certificate

The following commands show how a self signed certificate can be created and added to a Kubernetes secret that can be used by the IBM Application Gateway admission controller.

Replace the values in brackets (<>) with the correct values:

  • k8s_namespace is the Kubernetes namespace (eg: default)
  • webhook_service_name is the name of the webhook service defined in Create the webhook service (eg: ibm-application-gateway-injector-webhook-svc)
openssl req -nodes -new -x509 -keyout ca.key -out ca.crt -subj "/CN=IBM Application Gateway Webhook CA"
openssl genrsa -out webhook-server-tls-key.pem 2048
openssl req -new -key webhook-server-tls-key.pem -subj "/CN=<webhook_service_name>.<k8s_namespace>.svc" | openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -out webhook-server-tls-crt.pem
kubectl create secret generic ibm-application-gateway-webhook-certs --from-file=key.pem=webhook-server-tls-key.pem --from-file=cert.pem=webhook-server-tls-crt.pem --dry-run -o yaml | kubectl apply -f -

Start the webhook server

The IBM Application Gateway admission controller webhook server runs as part of the IBM Application Gateway operator.

Starting the webhook server if the operator has already been deployed

The following steps will deploy and start the webhook server if the operator has already been deployed.

  1. Modify the operator Deployment yaml (eg: operator.yaml) to include the webhook application labels and the certificate volume source.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ibm-application-gateway-operator
  labels:
    app: ibm-application-gateway-injector
spec:
  replicas: 1
  selector:
    matchLabels:
      name: ibm-application-gateway-operator
      app: ibm-application-gateway-injector
  template:
    metadata:
      labels:
        name: ibm-application-gateway-operator
        app: ibm-application-gateway-injector
    spec:
      serviceAccountName: ibm-application-gateway-operator
      imagePullSecrets:
        - name: regcred
      containers:
        - name: ibm-application-gateway-operator
          image: ibmcom/ibm-application-gateway-operator:20.09.0
          command:
          - ibm-application-gateway-operator
          imagePullPolicy: Never
          env:
            - name: WATCH_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: OPERATOR_NAME
              value: "ibm-application-gateway-operator"
          volumeMounts:
          - name: webhook-certs
            mountPath: /etc/webhook/certs
            readOnly: true
      volumes:
      - name: webhook-certs
        secret:
          secretName: ibm-application-gateway-webhook-certs
  1. Restart the operator
kubectl apply -f operator.yaml

Starting the webhook server if the operator has NOT already been deployed

The following steps will deploy and start the webhook server if the operator has not already been deployed.

  1. Create the operator service account.
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ibm-application-gateway-operator
kubectl apply -f service_account.yaml
  1. Create the role binding
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: null
  name: ibm-application-gateway-operator
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - services
  - services/finalizers
  - endpoints
  - persistentvolumeclaims
  - events
  - configmaps
  - secrets
  verbs:
  - create
  - delete
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - apps
  resources:
  - deployments
  - deployments/status
  - daemonsets
  - replicasets
  - statefulsets
  verbs:
  - create
  - delete
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - monitoring.coreos.com
  resources:
  - servicemonitors
  verbs:
  - get
  - create
- apiGroups:
  - apps
  resourceNames:
  - ibm-application-gateway-operator
  resources:
  - deployments/finalizers
  verbs:
  - update
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - apps
  resources:
  - replicasets
  - deployments
  verbs:
  - get
- apiGroups:
  - ibm.com
  resources:
  - '*'
  verbs:
  - create
  - delete
  - get
  - list
  - patch
  - update
  - watch

---  

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: ibm-application-gateway-operator
subjects:
- kind: ServiceAccount
  name: ibm-application-gateway-operator
- kind: ServiceAccount
  name: ibm-application-gateway  
roleRef:
  kind: Role
  name: ibm-application-gateway-operator
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f rbac.yaml
  1. Deploy the custom resource definition
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ibmapplicationgateways.ibm.com
spec:
  group: ibm.com
  names:
    kind: IBMApplicationGateway
    listKind: IBMApplicationGatewayList
    plural: ibmapplicationgateways
    singular: ibmapplicationgateway
  scope: Namespaced
  subresources:
    status: {}
    scale:
      # specReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Spec.Replicas.
      specReplicasPath: .spec.replicas
      # statusReplicasPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Replicas.
      statusReplicasPath: .status.replicas
      # labelSelectorPath defines the JSONPath inside of a custom resource that corresponds to Scale.Status.Selector.
      labelSelectorPath: .status.labelSelector
  validation:
    openAPIV3Schema:
      description: IAG is the Schema for the iags API
      properties:
        apiVersion:
          description: 'APIVersion defines the versioned schema of this representation
            of an object. Servers should convert recognized schemas to the latest
            internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
          type: string
        kind:
          description: 'Kind is a string value representing the REST resource this
            object represents. Servers may infer this from the endpoint the client
            submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
          type: string
        metadata:
          type: object
        spec:
          description: IAGSpec defines the desired state of IAG.
          type: object
          properties:
            replicas:
              type: integer
              description: The number of IBM Application Gateway replicas to create.
            deployment:
              type: object
              description: Defines the IBM Application Gateway deployment properties. 
              properties:
                image:
                  description: The name, tag and location of the IBM Application Gateway docker image.
                  type: string
                imagePullPolicy:
                  description: The policy used to decide when to pull the IBM Application Gateway docker image from a remote server. Default value is IfNotPresent.
                  type: string
                  enum:
                    - Never
                    - Always
                    - IfNotPresent
                imagePullSecrets:
                  type: array
                  description: A list of Kubernetes secrets that will be set on the IBM Application Gateway deployment.
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                        description: The name of the Kubernetes secret that defines the required remote server authentication credentials.
                    required:
                      - name
                serviceAccountName:
                  description: The Kubernetes service account that will run the IBM Application Gateway applications.
                  type: string
                lang:
                  description: The language for the IBM Application Gateway application. Default value is English (en).
                  type: string
                readinessProbe:
                  type: object
                  description: The settings for the readiness probe.
                  properties:
                    initialDelaySeconds:
                      description: The initial delay (in seconds) before starting the IBM Application Gateway application readiness poll. Default value is 0. Minimum value is 0.
                      type: integer
                      minimum: 0
                    periodSeconds:
                      description: The wait period (in seconds) between IBM Application Gateway application readiness polling. Default value is 10. Minimum value is 1.
                      type: integer
                      minimum: 1
                    failureThreshold:
                      description: The number of times the probe will be tried before failing. Failure will result in the Pod will be marked Unready. Default value is 3. Minimum value is 1. 
                      type: integer
                      minimum: 1
                    successThreshold:
                      description: The number of consecutive successes for the probe to be considered successful after having failed. Default value is 1. Minimum value is 1. 
                      type: integer
                      minimum: 1
                    timeoutSeconds: 
                      description: The number of seconds after which the probe times out. Default value is 1. Minimum value is 1.
                      type: integer
                      minimum: 1
                livenessProbe:
                  type: object
                  description: The settings for the liveness probe.
                  properties:
                    initialDelaySeconds:
                      description: The initial delay (in seconds) before starting the IBM Application Gateway application liveness poll. Default value is 0. Minimum value is 0.
                      type: integer
                      minimum: 0
                    periodSeconds:
                      description: The wait period (in seconds) between IBM Application Gateway application liveness polling. Default value is 10. Minimum value is 1.
                      type: integer
                      minimum: 1
                    failureThreshold:
                      description: The number of times the probe will be tried before failing. Failure will result in the container being restarted. Default value is 3. Minimum value is 1. 
                      type: integer
                      minimum: 1
                    timeoutSeconds: 
                      description: The number of seconds after which the probe times out. Default value is 1. Minimum value is 1.
                      type: integer
                      minimum: 1
              required:
                - image
            configuration:
              type: array
              description: Defines the IBM Application Gateway configuration properties.
              items:
                type: object
                properties:
                  type:
                    type: string
                    enum:
                      - configmap
                      - literal
                      - web
                      - oidc_registration
                  name:
                    type: string
                    description: The name of the config map that contains the IBM Application Gateway configuration. Required for configmap type.
                  dataKey:
                    type: string
                    description: The config map YAML entry that contains the IBM Application Gateway configuration. Required for configmap type.
                  value:
                    type: string
                    description: The IBM Application Gateway configuration YAML text. Required for literal type.
                  url:
                    type: string
                    description: The URL location of the remote IBM Application Gateway configuration. Required for web type.
                  discoveryEndpoint:
                    type: string
                    description: The discovery endpoint used to retrieve the OIDC OP registration endpoint to dynamically register a new client. Required for oidc_registration type.
                  postData: 
                    type: array
                    description: A list of keys and values that will be added to the registration request as POST data. This must include the mandatory redirect_uris value. Required for oidc_registration type.
                    items:
                      type: object
                      properties:
                        name: 
                          type: string
                          description: The key name of the data value to add to the request.
                        value: 
                          type: string
                          description: A single data value to add to the request. If this property is specified the values property will be ignored. Required if the values property has not been specified.
                        values:
                          type: array
                          description: A list of data values to add to the request as an array. If the value property has been specified this property will be ignored. Required if the value property has not been specified.
                          items:
                            type: string
                      required:
                        - name
                  secret:
                    type: string
                    description: The name of a Kubernetes secret that contains any authorization data required for the OIDC client registration. The resulting client_id and secret will also be added to this secret. Required for oidc_registration type.
                  headers:
                    type: array
                    description: A list of headers to add to the HTTP request to retrieve the configuration source.
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                          description: The value type. A literal type will add the value directly to the new header. A secret type will lookup a Kubernetes secret to retrieve the value.
                          enum:
                            - literal
                            - secret
                        name:
                          type: string
                          description: The name of the header that will be added to the HTTP request.
                        value:
                          type: string
                          description: The value of the header that will be added to the HTTP request. If the type is set as secret this will be the name of the Kubernetes secret.
                        secretKey:
                          type: string
                          description: The key name to retrieve the header value from the specified Kubernetes secret. Required if the type is set as secret.
                      required:
                        - type
                        - name
                        - value
                required:
                  - type
        status:
          description: IAGStatus defines the observed state of IAG
          type: object
      type: object
  version: v1
  versions:
  - name: v1
    served: true
    storage: true
kubectl apply -f crd.yaml
  1. Deploy the operator (webhook server)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ibm-application-gateway-operator
  labels:
    app: ibm-application-gateway-injector
spec:
  replicas: 1
  selector:
    matchLabels:
      name: ibm-application-gateway-operator
      app: ibm-application-gateway-injector
  template:
    metadata:
      labels:
        name: ibm-application-gateway-operator
        app: ibm-application-gateway-injector
    spec:
      serviceAccountName: ibm-application-gateway-operator
      imagePullSecrets:
        - name: regcred
      containers:
        - name: ibm-application-gateway-operator
          image: ibmcom/ibm-application-gateway-operator:20.09.0
          command:
          - ibm-application-gateway-operator
          imagePullPolicy: Never
          env:
            - name: WATCH_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: OPERATOR_NAME
              value: "ibm-application-gateway-operator"
          volumeMounts:
          - name: webhook-certs
            mountPath: /etc/webhook/certs
            readOnly: true
      volumes:
      - name: webhook-certs
        secret:
          secretName: ibm-application-gateway-injector-webhook-certs
kubectl apply -f operator.yaml

Create the webhook service

The webhook server is running and listening internally on port 443. A Kubernetes service needs to be created that will expose the internal port outside of the container.

Note: The name of the service that is created must match the common name prefix that was used to generate the certificates

apiVersion: v1
kind: Service
metadata:
  name: ibm-application-gateway-injector-webhook-svc
  namespace: default
  labels:
    app: ibm-application-gateway-injector
spec:
  ports:
  - port: 443
    targetPort: 8443
  selector:
    app: ibm-application-gateway-injector
kubectl apply -f service.yaml

Deploy the webhook configuration.

The IBM Application Gateway admission controller needs to be registered in Kubernetes so that it will be called as part of the deployment management process.

The clientConfig section of the webhook configuration must reference:

  1. The new service that was created so that the admission controller knows how to contact the webhook server.
  2. The certificate to use when communicating with the webhook server.
cat << EOF | kubectl apply -f -
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: ibm-application-gateway-injector-webhook-cfg
  labels:
    app: ibm-application-gateway-injector
webhooks:
- name: ibm-application-gateway-injector.ibm.com
  admissionReviewVersions: ["v1", "v1beta1"]
  sideEffects: NoneOnDryRun
  clientConfig:
    service:
      name: ibm-application-gateway-injector-webhook-svc
      namespace: default
      path: "/mutate"
    caBundle: "$(kubectl get secrets/ibm-application-gateway-webhook-certs -o jsonpath="{.data.cert\.pem}")" 
  rules:
  - operations: ["CREATE", "UPDATE", "DELETE"]
    apiGroups: ["apps", ""]
    apiVersions: ["v1"]
    resources: ["deployments"]
EOF

At this point the IBM Application Gateway admission controller is running and ready to go.

Deployment sidecar annotations

Each registered admission controller will be called by Kubernetes for each deployment management request. This means that there needs to be a method by which the admission controller can determine whether or not to perform any mutation. The IBM Application Gateway admission controller will check the deployment annotations to decide whether or not to handle container modifications.

If any of the annotation keys has a prefix of "ibm-application-gateway.security.ibm.com/" the IBM Application Gateway admission controller will mutate the request. The annotation keys and values are used to determine how the IBM Application Gateway sidecar container will be configured.

The supported annotations are mapped in the following categories:

  1. Deployment
  2. Service
  3. Configuration
  4. Environment

Deployment annotations

Deployment annotations define how the IBM Application Gateway sidecar container is deployment will be generated. The supported deployment keys are:

Name Description
ibm-application-gateway.security.ibm.com/deployment.image The name, tag and location of the IBM Application Gateway docker image. This is a required value and if not specified or the value is incorrect the request will fail.
ibm-application-gateway.security.ibm.com/deployment.imagePullPolicy The policy used to decide when to pull the IBM Application Gateway docker image from a remote server. If not specified the value will be set to ifNotPresent.

Note: If a imagePullSecret is required to pull the image it must be defined in the application deployment YAML.

Example:

ibm-application-gateway.security.ibm.com/deployment.image: ibmcom/ibm-application-gateway:20.09.0
ibm-application-gateway.security.ibm.com/deployment.imagePullPolicy: IfNotPresent

Service annotations

The IBM Application Gateway admission controller may add a new IBM Application Gateway sidecar container alongside the application. To be able to access the 8443 port of the sidecar container a new service may be required. If the service annotation is specified, the admission controller will create the new service exposing the port.

Note: This new service will be created by the admission controller. This means that the service will exist even if the Kubernetes deployment operation fails.

The supported service keys are:

Name Description
ibm-application-gateway.security.ibm.com/service.port The port to expose the internal 8443 port on. If not specified the service will not be created.

Example:

ibm-application-gateway.security.ibm.com/service.port: "30441"

will result in a new service being created:

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: "2020-06-10T06:05:45Z"
  generateName: appname-ibm-application-gateway-sidecar-svc
  labels:
    app: appname-ibm-application-gateway-sidecar-svc
  name: appname-ibm-application-gateway-sidecar-svcrdfqh
  namespace: default
spec:
  ports:
  - name: appname-ibm-application-gateway-sidecar-svc
    nodePort: 30441
    port: 8443
    protocol: TCP
    targetPort: 8443
  selector:
    app: appname-ibm-application-gateway-sidecar-pod
  type: NodePort  

Configuration annotations

The IBM Application Gateway sidecar container requires YAML configuration in order for it to run. The configuration can be created in one or more Kubernetes configmaps and/or one or more external web sources. The configuration sources are merged into a master configmap that is made available to the IBM Application Gateway sidecar container.

Note: The new master configmap will be created by the admission controller. This means that the configmap will exist even if the Kubernetes deployment operation fails.

The supported configuration keys are:

Name Description
ibm-application-gateway.security.ibm.com/configuration.<id>.type The type of the configuration source. The id must be unique for each separate source. The supported values are "configmap", "web" or "oidcregistration". Note that there can only be a single oidcregistration entry.
ibm-application-gateway.security.ibm.com/configuration.<id>.order The order in which to merge the configuration source into the master configmap. Later merges will overwrite any earlier values apart from array entries where the master configmap will contain all specified array entries from all sources. Note that the oidc_registration entry will always be merged last.
ibm-application-gateway.security.ibm.com/configuration.<id>.name The name of the config map that contains the IBM Application Gateway configuration. Required for configmap type.
ibm-application-gateway.security.ibm.com/configuration.<id>.dataKey The config map YAML entry that contains the IBM Application Gateway configuration. Required for configmap type.
ibm-application-gateway.security.ibm.com/configuration.<id>.url The URL location of the remote IBM Application Gateway configuration. Required for web type.
ibm-application-gateway.security.ibm.com/configuration.<id>.header.<hdrid>.type The type of header value to add to the request. A literal type will add the value directly to the new header. A secret type will lookup a Kubernetes secret to retrieve the value. The hdrid must be unique for each header.
ibm-application-gateway.security.ibm.com/configuration.<id>.header.<hdrid>.name The name of the header that will be added to the HTTP request.
ibm-application-gateway.security.ibm.com/configuration.<id>.header.<hdrid>.value The value of the header that will be added to the HTTP request. If the type is set as secret this will be the name of the Kubernetes secret.
ibm-application-gateway.security.ibm.com/configuration.<id>.header.<hdrid>.secretKey The key name to retrieve the header value from the specified Kubernetes secret. Required if the type is set as secret.
ibm-application-gateway.security.ibm.com/configuration.<id>.discoveryEndpoint The endpoint that can be used to discover the registration endpoint and token endpoint of the OIDC OP. Required for oidc_registration type.
ibm-application-gateway.security.ibm.com/configuration.<id>.secret Specifies a Kubernetes secret that may contain authorization data for the registration request. This is also the location where the resulting client ID and secret are stored upon successful registration. Required for oidc_registration type.
ibm-application-gateway.security.ibm.com/configuration.<id>.postData.<pdid>.name The name of a POST data entry that will be added to the registration request as POST data. Only valid for oidc_registration type.
ibm-application-gateway.security.ibm.com/configuration.<id>.postData.<pdid>.value A single value of the POST data entry that will be added to the registration request as POST data. Only valid for oidc_registration type.
ibm-application-gateway.security.ibm.com/configuration.<id>.postData.<pdid>.values.<valueid> A value that will be added to an array of values for the POST data entry that will be added to the registration request as POST data. This will be ignored if a single "value" has been set. Only valid for oidc_registration type.

Example:

ibm-application-gateway.security.ibm.com/configuration.test.type: configmap
ibm-application-gateway.security.ibm.com/configuration.test.name: test-config
ibm-application-gateway.security.ibm.com/configuration.test.dataKey: config
ibm-application-gateway.security.ibm.com/configuration.test.order: "1"
ibm-application-gateway.security.ibm.com/configuration.sample.type: "web"
ibm-application-gateway.security.ibm.com/configuration.sample.url: https://raw.github.ibm.com/IAG/iag-config/master/test/sample1.yaml
ibm-application-gateway.security.ibm.com/configuration.sample.order: "2"
ibm-application-gateway.security.ibm.com/configuration.sample.header.authz.type: secret
ibm-application-gateway.security.ibm.com/configuration.sample.header.authz.name: Authorization
ibm-application-gateway.security.ibm.com/configuration.sample.header.authz.value: githubsecret
ibm-application-gateway.security.ibm.com/configuration.sample.header.authz.secretKey: value
ibm-application-gateway.security.ibm.com/configuration.oidc.type: oidc_registration
ibm-application-gateway.security.ibm.com/configuration.oidc.discoveryEndpoint: https://iag-dev.pre1.idng.ibmcloudsecurity.com/oidc/endpoint/default/.well-known/openid-configuration
ibm-application-gateway.security.ibm.com/configuration.oidc.secret: oidc-client
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.rduri.name: redirect_uris
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.rduri.values.value1: https://127.0.0.1:30112/pkmsoidc
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.cn.name: client_name
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.cn.value: OperatorTest
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.aue.name: all_users_entitled
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.aue.value: "true"
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.ep.name: enforce_pkce
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.ep.value: "false"
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.ca.name: consent_action
ibm-application-gateway.security.ibm.com/configuration.oidc.postData.ca.value: "never_prompt"
ibm-application-gateway.security.ibm.com/configuration.oidc.order: "3"

will result in a new master configmap being created:

apiVersion: v1
data:
  config.yaml: |
    identity:
      oidc:
        client_id: secret:oidc-client/client_id
        client_secret: secret:oidc-client/client_secret
        discovery_endpoint: https://iag.ibmcloudsecurity.com/oidc/endpoint/default/.well-known/openid-configuration
    resource_servers:
    - connection_type: tcp
      path: /sample
      servers:
      - host: 10.0.0.12
        port: 80
    - connection_type: tcp
      path: /eai
      servers:
      - host: 10.0.0.15
        port: 8080
    server:
      local_applications:
        cred_viewer:
          enable_html: false
          path_segment: creds
    version: "20.09"
kind: ConfigMap
metadata:
  creationTimestamp: "2020-06-10T06:05:47Z"
  generateName: appname-ibm-application-gateway-sidecar-configmap
  labels:
    app: appname-ibm-application-gateway-sidecar-pod
  name: appname-ibm-application-gateway-sidecar-configmap9c8dm
  namespace: default

The config.yaml data value is a merging of the three defined configuration sources.

Environment annotations

The IBM Application Gateway sidecar container may require certain environment variables to be set to operate correctly. Environment annotations allow these environment variable values to be set.

The supported environment keys are:

Name Description
ibm-application-gateway.security.ibm.com/env.<name> This will result in a new environment variable being set where <name> specifies the name of the variable (case sensitive) and the specified value.

Example:

ibm-application-gateway.security.ibm.com/env.LANG: fr

will result in a new environment variable being set "LANG=fr".

Deployment example

Assuming that the IBM Application Gateway admission controller has been setup and deployed the following deployment will result in an IBM Application Gateway sidecar container being created alongside the application:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: testapp
  labels:
    app: testapp
    name: testapp
  annotations:
    ibm-application-gateway.security.ibm.com/env.LANG: en
    ibm-application-gateway.security.ibm.com/configuration.test.type: configmap
    ibm-application-gateway.security.ibm.com/configuration.test.name: test-config
    ibm-application-gateway.security.ibm.com/configuration.test.dataKey: config
    ibm-application-gateway.security.ibm.com/configuration.test.order: "1"
    ibm-application-gateway.security.ibm.com/configuration.sample.type: "web"
    ibm-application-gateway.security.ibm.com/configuration.sample.url: https://raw.github.ibm.com/IAG/iag-config/master/test/sample1.yaml
    ibm-application-gateway.security.ibm.com/configuration.sample.order: "2"
    ibm-application-gateway.security.ibm.com/configuration.sample.header.authz.type: secret
    ibm-application-gateway.security.ibm.com/configuration.sample.header.authz.name: Authorization
    ibm-application-gateway.security.ibm.com/configuration.sample.header.authz.value: githubsecret
    ibm-application-gateway.security.ibm.com/configuration.sample.header.authz.secretKey: value
    ibm-application-gateway.security.ibm.com/deployment.image: ibmcom/ibm-application-gateway:20.09.0
    ibm-application-gateway.security.ibm.com/deployment.imagePullPolicy: IfNotPresent
    ibm-application-gateway.security.ibm.com/service.port: "30441"
spec:
  selector:
    matchLabels:
      app: testapp
      name: testapp
  replicas: 1
  template:
    metadata:
      labels:
        app: testapp
        name: testapp
    spec:
      imagePullSecrets:
        - name: regcred
      containers:
      - name: testapp
        image: alpine
        command:
          - /bin/sh
          - "-c"
          - "sleep 70m"
        imagePullPolicy: IfNotPresent
kubectl apply -f deployment.yaml
$ kubectl get pods
NAME                                                READY   STATUS             RESTARTS   AGE
ibm-application-gateway-operator-58d7df64d9-848jz   1/1     Running.           1          1d
testapp-645db9c874-bmq4k                            2/2     Running            1          1d

Note: The testapp pod has 2 containers that are both ready.

$ kubectl get services
NAME                                             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
testapp-ibm-application-gateway-sidecar-svcrdfqh NodePort    10.109.167.144   <none>        8443:30441/TCP      1d
$ kubectl get configmaps
NAME                                                   DATA   AGE
test-config                                            1      6d
testapp-ibm-application-gateway-sidecar-configmap9c8dm 1      1d

Supported RESTful operations

Create

When a deployment is first created the IBM Application Gateway admission controller will be called with a RESTful create operation. The admission controller will perform the following tasks:

  1. Check to see if the deployment annotations contains any keys with the prefix "ibm-application-gateway.security.ibm.com/". If not then the admission controller will make no changes and return.
  2. Run some validation on the annotations to try and ensure that no simple failures will occur leaving the environment in an intermediate state.
  3. Check to see if the annotations contain a service port. If so a new service will be created.
  4. Read and merge the configuration sources to create a new master configmap.
  5. Return a new IBM Application Gateway container patch as the response. This will result in the IBM Application Gateway sidecar being created alongside the application.

Update

When a deployment is modified the IBM Application Gateway admission controller will be called with a RESTful update operation. The admission controller will perform the following tasks:

  1. Check to see if the deployment annotations contains any keys with the prefix "ibm-application-gateway.security.ibm.com/". If not then the admission controller will make no changes and return.
  2. Run some validation on the annotations to try and ensure that no simple failures will occur leaving the environment in an intermediate state.
  3. Check to see if the annotations contain a service port. If so the service will be updated if the port has changed.
  4. Read and merge the configuration sources to create a new master configmap.
  5. Return a new IBM Application Gateway container patch as the response. This will result in the IBM Application Gateway sidecar being updated alongside the application.

Delete

When a deployment is deleted the IBM Application Gateway admission controller will be called with a RESTful delete operation. The admission controller will perform the following tasks:

  1. Check to see if the deployment annotations contains any keys with the prefix "ibm-application-gateway.security.ibm.com/". If not then the admission controller will make no changes and return.
  2. Delete the service if it exists.
  3. Delete the master configmap.