github.com/brimstone/sbuca@v0.0.0-20151202175429-8691d9eba5c5/sbuca.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "net/http" 8 "net/url" 9 "os" 10 "strings" 11 12 "github.com/brimstone/sbuca/pkix" 13 "github.com/brimstone/sbuca/server" 14 "github.com/codegangsta/cli" 15 ) 16 17 func main() { 18 19 app := cli.NewApp() 20 app.Name = "sbuca" 21 app.Usage = "Simple But Useful CA" 22 app.Commands = []cli.Command{ 23 24 { 25 Name: "server", 26 Usage: "Run a CA server", 27 Flags: []cli.Flag{ 28 cli.StringFlag{ 29 Name: "dir", 30 Value: ".", 31 Usage: "Root directory for certificates", 32 }, 33 cli.StringFlag{ 34 Name: "address", 35 Value: os.Getenv("HOST") + ":8600", 36 Usage: "Token for cert signing functions", 37 }, 38 cli.StringFlag{ 39 Name: "admin-token", 40 Value: "", 41 Usage: "Token for administrative functions", 42 }, 43 cli.StringFlag{ 44 Name: "sign-token", 45 Value: "", 46 Usage: "Token for cert signing functions", 47 }, 48 }, 49 Action: func(c *cli.Context) { 50 config := map[string]string{ 51 "address": c.String("address"), 52 "root-dir": c.String("dir"), 53 "admin-token": c.String("admin-token"), 54 "sign-token": c.String("sign-token"), 55 } 56 server.Run(config) 57 }, 58 }, 59 60 { 61 Name: "genkey", 62 Usage: "Generate a RSA Private Key to STDOUT", 63 Action: func(c *cli.Context) { 64 key, err := pkix.NewKey() 65 if err != nil { 66 panic(err) 67 } 68 69 pem, err := key.ToPEM() 70 if err != nil { 71 panic(err) 72 } 73 74 fmt.Print(string(pem)) 75 }, 76 }, 77 78 { 79 Name: "gencsr", 80 Usage: "Generate a Certificate Request to STDOUT", 81 Flags: []cli.Flag{ 82 cli.StringFlag{ 83 Name: "key", 84 Usage: "RSA Private Key", 85 }, 86 }, 87 Action: func(c *cli.Context) { 88 keyName := c.String("key") 89 if keyName == "" { 90 fmt.Fprintln(os.Stderr, "[ERROR] Requere private key as parameter") 91 return 92 } 93 94 key, err := pkix.NewKeyFromPrivateKeyPEMFile(keyName) 95 if err != nil { 96 fmt.Fprintln(os.Stderr, "[ERROR] Failed to generate CSR: "+err.Error()) 97 return 98 } 99 100 csr, err := pkix.NewCertificateRequest(key) 101 if err != nil { 102 fmt.Fprintln(os.Stderr, "[ERROR] Failed to generate CSR: "+err.Error()) 103 return 104 } 105 106 pem, err := csr.ToPEM() 107 if err != nil { 108 fmt.Fprintln(os.Stderr, "[ERROR] Failed to generate CSR: "+err.Error()) 109 return 110 } 111 112 fmt.Print(string(pem)) 113 }, 114 }, 115 116 { 117 Name: "submitcsr", 118 Usage: "Submit a Certificate Request to CA", 119 Flags: []cli.Flag{ 120 cli.StringFlag{ 121 Name: "host", 122 Usage: "Host ip & port", 123 }, 124 cli.StringFlag{ 125 Name: "format", 126 Value: "cert", 127 Usage: "output cert or id", 128 }, 129 cli.StringFlag{ 130 Name: "token", 131 Usage: "Authorization Token", 132 }, 133 }, 134 Action: func(c *cli.Context) { 135 host := c.String("host") 136 if host == "" { 137 fmt.Fprintln(os.Stderr, "[ERROR] Requere host as parameter") 138 return 139 } 140 141 format := c.String("format") 142 if format != "cert" && format != "id" { 143 fmt.Fprintln(os.Stderr, "[ERROR] format should be 'cert' or 'id'") 144 return 145 } 146 147 args := c.Args() 148 if len(args) == 0 { 149 fmt.Fprintln(os.Stderr, "[ERROR] Should provide csr") 150 return 151 } 152 csrName := c.Args().First() 153 154 csr, err := pkix.NewCertificateRequestFromPEMFile(csrName) 155 if err != nil { 156 fmt.Fprintln(os.Stderr, "[ERROR] Failed to parse CSR: "+err.Error()) 157 return 158 } 159 160 //resp, err := http.Post("http://example.com/upload", "application/json", &buf) 161 //var data interface{} 162 pem, err := csr.ToPEM() 163 if err != nil { 164 fmt.Fprintln(os.Stderr, "[ERROR] Failed to parse CSR: "+err.Error()) 165 return 166 } 167 168 data := make(url.Values) 169 data.Add("csr", string(pem)) 170 171 //resp, err := http.PostForm("http://"+host+"/certificates", data) 172 client := &http.Client{} 173 req, _ := http.NewRequest("POST", "http://"+host+"/certificates", strings.NewReader(data.Encode())) 174 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 175 if c.String("token") != "" { 176 req.Header.Set("X-API-KEY", c.String("token")) 177 } 178 resp, err := client.Do(req) 179 if err != nil { 180 fmt.Fprintln(os.Stderr, "[ERROR] Failed to request: "+err.Error()) 181 return 182 } 183 decoder := json.NewDecoder(resp.Body) 184 respData := make(map[string]map[string]interface{}) 185 if err := decoder.Decode(&respData); err != nil { 186 panic(err) 187 } 188 189 if format == "cert" { 190 fmt.Print(respData["certificate"]["crt"]) 191 } 192 if format == "id" { 193 fmt.Println(respData["certificate"]["id"]) 194 } 195 }, 196 }, 197 198 { 199 Name: "getcrt", 200 Flags: []cli.Flag{ 201 cli.StringFlag{ 202 Name: "host", 203 Usage: "Host ip & port", 204 }, 205 }, 206 Usage: "Get a Certificate from CA and output to STDOUT", 207 Action: func(c *cli.Context) { 208 209 host := c.String("host") 210 if host == "" { 211 fmt.Fprintln(os.Stderr, "[ERROR] Requere host as parameter") 212 return 213 } 214 215 args := c.Args() 216 if len(args) == 0 { 217 fmt.Fprintln(os.Stderr, "[ERROR] Should provide id (same as serial number)") 218 return 219 } 220 id := c.Args().First() 221 222 resp, err := http.Get("http://" + host + "/certificates/" + id) 223 if err != nil { 224 fmt.Fprintln(os.Stderr, "[ERROR] Failed to request: "+err.Error()) 225 return 226 } 227 228 decoder := json.NewDecoder(resp.Body) 229 respData := make(map[string]map[string]interface{}) 230 if err := decoder.Decode(&respData); err != nil { 231 panic(err) 232 } 233 234 fmt.Print(respData["certificate"]["crt"]) 235 236 }, 237 }, 238 239 { 240 Name: "getcacrt", 241 Flags: []cli.Flag{ 242 cli.StringFlag{ 243 Name: "host", 244 Usage: "Host ip & port", 245 }, 246 }, 247 Usage: "Get CA's Certificate and output to STDOUT", 248 Action: func(c *cli.Context) { 249 250 host := c.String("host") 251 if host == "" { 252 fmt.Fprintln(os.Stderr, "[ERROR] Require host as parameter") 253 return 254 } 255 256 resp, err := http.Get("http://" + host + "/ca/certificate") 257 if err != nil { 258 fmt.Fprintln(os.Stderr, "[ERROR] Failed to request CA cert: "+err.Error()) 259 os.Exit(1) 260 } 261 262 decoder := json.NewDecoder(resp.Body) 263 if resp.StatusCode != 200 { 264 fmt.Fprintln(os.Stderr, "[ERROR] Failed to request CA cert: "+resp.Status) 265 os.Exit(resp.StatusCode) 266 } 267 respData := make(map[string]map[string]interface{}) 268 if err := decoder.Decode(&respData); err != nil { 269 panic(err) 270 } 271 272 fmt.Print(respData["ca"]["crt"]) 273 274 }, 275 }, 276 { 277 Name: "oneshot", 278 Flags: []cli.Flag{ 279 cli.StringFlag{ 280 Name: "host", 281 Usage: "Host ip & port", 282 }, 283 cli.StringFlag{ 284 Name: "key", 285 Usage: "Path to private key file", 286 }, 287 cli.StringFlag{ 288 Name: "crt", 289 Usage: "Path to public cert file", 290 }, 291 cli.StringFlag{ 292 Name: "ca", 293 Usage: "Path to public ca file", 294 }, 295 cli.StringFlag{ 296 Name: "token", 297 Usage: "Authorization Token", 298 }, 299 }, 300 Usage: "Generate key, request, and submit to a server, all in one shot", 301 Action: func(c *cli.Context) { 302 keypath := c.String("key") 303 if keypath == "" { 304 fmt.Fprintln(os.Stderr, "Path to private key required") 305 return 306 } 307 crtpath := c.String("crt") 308 if crtpath == "" { 309 fmt.Fprintln(os.Stderr, "Path to public certificate required") 310 return 311 } 312 capath := c.String("ca") 313 if capath == "" { 314 fmt.Fprintln(os.Stderr, "Path to central authority required") 315 return 316 } 317 host := c.String("host") 318 if host == "" { 319 fmt.Fprintln(os.Stderr, "Location of host required") 320 return 321 } 322 keyfile, err := os.Create(keypath) 323 if err != nil { 324 fmt.Println(err) 325 os.Exit(1) 326 } 327 defer keyfile.Close() 328 329 crtfile, err := os.Create(crtpath) 330 if err != nil { 331 fmt.Println(err) 332 os.Exit(1) 333 } 334 defer crtfile.Close() 335 336 cafile, err := os.Create(capath) 337 if err != nil { 338 fmt.Println(err) 339 os.Exit(1) 340 } 341 defer cafile.Close() 342 343 // genkey 344 key, err := pkix.NewKey() 345 if err != nil { 346 fmt.Println(err) 347 os.Exit(1) 348 } 349 350 pem, err := key.ToPEM() 351 if err != nil { 352 fmt.Println(err) 353 os.Exit(1) 354 } 355 356 n, err := io.WriteString(keyfile, string(pem)) 357 if err != nil { 358 fmt.Println(n, err) 359 } 360 fmt.Println("Key written to", keypath) 361 362 // gencsr 363 csr, err := pkix.NewCertificateRequest(key) 364 if err != nil { 365 fmt.Fprintln(os.Stderr, "[ERROR] Failed to generate CSR: "+err.Error()) 366 return 367 } 368 csrpem, err := csr.ToPEM() 369 // submitcsr 370 data := make(url.Values) 371 data.Add("csr", string(csrpem)) 372 373 //resp, err := http.PostForm("http://"+host+"/certificates", data) 374 client := &http.Client{} 375 req, _ := http.NewRequest("POST", "http://"+host+"/certificates", strings.NewReader(data.Encode())) 376 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 377 if c.String("token") != "" { 378 req.Header.Set("X-API-KEY", c.String("token")) 379 } 380 resp, err := client.Do(req) 381 if err != nil { 382 fmt.Fprintln(os.Stderr, "[ERROR] Failed to request: "+err.Error()) 383 return 384 } 385 decoder := json.NewDecoder(resp.Body) 386 respData := make(map[string]map[string]interface{}) 387 if err := decoder.Decode(&respData); err != nil { 388 panic(err) 389 } 390 391 n, err = io.WriteString(crtfile, string(respData["certificate"]["crt"].(string))) 392 if err != nil { 393 fmt.Println(n, err) 394 } 395 fmt.Println("Certificate written to", crtpath) 396 397 // getcacrt 398 resp, err = http.Get("http://" + host + "/ca/certificate") 399 if err != nil { 400 fmt.Fprintln(os.Stderr, "[ERROR] Failed to request CA cert: "+err.Error()) 401 os.Exit(1) 402 } 403 404 decoder = json.NewDecoder(resp.Body) 405 if resp.StatusCode != 200 { 406 fmt.Fprintln(os.Stderr, "[ERROR] Failed to request CA cert: "+resp.Status) 407 os.Exit(resp.StatusCode) 408 } 409 respData = make(map[string]map[string]interface{}) 410 if err := decoder.Decode(&respData); err != nil { 411 panic(err) 412 } 413 414 n, err = io.WriteString(cafile, string(respData["ca"]["crt"].(string))) 415 if err != nil { 416 fmt.Println(n, err) 417 } 418 fmt.Println("Certificate Authority written to", capath) 419 }, 420 }, 421 } 422 423 app.Run(os.Args) 424 425 }