1
0
mirror of https://github.com/smallstep/cli.git synced 2025-08-07 16:02:54 +03:00

Add flag --force on all commands using utils.WriteFile

Fixes smallstep/ca-component#121
This commit is contained in:
Mariano Cano
2018-11-27 17:36:27 -08:00
parent 1d001f5e28
commit 0cface6e9b
18 changed files with 95 additions and 240 deletions

View File

@@ -7,10 +7,12 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/certificates/ca" "github.com/smallstep/certificates/ca"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/config" "github.com/smallstep/cli/config"
"github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/crypto/pki" "github.com/smallstep/cli/crypto/pki"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@@ -18,7 +20,7 @@ import (
func bootstrapCommand() cli.Command { func bootstrapCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "bootstrap", Name: "bootstrap",
Action: cli.ActionFunc(bootstrapAction), Action: command.ActionFunc(bootstrapAction),
Usage: "initializes the environment to use the CA commands", Usage: "initializes the environment to use the CA commands",
UsageText: "**step ca bootstrap** [**--ca-url**=<uri>] [**--fingerprint**=<fingerprint>]", UsageText: "**step ca bootstrap** [**--ca-url**=<uri>] [**--fingerprint**=<fingerprint>]",
Description: `**step ca bootstrap** downloads the root certificate from the certificate 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 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.`, --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},
} }
} }

View File

@@ -14,9 +14,11 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/certificates/api" "github.com/smallstep/certificates/api"
"github.com/smallstep/certificates/ca" "github.com/smallstep/certificates/ca"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/crypto/pki" "github.com/smallstep/cli/crypto/pki"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/jose" "github.com/smallstep/cli/jose"
"github.com/smallstep/cli/ui" "github.com/smallstep/cli/ui"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
@@ -26,7 +28,7 @@ import (
func newCertificateCommand() cli.Command { func newCertificateCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "certificate", Name: "certificate",
Action: cli.ActionFunc(newCertificateAction), Action: command.ActionFunc(newCertificateAction),
Usage: "generates a new certificate pair signed by the root certificate", Usage: "generates a new certificate pair signed by the root certificate",
UsageText: `**step ca certificate** <hostname> <crt-file> <key-file> UsageText: `**step ca certificate** <hostname> <crt-file> <key-file>
[**--token**=<token>] [**--ca-url**=<uri>] [**--root**=<file>] [**--token**=<token>] [**--ca-url**=<uri>] [**--root**=<file>]
@@ -63,6 +65,7 @@ $ step ca certificate --token $TOKEN --not-after=1h internal.example.com interna
rootFlag, rootFlag,
notBeforeFlag, notBeforeFlag,
notAfterFlag, notAfterFlag,
flags.Force,
}, },
} }
} }
@@ -70,7 +73,7 @@ $ step ca certificate --token $TOKEN --not-after=1h internal.example.com interna
func signCertificateCommand() cli.Command { func signCertificateCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "sign", Name: "sign",
Action: cli.ActionFunc(signCertificateAction), Action: command.ActionFunc(signCertificateAction),
Usage: "generates a new certificate signing a certificate request", Usage: "generates a new certificate signing a certificate request",
UsageText: `**step ca sign** <csr-file> <crt-file> UsageText: `**step ca sign** <csr-file> <crt-file>
[**--token**=<token>] [**--ca-url**=<uri>] [**--root**=<file>] [**--token**=<token>] [**--ca-url**=<uri>] [**--root**=<file>]
@@ -104,6 +107,7 @@ $ step ca sign --token $TOKEN --not-after=1h internal.csr internal.crt
rootFlag, rootFlag,
notBeforeFlag, notBeforeFlag,
notAfterFlag, notAfterFlag,
flags.Force,
}, },
} }
} }
@@ -111,7 +115,7 @@ $ step ca sign --token $TOKEN --not-after=1h internal.csr internal.crt
func renewCertificateCommand() cli.Command { func renewCertificateCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "renew", Name: "renew",
Action: cli.ActionFunc(renewCertificateAction), Action: command.ActionFunc(renewCertificateAction),
Usage: "renew a valid certificate", Usage: "renew a valid certificate",
UsageText: `**step ca renew** <crt-file> <key-file> UsageText: `**step ca renew** <crt-file> <key-file>
[**--ca-url**=<uri>] [**--root**=<file>] [**--ca-url**=<uri>] [**--root**=<file>]
@@ -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", as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms",
"s", "m", "h".`, "s", "m", "h".`,
}, },
cli.BoolFlag{ flags.Force,
Name: "f,force",
Usage: "Force the overwrite of files without asking.",
},
}, },
} }
} }
@@ -464,7 +465,7 @@ func renewCertificateAction(ctx *cli.Context) error {
} }
data := append(pem.EncodeToMemory(serverBlock), pem.EncodeToMemory(caBlock)...) 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) return errs.FileError(err, outFile)
} }

