Skip to content

feat: support secret for consumer.credential #82

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

Merged
merged 1 commit into from
Apr 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion internal/controller/consumer_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,37 @@ func (r *ConsumerReconciler) SetupWithManager(mgr ctrl.Manager) error {
},
),
).
Watches(&corev1.Secret{},
handler.EnqueueRequestsFromMapFunc(r.listConsumersForSecret),
).
Complete(r)
}

func (r *ConsumerReconciler) listConsumersForSecret(ctx context.Context, obj client.Object) []reconcile.Request {
secret, ok := obj.(*corev1.Secret)
if !ok {
r.Log.Error(nil, "failed to convert to Secret", "object", obj)
return nil
}
consumerList := &v1alpha1.ConsumerList{}
if err := r.List(ctx, consumerList, client.MatchingFields{
indexer.SecretIndexRef: indexer.GenIndexKey(secret.GetNamespace(), secret.GetName()),
}); err != nil {
r.Log.Error(err, "failed to list consumers")
return nil
}
requests := make([]reconcile.Request, 0, len(consumerList.Items))
for _, consumer := range consumerList.Items {
requests = append(requests, reconcile.Request{
NamespacedName: client.ObjectKey{
Name: consumer.Name,
Namespace: consumer.Namespace,
},
})
}
return requests
}

