Skip to content
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
85 changes: 12 additions & 73 deletions pkg/agent/config.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package agent

import (
"errors"
"fmt"
"io"
"net/url"
Expand Down Expand Up @@ -62,9 +61,6 @@ type Config struct {
ExcludeAnnotationKeysRegex []string `yaml:"exclude-annotation-keys-regex"`
// Skips label keys that match the given set of regular expressions.
ExcludeLabelKeysRegex []string `yaml:"exclude-label-keys-regex"`

// MachineHub holds config specific to MachineHub mode.
MachineHub MachineHubConfig `yaml:"machineHub"`
}

type Endpoint struct {
Expand Down Expand Up @@ -92,33 +88,6 @@ type VenafiCloudConfig struct {
UploadPath string `yaml:"upload_path,omitempty"`
}

// MachineHubConfig holds configuration values specific to the CyberArk Machine Hub integration
type MachineHubConfig struct {
// Subdomain is the subdomain indicating where data should be pushed. Used
// for querying the Service Discovery Service to discover the Identity API
// URL.
Subdomain string `yaml:"subdomain"`

// CredentialsSecretName is the name of a Kubernetes Secret in the same
// namespace as the agent, which will be watched for a username and password
// to send to CyberArk Identity for authentication.
CredentialsSecretName string `yaml:"credentialsSecretName"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, not sure why we went with loading the credentials from a Kubernetes secret.

}

func (mhc MachineHubConfig) Validate() error {
var errs []error

if mhc.Subdomain == "" {
errs = append(errs, fmt.Errorf("subdomain must not be empty in MachineHub mode"))
}

if mhc.CredentialsSecretName == "" {
errs = append(errs, fmt.Errorf("credentialsSecretName must not be empty in MachineHub mode"))
}

return errors.Join(errs...)
}

type AgentCmdFlags struct {
// ConfigFilePath (--config-file, -c) is the path to the agent configuration
// YAML file.
Expand Down Expand Up @@ -364,10 +333,6 @@ const (
JetstackSecureAPIToken TLSPKMode = "Jetstack Secure API Token"
VenafiCloudKeypair TLSPKMode = "Venafi Cloud Key Pair Service Account"
VenafiCloudVenafiConnection TLSPKMode = "Venafi Cloud VenafiConnection"

// It is possible to push to both MachineHub and TLSPK. With this mode, the
// agent will only push to MachineHub and not to TLSPK.
Off TLSPKMode = "MachineHub only"
)

// The command-line flags and the config file are combined into this struct by
Expand Down Expand Up @@ -408,11 +373,6 @@ type CombinedConfig struct {
// Only used for testing purposes.
OutputPath string
InputPath string

// MachineHub-related settings.
MachineHubMode bool
MachineHubSubdomain string
MachineHubCredentialsSecretName string
}

// ValidateAndCombineConfig combines and validates the input configuration with
Expand All @@ -427,19 +387,6 @@ type CombinedConfig struct {
func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags) (CombinedConfig, client.Client, error) {
res := CombinedConfig{}

if flags.MachineHubMode {
if err := cfg.MachineHub.Validate(); err != nil {
return CombinedConfig{}, nil, fmt.Errorf("invalid MachineHub config provided: %w", err)
}

res.MachineHubMode = true
res.MachineHubSubdomain = cfg.MachineHub.Subdomain
res.MachineHubCredentialsSecretName = cfg.MachineHub.CredentialsSecretName

keysAndValues := []any{"credentialsSecretName", res.MachineHubCredentialsSecretName}
log.V(logs.Info).Info("Will push to CyberArk MachineHub using a username and password loaded from a Kubernetes Secret", keysAndValues...)
}

{
var (
mode TLSPKMode
Expand Down Expand Up @@ -473,31 +420,23 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
mode = JetstackSecureOAuth
reason = "--credentials-file was specified without --venafi-cloud"
default:
if !flags.MachineHubMode {
return CombinedConfig{}, nil, fmt.Errorf("no TLSPK mode specified and MachineHub mode is disabled. You must either enable the MachineHub mode (using --machine-hub), or enable one of the TLSPK modes.\n" +
"To enable one of the TLSPK modes, you can:\n" +
" - Use (--venafi-cloud with --credentials-file) or (--client-id with --private-key-path) to use the " + string(VenafiCloudKeypair) + " mode.\n" +
" - Use --venafi-connection for the " + string(VenafiCloudVenafiConnection) + " mode.\n" +
" - Use --credentials-file alone if you want to use the " + string(JetstackSecureOAuth) + " mode.\n" +
" - Use --api-token if you want to use the " + string(JetstackSecureAPIToken) + " mode.\n" +
"Note that it is possible to use one of the TLSPK modes along with the MachineHub mode (--machine-hub).")
}

mode = Off
return CombinedConfig{}, nil, fmt.Errorf("no TLSPK mode specified. " +
"To enable one of the TLSPK modes, you can:\n" +
" - Use (--venafi-cloud with --credentials-file) or (--client-id with --private-key-path) to use the " + string(VenafiCloudKeypair) + " mode.\n" +
" - Use --venafi-connection for the " + string(VenafiCloudVenafiConnection) + " mode.\n" +
" - Use --credentials-file alone if you want to use the " + string(JetstackSecureOAuth) + " mode.\n" +
" - Use --api-token if you want to use the " + string(JetstackSecureAPIToken) + " mode.")
}

keysAndValues = append(keysAndValues, "mode", mode, "reason", reason)
if mode != Off {
log.V(logs.Debug).Info("Configured to push to Venafi", keysAndValues...)
}

log.V(logs.Debug).Info("Configured to push to Venafi", keysAndValues...)
res.TLSPKMode = mode
}

var errs error

// Validation and defaulting of `server` and the deprecated `endpoint.path`.
if res.TLSPKMode != Off {
{
// Only relevant if using TLSPK backends
hasEndpointField := cfg.Endpoint.Host != "" && cfg.Endpoint.Path != ""
hasServerField := cfg.Server != ""
Expand Down Expand Up @@ -583,7 +522,7 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
}

// Validation of `cluster_id` and `organization_id`.
if res.TLSPKMode != Off {
{
var clusterID string
var organizationID string // Only used by the old jetstack-secure mode.
switch res.TLSPKMode { // nolint:exhaustive
Expand All @@ -605,8 +544,10 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
res.OrganizationID = organizationID
res.ClusterID = clusterID
res.ClusterDescription = cfg.ClusterDescription
}

// Validation of `data-gatherers`.
// Validation of `data-gatherers`.
{
if dgErr := ValidateDataGatherers(cfg.DataGatherers); dgErr != nil {
errs = multierror.Append(errs, dgErr)
}
Expand Down Expand Up @@ -807,8 +748,6 @@ func validateCredsAndCreateClient(log logr.Logger, flagCredentialsPath, flagClie
if err != nil {
errs = multierror.Append(errs, err)
}
case Off:
// No client needed in this mode.
default:
panic(fmt.Errorf("programmer mistake: auth mode not implemented: %s", cfg.TLSPKMode))
}
Expand Down
42 changes: 2 additions & 40 deletions pkg/agent/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,11 @@ func Test_ValidateAndCombineConfig(t *testing.T) {
withoutCmdLineFlags(),
)
assert.EqualError(t, err, testutil.Undent(`
no TLSPK mode specified and MachineHub mode is disabled. You must either enable the MachineHub mode (using --machine-hub), or enable one of the TLSPK modes.
To enable one of the TLSPK modes, you can:
no TLSPK mode specified. To enable one of the TLSPK modes, you can:
- Use (--venafi-cloud with --credentials-file) or (--client-id with --private-key-path) to use the Venafi Cloud Key Pair Service Account mode.
- Use --venafi-connection for the Venafi Cloud VenafiConnection mode.
- Use --credentials-file alone if you want to use the Jetstack Secure OAuth mode.
- Use --api-token if you want to use the Jetstack Secure API Token mode.
Note that it is possible to use one of the TLSPK modes along with the MachineHub mode (--machine-hub).`))
- Use --api-token if you want to use the Jetstack Secure API Token mode.`))
assert.Nil(t, cl)
})

