Implement config generator
This commit adds code to allow the generation of a default client configuration. The generator is run instead of the regular client code, when the option -generate-config is passed on the command line.
This commit is contained in:
parent
da24ae70b6
commit
c65853d1f9
3 changed files with 87 additions and 40 deletions
|
@ -20,9 +20,12 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
"git.cacert.org/cacert-gosigner/pkg/protocol"
|
"git.cacert.org/cacert-gosigner/pkg/protocol"
|
||||||
"git.cacert.org/cacert-gosignerclient/internal/client"
|
"git.cacert.org/cacert-gosignerclient/internal/client"
|
||||||
|
@ -42,7 +45,7 @@ const (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var (
|
||||||
showVersion, verbose bool
|
showVersion, verbose, generateConfig bool
|
||||||
configFile, logLevel string
|
configFile, logLevel string
|
||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
)
|
)
|
||||||
|
@ -56,6 +59,12 @@ func main() {
|
||||||
flag.StringVar(&configFile, "config", defaultConfigFile, "signer client configuration file")
|
flag.StringVar(&configFile, "config", defaultConfigFile, "signer client configuration file")
|
||||||
flag.BoolVar(&showVersion, "version", false, "show version")
|
flag.BoolVar(&showVersion, "version", false, "show version")
|
||||||
flag.BoolVar(&verbose, "verbose", false, "verbose output")
|
flag.BoolVar(&verbose, "verbose", false, "verbose output")
|
||||||
|
flag.BoolVar(
|
||||||
|
&generateConfig,
|
||||||
|
"generate-config",
|
||||||
|
false,
|
||||||
|
"generate a configuration file with default values instead of running the client",
|
||||||
|
)
|
||||||
flag.StringVar(&logLevel, "loglevel", "INFO", "log level")
|
flag.StringVar(&logLevel, "loglevel", "INFO", "log level")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
@ -71,9 +80,45 @@ func main() {
|
||||||
|
|
||||||
logger.SetLevel(parsedLevel)
|
logger.SetLevel(parsedLevel)
|
||||||
|
|
||||||
|
if generateConfig {
|
||||||
|
if err = generateDefaultConfig(); err != nil {
|
||||||
|
logger.WithError(err).Fatal("could not generate default configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := startClient(configFile, logger); err != nil {
|
||||||
|
logger.WithError(err).Fatal("client failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateDefaultConfig() error {
|
||||||
|
const defaultBaseConfiguration = `---
|
||||||
|
serial:
|
||||||
|
device: /dev/ttyUSB0
|
||||||
|
baud: 112500
|
||||||
|
`
|
||||||
|
|
||||||
|
cfg, err := config.LoadConfiguration(strings.NewReader(
|
||||||
|
defaultBaseConfiguration))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not load empty configuration: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
enc := yaml.NewEncoder(os.Stdout)
|
||||||
|
|
||||||
|
if err = enc.Encode(cfg); err != nil {
|
||||||
|
return fmt.Errorf("could not encode: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func startClient(configFile string, logger *logrus.Logger) error {
|
||||||
clientConfig, err := config.New(configFile)
|
clientConfig, err := config.New(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("could not configure client")
|
return fmt.Errorf("could not configure client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
commands := make(chan *protocol.Command)
|
commands := make(chan *protocol.Command)
|
||||||
|
@ -81,12 +126,12 @@ func main() {
|
||||||
|
|
||||||
clientHandler, err := handler.New(clientConfig, logger, commands, callbacks)
|
clientHandler, err := handler.New(clientConfig, logger, commands, callbacks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("could not setup client handler")
|
return fmt.Errorf("could not setup client handler: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
signerClient, err := client.New(clientConfig, logger, clientHandler, commands, callbacks)
|
signerClient, err := client.New(clientConfig, logger, clientHandler, commands, callbacks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("could not setup client")
|
return fmt.Errorf("could not setup client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() { _ = signerClient.Close() }()
|
defer func() { _ = signerClient.Close() }()
|
||||||
|
@ -94,6 +139,8 @@ func main() {
|
||||||
logger.Info("setup complete, starting client operation")
|
logger.Info("setup complete, starting client operation")
|
||||||
|
|
||||||
if err = signerClient.Run(context.Background()); err != nil {
|
if err = signerClient.Run(context.Background()); err != nil {
|
||||||
logger.WithError(err).Fatal("error in client")
|
return fmt.Errorf("error in client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -432,24 +432,16 @@ func (c *Client) updateCRL(d *messages.FetchCRLResponse) ([]*protocol.Command, e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) buildCRLFileName(caName string) string {
|
func (c *Client) buildCRLFileName(caName string) string {
|
||||||
return path.Join(c.config.PublicDataDirectory, fmt.Sprintf("%s.crl", caName))
|
return path.Join(c.config.PublicCRLDirectory, fmt.Sprintf("%s.crl", caName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) buildCertificateFileName(caName string, certFormat string) string {
|
func (c *Client) buildCertificateFileName(caName string, certFormat string) string {
|
||||||
return path.Join(c.config.PublicDataDirectory, fmt.Sprintf("%s.%s", caName, certFormat))
|
return path.Join(c.config.PublicCRLDirectory, fmt.Sprintf("%s.%s", caName, certFormat))
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ensurePublicDataDirectory() error {
|
|
||||||
if err := os.MkdirAll(c.config.PublicDataDirectory, worldReadableDirPerm); err != nil {
|
|
||||||
return fmt.Errorf("could not create public CA data directory %s: %w", c.config.PublicDataDirectory, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) writeCertificate(caName string, derBytes []byte) error {
|
func (c *Client) writeCertificate(caName string, derBytes []byte) error {
|
||||||
if err := c.ensurePublicDataDirectory(); err != nil {
|
if err := os.MkdirAll(c.config.PublicCRLDirectory, worldReadableDirPerm); err != nil {
|
||||||
return err
|
return fmt.Errorf("could not create public CA data directory %s: %w", c.config.PublicCRLDirectory, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.WriteFile(
|
if err := os.WriteFile(
|
||||||
|
@ -470,8 +462,8 @@ func (c *Client) writeCertificate(caName string, derBytes []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) writeCRL(caName string, crlBytes []byte) error {
|
func (c *Client) writeCRL(caName string, crlBytes []byte) error {
|
||||||
if err := c.ensurePublicDataDirectory(); err != nil {
|
if err := os.MkdirAll(c.config.PublicCRLDirectory, worldReadableDirPerm); err != nil {
|
||||||
return err
|
return fmt.Errorf("could not create public CA data directory %s: %w", c.config.PublicCRLDirectory, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.WriteFile(c.buildCRLFileName(caName), crlBytes, worldReadableFilePerm); err != nil {
|
if err := os.WriteFile(c.buildCRLFileName(caName), crlBytes, worldReadableFilePerm); err != nil {
|
||||||
|
|
|
@ -59,7 +59,8 @@ type ClientConfig struct {
|
||||||
FetchCRLInterval time.Duration `yaml:"fetch-crl-interval"`
|
FetchCRLInterval time.Duration `yaml:"fetch-crl-interval"`
|
||||||
ResponseAnnounceTimeout time.Duration `yaml:"response-announce-timeout"`
|
ResponseAnnounceTimeout time.Duration `yaml:"response-announce-timeout"`
|
||||||
ResponseDataTimeout time.Duration `yaml:"response-data-timeout"`
|
ResponseDataTimeout time.Duration `yaml:"response-data-timeout"`
|
||||||
PublicDataDirectory string `yaml:"public-data-directory"`
|
PublicCRLDirectory string `yaml:"public-crl-directory"`
|
||||||
|
PublicCertificateDirectory string `yaml:"public-certificate-directory"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientConfig) UnmarshalYAML(n *yaml.Node) error {
|
func (c *ClientConfig) UnmarshalYAML(n *yaml.Node) error {
|
||||||
|
@ -71,7 +72,8 @@ func (c *ClientConfig) UnmarshalYAML(n *yaml.Node) error {
|
||||||
FetchCRLInterval time.Duration `yaml:"fetch-crl-interval"`
|
FetchCRLInterval time.Duration `yaml:"fetch-crl-interval"`
|
||||||
ResponseAnnounceTimeout time.Duration `yaml:"response-announce-timeout"`
|
ResponseAnnounceTimeout time.Duration `yaml:"response-announce-timeout"`
|
||||||
ResponseDataTimeout time.Duration `yaml:"response-data-timeout"`
|
ResponseDataTimeout time.Duration `yaml:"response-data-timeout"`
|
||||||
PublicDataDirectory string `yaml:"public-data-directory"`
|
PublicCRLDirectory string `yaml:"public-crl-directory"`
|
||||||
|
PublicCertificateDirectory string `yaml:"public-certificate-directory"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
err := n.Decode(&data)
|
err := n.Decode(&data)
|
||||||
|
@ -129,11 +131,17 @@ func (c *ClientConfig) UnmarshalYAML(n *yaml.Node) error {
|
||||||
|
|
||||||
c.ResponseDataTimeout = data.ResponseDataTimeout
|
c.ResponseDataTimeout = data.ResponseDataTimeout
|
||||||
|
|
||||||
if data.PublicDataDirectory == "" {
|
if data.PublicCRLDirectory == "" {
|
||||||
data.PublicDataDirectory = defaultFilesDirectory
|
data.PublicCRLDirectory = defaultFilesDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
c.PublicDataDirectory = data.PublicDataDirectory
|
c.PublicCRLDirectory = data.PublicCRLDirectory
|
||||||
|
|
||||||
|
if data.PublicCertificateDirectory == "" {
|
||||||
|
data.PublicCertificateDirectory = defaultFilesDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
c.PublicCertificateDirectory = data.PublicCRLDirectory
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue