authenticationkubernetesapi-gatewaykong

Kong Ingress Controller: Failed parsing resource errors, dataplane-synchronizer Could not update kong admin


I write this post even though I already solved the issue, because I think it might help someone out there, since I couldn't the cause nor a solution anywhere.


I'm learning Kong authentication strategies, in particular through these plugins:

However, I've been stuck for almost an hour on a error which I wasn't able to identify nor address. From kong controller logs (kubectl logs -n kong -f <kong_controller_pod_name>):

[...]
2023-11-22T15:09:42Z    error   Failed parsing resource errors  {"url": "https://10.244.0.125:8444", "update_strategy": "InMemory", "error": "could not unmarshal config error: json: cannot unmarshal object into Go struct field ConfigError.flattened_errors of type []sendconfig.FlatEntityError"}
2023-11-22T15:09:42Z    error   dataplane-synchronizer  Could not update kong admin     {"error": "performing update for https://10.244.0.125:8444 failed: failed posting new config to /config: got status code 400"}

This error was being thrown every 3 seconds.

Setup

Kong Ingress Controller running on minikube:

minikube start --driver=docker
minikube tunnel      # running in another terminal

Then follow the steps from Get Started: Install KIC

Configuration Files

Secrets

File secrets.yaml:

# JWT Credential for Admin
apiVersion: v1
kind: Secret
metadata:
  name: jwt-admin-secret
  labels:
    konghq.com/credential: jwt
type: Opaque
stringData:
  key: admin-issuer
  algorithm: RS256
  secret: empty     # dummy field with arbitrary value, otherwise it throws an error
  rsa_public_key: |
    -----BEGIN PUBLIC KEY-----
    [...]
    -----END PUBLIC KEY-----
---
# JWT Credential for User
apiVersion: v1
kind: Secret
metadata:
  name: jwt-user-secret
  labels:
    konghq.com/credential: jwt
type: Opaque
stringData:
  key: user-issuer
  algorithm: RS256
  secret: empty     # dummy field with arbitrary value, otherwise it throws an error
  rsa_public_key: |
    -----BEGIN PUBLIC KEY-----
    [...]
    -----END PUBLIC KEY-----
---
# Basic auth for a generic user
apiVersion: v1
kind: Secret
metadata:
  name: user-generic-secret
  labels:
    konghq.com/credential: basic-auth
type: Opaque
stringData:
  username: user
  password: password
---
# Key auth for a generic API key
apiVersion: v1
kind: Secret
metadata:
  name: key-generic-secret
  labels:
    konghq.com/credential: key-auth
type: Opaque
stringData:
  key: key

Consumers

File consumers.yaml:

# Consumer for Admin JWT token
apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
 name: admin
 annotations:
   kubernetes.io/ingress.class: kong
username: admin
credentials:
- jwt-admin-secret      # references Kubernetes secret
---
# Consumer for User JWT token
apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
 name: user
 annotations:
   kubernetes.io/ingress.class: kong
username: user
credentials:
- jwt-user-secret       # references Kubernetes secret
---
# Consumer for generic basic auth user
apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
 name: generic-basic-auth-consumer
 annotations:
   kubernetes.io/ingress.class: kong
username: user
credentials:
- user-generic-secret   # references Kubernetes secret
---
# Consumer for generic key auth
apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
 name: user-api-key-consumer
 annotations:
   kubernetes.io/ingress.class: kong
username: user-key-auth
credentials:
- key-generic-secret    # references Kubernetes secret
---
# Consumer for anonymous user
apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
 name: anonymous-consumer
 annotations:
   kubernetes.io/ingress.class: kong
   konghq.com/plugins: 'request-termination-anonymous'
username: anonymous

Plugins

File plugins.yaml:

# JWT authentication
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: jwt-auth-foobar
plugin: jwt
config:
  anonymous: anonymous    # references a Consumer username
---
# Basic authentication
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: basic-auth-foobar
plugin: basic-auth
config:
  anonymous: anonymous    # references a Consumer username
  hide_credentials: true
---
# Key authentication
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: key-auth-foobar
plugin: key-auth
config:
  key_names:
    - apikey
  anonymous: anonymous    # references a Consumer username
  hide_credentials: true
---
# Request termination: when the authentication fails
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: request-termination-anonymous
plugin: request-termination
config:
  message: "Authentication required"
  status_code: 401

