diff --git a/CHANGELOG.md b/CHANGELOG.md index ed0932409..0bf2e239c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,10 @@ ### Enhancements: +- feat(ngwaf): add `--autoEnableNewVirtualPatches` flag to `ngwaf workspace create` and `ngwaf workspace update` for Automated Virtual Patching, and show it in `ngwaf workspace get` ([#1953](https://github.com/fastly/cli/pull/1953)) + ### Dependencies: + - build(deps): `github.com/fastly/go-fastly` from v17.8.0 to v18.0.0 ([#1949](https://github.com/fastly/cli/pull/1949)) - build(deps): `golang.org/x/term` from 0.46.0 to 0.47.0 ([#1944](https://github.com/fastly/cli/pull/1944)) - build(deps): `golang.org/x/crypto` from 0.57.0 to 0.58.0 ([#1944](https://github.com/fastly/cli/pull/1944)) diff --git a/pkg/commands/ngwaf/workspace/create.go b/pkg/commands/ngwaf/workspace/create.go index f177a58fe..78b4dbb50 100644 --- a/pkg/commands/ngwaf/workspace/create.go +++ b/pkg/commands/ngwaf/workspace/create.go @@ -27,11 +27,12 @@ type CreateCommand struct { name string // Optional. - attackThresholds argparser.OptionalString - defaultBlockingCode argparser.OptionalInt - defaultRedirectURL argparser.OptionalString - clientIPHeaders argparser.OptionalString - ipAnonymization argparser.OptionalString + attackThresholds argparser.OptionalString + defaultBlockingCode argparser.OptionalInt + defaultRedirectURL argparser.OptionalString + clientIPHeaders argparser.OptionalString + ipAnonymization argparser.OptionalString + autoEnableVirtualPatches argparser.OptionalBool } // NewCreateCommand returns a usable command registered under the parent. @@ -54,6 +55,7 @@ func NewCreateCommand(parent argparser.Registerer, g *global.Data) *CreateComman c.CmdClause.Flag("defaultBlockingCode", "Default status code that is returned when a request to your web application is blocked.").Action(c.defaultBlockingCode.Set).IntVar(&c.defaultBlockingCode.Value) c.CmdClause.Flag("defaultRedirectURL", "Redirect url to be used if code 301 or 302 is used.").Action(c.defaultRedirectURL.Set).StringVar(&c.defaultRedirectURL.Value) c.CmdClause.Flag("ipAnonymization", "Agents will anonymize IP addresses according to the option selected.").Action(c.ipAnonymization.Set).StringVar(&c.ipAnonymization.Value) + c.CmdClause.Flag("autoEnableNewVirtualPatches", "Automatically enable, in block mode, virtual patches released after this setting is enabled. Virtual patches released before it was enabled are not changed. Use --no-autoEnableNewVirtualPatches to disable.").Action(c.autoEnableVirtualPatches.Set).BoolVar(&c.autoEnableVirtualPatches.Value) c.RegisterFlagBool(c.JSONFlag()) return &c @@ -88,6 +90,9 @@ func (c *CreateCommand) Exec(_ io.Reader, out io.Writer) error { if c.ipAnonymization.WasSet { input.IPAnonymization = &c.ipAnonymization.Value } + if c.autoEnableVirtualPatches.WasSet { + input.AutoEnableNewVirtualPatches = &c.autoEnableVirtualPatches.Value + } fc, ok := c.Globals.APIClient.(*fastly.Client) if !ok { diff --git a/pkg/commands/ngwaf/workspace/update.go b/pkg/commands/ngwaf/workspace/update.go index 46d25d8c8..19f8ea7c2 100644 --- a/pkg/commands/ngwaf/workspace/update.go +++ b/pkg/commands/ngwaf/workspace/update.go @@ -25,14 +25,15 @@ type UpdateCommand struct { workspaceID string // Optional. - description argparser.OptionalString - blockingMode argparser.OptionalString - name argparser.OptionalString - attackThresholds argparser.OptionalString - defaultBlockingCode argparser.OptionalInt - defaultRedirectURL argparser.OptionalString - clientIPHeaders argparser.OptionalString - ipAnonymization argparser.OptionalString + description argparser.OptionalString + blockingMode argparser.OptionalString + name argparser.OptionalString + attackThresholds argparser.OptionalString + defaultBlockingCode argparser.OptionalInt + defaultRedirectURL argparser.OptionalString + clientIPHeaders argparser.OptionalString + ipAnonymization argparser.OptionalString + autoEnableVirtualPatches argparser.OptionalBool } // NewUpdateCommand returns a usable command registered under the parent. @@ -56,6 +57,7 @@ func NewUpdateCommand(parent argparser.Registerer, g *global.Data) *UpdateComman c.CmdClause.Flag("defaultBlockingCode", "Default status code that is returned when a request to your web application is blocked.").Action(c.defaultBlockingCode.Set).IntVar(&c.defaultBlockingCode.Value) c.CmdClause.Flag("defaultRedirectURL", "Redirect url to be used if code 301 or 302 is used.").Action(c.defaultRedirectURL.Set).StringVar(&c.defaultRedirectURL.Value) c.CmdClause.Flag("ipAnonymization", "Agents will anonymize IP addresses according to the option selected.").Action(c.ipAnonymization.Set).StringVar(&c.ipAnonymization.Value) + c.CmdClause.Flag("autoEnableNewVirtualPatches", "Automatically enable, in block mode, virtual patches released after this setting is enabled. Virtual patches released before it was enabled are not changed. Use --no-autoEnableNewVirtualPatches to disable.").Action(c.autoEnableVirtualPatches.Set).BoolVar(&c.autoEnableVirtualPatches.Value) c.RegisterFlagBool(c.JSONFlag()) return &c @@ -99,6 +101,9 @@ func (c *UpdateCommand) Exec(_ io.Reader, out io.Writer) error { if c.ipAnonymization.WasSet { input.IPAnonymization = &c.ipAnonymization.Value } + if c.autoEnableVirtualPatches.WasSet { + input.AutoEnableNewVirtualPatches = &c.autoEnableVirtualPatches.Value + } fc, ok := c.Globals.APIClient.(*fastly.Client) if !ok { diff --git a/pkg/commands/ngwaf/workspace/workspace_test.go b/pkg/commands/ngwaf/workspace/workspace_test.go index 8c84f707d..1835c78fb 100644 --- a/pkg/commands/ngwaf/workspace/workspace_test.go +++ b/pkg/commands/ngwaf/workspace/workspace_test.go @@ -82,6 +82,20 @@ func TestWorkspacesCreate(t *testing.T) { }, WantOutput: fstfmt.Success("Created workspace '%s' (workspace-id: %s)", workspaceName, workspaceID), }, + { + Name: "validate --autoEnableNewVirtualPatches flag", + Args: fmt.Sprintf("--description %s --name %s --blockingMode %s --autoEnableNewVirtualPatches", workspaceDescription, workspaceName, workspaceMode), + Client: &http.Client{ + Transport: &testutil.MockRoundTripper{ + Response: &http.Response{ + StatusCode: http.StatusOK, + Status: http.StatusText(http.StatusOK), + Body: io.NopCloser(bytes.NewReader(testutil.GenJSON(workspace))), + }, + }, + }, + WantOutput: fstfmt.Success("Created workspace '%s' (workspace-id: %s)", workspaceName, workspaceID), + }, { Name: "validate optional --json flag", Args: fmt.Sprintf("--description %s --name %s --blockingMode %s --clientIPHeaders %s --json", workspaceDescription, workspaceName, workspaceMode, workspaceClientIPHeaders), diff --git a/pkg/text/workspace.go b/pkg/text/workspace.go index b672b14f1..d6c03d4d0 100644 --- a/pkg/text/workspace.go +++ b/pkg/text/workspace.go @@ -32,6 +32,9 @@ func PrintWorkspace(out io.Writer, workspaceToPrint *workspaces.Workspace) { if workspaceToPrint.IPAnonymization != "" { fmt.Fprintf(out, "IP Anonymization: %s\n", workspaceToPrint.IPAnonymization) } + if workspaceToPrint.AutoEnableNewVirtualPatches != nil { + fmt.Fprintf(out, "Auto Enable New Virtual Patches: %t\n", *workspaceToPrint.AutoEnableNewVirtualPatches) + } fmt.Fprintf(out, "Updated (UTC): %s\n", workspaceToPrint.UpdatedAt.UTC().Format(time.Format)) }