1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
package certificate
import (
"bytes"
"crypto/x509"
"encoding/pem"
"os"
"github.com/pkg/errors"
"github.com/smallstep/cli/command"
"github.com/smallstep/cli/errs"
"github.com/smallstep/cli/flags"
"github.com/smallstep/cli/ui"
"github.com/smallstep/cli/utils"
"github.com/urfave/cli"
)
func formatCommand() cli.Command {
return cli.Command{
Name: "format",
Action: command.ActionFunc(formatAction),
Usage: `reformat certificate`,
UsageText: `**step certificate format** <crt_file> [**--out**=<path>]`,
Description: `**step certificate format** prints the certificate in
a different format.
Only 2 formats are currently supported; PEM and ASN.1 DER. This tool will convert
a certificate in one format to the other.
## POSITIONAL ARGUMENTS
<crt_file>
: Path to a certificate file.
## EXIT CODES
This command returns 0 on success and \>0 if any error occurs.
## EXAMPLES
Convert PEM format to DER.
'''
$ step certificate format foo.pem
'''
Convert DER format to PEM.
'''
$ step certificate format foo.der
'''
Convert PEM format to DER and write to disk.
'''
$ step certificate format foo.pem --out foo.der
'''
`,
Flags: []cli.Flag{
cli.StringFlag{
Name: "out",
Usage: `Path to write the reformatted result.`,
},
flags.Force,
},
}
}
func formatAction(ctx *cli.Context) error {
if err := errs.NumberOfArguments(ctx, 1); err != nil {
return err
}
var (
crtFile = ctx.Args().Get(0)
out = ctx.String("out")
ob []byte
)
crtBytes, err := utils.ReadFile(crtFile)
if err != nil {
return errs.FileError(err, crtFile)
}
switch {
case bytes.HasPrefix(crtBytes, []byte("-----BEGIN ")): // PEM format
var (
blocks []*pem.Block
block *pem.Block
)
for len(crtBytes) > 0 {
block, crtBytes = pem.Decode(crtBytes)
if block == nil {
return errors.Errorf("%s contains an invalid PEM block", crtFile)
}
if block.Type != "CERTIFICATE" {
return errors.Errorf("certificate bundle %s contains an "+
"unexpected PEM block of type %s\n\n expected type: "+
"CERTIFICATE", crtFile, block.Type)
}
blocks = append(blocks, block)
}
// Only format the first certificate in the chain.
crt, err := x509.ParseCertificate(blocks[0].Bytes)
if err != nil {
return err
}
ob = crt.Raw
default: // assuming DER format
p := &pem.Block{
Type: "CERTIFICATE",
Bytes: crtBytes,
}
ob = pem.EncodeToMemory(p)
}
if out == "" {
os.Stdout.Write(ob)
} else {
info, err := os.Stat(crtFile)
if err != nil {
return err
}
if err := utils.WriteFile(out, ob, info.Mode()); err != nil {
return err
}
ui.Printf("Your certificate has been saved in %s.\n", out)
}
return nil
}
|