Expand Down Expand Up @@ -617,42 +615,6 @@ func Test_ValidateAndCombineConfig(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, VenafiCloudVenafiConnection, got.TLSPKMode)
})

t.Run("machinehub only: username and password", func(t *testing.T) {
t.Setenv("POD_NAMESPACE", "venafi")
t.Setenv("KUBECONFIG", withFile(t, fakeKubeconfig))
got, _, err := ValidateAndCombineConfig(discardLogs(),
withConfig(testutil.Undent(`
machineHub:
subdomain: foo
credentialsSecretName: secret-1
period: 1h
`)),
withCmdLineFlags("--machine-hub"))
require.NoError(t, err)
assert.Equal(t, Off, got.TLSPKMode)
assert.Equal(t, true, got.MachineHubMode)
})

t.Run("machinehub + venafi-cloud-keypair-auth should work simultaneously", func(t *testing.T) {
t.Setenv("POD_NAMESPACE", "venafi")
t.Setenv("KUBECONFIG", withFile(t, fakeKubeconfig))
privKeyPath := withFile(t, fakePrivKeyPEM)
got, _, err := ValidateAndCombineConfig(discardLogs(),
withConfig(testutil.Undent(`
machineHub:
subdomain: foo
credentialsSecretName: secret-1
period: 1h
venafi-cloud:
upload_path: /v1/tlspk/upload/clusterdata
cluster_id: foo
`)),
withCmdLineFlags("--machine-hub", "--venafi-cloud", "--client-id", "5bc7d07c-45da-11ef-a878-523f1e1d7de1", "--private-key-path", privKeyPath))
require.NoError(t, err)
assert.Equal(t, VenafiCloudKeypair, got.TLSPKMode)
assert.Equal(t, true, got.MachineHubMode)
})
}