View File

@@ -7,15 +7,17 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/certificates/ca" "github.com/smallstep/certificates/ca"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
func rootComand() cli.Command { func rootComand() cli.Command {
return cli.Command{ return cli.Command{
Name: "root", Name: "root",
Action: cli.ActionFunc(rootAction), Action: command.ActionFunc(rootAction),
Usage: "downloads and validates the root certificate", Usage: "downloads and validates the root certificate",
UsageText: `**step ca root** <root-file> UsageText: `**step ca root** <root-file>
[**--ca-url**=<uri>] [**--fingerprint**=<fingerprint>]`, [**--ca-url**=<uri>] [**--fingerprint**=<fingerprint>]`,
@@ -50,6 +52,7 @@ $ step ca root root_ca.crt \
Flags: []cli.Flag{ Flags: []cli.Flag{
caURLFlag, caURLFlag,
fingerprintFlag, fingerprintFlag,
flags.Force,
}, },
} }
} }

View File

@@ -10,9 +10,11 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/certificates/authority" "github.com/smallstep/certificates/authority"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/crypto/pki" "github.com/smallstep/cli/crypto/pki"
"github.com/smallstep/cli/crypto/randutil" "github.com/smallstep/cli/crypto/randutil"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/jose" "github.com/smallstep/cli/jose"
"github.com/smallstep/cli/token" "github.com/smallstep/cli/token"
"github.com/smallstep/cli/token/provision" "github.com/smallstep/cli/token/provision"
@@ -30,7 +32,7 @@ type provisionersSelect struct {
func newTokenCommand() cli.Command { func newTokenCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "token", Name: "token",
Action: cli.ActionFunc(newTokenAction), Action: command.ActionFunc(newTokenAction),
Usage: "generates an OTT granting access to the CA", Usage: "generates an OTT granting access to the CA",
UsageText: `**step ca token** <hostname> UsageText: `**step ca token** <hostname>
[--**kid**=<kid>] [--**issuer**=<issuer>] [**--ca-url**=<uri>] [**--root**=<file>] [--**kid**=<kid>] [--**issuer**=<issuer>] [**--ca-url**=<uri>] [**--root**=<file>]
@@ -117,6 +119,7 @@ the certificate authority.`,
Usage: `Creates a token without contacting the certificate authority. Offline mode Usage: `Creates a token without contacting the certificate authority. Offline mode
requires the flags <--kid>, <--issuer>, <--key>, <--ca-url>, and <--root>.`, requires the flags <--kid>, <--issuer>, <--key>, <--ca-url>, and <--root>.`,
}, },
flags.Force,
}, },
} }
} }

View File

@@ -5,14 +5,17 @@ import (
"io/ioutil" "io/ioutil"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
func bundleCommand() cli.Command { func bundleCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "bundle", Name: "bundle",
Action: cli.ActionFunc(bundleAction), Action: command.ActionFunc(bundleAction),
Usage: `bundle a certificate with intermediate certificate(s) needed for certificate path validation.`, Usage: `bundle a certificate with intermediate certificate(s) needed for certificate path validation.`,
UsageText: `**step certificate bundle** <crt_file> <ca> <bundle_file>`, UsageText: `**step certificate bundle** <crt_file> <ca> <bundle_file>`,
Description: `**step certificate bundle** bundles a certificate 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 $ 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) 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 { append(pem.EncodeToMemory(crtBlock), pem.EncodeToMemory(caBlock)...), 0600); err != nil {
return errs.FileError(err, chainFile) return errs.FileError(err, chainFile)
} }

