11package agent
22
33import (
4+ "errors"
45 "fmt"
56 "io"
67 "net/url"
@@ -10,7 +11,6 @@ import (
1011
1112 "github.com/go-logr/logr"
1213 "github.com/hashicorp/go-multierror"
13- "github.com/pkg/errors"
1414 "github.com/spf13/cobra"
1515 "gopkg.in/yaml.v3"
1616 "k8s.io/client-go/rest"
@@ -63,7 +63,7 @@ type Config struct {
6363 // Skips label keys that match the given set of regular expressions.
6464 ExcludeLabelKeysRegex []string `yaml:"exclude-label-keys-regex"`
6565
66- // MachineHub holds config specific to MachineHub mode
66+ // MachineHub holds config specific to MachineHub mode.
6767 MachineHub MachineHubConfig `yaml:"machineHub"`
6868}
6969
@@ -94,13 +94,14 @@ type VenafiCloudConfig struct {
9494
9595// MachineHubConfig holds configuration values specific to the CyberArk Machine Hub integration
9696type MachineHubConfig struct {
97- // Subdomain is the subdomain indicating where data should be pushed. Used for
98- // querying the Service Discovery Service to discover the Identity API URL
97+ // Subdomain is the subdomain indicating where data should be pushed. Used
98+ // for querying the Service Discovery Service to discover the Identity API
99+ // URL.
99100 Subdomain string `yaml:"subdomain"`
100101
101- // CredentialsSecretName is the name of a Kubernetes Secret in the same namespace as
102- // the agent, which will be watched for a username and password to send to CyberArk
103- // Identity for authentication.
102+ // CredentialsSecretName is the name of a Kubernetes Secret in the same
103+ // namespace as the agent, which will be watched for a username and password
104+ // to send to CyberArk Identity for authentication.
104105 CredentialsSecretName string `yaml:"credentialsSecretName"`
105106}
106107
@@ -132,7 +133,7 @@ type AgentCmdFlags struct {
132133 // --credentials-file.
133134 VenafiCloudMode bool
134135
135- // MachineHubMode configures the agent to send data to CyberArk Machine Hub
136+ // MachineHubMode configures the agent to send data to CyberArk Machine Hub.
136137 MachineHubMode bool
137138
138139 // ClientID (--client-id) is the clientID in case of Venafi Cloud Key Pair
@@ -335,34 +336,44 @@ func InitAgentCmdFlags(c *cobra.Command, cfg *AgentCmdFlags) {
335336 )
336337 c .PersistentFlags ().MarkDeprecated ("disable-compression" , "no longer has an effect" )
337338
339+ c .PersistentFlags ().BoolVar (
340+ & cfg .MachineHubMode ,
341+ "machine-hub" ,
342+ false ,
343+ "Enables MachineHub mode. The agent will push data to CyberArk MachineHub. Can be used in conjunction with --venafi-cloud." ,
344+ )
345+
338346}
339347
340- // AuthMode controls how to authenticate to TLSPK / Jetstack Secure. Only one AuthMode
341- // may be provided if using using those backends.
342- type AuthMode string
348+ // TLSPKMode controls how to authenticate to TLSPK / Jetstack Secure. Only one
349+ // TLSPKMode may be provided if using using those backends.
350+ type TLSPKMode string
343351
344352const (
345- JetstackSecureOAuth AuthMode = "Jetstack Secure OAuth"
346- JetstackSecureAPIToken AuthMode = "Jetstack Secure API Token"
347- VenafiCloudKeypair AuthMode = "Venafi Cloud Key Pair Service Account"
348- VenafiCloudVenafiConnection AuthMode = "Venafi Cloud VenafiConnection"
349-
350- NoTLSPK AuthMode = "MachineHub only"
353+ JetstackSecureOAuth TLSPKMode = "Jetstack Secure OAuth"
354+ JetstackSecureAPIToken TLSPKMode = "Jetstack Secure API Token"
355+ VenafiCloudKeypair TLSPKMode = "Venafi Cloud Key Pair Service Account"
356+ VenafiCloudVenafiConnection TLSPKMode = "Venafi Cloud VenafiConnection"
357+
358+ // It is possible to push to both MachineHub and TLSPK. With this mode, the
359+ // agent will only push to MachineHub and not to TLSPK.
360+ Off TLSPKMode = "MachineHub only"
351361)
352362
353363// The command-line flags and the config file are combined into this struct by
354364// ValidateAndCombineConfig.
355365type CombinedConfig struct {
356- AuthMode AuthMode
357-
358- // Used by all modes.
359- ClusterID string
360366 DataGatherers []DataGatherer
361367 Period time.Duration
362368 BackoffMaxTime time.Duration
369+ InstallNS string
363370 StrictMode bool
364371 OneShot bool
365- InstallNS string
372+
373+ TLSPKMode TLSPKMode
374+
375+ // Used by all TLSPK modes.
376+ ClusterID string
366377
367378 // Used by JetstackSecureOAuth, JetstackSecureAPIToken, and
368379 // VenafiCloudKeypair. Ignored in VenafiCloudVenafiConnection mode.
@@ -388,10 +399,10 @@ type CombinedConfig struct {
388399 OutputPath string
389400 InputPath string
390401
391- // MachineHub-related settings
392- MachineHubMode bool
393-
394- MachineHub MachineHubConfig
402+ // MachineHub-related settings.
403+ MachineHubMode bool
404+ MachineHubSubdomain string
405+ MachineHubCredentialsSecretName string
395406}
396407
397408// ValidateAndCombineConfig combines and validates the input configuration with
@@ -414,12 +425,16 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
414425 }
415426
416427 res .MachineHubMode = true
417- res .MachineHubConfig = cfg .MachineHubConfig
428+ res .MachineHubSubdomain = cfg .MachineHub .Subdomain
429+ res .MachineHubCredentialsSecretName = cfg .MachineHub .CredentialsSecretName
430+
431+ keysAndValues := []any {"credentialsSecretName" , res .MachineHubCredentialsSecretName }
432+ log .V (logs .Info ).Info ("Will push to CyberArk MachineHub using a username and password loaded from a Kubernetes Secret" , keysAndValues ... )
418433 }
419434
420435 {
421436 var (
422- mode AuthMode
437+ mode TLSPKMode
423438 reason string
424439 keysAndValues []any
425440 )
@@ -448,24 +463,28 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
448463 reason = "--credentials-file was specified without --venafi-cloud"
449464 default :
450465 if ! flags .MachineHubMode {
451- return CombinedConfig {}, nil , fmt .Errorf ("no auth mode specified and MachineHub mode is disabled. You can use one of four auth modes:\n " +
466+ 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 " +
467+ "To enable one of the TLSPK modes, you can:\n " +
452468 " - Use (--venafi-cloud with --credentials-file) or (--client-id with --private-key-path) to use the " + string (VenafiCloudKeypair ) + " mode.\n " +
453469 " - Use --venafi-connection for the " + string (VenafiCloudVenafiConnection ) + " mode.\n " +
454470 " - Use --credentials-file alone if you want to use the " + string (JetstackSecureOAuth ) + " mode.\n " +
455- " - Use --api-token if you want to use the " + string (JetstackSecureAPIToken ) + " mode.\n " )
471+ " - Use --api-token if you want to use the " + string (JetstackSecureAPIToken ) + " mode.\n " +
472+ "Note that it is possible to use one of the TLSPK modes along with the MachineHub mode (--machine-hub)." )
456473 }
457474
458- mode = NoTLSPK
459- reason = "only MachineHub has been configured as a backend"
475+ mode = Off
460476 }
461477
462- res .AuthMode = mode
463478 keysAndValues = append (keysAndValues , "mode" , mode , "reason" , reason )
464- log .V (logs .Debug ).Info ("Authentication mode" , keysAndValues ... )
479+ if mode != Off {
480+ log .V (logs .Debug ).Info ("Configured to push to Venafi" , keysAndValues ... )
481+ }
482+
483+ res .TLSPKMode = mode
465484 }
466485
467486 // Validation and defaulting of `server` and the deprecated `endpoint.path`.
468- if res .AuthMode != NoTLSPK {
487+ if res .TLSPKMode != Off {
469488 // Only relevant if using TLSPK backends
470489 hasEndpointField := cfg .Endpoint .Host != "" && cfg .Endpoint .Path != ""
471490 hasServerField := cfg .Server != ""
@@ -488,7 +507,7 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
488507 endpointPath = cfg .Endpoint .Path
489508 case ! hasServerField && ! hasEndpointField :
490509 server = "https://preflight.jetstack.io"
491- if res .AuthMode == VenafiCloudKeypair {
510+ if res .TLSPKMode == VenafiCloudKeypair {
492511 // The VenafiCloudVenafiConnection mode doesn't need a server.
493512 server = client .VenafiCloudProdURL
494513 }
@@ -497,7 +516,7 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
497516 if urlErr != nil || url .Hostname () == "" {
498517 errs = multierror .Append (errs , fmt .Errorf ("server %q is not a valid URL" , server ))
499518 }
500- if res .AuthMode == VenafiCloudVenafiConnection && server != "" {
519+ if res .TLSPKMode == VenafiCloudVenafiConnection && server != "" {
501520 log .Info (fmt .Sprintf ("ignoring the server field specified in the config file. In %s mode, this field is not needed." , VenafiCloudVenafiConnection ))
502521 server = ""
503522 }
@@ -509,9 +528,9 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
509528 {
510529 var uploadPath string
511530 switch {
512- case res .AuthMode == VenafiCloudKeypair :
531+ case res .TLSPKMode == VenafiCloudKeypair :
513532 if cfg .VenafiCloud == nil || cfg .VenafiCloud .UploadPath == "" {
514- errs = multierror .Append (errs , fmt .Errorf ("the venafi-cloud.upload_path field is required when using the %s mode" , res .AuthMode ))
533+ errs = multierror .Append (errs , fmt .Errorf ("the venafi-cloud.upload_path field is required when using the %s mode" , res .TLSPKMode ))
515534 break // Skip to the end of the switch statement.
516535 }
517536 _ , urlErr := url .Parse (cfg .VenafiCloud .UploadPath )
@@ -521,14 +540,14 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
521540 }
522541
523542 uploadPath = cfg .VenafiCloud .UploadPath
524- case res .AuthMode == VenafiCloudVenafiConnection :
543+ case res .TLSPKMode == VenafiCloudVenafiConnection :
525544 // The venafi-cloud.upload_path was initially meant to let users
526545 // configure HTTP proxies, but it has never been used since HTTP
527546 // proxies don't rewrite paths. Thus, we've disabled the ability to
528547 // change this value with the new --venafi-connection flag, and this
529548 // field is simply ignored.
530549 if cfg .VenafiCloud != nil && cfg .VenafiCloud .UploadPath != "" {
531- log .Info (fmt .Sprintf (`ignoring the venafi-cloud.upload_path field in the config file. In %s mode, this field is not needed.` , res .AuthMode ))
550+ log .Info (fmt .Sprintf (`ignoring the venafi-cloud.upload_path field in the config file. In %s mode, this field is not needed.` , res .TLSPKMode ))
532551 }
533552 uploadPath = ""
534553 }
@@ -546,26 +565,26 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
546565 // https://venafi.atlassian.net/browse/VC-35385 is done.
547566 {
548567 if cfg .VenafiCloud != nil && cfg .VenafiCloud .UploaderID != "" {
549- log .Info (fmt .Sprintf (`ignoring the venafi-cloud.uploader_id field in the config file. This field is not needed in %s mode.` , res .AuthMode ))
568+ log .Info (fmt .Sprintf (`ignoring the venafi-cloud.uploader_id field in the config file. This field is not needed in %s mode.` , res .TLSPKMode ))
550569 }
551570 }
552571
553572 // Validation of `cluster_id` and `organization_id`.
554- if res .AuthMode != NoTLSPK {
573+ if res .TLSPKMode != Off {
555574 var clusterID string
556575 var organizationID string // Only used by the old jetstack-secure mode.
557576 switch {
558- case res .AuthMode == VenafiCloudKeypair :
577+ case res .TLSPKMode == VenafiCloudKeypair :
559578 if cfg .ClusterID == "" {
560- errs = multierror .Append (errs , fmt .Errorf ("cluster_id is required in %s mode" , res .AuthMode ))
579+ errs = multierror .Append (errs , fmt .Errorf ("cluster_id is required in %s mode" , res .TLSPKMode ))
561580 }
562581 clusterID = cfg .ClusterID
563- case res .AuthMode == VenafiCloudVenafiConnection :
582+ case res .TLSPKMode == VenafiCloudVenafiConnection :
564583 if cfg .ClusterID == "" {
565- errs = multierror .Append (errs , fmt .Errorf ("cluster_id is required in %s mode" , res .AuthMode ))
584+ errs = multierror .Append (errs , fmt .Errorf ("cluster_id is required in %s mode" , res .TLSPKMode ))
566585 }
567586 clusterID = cfg .ClusterID
568- case res .AuthMode == JetstackSecureOAuth || res .AuthMode == JetstackSecureAPIToken :
587+ case res .TLSPKMode == JetstackSecureOAuth || res .TLSPKMode == JetstackSecureAPIToken :
569588 if cfg .OrganizationID == "" {
570589 errs = multierror .Append (errs , fmt .Errorf ("organization_id is required" ))
571590 }
@@ -625,7 +644,7 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
625644 res .InstallNS = installNS
626645
627646 // Validation of --venafi-connection and --venafi-connection-namespace.
628- if res .AuthMode == VenafiCloudVenafiConnection {
647+ if res .TLSPKMode == VenafiCloudVenafiConnection {
629648 res .VenConnName = flags .VenConnName
630649 var venConnNS string = flags .VenConnNS
631650 if flags .VenConnNS == "" {
@@ -692,7 +711,7 @@ func validateCredsAndCreateClient(log logr.Logger, flagCredentialsPath, flagClie
692711 var preflightClient client.Client
693712 metadata := & api.AgentMetadata {Version : version .PreflightVersion , ClusterID : cfg .ClusterID }
694713 switch {
695- case cfg .AuthMode == JetstackSecureOAuth :
714+ case cfg .TLSPKMode == JetstackSecureOAuth :
696715 // Note that there are no command line flags to configure the
697716 // JetstackSecureOAuth mode.
698717 credsBytes , err := readCredentialsFile (flagCredentialsPath )
@@ -711,7 +730,7 @@ func validateCredsAndCreateClient(log logr.Logger, flagCredentialsPath, flagClie
711730 if err != nil {
712731 errs = multierror .Append (errs , err )
713732 }
714- case cfg .AuthMode == VenafiCloudKeypair :
733+ case cfg .TLSPKMode == VenafiCloudKeypair :
715734 var creds client.Credentials
716735
717736 if flagClientID != "" && flagCredentialsPath != "" {
@@ -754,7 +773,7 @@ func validateCredsAndCreateClient(log logr.Logger, flagCredentialsPath, flagClie
754773 if err != nil {
755774 errs = multierror .Append (errs , err )
756775 }
757- case cfg .AuthMode == VenafiCloudVenafiConnection :
776+ case cfg .TLSPKMode == VenafiCloudVenafiConnection :
758777 var restCfg * rest.Config
759778 restCfg , err := kubeconfig .LoadRESTConfig ("" )
760779 if err != nil {
@@ -766,18 +785,20 @@ func validateCredsAndCreateClient(log logr.Logger, flagCredentialsPath, flagClie
766785 if err != nil {
767786 errs = multierror .Append (errs , err )
768787 }
769- case cfg .AuthMode == JetstackSecureAPIToken :
788+ case cfg .TLSPKMode == JetstackSecureAPIToken :
770789 var err error
771790 preflightClient , err = client .NewAPITokenClient (metadata , flagAPIToken , cfg .Server )
772791 if err != nil {
773792 errs = multierror .Append (errs , err )
774793 }
794+ case cfg .TLSPKMode == Off :
795+ // No client needed in this mode.
775796 default :
776- panic (fmt .Errorf ("programmer mistake: auth mode not implemented: %s" , cfg .AuthMode ))
797+ panic (fmt .Errorf ("programmer mistake: auth mode not implemented: %s" , cfg .TLSPKMode ))
777798 }
778799
779800 if errs != nil {
780- return nil , fmt .Errorf ("failed loading config using the %s mode: %w" , cfg .AuthMode , errs )
801+ return nil , fmt .Errorf ("failed loading config using the %s mode: %w" , cfg .TLSPKMode , errs )
781802 }
782803
783804 return preflightClient , nil
@@ -814,7 +835,7 @@ func createCredentialClient(log logr.Logger, credentials client.Credentials, cfg
814835 uploaderID := "no"
815836
816837 var uploadPath string
817- if cfg .AuthMode == VenafiCloudKeypair {
838+ if cfg .TLSPKMode == VenafiCloudKeypair {
818839 // We don't do this for the VenafiCloudVenafiConnection mode because
819840 // the upload_path field is ignored in that mode.
820841 log .Info ("Loading upload_path from \" venafi-cloud\" configuration." )
@@ -904,7 +925,7 @@ func (c *Config) Dump() (string, error) {
904925 d , err := yaml .Marshal (& c )
905926
906927 if err != nil {
907- return "" , errors . Wrap ( err , "failed to generate YAML dump of config" )
928+ return "" , fmt . Errorf ( "failed to generate YAML dump of config: %w" , err )
908929 }
909930
910931 return string (d ), nil
0 commit comments