| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- /*
- Copyright 2026 LocoStack.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package reconciler
- import (
- "context"
- "fmt"
- "github.com/LocoStack/loco-operator/api/v1alpha1"
- corev1 "k8s.io/api/core/v1"
- apierrors "k8s.io/apimachinery/pkg/api/errors"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/runtime"
- "k8s.io/apimachinery/pkg/types"
- "sigs.k8s.io/controller-runtime/pkg/client"
- logf "sigs.k8s.io/controller-runtime/pkg/log"
- )
- // reconcileCredentials checks that all referenced Secrets exist and contain the
- // required keys. Returns true when all credentials are resolved.
- func ReconcileCredentials(ctx context.Context, c client.Client, scheme *runtime.Scheme, authSpec *v1alpha1.AuthSpec, obj client.Object) (*metav1.Condition, error) {
- log := logf.FromContext(ctx)
- if authSpec == nil {
- return &metav1.Condition{
- Type: "CredentialsResolved",
- Status: metav1.ConditionTrue,
- Reason: "NoCredentialsRequired",
- Message: "No auth configured",
- ObservedGeneration: obj.GetGeneration(),
- }, nil
- }
- secretRefs := make([]*corev1.SecretKeySelector, 0)
- if authSpec.APIKey != nil {
- secretRefs = append(secretRefs, &authSpec.APIKey.SecretRef)
- }
- if authSpec.BearerToken != nil {
- secretRefs = append(secretRefs, authSpec.BearerToken)
- }
- for _, hdr := range authSpec.Headers {
- if hdr.ValueFrom.SecretKeyRef != nil {
- secretRefs = append(secretRefs, hdr.ValueFrom.SecretKeyRef)
- }
- }
- for _, ref := range secretRefs {
- if reason, msg, err := checkSecretKey(ctx, c, obj.GetNamespace(), ref.Name, ref.Key); err != nil {
- log.Error(err, "Failed to check API key secret", "namespace", obj.GetNamespace(), "name", obj.GetName(), "secretName", ref.Name, "secretKey", ref.Key)
- return nil, err
- } else {
- if reason != "" {
- return &metav1.Condition{
- Type: "CredentialsResolved",
- Status: metav1.ConditionTrue,
- Reason: reason,
- Message: msg,
- }, nil
- }
- }
- }
- return &metav1.Condition{
- Type: "CredentialsResolved",
- Status: metav1.ConditionTrue,
- Reason: "CredentialsFound",
- Message: "All referenced secrets exist and contain the required keys",
- }, nil
- }
- // checkSecretKey verifies that a Secret exists and contains the given key.
- func checkSecretKey(ctx context.Context, c client.Client, namespace, secretName, key string) (string, string, error) {
- secret := &corev1.Secret{}
- if err := c.Get(ctx, types.NamespacedName{Name: secretName, Namespace: namespace}, secret); err != nil {
- if apierrors.IsNotFound(err) {
- return "SecretNotFound", fmt.Sprintf("Secret %q not found", secretName), nil
- }
- return "", "", err
- }
- if _, ok := secret.Data[key]; !ok {
- return "SecretKeyMissing", fmt.Sprintf("Secret %q does not contain key %q", secretName, key), nil
- }
- return "", "", nil
- }
|