Commit 168404a9 authored by Ivar Derksen's avatar Ivar Derksen
Browse files

Use irmago's download and update scheme

parent deed055b
checkschememanagers:
https://privacybydesign.foundation/schememanager/pbdf:
|
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELzHV5ipBimWpuZIDaQQd+KmNpNop
dpBeCqpDwf+Grrw9ReODb6nwlsPJ/c/gqLnc+Y3sKOAJ2bFGI+jHBSsglg==
-----END PUBLIC KEY-----
https://privacybydesign.github.io/irma-demo-schememanager:
|
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHVnmAY+kGkFZn7XXozdI4HY8GOjm
54ngh4chTfn6WsTCf2w5rprfIqML61z2VTE4k8yJ0Z1QbyW6cdaao8obTQ==
-----END PUBLIC KEY-----
checkcertificateexpiry:
- https://privacybydesign.foundation
- https://metrics.privacybydesign.foundation
......
......@@ -7,19 +7,15 @@
package main
import (
"encoding/xml"
"flag"
"fmt"
"github.com/privacybydesign/irmago/irma/cmd"
irma "github.com/privacybydesign/irmago"
"html/template"
"io"
"io/ioutil"
"log"
"net/http"
netUrl "net/url"
"os"
"path"
"path/filepath"
"strings"
"time"
......@@ -28,7 +24,6 @@ import (
"gopkg.in/yaml.v2"
"github.com/bwesterb/go-atum"
"github.com/privacybydesign/irmago"
)
var exampleConfig string = `
......@@ -90,8 +85,7 @@ var (
// Configuration
type Conf struct {
CheckSchemeManagers map[string]string // {url: pk}
BindAddr string // port to bind to
BindAddr string // port to bind to
CheckCertificateExpiry []string
CheckAtumServers []string
Interval time.Duration
......@@ -128,6 +122,31 @@ func main() {
log.Fatalf("Could not parse config file: %s", err)
}
// Load IRMA configuration
tempDir, err := ioutil.TempDir("", "")
if err != nil {
log.Printf("checkSchemeManager: TempDir: %s", err)
return
}
defer os.RemoveAll(tempDir)
icDir := path.Join(tempDir, "irma_configuration")
err = os.Mkdir(icDir, 0700)
if err != nil {
log.Printf("MkDir in temp dir for IRMA configuration(%s): %s", icDir, err)
return
}
irmaConfig, err := irma.NewConfiguration(icDir)
if err != nil {
log.Printf("IRMA configuration could not be loaded in temp dir %s", icDir)
return
}
err = irmaConfig.DownloadDefaultSchemes()
if err != nil {
log.Printf("default IRMA configuration cannot be downloaded")
return
}
// set up HTTP server
http.HandleFunc("/", handler)
......@@ -143,7 +162,7 @@ func main() {
go func() {
initialCheck = true
for {
check()
check(irmaConfig)
<-ticker.C
}
}()
......@@ -188,11 +207,11 @@ func difference(old, cur []string) (came, gone []string) {
return
}
func check() {
func check(irmaConfig *irma.Configuration) {
curIssues := []string{}
log.Println("Running checks ...")
curIssues = append(curIssues, checkSchemeManagers()...)
curIssues = append(curIssues, checkSchemeManagers(irmaConfig)...)
curIssues = append(curIssues, checkCertificateExpiry()...)
curIssues = append(curIssues, checkAtumServers()...)
......@@ -260,6 +279,7 @@ func pushToSlack(newIssues, fixedIssues []string, initial bool) {
func checkCertificateExpiry() []string {
ret := []string{}
for _, url := range conf.CheckCertificateExpiry {
log.Printf(" checking certificate expiry on %s", url)
ret = append(ret, checkCertificateExpiryOf(url)...)
}
return ret
......@@ -298,17 +318,9 @@ func checkAtumServers() []string {
return ret
}
func checkSchemeManagers() []string {
ret := []string{}
for url, pk := range conf.CheckSchemeManagers {
ret = append(ret, checkSchemeManager(url, pk)...)
}
return ret
}
func checkAtumServer(url string) (ret []string) {
ret = []string{}
log.Printf(" checking atum sever %s", url)
log.Printf(" checking atum server %s", url)
ts, err := atum.JsonStamp(url, []byte{1, 2, 3, 4, 5})
if err != nil {
ret = append(ret, fmt.Sprintf("%s: requesting Atum stamp failed: %s", url, err))
......@@ -330,169 +342,32 @@ func checkAtumServer(url string) (ret []string) {
return
}
func checkSchemeManager(url, pk string) (ret []string) {
func checkSchemeManagers(irmaConfig *irma.Configuration) (ret []string) {
ret = []string{}
log.Printf(" checking schememanager %s", url)
log.Printf(" checking schememanagers")
// First, we download all the files of the schememanager.
// We need a temporary directory to store the files.
// As `schememgr verify' is a bit picky, we put everything in
// <temp dir>/irma_configuration/<name of schememgr>
tempDir, err := ioutil.TempDir("", "")
if err != nil {
log.Printf("checkSchemeManager: TempDir: %s", err)
return
}
defer os.RemoveAll(tempDir)
icDir := path.Join(tempDir, "irma_configuration")
err = os.Mkdir(icDir, 0700)
if err != nil {
log.Printf("checkSchemeManager: MkDir(%s): %s", icDir, err)
return
}
parsedUrl, err := netUrl.Parse(url)
if err != nil {
ret = append(ret, fmt.Sprintf("Failed to parse url %s: %s", url, err))
return
}
_, name := path.Split(parsedUrl.Path)
baseDir := path.Join(icDir, name)
err = os.Mkdir(baseDir, 0700)
if err != nil {
log.Printf("checkSchemeManager: MkDir(%s): %s", icDir, err)
return
}
// Helper.
download := func(fn string) error {
resp, err := http.Get(url + "/" + fn)
if err != nil {
return err
}
if resp.StatusCode != 200 {
return fmt.Errorf("HTTP Code %d", resp.StatusCode)
}
defer resp.Body.Close()
localFn := path.Join(baseDir, fn)
localDir := filepath.Dir(localFn)
if _, err := os.Stat(localDir); os.IsNotExist(err) {
if err = os.MkdirAll(localDir, 0700); err != nil {
return fmt.Errorf("local: os.MkdirAll(%s): %s", localDir, err)
}
}
fh, err := os.Create(localFn)
if err != nil {
return fmt.Errorf("local: os.Create(%s): %s", localFn, err)
}
defer fh.Close()
_, err = io.Copy(fh, resp.Body)
if err != nil {
return fmt.Errorf("while downloading %s/%s: %s", url, fn, err)
}
return nil
}
// Download index.sig and index separately
if err = download("index.sig"); err != nil {
ret = append(ret, fmt.Sprintf("%s: failed to download index signature: %s", url, err))
}
if err = download("pk.pem"); err != nil {
ret = append(ret, fmt.Sprintf("%s: failed to download pk.pem: %s", url, err))
}
if err = download("index"); err != nil {
ret = append(ret, fmt.Sprintf("%s: failed to download index: %s", url, err))
return
}
// Overwrite public key
if err = ioutil.WriteFile(path.Join(baseDir, "pk.pem"), []byte(pk), 0600); err != nil {
log.Printf("checkSchemeManager: failed to write pk.pem: %s", err)
return
}
// Parse index
var idx irma.SchemeManagerIndex = make(map[string]irma.ConfigurationFileHash)
idxBytes, err := ioutil.ReadFile(path.Join(baseDir, "index"))
err := irmaConfig.UpdateSchemes()
if err != nil {
log.Printf("checkSchemeManager: failed to open downloaded index file: %s", err)
return
}
err = idx.FromString(string(idxBytes))
if err != nil {
ret = append(ret, fmt.Sprintf("%s: failed to parse index: %s", url, err))
log.Printf("checkSchemeManager: update schemes: %s", err)
return
}
// Download files
ok := true
for fn, _ := range idx {
bits := strings.SplitN(fn, "/", 2)
if len(bits) != 2 {
ret = append(ret, fmt.Sprintf("%s: unexpected index entry: %v", url, fn))
continue
irmaConfig.Warnings = []string{}
for _, manager := range irmaConfig.SchemeManagers {
// Verify signatures
if err = irmaConfig.VerifySchemeManager(manager); err != nil {
ret = append(ret, fmt.Sprintf("%s: irma scheme verify -> VerifySchemeManager: %s", manager.ID, err))
}
err = download(bits[1])
if err != nil {
ok = false
ret = append(ret, fmt.Sprintf("%s: failed to download %s: %s", url, bits[1], err))
// Check expiry dates on public keys
if err = irmaConfig.ValidateKeys(); err != nil {
ret = append(ret, fmt.Sprintf("%s: irma scheme verify -> ValidateKeys: %s", manager.ID, err))
}
}
if !ok {
return
}
// Verify signatures
err = cmd.RunVerify(icDir, false)
if err != nil {
ret = append(ret, fmt.Sprintf("%s: irma scheme verify: %s", url, err))
}
// Check expiry dates on public keys
pkDirs, err := filepath.Glob(path.Join(icDir, "*/*/PublicKeys"))
if err != nil {
log.Printf("checkSchemeManager: Glob(*/*/PublicKeys): %s", err)
return
}
for _, pkDir := range pkDirs {
pks, err := filepath.Glob(path.Join(pkDir, "*.xml"))
if err != nil {
log.Printf("checkSchemeManager: Glob: %s", err)
return
}
var maxExpiry int64 = 0
for _, pk := range pks {
var pkData struct{ ExpiryDate int64 }
pkBytes, err := ioutil.ReadFile(pk)
if err != nil {
log.Printf("checkSchemeManager: ReadFile(%s): %s", pk, err)
return
}
if err = xml.Unmarshal(pkBytes, &pkData); err != nil {
ret = append(ret, fmt.Sprintf("%s: failed to parse %s: %s", url, pk, err))
return
}
if maxExpiry < pkData.ExpiryDate {
maxExpiry = pkData.ExpiryDate
}
}
daysExpired := time.Since(time.Unix(maxExpiry, 0)).Hours() / 24
pkDirRel, _ := filepath.Rel(icDir, pkDir)
pkDirBits := strings.Split(pkDirRel, "/")
if daysExpired > 0 {
ret = append(ret, fmt.Sprintf("%s: publickey for %s.%s has expired %d days",
url, pkDirBits[0], pkDirBits[1], int(daysExpired)))
} else if daysExpired > -30 {
ret = append(ret, fmt.Sprintf("%s: publickey for %s.%s will expire in %d days",
url, pkDirBits[0], pkDirBits[1], int(-daysExpired)))
}
}
ret = append(ret, irmaConfig.Warnings...)
return
}
Supports Markdown
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