Skip to content
Closed
Show file tree
Hide file tree
Changes from 9 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ To learn more about active deprecations, we recommend checking [GitHub Discussio

- **General**: Allow excluding labels from being propagated from ScaledObject and ScaledJob to generated HPA and Job objects ([#6849](https://github.com/kedacore/keda/issues/6849))
- **General**: Improve Events emitted from ScaledObject controller ([#6802](https://github.com/kedacore/keda/issues/6802))
- **General**: Support token store in secret and fallback to current token string ([#6026](https://github.com/kedacore/keda/issues/6026))
- **Datadog Scaler**: Fix bug with datadogNamespace config ([#6828](https://github.com/kedacore/keda/pull/6828))
- **Metrics API**: Support multiple auth methods simultaneously in Metrics API scaler ([#6642](https://github.com/kedacore/keda/issues/6642))
- **Temporal Scaler**: Support custom tlsServerName ([#6820](https://github.com/kedacore/keda/pull/6820))
Expand Down
4 changes: 4 additions & 0 deletions apis/keda/v1alpha1/triggerauthentication_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,12 @@ type HashiCorpVault struct {
// Credential defines the Hashicorp Vault credentials depending on the authentication method
type Credential struct {
// +optional
// +kubebuilder:deprecated:warning="field `token` is deprecated and might be removed in further versions, use `tokenSecretRef` field instead"
Token string `json:"token,omitempty"`

// +optional
TokenSecretRef *SecretKeyRef `json:"tokenSecretRef,omitempty"`

// +optional
ServiceAccount string `json:"serviceAccount,omitempty"`
}
Expand Down
10 changes: 10 additions & 0 deletions config/crd/bases/keda.sh_clustertriggerauthentications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,16 @@ spec:
type: string
token:
type: string
tokenSecretRef:
properties:
key:
type: string
name:
type: string
required:
- key
- name
type: object
type: object
mount:
type: string
Expand Down
10 changes: 10 additions & 0 deletions config/crd/bases/keda.sh_triggerauthentications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,16 @@ spec:
type: string
token:
type: string
tokenSecretRef:
properties:
key:
type: string
name:
type: string
required:
- key
- name
type: object
type: object
mount:
type: string
Expand Down
57 changes: 39 additions & 18 deletions pkg/scaling/resolver/hashicorpvault_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package resolver

import (
"context"
"encoding/json"
"errors"
"fmt"
Expand All @@ -25,26 +26,36 @@ import (

"github.com/go-logr/logr"
vaultapi "github.com/hashicorp/vault/api"
corev1listers "k8s.io/client-go/listers/core/v1"
k8sClient "sigs.k8s.io/controller-runtime/pkg/client"

kedav1alpha1 "github.com/kedacore/keda/v2/apis/keda/v1alpha1"
)

// HashicorpVaultHandler is specification of Hashi Corp Vault
type HashicorpVaultHandler struct {
vault *kedav1alpha1.HashiCorpVault
client *vaultapi.Client
stopCh chan struct{}
vault *kedav1alpha1.HashiCorpVault
client *vaultapi.Client
k8sClient k8sClient.Client
stopCh chan struct{}
ctx context.Context
logger *logr.Logger
secretsLister corev1listers.SecretLister
}

// NewHashicorpVaultHandler creates a HashicorpVaultHandler object
func NewHashicorpVaultHandler(v *kedav1alpha1.HashiCorpVault) *HashicorpVaultHandler {
func NewHashicorpVaultHandler(ctx context.Context, client k8sClient.Client, v *kedav1alpha1.HashiCorpVault, logger *logr.Logger, secretListener corev1listers.SecretLister) *HashicorpVaultHandler {
return &HashicorpVaultHandler{
vault: v,
vault: v,
ctx: ctx,
logger: logger,
secretsLister: secretListener,
k8sClient: client,
}
}

// Initialize the Vault client
func (vh *HashicorpVaultHandler) Initialize(logger logr.Logger) error {
func (vh *HashicorpVaultHandler) Initialize() error {
config := vaultapi.DefaultConfig()
client, err := vaultapi.NewClient(config)
if err != nil {
Expand Down Expand Up @@ -77,7 +88,7 @@ func (vh *HashicorpVaultHandler) Initialize(logger logr.Logger) error {

if renew, ok := lookup.Data["renewable"].(bool); ok && renew {
vh.stopCh = make(chan struct{})
go vh.renewToken(logger)
go vh.renewToken()
}

vh.client = client
Expand All @@ -92,14 +103,24 @@ func (vh *HashicorpVaultHandler) token(client *vaultapi.Client) (string, error)
switch vh.vault.Authentication {
case kedav1alpha1.VaultAuthenticationToken:
// Got token from VAULT_TOKEN env variable
switch {
case len(client.Token()) > 0:
break
case len(vh.vault.Credential.Token) > 0:
token = vh.vault.Credential.Token
default:
return token, errors.New("could not get Vault token")
if len(client.Token()) > 0 {
return "", nil
}

// consume token from k8s secret
if vh.vault.Credential.TokenSecretRef != nil && vh.vault.Credential.TokenSecretRef.Name != "" && vh.vault.Credential.TokenSecretRef.Key != "" {
token = resolveAuthSecret(vh.ctx, vh.k8sClient, *vh.logger, vh.vault.Credential.TokenSecretRef.Name, vh.vault.Namespace, vh.vault.Credential.TokenSecretRef.Key, vh.secretsLister)
if token != "" {
return token, nil
}
}

// if the token is not set in the secret will fallback to the previews approach
if len(vh.vault.Credential.Token) > 0 {
return vh.vault.Credential.Token, nil
}
return token, errors.New("could not get Vault token")

case kedav1alpha1.VaultAuthenticationKubernetes:
if len(vh.vault.Mount) == 0 {
return token, errors.New("auth mount not in config")
Expand Down Expand Up @@ -141,10 +162,10 @@ func (vh *HashicorpVaultHandler) token(client *vaultapi.Client) (string, error)
}

// renewToken takes charge of renewing the vault token
func (vh *HashicorpVaultHandler) renewToken(logger logr.Logger) {
func (vh *HashicorpVaultHandler) renewToken() {
secret, err := vh.client.Auth().Token().RenewSelf(0)
if err != nil {
logger.Error(err, "Vault renew token: failed to create the payload")
vh.logger.Error(err, "Vault renew token: failed to create the payload")
}

renewer, err := vh.client.NewLifetimeWatcher(&vaultapi.RenewerInput{
Expand All @@ -153,7 +174,7 @@ func (vh *HashicorpVaultHandler) renewToken(logger logr.Logger) {
//Increment: 60,
})
if err != nil {
logger.Error(err, "Vault renew token: cannot create the renewer")
vh.logger.Error(err, "Vault renew token: cannot create the renewer")
}

go renewer.Renew()
Expand All @@ -169,7 +190,7 @@ RenewWatcherLoop:
break RenewWatcherLoop
case err := <-renewer.DoneCh():
if err != nil {
logger.Error(err, "error renewing token")
vh.logger.Error(err, "error renewing token")
}
break RenewWatcherLoop
}
Expand Down
Loading
Loading