aboutsummaryrefslogtreecommitdiff
path: root/cmd/silentct-mac/main.go
diff options
context:
space:
mode:
authorRasmus Dahlberg <rgdd@glasklarteknik.se>2024-05-16 12:48:22 +0200
committerRasmus Dahlberg <rgdd@glasklarteknik.se>2024-05-16 17:26:38 +0200
commitaba0f17953c9947bb51e78ed581f4e66b7012518 (patch)
tree6fbbbfe369224ca17088e429e49082f6ce9d5f5a /cmd/silentct-mac/main.go
parent6567c8f4ec3eefb855c6ef630a53b0fb8d8bf1e9 (diff)
Add man pages and installer Makefile
Includes renaming of the tools, part one of trying to simplify terminology and letting go of "node" and "moon". Improving the terminology was suggested by Martin H a while back, thank you.
Diffstat (limited to 'cmd/silentct-mac/main.go')
-rw-r--r--cmd/silentct-mac/main.go121
1 files changed, 121 insertions, 0 deletions
diff --git a/cmd/silentct-mac/main.go b/cmd/silentct-mac/main.go
new file mode 100644
index 0000000..2add812
--- /dev/null
+++ b/cmd/silentct-mac/main.go
@@ -0,0 +1,121 @@
+package main
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+
+ "rgdd.se/silent-ct/internal/flagopt"
+ "rgdd.se/silent-ct/internal/ioutil"
+ "rgdd.se/silent-ct/internal/logger"
+ "rgdd.se/silent-ct/pkg/crtutil"
+ "rgdd.se/silent-ct/pkg/policy"
+ "rgdd.se/silent-ct/pkg/submission"
+)
+
+const usage = `
+silentct-mac is a utility that helps allowlist legitimately issued certificates
+while monitoring Certificate Transparency logs. One or more certificate chains
+are bundled with a message authentication code, such that the silentct-mon tool
+can fetch them over an insecure channel or from untrusted intermediary storage.
+
+Usage: silentct-mac [Options] -n NAME -s SECRET CRT-FILE [CRT-FILE ...]
+
+Options:
+ -n, --name Name of the system that allowlists certificates
+ -o, --output Filename to write allowlisted certificates to (default: stdout)
+ -s, --secret Shared secret between the allowlisting system and its monitor
+ -v, --verbosity Leveled logging output (default: NOTICE)
+`
+
+type config struct {
+ // Options
+ name string
+ output string
+ secret string
+ verbosity string
+
+ // Extracted
+ log *logger.Logger
+ files []string
+}
+
+func configure(cmd string, args []string) (cfg config, err error) {
+ fs := flag.NewFlagSet(cmd, flag.ContinueOnError)
+ fs.Usage = func() {}
+ flagopt.StringOpt(fs, &cfg.name, "name", "n", "")
+ flagopt.StringOpt(fs, &cfg.output, "output", "o", "")
+ flagopt.StringOpt(fs, &cfg.secret, "secret", "s", "")
+ flagopt.StringOpt(fs, &cfg.verbosity, "verbosity", "v", logger.LevelNotice.String())
+ if err = fs.Parse(args); err != nil {
+ return cfg, err
+ }
+
+ // Options
+ if cfg.name == "" {
+ return cfg, fmt.Errorf("node name is required")
+ }
+ if cfg.secret == "" {
+ return cfg, fmt.Errorf("node secret is required")
+ }
+ lv, err := logger.NewLevel(cfg.verbosity)
+ if err != nil {
+ return cfg, fmt.Errorf("invalid verbosity: %v", err)
+ }
+ cfg.log = logger.New(logger.Config{Level: lv, File: os.Stderr})
+
+ // Arguments
+ cfg.files = fs.Args()
+ if len(cfg.files) == 0 {
+ return cfg, fmt.Errorf("at least one certificate chain file is required")
+ }
+
+ return cfg, err
+}
+
+func main() {
+ cfg, err := configure(os.Args[0], os.Args[1:])
+ if err != nil {
+ if errors.Is(err, flag.ErrHelp) {
+ fmt.Fprintf(os.Stdout, "%s", usage[1:])
+ os.Exit(0)
+ }
+ if !strings.Contains(err.Error(), "flag provided but not defined") {
+ fmt.Fprintf(os.Stdout, "%v\n", err)
+ }
+ os.Exit(1)
+ }
+
+ var chains [][]byte
+ for i, path := range cfg.files {
+ b, err := ioutil.ReadData(path)
+ if err != nil {
+ cfg.log.Dief("file %d: %v\n", i, err)
+ }
+ if _, err := crtutil.CertificateChainFromPEM(b); err != nil {
+ cfg.log.Dief("file %d: %v\n", i, err)
+ }
+
+ chains = append(chains, b)
+ }
+
+ node, err := policy.NewNode(cfg.name, cfg.secret, "http://www.example.org/unused", nil)
+ if err != nil {
+ cfg.log.Dief("api: %v\n", err)
+ }
+ s, err := submission.New(node, chains)
+ if err != nil {
+ cfg.log.Dief("api: %v\n", err)
+ }
+
+ fp := os.Stdout
+ if cfg.output != "" {
+ if fp, err = os.OpenFile(cfg.output, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
+ cfg.log.Dief("output: %v\n", err)
+ }
+ }
+
+ fmt.Fprintf(fp, "%s", string(s))
+}