github.com/letsencrypt/boulder@v0.20251208.0/cmd/boulder/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 8 _ "github.com/letsencrypt/boulder/cmd/bad-key-revoker" 9 _ "github.com/letsencrypt/boulder/cmd/boulder-ca" 10 _ "github.com/letsencrypt/boulder/cmd/boulder-observer" 11 _ "github.com/letsencrypt/boulder/cmd/boulder-publisher" 12 _ "github.com/letsencrypt/boulder/cmd/boulder-ra" 13 _ "github.com/letsencrypt/boulder/cmd/boulder-sa" 14 _ "github.com/letsencrypt/boulder/cmd/boulder-va" 15 _ "github.com/letsencrypt/boulder/cmd/boulder-wfe2" 16 _ "github.com/letsencrypt/boulder/cmd/cert-checker" 17 _ "github.com/letsencrypt/boulder/cmd/crl-checker" 18 _ "github.com/letsencrypt/boulder/cmd/crl-storer" 19 _ "github.com/letsencrypt/boulder/cmd/crl-updater" 20 _ "github.com/letsencrypt/boulder/cmd/email-exporter" 21 _ "github.com/letsencrypt/boulder/cmd/log-validator" 22 _ "github.com/letsencrypt/boulder/cmd/nonce-service" 23 _ "github.com/letsencrypt/boulder/cmd/remoteva" 24 _ "github.com/letsencrypt/boulder/cmd/reversed-hostname-checker" 25 _ "github.com/letsencrypt/boulder/cmd/sfe" 26 "github.com/letsencrypt/boulder/core" 27 28 "github.com/letsencrypt/boulder/cmd" 29 ) 30 31 // readAndValidateConfigFile uses the ConfigValidator registered for the given 32 // command to validate the provided config file. If the command does not have a 33 // registered ConfigValidator, this function does nothing. 34 func readAndValidateConfigFile(name, filename string) error { 35 cv := cmd.LookupConfigValidator(name) 36 if cv == nil { 37 return nil 38 } 39 file, err := os.Open(filename) 40 if err != nil { 41 return err 42 } 43 defer file.Close() 44 if name == "boulder-observer" { 45 // Only the boulder-observer uses YAML config files. 46 return cmd.ValidateYAMLConfig(cv, file) 47 } 48 return cmd.ValidateJSONConfig(cv, file) 49 } 50 51 // getConfigPath returns the path to the config file if it was provided as a 52 // command line flag. If the flag was not provided, it returns an empty string. 53 func getConfigPath() string { 54 for i := range len(os.Args) { 55 arg := os.Args[i] 56 if arg == "--config" || arg == "-config" { 57 if i+1 < len(os.Args) { 58 return os.Args[i+1] 59 } 60 } 61 config, ok := strings.CutPrefix(arg, "--config=") 62 if ok { 63 return config 64 } 65 config, ok = strings.CutPrefix(arg, "-config=") 66 if ok { 67 return config 68 } 69 } 70 return "" 71 } 72 73 var boulderUsage = fmt.Sprintf(`Usage: %s <subcommand> [flags] 74 75 Each boulder component has its own subcommand. Use --list to see 76 a list of the available components. Use <subcommand> --help to 77 see the usage for a specific component. 78 `, 79 core.Command()) 80 81 func main() { 82 defer cmd.AuditPanic() 83 84 if len(os.Args) <= 1 { 85 // No arguments passed. 86 fmt.Fprint(os.Stderr, boulderUsage) 87 return 88 } 89 90 if os.Args[1] == "--help" || os.Args[1] == "-help" { 91 // Help flag passed. 92 fmt.Fprint(os.Stderr, boulderUsage) 93 return 94 } 95 96 if os.Args[1] == "--list" || os.Args[1] == "-list" { 97 // List flag passed. 98 for _, c := range cmd.AvailableCommands() { 99 fmt.Println(c) 100 } 101 return 102 } 103 104 // Remove the subcommand from the arguments. 105 command := os.Args[1] 106 os.Args = os.Args[1:] 107 108 config := getConfigPath() 109 if config != "" { 110 // Config flag passed. 111 err := readAndValidateConfigFile(command, config) 112 if err != nil { 113 fmt.Fprintf(os.Stderr, "Error validating config file %q for command %q: %s\n", config, command, err) 114 os.Exit(1) 115 } 116 } 117 118 commandFunc := cmd.LookupCommand(command) 119 if commandFunc == nil { 120 fmt.Fprintf(os.Stderr, "Unknown subcommand %q.\n", command) 121 os.Exit(1) 122 } 123 commandFunc() 124 }