Skip to content

Commit

Permalink
[STORY-443] Add flag --no-letsencrypt when creating a domain
Browse files Browse the repository at this point in the history
  • Loading branch information
leo-scalingo committed Apr 19, 2024
1 parent 5af36f3 commit 61fe657
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 64 deletions.
85 changes: 69 additions & 16 deletions cmd/domains.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package cmd

import (
"os"

"github.com/urfave/cli/v2"
"gopkg.in/errgo.v1"

"github.com/Scalingo/cli/cmd/autocomplete"
"github.com/Scalingo/cli/detect"
"github.com/Scalingo/cli/domains"
"github.com/Scalingo/cli/utils"
scalingo "github.com/Scalingo/go-scalingo/v7"
)

var (
Expand Down Expand Up @@ -46,29 +50,48 @@ var (
Usage: "Add a custom domain to an application",
ArgsUsage: "domain",
Flags: []cli.Flag{&appFlag,
&cli.StringFlag{Name: "cert", Usage: "SSL Signed Certificate", Value: "domain.crt"},
&cli.StringFlag{Name: "key", Usage: "SSL Keypair", Value: "domain.key"},
&cli.StringFlag{Name: "cert", Usage: "SSL Signed Certificate"},
&cli.StringFlag{Name: "key", Usage: "SSL Keypair"},
&cli.BoolFlag{Name: "no-letsencrypt", Usage: "Disable automatic Let's Encrypt certificate generation", Value: false},
},
Description: CommandDescription{
Description: "Add a custom domain to an application",
Examples: []string{"scalingo --app my-app domains-add example.com"},
SeeAlso: []string{"domains", "domains-remove"},
Examples: []string{
"scalingo --app my-app domains-add example.com",
"scalingo --app my-app domains-add --cert ./cert.pem --key ./key.pem example.com",
"scalingo --app my-app domains-add --no-letsencrypt example.com",
},
SeeAlso: []string{"domains", "domains-remove"},
}.Render(),

Action: func(c *cli.Context) error {
currentApp := detect.CurrentApp(c)
utils.CheckForConsent(c.Context, currentApp, utils.ConsentTypeContainers)
var err error

if c.Args().Len() == 1 {
cert := c.String("cert")
if cert == "domain.crt" {
cert = ""
}
key := c.String("key")
if key == "domain.key" {
key = ""
certContent, keyContent, err := validateTLSParams(cert, key)
if err != nil {
errorQuit(c.Context, err)
}
err = domains.Add(c.Context, currentApp, c.Args().First(), cert, key)

params := scalingo.DomainsAddParams{
Name: c.Args().First(),
}
if certContent != "" {
params.TLSCert = &certContent
}
if keyContent != "" {
params.TLSKey = &keyContent
}
if c.Bool("no-letsencrypt") {
letsEncryptEnabled := false
params.LetsEncryptEnabled = &letsEncryptEnabled
}

err = domains.Add(c.Context, currentApp, params)

Check failure on line 94 in cmd/domains.go

View workflow job for this annotation

GitHub Actions / golangci-lint on a PR or from a tag

ineffectual assignment to err (ineffassign)
} else {
cli.ShowCommandHelp(c, "domains-add")
}
Expand Down Expand Up @@ -138,17 +161,23 @@ var (
Action: func(c *cli.Context) error {
currentApp := detect.CurrentApp(c)
utils.CheckForConsent(c.Context, currentApp, utils.ConsentTypeContainers)
var err error
if c.Args().Len() == 2 && c.Args().Slice()[1] == "disable" {
err = domains.DisableSSL(c.Context, currentApp, c.Args().First())
err := domains.DisableSSL(c.Context, currentApp, c.Args().First())
if err != nil {
errorQuit(c.Context, err)
}
} else if c.Args().Len() == 1 {
err = domains.EnableSSL(c.Context, currentApp, c.Args().First(), c.String("cert"), c.String("key"))
certContent, keyContent, err := validateTLSParams(c.String("cert"), c.String("key"))
if err != nil {
errorQuit(c.Context, err)
}
err = domains.EnableSSL(c.Context, currentApp, c.Args().First(), certContent, keyContent)
if err != nil {
errorQuit(c.Context, err)
}
} else {
cli.ShowCommandHelp(c, "domains-ssl")
}
if err != nil {
errorQuit(c.Context, err)
}
return nil
},
BashComplete: func(c *cli.Context) {
Expand Down Expand Up @@ -219,3 +248,27 @@ This domain is called the canonical domain. This command sets the canonical doma
},
}
)

func validateTLSParams(cert, key string) (string, string, error) {
if cert == "" && key == "" {
return "", "", nil
}

if cert == "" && key != "" {
return "", "", errgo.New("--cert <certificate path> should be defined")
}

if key == "" && cert != "" {
return "", "", errgo.New("--key <key path> should be defined")
}

certContent, err := os.ReadFile(cert)
if err != nil {
return "", "", errgo.Notef(err, "fail to read the TLS certificate")
}
keyContent, err := os.ReadFile(key)
if err != nil {
return "", "", errgo.Notef(err, "fail to read the private key")
}
return string(certContent), string(keyContent), nil
}
21 changes: 5 additions & 16 deletions domains/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,20 @@ package domains
import (
"context"

"gopkg.in/errgo.v1"

"github.com/Scalingo/cli/config"
"github.com/Scalingo/cli/io"
"github.com/Scalingo/go-scalingo/v7"
"github.com/Scalingo/go-utils/errors/v2"
)

func Add(ctx context.Context, app string, domain string, cert string, key string) error {
certContent, keyContent, err := validateSSL(cert, key)
if err != nil {
return errgo.Mask(err)
}

func Add(ctx context.Context, app string, params scalingo.DomainsAddParams) error {
c, err := config.ScalingoClient(ctx)
if err != nil {
return errgo.Notef(err, "fail to get Scalingo client")
return errors.Wrapf(ctx, err, "get Scalingo client")
}
d, err := c.DomainsAdd(ctx, app, scalingo.Domain{
Name: domain,
TLSCert: certContent,
TLSKey: keyContent,
})

d, err := c.DomainsAdd(ctx, app, params)
if err != nil {
return errgo.Mask(err)
return errors.Wrap(ctx, err, "add domain to application")
}

io.Status("Domain", d.Name, "has been created, access your app at the following URL:\n")
Expand Down
34 changes: 2 additions & 32 deletions domains/ssl.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package domains

import (
"context"
"os"

"gopkg.in/errgo.v1"

Expand All @@ -29,7 +28,7 @@ func DisableSSL(ctx context.Context, app string, domain string) error {
return nil
}

func EnableSSL(ctx context.Context, app, domain, certPath, keyPath string) error {
func EnableSSL(ctx context.Context, app, domain, cert, key string) error {
c, err := config.ScalingoClient(ctx)
if err != nil {
return errgo.Notef(err, "fail to get Scalingo client")
Expand All @@ -40,40 +39,11 @@ func EnableSSL(ctx context.Context, app, domain, certPath, keyPath string) error
return errgo.Notef(err, "fail to find the matching domain to enable SSL")
}

certContent, keyContent, err := validateSSL(certPath, keyPath)
if err != nil {
return errgo.Notef(err, "fail to validate the given certificate and key")
}

d, err = c.DomainSetCertificate(ctx, app, d.ID, certContent, keyContent)
d, err = c.DomainSetCertificate(ctx, app, d.ID, cert, key)
if err != nil {
return errgo.Notef(err, "fail to set the domain certificate")
}

io.Status("The certificate and key have been installed for " + d.Name + " (Validity: " + d.Validity.UTC().String() + ")")
return nil
}

func validateSSL(cert, key string) (string, string, error) {
if cert == "" && key == "" {
return "", "", nil
}

if cert == "" && key != "" {
return "", "", errgo.New("--cert <certificate path> should be defined")
}

if key == "" && cert != "" {
return "", "", errgo.New("--key <key path> should be defined")
}

certContent, err := os.ReadFile(cert)
if err != nil {
return "", "", errgo.Notef(err, "fail to read the TLS certificate")
}
keyContent, err := os.ReadFile(key)
if err != nil {
return "", "", errgo.Notef(err, "fail to read the private key")
}
return string(certContent), string(keyContent), nil
}

0 comments on commit 61fe657

Please sign in to comment.