Skip to content

Commit 8b8a917

Browse files
committed
add config + new client for NGTS
This will add initial support for NGTS. Auth is based on the existing Venafi Cloud client using a keypair. Signed-off-by: Ashley Davis <ashley.davis@cyberark.com>
1 parent 4445a6b commit 8b8a917

File tree

6 files changed

+1073
-77
lines changed

6 files changed

+1073
-77
lines changed

pkg/agent/config.go

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,17 @@ type AgentCmdFlags struct {
178178

179179
// Prometheus (--enable-metrics) enables the Prometheus metrics server.
180180
Prometheus bool
181+
182+
// NGTSMode (--ngts) turns on the NGTS mode. The agent will authenticate
183+
// using key pair authentication and send data to NGTS endpoints.
184+
NGTSMode bool
185+
186+
// TSGID (--tsg-id) is the TSG (Tenant Security Group) ID for NGTS mode.
187+
TSGID string
188+
189+
// NGTSServerURL (--ngts-server-url) is a hidden flag for developers to
190+
// override the NGTS server URL for testing purposes.
191+
NGTSServerURL string
181192
}
182193

183194
func InitAgentCmdFlags(c *cobra.Command, cfg *AgentCmdFlags) {
@@ -330,6 +341,34 @@ func InitAgentCmdFlags(c *cobra.Command, cfg *AgentCmdFlags) {
330341
panic(err)
331342
}
332343

344+
c.PersistentFlags().BoolVar(
345+
&cfg.NGTSMode,
346+
"ngts",
347+
false,
348+
"Enables NGTS mode. The agent will authenticate using key pair authentication and send data to NGTS endpoints. "+
349+
"Must be used in conjunction with --tsg-id, --client-id, and --private-key-path.",
350+
)
351+
c.PersistentFlags().StringVar(
352+
&cfg.TSGID,
353+
"tsg-id",
354+
"",
355+
"The TSG (Tenant Security Group) ID for NGTS mode. Required when using --ngts.",
356+
)
357+
358+
ngtsServerURLFlag := "ngts-server-url"
359+
360+
c.PersistentFlags().StringVar(
361+
&cfg.NGTSServerURL,
362+
ngtsServerURLFlag,
363+
"",
364+
"Override the NGTS server URL for testing purposes. This flag is intended for agent development and should not need to be set.",
365+
)
366+
367+
// ngts-server-url is intended only for developers, so hide it from help
368+
if err := c.PersistentFlags().MarkHidden(ngtsServerURLFlag); err != nil {
369+
panic(err)
370+
}
371+
333372
}
334373

335374
// OutputMode controls how the collected data is published.
@@ -343,6 +382,7 @@ const (
343382
VenafiCloudVenafiConnection OutputMode = "Venafi Cloud VenafiConnection"
344383
LocalFile OutputMode = "Local File"
345384
MachineHub OutputMode = "MachineHub"
385+
NGTS OutputMode = "NGTS"
346386
)
347387

