Solution Patterns: Connect, Secure and Protect with Red Hat Connectivity Link

See the Solution in Action

1. Walkthrough As a Platform Engineer

The ansible scripts we just run has setup the following as ArgoCD applicatiopns:

  • Red Hat Connectivity Link/Kuadrant operator and a Kuadrant instance

  • A TLS issuer for TLS certificates. [View CR]

    Click to see an example and description
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: prod-web-lets-encrypt-issuer
    spec:
      acme:
        email: abc@example.com
        preferredChain: ''
        privateKeySecretRef:
          name: le-production
        server: 'https://acme-v02.api.letsencrypt.org/directory'
        solvers:
          - dns01:
              route53:
                accessKeyIDSecretRef:
                  key: ********
                  name: ********
                region: ********
                secretAccessKeySecretRef:
                  key: AWS_SECRET_ACCESS_KEY
                  name: ********
    • TLS Issuer references to the ACME server Let’s Encrypt

    • It uses the DNS providers credentials, in this case AWS to create the TLS certificates

  • A Gateway (based on istio gateway) with a wildcard hostname based on the root domain. [View CR]

    Click to see an example and description
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: prod-web
      namespace: ingress-gateway
      labels:
        app.kubernetes.io/instance: ingress-gateway
        kuadrant.io/lb-attribute-geo-code: EU
    spec:
      gatewayClassName: istio
      listeners:
        - allowedRoutes:
            namespaces:
              from: All
          hostname: '*.globex.mycluster.example.com'
          name: api
          port: 443
          protocol: HTTPS
          tls:
            certificateRefs:
              - group: ''
                kind: Secret
                name: api-tls
            mode: Terminate
    • gatewayClassName refers to Istio as a the provider (Istio has also been setup by the Ansible script) *

  • Various policies attached to the Gateway:

    • A default deny-all Auth Policy to start with zero-trust [View CR]

      Click to see an example and description
      apiVersion: kuadrant.io/v1beta2
      kind: AuthPolicy
      metadata:
        name: prod-web-deny-all
        namespace: ingress-gateway
      spec:
        targetRef:
          group: gateway.networking.k8s.io
          kind: Gateway
          name: ingress-gateway
        rules:
          authorization:
            deny-all:
              opa:
                rego: "allow = false"
          response:
            unauthorized:
              headers:
                "content-type":
                  value: application/json
              body:
                value: |
                  {
                    "error": "Forbidden",
                    "message": "Access denied by default by the gateway operator. If you are the administrator of the service, create a specific auth policy for the route."
                  }
      • the target states that this AuthPolicy is attached to a specific Gateway

      • AuthorizationRule in this case is based pon opa - Open Policy Agent (OPA) Rego policy.

      • You can define the response to be sent in the response section; in this case, a response has been defined for unauthorized requests

    • TLS Policy [View CR]

      Click to see an example and description
      apiVersion: kuadrant.io/v1alpha1
      kind: TLSPolicy
      metadata:
        name: prod-web-tls-policy
        namespace: ingress-gateway
        finalizers:
          - kuadrant.io/tls-policy
        labels:
          app.kubernetes.io/instance: ingress-gateway
      spec:
        issuerRef:
          group: cert-manager.io
          kind: ClusterIssuer
          name: prod-web-lets-encrypt-issuer
        targetRef:
          group: gateway.networking.k8s.io
          kind: Gateway
          name: prod-web
      • This policy uses the CertificateIssuer to set up TLS certificates for the listeners defined within the Gateway.

      • The TLS certificate generated is attached to the Gateway as secret.

  • A sample EchoAPI endpoint and it’s HTTPRoute:

    • This is service literally echoes the request and is just used here for testing purposes. [View HTTPRoute]

      Click to see an example and description
      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: echo-api
        namespace: echo-api
      spec:
        hostnames:
          - echo.globex.mycluster.example.com
        parentRefs:
          - group: gateway.networking.k8s.io
            kind: Gateway
            name: prod-web
            namespace: ingress-gateway
        rules:
          - backendRefs:
              - group: ''
                kind: Service
                name: echo-api
                namespace: echo-api
                port: 8080
                weight: 1
            matches:
              - path:
                  type: PathPrefix
                  value: /
      • the hostname will be to access the service that is defined within backendRefs

1.1. Create a DNS Policy

Now that we have setup a secure, protected application connectivity environment, we are now ready to expose this to the Internet. We will do so by creating a DNSPolicy

  • Copy the following into the Import YAML utility accessible by the (+) button on top of the OpenShift Console

    apiVersion: kuadrant.io/v1alpha1
    kind: DNSPolicy
    metadata:
      name: prod-web-dnspolicy
      namespace: ingress-gateway
    spec:
      routingStrategy: "simple"
      targetRef:
        name: prod-web
        group: gateway.networking.k8s.io
        kind: Gateway
  • The DNSPolicy acts against a target Gateway by processing its listeners for hostnames and then create dns records for those hostnames.

  • Note that the routingStrategy is marked as "simple" because this is a single cluster deployment. But in case of multi-cluster deployments DNSPolicy allows for routingStrategy: loadbalanced and can optionally include loadbalancing specifications.

  • The targetRef sections refers to the [Gateway] created when the Ansible script was executed.

  • A number of DNS records are created on AWS Route 53.

    route53 dnsrecords

1.2. Echo API Walkthrough

Due to the nature of DNS Records it may take a while for it get propagated.
  • Check if the HTTPRoute works as it should. Run this curl command from a terminal.

    curl -k -w "%{http_code}" https://echo.globex.%AWSROOTZONE%
  • The Output will look like this

    {
      "method": "GET",
      "path": "/",
      "query_string": null,
      "body": "",
      "headers": {
        "HTTP_HOST": "echo.%AWSROOTZONE%",
        ...
      }
      ..
    }
  • Now let us run this 10 times and see how this responds to RateLimitPolicy that was applied

    for i in {1..10}; do curl -k -w "%{http_code}" https://echo.globex.%AWSROOTZONE%; done
  • You would see that you will get a response 5 times, post which you would see Too Many Requests 429

  • We haven’t setup a RateLimitPolicy for the echoAPI itself, and so the gateway’s default RateLimitPolicy gets applied to the echoAPI HTTPRoute. You can create another RateLimitPolicy and attach it to the echoAPI HTTPRoute to check this out.

    apiVersion: kuadrant.io/v1beta2
    kind: RateLimitPolicy
    metadata:
      name: echo-api-rlp
      namespace: echo-api
    spec:
      limits:
        echoa-api:
          rates:
            - duration: 10
              limit: 8
              unit: second
      targetRef:
        group: gateway.networking.k8s.io
        kind: HTTPRoute
        name: echo-api
        namespace: echo-api
  • Learn more about Rate Limiting here

1.3. What’s next

In the next section, we’ll go through the Developer’s Workflow