How to integrate Cloud Armor with Kong?

286 views Asked by At

I'm looking to integrate Cloud Armor with Kong to enhance security in my setup.

Did some research but couldn't find anything like that apart from someone having the same issue, namely

create an kong ingress controller and point my n service using same load balancer with cloud armor profile attached to kong by default.

How can that be done?

Tried what Bobbake4 suggested on a cluster, but didn’t work.

Backend Config:

 ➜  ~ devk describe BackendConfig
 Name:         cloudarmor-bitbucket
 Namespace:    default
 Labels:       <none>
 Annotations:  <none>
 API Version:  cloud.google.com/v1
 Kind:         BackendConfig
 Metadata:
   Creation Timestamp:  2023-07-26T19:13:05Z
   Generation:          1
   Resource Version:    33765445
   UID:                 some-uid
 Spec:
   Security Policy:
     Name:  bitbucket-pipelines-whitelist
 Events:    <none>

Proxy service:

 devk get service kong-proxy -n kong-ext -o yaml
 apiVersion: v1
 kind: Service
 metadata:
   annotations:
     cloud.google.com/backend-config: '{"default": "cloudarmor-bitbucket"}'
     cloud.google.com/neg: '{"ingress":true}'

enter image description here

Here's the full service

 apiVersion: v1
 kind: Service
 metadata:
   annotations:
     cloud.google.com/backend-config: '{"default": "bitbucket-pipelines-whitelist"}'
     cloud.google.com/neg: '{"ingress":true}'
     kubectl.kubernetes.io/last-applied-configuration: |
       {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{"service.beta.kubernetes.io/aws-load-balancer-backend-protocol":"tcp","service.beta.kubernetes.io/aws-load-balancer-type":"nlb"},"name":"kong-proxy","namespace":"kong-ext"},"spec":{"ports":[{"name":"proxy","port":80,"protocol":"TCP","targetPort":8000},{"name":"proxy-ssl","port":443,"protocol":"TCP","targetPort":8443}],"selector":{"app":"proxy-kong"},"type":"LoadBalancer"}}
   creationTimestamp: "2023-07-19T23:26:53Z"
   finalizers:
   - service.kubernetes.io/load-balancer-cleanup
   name: kong-proxy
   namespace: kong-ext
   resourceVersion: "11159902"
   uid: fd88a72b-0602-4398-9a0e-7ac4cd8366a0
 spec:
   allocateLoadBalancerNodePorts: true
   clusterIP: 10.118.0.217
   clusterIPs:
   - 10.118.0.217
   externalTrafficPolicy: Cluster
   internalTrafficPolicy: Cluster
   ipFamilies:
   - IPv4
   ipFamilyPolicy: SingleStack
   ports:
   - name: proxy
     nodePort: 31413
     port: 80
     protocol: TCP
     targetPort: 8000
   - name: proxy-ssl
     nodePort: 31915
     port: 443
     protocol: TCP
     targetPort: 8443
   selector:
     app: proxy-kong
   sessionAffinity: None
   type: LoadBalancer

and

 apiVersion: cloud.google.com/v1
 kind: BackendConfig
 metadata:
   annotations:
     kubectl.kubernetes.io/last-applied-configuration: |
       {"apiVersion":"cloud.google.com/v1","kind":"BackendConfig","metadata":{"annotations":{},"name":"bitbucket-pipelines-whitelist","namespace":"kong-ext"},"spec":{"securityPolicy":{"name":"bitbucket-pipelines-whitelist"}}}
   creationTimestamp: "2023-08-03T18:05:04Z"
   generation: 1
   name: bitbucket-pipelines-whitelist
   namespace: kong-ext
   resourceVersion: "11157046"
   uid: 2a882b8a-ad69-4375-8ae9-3523fa47f4df
 spec:
   securityPolicy:
     name: bitbucket-pipelines-whitelist

As pointed by boredabdel, changed the Kong proxy to ClusterIP but now I don't have a public IP and still can't assign the Cloud Armor to the service

 change the kong-proxy service to Cluster IP
apiVersion: v1
kind: Service
metadata:
  annotations:
    cloud.google.com/backend-config: '{"default": "bitbucket-pipelines-whitelist"}'
    cloud.google.com/neg: '{"ingress":true}'
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{"service.beta.kubernetes.io/aws-load-balancer-backend-protocol":"tcp","service.beta.kubernetes.io/aws-load-balancer-type":"nlb"},"name":"kong-proxy","namespace":"kong-ext"},"spec":{"ports":[{"name":"proxy","port":80,"protocol":"TCP","targetPort":8000},{"name":"proxy-ssl","port":443,"protocol":"TCP","targetPort":8443}],"selector":{"app":"proxy-kong"},"type":"LoadBalancer"}}
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp
    service.beta.kubernetes.io/aws-load-balancer-type: nlb
  creationTimestamp: "2023-07-19T23:26:53Z"
  name: kong-proxy
  namespace: kong-ext
  resourceVersion: "14344187"
  uid: fd88a72b-0602-4398-9a0e-7ac4cd8366a0
spec:
  clusterIP: 10.118.0.217
  clusterIPs:
  - 10.118.0.217
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: proxy
    port: 80
    protocol: TCP
    targetPort: 8000
  - name: proxy-ssl
    port: 443
    protocol: TCP
    targetPort: 8443
  selector:
    app: proxy-kong
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}
2

There are 2 answers

7
boredabdel On

I'm not very familiar with Kong. But if Kong is just an Ingress controller. Than it should not be an issue.

Cloud Armor attaches policies to the backend not to the Ingress.

The way you would do it typically is:

  • Create your Cloud Armor Policy
  • Create a BackendConfig object which points to the policy
  • Associate the BackendConfig object to the Kubernetes Service via annotation

Than you would expose your Service via Ingress as every other Ingress works

2
Bobbake4 On

I have this setup for a few projects I maintain. The basic flow is similar to what @boredabdel mentioned in that you need to create a BackendConfig but you must attach this to the Kong proxy service inside Kubernetes. I use the Kong Helm chart to manage Kong and it will create multiple services so it's important for you to apply the BackendConfig to the proxy service the Helm chart creates. Below is a sample BackendConfig which will attach the Cloud Armor policy named my-cloud-armor-policy, note that it is called securityPolicy. This can be applied to the service with a simple annotation in the service YAML shown below.

Backend Config CRD

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: kong-backend-config
spec:
  securityPolicy:
    name: my-cloud-armor-policy

Apply to the Kong Proxy service in the annotations block

apiVersion: v1
kind: Service
metadata:
  name: {helm-release-name}-kong-proxy
  annotations:
    cloud.google.com/backend-config: '{"ports": {"80":"kong-backend-config","443":"kong-backend-config"}}'

It's important to note that the BackendConfig changes will take a second to sync as it's an asynchronous process. If you don't see the changes right away give it 5 minutes before making any changes.

Finally, after the changes are complete you can navigate to the load balancers inside Google Cloud under "Network Services -> Load Balancing" and view the Kong load balancer settings there. If you select the LB and expand the Backend services block you can confirm if the Backend security policy is attached to the Kong LB. Don't make any manual changes here though as they will get overwritten on the next k8s sync.