From 3e088d4af75b405ee305e360a1b7c7911e9a7893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sat, 4 Dec 2021 10:40:15 +0100 Subject: [PATCH] New configuration for commands/handlers to run after updates * The new configuration includes specific commands per file, as well as handlers that can be triggered by updates but will only ever run once. * For now, commands from the pre_commands section are executed, the rest is ignored --- buildcert.go | 8 ++++---- config.go | 32 +++++++++++++++++++++----------- fetch-certificates.yml.example | 23 ++++++++++++++++++++--- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/buildcert.go b/buildcert.go index 4853c8d..b6e182f 100644 --- a/buildcert.go +++ b/buildcert.go @@ -206,12 +206,12 @@ func (b *tCertificateBuilder) RunCommandsIfChanged() error { log.Debug("Not running commands") return nil } - for i := range b.config.AfterUpdate { + for i := range b.config.AfterUpdate.PreCommands { err := b.RunCommand(i) if err != nil { return fmt.Errorf( "Failed while executing command '%s': %w", - b.config.AfterUpdate[i], + b.config.AfterUpdate.PreCommands[i], err, ) } @@ -224,9 +224,9 @@ func (b *tCertificateBuilder) RunCommand(pos int) error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() - log := b.logger.WithField("command", b.config.AfterUpdate[pos]) + log := b.logger.WithField("command", b.config.AfterUpdate.PreCommands[pos]) log.Debug("Executing command") - cmd := exec.CommandContext(ctx, "sh", "-c", b.config.AfterUpdate[pos]) + cmd := exec.CommandContext(ctx, "sh", "-c", b.config.AfterUpdate.PreCommands[pos]) output, err := cmd.CombinedOutput() if len(output) != 0 { if utf8.Valid(output) { diff --git a/config.go b/config.go index 7d6050a..02458fe 100644 --- a/config.go +++ b/config.go @@ -59,19 +59,29 @@ type ( Servers []tLdapServerConfig `yaml:"servers"` } + // Handlers. Each handler has a name and contains a list of commands. + tHandlers map[string][]string + + // Certificate file updates configuration. + tCertFileUpdateConfig struct { + PreCommands []string `yaml:"pre_commands"` + Handlers tHandlers `yaml:"handlers"` + PostCommands []string `yaml:"post_commands"` + } + // Certificate file configuration. tCertificateFileConfig struct { - Path string `yaml:"path"` - Mode os.FileMode `yaml:"mode"` - Owner string `yaml:"owner"` - Group string `yaml:"group"` - PrependFiles []string `yaml:"prepend_files"` - Certificate string `yaml:"certificate"` - CACertificates []string `yaml:"ca"` - CAChainOf string `yaml:"ca_chain_of"` - Reverse bool `yaml:"reverse"` - AppendFiles []string `yaml:"append_files"` - AfterUpdate []string `yaml:"after_update"` + Path string `yaml:"path"` + Mode os.FileMode `yaml:"mode"` + Owner string `yaml:"owner"` + Group string `yaml:"group"` + PrependFiles []string `yaml:"prepend_files"` + Certificate string `yaml:"certificate"` + CACertificates []string `yaml:"ca"` + CAChainOf string `yaml:"ca_chain_of"` + Reverse bool `yaml:"reverse"` + AppendFiles []string `yaml:"append_files"` + AfterUpdate tCertFileUpdateConfig `yaml:"after_update"` } // Main configuration. diff --git a/fetch-certificates.yml.example b/fetch-certificates.yml.example index 4c5d492..2d637ae 100644 --- a/fetch-certificates.yml.example +++ b/fetch-certificates.yml.example @@ -53,6 +53,15 @@ ldap: - host: ldap1.example.org - host: ldap2.example.org +# Handlers. Certificate updates can specify that a handler must be executed +# if the PEM file is replaced. A handler will only be executed once for all +# triggered updates. Each handler is a list of commands. When a handler runs, +# the first command that fails will stop the execution. +handlers: + apache: + - /usr/sbin/apache2ctl configtest + - /usr/sbin/apache2ctl graceful + # Certificates that must be updated certificates: @@ -89,7 +98,15 @@ certificates: # A list of files to append to the output. append_files: - /some/other/file.pem - # A list of commands that will be executed when the file is replaced. - # If one of the commands fails, execution will stop. + # Define what must be done after an update. after_update: - - apache2ctl graceful + # Commands to execute before handlers are run. The order of the commands + # is respected. If a command fails to run, execution stops. + pre_commands: [] + # Handlers to trigger. Handlers will still be executed if a pre-command + # had failed but they were triggered by more than one update. Execution + # order is arbitrary. + handlers: + - apache + # Commands to execute after handlers are run. + post_commands: []