diff --git a/command/ca/bootstrap.go b/command/ca/bootstrap.go index 5019c262..8fc9e429 100644 --- a/command/ca/bootstrap.go +++ b/command/ca/bootstrap.go @@ -7,10 +7,12 @@ import ( "github.com/pkg/errors" "github.com/smallstep/certificates/ca" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/config" "github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pki" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/utils" "github.com/urfave/cli" ) @@ -18,7 +20,7 @@ import ( func bootstrapCommand() cli.Command { return cli.Command{ Name: "bootstrap", - Action: cli.ActionFunc(bootstrapAction), + Action: command.ActionFunc(bootstrapAction), Usage: "initializes the environment to use the CA commands", UsageText: "**step ca bootstrap** [**--ca-url**=] [**--fingerprint**=]", Description: `**step ca bootstrap** downloads the root certificate from the certificate @@ -30,7 +32,7 @@ url, the root certificate location and its fingerprint. After the bootstrap, ca commands do not need to specify the flags --ca-url, --root or --fingerprint if we want to use the same environment.`, - Flags: []cli.Flag{caURLFlag, fingerprintFlag}, + Flags: []cli.Flag{caURLFlag, fingerprintFlag, flags.Force}, } } diff --git a/command/ca/certificate.go b/command/ca/certificate.go index 2a564440..f08c8c75 100644 --- a/command/ca/certificate.go +++ b/command/ca/certificate.go @@ -14,9 +14,11 @@ import ( "github.com/pkg/errors" "github.com/smallstep/certificates/api" "github.com/smallstep/certificates/ca" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pki" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/jose" "github.com/smallstep/cli/ui" "github.com/smallstep/cli/utils" @@ -26,7 +28,7 @@ import ( func newCertificateCommand() cli.Command { return cli.Command{ Name: "certificate", - Action: cli.ActionFunc(newCertificateAction), + Action: command.ActionFunc(newCertificateAction), Usage: "generates a new certificate pair signed by the root certificate", UsageText: `**step ca certificate** [**--token**=] [**--ca-url**=] [**--root**=] @@ -63,6 +65,7 @@ $ step ca certificate --token $TOKEN --not-after=1h internal.example.com interna rootFlag, notBeforeFlag, notAfterFlag, + flags.Force, }, } } @@ -70,7 +73,7 @@ $ step ca certificate --token $TOKEN --not-after=1h internal.example.com interna func signCertificateCommand() cli.Command { return cli.Command{ Name: "sign", - Action: cli.ActionFunc(signCertificateAction), + Action: command.ActionFunc(signCertificateAction), Usage: "generates a new certificate signing a certificate request", UsageText: `**step ca sign** [**--token**=] [**--ca-url**=] [**--root**=] @@ -104,6 +107,7 @@ $ step ca sign --token $TOKEN --not-after=1h internal.csr internal.crt rootFlag, notBeforeFlag, notAfterFlag, + flags.Force, }, } } @@ -111,7 +115,7 @@ $ step ca sign --token $TOKEN --not-after=1h internal.csr internal.crt func renewCertificateCommand() cli.Command { return cli.Command{ Name: "renew", - Action: cli.ActionFunc(renewCertificateAction), + Action: command.ActionFunc(renewCertificateAction), Usage: "renew a valid certificate", UsageText: `**step ca renew** [**--ca-url**=] [**--root**=] @@ -176,10 +180,7 @@ sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`, }, - cli.BoolFlag{ - Name: "f,force", - Usage: "Force the overwrite of files without asking.", - }, + flags.Force, }, } } @@ -464,7 +465,7 @@ func renewCertificateAction(ctx *cli.Context) error { } data := append(pem.EncodeToMemory(serverBlock), pem.EncodeToMemory(caBlock)...) - if err := utils.WriteFileForce(outFile, data, 0600, ctx.Bool("force")); err != nil { + if err := utils.WriteFile(outFile, data, 0600); err != nil { return errs.FileError(err, outFile) } diff --git a/command/ca/root.go b/command/ca/root.go index fea4f104..3fc01ed6 100644 --- a/command/ca/root.go +++ b/command/ca/root.go @@ -7,15 +7,17 @@ import ( "github.com/pkg/errors" "github.com/smallstep/certificates/ca" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/urfave/cli" ) func rootComand() cli.Command { return cli.Command{ Name: "root", - Action: cli.ActionFunc(rootAction), + Action: command.ActionFunc(rootAction), Usage: "downloads and validates the root certificate", UsageText: `**step ca root** [**--ca-url**=] [**--fingerprint**=]`, @@ -50,6 +52,7 @@ $ step ca root root_ca.crt \ Flags: []cli.Flag{ caURLFlag, fingerprintFlag, + flags.Force, }, } } diff --git a/command/ca/token.go b/command/ca/token.go index 4705ac65..62f30fce 100644 --- a/command/ca/token.go +++ b/command/ca/token.go @@ -10,9 +10,11 @@ import ( "github.com/pkg/errors" "github.com/smallstep/certificates/authority" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/crypto/pki" "github.com/smallstep/cli/crypto/randutil" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/jose" "github.com/smallstep/cli/token" "github.com/smallstep/cli/token/provision" @@ -30,7 +32,7 @@ type provisionersSelect struct { func newTokenCommand() cli.Command { return cli.Command{ Name: "token", - Action: cli.ActionFunc(newTokenAction), + Action: command.ActionFunc(newTokenAction), Usage: "generates an OTT granting access to the CA", UsageText: `**step ca token** [--**kid**=] [--**issuer**=] [**--ca-url**=] [**--root**=] @@ -117,6 +119,7 @@ the certificate authority.`, Usage: `Creates a token without contacting the certificate authority. Offline mode requires the flags <--kid>, <--issuer>, <--key>, <--ca-url>, and <--root>.`, }, + flags.Force, }, } } diff --git a/command/certificate/bundle.go b/command/certificate/bundle.go index 500d7b01..49097d18 100644 --- a/command/certificate/bundle.go +++ b/command/certificate/bundle.go @@ -5,14 +5,17 @@ import ( "io/ioutil" "github.com/pkg/errors" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" + "github.com/smallstep/cli/utils" "github.com/urfave/cli" ) func bundleCommand() cli.Command { return cli.Command{ Name: "bundle", - Action: cli.ActionFunc(bundleAction), + Action: command.ActionFunc(bundleAction), Usage: `bundle a certificate with intermediate certificate(s) needed for certificate path validation.`, UsageText: `**step certificate bundle** `, Description: `**step certificate bundle** bundles a certificate @@ -41,6 +44,7 @@ Bundle a certificate with the intermediate certificate authority (issuer): $ step certificate bundle foo.crt intermediate-ca.crt foo-bundle.crt ''' `, + Flags: []cli.Flag{flags.Force}, } } @@ -70,7 +74,7 @@ func bundleAction(ctx *cli.Context) error { } chainFile := ctx.Args().Get(2) - if err := ioutil.WriteFile(chainFile, + if err := utils.WriteFile(chainFile, append(pem.EncodeToMemory(crtBlock), pem.EncodeToMemory(caBlock)...), 0600); err != nil { return errs.FileError(err, chainFile) } diff --git a/command/certificate/create.go b/command/certificate/create.go index fbcac2ff..1995d36e 100644 --- a/command/certificate/create.go +++ b/command/certificate/create.go @@ -4,13 +4,14 @@ import ( "crypto/rand" "crypto/x509/pkix" "encoding/pem" - "os" "github.com/pkg/errors" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/crypto/keys" "github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/x509util" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" x509 "github.com/smallstep/cli/pkg/x509" "github.com/smallstep/cli/utils" "github.com/urfave/cli" @@ -19,7 +20,7 @@ import ( func createCommand() cli.Command { return cli.Command{ Name: "create", - Action: cli.ActionFunc(createAction), + Action: command.ActionFunc(createAction), Usage: "create a certificate or certificate signing request", UsageText: `**step certificate create** [**ca**=] [**ca-key**=] [**--csr**] @@ -192,6 +193,7 @@ unset, default is P-256 for EC keys and Ed25519 for OKP keys. : Ed25519 Curve `, }, + flags.Force, }, } } @@ -320,8 +322,7 @@ func createAction(ctx *cli.Context) error { return errs.NewError("unexpected type: %s", typ) } - if err := utils.WriteFile(crtFile, pem.EncodeToMemory(pubPEM), - os.FileMode(0600)); err != nil { + if err := utils.WriteFile(crtFile, pem.EncodeToMemory(pubPEM), 0600); err != nil { return errs.FileError(err, crtFile) } diff --git a/command/certificate/format.go b/command/certificate/format.go index f136be35..e7ea1771 100644 --- a/command/certificate/format.go +++ b/command/certificate/format.go @@ -7,7 +7,9 @@ import ( "os" "github.com/pkg/errors" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/utils" "github.com/urfave/cli" ) @@ -15,7 +17,7 @@ import ( func formatCommand() cli.Command { return cli.Command{ Name: "format", - Action: cli.ActionFunc(formatAction), + Action: command.ActionFunc(formatAction), Usage: `reformat certificate.`, UsageText: `**step certificate format** [**--out**=]`, Description: `**step certificate format** prints the certificate in @@ -55,6 +57,7 @@ $ step certificate format foo.pem --out foo.der Name: "out", Usage: `Path to write the reformatted result.`, }, + flags.Force, }, } } diff --git a/command/command.go b/command/command.go index 5519c9f2..a613a8a4 100644 --- a/command/command.go +++ b/command/command.go @@ -20,6 +20,7 @@ import ( const IgnoreEnvVar = "STEP_IGNORE_ENV_VAR" var cmds []cli.Command +var currentContext *cli.Context func init() { os.Unsetenv(IgnoreEnvVar) @@ -40,6 +41,19 @@ func Retrieve() []cli.Command { return cmds } +// ActionFunc returns a cli.ActionFunc that stores the context. +func ActionFunc(fn cli.ActionFunc) cli.ActionFunc { + return func(ctx *cli.Context) error { + currentContext = ctx + return fn(ctx) + } +} + +// IsForce returns if the force flag was passed +func IsForce() bool { + return currentContext != nil && currentContext.Bool("force") +} + // getConfigVars load the defaults.json file and sets the flags if they are not // already set or the EnvVar is set to IgnoreEnvVar. // diff --git a/command/crypto/change-pass.go b/command/crypto/change-pass.go index 5a021e0e..2f37f8e7 100644 --- a/command/crypto/change-pass.go +++ b/command/crypto/change-pass.go @@ -9,8 +9,10 @@ import ( "github.com/pkg/errors" "github.com/urfave/cli" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/jose" "github.com/smallstep/cli/utils" ) @@ -18,7 +20,7 @@ import ( func changePassCommand() cli.Command { return cli.Command{ Name: "change-pass", - Action: cli.ActionFunc(changePassAction), + Action: command.ActionFunc(changePassAction), Usage: "Change password of an encrypted private key (PEM or JWK format)", UsageText: `**step crypto change-pass** [**--out**=]`, Description: `**step crypto change-pass** extracts the private key from @@ -56,6 +58,7 @@ $ step crypto change-pass key.jwk --out new-key.jwk Name: "out,output-file", Usage: "The new encrypted key path. Default to overwriting the positional argument", }, + flags.Force, }, } } diff --git a/command/crypto/jwk/create.go b/command/crypto/jwk/create.go index 87ab83a6..66513396 100644 --- a/command/crypto/jwk/create.go +++ b/command/crypto/jwk/create.go @@ -9,8 +9,10 @@ import ( "os" "github.com/pkg/errors" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/crypto/randutil" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/jose" "github.com/smallstep/cli/utils" "github.com/urfave/cli" @@ -26,7 +28,7 @@ const ( func createCommand() cli.Command { return cli.Command{ Name: "create", - Action: cli.ActionFunc(createAction), + Action: command.ActionFunc(createAction), Usage: "create a JWK (JSON Web Key)", UsageText: `**step crypto jwk create** [**--kty**=] [**--alg**=] [**--use**=] @@ -397,12 +399,9 @@ existing instead of creating a new key.`, key material will be written to disk unencrypted. This is not recommended. Requires **--insecure** flag.`, }, - cli.BoolFlag{ - Name: "subtle", - }, - cli.BoolFlag{ - Name: "insecure", - }, + flags.Subtle, + flags.Insecure, + flags.Force, }, } } diff --git a/command/crypto/key/format.go b/command/crypto/key/format.go index 7e84b465..8a423be2 100644 --- a/command/crypto/key/format.go +++ b/command/crypto/key/format.go @@ -10,9 +10,10 @@ import ( "os" "github.com/pkg/errors" - + "github.com/smallstep/cli/command" "github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/utils" "github.com/urfave/cli" ) @@ -20,7 +21,7 @@ import ( func formatCommand() cli.Command { return cli.Command{ Name: "format", - Action: cli.ActionFunc(formatAction), + Action: command.ActionFunc(formatAction), Usage: `reformat certificate.`, UsageText: `**step crypto key format** [**--out**=]`, Description: `**step crypto key format** prints the key in @@ -66,6 +67,7 @@ $ step crypto key format foo-key.pem --out foo-key.der Name: "password-file", Usage: `location of file containing passphrase to decrypt private key`, }, + flags.Force, }, } } diff --git a/command/crypto/keypair.go b/command/crypto/keypair.go index 925df070..95f0648a 100644 --- a/command/crypto/keypair.go +++ b/command/crypto/keypair.go @@ -5,9 +5,11 @@ import ( "os" "github.com/pkg/errors" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/crypto/keys" "github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/jose" "github.com/smallstep/cli/utils" "github.com/urfave/cli" @@ -16,7 +18,7 @@ import ( func createKeyPairCommand() cli.Command { return cli.Command{ Name: "keypair", - Action: cli.ActionFunc(createAction), + Action: command.ActionFunc(createAction), Usage: "generate a public / private keypair in PEM format.", UsageText: `**step crypto keypair** [**--curve**=] [**--no-password**] [**--size**=] @@ -135,6 +137,7 @@ existing instead of creating a new key.`, Sensitive key material will be written to disk unencrypted. This is not recommended. Requires **--insecure** flag.`, }, + flags.Force, }, } } diff --git a/command/crypto/nacl/box.go b/command/crypto/nacl/box.go index a50b0b1b..8d17f6de 100644 --- a/command/crypto/nacl/box.go +++ b/command/crypto/nacl/box.go @@ -7,7 +7,9 @@ import ( "os" "github.com/pkg/errors" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/utils" "github.com/urfave/cli" "golang.org/x/crypto/nacl/box" @@ -93,7 +95,7 @@ message func boxKeypairCommand() cli.Command { return cli.Command{ Name: "keypair", - Action: cli.ActionFunc(boxKeypairAction), + Action: command.ActionFunc(boxKeypairAction), Usage: "generate a key for use with seal and open", UsageText: "**step crypto nacl box keypair** ", Description: `Generates a new public/private keypair suitable for use with seal and open. @@ -110,6 +112,7 @@ For examples, see **step help crypto nacl box**. : The path to write the encrypted private key.`, + Flags: []cli.Flag{flags.Force}, } } diff --git a/command/crypto/nacl/sign.go b/command/crypto/nacl/sign.go index b13e50bc..df340993 100644 --- a/command/crypto/nacl/sign.go +++ b/command/crypto/nacl/sign.go @@ -7,7 +7,9 @@ import ( "os" "github.com/pkg/errors" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/utils" "github.com/urfave/cli" "golang.org/x/crypto/nacl/sign" @@ -65,7 +67,7 @@ message func signKeypairCommand() cli.Command { return cli.Command{ Name: "keypair", - Action: cli.ActionFunc(signKeypairAction), + Action: command.ActionFunc(signKeypairAction), Usage: "generates a pair for use with sign and open", UsageText: "**step crypto nacl sign keypair** ", Description: `**step crypto nacl sign keypair** generates a secret key and a corresponding @@ -74,6 +76,7 @@ public key valid for verifying and signing messages. This command uses an implementation of NaCl's crypto_sign_keypair function. For examples, see **step help crypto nacl sign**.`, + Flags: []cli.Flag{flags.Force}, } } diff --git a/command/crypto/otp/generate.go b/command/crypto/otp/generate.go index 2754b5c4..561ed64e 100644 --- a/command/crypto/otp/generate.go +++ b/command/crypto/otp/generate.go @@ -8,7 +8,9 @@ import ( "github.com/pquerna/otp" "github.com/pquerna/otp/totp" + "github.com/smallstep/cli/command" "github.com/smallstep/cli/errs" + "github.com/smallstep/cli/flags" "github.com/smallstep/cli/utils" "github.com/urfave/cli" ) @@ -16,7 +18,7 @@ import ( func generateCommand() cli.Command { return cli.Command{ Name: "generate", - Action: cli.ActionFunc(generateAction), + Action: command.ActionFunc(generateAction), Usage: "one-time password", UsageText: `**step crypto otp generate**`, Description: `**step crypto otp generate** does TOTP and HTOP`, @@ -61,6 +63,7 @@ https://github.com/google/google-authenticator/wiki/Key-Uri-Format`, Name: "qr", Usage: `Write a QR code to the specified path`, }, + flags.Force, }, } } diff --git a/crypto/pki/pki.go b/crypto/pki/pki.go index b381e094..8a29ecb2 100644 --- a/crypto/pki/pki.go +++ b/crypto/pki/pki.go @@ -6,7 +6,6 @@ import ( "encoding/json" "encoding/pem" "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -300,7 +299,7 @@ func (p *PKI) Save() error { return errors.Wrapf(err, "error marshalling %s", p.config) } - if err = ioutil.WriteFile(p.config, b, 0666); err != nil { + if err = utils.WriteFile(p.config, b, 0666); err != nil { return errs.FileError(err, p.config) } diff --git a/flags/flags.go b/flags/flags.go index fa8c1351..72c43e7d 100644 --- a/flags/flags.go +++ b/flags/flags.go @@ -1,206 +1,21 @@ package flags import ( - "fmt" - "strings" - "github.com/urfave/cli" ) -// OldPasswordFile returns a flag for receiving an old password -func OldPasswordFile(usage string) cli.Flag { - if usage == "" { - usage = "The path to the `FILE` containing the old encryption password" - } - - return cli.StringFlag{ - Name: "old-password-file, o", - Usage: usage, - EnvVar: "STEP_OLD_PASSWORD_FILE", - } +// Subtle is the flag required for delicate operations. +var Subtle = cli.BoolFlag{ + Name: "subtle", } -// NewPasswordFile returns a flag for receiving a new password -func NewPasswordFile(usage string) cli.Flag { - if usage == "" { - usage = "The path to the `FILE` containing the new encryption password" - } - - return cli.StringFlag{ - Name: "new-password-file, n", - Usage: usage, - EnvVar: "STEP_NEW_PASSWORD_FILE", - } +// Insecure is the flag required on insecure operations +var Insecure = cli.BoolFlag{ + Name: "insecure", } -// Bits returns a flag for receiving the number of bits in generating a key -func Bits(usage string, value int) cli.Flag { - if usage == "" { - usage = "Number of bits used to generate the private key" - } - - if value == 0 { - value = 256 - } - - return cli.IntFlag{ - Name: "bits, b", - Usage: usage, - EnvVar: "STEP_BITS", - Value: value, - } -} - -// Action returns a flag for receiving an action out of several possibilities -func Action(usage string, possibilities []string, value string) cli.Flag { - usage = fmt.Sprintf("%s (Options: %s)", usage, strings.Join(possibilities, ", ")) - return cli.StringFlag{ - Name: "action, a", - Usage: usage, - EnvVar: "STEP_ACTION", - Value: value, - } -} - -// Type returns a flag for receiving a type of thing to create out of several -// possibilties -func Type(usage string, possibilities []string, value string) cli.Flag { - usage = fmt.Sprintf("%s (Options: %s)", usage, strings.Join(possibilities, ", ")) - return cli.StringFlag{ - Name: "type, t", - Usage: usage, - EnvVar: "STEP_TYPE", - Value: value, - } -} - -// Alg returns a flag for receiving the type of algorithm to use when performing an operation -func Alg(usage string, possibilities []string, value string) cli.Flag { - usage = fmt.Sprintf("%s (Options: %s)", usage, strings.Join(possibilities, ", ")) - return cli.StringFlag{ - Name: "alg", - Usage: usage, - EnvVar: "STEP_ALG", - Value: value, - } -} - -// RootCertificate returns a flag for specifying the path to a root certificate -func RootCertificate(usage string) cli.Flag { - if usage == "" { - usage = "The file `PATH` to the root certificate" - } - - return cli.StringFlag{ - Name: "root, r", - Usage: usage, - EnvVar: "STEP_ROOT_CERTIFICATE", - } -} - -// PasswordFile returns a flag for specifying the path to a file containing a password -func PasswordFile(usage string) cli.Flag { - if usage == "" { - usage = "Path to file containing a password" - } - - return cli.StringFlag{ - Name: "password-file, p", - Usage: usage, - EnvVar: "STEP_PASSWORD_FILE", - } -} - -// OutputFile returns a flag for specifying the path inwhich to write output too -func OutputFile(usage string) cli.Flag { - if usage == "" { - usage = "Path to where the output should be written" - } - - return cli.StringFlag{ - Name: "output-file, o", - Usage: usage, - EnvVar: "STEP_OUTPUT_FILE", - } -} - -// Number returns a flag for collecting the number of something to create -func Number(usage string) cli.Flag { - if usage == "" { - usage = "The `NUMBER` of entities to create" - } - - return cli.StringFlag{ - Name: "number, n", - Usage: usage, - EnvVar: "STEP_NUMBER", - } -} - -// Prefix returns a flag for prefixing to the name of an entity during creation -func Prefix(usage, value string) cli.Flag { - if usage == "" { - usage = "The `PREFIX` to apply to the names of all created entities" - } - - return cli.StringFlag{ - Name: "prefix, p", - Usage: usage, - Value: value, - EnvVar: "STEP_PREFIX", - } -} - -// OAuthProvider returns a flag for allowing the user to select an oauth provider -func OAuthProvider(usage string, providers []string, value string) cli.Flag { - usage = fmt.Sprintf("%s (Options: %s)", usage, strings.Join(providers, ", ")) - return cli.StringFlag{ - Name: "provider, idp", - Usage: usage, - Value: value, - EnvVar: "STEP_PROVIDER", - } -} - -// Email returns a flag allowing the user to specify their email -func Email(usage string) cli.Flag { - if usage == "" { - usage = "Email to use" - } - - return cli.StringFlag{ - Name: "email, e", - Usage: usage, - EnvVar: "STEP_EMAIL", - } -} - -// Console returns a flag allowing the user to specify whether or not they want -// to remain entirely in the console -func Console(usage string) cli.Flag { - if usage == "" { - usage = "Whether or not to remain entirely in the console to complete the action" - } - - return cli.BoolFlag{ - Name: "console, c", - Usage: usage, - EnvVar: "STEP_CONSOLE", - } -} - -// Limit returns a flag for limiting the results return by a command -func Limit(usage string, value int) cli.Flag { - if usage == "" { - usage = "The maximum `NUMBER` of results to return" - } - if value == 0 { - value = 10 - } - - return cli.IntFlag{ - Name: "limit, l", - Usage: usage, - Value: value, - } +// Force is a cli.Flag used to overwrite files. +var Force = cli.BoolFlag{ + Name: "f,force", + Usage: "Force the overwrite of files without asking.", } diff --git a/utils/write.go b/utils/write.go index ae6470db..aa70a36d 100644 --- a/utils/write.go +++ b/utils/write.go @@ -10,6 +10,7 @@ import ( "syscall" "github.com/pkg/errors" + "github.com/smallstep/cli/command" "golang.org/x/crypto/ssh/terminal" ) @@ -21,19 +22,12 @@ var ( ErrIsDir = errors.New("file is a directory") ) -// WriteFile wraps ioutil.WriteFile with a prompt to overwrite a file if the -// file exists. It returns ErrFileExists if the user picks to not overwrite -// the file. -func WriteFile(filename string, data []byte, perm os.FileMode) error { - return WriteFileForce(filename, data, perm, false) -} - -// WriteFileForce wraps ioutil.WriteFile with a prompt to overwrite a file if +// WriteFile wraps ioutil.WriteFile with a prompt to overwrite a file if // the file exists. It returns ErrFileExists if the user picks to not overwrite // the file. If force is set to true, the prompt will not be presented and the // file if exists will be overwritten. -func WriteFileForce(filename string, data []byte, perm os.FileMode, force bool) error { - if force { +func WriteFile(filename string, data []byte, perm os.FileMode) error { + if command.IsForce() { return ioutil.WriteFile(filename, data, perm) }