Skip to main content

IBM Application Gateway Dynamic Client Registration Example

The IBM Application Gateway can be deployed in Kubernetes as an instance of the custom object type IBMApplicationGateway. A special configuration source can be specified that will allow the custom Kubernetes IBM Application Gateway operator to dynamically register a new client with an OIDC OP. The new client ID and secret will be added to the IBM Application Gateway configuration as an OIDC identity.

Operator Deployment Model

Example

The following steps will:

  • Setup the IBM Application Gateway operator
  • Register a new client application with IBM Security Verify
  • Create an application that will be fronted by IBM Application Gateway
  • Access the application via the IBM Application Gateway
  • The page will show the identity and other headers that have been added to the request by the IBM Application Gateway

Steps 1 - 11 are required to setup the IBM Application Gateway operator. To deploy further applications other than the one listed in the subsequent steps, the operator setup does NOT need to be performed again.

Note: This example uses Minikube with a docker driver

  1. Start Minikube.
minikube start --driver docker
  1. Set context.
kubectl config use-context minikube
eval $(minikube docker-env)
  1. Paste the following into a file named operator_service_account.yaml.
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ibm-application-gateway-operator
  1. Create the operator service account.
kubectl apply -f operator_service_account.yaml
  1. Paste the following into a file named rbac.yaml.
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
  1. Create the role binding.
kubectl apply -f rbac.yaml
  1. Paste the following into a file named crd.yaml.
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
  1. Deploy the custom resource definition.
kubectl apply -f crd.yaml
  1. Paste the following into a file named operator.yaml.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ibm-application-gateway-operator
spec:
  replicas: 1
  selector:
    matchLabels:
      name: ibm-application-gateway-operator
  template:
    metadata:
      labels:
        name: ibm-application-gateway-operator
    spec:
      serviceAccountName: ibm-application-gateway-operator
      containers:
        - name: ibm-application-gateway-operator
          image: ibmcom/ibm-application-gateway-operator:20.09.0
          command:
          - ibm-application-gateway-operator
          imagePullPolicy: IfNotPresent
          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"
  1. Deploy the operator.
kubectl apply -f operator.yaml
  1. Ensure that the operator pod has started correctly.
kubectl get all

NAME                                                    READY   STATUS    RESTARTS   AGE
pod/ibm-application-gateway-operator-6bb9c7d4fc-lq4v2   1/1     Running   0          11s

NAME                                               TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
service/kubernetes                                 ClusterIP      10.96.0.1        <none>        443/TCP             11m

NAME                                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ibm-application-gateway-operator   1/1     1            1           11s

NAME                                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/ibm-application-gateway-operator-6bb9c7d4fc   1         1         1       11s
  1. Paste the following into a file named iag_service_account.yaml.
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ibm-application-gateway
  1. Create the IBM Application Gateway service account.
kubectl apply -f iag_service_account.yaml
  1. Retrieve the IBM Security Verify API Access client ID and secret. For details see the IBM Security Verify documentation

  2. Paste the API Access client ID into a file named tokenRetrievalClientId.

  3. Paste the API Access client secret into a file named tokenRetrievalClientSecret.

  4. Create a Kubernetes secret containing the API Access client ID and secret.

kubectl create secret generic oidc-client --from-file=./tokenRetrievalClientSecret --from-file=./tokenRetrievalClientId
  1. Paste the following into a file named co.yaml.
apiVersion: ibm.com/v1
kind: IBMApplicationGateway
metadata:
  name: iag-instance
