Execute scripts under $CERTSPOTTER_CONFIG_DIR/hooks.d, if it exists
This commit is contained in:
parent
d08ad53464
commit
fd0a2a4d44
|
@ -99,6 +99,9 @@ func defaultWatchListPathIfExists() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func defaultScriptDir() string {
|
||||||
|
return filepath.Join(defaultConfigDir(), "hooks.d")
|
||||||
|
}
|
||||||
|
|
||||||
func readWatchListFile(filename string) (monitor.WatchList, error) {
|
func readWatchListFile(filename string) (monitor.WatchList, error) {
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
|
@ -162,11 +165,6 @@ func main() {
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(flags.email) == 0 && len(flags.script) == 0 && flags.stdout == false {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s: at least one of -email, -script, or -stdout must be specified (see -help for details)\n", programName)
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &monitor.Config{
|
config := &monitor.Config{
|
||||||
LogListSource: flags.logs,
|
LogListSource: flags.logs,
|
||||||
StateDir: flags.stateDir,
|
StateDir: flags.stateDir,
|
||||||
|
@ -174,11 +172,22 @@ func main() {
|
||||||
StartAtEnd: flags.startAtEnd,
|
StartAtEnd: flags.startAtEnd,
|
||||||
Verbose: flags.verbose,
|
Verbose: flags.verbose,
|
||||||
Script: flags.script,
|
Script: flags.script,
|
||||||
|
ScriptDir: defaultScriptDir(),
|
||||||
Email: flags.email,
|
Email: flags.email,
|
||||||
Stdout: flags.stdout,
|
Stdout: flags.stdout,
|
||||||
HealthCheckInterval: flags.healthcheck,
|
HealthCheckInterval: flags.healthcheck,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(config.Email) == 0 && config.Script == "" && !fileExists(config.ScriptDir) && config.Stdout == false {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s: no notification methods were specified\n", programName)
|
||||||
|
fmt.Fprintf(os.Stderr, "Please specify at least one of the following notification methods:\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " - Place one or more executable scripts in the %s directory\n", config.ScriptDir)
|
||||||
|
fmt.Fprintf(os.Stderr, " - Specify an email address using the -email flag\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " - Specify the path to an executable script using the -script flag\n")
|
||||||
|
fmt.Fprintf(os.Stderr, " - Specify the -stdout flag\n")
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
if flags.watchlist == "-" {
|
if flags.watchlist == "-" {
|
||||||
watchlist, err := monitor.ReadWatchList(os.Stdin)
|
watchlist, err := monitor.ReadWatchList(os.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -21,6 +21,7 @@ type Config struct {
|
||||||
Verbose bool
|
Verbose bool
|
||||||
SaveCerts bool
|
SaveCerts bool
|
||||||
Script string
|
Script string
|
||||||
|
ScriptDir string
|
||||||
Email []string
|
Email []string
|
||||||
Stdout bool
|
Stdout bool
|
||||||
HealthCheckInterval time.Duration
|
HealthCheckInterval time.Duration
|
||||||
|
|
|
@ -12,9 +12,12 @@ package monitor
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
@ -44,6 +47,12 @@ func notify(ctx context.Context, config *Config, notif notification) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.ScriptDir != "" {
|
||||||
|
if err := execScriptDir(ctx, config.ScriptDir, notif); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +113,32 @@ func execScript(ctx context.Context, scriptName string, notif notification) erro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func execScriptDir(ctx context.Context, dirPath string, notif notification) error {
|
||||||
|
dirents, err := os.ReadDir(dirPath)
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return fmt.Errorf("error executing scripts in directory %q: %w", dirPath, err)
|
||||||
|
}
|
||||||
|
for _, dirent := range dirents {
|
||||||
|
if strings.HasPrefix(dirent.Name(), ".") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
scriptPath := filepath.Join(dirPath, dirent.Name())
|
||||||
|
info, err := os.Stat(scriptPath)
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return fmt.Errorf("error executing %q in directory %q: %w", dirent.Name(), dirPath, err)
|
||||||
|
} else if info.Mode().IsRegular() && isExecutable(info.Mode()) {
|
||||||
|
if err := execScript(ctx, scriptPath, notif); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func isExecutable(mode os.FileMode) bool {
|
func isExecutable(mode os.FileMode) bool {
|
||||||
return mode&0111 != 0
|
return mode&0111 != 0
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue