Skip to content

Commit

Permalink
Add backend authentication for targetRefs on vmusers by secret adapt …
Browse files Browse the repository at this point in the history
…vmauth config generation (#714)

backend basic authentication support on vmuser to add them as header on vmauth configuration it will satisfy the basicauth authorization for bellow issue
#669

* add docs

* add test
  • Loading branch information
mohammadkhavari authored Apr 17, 2024
1 parent 162993c commit 99fbc98
Show file tree
Hide file tree
Showing 6 changed files with 1,802 additions and 1,592 deletions.
15 changes: 15 additions & 0 deletions api/v1beta1/vmuser_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
// TargetRefBasicAuth allow an target endpoint to authenticate over basic authentication
// +optional
TargetRefBasicAuth *TargetRefBasicAuth `json:"targetRefBasicAuth,omitempty"`
}

// VMUserIPFilters defines filters for IP addresses
Expand Down Expand Up @@ -191,6 +194,18 @@ type StaticRef struct {
URLs []string `json:"urls,omitempty"`
}

// TargetRefBasicAuth target basic authentication
type TargetRefBasicAuth struct {
// The secret in the service scrape namespace that contains the username
// for authentication.
// It must be at them same namespace as CRD
Username v1.SecretKeySelector `json:"username"`
// The secret in the service scrape namespace that contains the password
// for authentication.
// It must be at them same namespace as CRD
Password v1.SecretKeySelector `json:"password"`
}

// VMUserStatus defines the observed state of VMUser
type VMUserStatus struct{}

Expand Down
22 changes: 22 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 56 additions & 0 deletions config/crd/bases/operator.victoriametrics.com_vmusers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,62 @@ spec:
It allows to hide tenant configuration from user with crd as ref.
it also may contain any url encoded params.
type: string
targetRefBasicAuth:
description: TargetRefBasicAuth allow an target 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
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
required:
- password
- username
type: object
type: object
type: array
tls_insecure_skip_verify:
Expand Down
26 changes: 26 additions & 0 deletions controllers/factory/vmauth/vmusers_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package vmauth
import (
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"math/big"
"net/url"
Expand Down Expand Up @@ -61,6 +62,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 {
Expand Down Expand Up @@ -135,6 +142,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.TargetRefBasicAuth != nil {
bac, err := loadBasicAuthSecret(ctx, rclient, user.Namespace, &victoriametricsv1beta1.BasicAuth{Username: ref.TargetRefBasicAuth.Username, Password: ref.TargetRefBasicAuth.Password})

Check failure on line 151 in controllers/factory/vmauth/vmusers_config.go

View workflow job for this annotation

GitHub Actions / test and build

undefined: loadBasicAuthSecret) (typecheck)

Check failure on line 151 in controllers/factory/vmauth/vmusers_config.go

View workflow job for this annotation

GitHub Actions / test and build

undefined: loadBasicAuthSecret
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 {
Expand Down
107 changes: 106 additions & 1 deletion controllers/factory/vmauth/vmusers_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,112 @@ func Test_buildVMAuthConfig(t *testing.T) {
bearer_token: bearer-token-2
`,
},

{
name: "with targetRef basicauth secret refs and headers",
args: args{
vmauth: &v1beta1.VMAuth{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vmauth",
Namespace: "default",
},
Spec: v1beta1.VMAuthSpec{SelectAllByDefault: true},
},
},
predefinedObjects: []runtime.Object{
&v1beta1.VMUser{
ObjectMeta: metav1.ObjectMeta{
Name: "user-1",
Namespace: "default",
},
Spec: v1beta1.VMUserSpec{
Name: pointer.String("user-1"),

Check failure on line 681 in controllers/factory/vmauth/vmusers_config_test.go

View workflow job for this annotation

GitHub Actions / test and build

undefined: pointer
UserName: pointer.String("some-user"),

Check failure on line 682 in controllers/factory/vmauth/vmusers_config_test.go

View workflow job for this annotation

GitHub Actions / test and build

undefined: pointer
PasswordRef: &v1.SecretKeySelector{
Key: "password",
LocalObjectReference: v1.LocalObjectReference{
Name: "generated-secret",
},
},
TargetRefs: []v1beta1.TargetRef{
{
Static: &v1beta1.StaticRef{URL: "http://some-static"},
Paths: []string{"/"},
Headers: []string{"baz: bar"},
TargetRefBasicAuth: &v1beta1.TargetRefBasicAuth{
Username: v1.SecretKeySelector{
Key: "username",
LocalObjectReference: v1.LocalObjectReference{
Name: "backend-auth-secret",
},
},
Password: v1.SecretKeySelector{
Key: "password",
LocalObjectReference: v1.LocalObjectReference{
Name: "backend-auth-secret",
},
},
},
},
},
},
},
&v1beta1.VMUser{
ObjectMeta: metav1.ObjectMeta{
Name: "user-15",
Namespace: "monitoring",
},
Spec: v1beta1.VMUserSpec{
Name: pointer.String("user-15"),

Check failure on line 718 in controllers/factory/vmauth/vmusers_config_test.go

View workflow job for this annotation

GitHub Actions / test and build

undefined: pointer
BearerToken: pointer.String("bearer-token-10"),

Check failure on line 719 in controllers/factory/vmauth/vmusers_config_test.go

View workflow job for this annotation

GitHub Actions / test and build

undefined: pointer (typecheck)
TargetRefs: []v1beta1.TargetRef{
{
Static: nil,
CRD: &v1beta1.CRDRef{
Kind: "VMAgent",
Name: "test",
Namespace: "default",
},
Paths: []string{"/"},
},
},
},
},
&v1beta1.VMAgent{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
},
&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "generated-secret",
Namespace: "default",
},
Data: map[string][]byte{"password": []byte(`generated-password`), "token": []byte(`some-bearer-token`)},
},
&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "backend-auth-secret",
Namespace: "default",
},
Data: map[string][]byte{"password": []byte(`pass`), "username": []byte(`user`)},
},
},
want: `users:
- url_prefix:
- http://some-static
headers:
- 'baz: bar'
- 'Authorization: Basic dXNlcjpwYXNz'
name: user-1
username: some-user
password: generated-password
- url_prefix:
- http://vmagent-test.default.svc:8429
name: user-15
bearer_token: bearer-token-10
`,
},
{
name: "with secret refs",
args: args{
Expand Down
Loading

0 comments on commit 99fbc98

Please sign in to comment.