func (r *ConsumerReconciler) listConsumersForGateway(ctx context.Context, obj client.Object) []reconcile.Request {
gateway, ok := obj.(*gatewayv1.Gateway)
if !ok {
Expand All @@ -70,7 +98,7 @@ func (r *ConsumerReconciler) listConsumersForGateway(ctx context.Context, obj cl
}
consumerList := &v1alpha1.ConsumerList{}
if err := r.List(ctx, consumerList, client.MatchingFields{
indexer.ConsumerGatewayRef: indexer.GenIndexKey(gateway.Name, gateway.GetNamespace()),
indexer.ConsumerGatewayRef: indexer.GenIndexKey(gateway.GetNamespace(), gateway.GetName()),
}); err != nil {
r.Log.Error(err, "failed to list consumers")
return nil
Expand Down
27 changes: 27 additions & 0 deletions internal/controller/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,35 @@ func setupConsumerIndexer(mgr ctrl.Manager) error {
); err != nil {
return err
}
if err := mgr.GetFieldIndexer().IndexField(
context.Background(),
&v1alpha1.Consumer{},
SecretIndexRef,
ConsumerSecretIndexFunc,
); err != nil {
return err
}
return nil
}

func ConsumerSecretIndexFunc(rawObj client.Object) []string {
consumer := rawObj.(*v1alpha1.Consumer)
secretKeys := make([]string, 0)

for _, credential := range consumer.Spec.Credentials {
if credential.SecretRef == nil {
continue
}
ns := consumer.GetNamespace()
if credential.SecretRef.Namespace != nil {
ns = *credential.SecretRef.Namespace
}
key := GenIndexKey(ns, credential.SecretRef.Name)
secretKeys = append(secretKeys, key)
}
return secretKeys
}

func ConsumerGatewayRefIndexFunc(rawObj client.Object) []string {
consumer := rawObj.(*v1alpha1.Consumer)

Expand Down
2 changes: 1 addition & 1 deletion internal/provider/adc/translator/consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (t *Translator) TranslateConsumerV1alpha1(tctx *provider.TranslateContext,
}
authConfig := make(map[string]any)
for k, v := range secret.Data {
authConfig[k] = v
authConfig[k] = string(v)
}
credential.Config = authConfig
} else {
Expand Down
163 changes: 78 additions & 85 deletions test/e2e/crds/consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,73 +109,97 @@ spec:
s.ResourceApplied("httproute", "httpbin", defaultHTTPRoute, 1)
}

Context("Consumer plugins", func() {
var keyAuthConsumer = `apiVersion: gateway.apisix.io/v1alpha1
Context("Credential", func() {
var defaultCredential = `apiVersion: gateway.apisix.io/v1alpha1
kind: Consumer
metadata:
name: consumer-sample
spec:
gatewayRef:
name: api7ee
plugins:
- name: key-auth
credentials:
- type: basic-auth
name: basic-auth-sample
config:
username: sample-user
password: sample-password
- type: key-auth
name: key-auth-sample
config:
key: sample-key
- type: key-auth
name: key-auth-sample2
config:
key: sample-key2
`
var basicAuthConsumer = `apiVersion: gateway.apisix.io/v1alpha1
var updateCredential = `apiVersion: gateway.apisix.io/v1alpha1
kind: Consumer
metadata:
name: consumer-sample
spec:
gatewayRef:
name: api7ee
plugins:
- name: basic-auth
credentials:
- type: basic-auth
name: basic-auth-sample
config:
username: sample-user
password: sample-password
plugins:
- name: key-auth
config:
key: consumer-key
`

BeforeEach(beforeEachHTTP)

It("key-auth", func() {
s.ResourceApplied("Consumer", "consumer-sample", keyAuthConsumer, 1)
It("Create/Update/Delete", func() {
s.ResourceApplied("Consumer", "consumer-sample", defaultCredential, 1)

s.NewAPISIXClient().
GET("/get").
WithHeader("apikey", "sample-key").
WithHost("httpbin.org").
Expect().
Status(401)
Status(200)

s.NewAPISIXClient().
GET("/get").
WithHeader("apikey", "sample-key").
WithHeader("apikey", "sample-key2").
WithHost("httpbin.org").
Expect().
Status(200)

By("delete Consumer")
err := s.DeleteResourceFromString(keyAuthConsumer)
Expect(err).NotTo(HaveOccurred(), "deleting Consumer")
time.Sleep(5 * time.Second)
s.NewAPISIXClient().
GET("/get").
WithBasicAuth("sample-user", "sample-password").
WithHost("httpbin.org").
Expect().
Status(200)

By("update Consumer")
s.ResourceApplied("Consumer", "consumer-sample", updateCredential, 2)

s.NewAPISIXClient().
GET("/get").
WithHeader("apikey", "sample-key").
WithHost("httpbin.org").
Expect().
Status(401)
})

It("basic-auth", func() {
s.ResourceApplied("Consumer", "consumer-sample", basicAuthConsumer, 1)

s.NewAPISIXClient().
GET("/get").
WithHeader("apikey", "sample-key2").
WithHost("httpbin.org").
Expect().
Status(401)

s.NewAPISIXClient().
GET("/get").
WithHeader("apikey", "consumer-key").
WithHost("httpbin.org").
Expect().
Status(200)

s.NewAPISIXClient().
GET("/get").
WithBasicAuth("sample-user", "sample-password").
Expand All @@ -184,7 +208,7 @@ spec:
Status(200)

By("delete Consumer")
err := s.DeleteResourceFromString(basicAuthConsumer)
err := s.DeleteResourceFromString(updateCredential)
Expect(err).NotTo(HaveOccurred(), "deleting Consumer")
time.Sleep(5 * time.Second)

Expand All @@ -197,8 +221,26 @@ spec:
})
})

Context("Credential", func() {
var defaultCredential = `apiVersion: gateway.apisix.io/v1alpha1
Context("SecretRef", func() {
var keyAuthSecret = `
apiVersion: v1
kind: Secret
metadata:
name: key-auth-secret
data:
key: c2FtcGxlLWtleQ==
`
var basicAuthSecret = `
apiVersion: v1
kind: Secret
metadata:
name: basic-auth-secret
data:
username: c2FtcGxlLXVzZXI=
password: c2FtcGxlLXBhc3N3b3Jk
`
var defaultConsumer = `
apiVersion: gateway.apisix.io/v1alpha1
kind: Consumer
metadata:
name: consumer-sample
Expand All @@ -208,40 +250,25 @@ spec:
credentials:
- type: basic-auth
name: basic-auth-sample
config:
username: sample-user
password: sample-password
secretRef:
name: basic-auth-secret
- type: key-auth
name: key-auth-sample
config:
key: sample-key
secretRef:
name: key-auth-secret
- type: key-auth
name: key-auth-sample2
config:
key: sample-key2
`
var updateCredential = `apiVersion: gateway.apisix.io/v1alpha1
kind: Consumer
metadata:
name: consumer-sample
spec:
gatewayRef:
name: api7ee
credentials:
- type: basic-auth
name: basic-auth-sample
config:
username: sample-user
password: sample-password
plugins:
- name: key-auth
config:
key: consumer-key
`
BeforeEach(beforeEachHTTP)

It("Create/Update/Delete", func() {
s.ResourceApplied("Consumer", "consumer-sample", defaultCredential, 1)
err := s.CreateResourceFromString(keyAuthSecret)
Expect(err).NotTo(HaveOccurred(), "creating key-auth secret")
err = s.CreateResourceFromString(basicAuthSecret)
Expect(err).NotTo(HaveOccurred(), "creating basic-auth secret")
s.ResourceApplied("Consumer", "consumer-sample", defaultConsumer, 1)

s.NewAPISIXClient().
GET("/get").
Expand All @@ -250,22 +277,17 @@ spec:
Expect().
Status(200)

s.NewAPISIXClient().
GET("/get").
WithHeader("apikey", "sample-key2").
WithHost("httpbin.org").
Expect().
Status(200)

s.NewAPISIXClient().
GET("/get").
WithBasicAuth("sample-user", "sample-password").
WithHost("httpbin.org").
Expect().
Status(200)

By("update Consumer")
s.ResourceApplied("Consumer", "consumer-sample", updateCredential, 2)
By("delete consumer")
err = s.DeleteResourceFromString(defaultConsumer)
Expect(err).NotTo(HaveOccurred(), "deleting consumer")
time.Sleep(5 * time.Second)

s.NewAPISIXClient().
GET("/get").
Expand All @@ -274,32 +296,6 @@ spec:
Expect().
Status(401)

s.NewAPISIXClient().
GET("/get").
WithHeader("apikey", "sample-key2").
WithHost("httpbin.org").
Expect().
Status(401)

s.NewAPISIXClient().
GET("/get").
WithHeader("apikey", "consumer-key").
WithHost("httpbin.org").
Expect().
Status(200)

s.NewAPISIXClient().
GET("/get").
WithBasicAuth("sample-user", "sample-password").
WithHost("httpbin.org").
Expect().
Status(200)

By("delete Consumer")
err := s.DeleteResourceFromString(updateCredential)
Expect(err).NotTo(HaveOccurred(), "deleting Consumer")
time.Sleep(5 * time.Second)

s.NewAPISIXClient().
GET("/get").
WithBasicAuth("sample-user", "sample-password").
Expand All @@ -308,7 +304,4 @@ spec:
Status(401)
})
})

PContext("SecretRef", func() {
})
})
1 change: 0 additions & 1 deletion test/e2e/scaffold/scaffold.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,6 @@ func (s *Scaffold) GetDeploymentLogs(name string) string {
Resource("pods").
Namespace(s.namespace).
Name(pod.Name).SubResource("log").
Param("container", name).
Do(context.TODO()).
Raw()
if err == nil {
Expand Down
Loading