diff --git a/go.mod b/go.mod index bad1ae36c682a5179dc37b190fbc5abcca6509e3..bae34b734eca324abe609f70eb1fb5126b2ca9e8 100644 --- a/go.mod +++ b/go.mod @@ -3,3 +3,5 @@ module acme-web go 1.17 require github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 + +require gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 42c4f03ee7f02e36f597b135d88d499cbe301eee..a526d8490b325f04f4d5294eae98c4fc84433880 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,4 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/main.go b/main.go index 69a449ec00f714468494ec39f5a2c62c2b4eb366..a38067ab758c287121d4baab28ff8b68052b8d1e 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/docopt/docopt-go" + "gopkg.in/ini.v1" ) var ( @@ -17,6 +18,7 @@ var ( buildTime string webDir string jsonConverter string + bearerToken string WarningLogger *log.Logger InfoLogger *log.Logger ErrorLogger *log.Logger @@ -65,6 +67,33 @@ func renderPage(w http.ResponseWriter, req *http.Request) { http.ServeFile(w, req, serveFile) } +// trigger puppet +func triggerPuppet(w http.ResponseWriter, req *http.Request) { + cmd := exec.Command("/usr/bin/pkill", "-f", "/opt/puppetlabs/puppet/bin/puppet", "-s", "SIGUSR1") + authToken := strings.Split(req.Header.Get("Authorization"), "Bearer ")[1] + statusFile := "/tmp/200.json" + + // create json files on the fly + okMsg := []byte("{\n \"status\": \"OK\",\n \"response\": 200\n }") + koMsg := []byte("{\n \"status\": \"KO\",\n \"response\": 503\n }") + okErr := os.WriteFile("/tmp/200.json", okMsg, 0644) + koErr := os.WriteFile("/tmp/503.json", koMsg, 0644) + if okErr != nil || koErr != nil { + statusFile = "/tmp/503.json" + w.WriteHeader(http.StatusUnauthorized) + } else if authToken != bearerToken { + statusFile = "/tmp/503.json" + w.WriteHeader(http.StatusUnauthorized) + } else { + cmd.Run() + if verboseBool { + InfoLogger.Printf("HTTP Status %v", http.StatusOK) + } + w.Header().Set("Content-Type", "application/json") + } + http.ServeFile(w, req, statusFile) +} + // function redirect func redirect(w http.ResponseWriter, req *http.Request) { redirectURL := filepath.Join(req.URL.Path, "/by_name.html") @@ -76,7 +105,7 @@ func main() { progName := filepath.Base(os.Args[0]) usage := fmt.Sprintf(`ACME Web: - - serve ACME HTML pages + - serve ACME HTML pages, trigger Puppet, expose API Usage: %v [--json-converter=JSONCONVERTER] [--listen-address=LISTENADDRESS] [--listen-port=LISTENPORT] [--verbose] @@ -85,13 +114,13 @@ Usage: %v -v | --version Options: - -h --help Show this screen - -b --build Print version and build information and exit - -v --version Print version information and exit - --json-converter=JSONCONVERTER Path to json converter script [default: /usr/bin/cert2json.py] - --listen-address=LISTENADDRESS Web server address. Check Go net/http documentation [default: any] - --listen-port=LISTENPORT Web server port [default: 8000] - --verbose Log also successful connections + -h --help Show this screen + -b --build Print version and build information and exit + -v --version Print version information and exit + --json-converter=JSONCONVERTER Path to json converter script [default: /usr/bin/cert2json.py] + --listen-address=LISTENADDRESS Web server address. Check Go net/http documentation [default: any] + --listen-port=LISTENPORT Web server port [default: 8000] + --verbose Log also successful connections `, progName, progName, progName, progName) arguments, _ := docopt.ParseArgs(usage, nil, appVersion) @@ -101,6 +130,13 @@ Options: os.Exit(0) } + cfg, err := ini.Load("/root/.acme.ini") + if err != nil { + fmt.Printf("Fail to read file: %v", err) + os.Exit(1) + } + bearerToken = fmt.Sprintf("Bearer %v", cfg.Section("acme").Key("bearer_token").String()) + webDir = "/var/www/acme_web" jsonConverter = arguments["--json-converter"].(string) verboseBool = arguments["--verbose"].(bool) @@ -116,10 +152,13 @@ Options: "/sectigo_ov/sectigo_ov.json", "/sectigo_ov/sectigo_ov_expired.json", "/sectigo_ev/by_name.html", "/sectigo_ev/by_date.html", "/sectigo_ev/sectigo_ev.json", "/sectigo_ev/sectigo_ev_expired.json"} + puppetURL := "/puppet" fs := http.FileServer(http.Dir("/var/www/acme_web/static")) http.Handle("/static/", http.StripPrefix("/static/", fs)) + http.HandleFunc(puppetURL, triggerPuppet) + http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) { http.ServeFile(res, req, filepath.Join(webDir, "index.html")) })