Skip to content

Commit 76caca5

Browse files
committed
Code review; validate secrets
1 parent d1d1b15 commit 76caca5

23 files changed

+862
-132
lines changed

charts/nginx-gateway-fabric/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,8 @@ The following table lists the configurable parameters of the NGINX Gateway Fabri
268268
| `nginx.image.tag` | | string | `"edge"` |
269269
| `nginx.lifecycle` | The lifecycle of the nginx container. | object | `{}` |
270270
| `nginx.plus` | Is NGINX Plus image being used | bool | `false` |
271-
| `nginx.usage.caSecretName` | The name of the Secret containing the CA certificate for verifying the NGINX Plus usage reporting server. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `""` |
272-
| `nginx.usage.clientSSLSecretName` | The name of the Secret containing the client certificate/key for communicating with the NGINX Plus usage reporting server. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `""` |
271+
| `nginx.usage.caSecretName` | The name of the Secret containing the NGINX Instance Manager CA certificate. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `""` |
272+
| `nginx.usage.clientSSLSecretName` | The name of the Secret containing the client certificate and key for authenticating with NGINX Instance Manager. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `""` |
273273
| `nginx.usage.endpoint` | The endpoint of the NGINX Plus usage reporting server. Default: product.connect.nginx.com | string | `""` |
274274
| `nginx.usage.resolver` | The nameserver used to resolve the NGINX Plus usage reporting endpoint. Used with NGINX Instance Manager. | string | `""` |
275275
| `nginx.usage.secretName` | The name of the Secret containing the JWT for NGINX Plus usage reporting. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `"nplus-license"` |

