1
0
mirror of https://github.com/smallstep/cli.git synced 2025-08-09 03:22:43 +03:00
This commit is contained in:
Dominik Roos
2021-12-02 22:38:16 +01:00
parent 953d552603
commit 8de234779b
11 changed files with 88 additions and 43 deletions

View File

@@ -79,7 +79,7 @@ authenticity of the remote server.
debugging invalid certificates remotely.`, debugging invalid certificates remotely.`,
}, },
flags.ServerName, flags.ServerName,
command.FingerprintFormatFlag(), command.FingerprintFormatFlag("hex"),
}, },
} }
} }
@@ -99,7 +99,7 @@ func fingerprintAction(ctx *cli.Context) error {
format = ctx.String("format") format = ctx.String("format")
) )
encoding, err := command.GetFingerprintEncoding(format, "hex") encoding, err := command.GetFingerprintEncoding(format)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -211,28 +211,27 @@ func setEnvVar(c *cli.Command) {
} }
// FingerprintFormatFlag returns a flag for configuring the fingerprint format. // FingerprintFormatFlag returns a flag for configuring the fingerprint format.
func FingerprintFormatFlag() cli.StringFlag { func FingerprintFormatFlag(defaultFmt string) cli.StringFlag {
return cli.StringFlag{ return cli.StringFlag{
Name: "format", Name: "format",
Usage: `The <format> of the fingerprint, it must be "hex", "base64", "base64-url", "base64-raw", or "emoji".`, Usage: `The <format> of the fingerprint, it must be "hex", "base64", "base64-url", "base64-raw", "base64-url-raw" or "emoji".`,
Value: defaultFmt,
} }
} }
// GetFingerprintEncoding gets the fingerprint encoding from the format flag. // GetFingerprintEncoding gets the fingerprint encoding from the format flag.
func GetFingerprintEncoding(format, defaultFmt string) (fingerprint.Encoding, error) { func GetFingerprintEncoding(format string) (fingerprint.Encoding, error) {
if format == "" {
format = defaultFmt
}
switch strings.ToLower(strings.TrimSpace(format)) { switch strings.ToLower(strings.TrimSpace(format)) {
case "hex", "": case "hex", "":
return fingerprint.HexFingerprint, nil return fingerprint.HexFingerprint, nil
case "base64": case "base64":
return fingerprint.Base64Fingerprint, nil return fingerprint.Base64StdFingerprint, nil
case "base64url", "base64-url": case "base64url", "base64-url":
return fingerprint.Base64URLFingerprint, nil return fingerprint.Base64URLFingerprint, nil
case "base64urlraw", "base64url-raw", "base64-url-raw":
return fingerprint.Base64RawURLFingerprint, nil
case "base64raw", "base64-raw": case "base64raw", "base64-raw":
return fingerprint.Base64RawFingerprint, nil return fingerprint.Base64RawStdFingerprint, nil
case "emoji", "emojisum": case "emoji", "emojisum":
return fingerprint.EmojiFingerprint, nil return fingerprint.EmojiFingerprint, nil
default: default:

View File

@@ -29,7 +29,7 @@ func TestGetFingerprintEncoding(t *testing.T) {
args{ args{
"base64", "base64",
}, },
fingerprint.Base64Fingerprint, fingerprint.Base64StdFingerprint,
false, false,
}, },
{ {
@@ -53,7 +53,7 @@ func TestGetFingerprintEncoding(t *testing.T) {
args{ args{
"base64raw", "base64raw",
}, },
fingerprint.Base64RawFingerprint, fingerprint.Base64RawStdFingerprint,
false, false,
}, },
{ {
@@ -61,7 +61,31 @@ func TestGetFingerprintEncoding(t *testing.T) {
args{ args{
"base64-raw", "base64-raw",
}, },
fingerprint.Base64RawFingerprint, fingerprint.Base64RawStdFingerprint,
false,
},
{
"base64urlraw",
args{
"base64urlraw",
},
fingerprint.Base64RawURLFingerprint,
false,
},
{
"base64url-raw",
args{
"base64url-raw",
},
fingerprint.Base64RawURLFingerprint,
false,
},
{
"base64-url-raw",
args{
"base64-url-raw",
},
fingerprint.Base64RawURLFingerprint,
false, false,
}, },
{ {
@@ -91,7 +115,7 @@ func TestGetFingerprintEncoding(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, err := GetFingerprintEncoding(tt.args.format, "hex") got, err := GetFingerprintEncoding(tt.args.format)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("GetFingerprintEncoding() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("GetFingerprintEncoding() error = %v, wantErr %v", err, tt.wantErr)
return return

View File

@@ -10,11 +10,12 @@ import (
"os" "os"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/crypto/fingerprint" "github.com/smallstep/cli/crypto/fingerprint"
"github.com/smallstep/cli/crypto/pemutil" "github.com/smallstep/cli/crypto/pemutil"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
"go.step.sm/cli-utils/command" libcommand "go.step.sm/cli-utils/command"
"go.step.sm/cli-utils/errs" "go.step.sm/cli-utils/errs"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
) )
@@ -22,7 +23,7 @@ import (
func fingerprintCommand() cli.Command { func fingerprintCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "fingerprint", Name: "fingerprint",
Action: command.ActionFunc(fingerprintAction), Action: libcommand.ActionFunc(fingerprintAction),
Usage: `print the fingerprint of a public key`, Usage: `print the fingerprint of a public key`,
UsageText: `**step crypto key fingerprint** <key-file>`, UsageText: `**step crypto key fingerprint** <key-file>`,
Description: `**step crypto key fingerprint** prints the fingerprint of a public key. The Description: `**step crypto key fingerprint** prints the fingerprint of a public key. The
@@ -101,7 +102,7 @@ $ step crypto key fingerprint --password-file pass.txt priv.pem
Name: "raw", Name: "raw",
Usage: "Print the raw bytes instead of the fingerprint. These bytes can be piped to a different hash command.", Usage: "Print the raw bytes instead of the fingerprint. These bytes can be piped to a different hash command.",
}, },
command.FingerprintFormatFlag(), command.FingerprintFormatFlag(""),
}, },
} }
} }
@@ -138,7 +139,12 @@ func fingerprintAction(ctx *cli.Context) error {
prefix = "SHA1:" prefix = "SHA1:"
hash = crypto.SHA1 hash = crypto.SHA1
} }
encoding, err := command.GetFingerprintEncoding(format, defaultFmt)
if format == "" {
format = defaultFmt
}
encoding, err := command.GetFingerprintEncoding(format)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -3,18 +3,19 @@ package ssh
import ( import (
"fmt" "fmt"
"github.com/smallstep/cli/command"
libfingerprint "github.com/smallstep/cli/crypto/fingerprint" libfingerprint "github.com/smallstep/cli/crypto/fingerprint"
"github.com/smallstep/cli/crypto/sshutil" "github.com/smallstep/cli/crypto/sshutil"
"github.com/smallstep/cli/utils" "github.com/smallstep/cli/utils"
"github.com/urfave/cli" "github.com/urfave/cli"
"go.step.sm/cli-utils/command" libcommand "go.step.sm/cli-utils/command"
"go.step.sm/cli-utils/errs" "go.step.sm/cli-utils/errs"
) )
func fingerPrintCommand() cli.Command { func fingerPrintCommand() cli.Command {
return cli.Command{ return cli.Command{
Name: "fingerprint", Name: "fingerprint",
Action: command.ActionFunc(fingerprint), Action: libcommand.ActionFunc(fingerprint),
Usage: "print the fingerprint of an SSH public key or certificate", Usage: "print the fingerprint of an SSH public key or certificate",
UsageText: `**step ssh fingerprint** <file>`, UsageText: `**step ssh fingerprint** <file>`,
Description: `**step ssh fingerprint** prints the fingerprint of an ssh public key or Description: `**step ssh fingerprint** prints the fingerprint of an ssh public key or
@@ -37,7 +38,7 @@ Print the fingerprint for an SSH public key:
$ step ssh fingerprint id_ecdsa.pub $ step ssh fingerprint id_ecdsa.pub
'''`, '''`,
Flags: []cli.Flag{ Flags: []cli.Flag{
command.FingerprintFormatFlag(), command.FingerprintFormatFlag("base64-raw"),
}, },
} }
} }
@@ -54,7 +55,7 @@ func fingerprint(ctx *cli.Context) error {
) )
if format != "" { if format != "" {
encoding, err := command.GetFingerprintEncoding(format, "hex") encoding, err := command.GetFingerprintEncoding(format)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -12,8 +12,8 @@ func toEmoji(input []byte) string {
// emojiCodeMap is a mapping from byte to emoji. // emojiCodeMap is a mapping from byte to emoji.
// //
// The mapping is based on https://github.com/emojisum/emojisum with amendments // The mapping is based on draft+2 of https://github.com/emojisum/emojisum.
// proposed in https://github.com/emojisum/emojisum/issues/37. // (see: https://github.com/emojisum/emojisum/releases/tag/draft%2B2)
var emojiCodeMap = []string{ var emojiCodeMap = []string{
"\U0001f44d", // 👍 :+1: "\U0001f44d", // 👍 :+1:
"\U0001f3b1", // 🎱 :8ball: "\U0001f3b1", // 🎱 :8ball:

View File

@@ -15,12 +15,14 @@ type Encoding int
const ( const (
// HexFingerprint represents the hex encoding of the fingerprint. // HexFingerprint represents the hex encoding of the fingerprint.
HexFingerprint Encoding = iota HexFingerprint Encoding = iota
// Base64Fingerprint represents the base64 encoding of the fingerprint. // Base64StdFingerprint represents the base64 encoding of the fingerprint.
Base64Fingerprint Base64StdFingerprint
// Base64URLFingerprint represents the base64URL encoding of the fingerprint. // Base64URLFingerprint represents the base64URL encoding of the fingerprint.
Base64URLFingerprint Base64URLFingerprint
// Base64RawFingerprint represents the base64Raw encoding of the fingerprint. // Base64RawStdFingerprint represents the base64RawStd encoding of the fingerprint.
Base64RawFingerprint Base64RawStdFingerprint
// Base64RawURLFingerprint represents the base64RawURL encoding of the fingerprint.
Base64RawURLFingerprint
// EmojiFingerprint represents the emoji encoding of the fingerprint. // EmojiFingerprint represents the emoji encoding of the fingerprint.
EmojiFingerprint EmojiFingerprint
) )
@@ -88,12 +90,14 @@ func encode(input []byte, encoding Encoding) string {
switch encoding { switch encoding {
case HexFingerprint: case HexFingerprint:
return strings.ToLower(hex.EncodeToString(input)) return strings.ToLower(hex.EncodeToString(input))
case Base64Fingerprint: case Base64StdFingerprint:
return base64.StdEncoding.EncodeToString(input) return base64.StdEncoding.EncodeToString(input)
case Base64URLFingerprint: case Base64URLFingerprint:
return base64.URLEncoding.EncodeToString(input) return base64.URLEncoding.EncodeToString(input)
case Base64RawFingerprint: case Base64RawStdFingerprint:
return base64.RawStdEncoding.EncodeToString(input) return base64.RawStdEncoding.EncodeToString(input)
case Base64RawURLFingerprint:
return base64.RawURLEncoding.EncodeToString(input)
case EmojiFingerprint: case EmojiFingerprint:
return toEmoji(input) return toEmoji(input)
default: default:
@@ -112,11 +116,13 @@ func decode(input string, encoding Encoding) ([]byte, error) {
switch encoding { switch encoding {
case HexFingerprint: case HexFingerprint:
return hex.DecodeString(input) return hex.DecodeString(input)
case Base64Fingerprint: case Base64StdFingerprint:
return base64.StdEncoding.DecodeString(input) return base64.StdEncoding.DecodeString(input)
case Base64URLFingerprint: case Base64URLFingerprint:
return base64.URLEncoding.DecodeString(input) return base64.URLEncoding.DecodeString(input)
case Base64RawFingerprint: case Base64RawStdFingerprint:
return base64.RawStdEncoding.DecodeString(input)
case Base64RawURLFingerprint:
return base64.RawURLEncoding.DecodeString(input) return base64.RawURLEncoding.DecodeString(input)
case EmojiFingerprint: case EmojiFingerprint:
return nil, errors.New("decoding emoji fingerprint not supported") return nil, errors.New("decoding emoji fingerprint not supported")

View File

@@ -28,13 +28,16 @@ func TestEncodedFingerprint(t *testing.T) {
[]Option{WithHash(crypto.SHA256), WithEncoding(HexFingerprint)}, []Option{WithHash(crypto.SHA256), WithEncoding(HexFingerprint)},
}, },
{"base64", "testdata/ca.der", "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg=", {"base64", "testdata/ca.der", "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg=",
[]Option{WithHash(crypto.SHA256), WithEncoding(Base64Fingerprint)}, []Option{WithHash(crypto.SHA256), WithEncoding(Base64StdFingerprint)},
}, },
{"base64url", "testdata/ca.der", "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat_pg=", {"base64url", "testdata/ca.der", "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat_pg=",
[]Option{WithHash(crypto.SHA256), WithEncoding(Base64URLFingerprint)}, []Option{WithHash(crypto.SHA256), WithEncoding(Base64URLFingerprint)},
}, },
{"base64raw", "testdata/ca.der", "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg", {"base64raw", "testdata/ca.der", "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg",
[]Option{WithHash(crypto.SHA256), WithEncoding(Base64RawFingerprint)}, []Option{WithHash(crypto.SHA256), WithEncoding(Base64RawStdFingerprint)},
},
{"base64url-raw", "testdata/ca.der", "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat_pg",
[]Option{WithHash(crypto.SHA256), WithEncoding(Base64RawURLFingerprint)},
}, },
{"emoji", "testdata/ca.der", "🚁🍎👺🚌🏮☁️🎍👀🇮🇹✋🍼🚽⛅🐼🚬🎅🇷🇺🇷🇺🚂🤢🎀💩🚁🎆👺🎨👌✔️🚸🌈⚡🐼", {"emoji", "testdata/ca.der", "🚁🍎👺🚌🏮☁️🎍👀🇮🇹✋🍼🚽⛅🐼🚬🎅🇷🇺🇷🇺🚂🤢🎀💩🚁🎆👺🎨👌✔️🚸🌈⚡🐼",
[]Option{WithHash(crypto.SHA256), WithEncoding(EmojiFingerprint)}, []Option{WithHash(crypto.SHA256), WithEncoding(EmojiFingerprint)},
@@ -44,13 +47,16 @@ func TestEncodedFingerprint(t *testing.T) {
[]Option{WithHash(crypto.SHA256), WithEncoding(HexFingerprint), WithPrefix("PREFIX:")}, []Option{WithHash(crypto.SHA256), WithEncoding(HexFingerprint), WithPrefix("PREFIX:")},
}, },
{"prefix, base64", "testdata/ca.der", "PREFIX:aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg=", {"prefix, base64", "testdata/ca.der", "PREFIX:aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg=",
[]Option{WithHash(crypto.SHA256), WithEncoding(Base64Fingerprint), WithPrefix("PREFIX:")}, []Option{WithHash(crypto.SHA256), WithEncoding(Base64StdFingerprint), WithPrefix("PREFIX:")},
}, },
{"prefix, base64url", "testdata/ca.der", "PREFIX:aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat_pg=", {"prefix, base64url", "testdata/ca.der", "PREFIX:aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat_pg=",
[]Option{WithHash(crypto.SHA256), WithEncoding(Base64URLFingerprint), WithPrefix("PREFIX:")}, []Option{WithHash(crypto.SHA256), WithEncoding(Base64URLFingerprint), WithPrefix("PREFIX:")},
}, },
{"prefix, base64url-raw", "testdata/ca.der", "PREFIX:aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat_pg",
[]Option{WithHash(crypto.SHA256), WithEncoding(Base64RawURLFingerprint), WithPrefix("PREFIX:")},
},
{"prefix, base64raw", "testdata/ca.der", "PREFIX:aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg", {"prefix, base64raw", "testdata/ca.der", "PREFIX:aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg",
[]Option{WithHash(crypto.SHA256), WithEncoding(Base64RawFingerprint), WithPrefix("PREFIX:")}, []Option{WithHash(crypto.SHA256), WithEncoding(Base64RawStdFingerprint), WithPrefix("PREFIX:")},
}, },
{"prefix, emoji", "testdata/ca.der", "PREFIX:🚁🍎👺🚌🏮☁️🎍👀🇮🇹✋🍼🚽⛅🐼🚬🎅🇷🇺🇷🇺🚂🤢🎀💩🚁🎆👺🎨👌✔️🚸🌈⚡🐼", {"prefix, emoji", "testdata/ca.der", "PREFIX:🚁🍎👺🚌🏮☁️🎍👀🇮🇹✋🍼🚽⛅🐼🚬🎅🇷🇺🇷🇺🚂🤢🎀💩🚁🎆👺🎨👌✔️🚸🌈⚡🐼",
[]Option{WithHash(crypto.SHA256), WithEncoding(EmojiFingerprint), WithPrefix("PREFIX:")}, []Option{WithHash(crypto.SHA256), WithEncoding(EmojiFingerprint), WithPrefix("PREFIX:")},

View File

@@ -53,8 +53,8 @@ func Fingerprint(in []byte, opts ...FingerprintOption) (string, error) {
} }
fp := ssh.FingerprintSHA256(key) fp := ssh.FingerprintSHA256(key)
if o.FingerprintOptions != nil { if len(o.FingerprintOptions) != 0 {
raw, err := fingerprint.Decode(fp, fingerprint.WithPrefix("SHA256:"), fingerprint.WithEncoding(fingerprint.Base64RawFingerprint)) raw, err := fingerprint.Decode(fp, fingerprint.WithPrefix("SHA256:"), fingerprint.WithEncoding(fingerprint.Base64RawStdFingerprint))
if err != nil { if err != nil {
return "", errors.Wrap(err, "decoding fingerprint") return "", errors.Wrap(err, "decoding fingerprint")
} }

View File

@@ -27,11 +27,13 @@ const (
// HexFingerprint represents hex encoding of fingerprint. // HexFingerprint represents hex encoding of fingerprint.
HexFingerprint = FingerprintEncoding(fingerprint.HexFingerprint) HexFingerprint = FingerprintEncoding(fingerprint.HexFingerprint)
// Base64Fingerprint represents base64 encoding of fingerprint. // Base64Fingerprint represents base64 encoding of fingerprint.
Base64Fingerprint = FingerprintEncoding(fingerprint.Base64Fingerprint) Base64Fingerprint = FingerprintEncoding(fingerprint.Base64StdFingerprint)
// Base64URLFingerprint represents base64URL encoding of fingerprint. // Base64URLFingerprint represents base64URL encoding of fingerprint.
Base64URLFingerprint = FingerprintEncoding(fingerprint.Base64URLFingerprint) Base64URLFingerprint = FingerprintEncoding(fingerprint.Base64URLFingerprint)
// Base64RawFingerprint represents base64Raw encoding of fingerprint. // Base64RawURLFingerprint represents base64Raw encoding of fingerprint.
Base64RawFingerprint = FingerprintEncoding(fingerprint.Base64RawFingerprint) Base64RawURLFingerprint = FingerprintEncoding(fingerprint.Base64RawURLFingerprint)
// Base64RawStdFingerprint represents base64Raw encoding of fingerprint.
Base64RawStdFingerprint = FingerprintEncoding(fingerprint.Base64RawStdFingerprint)
// EmojiFingerprint represents emoji encoding of fingerprint. // EmojiFingerprint represents emoji encoding of fingerprint.
EmojiFingerprint = FingerprintEncoding(fingerprint.EmojiFingerprint) EmojiFingerprint = FingerprintEncoding(fingerprint.EmojiFingerprint)
) )

View File

@@ -39,7 +39,8 @@ func TestEncodedFingerprint(t *testing.T) {
{"hex", "test_files/ca.crt", HexFingerprint, "6908751f68290d4573ae0be39a98c8b9b7b7d4e8b2a6694b7509946626adfe98"}, {"hex", "test_files/ca.crt", HexFingerprint, "6908751f68290d4573ae0be39a98c8b9b7b7d4e8b2a6694b7509946626adfe98"},
{"base64", "test_files/ca.crt", Base64Fingerprint, "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg="}, {"base64", "test_files/ca.crt", Base64Fingerprint, "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg="},
{"base64url", "test_files/ca.crt", Base64URLFingerprint, "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat_pg="}, {"base64url", "test_files/ca.crt", Base64URLFingerprint, "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat_pg="},
{"base64raw", "test_files/ca.crt", Base64RawFingerprint, "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg"}, {"base64raw", "test_files/ca.crt", Base64RawStdFingerprint, "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat/pg"},
{"base64raw", "test_files/ca.crt", Base64RawURLFingerprint, "aQh1H2gpDUVzrgvjmpjIube31OiypmlLdQmUZiat_pg"},
{"emoji", "test_files/ca.crt", EmojiFingerprint, "🚁🍎👺🚌🏮☁️🎍👀🇮🇹✋🍼🚽⛅🐼🚬🎅🇷🇺🇷🇺🚂🤢🎀💩🚁🎆👺🎨👌✔️🚸🌈⚡🐼"}, {"emoji", "test_files/ca.crt", EmojiFingerprint, "🚁🍎👺🚌🏮☁️🎍👀🇮🇹✋🍼🚽⛅🐼🚬🎅🇷🇺🇷🇺🚂🤢🎀💩🚁🎆👺🎨👌✔️🚸🌈⚡🐼"},
} }
for _, tt := range tests { for _, tt := range tests {