View File

@@ -4,13 +4,14 @@ import (
"crypto/rand" "crypto/rand"
"crypto/x509/pkix" "crypto/x509/pkix"
"encoding/pem" "encoding/pem"
"os"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/crypto/keys" "github.com/smallstep/cli/crypto/keys"
"github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/crypto/x509util" "github.com/smallstep/cli/crypto/x509util"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
x509 "github.com/smallstep/cli/pkg/x509" x509 "github.com/smallstep/cli/pkg/x509"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
@@ -19,7 +20,7 @@ import (
func createCommand() cli.Command { func createCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "create", Name: "create",
Action: cli.ActionFunc(createAction), Action: command.ActionFunc(createAction),
Usage: "create a certificate or certificate signing request", Usage: "create a certificate or certificate signing request",
UsageText: `**step certificate create** <subject> <crt_file> <key_file> UsageText: `**step certificate create** <subject> <crt_file> <key_file>
[**ca**=<issuer-cert>] [**ca-key**=<issuer-key>] [**--csr**] [**ca**=<issuer-cert>] [**ca-key**=<issuer-key>] [**--csr**]
@@ -192,6 +193,7 @@ unset, default is P-256 for EC keys and Ed25519 for OKP keys.
: Ed25519 Curve : Ed25519 Curve
`, `,
}, },
flags.Force,
}, },
} }
} }
@@ -320,8 +322,7 @@ func createAction(ctx *cli.Context) error {
return errs.NewError("unexpected type: %s", typ) return errs.NewError("unexpected type: %s", typ)
} }
if err := utils.WriteFile(crtFile, pem.EncodeToMemory(pubPEM), if err := utils.WriteFile(crtFile, pem.EncodeToMemory(pubPEM), 0600); err != nil {
os.FileMode(0600)); err != nil {
return errs.FileError(err, crtFile) return errs.FileError(err, crtFile)
} }

View File

@@ -7,7 +7,9 @@ import (
"os" "os"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@@ -15,7 +17,7 @@ import (
func formatCommand() cli.Command { func formatCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "format", Name: "format",
Action: cli.ActionFunc(formatAction), Action: command.ActionFunc(formatAction),
Usage: `reformat certificate.`, Usage: `reformat certificate.`,
UsageText: `**step certificate format** <crt_file> [**--out**=<path>]`, UsageText: `**step certificate format** <crt_file> [**--out**=<path>]`,
Description: `**step certificate format** prints the certificate in Description: `**step certificate format** prints the certificate in
@@ -55,6 +57,7 @@ $ step certificate format foo.pem --out foo.der
Name: "out", Name: "out",
Usage: `Path to write the reformatted result.`, Usage: `Path to write the reformatted result.`,
}, },
flags.Force,
}, },
} }
} }

View File