charts/nginx-gateway-fabric/values.schema.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,14 +264,14 @@
264264
"properties": {
265265
"caSecretName": {
266266
"default": "",
267-
"description": "The name of the Secret containing the CA certificate for verifying the NGINX Plus usage reporting\nserver. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway).",
267+
"description": "The name of the Secret containing the NGINX Instance Manager CA certificate.\nMust exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway).",
268268
"required": [],
269269
"title": "caSecretName",
270270
"type": "string"
271271
},
272272
"clientSSLSecretName": {
273273
"default": "",
274-
"description": "The name of the Secret containing the client certificate/key for communicating with the NGINX Plus usage reporting\nserver. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway).",
274+
"description": "The name of the Secret containing the client certificate and key for authenticating with NGINX Instance Manager.\nMust exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway).",
275275
"required": [],
276276
"title": "clientSSLSecretName",
277277
"type": "string"

charts/nginx-gateway-fabric/values.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ nginx:
149149
# -- Disable client verification of the NGINX Plus usage reporting server certificate.
150150
skipVerify: false
151151

152-
# -- The name of the Secret containing the CA certificate for verifying the NGINX Plus usage reporting
153-
# server. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway).
152+
# -- The name of the Secret containing the NGINX Instance Manager CA certificate.
153+
# Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway).
154154
caSecretName: ""
155155

156-
# -- The name of the Secret containing the client certificate/key for communicating with the NGINX Plus usage reporting
157-
# server. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway).
156+
# -- The name of the Secret containing the client certificate and key for authenticating with NGINX Instance Manager.
157+
# Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway).
158158
clientSSLSecretName: ""
159159

160160
# @schema

cmd/gateway/commands.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func createRootCommand() *cobra.Command {
4747
return rootCmd
4848
}
4949

50+
//nolint:gocyclo
5051
func createStaticModeCommand() *cobra.Command {
5152
// flag names
5253
const (
@@ -200,6 +201,10 @@ func createStaticModeCommand() *cobra.Command {
200201
}
201202

202203
var usageReportConfig config.UsageReportConfig
204+
if plus && usageReportSecretName.value == "" {
205+
return errors.New("usage-report-secret is required when using NGINX Plus")
206+
}
207+
203208
if plus {
204209
usageReportConfig = config.UsageReportConfig{
205210
SecretName: usageReportSecretName.value,
@@ -392,8 +397,6 @@ func createStaticModeCommand() *cobra.Command {
392397
"that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway).",
393398
)
394399

395-
cmd.MarkFlagsRequiredTogether(plusFlag, usageReportSecretFlag)
396-
397400
cmd.Flags().Var(
398401
&usageReportEndpoint,
399402
usageReportEndpointFlag,
@@ -416,16 +419,16 @@ func createStaticModeCommand() *cobra.Command {
416419
cmd.Flags().Var(
417420
&usageReportClientSSLSecretName,
418421
usageReportClientSSLSecretFlag,
419-
"The name of the Secret containing the client cert/key for communicating with the NGINX Plus usage reporting "+
420-
"server. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in "+
422+
"The name of the Secret containing the client certificate and key for authenticating with NGINX Instance Manager. "+
423+
"Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in "+
421424
"(default namespace: nginx-gateway).",
422425
)
423426

424427
cmd.Flags().Var(
425428
&usageReportCASecretName,
426429
usageReportCASecretFlag,
427-
"The name of the Secret containing the CA cert for verifying the NGINX Plus usage reporting "+
428-
"server. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in "+
430+
"The name of the Secret containing the NGINX Instance Manager CA certificate. "+
431+
"Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in "+
429432
"(default namespace: nginx-gateway).",
430433
)
431434

@@ -533,11 +536,8 @@ func createCopyCommand() *cobra.Command {
533536
Use: "copy",
534537
Short: "Copy files to another directory",
535538
RunE: func(_ *cobra.Command, _ []string) error {
536-
if len(srcFiles) == 0 {
537-
return errors.New("source must not be empty")
538-
}
539-
if len(dest) == 0 {
540-
return errors.New("destination must not be empty")
539+
if err := validateSleepArgs(srcFiles, dest); err != nil {
540+
return err
541541
}
542542

543543
for _, src := range srcFiles {

cmd/gateway/validation.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,15 @@ func ensureNoPortCollisions(ports ...int) error {
205205

206206
return nil
207207
}
208+
209+
// validateSleepArgs ensures that arguments to the sleep command are set.
210+
func validateSleepArgs(srcFiles []string, dest string) error {
211+
if len(srcFiles) == 0 {
212+
return errors.New("source must not be empty")
213+
}
214+
if len(dest) == 0 {
215+
return errors.New("destination must not be empty")
216+
}
217+
218+
return nil
219+
}

cmd/gateway/validation_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,3 +553,47 @@ func TestEnsureNoPortCollisions(t *testing.T) {
553553
g.Expect(ensureNoPortCollisions(9113, 8081)).To(Succeed())
554554
g.Expect(ensureNoPortCollisions(9113, 9113)).ToNot(Succeed())
555555
}
556+
557+
func TestValidateSleepArgs(t *testing.T) {
558+
t.Parallel()
559+
560+
tests := []struct {
561+
name string
562+
dest string
563+
srcFiles []string
564+
expErr bool
565+
}{
566+
{
567+
name: "valid values",
568+
dest: "/dest/file",
569+
srcFiles: []string{"/src/file"},
570+
expErr: false,
571+
},
572+
{
573+
name: "invalid dest",
574+
dest: "",
575+
srcFiles: []string{"/src/file"},
576+
expErr: true,
577+
},
578+
{
579+
name: "invalid src",
580+
dest: "/dest/file",
581+
srcFiles: []string{},
582+
expErr: true,
583+
},
584+
}
585+
586+
for _, tc := range tests {
587+
t.Run(tc.name, func(t *testing.T) {
588+
t.Parallel()
589+
g := NewWithT(t)
590+
591+
err := validateSleepArgs(tc.srcFiles, tc.dest)
592+
if !tc.expErr {
593+
g.Expect(err).ToNot(HaveOccurred())
594+
} else {
595+
g.Expect(err).To(HaveOccurred())
596+
}
597+
})
598+
}
599+
}

internal/mode/static/handler.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,10 @@ func (h *eventHandlerImpl) HandleEventBatch(ctx context.Context, logger logr.Log
173173
case state.EndpointsOnlyChange:
174174
h.version++
175175
cfg := dataplane.BuildConfiguration(ctx, gr, h.cfg.serviceResolver, h.version)
176-
if err := h.setDeploymentCtx(ctx, &cfg); err != nil {
176+
if depCtx, err := h.setDeploymentCtx(ctx, logger); err != nil {
177177
logger.Error(err, "error setting deployment context for usage reporting")
178+
} else {
179+
cfg.DeploymentContext = depCtx
178180
}
179181

180182
h.setLatestConfiguration(&cfg)
@@ -187,8 +189,10 @@ func (h *eventHandlerImpl) HandleEventBatch(ctx context.Context, logger logr.Log
187189
case state.ClusterStateChange:
188190
h.version++
189191
cfg := dataplane.BuildConfiguration(ctx, gr, h.cfg.serviceResolver, h.version)
190-
if err := h.setDeploymentCtx(ctx, &cfg); err != nil {
192+
if depCtx, err := h.setDeploymentCtx(ctx, logger); err != nil {
191193
logger.Error(err, "error setting deployment context for usage reporting")
194+
} else {
195+
cfg.DeploymentContext = depCtx
192196
}
193197

194198
h.setLatestConfiguration(&cfg)
@@ -497,9 +501,12 @@ func getGatewayAddresses(
497501
}
498502

499503
// setDeploymentCtx sets the deployment context metadata for nginx plus reporting.
500-
func (h *eventHandlerImpl) setDeploymentCtx(ctx context.Context, cfg *dataplane.Configuration) error {
504+
func (h *eventHandlerImpl) setDeploymentCtx(
505+
ctx context.Context,
506+
logger logr.Logger,
507+
) (dataplane.DeploymentContext, error) {
501508
if !h.cfg.plus {
502-
return nil
509+
return dataplane.DeploymentContext{}, nil
503510
}
504511

505512
podNSName := types.NamespacedName{
@@ -509,27 +516,29 @@ func (h *eventHandlerImpl) setDeploymentCtx(ctx context.Context, cfg *dataplane.
509516

510517
clusterInfo, err := telemetry.CollectClusterInformation(ctx, h.cfg.k8sReader)
511518
if err != nil {
512-
return fmt.Errorf("error getting cluster information")
519+
return dataplane.DeploymentContext{}, fmt.Errorf("error getting cluster information")
513520
}
514521

522+
var installationID string
523+
// InstallationID is not required by the usage API, so if we can't get it, don't return an error
515524
replicaSet, err := telemetry.GetPodReplicaSet(ctx, h.cfg.k8sReader, podNSName)
516525
if err != nil {
517-
return fmt.Errorf("failed to get replica set for pod %v: %w", podNSName, err)
518-
}
519-
520-
deploymentID, err := telemetry.GetDeploymentID(replicaSet)
521-
if err != nil {
522-
return fmt.Errorf("failed to get NGF deploymentID: %w", err)
526+
logger.Error(err, fmt.Sprintf("failed to get replica set for pod %v", podNSName))
527+
} else {
528+
installationID, err = telemetry.GetDeploymentID(replicaSet)
529+
if err != nil {
530+
logger.Error(err, "failed to get NGF installationID")
531+
}
523532
}
524533

525-
cfg.DeploymentContext = dataplane.DeploymentContext{
534+
depCtx := dataplane.DeploymentContext{
526535
Integration: "ngf",
527536
ClusterID: clusterInfo.ClusterID,
528537
ClusterNodeCount: clusterInfo.NodeCount,
529-
InstallationID: deploymentID,
538+
InstallationID: installationID,
530539
}
531540

532-
return nil
541+
return depCtx, nil
533542
}
534543

535544
// GetLatestConfiguration gets the latest configuration.

0 commit comments

Comments
 (0)