diff --git a/api/v1beta1/vmuser_types.go b/api/v1beta1/vmuser_types.go index 1eeefd7b9..2c9cf3910 100644 --- a/api/v1beta1/vmuser_types.go +++ b/api/v1beta1/vmuser_types.go @@ -1,4 +1,4 @@ -package v1beta1 + package v1beta1 import ( "fmt" @@ -150,6 +150,9 @@ type TargetRef struct { // See https://docs.victoriametrics.com/vmauth.html#dropping-request-path-prefix for more details. // +optional DropSrcPathPrefixParts *int `json:"drop_src_path_prefix_parts,omitempty"` + // BasicAuth allow an endpoint to authenticate over basic authentication + // +optional + BasicAuth *BasicAuth `json:"basicAuth,omitempty"` } // VMUserIPFilters defines filters for IP addresses diff --git a/config/crd/bases/operator.victoriametrics.com_vmusers.yaml b/config/crd/bases/operator.victoriametrics.com_vmusers.yaml index c6a1bbf58..627e652a0 100644 --- a/config/crd/bases/operator.victoriametrics.com_vmusers.yaml +++ b/config/crd/bases/operator.victoriametrics.com_vmusers.yaml @@ -162,6 +162,57 @@ spec: crd or static per targetRef. user can define multiple targetRefs with different ref Types. properties: + basicAuth: + description: BasicAuth allow an endpoint to authenticate over + basic authentication + properties: + password: + description: The secret in the service scrape namespace + that contains the password for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + password_file: + description: PasswordFile defines path to password file + at disk + type: string + username: + description: The secret in the service scrape namespace + that contains the username for authentication. It must + be at them same namespace as CRD + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object crd: description: |- CRD describes exist operator's CRD object, diff --git a/controllers/factory/vmuser.go b/controllers/factory/vmuser.go index e564fba9f..261928f0e 100644 --- a/controllers/factory/vmuser.go +++ b/controllers/factory/vmuser.go @@ -3,6 +3,7 @@ package factory import ( "context" "crypto/rand" + "encoding/base64" "fmt" "math/big" "net/url" @@ -60,6 +61,12 @@ func buildVMAuthConfig(ctx context.Context, rclient client.Client, vmauth *victo toUpdate := injectAuthSettings(existSecrets, users) logger.WithContext(ctx).Info("VMAuth reconcile stats", "VMAuth", vmauth.Name, "toUpdate", len(toUpdate), "tocreate", len(toCreateSecrets), "exist", len(existSecrets)) + // inject backend authentication header. + err = injectBackendAuthHeader(ctx, rclient, users) + if err != nil { + return nil, err + } + // generate yaml config for vmauth. cfg, err := generateVMAuthConfig(vmauth, users, crdCache) if err != nil { @@ -134,6 +141,25 @@ func injectSecretValueByRef(src []*victoriametricsv1beta1.VMUser, secretValueCac } } +func injectBackendAuthHeader(ctx context.Context, rclient client.Client, users []*victoriametricsv1beta1.VMUser) error { + for i := range users { + user := users[i] + for j := range user.Spec.TargetRefs { + ref := &user.Spec.TargetRefs[j] + if ref.BasicAuth != nil { + bac, err := loadBasicAuthSecret(ctx, rclient, user.Namespace, ref.BasicAuth) + if err != nil { + return fmt.Errorf("could not load basicAuth config. %w", err) + } + token := bac.username + ":" + bac.password + token64 := base64.StdEncoding.EncodeToString([]byte(token)) + Header := "Authorization: Basic " + token64 + ref.Headers = append(ref.Headers, Header) + } + } + } + return nil +} func injectAuthSettings(src []corev1.Secret, dst []*victoriametricsv1beta1.VMUser) []corev1.Secret { var toUpdate []corev1.Secret if len(src) == 0 || len(dst) == 0 {