func Example() { app := cli.NewApp() app.Name = "todo" app.Usage = "task list on the command line" app.Commands = []cli.Command{ { Name: "add", ShortName: "a", Usage: "add a task to the list", Action: func(c *cli.Context) { println("added task: ", c.Args().First()) }, }, { Name: "complete", ShortName: "c", Usage: "complete a task on the list", Action: func(c *cli.Context) { println("completed task: ", c.Args().First()) }, }, } app.Run(os.Args) }
func ExampleAppBashComplete() { // set args for examples sake os.Args = []string{"greet", "--generate-bash-completion"} app := cli.NewApp() app.Name = "greet" app.EnableBashCompletion = true app.Commands = []cli.Command{ { Name: "describeit", ShortName: "d", Usage: "use it to see a description", Description: "This is how we describe describeit the function", Action: func(c *cli.Context) { fmt.Printf("i like to describe things") }, }, { Name: "next", Usage: "next example", Description: "more stuff to see when generating bash completion", Action: func(c *cli.Context) { fmt.Printf("the next example") }, }, } app.Run(os.Args) // Output: // describeit // d // next // help // h }
func TestApp_DefaultStdout(t *testing.T) { app := cli.NewApp() if app.Writer != os.Stdout { t.Error("Default output writer not set.") } }
func ExampleAppHelp() { // set args for examples sake os.Args = []string{"greet", "h", "describeit"} app := cli.NewApp() app.Name = "greet" app.Flags = []cli.Flag{ cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, } app.Commands = []cli.Command{ { Name: "describeit", ShortName: "d", Usage: "use it to see a description", Description: "This is how we describe describeit the function", Action: func(c *cli.Context) { fmt.Printf("i like to describe things") }, }, } app.Run(os.Args) // Output: // NAME: // describeit - use it to see a description // // USAGE: // command describeit [arguments...] // // DESCRIPTION: // This is how we describe describeit the function }
func TestGlobalFlagsInSubcommands(t *testing.T) { subcommandRun := false app := cli.NewApp() app.Flags = []cli.Flag{ cli.BoolFlag{Name: "debug, d", Usage: "Enable debugging"}, } app.Commands = []cli.Command{ cli.Command{ Name: "foo", Subcommands: []cli.Command{ { Name: "bar", Action: func(c *cli.Context) { if c.GlobalBool("debug") { subcommandRun = true } }, }, }, }, } app.Run([]string{"command", "-d", "foo", "bar"}) expect(t, subcommandRun, true) }
func TestApp_RunAsSubcommandParseFlags(t *testing.T) { var context *cli.Context a := cli.NewApp() a.Commands = []cli.Command{ { Name: "foo", Action: func(c *cli.Context) { context = c }, Flags: []cli.Flag{ cli.StringFlag{ Name: "lang", Value: "english", Usage: "language for the greeting", }, }, Before: func(_ *cli.Context) error { return nil }, }, } a.Run([]string{"", "foo", "--lang", "spanish", "abcd"}) expect(t, context.Args().Get(0), "abcd") expect(t, context.String("lang"), "spanish") }
func TestApp_ParseSliceFlags(t *testing.T) { var parsedOption, firstArg string var parsedIntSlice []int var parsedStringSlice []string app := cli.NewApp() command := cli.Command{ Name: "cmd", Flags: []cli.Flag{ cli.IntSliceFlag{Name: "p", Value: &cli.IntSlice{}, Usage: "set one or more ip addr"}, cli.StringSliceFlag{Name: "ip", Value: &cli.StringSlice{}, Usage: "set one or more ports to open"}, }, Action: func(c *cli.Context) { parsedIntSlice = c.IntSlice("p") parsedStringSlice = c.StringSlice("ip") parsedOption = c.String("option") firstArg = c.Args().First() }, } app.Commands = []cli.Command{command} app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"}) IntsEquals := func(a, b []int) bool { if len(a) != len(b) { return false } for i, v := range a { if v != b[i] { return false } } return true } StrsEquals := func(a, b []string) bool { if len(a) != len(b) { return false } for i, v := range a { if v != b[i] { return false } } return true } var expectedIntSlice = []int{22, 80} var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"} if !IntsEquals(parsedIntSlice, expectedIntSlice) { t.Errorf("%v does not match %v", parsedIntSlice, expectedIntSlice) } if !StrsEquals(parsedStringSlice, expectedStringSlice) { t.Errorf("%v does not match %v", parsedStringSlice, expectedStringSlice) } }
func TestApp_Command(t *testing.T) { app := cli.NewApp() fooCommand := cli.Command{Name: "foobar", ShortName: "f"} batCommand := cli.Command{Name: "batbaz", ShortName: "b"} app.Commands = []cli.Command{ fooCommand, batCommand, } for _, test := range commandAppTests { expect(t, app.Command(test.name) != nil, test.expected) } }
func TestApp_Float64Flag(t *testing.T) { var meters float64 app := cli.NewApp() app.Flags = []cli.Flag{ cli.Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"}, } app.Action = func(c *cli.Context) { meters = c.Float64("height") } app.Run([]string{"", "--height", "1.93"}) expect(t, meters, 1.93) }
func TestApp_Run(t *testing.T) { s := "" app := cli.NewApp() app.Action = func(c *cli.Context) { s = s + c.Args().First() } err := app.Run([]string{"command", "foo"}) expect(t, err, nil) err = app.Run([]string{"command", "bar"}) expect(t, err, nil) expect(t, s, "foobar") }
func TestAppNoHelpFlag(t *testing.T) { oldFlag := cli.HelpFlag defer func() { cli.HelpFlag = oldFlag }() cli.HelpFlag = cli.BoolFlag{} app := cli.NewApp() err := app.Run([]string{"test", "-h"}) if err != flag.ErrHelp { t.Errorf("expected error about missing help flag, but got: %s (%T)", err, err) } }
func ExampleApp() { // set args for examples sake os.Args = []string{"greet", "--name", "Jeremy"} app := cli.NewApp() app.Name = "greet" app.Flags = []cli.Flag{ cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, } app.Action = func(c *cli.Context) { fmt.Printf("Hello %v\n", c.String("name")) } app.Run(os.Args) // Output: // Hello Jeremy }
// NewAppShell creates a basic AppShell object containing CLI metadata func NewAppShell(name string) (shell *AppShell) { app := cli.NewApp() app.Name = name app.Version = "0.0.0" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "config", Value: "config.json", EnvVar: "BOULDER_CONFIG", }, } return &AppShell{app: app} }
func TestApp_SetStdout(t *testing.T) { w := &mockWriter{} app := cli.NewApp() app.Name = "test" app.Writer = w err := app.Run([]string{"help"}) if err != nil { t.Fatalf("Run error: %s", err) } if len(w.written) == 0 { t.Error("App did not write output to desired writer.") } }
// NewAppShell creates a basic AppShell object containing CLI metadata func NewAppShell(name string) (shell *AppShell) { app := cli.NewApp() app.Name = name app.Version = fmt.Sprintf("0.1.0 [%s]", core.GetBuildID()) app.Flags = []cli.Flag{ cli.StringFlag{ Name: "config", Value: "config.json", EnvVar: "BOULDER_CONFIG", Usage: "Path to Config JSON", }, } return &AppShell{App: app} }
func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) { var args []string app := cli.NewApp() command := cli.Command{ Name: "cmd", Action: func(c *cli.Context) { args = c.Args() }, } app.Commands = []cli.Command{command} app.Run([]string{"", "cmd", "my-arg", "--", "notAFlagAtAll"}) expect(t, args[0], "my-arg") expect(t, args[1], "--") expect(t, args[2], "notAFlagAtAll") }
func TestAppHelpPrinter(t *testing.T) { oldPrinter := cli.HelpPrinter defer func() { cli.HelpPrinter = oldPrinter }() var wasCalled = false cli.HelpPrinter = func(template string, data interface{}) { wasCalled = true } app := cli.NewApp() app.Run([]string{"-h"}) if wasCalled == false { t.Errorf("Help printer expected to be called, but was not") } }
func TestCommandDoNotIgnoreFlags(t *testing.T) { app := cli.NewApp() set := flag.NewFlagSet("test", 0) test := []string{"blah", "blah", "-break"} set.Parse(test) c := cli.NewContext(app, set, set) command := cli.Command{ Name: "test-cmd", ShortName: "tc", Usage: "this is for testing", Description: "testing", Action: func(_ *cli.Context) {}, } err := command.Run(c) expect(t, err.Error(), "flag provided but not defined: -break") }
func TestAppVersionPrinter(t *testing.T) { oldPrinter := cli.VersionPrinter defer func() { cli.VersionPrinter = oldPrinter }() var wasCalled = false cli.VersionPrinter = func(c *cli.Context) { wasCalled = true } app := cli.NewApp() ctx := cli.NewContext(app, nil, nil) cli.ShowVersion(ctx) if wasCalled == false { t.Errorf("Version printer expected to be called, but was not") } }
// NewAppShell creates a basic AppShell object containing CLI metadata func NewAppShell(name, usage string) (shell *AppShell) { app := cli.NewApp() app.Name = name app.Usage = usage app.Version = Version() app.Author = "Boulder contributors" app.Email = "*****@*****.**" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "config", Value: "config.json", EnvVar: "BOULDER_CONFIG", Usage: "Path to Config JSON", }, } return &AppShell{App: app} }
func TestCommandIgnoreFlags(t *testing.T) { app := cli.NewApp() set := flag.NewFlagSet("test", 0) test := []string{"blah", "blah"} set.Parse(test) c := cli.NewContext(app, set, set) command := cli.Command{ Name: "test-cmd", ShortName: "tc", Usage: "this is for testing", Description: "testing", Action: func(_ *cli.Context) {}, SkipFlagParsing: true, } err := command.Run(c) expect(t, err, nil) }
func TestApp_CommandWithArgBeforeFlags(t *testing.T) { var parsedOption, firstArg string app := cli.NewApp() command := cli.Command{ Name: "cmd", Flags: []cli.Flag{ cli.StringFlag{Name: "option", Value: "", Usage: "some option"}, }, Action: func(c *cli.Context) { parsedOption = c.String("option") firstArg = c.Args().First() }, } app.Commands = []cli.Command{command} app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"}) expect(t, parsedOption, "my-option") expect(t, firstArg, "my-arg") }
func TestAppCommandNotFound(t *testing.T) { beforeRun, subcommandRun := false, false app := cli.NewApp() app.CommandNotFound = func(c *cli.Context, command string) { beforeRun = true } app.Commands = []cli.Command{ cli.Command{ Name: "bar", Action: func(c *cli.Context) { subcommandRun = true }, }, } app.Run([]string{"command", "foo"}) expect(t, beforeRun, true) expect(t, subcommandRun, false) }
func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) { var parsedOption string var args []string app := cli.NewApp() command := cli.Command{ Name: "cmd", Flags: []cli.Flag{ cli.StringFlag{Name: "option", Value: "", Usage: "some option"}, }, Action: func(c *cli.Context) { parsedOption = c.String("option") args = c.Args() }, } app.Commands = []cli.Command{command} app.Run([]string{"", "cmd", "my-arg", "--option", "my-option", "--", "--notARealFlag"}) expect(t, parsedOption, "my-option") expect(t, args[0], "my-arg") expect(t, args[1], "--") expect(t, args[2], "--notARealFlag") }
func ExampleAppSubcommand() { // set args for examples sake os.Args = []string{"say", "hi", "english", "--name", "Jeremy"} app := cli.NewApp() app.Name = "say" app.Commands = []cli.Command{ { Name: "hello", ShortName: "hi", Usage: "use it to see a description", Description: "This is how we describe hello the function", Subcommands: []cli.Command{ { Name: "english", ShortName: "en", Usage: "sends a greeting in english", Description: "greets someone in english", Flags: []cli.Flag{ cli.StringFlag{ Name: "name", Value: "Bob", Usage: "Name of the person to greet", }, }, Action: func(c *cli.Context) { fmt.Println("Hello,", c.String("name")) }, }, }, }, } app.Run(os.Args) // Output: // Hello, Jeremy }
func main() { app := cli.NewApp() app.Name = "policy-loader" app.Usage = "Loads/dumps rules into/from the policy database" app.Version = cmd.Version() app.Author = "Boulder contributors" app.Email = "*****@*****.**" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "config", Value: "config.json", EnvVar: "BOULDER_CONFIG", Usage: "Path to Boulder JSON configuration file", }, cli.StringFlag{ Name: "rule-file", Value: "rules.json", EnvVar: "BOULDER_POLICY_RULES", Usage: "Path to Boulder policy whitelist and blacklist rule file", }, } app.Commands = append(app.Commands, []cli.Command{ cli.Command{ Name: "dump-rules", Usage: "Write out whitelist and blacklist from database to a rule file", Action: func(c *cli.Context) { padb, ruleFile := setupFromContext(c) ruleSet, err := padb.DumpRules() cmd.FailOnError(err, "Couldn't retrieve whitelist rules") var rules struct { Blacklist []string Whitelist []string } for _, r := range ruleSet.Blacklist { rules.Blacklist = append(rules.Blacklist, r.Host) } for _, r := range ruleSet.Whitelist { rules.Whitelist = append(rules.Whitelist, r.Host) } rulesJSON, err := json.Marshal(rules) cmd.FailOnError(err, "Couldn't marshal rule list") err = ioutil.WriteFile(ruleFile, rulesJSON, os.ModePerm) cmd.FailOnError(err, "Failed to write the rule file") fmt.Printf("# Saved rule list to %s\n", ruleFile) }, }, cli.Command{ Name: "load-rules", Usage: "Load whitelist and blacklist into database from a rule file", Action: func(c *cli.Context) { padb, ruleFile := setupFromContext(c) rulesJSON, err := ioutil.ReadFile(ruleFile) cmd.FailOnError(err, "Couldn't read configuration file") rules := policy.RawRuleSet{} err = json.Unmarshal(rulesJSON, &rules) cmd.FailOnError(err, "Couldn't unmarshal rules list") rs := policy.RuleSet{} for _, r := range rules.Blacklist { rs.Blacklist = append(rs.Blacklist, policy.BlacklistRule{ Host: strings.ToLower(r), }) } for _, r := range rules.Whitelist { rs.Whitelist = append(rs.Whitelist, policy.WhitelistRule{ Host: strings.ToLower(r), }) } err = padb.LoadRules(rs) cmd.FailOnError(err, "Couldn't load rules") fmt.Println("# Loaded whitelist and blacklist into database") }, }, }...) app.Run(os.Args) }
func main() { app := cli.NewApp() app.Name = "admin-revoker" app.Usage = "Revokes issued certificates" app.Version = cmd.Version() app.Author = "Boulder contributors" app.Email = "*****@*****.**" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "config", Value: "config.json", EnvVar: "BOULDER_CONFIG", Usage: "Path to Boulder JSON configuration file", }, cli.BoolFlag{ Name: "deny", Usage: "Add certificate DNS names to the denied list", }, } app.Commands = []cli.Command{ { Name: "serial-revoke", Usage: "Revoke a single certificate by the hex serial number", Action: func(c *cli.Context) { // 1: serial, 2: reasonCode (3: deny flag) serial := c.Args().First() reasonCode, err := strconv.Atoi(c.Args().Get(1)) cmd.FailOnError(err, "Reason code argument must be a integer") deny := c.GlobalBool("deny") cac, auditlogger, dbMap, _ := setupContext(c) tx, err := dbMap.Begin() if err != nil { tx.Rollback() } cmd.FailOnError(err, "Couldn't begin transaction") err = revokeBySerial(serial, core.RevocationCode(reasonCode), deny, cac, auditlogger, tx) if err != nil { tx.Rollback() } cmd.FailOnError(err, "Couldn't revoke certificate") err = tx.Commit() cmd.FailOnError(err, "Couldn't cleanly close transaction") }, }, { Name: "reg-revoke", Usage: "Revoke all certificates associated with a registration ID", Action: func(c *cli.Context) { // 1: registration ID, 2: reasonCode (3: deny flag) regID, err := strconv.ParseInt(c.Args().First(), 10, 64) cmd.FailOnError(err, "Registration ID argument must be a integer") reasonCode, err := strconv.Atoi(c.Args().Get(1)) cmd.FailOnError(err, "Reason code argument must be a integer") deny := c.GlobalBool("deny") cac, auditlogger, dbMap, sac := setupContext(c) // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 defer auditlogger.AuditPanic() tx, err := dbMap.Begin() if err != nil { tx.Rollback() } cmd.FailOnError(err, "Couldn't begin transaction") _, err = sac.GetRegistration(regID) if err != nil { cmd.FailOnError(err, "Couldn't fetch registration") } err = revokeByReg(regID, core.RevocationCode(reasonCode), deny, cac, auditlogger, tx) if err != nil { tx.Rollback() } cmd.FailOnError(err, "Couldn't revoke certificate") err = tx.Commit() cmd.FailOnError(err, "Couldn't cleanly close transaction") }, }, { Name: "list-reasons", Usage: "List all revocation reason codes", Action: func(c *cli.Context) { var codes core.RevocationCodes for k := range core.RevocationReasons { codes = append(codes, k) } sort.Sort(codes) fmt.Printf("Revocation reason codes\n-----------------------\n\n") for _, k := range codes { fmt.Printf("%d: %s\n", k, core.RevocationReasons[k]) } }, }, } err := app.Run(os.Args) cmd.FailOnError(err, "Failed to run application") }
func main() { app := cli.NewApp() app.Name = "single-ocsp" app.Usage = `Creates a single OCSP response. According to the BRs, the OCSP responses for intermediate certificate must be issued once per year. So there's a need to issue OCSP responses for these certificates, but it doesn't make sense to use all the infrastructure that the "ocsp-updater" tool requires. This tool allows an administrator to manually generate an OCSP response for an intermediate certificate. ` app.Version = cmd.Version() app.Author = "Boulder contributors" app.Email = "*****@*****.**" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "issuer", Usage: "Issuer certificate (DER)", }, cli.StringFlag{ Name: "responder", Usage: "OCSP responder certificate (DER)", }, cli.StringFlag{ Name: "target", Usage: "Certificate whose status is being reported (DER)", }, cli.StringFlag{ Name: "template", Usage: `OCSP template file (JSON), e.g.: { "Status": 0, // Good "ThisUpdate": "2015-08-26T00:00:00Z", "NextUpdate": "2016-08-26T00:00:00Z" } { "Status": 1, // Revoked "ThisUpdate": "2015-08-26T00:00:00Z", "NextUpdate": "2016-08-26T00:00:00Z", "RevokedAt": "2015-08-20T00:00:00Z", "RevocationReason": 1 // Key compromise } `, }, cli.StringFlag{ Name: "pkcs11", Usage: `PKCS#11 configuration (JSON), e.g.: { "Module": "/Library/OpenSC/lib/opensc-pkcs11.so", "Token": "Yubico Yubikey NEO CCID", "Label": "PIV AUTH key", "PIN": "123456" } `, }, cli.StringFlag{ Name: "out", Usage: "File to which the OCSP response will be written", }, } app.Action = func(c *cli.Context) { issuer, responder, target, template, pkcs11, err := readFiles(c) cmd.FailOnError(err, "Failed to read files") // Instantiate the private key from PKCS11 priv, err := pkcs11key.New(pkcs11.Module, pkcs11.TokenLabel, pkcs11.PIN, pkcs11.PrivateKeyLabel, int(pkcs11.SlotID)) cmd.FailOnError(err, "Failed to load PKCS#11 key") // Populate the remaining fields in the template template.SerialNumber = target.SerialNumber template.Certificate = responder // Sign the OCSP response responseBytes, err := ocsp.CreateResponse(issuer, responder, template, priv) cmd.FailOnError(err, "Failed to sign OCSP response") // Write the OCSP response to stdout outFile := c.GlobalString("out") if len(outFile) == 0 { cmd.FailOnError(fmt.Errorf(""), "No output file provided") } ioutil.WriteFile(outFile, responseBytes, 0666) } err := app.Run(os.Args) cmd.FailOnError(err, "Failed to run application") }
func main() { app := cli.NewApp() app.Name = "jose-util" app.Usage = "command-line utility to deal with JOSE objects" app.Version = "0.0.2" app.Author = "" app.Email = "" app.Commands = []cli.Command{ { Name: "encrypt", Usage: "encrypt a plaintext", Flags: []cli.Flag{ cli.StringFlag{ Name: "key, k", Usage: "Path to key file (PEM/DER)", }, cli.StringFlag{ Name: "input, in", Usage: "Path to input file (stdin if missing)", }, cli.StringFlag{ Name: "output, out", Usage: "Path to output file (stdout if missing)", }, cli.StringFlag{ Name: "algorithm, alg", Usage: "Key management algorithm (e.g. RSA-OAEP)", }, cli.StringFlag{ Name: "encryption, enc", Usage: "Content encryption algorithm (e.g. A128GCM)", }, cli.BoolFlag{ Name: "full, f", Usage: "Use full serialization format (instead of compact)", }, }, Action: func(c *cli.Context) { keyBytes, err := ioutil.ReadFile(requiredFlag(c, "key")) exitOnError(err, "unable to read key file") pub, err := jose.LoadPublicKey(keyBytes) exitOnError(err, "unable to read public key") alg := jose.KeyAlgorithm(requiredFlag(c, "alg")) enc := jose.ContentEncryption(requiredFlag(c, "enc")) crypter, err := jose.NewEncrypter(alg, enc, pub) exitOnError(err, "unable to instantiate encrypter") obj, err := crypter.Encrypt(readInput(c.String("input"))) exitOnError(err, "unable to encrypt") var msg string if c.Bool("full") { msg = obj.FullSerialize() } else { msg, err = obj.CompactSerialize() exitOnError(err, "unable to serialize message") } writeOutput(c.String("output"), []byte(msg)) }, }, { Name: "decrypt", Usage: "decrypt a ciphertext", Flags: []cli.Flag{ cli.StringFlag{ Name: "key, k", Usage: "Path to key file (PEM/DER)", }, cli.StringFlag{ Name: "input, in", Usage: "Path to input file (stdin if missing)", }, cli.StringFlag{ Name: "output, out", Usage: "Path to output file (stdout if missing)", }, }, Action: func(c *cli.Context) { keyBytes, err := ioutil.ReadFile(requiredFlag(c, "key")) exitOnError(err, "unable to read private key") priv, err := jose.LoadPrivateKey(keyBytes) exitOnError(err, "unable to read private key") obj, err := jose.ParseEncrypted(string(readInput(c.String("input")))) exitOnError(err, "unable to parse message") plaintext, err := obj.Decrypt(priv) exitOnError(err, "unable to decrypt message") writeOutput(c.String("output"), plaintext) }, }, { Name: "sign", Usage: "sign a plaintext", Flags: []cli.Flag{ cli.StringFlag{ Name: "algorithm, alg", Usage: "Signing algorithm (e.g. PS256)", }, cli.StringFlag{ Name: "key, k", Usage: "Path to key file (PEM/DER)", }, cli.StringFlag{ Name: "input, in", Usage: "Path to input file (stdin if missing)", }, cli.StringFlag{ Name: "output, out", Usage: "Path to output file (stdout if missing)", }, cli.BoolFlag{ Name: "full, f", Usage: "Use full serialization format (instead of compact)", }, }, Action: func(c *cli.Context) { keyBytes, err := ioutil.ReadFile(requiredFlag(c, "key")) exitOnError(err, "unable to read key file") signingKey, err := jose.LoadPrivateKey(keyBytes) exitOnError(err, "unable to read private key") alg := jose.SignatureAlgorithm(requiredFlag(c, "algorithm")) signer, err := jose.NewSigner(alg, signingKey) exitOnError(err, "unable to make signer") obj, err := signer.Sign(readInput(c.String("input"))) exitOnError(err, "unable to sign") var msg string if c.Bool("full") { msg = obj.FullSerialize() } else { msg, err = obj.CompactSerialize() exitOnError(err, "unable to serialize message") } writeOutput(c.String("output"), []byte(msg)) }, }, { Name: "verify", Usage: "verify a signature", Flags: []cli.Flag{ cli.StringFlag{ Name: "key, k", Usage: "Path to key file (PEM/DER)", }, cli.StringFlag{ Name: "input, in", Usage: "Path to input file (stdin if missing)", }, cli.StringFlag{ Name: "output, out", Usage: "Path to output file (stdout if missing)", }, }, Action: func(c *cli.Context) { keyBytes, err := ioutil.ReadFile(requiredFlag(c, "key")) exitOnError(err, "unable to read key file") verificationKey, err := jose.LoadPublicKey(keyBytes) exitOnError(err, "unable to read private key") obj, err := jose.ParseSigned(string(readInput(c.String("input")))) exitOnError(err, "unable to parse message") plaintext, err := obj.Verify(verificationKey) exitOnError(err, "invalid signature") writeOutput(c.String("output"), plaintext) }, }, { Name: "expand", Usage: "expand compact message to full format", Flags: []cli.Flag{ cli.StringFlag{ Name: "input, in", Usage: "Path to input file (stdin if missing)", }, cli.StringFlag{ Name: "output, out", Usage: "Path to output file (stdout if missing)", }, cli.StringFlag{ Name: "format, f", Usage: "Message format (JWE/JWS, defaults to JWE)", }, }, Action: func(c *cli.Context) { input := string(readInput(c.String("input"))) var serialized string var err error switch c.String("format") { case "", "JWE": var jwe *jose.JsonWebEncryption jwe, err = jose.ParseEncrypted(input) if err == nil { serialized = jwe.FullSerialize() } case "JWS": var jws *jose.JsonWebSignature jws, err = jose.ParseSigned(input) if err == nil { serialized = jws.FullSerialize() } } exitOnError(err, "unable to expand message") writeOutput(c.String("output"), []byte(serialized)) }, }, } err := app.Run(os.Args) exitOnError(err, "unable to run application") }
func main() { app := cli.NewApp() app.Name = "orphan-finder" app.Usage = "Reads orphaned certificates from a boulder-ca log or a der file and add them to the database" app.Version = cmd.Version() app.Author = "Boulder contributors" app.Email = "*****@*****.**" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "config", Value: "config.json", EnvVar: "BOULDER_CONFIG", Usage: "Path to Boulder JSON configuration file", }, } app.Commands = []cli.Command{ { Name: "parse-ca-log", Usage: "Parses boulder-ca logs to add multiple orphaned certificates", Flags: []cli.Flag{ cli.StringFlag{ Name: "log-file", Usage: "Path to boulder-ca log file to parse", }, }, Action: func(c *cli.Context) { stats, logger, sa := setup(c) logPath := c.String("log-file") if logPath == "" { fmt.Println("log file path must be provided") os.Exit(1) } logData, err := ioutil.ReadFile(logPath) cmd.FailOnError(err, "Failed to read log file") orphansFound := int64(0) orphansAdded := int64(0) for _, line := range strings.Split(string(logData), "\n") { found, added := parseLogLine(sa, logger, line) if found { orphansFound++ if added { orphansAdded++ } } } logger.Info(fmt.Sprintf("Found %d orphans and added %d to the database\n", orphansFound, orphansAdded)) stats.Inc("orphaned-certificates.found", orphansFound, 1.0) stats.Inc("orphaned-certificates.added", orphansAdded, 1.0) stats.Inc("orphaned-certificates.adding-failed", orphansFound-orphansAdded, 1.0) }, }, { Name: "parse-der", Usage: "Parses a single orphaned DER certificate file and adds it to the database", Flags: []cli.Flag{ cli.StringFlag{ Name: "der-file", Usage: "Path to DER certificate file", }, cli.IntFlag{ Name: "regID", Usage: "Registration ID of user who requested the certificate", }, }, Action: func(c *cli.Context) { _, _, sa := setup(c) derPath := c.String("der-file") if derPath == "" { fmt.Println("der file path must be provided") os.Exit(1) } regID := c.Int("regID") if regID == 0 { fmt.Println("--regID must be non-zero") os.Exit(1) } der, err := ioutil.ReadFile(derPath) cmd.FailOnError(err, "Failed to read DER file") err = checkDER(sa, der) cmd.FailOnError(err, "Pre-AddCertificate checks failed") _, err = sa.AddCertificate(der, int64(regID)) cmd.FailOnError(err, "Failed to add certificate to database") }, }, } app.Run(os.Args) }