From 096218f68056a9bca5eec31e1f542a88ab0de66e Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sun, 20 Feb 2022 19:14:07 +0000 Subject: [PATCH 01/22] add some first working version --- README.md | 12 ++++- certcal.go | 60 ++++++++++++++++++++++++ go.mod | 8 ++++ go.sum | 7 +++ handler/handler.go | 53 ++++++++++++++++++++++ hosts/hosts.go | 111 +++++++++++++++++++++++++++++++++++++++++++++ ical/ical.go | 79 ++++++++++++++++++++++++++++++++ 7 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 certcal.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 handler/handler.go create mode 100644 hosts/hosts.go create mode 100644 ical/ical.go diff --git a/README.md b/README.md index 885c94d..3174661 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,12 @@ # certcal -provide an iCal web feed for certificate expiry + +Provide an iCal web feed for certificate expiry + + +## Usage + +### Standalone + + +### As part of an existing http mux + diff --git a/certcal.go b/certcal.go new file mode 100644 index 0000000..e213c77 --- /dev/null +++ b/certcal.go @@ -0,0 +1,60 @@ +package main + +import ( + "github.com/mrtazz/certcal/handler" + "github.com/mrtazz/certcal/hosts" + log "github.com/sirupsen/logrus" + "net/http" + "os" + "strings" + "time" +) + +func main() { + + log.SetFormatter(&log.TextFormatter{ + FullTimestamp: true, + }) + logger := log.WithFields(log.Fields{ + "package": "main", + }) + + checkHosts := os.Getenv("CERTCAL_HOSTS") + if checkHosts == "" { + logger.Error("missing env var CERTCAL_HOSTS") + os.Exit(1) + } + + var duration time.Duration + durationString := os.Getenv("CERTCAL_INTERVAL") + switch durationString { + case "": + logger.Error("missing env var CERTCAL_INTERVAL, defaulting to 1 day") + duration = 24 * time.Hour + default: + var err error + duration, err = time.ParseDuration(durationString) + if err != nil { + logger.Error("unable to parse CERTCAL_INTERVAL, defaulting to 1 day") + duration = 24 * time.Hour + } + } + + var port string + if port = os.Getenv("PORT"); port == "" { + port = "3000" + } + + hosts.AddHosts(strings.Split(checkHosts, ",")) + hosts.UpdateEvery(duration) + + address := ":" + port + + logger.WithFields(log.Fields{ + "address": address, + }).Info("starting web server") + http.HandleFunc("/hosts", handler.Handler) + //http.HandleFunc("/metrics", headers) + http.ListenAndServe(address, nil) + +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c0a6fd3 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/mrtazz/certcal + +go 1.17 + +require ( + github.com/sirupsen/logrus v1.8.1 // indirect + golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..58fa35a --- /dev/null +++ b/go.sum @@ -0,0 +1,7 @@ +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/handler/handler.go b/handler/handler.go new file mode 100644 index 0000000..a56b066 --- /dev/null +++ b/handler/handler.go @@ -0,0 +1,53 @@ +package handler + +import ( + "fmt" + "github.com/mrtazz/certcal/hosts" + "github.com/mrtazz/certcal/ical" + log "github.com/sirupsen/logrus" + "net/http" + "time" +) + +const ( + contentType = "application/octet-stream" +) + +var ( + logger = log.WithFields(log.Fields{ + "package": "handler", + }) +) + +// Handler implements the ical handler +func Handler(w http.ResponseWriter, req *http.Request) { + checkedHosts := hosts.GetHosts() + cal := ical.Calendar{ + Events: make([]ical.Event, 0, len(checkedHosts)), + } + + for _, h := range checkedHosts { + if len(h.Certs) > 0 { + cal.Events = append(cal.Events, + ical.Event{ + CreatedAt: time.Now(), + LastModified: time.Now(), + DtStamp: time.Now(), + Summary: fmt.Sprintf("cert for %s expires", h.HostString), + Start: h.Certs[0].NotAfter, + End: h.Certs[0].NotAfter, + URL: "", + Description: fmt.Sprintf("cert for %s expires", h.HostString), + }) + } + } + + out, err := cal.Render() + if err != nil { + logger.Error(err) + w.WriteHeader(http.StatusInternalServerError) + } + + w.Header().Set("Content-Type", contentType) + fmt.Fprintf(w, out) +} diff --git a/hosts/hosts.go b/hosts/hosts.go new file mode 100644 index 0000000..f5f9ea1 --- /dev/null +++ b/hosts/hosts.go @@ -0,0 +1,111 @@ +package hosts + +import ( + "crypto/tls" + "crypto/x509" + log "github.com/sirupsen/logrus" + "net" + "strings" + "sync" + "time" +) + +var ( + info []*Info + lock sync.Mutex + done = make(chan bool) + logger = log.WithFields(log.Fields{ + "package": "hosts", + }) +) + +// GetHosts returns all configured hosts +func GetHosts() []*Info { + lock.Lock() + defer lock.Unlock() + return info +} + +// UpdateEvery runs an update on all hosts every interval +func UpdateEvery(interval time.Duration) { + ticker := time.NewTicker(interval) + go func() { + for { + select { + case <-done: + return + case <-ticker.C: + logger.Info("updating hosts") + updateAllHosts() + } + } + }() +} + +func updateAllHosts() { + lock.Lock() + defer lock.Unlock() + for _, i := range info { + logger.WithFields(log.Fields{ + "host": i.HostString, + }).Info("retrieving certs") + i.GetCerts(5 * time.Second) + } +} + +// Info provides information for a host +type Info struct { + HostString string + Certs []*x509.Certificate +} + +// AddHost adds a new host to watch +func AddHost(hostString string) { + if !strings.Contains(hostString, ":") { + hostString = hostString + ":443" + } + info = append(info, &Info{ + HostString: hostString, + }) +} + +// AddHosts adds a set of hosts to watch +func AddHosts(hostStrings []string) { + for _, h := range hostStrings { + AddHost(h) + } +} + +// GetCerts retrieves certs for the configure Host +func (i *Info) GetCerts(timeout time.Duration) error { + dialer := &net.Dialer{Timeout: timeout} + conn, err := tls.DialWithDialer(dialer, "tcp", i.HostString, + &tls.Config{ + InsecureSkipVerify: true, + }) + if err != nil { + return err + } + + defer conn.Close() + + if err := conn.Handshake(); err != nil { + return err + } + + peerCerts := conn.ConnectionState().PeerCertificates + i.Certs = make([]*x509.Certificate, 0, len(peerCerts)) + logger.WithFields(log.Fields{ + "num_certs": len(peerCerts), + "host": i.HostString, + }).Info("found certs") + + for _, cert := range peerCerts { + if cert.IsCA { + continue + } + i.Certs = append(i.Certs, cert) + } + + return nil +} diff --git a/ical/ical.go b/ical/ical.go new file mode 100644 index 0000000..3d86aee --- /dev/null +++ b/ical/ical.go @@ -0,0 +1,79 @@ +package ical + +import ( + "bytes" + "text/template" + "time" +) + +// general calendar format +//BEGIN:VCALENDAR +//VERSION:2.0 +//METHOD:PUBLISH +//PRODID:-//schulferien.org//iCal Generator//DE +//BEGIN:VEVENT +//CREATED:20220110T032314Z +//LAST-MODIFIED:20220110T032314Z +//DTSTAMP:20220110T032314Z +//SUMMARY:Winterferien 2021 Berlin +//DTSTART;VALUE=DATE:20210201 +//DTEND;VALUE=DATE:20210207 +//URL:http://www.schulferien.org +//DESCRIPTION:Alle Termine auf www.schulferien.org +//TRANSP:TRANSPARENT +//UID:F_2021_termin61db9894553f9@schulferien.org +//END:VEVENT +//END:VCALENDAR + +const ( + icalTemplate = `BEGIN:VCALENDAR +VERSION:2.0 +METHOD:PUBLISH +PRODID:-//github.com/mrtazz/certcal//iCal cert feed//EN +{{- range .Events }} +BEGIN:VEVENT +CREATED:{{ .CreatedAt.Format "20060102T150405Z" }} +LAST-MODIFIED:{{ .LastModified.Format "20060102T150405Z" }} +DTSTAMP:{{ .DtStamp.Format "20060102T150405Z"}} +SUMMARY:{{ .Summary }} +DTSTART;VALUE=DATE:{{ .Start.Format "20060102"}} +DTEND;VALUE=DATE:{{ .End.Format "20060102"}} +URL:{{ .URL }} +DESCRIPTION:{{ .Description }} +TRANSP:TRANSPARENT +UID: @certcal.mrtazz.github.com +END:VEVENT +{{- end }} +END:VCALENDAR` +) + +// Event represents a calendar +type Event struct { + CreatedAt time.Time + LastModified time.Time + DtStamp time.Time + Summary string + Start time.Time + End time.Time + URL string + Description string +} + +// Calendar represents a calendar feed +type Calendar struct { + Events []Event +} + +// Render a calendar feed +func (c *Calendar) Render() (string, error) { + tmpl, err := template.New("feed").Parse(icalTemplate) + if err != nil { + return "", err + } + var tpl bytes.Buffer + err = tmpl.Execute(&tpl, c) + if err != nil { + return "", err + } + return tpl.String(), nil +} From 9e64e234c4f5c7e8ecdfe35d3771f8a82a1709a4 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sun, 20 Feb 2022 19:18:24 +0000 Subject: [PATCH 02/22] add first testing scaffold --- go.mod | 9 ++++++++- go.sum | 10 ++++++++++ ical/ical_test.go | 11 +++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 ical/ical_test.go diff --git a/go.mod b/go.mod index c0a6fd3..2b3c2ba 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,13 @@ module github.com/mrtazz/certcal go 1.17 require ( - github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sirupsen/logrus v1.8.1 + github.com/stretchr/testify v1.7.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/go.sum b/go.sum index 58fa35a..d2ec8fa 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,17 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ical/ical_test.go b/ical/ical_test.go new file mode 100644 index 0000000..5d3a1be --- /dev/null +++ b/ical/ical_test.go @@ -0,0 +1,11 @@ +package ical + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestRender(t *testing.T) { + assert := assert.New(t) + +} From 4d9e1ddaa90bfac441f9c9d660beb0ef542a8691 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sun, 20 Feb 2022 19:20:08 +0000 Subject: [PATCH 03/22] add action for tests --- .github/workflows/tests.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..d893ff9 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,23 @@ +name: CI +on: push +jobs: + + test: + name: Build + runs-on: ubuntu-latest + steps: + + - name: Set up Go 1.17 + uses: actions/setup-go@v2 + with: + go-version: 1.17 + id: go + + - name: Check out code + uses: actions/checkout@v2 + with: + fetch-depth: 1 + + - name: Run tests + run: | + go test -v ./... From 6988a323a3e84c64b963030e4191a5d7d24e9e25 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sun, 20 Feb 2022 19:20:44 +0000 Subject: [PATCH 04/22] tests are tests --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d893ff9..f6fd21e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -3,7 +3,7 @@ on: push jobs: test: - name: Build + name: test runs-on: ubuntu-latest steps: From ea58ed29736764aa29fdff2894725a76ccc18f1d Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Mon, 21 Feb 2022 08:37:14 +0000 Subject: [PATCH 05/22] add basic ical rendering test --- ical/ical.go | 19 ------------------ ical/ical_test.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/ical/ical.go b/ical/ical.go index 3d86aee..1a8c2e7 100644 --- a/ical/ical.go +++ b/ical/ical.go @@ -6,25 +6,6 @@ import ( "time" ) -// general calendar format -//BEGIN:VCALENDAR -//VERSION:2.0 -//METHOD:PUBLISH -//PRODID:-//schulferien.org//iCal Generator//DE -//BEGIN:VEVENT -//CREATED:20220110T032314Z -//LAST-MODIFIED:20220110T032314Z -//DTSTAMP:20220110T032314Z -//SUMMARY:Winterferien 2021 Berlin -//DTSTART;VALUE=DATE:20210201 -//DTEND;VALUE=DATE:20210207 -//URL:http://www.schulferien.org -//DESCRIPTION:Alle Termine auf www.schulferien.org -//TRANSP:TRANSPARENT -//UID:F_2021_termin61db9894553f9@schulferien.org -//END:VEVENT -//END:VCALENDAR - const ( icalTemplate = `BEGIN:VCALENDAR VERSION:2.0 diff --git a/ical/ical_test.go b/ical/ical_test.go index 5d3a1be..78af527 100644 --- a/ical/ical_test.go +++ b/ical/ical_test.go @@ -3,9 +3,58 @@ package ical import ( "github.com/stretchr/testify/assert" "testing" + "time" ) -func TestRender(t *testing.T) { +func TestSomething(t *testing.T) { + + testDate := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) assert := assert.New(t) + tests := map[string]struct { + input Calendar + want string + }{ + "simple": { + input: Calendar{ + Events: []Event{ + { + CreatedAt: testDate, + LastModified: testDate, + DtStamp: testDate, + Summary: "test event", + Start: testDate, + End: testDate, + URL: "", + Description: "description of test event", + }, + }, + }, + want: `BEGIN:VCALENDAR +VERSION:2.0 +METHOD:PUBLISH +PRODID:-//github.com/mrtazz/certcal//iCal cert feed//EN +BEGIN:VEVENT +CREATED:20091110T230000Z +LAST-MODIFIED:20091110T230000Z +DTSTAMP:20091110T230000Z +SUMMARY:test event +DTSTART;VALUE=DATE:20091110 +DTEND;VALUE=DATE:20091110 +URL: +DESCRIPTION:description of test event +TRANSP:TRANSPARENT +UID: @certcal.mrtazz.github.com +END:VEVENT +END:VCALENDAR`, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + out, err := tc.input.Render() + assert.Equal(nil, err) + assert.Equal(tc.want, out) + }) + } } From b39f320a13e9ccdbcfea94ff38111d2619f3a760 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Mon, 21 Feb 2022 08:54:11 +0000 Subject: [PATCH 06/22] add unique IDs to calendar events --- handler/handler.go | 21 ++++++++++----------- ical/ical.go | 11 ++++++++++- ical/ical_test.go | 35 +++++++++++++++++++---------------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/handler/handler.go b/handler/handler.go index a56b066..abc3e02 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -28,17 +28,16 @@ func Handler(w http.ResponseWriter, req *http.Request) { for _, h := range checkedHosts { if len(h.Certs) > 0 { - cal.Events = append(cal.Events, - ical.Event{ - CreatedAt: time.Now(), - LastModified: time.Now(), - DtStamp: time.Now(), - Summary: fmt.Sprintf("cert for %s expires", h.HostString), - Start: h.Certs[0].NotAfter, - End: h.Certs[0].NotAfter, - URL: "", - Description: fmt.Sprintf("cert for %s expires", h.HostString), - }) + cal.AddEvent(ical.Event{ + CreatedAt: time.Now(), + LastModified: time.Now(), + DtStamp: time.Now(), + Summary: fmt.Sprintf("cert for %s expires", h.HostString), + Start: h.Certs[0].NotAfter, + End: h.Certs[0].NotAfter, + URL: "", + Description: fmt.Sprintf("cert for %s expires", h.HostString), + }) } } diff --git a/ical/ical.go b/ical/ical.go index 1a8c2e7..ddad60e 100644 --- a/ical/ical.go +++ b/ical/ical.go @@ -2,6 +2,8 @@ package ical import ( "bytes" + "crypto/sha256" + "fmt" "text/template" "time" ) @@ -22,7 +24,7 @@ DTEND;VALUE=DATE:{{ .End.Format "20060102"}} URL:{{ .URL }} DESCRIPTION:{{ .Description }} TRANSP:TRANSPARENT -UID: @certcal.mrtazz.github.com +UID:{{ .UID }}@certcal.mrtazz.github.com END:VEVENT {{- end }} END:VCALENDAR` @@ -38,6 +40,7 @@ type Event struct { End time.Time URL string Description string + UID string } // Calendar represents a calendar feed @@ -45,6 +48,12 @@ type Calendar struct { Events []Event } +// AddEvent adds an event to the calendar +func (c *Calendar) AddEvent(e Event) { + e.UID = fmt.Sprintf("%x", sha256.Sum256([]byte(e.Summary))) + c.Events = append(c.Events, e) +} + // Render a calendar feed func (c *Calendar) Render() (string, error) { tmpl, err := template.New("feed").Parse(icalTemplate) diff --git a/ical/ical_test.go b/ical/ical_test.go index 78af527..d379eea 100644 --- a/ical/ical_test.go +++ b/ical/ical_test.go @@ -11,22 +11,20 @@ func TestSomething(t *testing.T) { testDate := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) assert := assert.New(t) tests := map[string]struct { - input Calendar - want string + events []Event + want string }{ "simple": { - input: Calendar{ - Events: []Event{ - { - CreatedAt: testDate, - LastModified: testDate, - DtStamp: testDate, - Summary: "test event", - Start: testDate, - End: testDate, - URL: "", - Description: "description of test event", - }, + events: []Event{ + { + CreatedAt: testDate, + LastModified: testDate, + DtStamp: testDate, + Summary: "test event", + Start: testDate, + End: testDate, + URL: "", + Description: "description of test event", }, }, want: `BEGIN:VCALENDAR @@ -43,7 +41,7 @@ DTEND;VALUE=DATE:20091110 URL: DESCRIPTION:description of test event TRANSP:TRANSPARENT -UID: @certcal.mrtazz.github.com +UID:3f81ea40a91ac4d91eda58327fcfae58bc6b6e8535a4531bb3f129e1abe7c0bc@certcal.mrtazz.github.com END:VEVENT END:VCALENDAR`, }, @@ -52,7 +50,12 @@ END:VCALENDAR`, for name, tc := range tests { t.Run(name, func(t *testing.T) { - out, err := tc.input.Render() + c := Calendar{} + for _, e := range tc.events { + c.AddEvent(e) + } + + out, err := c.Render() assert.Equal(nil, err) assert.Equal(tc.want, out) }) From 1fcc3103336168d73663150fb005c9b6c01e336c Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Mon, 21 Feb 2022 12:44:50 +0000 Subject: [PATCH 07/22] add Docker build --- .github/workflows/docker-build.yml | 15 +++++++++++++++ Dockerfile | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 .github/workflows/docker-build.yml create mode 100644 Dockerfile diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000..f530211 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,15 @@ +name: docker + +on: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + name: build + + steps: + - uses: actions/checkout@v2 + + - name: Build image + run: docker build . --file Dockerfile --tag github.com/mrtazz/certcal diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f66f02a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM golang:1.17-alpine3.15 AS builder + +RUN mkdir /app + +WORKDIR /app + +ADD . /app/ + +RUN go build certcal.go - certcal + +FROM alpine:3.15 +RUN apk --no-cache add ca-certificates + +WORKDIR /app +COPY --from=builder /app/certcal /app/certcal +RUN chown -R nobody /app && chmod +x /app/certcal + +USER nobody +ENV PORT=3000 +ENV CERTCAL_HOSTS="unwiredcouch.com,github.com" +ENTRYPOINT ["/app/certcal"] From 276679778557269007048758c317f5e93b91dc36 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Mon, 21 Feb 2022 12:49:41 +0000 Subject: [PATCH 08/22] forgot -o --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f66f02a..dcd41ba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ WORKDIR /app ADD . /app/ -RUN go build certcal.go - certcal +RUN go build certcal.go -o certcal FROM alpine:3.15 RUN apk --no-cache add ca-certificates From 9654a2b3ad9fcb0d361c5871efbeabbb7dfed07c Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Mon, 21 Feb 2022 14:40:31 +0000 Subject: [PATCH 09/22] fix go build argument order --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index dcd41ba..a2a8fc5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ WORKDIR /app ADD . /app/ -RUN go build certcal.go -o certcal +RUN go build -o certcal certcal.go FROM alpine:3.15 RUN apk --no-cache add ca-certificates From f8cda4677dd6cce07662144d5bb0b83926f7956d Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Mon, 21 Feb 2022 14:54:08 +0000 Subject: [PATCH 10/22] update the README some more --- README.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3174661..6d1d5d9 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,64 @@ # certcal -Provide an iCal web feed for certificate expiry +Provide an iCal web feed for certificate expiry. ## Usage +There are a couple of ways to run this + ### Standalone +You can download one of the binaries and run it as a standalone: + +```shell +% PORT=3000 CERTCAL_INTERVAL=5h CERTCAL_HOSTS="unwiredcouch.com" ./certcal +``` ### As part of an existing http mux +You can include the handler in your existing mux, something along the lines +of: + +```go +import ( + "github.com/mrtazz/certcal/handler" + "github.com/mrtazz/certcal/hosts" + "net/http" + "time" +) + +func Run() { + + ... + + hosts.AddHosts([]string{"unwiredcouch.com"}) + hosts.UpdateEvery(5 * time.Hour) + + http.HandleFunc("/hosts", handler.Handler) + http.ListenAndServe(":3000", nil) + +} +``` + + +### Via Docker +There is a docker image as well that you can use + + +## FAQ + +### Shouldn't certs renew automatically? +Probably. But sometimes they aren't. + +### Shouldn't this be an alert somewhere? +Maybe, up to you. + +### Old expiry events are disappearing! +That is by design. The UID of the `VEVENT` is the `sha256sum` of the summary +of the event. Because generally if the cert got renewed the old event is just +cruft. + + +## Inspiration +[genuinetools/certok](https://github.com/genuinetools/certok) inspired this From 4de9dfd903efcfdfbc2eeedf4743d14c9997763a Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Mon, 21 Feb 2022 14:54:30 +0000 Subject: [PATCH 11/22] add LICENSE --- LICENSE | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3860573 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2022 Daniel Schauenberg + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From d3a25448f43d6b87c4cb4f648ebdf23a1de8cb92 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Mon, 21 Feb 2022 14:55:20 +0000 Subject: [PATCH 12/22] retab README --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6d1d5d9..6febe8a 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ of: ```go import ( - "github.com/mrtazz/certcal/handler" - "github.com/mrtazz/certcal/hosts" - "net/http" + "github.com/mrtazz/certcal/handler" + "github.com/mrtazz/certcal/hosts" + "net/http" "time" ) @@ -32,11 +32,11 @@ func Run() { ... - hosts.AddHosts([]string{"unwiredcouch.com"}) - hosts.UpdateEvery(5 * time.Hour) + hosts.AddHosts([]string{"unwiredcouch.com"}) + hosts.UpdateEvery(5 * time.Hour) - http.HandleFunc("/hosts", handler.Handler) - http.ListenAndServe(":3000", nil) + http.HandleFunc("/hosts", handler.Handler) + http.ListenAndServe(":3000", nil) } ``` From 81869ac6c56172d5cb9cc346719eb65420c9d93a Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Thu, 24 Feb 2022 20:28:59 +0000 Subject: [PATCH 13/22] add initial definition for a release workflow --- .github/workflows/release.yml | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..7df5e13 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,64 @@ +name: release +on: + push: + tags: + - '*' + +jobs: + release: + name: github + runs-on: ubuntu-latest + env: + BUILDER_NAME: "GitHub Actions" + BUILDER_EMAIL: noreply@actions.github.com + + steps: + + - name: Set up Go 1.17 + uses: actions/setup-go@v2 + with: + go-version: 1.17 + id: go + + - name: Check out code + uses: actions/checkout@v2 + with: + fetch-depth: 1 + + - name: build for platforms + run: | + BUILD_GOARCH=amd64 BUILD_GOOS=freebsd make build-standalone + BUILD_GOARCH=amd64 BUILD_GOOS=linux make build-standalone + BUILD_GOARCH=amd64 BUILD_GOOS=darwin make build-standalone + + - name: create release + run: make github-release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + docker: + name: docker + env: + BUILDER_NAME: "GitHub Actions" + BUILDER_EMAIL: noreply@actions.github.com + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag mrtazz/certcal:${GITHUB_SHA} --tag mrtazz/certcal:latest + + - name: push to docker hub + run: | + echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u mrtazz --password-stdin + docker push mrtazz/certcal:${GITHUB_SHA} + docker push mrtazz/certcal:latest + docker logout hub.docker.com + + - name: push to ghcr + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + docker push mrtazz/certcal:${GITHUB_SHA} + docker push mrtazz/certcal:latest + docker logout ghcr.io From 7abe8b0a367d53eb7926353ac8455d252b3ed735 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sat, 26 Feb 2022 12:50:15 +0000 Subject: [PATCH 14/22] add Makefile and .gitignore --- .gitignore | 2 ++ Makefile | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6fd55ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +certcal +.release_artifacts diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4f266a2 --- /dev/null +++ b/Makefile @@ -0,0 +1,77 @@ +# +# some housekeeping tasks +# + +# variable definitions +NAME := certcal +DESC := provide an iCal web feed for certificate expiration +PREFIX ?= usr/local +VERSION := $(shell git describe --tags --always --dirty) +GOVERSION := $(shell go version) + +BUILD_GOOS ?= $(shell go env GOOS) +BUILD_GOARCH ?= $(shell go env GOARCH) + +RELEASE_ARTIFACTS_DIR := .release_artifacts +CHECKSUM_FILE := checksums.txt + +$(RELEASE_ARTIFACTS_DIR): + install -d $@ + +BUILDER := $(shell echo "${BUILDER_NAME} <${EMAIL}>") + +PKG_RELEASE ?= 1 +PROJECT_URL := "https://github.com/mrtazz/$(NAME)" +LDFLAGS := -X 'main.version=$(VERSION)' \ + -X 'main.goversion=$(GOVERSION)' + +TARGETS := certcal +INSTALLED_TARGETS = $(addprefix $(PREFIX)/bin/, $(TARGETS)) + +certcal: certcal.go + GOOS=$(BUILD_GOOS) GOARCH=$(BUILD_GOARCH) go build -ldflags "$(LDFLAGS)" -o $@ $< + +.PHONY: all +all: $(TARGETS) $(MAN_TARGETS) +.DEFAULT_GOAL:=all + +# development tasks +.PHONY: test +test: + go test -v ./... + +.PHONY: coverage +coverage: + go test -v -race -coverprofile=cover.out ./... + @-go tool cover -html=cover.out -o cover.html + +.PHONY: benchmark +benchmark: + @echo "Running tests..." + @go test -bench=. ${NAME} + +# install tasks +$(PREFIX)/bin/%: % + install -d $$(dirname $@) + install -m 755 $< $@ + +.PHONY: install +install: $(INSTALLED_TARGETS) $(INSTALLED_MAN_TARGETS) + +.PHONY: local-install +local-install: + $(MAKE) install PREFIX=usr/local + +.PHONY: build-artifact +build-artifact: certcal $(RELEASE_ARTIFACTS_DIR) + mv certcal $(RELEASE_ARTIFACTS_DIR)/certcal-$(VERSION).$(BUILD_GOOS).$(BUILD_GOARCH) + cd $(RELEASE_ARTIFACTS_DIR) && shasum -a 256 certcal-$(VERSION).$(BUILD_GOOS).$(BUILD_GOARCH) >> $(CHECKSUM_FILE) + +.PHONY: github-release +github-release: + gh release create $(VERSION) --title 'Release $(VERSION)' --notes-file docs/releases/$(VERSION).md $(RELEASE_ARTIFACTS_DIR)/* + +# clean up tasks +.PHONY: clean +clean: + git clean -fdx From 9b231df8caaba14100815237bd30c3807b277e68 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sat, 26 Feb 2022 12:51:11 +0000 Subject: [PATCH 15/22] rename TestSomething to TestRender --- ical/ical_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ical/ical_test.go b/ical/ical_test.go index d379eea..9122fef 100644 --- a/ical/ical_test.go +++ b/ical/ical_test.go @@ -6,7 +6,7 @@ import ( "time" ) -func TestSomething(t *testing.T) { +func TestRender(t *testing.T) { testDate := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) assert := assert.New(t) From 052da7309850bb027322acb3c1a09af80f1e092a Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sat, 26 Feb 2022 12:51:50 +0000 Subject: [PATCH 16/22] use makefile in test --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f6fd21e..59555bb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,4 +20,4 @@ jobs: - name: Run tests run: | - go test -v ./... + make test From 47861e951a64b0acba94d77a6aa303fddba39d11 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sat, 26 Feb 2022 12:58:53 +0000 Subject: [PATCH 17/22] remove docker hub push the free account only allows for a single access token and I don't want to share that one between open source projects --- .github/workflows/release.yml | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7df5e13..8c1cdd3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,9 +27,9 @@ jobs: - name: build for platforms run: | - BUILD_GOARCH=amd64 BUILD_GOOS=freebsd make build-standalone - BUILD_GOARCH=amd64 BUILD_GOOS=linux make build-standalone - BUILD_GOARCH=amd64 BUILD_GOOS=darwin make build-standalone + BUILD_GOARCH=amd64 BUILD_GOOS=freebsd make build-artifact + BUILD_GOARCH=amd64 BUILD_GOOS=linux make build-artifact + BUILD_GOARCH=amd64 BUILD_GOOS=darwin make build-artifact - name: create release run: make github-release @@ -40,7 +40,7 @@ jobs: name: docker env: BUILDER_NAME: "GitHub Actions" - BUILDER_EMAIL: noreply@actions.github.com + BUILDER_EMAIL: actions@noreply.github.com runs-on: ubuntu-latest @@ -49,13 +49,6 @@ jobs: - name: Build the Docker image run: docker build . --file Dockerfile --tag mrtazz/certcal:${GITHUB_SHA} --tag mrtazz/certcal:latest - - name: push to docker hub - run: | - echo ${{ secrets.DOCKER_HUB_TOKEN }} | docker login -u mrtazz --password-stdin - docker push mrtazz/certcal:${GITHUB_SHA} - docker push mrtazz/certcal:latest - docker logout hub.docker.com - - name: push to ghcr run: | echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin From 52003bc0e15a75967bb363e40075def64eafb695 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sat, 26 Feb 2022 13:14:21 +0000 Subject: [PATCH 18/22] remove all target --- Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 4f266a2..8820a35 100644 --- a/Makefile +++ b/Makefile @@ -28,12 +28,10 @@ LDFLAGS := -X 'main.version=$(VERSION)' \ TARGETS := certcal INSTALLED_TARGETS = $(addprefix $(PREFIX)/bin/, $(TARGETS)) +.PHONY: certcal certcal: certcal.go GOOS=$(BUILD_GOOS) GOARCH=$(BUILD_GOARCH) go build -ldflags "$(LDFLAGS)" -o $@ $< - -.PHONY: all -all: $(TARGETS) $(MAN_TARGETS) -.DEFAULT_GOAL:=all +.DEFAULT_GOAL:=certcal # development tasks .PHONY: test From 137b4eb06f46cac6487f057509df028dcca8edff Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sat, 26 Feb 2022 13:15:13 +0000 Subject: [PATCH 19/22] use kong for cli flags --- certcal.go | 64 +++++++++++++++++++++++++++--------------------------- go.mod | 4 +++- go.sum | 7 ++++++ 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/certcal.go b/certcal.go index e213c77..37f07a2 100644 --- a/certcal.go +++ b/certcal.go @@ -1,15 +1,29 @@ package main import ( + "fmt" + "github.com/alecthomas/kong" "github.com/mrtazz/certcal/handler" "github.com/mrtazz/certcal/hosts" log "github.com/sirupsen/logrus" "net/http" - "os" - "strings" "time" ) +var ( + version = "" + goversion = "" +) + +// CLI defines the command line arguments +var CLI struct { + Serve struct { + Hosts []string `required:"" help:"hosts to check certs for." env:"CERTCAL_HOSTS"` + Interval string `required:"" help:"interval in which to check certs" env:"CERTCAL_INTERVAL" default:"24h"` + Port int `help:"port for the server to listen on" env:"PORT" default:"3000"` + } `cmd:"" help:"run the server."` +} + func main() { log.SetFormatter(&log.TextFormatter{ @@ -19,42 +33,28 @@ func main() { "package": "main", }) - checkHosts := os.Getenv("CERTCAL_HOSTS") - if checkHosts == "" { - logger.Error("missing env var CERTCAL_HOSTS") - os.Exit(1) - } - - var duration time.Duration - durationString := os.Getenv("CERTCAL_INTERVAL") - switch durationString { - case "": - logger.Error("missing env var CERTCAL_INTERVAL, defaulting to 1 day") - duration = 24 * time.Hour - default: - var err error - duration, err = time.ParseDuration(durationString) + ctx := kong.Parse(&CLI) + switch ctx.Command() { + case "serve": + duration, err := time.ParseDuration(CLI.Serve.Interval) if err != nil { logger.Error("unable to parse CERTCAL_INTERVAL, defaulting to 1 day") duration = 24 * time.Hour } - } - - var port string - if port = os.Getenv("PORT"); port == "" { - port = "3000" - } + hosts.AddHosts(CLI.Serve.Hosts) + hosts.UpdateEvery(duration) - hosts.AddHosts(strings.Split(checkHosts, ",")) - hosts.UpdateEvery(duration) + address := fmt.Sprintf(":%d", CLI.Serve.Port) - address := ":" + port + logger.WithFields(log.Fields{ + "address": address, + }).Info("starting web server") + http.HandleFunc("/hosts", handler.Handler) + //http.HandleFunc("/metrics", headers) + http.ListenAndServe(address, nil) - logger.WithFields(log.Fields{ - "address": address, - }).Info("starting web server") - http.HandleFunc("/hosts", handler.Handler) - //http.HandleFunc("/metrics", headers) - http.ListenAndServe(address, nil) + default: + logger.Error("Unknown command: " + ctx.Command()) + } } diff --git a/go.mod b/go.mod index 2b3c2ba..a75cbe1 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,10 @@ require ( ) require ( + github.com/alecthomas/kong v0.4.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index d2ec8fa..d619aaf 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,11 @@ +github.com/alecthomas/kong v0.4.1 h1:0sFnMts+ijOiFuSHsMB9MlDi3NGINBkx9KIw1/gcuDw= +github.com/alecthomas/kong v0.4.1/go.mod h1:uzxf/HUh0tj43x1AyJROl3JT7SgsZ5m+icOv1csRhc0= +github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= @@ -15,3 +20,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From dfab25be2390042747f86fc647577fc6630e8b9d Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sat, 26 Feb 2022 13:18:29 +0000 Subject: [PATCH 20/22] remove metrics handler for now --- certcal.go | 1 - 1 file changed, 1 deletion(-) diff --git a/certcal.go b/certcal.go index 37f07a2..292119d 100644 --- a/certcal.go +++ b/certcal.go @@ -50,7 +50,6 @@ func main() { "address": address, }).Info("starting web server") http.HandleFunc("/hosts", handler.Handler) - //http.HandleFunc("/metrics", headers) http.ListenAndServe(address, nil) default: From df0f872ea9454b2d7c3a223681da2cf248ebea3b Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sat, 26 Feb 2022 13:18:53 +0000 Subject: [PATCH 21/22] update README --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6febe8a..51ee4d6 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,18 @@ There are a couple of ways to run this You can download one of the binaries and run it as a standalone: ```shell +% ./certcal serve --help +Usage: certcal serve --hosts=HOSTS,... --interval="24h" + +run the server. + +Flags: + -h, --help Show context-sensitive help. + + --hosts=HOSTS,... hosts to check certs for ($CERTCAL_HOSTS). + --interval="24h" interval in which to check certs ($CERTCAL_INTERVAL) + --port=3000 port for the server to listen on ($PORT) + % PORT=3000 CERTCAL_INTERVAL=5h CERTCAL_HOSTS="unwiredcouch.com" ./certcal ``` @@ -43,7 +55,11 @@ func Run() { ### Via Docker -There is a docker image as well that you can use +There is a docker image as well that you can use: + +```sh +docker pull ghcr.io/mrtazz/certcal +``` ## FAQ From de01a2c0fab298b3de3d270cc2f9a0a4db20a380 Mon Sep 17 00:00:00 2001 From: Daniel Schauenberg Date: Sat, 26 Feb 2022 13:20:26 +0000 Subject: [PATCH 22/22] add docs with initial releases changelog --- docs/releases/0.1.0.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/releases/0.1.0.md diff --git a/docs/releases/0.1.0.md b/docs/releases/0.1.0.md new file mode 100644 index 0000000..9bbcd0c --- /dev/null +++ b/docs/releases/0.1.0.md @@ -0,0 +1,3 @@ +## v0.1.0 (2022-??-??) +- initial version +