348388
// The command-line flags and the config file and some environment variables are
@@ -387,6 +427,10 @@ type CombinedConfig struct {
387427
ExcludeAnnotationKeysRegex []*regexp.Regexp
388428
ExcludeLabelKeysRegex []*regexp.Regexp
389429

430+
// NGTS mode only.
431+
TSGID string
432+
NGTSServerURL string
433+
390434
// Only used for testing purposes.
391435
OutputPath string
392436
InputPath string
@@ -411,6 +455,10 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
411455
keysAndValues []any
412456
)
413457
switch {
458+
case flags.NGTSMode:
459+
mode = NGTS
460+
reason = "--ngts was specified"
461+
keysAndValues = []any{"ngts", true}
414462
case flags.VenafiCloudMode && flags.CredentialsPath != "":
415463
mode = VenafiCloudKeypair
416464
reason = "--venafi-cloud and --credentials-path were specified"
@@ -448,6 +496,7 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
448496
default:
449497
return CombinedConfig{}, nil, fmt.Errorf("no output mode specified. " +
450498
"To enable one of the output modes, you can:\n" +
499+
" - Use --ngts with --tsg-id, --client-id, and --private-key-path to use the " + string(NGTS) + " mode.\n" +
451500
" - Use (--venafi-cloud with --credentials-file) or (--client-id with --private-key-path) to use the " + string(VenafiCloudKeypair) + " mode.\n" +
452501
" - Use --venafi-connection for the " + string(VenafiCloudVenafiConnection) + " mode.\n" +
453502
" - Use --credentials-file alone if you want to use the " + string(JetstackSecureOAuth) + " mode.\n" +
@@ -463,6 +512,55 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
463512

464513
var errs error
465514

515+
// Validation of NGTS mode requirements.
516+
if res.OutputMode == NGTS {
517+
if flags.TSGID == "" {
518+
errs = multierror.Append(errs, fmt.Errorf("--tsg-id is required when using --ngts"))
519+
}
520+
if flags.ClientID == "" {
521+
errs = multierror.Append(errs, fmt.Errorf("--client-id is required when using --ngts"))
522+
}
523+
if flags.PrivateKeyPath == "" {
524+
errs = multierror.Append(errs, fmt.Errorf("--private-key-path is required when using --ngts"))
525+
}
526+
527+
// Error if MachineHub mode is also enabled
528+
if flags.MachineHubMode {
529+
errs = multierror.Append(errs, fmt.Errorf("--machine-hub cannot be used with --ngts. These are mutually exclusive modes."))
530+
}
531+
532+
// Error if VenafiConnection mode flags are used
533+
if flags.VenConnName != "" {
534+
errs = multierror.Append(errs, fmt.Errorf("--venafi-connection cannot be used with --ngts. Use --client-id and --private-key-path instead."))
535+
}
536+
537+
// Error if Jetstack Secure OAuth mode flags are used
538+
if !flags.VenafiCloudMode && flags.CredentialsPath != "" {
539+
errs = multierror.Append(errs, fmt.Errorf("--credentials-file (for Jetstack Secure OAuth) cannot be used with --ngts. Use --client-id and --private-key-path instead."))
540+
}
541+
542+
// Error if API Token mode is used
543+
if flags.APIToken != "" {
544+
errs = multierror.Append(errs, fmt.Errorf("--api-token cannot be used with --ngts. Use --client-id and --private-key-path instead."))
545+
}
546+
547+
// Error if --venafi-cloud is used with --ngts
548+
if flags.VenafiCloudMode {
549+
errs = multierror.Append(errs, fmt.Errorf("--venafi-cloud cannot be used with --ngts. These are different deployment targets."))
550+
}
551+
552+
// Error if organization_id or cluster_id are set in config (these are for Jetstack Secure / CM-SaaS)
553+
if cfg.OrganizationID != "" {
554+
errs = multierror.Append(errs, fmt.Errorf("organization_id in config file is not supported in NGTS mode. This field is only for Jetstack Secure."))
555+
}
556+
if cfg.ClusterID != "" {
557+
errs = multierror.Append(errs, fmt.Errorf("cluster_id in config file is not supported in NGTS mode. Use cluster_name instead."))
558+
}
559+
560+
res.TSGID = flags.TSGID
561+
res.NGTSServerURL = flags.NGTSServerURL
562+
}
563+
466564
// Validation and defaulting of `server` and the deprecated `endpoint.path`.
467565
{
468566
// Only relevant if using TLSPK backends
@@ -491,15 +589,31 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
491589
// The VenafiCloudVenafiConnection mode doesn't need a server.
492590
server = client.VenafiCloudProdURL
493591
}
592+
if res.OutputMode == NGTS {
593+
// In NGTS mode, use NGTSServerURL if provided, otherwise we'll use a default
594+
// (which will be determined when creating the client)
595+
server = res.NGTSServerURL
596+
}
597+
}
598+
599+
// For NGTS mode with custom server URL
600+
if res.OutputMode == NGTS && res.NGTSServerURL != "" {
601+
log.Info("Using custom NGTS server URL (for testing)", "url", res.NGTSServerURL)
602+
server = res.NGTSServerURL
494603
}
604+
495605
url, urlErr := url.Parse(server)
496-
if urlErr != nil || url.Hostname() == "" {
606+
if urlErr != nil || (url.Hostname() == "" && server != "") {
497607
errs = multierror.Append(errs, fmt.Errorf("server %q is not a valid URL", server))
498608
}
499609
if res.OutputMode == VenafiCloudVenafiConnection && server != "" {
500610
log.Info(fmt.Sprintf("ignoring the server field specified in the config file. In %s mode, this field is not needed.", VenafiCloudVenafiConnection))
501611
server = ""
502612
}
613+
if res.OutputMode == NGTS && cfg.Server != "" && res.NGTSServerURL == "" {
614+
log.Info(fmt.Sprintf("ignoring the server field specified in the config file. In %s mode, use --ngts-server-url for testing.", NGTS))
615+
server = res.NGTSServerURL
616+
}
503617
res.Server = server
504618
res.EndpointPath = endpointPath
505619
}
@@ -530,6 +644,12 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
530644
log.Info(fmt.Sprintf(`ignoring the venafi-cloud.upload_path field in the config file. In %s mode, this field is not needed.`, res.OutputMode))
531645
}
532646
uploadPath = ""
647+
case NGTS:
648+
// NGTS mode doesn't use the upload_path field
649+
if cfg.VenafiCloud != nil && cfg.VenafiCloud.UploadPath != "" {
650+
log.Info(fmt.Sprintf(`ignoring the venafi-cloud.upload_path field in the config file. In %s mode, this field is not needed.`, res.OutputMode))
651+
}
652+
uploadPath = ""
533653
}
534654
res.UploadPath = uploadPath
535655
}
@@ -555,6 +675,13 @@ func ValidateAndCombineConfig(log logr.Logger, cfg Config, flags AgentCmdFlags)
555675
var clusterID string // Required by the old jetstack-secure mode deprecated for venafi cloud modes.
556676
var organizationID string // Only used by the old jetstack-secure mode.
557677
switch res.OutputMode { // nolint:exhaustive
678+
case NGTS:
679+
// NGTS mode requires cluster_name
680+
if cfg.ClusterName == "" {
681+
errs = multierror.Append(errs, fmt.Errorf("cluster_name is required in %s mode", res.OutputMode))
682+
}
683+
clusterName = cfg.ClusterName
684+
// cluster_id and organization_id were already validated to not be present in NGTS mode
558685
case VenafiCloudKeypair, VenafiCloudVenafiConnection:
559686
// For backwards compatibility, use the agent config's `cluster_id` as
560687
// ClusterName if `cluster_name` is not set.
@@ -820,6 +947,27 @@ func validateCredsAndCreateClient(log logr.Logger, flagCredentialsPath, flagClie
820947
if err != nil {
821948
errs = multierror.Append(errs, err)
822949
}
950+
case NGTS:
951+
var creds *client.NGTSServiceAccountCredentials
952+
953+
if flagClientID == "" || flagPrivateKeyPath == "" {
954+
errs = multierror.Append(errs, fmt.Errorf("both --client-id and --private-key-path are required for NGTS mode"))
955+
break
956+
}
957+
958+
creds = &client.NGTSServiceAccountCredentials{
959+
ClientID: flagClientID,
960+
PrivateKeyFile: flagPrivateKeyPath,
961+
}
962+
963+
// rootCAs can be used in future to support custom CA certs, but for now will remain empty
964+
var rootCAs *x509.CertPool
965+
966+
var err error
967+
outputClient, err = client.NewNGTSClient(metadata, creds, cfg.Server, cfg.TSGID, rootCAs)
968+
if err != nil {
969+
errs = multierror.Append(errs, err)
970+
}
823971
default:
824972
panic(fmt.Errorf("programmer mistake: output mode not implemented: %s", cfg.OutputMode))
825973
}

0 commit comments

Comments
 (0)