Skip to content
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

Add backend authentication for targetRefs on vmusers by secret #714

Merged
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
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 @@
import (
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"math/big"
"net/url"
Expand Down Expand Up @@ -61,6 +62,12 @@
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 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 @@
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
Loading