-
Notifications
You must be signed in to change notification settings - Fork 3
APIKey secret labels #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
6b6e41e to
9d0a939
Compare
9d0a939 to
d502fcf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Codewise looks good. Just one question regarding the approach for computing the authpolicy.
I have run some verification steps and it's working as expected.
When the authpolicy is missing, the controller successfully creates the secret, without reporting error logs 👍
make kind-create-cluster
make install
make gateway-api-install
make kuadrant-core-install
make local-deploy
kubectl create ns gateway-system
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: gateway-system
spec:
gatewayClassName: istio
listeners:
- name: http
protocol: HTTP
port: 80
hostname: "example.com"
allowedRoutes:
namespaces:
from: All
EOF
kubectl create ns toystore
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-route
namespace: toystore
spec:
hostnames:
- example.com
parentRefs:
- name: my-gateway
namespace: gateway-system
rules:
- matches:
- path:
type: PathPrefix
value: "/"
backendRefs:
- name: toystore
port: 80
EOF
cat <<EOF >route-status-patch.yaml
status:
parents:
- controllerName: istio.io/gateway-controller
conditions:
- lastTransitionTime: "2025-09-03T19:16:16Z"
message: Route was valid
observedGeneration: 1
reason: Accepted
status: "True"
type: Accepted
parentRef:
group: gateway.networking.k8s.io
kind: Gateway
name: my-gateway
namespace: gateway-system
EOF
kubectl patch httproute my-route --type=merge --patch "$(cat route-status-patch.yaml)" --subresource status -n toystore
rm route-status-patch.yaml
kubectl apply -f - <<EOF
apiVersion: kuadrant.io/v1
kind: AuthPolicy
metadata:
name: toystore-auth
namespace: toystore
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: my-route
rules:
authentication:
"api-key-users":
apiKey:
selector:
matchLabels:
app: toystore
credentials:
authorizationHeader:
prefix: APIKEY
EOF
cat <<EOF >authpolicy-status-patch.yaml
status:
conditions:
- lastTransitionTime: "2025-09-03T19:16:16Z"
message: Route was valid
reason: Accepted
status: "True"
type: Accepted
- lastTransitionTime: "2025-09-03T19:16:16Z"
message: Route was valid
reason: Enforced
status: "True"
type: Enforced
EOF
kubectl patch authpolicy toystore-auth --type=merge --patch "$(cat authpolicy-status-patch.yaml)" --subresource status -n toystore
rm authpolicy-status-patch.yaml
kubectl apply -f - <<EOF
apiVersion: devportal.kuadrant.io/v1alpha1
kind: APIProduct
metadata:
name: toystore-api
namespace: toystore
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: my-route
displayName: Toystore API
description: Manage toy inventory
approvalMode: manual
publishStatus: Published
EOF
kubectl apply -f - <<EOF
apiVersion: extensions.kuadrant.io/v1alpha1
kind: PlanPolicy
metadata:
name: toystore-plans
namespace: toystore
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: my-route
plans:
- tier: gold
predicate: |
has(auth.identity) && auth.identity.metadata.annotations["secret.kuadrant.io/plan-id"] == "gold"
limits:
daily: 100
- tier: silver
predicate: |
has(auth.identity) && auth.identity.metadata.annotations["secret.kuadrant.io/plan-id"] == "silver"
limits:
daily: 50
- tier: premium
predicate: |
has(auth.identity) && auth.identity.metadata.annotations["secret.kuadrant.io/plan-id"] == "premium"
limits:
daily: 10
EOF
kubectl apply -f - <<EOF
apiVersion: devportal.kuadrant.io/v1alpha1
kind: APIKey
metadata:
name: my-app-apikey
namespace: toystore
spec:
# Reference to the APIProduct this key is for
apiProductRef:
name: toystore-api
# Plan tier for rate limiting and feature access
planTier: premium
# Use case description for approval review
useCase: Mobile application for pet store management
requestedBy:
userId: user-12345
email: developer@example.com
EOF
kubectl patch apikey my-app-apikey -n toystore --subresource=status --type='merge' -p '{"status":{"phase":"Approved"}}'
eguzki
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good to me.
Just one issue found, but it is based on an edge case: approving an apikey for authpolicy that does not have apikey auth method.
| return v.GetMethod() == v1beta3.ApiKeyAuthentication | ||
| }) | ||
|
|
||
| if apiKeyAuthMethods != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an slice can be not nil and empty!
Tried with an authpolicy only with jwt auth method, and when creating a apikey and approving it, the controller panic'ed
026-01-19T17:44:16Z ERROR Observed a panic {"controller": "apikey", "controllerGroup": "devportal.kuadrant.io", "controllerKind": "APIKey", "APIKey": {"name":"my-app-apikey","namespace":"toystore"}, "namespace": "toystore", "name": "my-app-apikey", "reconcileID": "6ff38d4c-a37d-484f-9ae8-e0c29efd7623", "panic": "runtime error: index out of range [0] with length 0", "panicGoValue": "runtime.boundsError{x:0, y:0, signed:true, code:0x0}", "stacktrace": "goroutine 299 [running]:\nk8s.io/apimachinery/pkg/util/runtime.logPanic({0x2543448, 0xc000526a20}, {0x2059200, 0xc000ba20c0})\n\t/go/pkg/mod/k8s.io/apimachinery@v0.33.3/pkg/util/runtime/runtime.go:132 +0xbc\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Reconcile.func1()\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.21.0/pkg/internal/controller/controller.go:108 +0x112\npanic({0x2059200?, 0xc000ba20c0?})\n\t/usr/local/go/src/runtime/panic.go:792 +0x132\ngithub.com/kuadrant/developer-portal-controller/internal/controller.getAPIKeyAuthScheme(0xc000526bd0)\n\t/workspace/internal/controller/apikey_controller.go:293 +0x33d\ngithub.com/kuadrant/developer-portal-controller/internal/controller.(*APIKeyReconciler).reconcileApproved(0xc000791560, {0x2543448, 0xc000526a20}, 0xc000f00700)\n\t/workspace/internal/controller/apikey_controller.go:225 +0x185\ngithub.com/kuadrant/developer-portal-controller/internal/controller.(*APIKeyReconciler).Reconcile(0xc000791560, {0x2543448, 0xc000526a20}, {{{0xc000b981d8?, 0x21d3593?}, {0xc000b981e0?, 0x100?}}})\n\t/workspace/internal/controller/apikey_controller.go:100 +0x21e\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Reconcile(0xc000526990?, {0x2543448?, 0xc000526a20?}, {{{0xc000b981d8?, 0x0?}, {0xc000b981e0?, 0x0?}}})\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.21.0/pkg/internal/controller/controller.go:119 +0xbf\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).reconcileHandler(0x256cb80, {0x2543480, 0xc000532dc0}, {{{0xc000b981d8, 0x8}, {0xc000b981e0, 0xd}}}, 0x0)\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.21.0/pkg/internal/controller/controller.go:340 +0x3ad\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).processNextWorkItem(0x256cb80, {0x2543480, 0xc000532dc0})\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.21.0/pkg/internal/controller/controller.go:300 +0x21b\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Start.func2.1()\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.21.0/pkg/internal/controller/controller.go:202 +0x85\ncreated by sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Start.func2 in goroutine 88\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.21.0/pkg/internal/controller/controller.go:198 +0x28f\n"}
k8s.io/apimachinery/pkg/util/runtime.logPanic
/go/pkg/mod/k8s.io/apimachinery@v0.33.3/pkg/util/runtime/runtime.go:142
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Reconcile.func1
/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.21.0/pkg/internal/controller/controller.go:108
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oopsie! that true, better to check the length
Signed-off-by: dd <4183971+didierofrivia@users.noreply.github.com>
Signed-off-by: dd <4183971+didierofrivia@users.noreply.github.com>
Signed-off-by: dd <4183971+didierofrivia@users.noreply.github.com>
Signed-off-by: dd <4183971+didierofrivia@users.noreply.github.com>
Signed-off-by: dd <4183971+didierofrivia@users.noreply.github.com>
Signed-off-by: dd di cesare <4183971+didierofrivia@users.noreply.github.com> Signed-off-by: dd <4183971+didierofrivia@users.noreply.github.com>
Signed-off-by: dd <4183971+didierofrivia@users.noreply.github.com>
046d73a to
a145e0e
Compare
Closes #14
This PR makes the Developer Portal APIKey controller to automatically propagate
AuthPolicyAPIKeyselector labels to the generatedSecrets. This enables Authorino to correctly identify and validate API keys (Secrets) based on the labels defined in theAuthPolicy's authentication scheme. It also corrects the label key from app to use the constantapiKeySecretLabelDevPortalKey(devportal.kuadrant.io/apiproduct). Besides, it updates its resource Status displaying the associated information for the APIKey auth method and credential location