@@ -20,6 +20,7 @@ import (
const IgnoreEnvVar = "STEP_IGNORE_ENV_VAR" const IgnoreEnvVar = "STEP_IGNORE_ENV_VAR"
var cmds []cli.Command var cmds []cli.Command
var currentContext *cli.Context
func init() { func init() {
os.Unsetenv(IgnoreEnvVar) os.Unsetenv(IgnoreEnvVar)
@@ -40,6 +41,19 @@ func Retrieve() []cli.Command {
return cmds 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 // getConfigVars load the defaults.json file and sets the flags if they are not
// already set or the EnvVar is set to IgnoreEnvVar. // already set or the EnvVar is set to IgnoreEnvVar.
// //

View File

@@ -9,8 +9,10 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli" "github.com/urfave/cli"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/jose" "github.com/smallstep/cli/jose"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
) )
@@ -18,7 +20,7 @@ import (
func changePassCommand() cli.Command { func changePassCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "change-pass", Name: "change-pass",
Action: cli.ActionFunc(changePassAction), Action: command.ActionFunc(changePassAction),
Usage: "Change password of an encrypted private key (PEM or JWK format)", Usage: "Change password of an encrypted private key (PEM or JWK format)",
UsageText: `**step crypto change-pass** <key-file> [**--out**=<file>]`, UsageText: `**step crypto change-pass** <key-file> [**--out**=<file>]`,
Description: `**step crypto change-pass** extracts the private key from 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", Name: "out,output-file",
Usage: "The <file> new encrypted key path. Default to overwriting the <key> positional argument", Usage: "The <file> new encrypted key path. Default to overwriting the <key> positional argument",
}, },
flags.Force,
}, },
} }
} }

View File

@@ -9,8 +9,10 @@ import (
"os" "os"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/crypto/randutil" "github.com/smallstep/cli/crypto/randutil"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/jose" "github.com/smallstep/cli/jose"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
@@ -26,7 +28,7 @@ const (
func createCommand() cli.Command { func createCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "create", Name: "create",
Action: cli.ActionFunc(createAction), Action: command.ActionFunc(createAction),
Usage: "create a JWK (JSON Web Key)", Usage: "create a JWK (JSON Web Key)",
UsageText: `**step crypto jwk create** <public-jwk-file> <private-jwk-file> UsageText: `**step crypto jwk create** <public-jwk-file> <private-jwk-file>
[**--kty**=<type>] [**--alg**=<algorithm>] [**--use**=<use>] [**--kty**=<type>] [**--alg**=<algorithm>] [**--use**=<use>]
@@ -397,12 +399,9 @@ existing <pem-file> instead of creating a new key.`,
key material will be written to disk unencrypted. This is not key material will be written to disk unencrypted. This is not
recommended. Requires **--insecure** flag.`, recommended. Requires **--insecure** flag.`,
}, },
cli.BoolFlag{ flags.Subtle,
Name: "subtle", flags.Insecure,
}, flags.Force,
cli.BoolFlag{
Name: "insecure",
},
}, },
} }
} }

View File

@@ -10,9 +10,10 @@ import (
"os" "os"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@@ -20,7 +21,7 @@ import (
func formatCommand() cli.Command { func formatCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "format", Name: "format",
Action: cli.ActionFunc(formatAction), Action: command.ActionFunc(formatAction),
Usage: `reformat certificate.`, Usage: `reformat certificate.`,
UsageText: `**step crypto key format** <key_file> [**--out**=<path>]`, UsageText: `**step crypto key format** <key_file> [**--out**=<path>]`,
Description: `**step crypto key format** prints the key in 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", Name: "password-file",
Usage: `location of file containing passphrase to decrypt private key`, Usage: `location of file containing passphrase to decrypt private key`,
}, },
flags.Force,
}, },
} }
} }

View File

@@ -5,9 +5,11 @@ import (
"os" "os"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/crypto/keys" "github.com/smallstep/cli/crypto/keys"
"github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/jose" "github.com/smallstep/cli/jose"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
@@ -16,7 +18,7 @@ import (
func createKeyPairCommand() cli.Command { func createKeyPairCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "keypair", Name: "keypair",
Action: cli.ActionFunc(createAction), Action: command.ActionFunc(createAction),
Usage: "generate a public / private keypair in PEM format.", Usage: "generate a public / private keypair in PEM format.",
UsageText: `**step crypto keypair** <pub_file> <priv_file> UsageText: `**step crypto keypair** <pub_file> <priv_file>
[**--curve**=<curve>] [**--no-password**] [**--size**=<size>] [**--curve**=<curve>] [**--no-password**] [**--size**=<size>]
@@ -135,6 +137,7 @@ existing <jwk-file> instead of creating a new key.`,
Sensitive key material will be written to disk unencrypted. This is not Sensitive key material will be written to disk unencrypted. This is not
recommended. Requires **--insecure** flag.`, recommended. Requires **--insecure** flag.`,
}, },
flags.Force,
}, },
} }
} }

View File