spec:
  replicas: 1
  deployment:
    serviceAccountName: ibm-application-gateway
    image: ibmcom/ibm-application-gateway:20.09.0
    imagePullPolicy: IfNotPresent 
  configuration:
    - type: oidc_registration
      discoveryEndpoint: https://iag-dev.pre1.idng.ibmcloudsecurity.com/oidc/endpoint/default/.well-known/openid-configuration
      postData: 
        - name: redirect_uris
          values:
            - https://127.0.0.1:30112/pkmsoidc
        - name: client_name
          value: OperatorTest
        - name: enforce_pkce
          value: "false"
        - name: all_users_entitled
          value: "true"
        - name: consent_action
          value: never_prompt
      secret: oidc-client
    - type: literal 
      value: |
        version: "20.09"
        resource_servers:
          - path: "/static"
            connection_type: "ssl"
            servers:
              - host: resource-server.au-syd.mybluemix.net
                port: 443
            identity_headers:
              attributes:
                - attribute: groupIds
                  header: iv_groups
                - attribute: AZN_CRED_AUTHZN_ID
                  header: iv_user
              jwt:
                certificate: "B64:QmFnIEF0dHJpYnV0ZXMKICAgIGZyaWVuZGx5TmFtZTogUlNBCiAgICBsb2NhbEtleUlEOiAwMyA4MiAwMSAwMSAwMCBEMyAwMyBCNSBFMiBERSA3RiBEMSAwOCBFOCBBMCA5QyBENCBDRSBCOCAwQSA1QSBEOSAyRCA2NSAzMCBDNyA3MCA5RiAyRCAxRiA0OSBFRSA3MCA1OCA3QyAyRSA0MCBDOCA3MCBGRSBEOSBFNiAzRSA0RSA2QiBENiAzOCBFMCBEMiAyMyAzOCA3QyBGOSA2RCBDMiAxNCAyRSBERCA2NyBGMSBBRCBDOCAwMyAxNCAyQiBGNCAzNCBEOCA4MCA4MSAwNCBFMiBFMCBBRCA2MSBDMCA4NyA2MSA2RiBCQiA5RSAzMiBDNSBEMCA0MiBERSAxMCBEQSAwNCBDNSAzRSA5OCA2QSA2NCBCQiBCNyA2RSBDQiBDRSBGQyBFRCBDMCBEQiBFMyA3RiAzQSBFRCAxQSBBMyBCNSBBMyBDNyBDRCAxMyAwMSA1NCAwMCBGMSBGRCAwNyBCRCA1NSA3QiBCMyA0NCBFMiA4RiA1OSA0RSAyNSBENiBFMSAyQiBFRSA3MSBFOCBGMCA2NSAxNiAxOCA2OCBEQiBCNCBCNiBBMCBDMiAxNiAwMCBBMiA4MSA1RiBGNyA2NCAwNiA1RiBEQSAyQSBENiA3MiBFRiBCMyBBQyBBMyA0NyAyMiBFOCAxRCA2NiAxMSBDOCBBNSBDOCBBNyAxRCBFNiAxMSA4QiAwOSBBQyAzMyAzNSBGQyAzMyBEOSA5RiA1OCBDNSAzOSBFNyBDMyA3MCAwMiA4NCAxQSA2MSAyMSA5MSBDNCBCOSA2MSBEMiAzOSA3NiBFMSAzRiAzQSBGOCBFNCBGRSBBRSAyQiBCNiA1MyAxMSA0NCBDNiAxRCA2RiA1RCBGMyBGQyAxMyAyNCBFNCA2RCA4QiAwRSA0NCAyNiAzMCAxQSA1QSAyOSA2RSA5RiA4MiBGRCBFRSA2QyA2QSBCQyBBOCBCRiAyQyBCMSA3MiBBQiBENSBDMCBGNyA3NCA3MiA5NCA4RSA3RSA5QyAxOSBFNyAyRiA1MCBEMSAKS2V5IEF0dHJpYnV0ZXM6IDxObyBBdHRyaWJ1dGVzPgotLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS0KTUlJRXZ3SUJBREFOQmdrcWhraUc5dzBCQVFFRkFBU0NCS2t3Z2dTbEFnRUFBb0lCQVFEbllIR3ZsY0VsWE1jVQprNWVxZ3d2ajJNc2FQblVPWVJYdy9FY2dzRWhKdnRtUVg4ak5lR3Fia1ZnSEJWL3RwZ1lsOW1jSHRPeXRvTzdRCjRLczhBZUFYek5tVCttUTNOR1h5bmx3K1Jod1prZm5vWUhZUExldkZhby82YzY5M1Z6WFFqaXpWa1RITHNjZloKeXJNN2VYdU9rcU9kUlVDTnpFSmNyVVlna3MrTVhsRlo0Zjk0WU9vZGNzYkJzLzZRYXFiWXBVcEEwUXpvRDRRaQpxOXlmUEFoM002WUJ5SnNMeGw5Q3RrVnlSaVFKUG5vZGl1SW1DNTRmZTBIN0NHNlpFOUhCeEc0YTBaZ1VVYWM2CnZoU25zaDJvRVVvQnZkaXVxaWsrYU1uNzFVR3BFTDRZWjQ2STRsQWd4d2xLRlBOZE5zSzBJY0VZbUo4VndCUUQKVnZsQlpKSVRBZ01CQUFFQ2dnRUFaOG4xZFVRQjdoYWVIdmJOOCtqdzduWVROV1NLOGJaUE4xaVROM0NjSEtpRgp3Nk9UMmNlSVd0eHAxa3hzNlpldDdsMkhmZ2VFbTZZek9uTnRuRzlpN0lveGw1V2NXcjhnZENMaFVmWDFLT3M0ClpTclFDcU1ZdmVlOVNpV1dzanZtb2ZVRTI1QlQvQUYxbXBhNHE1Y2srNkYvejA1L1ZKd3BzSlR4Zmk4Yzl1T0YKdGVxMmJDMUJUdFhNSjhJaHZTNi9LWjk0SFZzT2NwcHg2bG5oR1lwS0pQbHU2UHRZYmxCNjFYNkZqWng2MkloRgpQU0Z0UXVoMFlYbWZjYkpKNjlZYm9FQ0hsSEN0ZTE0MGxyanRHeHpEZ3FXa3EybWRyTFF6RHNhOWkxVjNvRE52Ckg0K3NrMGNwN1NVeGpWbXA1TzZENjdkTmZJaWk2MklnRUZNb0NRZUdjUUtCZ1FEN3RvM0pQbWF4SElKUWVOZXEKUkl0b3FpalUxcFJHVXZONUE4cEthckhkTHhPNnJxV25ZT0NHNzJzV0crSXRDeGg0dVJtYlBxcy9heXpDRVE2bgpkK05OWG9tbFV2Wng1dU90VGl5dkhVOUZ3ZE16clJ6T0hIc0lkUktHY2QxY0RWQm00dCtyRnlGRDl1YXNlN1dCCkxPbEFkRC95YkRWZjFUY1d4em5kbGFJNnJRS0JnUURyVVRtOGYwdm9yZm4vV29Ta3NmOEJ4M2JSYjB1Wk85Z1EKVGIveC84WXJvdStvKzZjcHRuMHk0N3MvckRNWFUyUUxNKzdHT3ZuNEd6eHVYVXBVdEZhY1pyOFB1Y09lM3ZqNQpsY21ablZHUHBSaVlvUWYvQVFFUWZtNk9ldUNOQ0dKUkZsM0szS09uN2xJaTI1MnVONHRZbXdLWGFkSjBOdVVYCk1za1NjRkpYdndLQmdRQ2Exazhkcmc4SmY5b0JtblEvdnU1cXNkRndLNWNHTTF5bDRsajdzZW83Znd3SjJBajYKanpOT2pkUTN3MnM3L2dsTnFiOUFxaW81VnJvdm5zSis3ZGFhN3o2SXZpSHZLdkorMXduUnBwdnU4eTN5S2RrQQpTTEMrSVJZR01lRFRFVFdXTkpVVjc2Sjg1bEk3WTlYZzRqbVJkbkVudEx5WWVOWHNZeDBMVzFKeCtRS0JnUUN2CndMYlNwbkRYbERsSUV4OUdzdnEzSlhjRTdZOFZIN0U4WEJXa2RWaFpkeFJ3cmFRb2IzZ0s3alFJVm1EQ1p6SXQKZTlnMmpnM3MxTXJKMHp1VkVDd3dIRDFQVFh0aHlUOURpakJNWDBkdmRldHM4N2k1S05MV3N0ZDM2eWFUcjFOZgpKTWxnbm5KTkZwNmFFbFV1cmFXUnhCU25hZzRaWm5hc1lPMzBxNWVVbVFLQmdRQzNKdDdxVHpSSVB0VEhQZGdlCmxzUThGZDBaeHdkNDNncENVYnpndys1QjlvSWVmMFV2NE1YZzMzZDZOaGV6MFdrTHBaMmFZZy8yVnBjV09NTjQKMC9KRW9ta2xjeFlFSkxaY0MyeDhWOVkxemgrOTBFTkpKVnZGS0FadXdhM2Ftc1VicU0ySnFvQ0thR29pbUdEdgptc1kvS1Q0NE8ycm9wazBBWEJ4VWlUZ3Ewdz09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0KQmFnIEF0dHJpYnV0ZXMKICAgIGZyaWVuZGx5TmFtZTogUlNBCiAgICBsb2NhbEtleUlEOiAwMyA4MiAwMSAwMSAwMCBEMyAwMyBCNSBFMiBERSA3RiBEMSAwOCBFOCBBMCA5QyBENCBDRSBCOCAwQSA1QSBEOSAyRCA2NSAzMCBDNyA3MCA5RiAyRCAxRiA0OSBFRSA3MCA1OCA3QyAyRSA0MCBDOCA3MCBGRSBEOSBFNiAzRSA0RSA2QiBENiAzOCBFMCBEMiAyMyAzOCA3QyBGOSA2RCBDMiAxNCAyRSBERCA2NyBGMSBBRCBDOCAwMyAxNCAyQiBGNCAzNCBEOCA4MCA4MSAwNCBFMiBFMCBBRCA2MSBDMCA4NyA2MSA2RiBCQiA5RSAzMiBDNSBEMCA0MiBERSAxMCBEQSAwNCBDNSAzRSA5OCA2QSA2NCBCQiBCNyA2RSBDQiBDRSBGQyBFRCBDMCBEQiBFMyA3RiAzQSBFRCAxQSBBMyBCNSBBMyBDNyBDRCAxMyAwMSA1NCAwMCBGMSBGRCAwNyBCRCA1NSA3QiBCMyA0NCBFMiA4RiA1OSA0RSAyNSBENiBFMSAyQiBFRSA3MSBFOCBGMCA2NSAxNiAxOCA2OCBEQiBCNCBCNiBBMCBDMiAxNiAwMCBBMiA4MSA1RiBGNyA2NCAwNiA1RiBEQSAyQSBENiA3MiBFRiBCMyBBQyBBMyA0NyAyMiBFOCAxRCA2NiAxMSBDOCBBNSBDOCBBNyAxRCBFNiAxMSA4QiAwOSBBQyAzMyAzNSBGQyAzMyBEOSA5RiA1OCBDNSAzOSBFNyBDMyA3MCAwMiA4NCAxQSA2MSAyMSA5MSBDNCBCOSA2MSBEMiAzOSA3NiBFMSAzRiAzQSBGOCBFNCBGRSBBRSAyQiBCNiA1MyAxMSA0NCBDNiAxRCA2RiA1RCBGMyBGQyAxMyAyNCBFNCA2RCA4QiAwRSA0NCAyNiAzMCAxQSA1QSAyOSA2RSA5RiA4MiBGRCBFRSA2QyA2QSBCQyBBOCBCRiAyQyBCMSA3MiBBQiBENSBDMCBGNyA3NCA3MiA5NCA4RSA3RSA5QyAxOSBFNyAyRiA1MCBEMSAKc3ViamVjdD1DTiA9IHJzYS5hdXRvdGVzdC5pYm0uY29tCgppc3N1ZXI9Q04gPSByc2EuYXV0b3Rlc3QuaWJtLmNvbQoKLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBakNDQWVxZ0F3SUJBZ0lJV3ZmTmxuV0c1MWt3RFFZSktvWklodmNOQVFFTkJRQXdIekVkTUJzR0ExVUUKQXhNVWNuTmhMbUYxZEc5MFpYTjBMbWxpYlM1amIyMHdIaGNOTVRreE1qRTVNREV6TWpBeldoY05Namt4TWpFMwpNREV6TWpBeldqQWZNUjB3R3dZRFZRUURFeFJ5YzJFdVlYVjBiM1JsYzNRdWFXSnRMbU52YlRDQ0FTSXdEUVlKCktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQU9kZ2NhK1Z3U1ZjeHhTVGw2cURDK1BZeXhvK2RRNWgKRmZEOFJ5Q3dTRW0rMlpCZnlNMTRhcHVSV0FjRlgrMm1CaVgyWndlMDdLMmc3dERncXp3QjRCZk0yWlA2WkRjMApaZktlWEQ1R0hCbVIrZWhnZGc4dDY4VnFqL3B6cjNkWE5kQ09MTldSTWN1eHg5bktzenQ1ZTQ2U281MUZRSTNNClFseXRSaUNTejR4ZVVWbmgvM2hnNmgxeXhzR3ovcEJxcHRpbFNrRFJET2dQaENLcjNKODhDSGN6cGdISW13dkcKWDBLMlJYSkdKQWsrZWgySzRpWUxuaDk3UWZzSWJwa1QwY0hFYmhyUm1CUlJwenErRktleUhhZ1JTZ0c5Mks2cQpLVDVveWZ2VlFha1F2aGhuam9qaVVDREhDVW9VODEwMndyUWh3UmlZbnhYQUZBTlcrVUZra2hNQ0F3RUFBYU5DCk1FQXdIUVlEVlIwT0JCWUVGQmN6SEZZYWdUd0VuNGVNOVlacTZ6TS9QeFdFTUI4R0ExVWRJd1FZTUJhQUZCY3oKSEZZYWdUd0VuNGVNOVlacTZ6TS9QeFdFTUEwR0NTcUdTSWIzRFFFQkRRVUFBNElCQVFEVEE3WGkzbi9SQ09pZwpuTlRPdUFwYTJTMWxNTWR3bnkwZlNlNXdXSHd1UU1ody90bm1QazVyMWpqZzBpTTRmUGx0d2hRdTNXZnhyY2dECkZDdjBOTmlBZ1FUaTRLMWh3SWRoYjd1ZU1zWFFRdDRRMmdURlBwaHFaTHUzYnN2Ty9PM0EyK04vT3UwYW83V2oKeDgwVEFWUUE4ZjBIdlZWN3MwVGlqMWxPSmRiaEsrNXg2UEJsRmhobzI3UzJvTUlXQUtLQlgvZGtCbC9hS3RaeQo3N09zbzBjaTZCMW1FY2lseUtjZDVoR0xDYXd6TmZ3ejJaOVl4VG5udzNBQ2hCcGhJWkhFdVdIU09YYmhQenI0CjVQNnVLN1pURVVUR0hXOWQ4L3dUSk9SdGl3NUVKakFhV2lsdW40TDk3bXhxdktpL0xMRnlxOVhBOTNSeWxJNSsKbkJubkwxRFIKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="
                hdr_name: jwt
                claims:
                  - text: www.ibm.com
                    name: iss
                  - attr: AZN_CRED_PRINCIPAL_NAME
                    name: sub
                  - attr: AZN_*
  1. Deploy the custom object.