func Test_ValidateAndCombineConfig_VenafiCloudKeyPair(t *testing.T) {
Expand Down
26 changes: 6 additions & 20 deletions pkg/agent/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,28 +337,14 @@ func gatherAndOutputData(ctx context.Context, eventf Eventf, config CombinedConf
log.Info("Warning: PushingErr: retrying", "in", t, "reason", err)
})

if config.MachineHubMode {
post := func() (any, error) {
log.Info("machine hub mode not yet implemented")
return struct{}{}, nil
}

group.Go(func() error {
_, err := backoff.Retry(ctx, post, backoff.WithBackOff(backOff), backoff.WithNotify(notificationFunc), backoff.WithMaxElapsedTime(config.BackoffMaxTime))
return err
})
post := func() (any, error) {
return struct{}{}, postData(klog.NewContext(ctx, log), config, preflightClient, readings)
}

if config.TLSPKMode != Off {
post := func() (any, error) {
return struct{}{}, postData(klog.NewContext(ctx, log), config, preflightClient, readings)
}

group.Go(func() error {
_, err := backoff.Retry(ctx, post, backoff.WithBackOff(backOff), backoff.WithNotify(notificationFunc), backoff.WithMaxElapsedTime(config.BackoffMaxTime))
return err
})
}
group.Go(func() error {
_, err := backoff.Retry(ctx, post, backoff.WithBackOff(backOff), backoff.WithNotify(notificationFunc), backoff.WithMaxElapsedTime(config.BackoffMaxTime))
return err
})

groupErr := group.Wait()
if groupErr != nil {
Expand Down