forked from smallstep/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
format.go
128 lines (110 loc) 路 2.65 KB
/
format.go
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
}