Skip to content
Closed
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ 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**: Add a specific timeout configuration parameter for the Datadog trigger ([#6999](https://github.com/kedacore/keda/pull/6999))
- **Datadog Scaler**: Fix bug with datadogNamespace config ([#6828](https://github.com/kedacore/keda/pull/6828))
- **Datadog Scaler**: Improve Datadog scaler error messages ([#6999](https://github.com/kedacore/keda/pull/6999))
- **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