117 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
| package main
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 
 | |
| 	"github.com/jmhodges/clock"
 | |
| 
 | |
| 	"github.com/letsencrypt/boulder/cmd"
 | |
| 	"github.com/letsencrypt/boulder/db"
 | |
| 	"github.com/letsencrypt/boulder/features"
 | |
| 	bgrpc "github.com/letsencrypt/boulder/grpc"
 | |
| 	blog "github.com/letsencrypt/boulder/log"
 | |
| 	rapb "github.com/letsencrypt/boulder/ra/proto"
 | |
| 	"github.com/letsencrypt/boulder/sa"
 | |
| 	sapb "github.com/letsencrypt/boulder/sa/proto"
 | |
| )
 | |
| 
 | |
| // admin holds all of the external connections necessary to perform admin
 | |
| // actions on a boulder deployment.
 | |
| type admin struct {
 | |
| 	rac   rapb.RegistrationAuthorityClient
 | |
| 	sac   sapb.StorageAuthorityClient
 | |
| 	saroc sapb.StorageAuthorityReadOnlyClient
 | |
| 	// TODO: Remove this and only use sac and saroc to interact with the db.
 | |
| 	// We cannot have true dry-run safety as long as we have a direct dbMap.
 | |
| 	dbMap *db.WrappedMap
 | |
| 
 | |
| 	// TODO: Remove this when the dbMap is removed and the dryRunSAC and dryRunRAC
 | |
| 	// handle all dry-run safety.
 | |
| 	dryRun bool
 | |
| 
 | |
| 	clk clock.Clock
 | |
| 	log blog.Logger
 | |
| }
 | |
| 
 | |
| // newAdmin constructs a new admin object on the heap and returns a pointer to
 | |
| // it.
 | |
| func newAdmin(configFile string, dryRun bool) (*admin, error) {
 | |
| 	// Unlike most boulder service constructors, this does all of its own config
 | |
| 	// parsing and dependency setup. If this is broken out into its own package
 | |
| 	// (outside the //cmd/ directory) those pieces of setup should stay behind
 | |
| 	// in //cmd/admin/main.go, to match other boulder services.
 | |
| 	var c Config
 | |
| 	err := cmd.ReadConfigFile(configFile, &c)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("parsing config file: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	scope, logger, oTelShutdown := cmd.StatsAndLogging(c.Syslog, c.OpenTelemetry, c.Admin.DebugAddr)
 | |
| 	defer oTelShutdown(context.Background())
 | |
| 	logger.Info(cmd.VersionString())
 | |
| 
 | |
| 	clk := cmd.Clock()
 | |
| 	features.Set(c.Admin.Features)
 | |
| 
 | |
| 	tlsConfig, err := c.Admin.TLS.Load(scope)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("loading TLS config: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	var rac rapb.RegistrationAuthorityClient = dryRunRAC{log: logger}
 | |
| 	if !dryRun {
 | |
| 		raConn, err := bgrpc.ClientSetup(c.Admin.RAService, tlsConfig, scope, clk)
 | |
| 		if err != nil {
 | |
| 			return nil, fmt.Errorf("creating RA gRPC client: %w", err)
 | |
| 		}
 | |
| 		rac = rapb.NewRegistrationAuthorityClient(raConn)
 | |
| 	}
 | |
| 
 | |
| 	saConn, err := bgrpc.ClientSetup(c.Admin.SAService, tlsConfig, scope, clk)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("creating SA gRPC client: %w", err)
 | |
| 	}
 | |
| 	saroc := sapb.NewStorageAuthorityReadOnlyClient(saConn)
 | |
| 
 | |
| 	var sac sapb.StorageAuthorityClient = dryRunSAC{log: logger}
 | |
| 	if !dryRun {
 | |
| 		sac = sapb.NewStorageAuthorityClient(saConn)
 | |
| 	}
 | |
| 
 | |
| 	dbMap, err := sa.InitWrappedDb(c.Admin.DB, nil, logger)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("creating database connection: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return &admin{
 | |
| 		rac:    rac,
 | |
| 		sac:    sac,
 | |
| 		saroc:  saroc,
 | |
| 		dbMap:  dbMap,
 | |
| 		dryRun: dryRun,
 | |
| 		clk:    clk,
 | |
| 		log:    logger,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // findActiveInputMethodFlag returns a single key from setInputs with a value of `true`,
 | |
| // if exactly one exists. Otherwise it returns an error.
 | |
| func findActiveInputMethodFlag(setInputs map[string]bool) (string, error) {
 | |
| 	var activeFlags []string
 | |
| 	for flag, isSet := range setInputs {
 | |
| 		if isSet {
 | |
| 			activeFlags = append(activeFlags, flag)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if len(activeFlags) == 0 {
 | |
| 		return "", errors.New("at least one input method flag must be specified")
 | |
| 	} else if len(activeFlags) > 1 {
 | |
| 		return "", fmt.Errorf("more than one input method flag specified: %v", activeFlags)
 | |
| 	}
 | |
| 
 | |
| 	return activeFlags[0], nil
 | |
| }
 |