@@ -7,7 +7,9 @@ import (
"os" "os"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
"golang.org/x/crypto/nacl/box" "golang.org/x/crypto/nacl/box"
@@ -93,7 +95,7 @@ message
func boxKeypairCommand() cli.Command { func boxKeypairCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "keypair", Name: "keypair",
Action: cli.ActionFunc(boxKeypairAction), Action: command.ActionFunc(boxKeypairAction),
Usage: "generate a key for use with seal and open", Usage: "generate a key for use with seal and open",
UsageText: "**step crypto nacl box keypair** <pub-file> <priv-file>", UsageText: "**step crypto nacl box keypair** <pub-file> <priv-file>",
Description: `Generates a new public/private keypair suitable for use with seal and open. 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**.
<priv-file> <priv-file>
: The path to write the encrypted private key.`, : The path to write the encrypted private key.`,
Flags: []cli.Flag{flags.Force},
} }
} }

View File

@@ -7,7 +7,9 @@ import (
"os" "os"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
"golang.org/x/crypto/nacl/sign" "golang.org/x/crypto/nacl/sign"
@@ -65,7 +67,7 @@ message
func signKeypairCommand() cli.Command { func signKeypairCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "keypair", Name: "keypair",
Action: cli.ActionFunc(signKeypairAction), Action: command.ActionFunc(signKeypairAction),
Usage: "generates a pair for use with sign and open", Usage: "generates a pair for use with sign and open",
UsageText: "**step crypto nacl sign keypair** <pub-file> <priv-file>", UsageText: "**step crypto nacl sign keypair** <pub-file> <priv-file>",
Description: `**step crypto nacl sign keypair** generates a secret key and a corresponding 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. This command uses an implementation of NaCl's crypto_sign_keypair function.
For examples, see **step help crypto nacl sign**.`, For examples, see **step help crypto nacl sign**.`,
Flags: []cli.Flag{flags.Force},
} }
} }

View File

@@ -8,7 +8,9 @@ import (
"github.com/pquerna/otp" "github.com/pquerna/otp"
"github.com/pquerna/otp/totp" "github.com/pquerna/otp/totp"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/errs" "github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@@ -16,7 +18,7 @@ import (
func generateCommand() cli.Command { func generateCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "generate", Name: "generate",
Action: cli.ActionFunc(generateAction), Action: command.ActionFunc(generateAction),
Usage: "one-time password", Usage: "one-time password",
UsageText: `**step crypto otp generate**`, UsageText: `**step crypto otp generate**`,
Description: `**step crypto otp generate** does TOTP and HTOP`, 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", Name: "qr",
Usage: `Write a QR code to the specified path`, Usage: `Write a QR code to the specified path`,
}, },
flags.Force,
}, },
} }
} }

View File

@@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"encoding/pem" "encoding/pem"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@@ -300,7 +299,7 @@ func (p *PKI) Save() error {
return errors.Wrapf(err, "error marshalling %s", p.config) 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) return errs.FileError(err, p.config)
} }

View File

@@ -1,206 +1,21 @@
package flags package flags
import ( import (
"fmt"
"strings"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
// OldPasswordFile returns a flag for receiving an old password // Subtle is the flag required for delicate operations.
func OldPasswordFile(usage string) cli.Flag { var Subtle = cli.BoolFlag{
if usage == "" { Name: "subtle",
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",
}
} }
// NewPasswordFile returns a flag for receiving a new password // Insecure is the flag required on insecure operations
func NewPasswordFile(usage string) cli.Flag { var Insecure = cli.BoolFlag{
if usage == "" { Name: "insecure",
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",
}
} }
// Bits returns a flag for receiving the number of bits in generating a key // Force is a cli.Flag used to overwrite files.
func Bits(usage string, value int) cli.Flag { var Force = cli.BoolFlag{
if usage == "" { Name: "f,force",
usage = "Number of bits used to generate the private key" Usage: "Force the overwrite of files without asking.",
}
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,
}
} }

View File

@@ -10,6 +10,7 @@ import (
"syscall" "syscall"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
) )
@@ -21,19 +22,12 @@ var (
ErrIsDir = errors.New("file is a directory") ErrIsDir = errors.New("file is a directory")
) )
// WriteFile wraps ioutil.WriteFile with a prompt to overwrite a file if the // WriteFile wraps ioutil.WriteFile with a prompt to overwrite a file if
// 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
// the file exists. It returns ErrFileExists if the user picks to not overwrite // 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 // the file. If force is set to true, the prompt will not be presented and the
// file if exists will be overwritten. // file if exists will be overwritten.
func WriteFileForce(filename string, data []byte, perm os.FileMode, force bool) error { func WriteFile(filename string, data []byte, perm os.FileMode) error {
if force { if command.IsForce() {
return ioutil.WriteFile(filename, data, perm) return ioutil.WriteFile(filename, data, perm)
} }