Commit 558914b7 authored by Oliver Lowe's avatar Oliver Lowe

initial commit

parents
awscert
*.tar.gz
*.tgz
AWSCERT
A work in progress.
awscert(1) reads an awscert file and prints the certificate and its
owner if the certificate should be renewed soon. This is currently
hardcoded to 60 days.
An awscert file is a newline-delimited list of certificate
declarations. A certificate declaration starts with the keyword
"cert", followed by the type of certificate, who it belongs to, and
finally the date when the certificate was obtained.
Here is the simplest example:
cert SAA of Oliver valid from 2018-03-01
This is listing the certificate "SAA", short for "Solutions Architect
Associate", obtained by Oliver on the 1st of March 2018.
Certificates do not have to be cryptic acronyms:
cert "Developer Associate" of Farid valid from 2018-01-01
Note the double quotes. Values with whitespace need to be quoted:
cert "DevOps Professional" of "Walter Heck" valid from 2018-02-01
The date format is rigid (for now). It must have the form YYYY-MM-dd.
The command-line usage is very simple. The synopsis:
usage: awscert [-v] file
From the source repository, build awscert(1). awscert(1) is written
in Go with no external dependencies, so a standard installation of go
is fine. Set the test file "certificates" as the argument to
awscert(1) to run it:
go build
./awscert certificates
Set the flag "v" to add verbosity. awscert(1) will print information
about each certificate it finds to standard error.
./awscert -v certificates
package main
import (
"fmt"
"flag"
"os"
"text/scanner"
"time"
"strings"
)
const dateLayout string = "2006-01-02"
const validDuration time.Duration = time.Hour*24*365*2 // 2 years
const validWarn time.Duration = time.Hour*24*60 // 60 days
func usage() {
fmt.Printf("usage: awscert [-v] file\n")
os.Exit(1)
}
type cert struct {
Type string
Owner string
Start time.Time
}
func (c *cert) Clear() error {
c.Type = ""
c.Owner = ""
c.Start = time.Now()
return nil
}
func main() {
if len(os.Args) < 2 {
usage()
}
verbose := flag.Bool("v", false, "")
flag.Parse()
file, err := os.Open(flag.Args()[0])
if err != nil {
fmt.Printf("cannot open certificates file: %v\n", err)
os.Exit(1)
}
defer file.Close()
var c cert
var s scanner.Scanner
s.Init(file)
s.Filename = file.Name()
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
if s.TokenText() == "cert" {
if err = c.Clear(); err != nil {
fmt.Printf("%v\n", err)
os.Exit(1)
}
s.Scan()
c.Type = s.TokenText()
s.Scan()
if s.TokenText() != "of" {
fmt.Fprintf(os.Stderr, "%s: syntax error: ", s.Position)
fmt.Fprintf(os.Stderr, "unexpected %s, ", s.TokenText())
fmt.Fprintf(os.Stderr, "expected of\n")
os.Exit(1)
}
s.Scan()
c.Owner = s.TokenText()
s.Scan()
if s.TokenText() != "valid" {
fmt.Fprintf(os.Stderr, "%s: syntax error: ", s.Position)
fmt.Fprintf(os.Stderr, "unexpected %s, ", s.TokenText())
fmt.Fprintf(os.Stderr, "expected valid\n")
os.Exit(1)
}
s.Scan()
if s.TokenText() == "from" {
var dates []string
var datestr string
// scan until we hit a newline
for s.Peek() != 0x000A {
s.Scan()
dates = append(dates, s.TokenText())
}
datestr = strings.Join(dates, "")
t, err := time.Parse(dateLayout, datestr)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error reading certificate start date: ", s.Position)
fmt.Fprintf(os.Stderr, "%v\n", err)
} else {
c.Start = t
}
} else {
fmt.Fprintf(os.Stderr, "%s: syntax error: ", s.Position)
fmt.Fprintf(os.Stderr, "unexpected %s, ", s.TokenText())
fmt.Fprintf(os.Stderr, "expected from or to\n")
os.Exit(1)
}
expiry := c.Start.Add(validDuration)
remaining := expiry.Sub(time.Now())
if remaining < validWarn {
fmt.Printf("%s needs to review their certs\n", c.Owner)
}
if *verbose {
fmt.Fprintf(os.Stderr, "type: %s, owner: %s, ", c.Type, c.Owner)
fmt.Fprintf(os.Stderr, "valid from: %s\n", c.Start.String())
}
}
}
}
// Good records, including values with quoted whitespace
cert SA of Oliver valid from 2018-03-01
cert "Developer Associate" of Farid valid from 2018-01-01
cert "DevOps professional" of "Walter Heck" valid from 2018-02-01
cert "old AWS cert" of "Oliver Lowe" valid from 2014-01-01
// Bad records
cert spaces without quotes of Oliver valid from 2018-01-01
cert badowner of Oliver L valid from 2018-01-01
cert baddate of Oliver valid from 1st January 2018
cert baddate2 of Oliver valid from 01/1/2018
cert baddate3 of Oliver valid from 01-01-2018
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment