Connect and protect APIs and services

You can use Connectivity Link to protect applications and APIs on existing OpenShift Container Platform clusters and Gateway objects. You can also monitor workloads and the status of OpenShift Container Platform resource metrics and tracing by using observability dashboards and alerts.

Example tasks
  • Configure routes

    • Set up application routes and API definitions and publish them to the cluster.

  • Protect applications with Auth policies and allow API access

    • OAuth 2

    • JWT authorization policies

    • API keys

    • Kubernetes tokens

    • Role-based access (RBAC)

    • Relationship-based access control (ReBAC)

    • Open Policy Agent (OPA)

  • Observe application and API performance

    • Monitor workloads and the status of OpenShift Container Platform resource metrics and tracing by using observability dashboards and alerts.

    • Ensure that APIs meet performance and availability benchmarks achieved by other data centers by viewing API metrics, such as uptime, requests per second, latency, and errors per minute.

Allow API access

You can allow users access to your APIs by overriding existing deny-all gateway-level policies. You must also attach application-level AuthPolicy objects and rate-limiting CRs to your HTTPRoute objects.

Important

The following example allows two users access to the Toystore API by using API keys to authenticate the requests. Other options, such as OpenID Connect, are more appropriate for production use. Use the "least-access" approach that is best for your use case.

Prerequisites
  • Connectivity Link is installed.

  • You configured Connectivity Link policies.

  • You installed the OpenShift CLI (oc).

  • You are logged into OpenShift Container Platform as a cluster administrator.

Procedure
  1. Set the KUADRANT_SYSTEM_NS environment variable based on where you created the Kuadrant custom resource (CR) by running the following command:

    $ export KUADRANT_SYSTEM_NS=$(oc get kuadrant -A -o jsonpath="{.items[0].metadata.namespace}")
  2. Create the Secret custom resources (CRs), or API keys, for bob and alice users that contain the following information:

    Example user Secret CRs
    apiVersion: v1
    kind: Secret
    metadata:
      name: bob-key
      namespace: ${KUADRANT_SYSTEM_NS}
      labels:
        authorino.kuadrant.io/managed-by: authorino
        app: toystore
      annotations:
        secret.kuadrant.io/user-id: bob
    stringData:
      api_key: IAMBOB
    type: Opaque
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: alice-key
      namespace: ${KUADRANT_SYSTEM_NS}
      labels:
        authorino.kuadrant.io/managed-by: authorino
        app: toystore
      annotations:
        secret.kuadrant.io/user-id: alice
    stringData:
      api_key: IAMALICE
    type: Opaque
    EOF
  3. Apply the API keys by running the following commands:

    $ oc apply -f <bob_key.yaml>

    Replace <bob_key.yaml> with the filename you used.

    $ oc apply -f <alice_key.yaml>

    Replace <alice_key.yaml> with the filename you used.

  4. Create a new AuthPolicy in a different namespace that overrides the deny-all policy and accepts the API keys. For example, the following toystore-auth.yaml:

    Example user AuthPolicy
    apiVersion: kuadrant.io/v1
    kind: AuthPolicy
    metadata:
      name: toystore-auth
      namespace: ${KUADRANT_DEVELOPER_NS}
    spec:
      targetRef:
        group: gateway.networking.k8s.io
        kind: HTTPRoute
        name: toystore
      defaults:
       when:
         - predicate: "request.path != '/health'"
       rules:
        authentication:
          "api-key-users":
            apiKey:
              selector:
                matchLabels:
                  app: toystore
            credentials:
              authorizationHeader:
                prefix: APIKEY
        response:
          success:
            filters:
              "identity":
                json:
                  properties:
                    "userid":
                      selector: auth.identity.metadata.annotations.secret\.kuadrant\.io/user-id
  5. Apply the AuthPolicy CR by running the following commands:

    $ oc apply -f <bob_key.yaml>

    Replace <bob_key.yaml> with the filename you used.

Service and Deployment objects reference

Before you can create a route to host your application at a public URL, you must create a Service custom resource (CR) as a routing rule. As a best practice, you must also create a Deployment object that is the application pod.

The following is an example of both Deployment and Service CRs for the Toystore example application that you can use as reference in creating your own.

Example application Deployment and Service CRs
apiVersion: apps/v1
kind: Deployment
metadata:
  name: toystore
  labels:
    app: toystore
spec:
  selector:
    matchLabels:
      app: toystore
  template:
    metadata:
      labels:
        app: toystore
    spec:
      containers:
        - name: toystore
          image: quay.io/kuadrant/authorino-examples:api
          env:
            - name: LOG_LEVEL
              value: "debug"
            - name: PORT
              value: "3000"
          ports:
            - containerPort: 3000
              name: http
  replicas: 1
---
apiVersion: v1
kind: Service
metadata:
  name: toystore
spec:
  selector:
    app: toystore
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 3000
Create an HTTP route for an application

As an application developer, you can create a route to host your application at a public URL.

In Gateway API, use the HTTPRoute custom resource (CR) to specify the routing behavior of HTTP requests from your Gateway object to your application. An HTTPRoute CR is especially useful for multiplexing HTTP or terminated HTTPS connections.

Prerequisites
  • You installed Connectivity Link on one or more clusters.

  • You installed the OpenShift CLI (oc).

  • You have write access to the OpenShift Container Platform namespaces you need to work with.

  • You have access to external or on-premise DNS.

  • You created and applied a Gateway object.

  • You have a web application that exposes a port and a TCP endpoint listening for traffic on the port.

  • You created a Service object for your application.

  • You have a local Certificate Authority (CA) bundle.

Procedure
  1. Create an HTTPRoute custom resource (CR), such as <toystore>-route.yaml, that has the following information:

    Example HTTPRoute CR
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: <toystore>
      namespace: <${KUADRANT_DEVELOPER_NS}>
      labels:
        deployment: <toystore>
        service: <toystore>
    spec:
      parentRefs:
        - name: <${KUADRANT_GATEWAY_NAME}>
          namespace: <${KUADRANT_GATEWAY_NS}>
      hostnames:
        - api.${KUADRANT_ZONE_ROOT_DOMAIN}
      rules:
        - matches:
            - method: GET
              path:
                type: PathPrefix
                value: /cars
            - method: GET
              path:
                type: PathPrefix
                value: /health
          backendRefs:
            - name: <toystore>
              port: 80
    • Replace <toystore> with the name of your application.

    • metadata.namespace: The namespace in which you are deploying your application. Replace <${KUADRANT_DEVELOPER_NS}> with the environment variable you used during installation.

    • spec.parentRefs.name and spec.parentRefs.namespace: The values must match the Gateway object.

    • spec.hostnames: The hostname must match the one specified in the Gateway object.

    • hostname.rules.matches.backendRefs.name: The name of the Service for your application.

  2. Apply your HTTPRoute CR by running the following command:

    $ oc apply -f <toystore>-route.yaml

    Replace <toystore> with the name of your application.

    Example output
    httproute.gateway.networking.k8s.io/toystore-route created

    The output indicates that the route to the application exists.

Verification
  1. Verify that the HTTPRoute is created by running the following command:

    $ oc get httproute <toystore> -n kuadrant -o=jsonpath='{.status.parents[].conditions[?(@.type=="Accepted")].message}{"\n"}{.status.parents[].conditions[?(@.type=="ResolvedRefs")].message}'

    Replace <toystore> with the name of your application.

    Example output
    Route was valid
  2. If you have DNSPolicy and TLSPolicy objects applied, you can validate that your backend is reachable by running the following command:

    $ curl -k  https://api.${KUADRANT_ZONE_ROOT_DOMAIN}:443/cars

    Note that the example TLSPolicy CR uses a self-signed ClusterIssuer object.

Override the low-limit RateLimitPolicy for specific users

When you want to only allow a certain number of requests for specific users to an API that you are developing, and a general limit for all other users, you can override the default low-limit RateLimitPolicy custom resource (CR).

Important

An existing Gateway-level policy affects new HTTPRoute objects. Because you want users to now access this API, you must override that Gateway policy. For simplicity, you can use API keys to authenticate the requests, but other options such as OpenID Connect are also available.

