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  }