diff --git a/CHANGELOG.md b/CHANGELOG.md index 70b858a12..100b8a360 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] ### Breaking: +- feat(backend): `backend create` now enables SSL by default. Backends will use HTTPS on port 443 unless explicitly disabled with `--no-use-ssl`. Users who need non-SSL backends must now use the `--no-use-ssl` flag and specify `--port`. ### Enhancements: - build(dockerfile-rust): add wasm tools to the rust docker container ([#1552](https://github.com/fastly/cli/pull/1552)) diff --git a/pkg/app/metadata.json b/pkg/app/metadata.json index 12cf578d7..e8ff3d0e7 100644 --- a/pkg/app/metadata.json +++ b/pkg/app/metadata.json @@ -159,8 +159,18 @@ "examples": [ { "cmd": "fastly backend create --name example --address example.com --version active --autoclone", - "description": "Create a backend with a hostname assigned to the `--address` flag. The `--override-host`, `--ssl-cert-hostname` and `--ssl-sni-hostname` will default to the same hostname assigned to `--address`.", + "description": "Create a backend with a hostname assigned to the `--address` flag. The `--override-host`, `--ssl-cert-hostname` and `--ssl-sni-hostname` will default to the same hostname assigned to `--address`. SSL is enabled by default with port 443.", "title": "Create a backend on the currently active service version" + }, + { + "cmd": "fastly backend create --name my_backend --address http-me.fastly.dev --version latest --autoclone", + "description": "Create a backend with SSL enabled by default. The backend will use port 443 unless explicitly specified with `--port`.", + "title": "Create a backend with default SSL settings" + }, + { + "cmd": "fastly backend create --name my_backend --address http-me.fastly.dev --version latest --autoclone --no-use-ssl --port 80", + "description": "Create a backend without SSL using the `--no-use-ssl` flag. When SSL is disabled, you should explicitly specify the port.", + "title": "Create a backend without SSL" } ], "apis": [ diff --git a/pkg/commands/backend/backend_test.go b/pkg/commands/backend/backend_test.go index 8f3307c00..8755b8239 100644 --- a/pkg/commands/backend/backend_test.go +++ b/pkg/commands/backend/backend_test.go @@ -205,6 +205,32 @@ func TestBackendCreate(t *testing.T) { }, WantError: "'prefer-ipv6' flag must be one of the following [true, false]", }, + // The following test verifies that --use-ssl defaults to true and port defaults to 443 + { + Args: "--service-id 123 --version 3 --address http-me.fastly.dev --name my_backend", + API: mock.API{ + ListVersionsFn: testutil.ListVersions, + CreateBackendFn: createBackendWithSSL(true, 443), + }, + WantOutput: "Created backend my_backend (service 123 version 3)", + }, + // The following test verifies that --no-use-ssl disables SSL + { + Args: "--service-id 123 --version 3 --address http-me.fastly.dev --name my_backend --no-use-ssl --port 80", + API: mock.API{ + ListVersionsFn: testutil.ListVersions, + CreateBackendFn: createBackendWithSSL(false, 80), + }, + WantOutput: "Created backend my_backend (service 123 version 3)", + }, + // The following test verifies that both --use-ssl and --no-use-ssl results in an error + { + Args: "--service-id 123 --version 3 --address http-me.fastly.dev --name my_backend --use-ssl --no-use-ssl", + API: mock.API{ + ListVersionsFn: testutil.ListVersions, + }, + WantError: "cannot specify both --use-ssl and --no-use-ssl", + }, } testutil.RunCLIScenarios(t, []string{root.CommandName, "create"}, scenarios) } @@ -454,6 +480,18 @@ func createBackendWithPort(wantPort int) func(_ context.Context, _ *fastly.Creat } } +func createBackendWithSSL(wantSSL bool, wantPort int) func(_ context.Context, _ *fastly.CreateBackendInput) (*fastly.Backend, error) { + return func(ctx context.Context, i *fastly.CreateBackendInput) (*fastly.Backend, error) { + useSSL := i.UseSSL != nil && bool(*i.UseSSL) + port := i.Port != nil && *i.Port == wantPort + + if useSSL == wantSSL && port { + return createBackendOK(ctx, i) + } + return createBackendError(ctx, i) + } +} + func listBackendsOK(_ context.Context, i *fastly.ListBackendsInput) ([]*fastly.Backend, error) { return []*fastly.Backend{ { diff --git a/pkg/commands/backend/create.go b/pkg/commands/backend/create.go index 878602683..5e2b67293 100644 --- a/pkg/commands/backend/create.go +++ b/pkg/commands/backend/create.go @@ -56,6 +56,7 @@ type CreateCommand struct { tcpKaTime argparser.OptionalInt httpKaTime argparser.OptionalInt useSSL argparser.OptionalBool + noUseSSL argparser.OptionalBool weight argparser.OptionalInt } @@ -123,7 +124,8 @@ func NewCreateCommand(parent argparser.Registerer, g *global.Data) *CreateComman c.CmdClause.Flag("tcp-ka-probes", "Configure how many unacknowledged TCP keepalive probes to send before considering the connection dead.").Action(c.tcpKaProbes.Set).IntVar(&c.tcpKaProbes.Value) c.CmdClause.Flag("tcp-ka-time", "Configure how long to wait after the last sent data before sending TCP keepalive probes.").Action(c.tcpKaTime.Set).IntVar(&c.tcpKaTime.Value) c.CmdClause.Flag("http-ka-time", "Configure how long to keep idle HTTP keepalive connections in the connection pool.").Action(c.httpKaTime.Set).IntVar(&c.httpKaTime.Value) - c.CmdClause.Flag("use-ssl", "Whether or not to use SSL to reach the backend").Action(c.useSSL.Set).BoolVar(&c.useSSL.Value) + c.CmdClause.Flag("use-ssl", "Whether or not to use SSL to reach the backend (default: true)").Action(c.useSSL.Set).BoolVar(&c.useSSL.Value) + c.CmdClause.Flag("no-use-ssl", "Disable SSL for the backend (overrides default)").Action(c.noUseSSL.Set).BoolVar(&c.noUseSSL.Value) c.CmdClause.Flag("weight", "Weight used to load balance this backend against others").Action(c.weight.Set).IntVar(&c.weight.Value) return &c @@ -268,15 +270,37 @@ func (c *CreateCommand) Exec(_ io.Reader, out io.Writer) error { if c.weight.WasSet { input.Weight = &c.weight.Value } + // Set UseSSL: handle --use-ssl, --no-use-ssl, and default behavior + if c.noUseSSL.WasSet && c.useSSL.WasSet { + err := errors.New("cannot specify both --use-ssl and --no-use-ssl") + c.Globals.ErrLog.Add(err) + return err + } + switch { + case c.noUseSSL.WasSet: + input.UseSSL = fastly.ToPointer(fastly.Compatibool(false)) + case c.useSSL.WasSet: + input.UseSSL = fastly.ToPointer(fastly.Compatibool(c.useSSL.Value)) + default: + // Default to true + input.UseSSL = fastly.ToPointer(fastly.Compatibool(true)) + } switch { case c.port.WasSet: input.Port = &c.port.Value + case c.noUseSSL.WasSet: + // If --no-use-ssl is set, don't set a default port + // User should specify --port explicitly case c.useSSL.WasSet && c.useSSL.Value: + // If use-ssl is explicitly set to true and no port is specified, use 443 if c.Globals.Flags.Verbose { text.Warning(out, "Use-ssl was set but no port was specified, using default port 443\n\n") } input.Port = fastly.ToPointer(443) + case !c.useSSL.WasSet && !c.noUseSSL.WasSet: + // If neither flag is set (defaults to SSL true), use 443 + input.Port = fastly.ToPointer(443) } if input.Address != nil && !c.overrideHost.WasSet && !c.sslCertHostname.WasSet && !c.sslSNIHostname.WasSet {