Prerequisites
  • You installed Connectivity Link on one or more clusters.

  • If you plan to use rate-limiting in a multicluster environment, you have a shared Redis-based datastore.

  • You installed the OpenShift CLI (oc).

  • You have write access to the OpenShift Container Platform namespaces you need to work with.

  • You have access to external or on-premise DNS.

  • You created a Gateway object.

  • You configured your gateway policies and HTTP routes.

Procedure
  1. Create a new RateLimitPolicy custom resource (CR) in a different namespace to override the default low-limit policy and set rate limits for specific users by using the following example:

    Example RateLimitPolicy CR for specific users
    apiVersion: kuadrant.io/v1
    kind: RateLimitPolicy
    metadata:
      name: toystore-rlp
      namespace: ${KUADRANT_DEVELOPER_NS}
    spec:
      targetRef:
        group: gateway.networking.k8s.io
        kind: HTTPRoute
        name: toystore
      limits:
        "general-user":
          rates:
          - limit: 5
            window: 10s
          counters:
          - expression: auth.identity.userid
          when:
          - predicate: "auth.identity.userid != 'bob'"
        "bob-limit":
          rates:
          - limit: 2
            window: 10s
          when:
          - predicate: "auth.identity.userid == 'bob'"
  2. Apply the CR by running the following command:

    $ oc apply -f <toystore-rlp>
    • Replace <toystore-rlp> with the name of your YAML.

    • Wait a few minutes for the RateLimitPolicy CR to be applied.

  3. Check that the RateLimitPolicy has a status of Accepted and Enforced by running the following command:

    $ oc get ratelimitpolicy -n ${KUADRANT_DEVELOPER_NS} toystore-rlp -o=jsonpath='{.status.conditions[?(@.type=="Accepted")].message}{"\n"}{.status.conditions[?(@.type=="Enforced")].message}'
  4. Check that the status of the HTTPRoute is now affected by the RateLimitPolicy CR in the same namespace:

    $ oc get httproute toystore -n ${KUADRANT_DEVELOPER_NS} -o=jsonpath='{.status.parents[0].conditions[?(@.type=="kuadrant.io/RateLimitPolicyAffected")].message}'
Verification
  1. Send requests as user alice by running the following command:

    $ while :; do curl -k --write-out '%{http_code}\n' --silent --output /dev/null -H 'Authorization: APIKEY IAMALICE' "https://api.$KUADRANT_ZONE_ROOT_DOMAIN/cars" | grep -E --color "\b(429)\b|$"; sleep 1; done

    The expected outcome is an HTTP status 200 every second for 5 seconds, followed by HTTP status 429 every second for 5 seconds.

  2. Send requests as user bob by running the following command:

    $ while :; do curl -k --write-out '%{http_code}\n' --silent --output /dev/null -H 'Authorization: APIKEY IAMBOB' "https://api.$KUADRANT_ZONE_ROOT_DOMAIN/cars" | grep -E --color "\b(429)\b|$"; sleep 1; done

    The expected outcome is an HTTP status 200 every second for 2 seconds, followed by HTTP status 429 every second for 8 seconds.

Workflow to configure your Gateway, routes, and policy resources

After you deploy your Gateway object, you must expose endpoints, program your HTTP listener, and secure your connections with policies. You can also apply rate-limiting to ensure performance.

Important

In multicluster environments, you must perform all of the steps in each cluster individually, unless specifically excluded.

To complete your deployment, take the following steps:

  • Create and apply a TLSPolicy custom resource (CR) that uses your CertificateIssuer object to set up your HTTPS listener certificates.

  • Create and apply an HTTPRoute or GRPCRoute CR for your Gateway object to communicate with your backend application API.

  • Create and apply an AuthPolicy CR to set up a default HTTP 403 response for any unprotected endpoints.

    Tip

    Use the oc explain authpolicies command to understand which authentication methods are supported when you use Connectivity Link on OpenShift Container Platform. The in-cluster API documentation lists all supported authentication mechanisms.

  • Create and apply a RateLimitPolicy CR to set up a default artificially low global limit to further protect any endpoints exposed by the Gateway object.

  • Create and apply a DNSPolicy CR with a load balancing strategy for your Gateway object.