aboutsummaryrefslogtreecommitdiff
path: root/cmd/silentct-mac
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
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')
-rw-r--r--cmd/silentct-mac/examples.help2man6
-rw-r--r--cmd/silentct-mac/main.go121
-rw-r--r--cmd/silentct-mac/name.help2man2
-rw-r--r--cmd/silentct-mac/see-also.help2man2
4 files changed, 131 insertions, 0 deletions
diff --git a/cmd/silentct-mac/examples.help2man b/cmd/silentct-mac/examples.help2man
new file mode 100644
index 0000000..f7bbff5
--- /dev/null
+++ b/cmd/silentct-mac/examples.help2man
@@ -0,0 +1,6 @@
+[EXAMPLES]
+Allowlist the current certificate in a Let's Encrypt deployment:
+
+.B $ silentct-mac -n example.org -s sikritpassword -o /var/www/example.org/silent-ct/allowlist /etc/letsencrypt/live/example.org/fullchain.pem
+
+You may run the above as part of your crontab or certbot renewal configuration.
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))
+}
diff --git a/cmd/silentct-mac/name.help2man b/cmd/silentct-mac/name.help2man
new file mode 100644
index 0000000..d7f6a28
--- /dev/null
+++ b/cmd/silentct-mac/name.help2man
@@ -0,0 +1,2 @@
+[NAME]
+silentct-mac - allowlist certificates with message authentication codes
diff --git a/cmd/silentct-mac/see-also.help2man b/cmd/silentct-mac/see-also.help2man
new file mode 100644
index 0000000..02987dc
--- /dev/null
+++ b/cmd/silentct-mac/see-also.help2man
@@ -0,0 +1,2 @@
+[SEE ALSO]
+.BR silentct-mon (1)