func main() { var Usage = func() { fmt.Fprintf(os.Stderr, "Mozilla InvestiGator Action Generator\n"+ "usage: %s -k=<key id> (-i <input file)\n\n"+ "Command line to generate and sign MIG Actions.\n"+ "The resulting actions are display on stdout.\n\n"+ "Options:\n", os.Args[0]) flag.PrintDefaults() } // command line options var key = flag.String("k", "key identifier", "Key identifier used to sign the action (ex: B75C2346)") var pretty = flag.Bool("p", false, "Print signed action in pretty JSON format") var urlencode = flag.Bool("urlencode", false, "URL Encode marshalled JSON before output") var posturl = flag.String("posturl", "", "POST action to <url> (enforces urlencode)") var file = flag.String("i", "/path/to/file", "Load action from file") var validfrom = flag.String("validfrom", "now", "(optional) set an ISO8601 date the action will be valid from. If unset, use 'now'.") var expireafter = flag.String("expireafter", "30m", "(optional) set a validity duration for the action. If unset, use '30m'.") flag.Parse() // We need a key, if none is set on the command line, fail if *key == "key identifier" { Usage() os.Exit(-1) } var a mig.Action var err error // if a file is defined, load action from that if *file != "/path/to/file" { a, err = mig.ActionFromFile(*file) } else { // otherwise, use interactive mode a, err = getActionFromTerminal() } if err != nil { panic(err) } // set the dates if *validfrom == "now" { a.ValidFrom = time.Now().UTC() } else { a.ValidFrom, err = time.Parse("2014-01-01T00:00:00.0Z", *validfrom) if err != nil { panic(err) } } period, err := time.ParseDuration(*expireafter) if err != nil { log.Fatal(err) } a.ExpireAfter = a.ValidFrom.Add(period) // compute the signature str, err := a.String() if err != nil { panic(err) } a.PGPSignature, err = sign.Sign(str, *key) if err != nil { panic(err) } a.PGPSignatureDate = time.Now().UTC() var jsonAction []byte if *pretty { jsonAction, err = json.MarshalIndent(a, "", "\t") } else { jsonAction, err = json.Marshal(a) } if err != nil { panic(err) } // if asked, url encode the action before marshaling it actionstr := string(jsonAction) if *urlencode { strJsonAction := string(jsonAction) actionstr = url.QueryEscape(strJsonAction) } if *posturl != "" { resp, err := http.PostForm(*posturl, url.Values{"action": {actionstr}}) if err != nil { panic(err) } var buf [512]byte reader := resp.Body for { n, err := reader.Read(buf[0:]) if err != nil { os.Exit(0) } fmt.Print(string(buf[0:n])) } } // find keyring in default location u, err := user.Current() if err != nil { panic(err) } // load keyring var gnupghome string gnupghome = os.Getenv("GNUPGHOME") if gnupghome == "" { gnupghome = "/.gnupg" } keyring, err := os.Open(u.HomeDir + gnupghome + "/pubring.gpg") if err != nil { panic(err) } defer keyring.Close() // syntax checking err = a.Validate() if err != nil { panic(err) } // syntax checking err = a.VerifySignature(keyring) if err != nil { panic(err) } }
// createAction receives a signed action in a POST request, validates it, // and write it into the scheduler spool func createAction(respWriter http.ResponseWriter, request *http.Request) { var err error opid := mig.GenID() var action mig.Action resource := cljs.New(request.URL.String()) defer func() { if e := recover(); e != nil { ctx.Channels.Log <- mig.Log{OpID: opid, ActionID: action.ID, Desc: fmt.Sprintf("%v", e)}.Err() resource.SetError(cljs.Error{Code: fmt.Sprintf("%d", opid), Message: fmt.Sprintf("%v", e)}) respond(500, resource, respWriter, request, opid) } ctx.Channels.Log <- mig.Log{OpID: opid, ActionID: action.ID, Desc: "leaving createAction()"}.Debug() }() // parse the POST body into a mig action request.ParseForm() postAction := request.FormValue("action") err = json.Unmarshal([]byte(postAction), &action) if err != nil { panic(err) } ctx.Channels.Log <- mig.Log{OpID: opid, Desc: fmt.Sprintf("Received action for creation '%s'", action)}.Debug() // load keyring and validate action keyring, err := os.Open(ctx.OpenPGP.PubRing) if err != nil { panic(err) } defer keyring.Close() err = action.Validate() if err != nil { panic(err) } err = action.VerifySignature(keyring) if err != nil { panic(err) } action.ID = mig.GenID() ctx.Channels.Log <- mig.Log{OpID: opid, ActionID: action.ID, Desc: "Received new action with valid signature"} // write action to disk destdir := fmt.Sprintf("%s/%d.json", ctx.Directories.Action.New, action.ID) newAction, err := json.Marshal(action) if err != nil { panic(err) } err = safeWrite(opid, destdir, newAction) if err != nil { panic(err) } ctx.Channels.Log <- mig.Log{OpID: opid, ActionID: action.ID, Desc: "Action committed to spool"} err = resource.AddItem(cljs.Item{ Href: "/api/action?actionid=" + fmt.Sprintf("%d", action.ID), Data: []cljs.Data{{Name: "action ID " + fmt.Sprintf("%d", action.ID), Value: action}}, }) if err != nil { panic(err) } respond(201, resource, respWriter, request, opid) }
func main() { var err error var Usage = func() { fmt.Fprintf(os.Stderr, "Mozilla InvestiGator Action Verifier\n"+ "usage: %s <-a action file> <-c command file>\n\n"+ "Command line to verify an action *or* command.\n"+ "Options:\n", os.Args[0]) flag.PrintDefaults() } hasaction := false hascommand := false // command line options var actionfile = flag.String("a", "/path/to/action", "Load action from file") var commandfile = flag.String("c", "/path/to/command", "Load command from file") var pubring = flag.String("pubring", "/path/to/pubring", "Use pubring at <path>") flag.Parse() // if a file is defined, load action from that if *actionfile != "/path/to/action" { hasaction = true } if *commandfile != "/path/to/command" { hascommand = true } if (hasaction && hascommand) || (!hasaction && !hascommand) { Usage() panic(err) } var a mig.Action if hasaction { a, err = mig.ActionFromFile(*actionfile) if err != nil { panic(err) } } else { c, err := mig.CmdFromFile(*commandfile) if err != nil { panic(err) } a = c.Action } fmt.Printf("%s\n", a) err = a.Validate() if err != nil { fmt.Println(err) } // find keyring in default location u, err := user.Current() if err != nil { panic(err) } if *pubring != "/path/to/pubring" { // load keyring var gnupghome string gnupghome = os.Getenv("GNUPGHOME") if gnupghome == "" { gnupghome = "/.gnupg" } *pubring = u.HomeDir + gnupghome + "/pubring.gpg" } keyring, err := os.Open(*pubring) if err != nil { panic(err) } defer keyring.Close() // syntax checking err = a.VerifySignature(keyring) if err != nil { panic(err) } fmt.Println("Valid signature") }