Services

File services.yaml:

# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: foobar
  name: foobar
spec:
  replicas: 1
  selector:
    matchLabels:
      app: foobar
  strategy: {}
  template:
    metadata:
      labels:
        app: foobar
    spec:
      containers:
        - image: mikyll/foobar:latest
          name: foobar
          ports:
            - containerPort: 3000
---
# Service
apiVersion: v1
kind: Service
metadata:
  labels:
    app: foobar-service
  name: foobar-service
spec:
  ports:
    - port: 3000
      name: http
      protocol: TCP
      targetPort: 3000
  selector:
    app: foobar
---
# Route /foobar/test/auth/key
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: foobar-route-test-keyauth
  annotations:
    konghq.com/strip-path: 'true'
    konghq.com/plugins: 'key-auth-foobar'
spec:
  parentRefs:
  - name: kong
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /foobar/test/auth/key
    backendRefs:
    - name: foobar-service
      kind: Service
      port: 3000

---
# Route /foobar/test/auth/basic
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: foobar-route-test-basicauth
  annotations:
    konghq.com/strip-path: 'true'
    konghq.com/plugins: 'basic-auth-foobar'
spec:
  parentRefs:
  - name: kong
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /foobar/test/auth/basic
    backendRefs:
    - name: foobar-service
      kind: Service
      port: 3000

---
# Route /foobar/test/auth/jwt
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: foobar-route-test-jwtauth
  annotations:
    konghq.com/strip-path: 'true'
    konghq.com/plugins: 'jwt-auth-foobar'
spec:
  parentRefs:
  - name: kong
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /foobar/test/auth/jwt
    backendRefs:
    - name: foobar-service
      kind: Service
      port: 3000

Applied with:

cat secrets.yaml | kubectl apply -f -
cat consumers.yaml | kubectl apply -f -
cat plugins.yaml | kubectl apply -f -
cat services.yaml | kubectl apply -f -

Solution

  • The issue was caused by these two consumers:

    # Consumer for User JWT token
    apiVersion: configuration.konghq.com/v1
    kind: KongConsumer
    metadata:
     name: user
     annotations:
       kubernetes.io/ingress.class: kong
    username: user # <-- HERE
    credentials:
    - jwt-user-secret
    ---
    # Consumer for generic basic auth user
    apiVersion: configuration.konghq.com/v1
    kind: KongConsumer
    metadata:
     name: generic-basic-auth-consumer
     annotations:
       kubernetes.io/ingress.class: kong
    username: user # <-- HERE
    credentials:
    - user-generic-secret
    

    The configuration failed because both had the same username "user", and appearently that's not allowed. Therefore, changing one of them solved the issue.

    Solution

    New file consumers.yaml:

    # Consumer for Admin JWT token
    apiVersion: configuration.konghq.com/v1
    kind: KongConsumer
    metadata:
     name: admin
     annotations:
       kubernetes.io/ingress.class: kong
    username: admin
    credentials:
    - jwt-admin-secret      # references Kubernetes secret
    ---
    # Consumer for User JWT token
    apiVersion: configuration.konghq.com/v1
    kind: KongConsumer
    metadata:
     name: user
     annotations:
       kubernetes.io/ingress.class: kong
    username: user
    credentials:
    - jwt-user-secret       # references Kubernetes secret
    ---
    # Consumer for generic basic auth user
    apiVersion: configuration.konghq.com/v1
    kind: KongConsumer
    metadata:
     name: generic-basic-auth-consumer
     annotations:
       kubernetes.io/ingress.class: kong
    username: generic
    credentials:
    - user-generic-secret   # references Kubernetes secret
    ---
    # Consumer for generic key auth
    apiVersion: configuration.konghq.com/v1
    kind: KongConsumer
    metadata:
     name: user-api-key-consumer
     annotations:
       kubernetes.io/ingress.class: kong
    username: user-key-auth
    credentials:
    - key-generic-secret    # references Kubernetes secret
    ---
    # Consumer for anonymous user
    apiVersion: configuration.konghq.com/v1
    kind: KongConsumer
    metadata:
     name: anonymous-consumer
     annotations:
       kubernetes.io/ingress.class: kong
       konghq.com/plugins: 'request-termination-anonymous'
    username: anonymous
    

    Update

    This problem occurs only in DB-less mode, and was added to KIC v3.1.x milestone.

    Related GitHub Issue