forked from cloudflare/cfssl
/
cfssljson.go
182 lines (162 loc) · 4.02 KB
/
cfssljson.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// cfssljson splits out JSON with cert, csr, and key fields to separate
// files.
package main
import (
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
)
func readFile(filespec string) ([]byte, error) {
if filespec == "-" {
return ioutil.ReadAll(os.Stdin)
}
return ioutil.ReadFile(filespec)
}
func writeFile(filespec, contents string, perms os.FileMode) {
err := ioutil.WriteFile(filespec, []byte(contents), perms)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}
// ResponseMessage represents the format of a CFSSL output for an error or message
type ResponseMessage struct {
Code int `json:"int"`
Message string `json:"message"`
}
// Response represents the format of a CFSSL output
type Response struct {
Success bool `json:"success"`
Result map[string]interface{} `json:"result"`
Errors []ResponseMessage `json:"errors"`
Messages []ResponseMessage `json:"messages"`
}
type outputFile struct {
Filename string
Contents string
IsBinary bool
Perms os.FileMode
}
func main() {
bare := flag.Bool("bare", false, "the response from CFSSL is not wrapped in the API standard response")
inFile := flag.String("f", "-", "JSON input")
output := flag.Bool("stdout", false, "output the response instead of saving to a file")
flag.Parse()
var baseName string
if flag.NArg() == 0 {
baseName = "cert"
} else {
baseName = flag.Arg(0)
}
var input = map[string]interface{}{}
var outs []outputFile
var cert string
var key string
var csr string
fileData, err := readFile(*inFile)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to read input: %v\n", err)
os.Exit(1)
}
if *bare {
err = json.Unmarshal(fileData, &input)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse input: %v\n", err)
os.Exit(1)
}
} else {
var response Response
err = json.Unmarshal(fileData, &response)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse input: %v\n", err)
os.Exit(1)
}
if !response.Success {
fmt.Fprintf(os.Stderr, "Request failed:\n")
for _, msg := range response.Errors {
fmt.Fprintf(os.Stderr, "\t%s\n", msg.Message)
}
os.Exit(1)
}
input = response.Result
}
if contents, ok := input["cert"]; ok {
cert = contents.(string)
} else if contents, ok = input["certificate"]; ok {
cert = contents.(string)
}
if cert != "" {
outs = append(outs, outputFile{
Filename: baseName + ".pem",
Contents: cert,
Perms: 0664,
})
}
if contents, ok := input["key"]; ok {
key = contents.(string)
} else if contents, ok = input["private_key"]; ok {
key = contents.(string)
}
if key != "" {
outs = append(outs, outputFile{
Filename: baseName + "-key.pem",
Contents: key,
Perms: 0600,
})
}
if contents, ok := input["encrypted_key"]; ok {
encKey := contents.(string)
outs = append(outs, outputFile{
Filename: baseName + "-key.enc",
Contents: encKey,
IsBinary: true,
Perms: 0600,
})
}
if contents, ok := input["csr"]; ok {
csr = contents.(string)
} else if contents, ok = input["certificate_request"]; ok {
csr = contents.(string)
}
if csr != "" {
outs = append(outs, outputFile{
Filename: baseName + ".csr",
Contents: csr,
Perms: 0644,
})
}
if contents, ok := input["bundle"]; ok {
outs = append(outs, outputFile{
Filename: baseName + "-bundle.pem",
Contents: contents.(string),
Perms: 0644,
})
}
if contents, ok := input["ocspResponse"]; ok {
//ocspResponse is base64 encoded
resp, err := base64.StdEncoding.DecodeString(contents.(string))
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse ocspResponse: %v\n", err)
os.Exit(1)
}
outs = append(outs, outputFile{
Filename: baseName + "-response.der",
Contents: string(resp),
IsBinary: true,
Perms: 0644,
})
}
for _, e := range outs {
if *output {
if e.IsBinary {
e.Contents = base64.StdEncoding.EncodeToString([]byte(e.Contents))
}
fmt.Fprintf(os.Stdout, "%s\n", e.Contents)
} else {
writeFile(e.Filename, e.Contents, e.Perms)
}
}
}