Note: This will dynamically register a new client/application named OperatorTest with IBM Security Verify.

kubectl apply -f co.yaml
  1. Ensure that the IBM Application Gateway pod has started correctly.
kubectl get all

NAME                                                    READY   STATUS    RESTARTS   AGE
pod/iag-instance-76759f9764-nh4jd                       1/1     Running   0          3s
pod/ibm-application-gateway-operator-6bb9c7d4fc-lq4v2   1/1     Running   0          10m

NAME                                               TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
service/ibm-application-gateway-operator-metrics   ClusterIP      10.110.202.103   <none>        8383/TCP,8686/TCP   10m
service/kubernetes                                 ClusterIP      10.96.0.1        <none>        443/TCP             11m

NAME                                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/iag-instance                       1/1     1            1           3s
deployment.apps/ibm-application-gateway-operator   1/1     1            1           10m

NAME                                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/iag-instance-76759f9764                       1         1         1       3s
replicaset.apps/ibm-application-gateway-operator-6bb9c7d4fc   1         1         1       10m
  1. Expose the IBM Application Gateway port.
kubectl port-forward deployment.apps/iag-instance 30112:8443
  1. Use a browser to access the demo URL.
https://127.0.0.1:30112/static
  1. Sign in using the IBM Security Verify sign in page.

Example

  1. The demo page is shown.

This page includes the following pieces that have been added by the IBM Application Gateway:

  • A JWT header has been added
  • The IV-USER, IV-GROUPS and IV-SERVER-NAME headers have been added
  • The JWT has been extracted

Demo Application

  1. Exit the port forward process by pressing ctrl-c in the shell.

  2. Cleanup.

kubectl delete -f co.yaml
kubectl delete -f iag_service_account.yaml
kubectl delete -f operator.yaml
kubectl delete -f crd.yaml
kubectl delete -f rbac.yaml
kubectl delete -f operator_service_account.yaml
  1. Stop Minikube.
minikube stop