Draw the actual rest of the fucking owl.
Change-Id: Ia04fb49ebbe3a5afccc57e62f6335e35b45192fe
diff --git a/bgpwtf/cccampix/verifier/processor_pgp.go b/bgpwtf/cccampix/verifier/processor_pgp.go
new file mode 100644
index 0000000..423cb7e
--- /dev/null
+++ b/bgpwtf/cccampix/verifier/processor_pgp.go
@@ -0,0 +1,153 @@
+package main
+
+import (
+ "context"
+ "encoding/hex"
+ "fmt"
+ "sync"
+ "time"
+
+ pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto"
+ "code.hackerspace.pl/hscloud/bgpwtf/cccampix/verifier/model"
+ "github.com/golang/glog"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+type pgp struct {
+ pgpc pb.PGPEncryptorClient
+}
+
+func newPGP(pgpc pb.PGPEncryptorClient) (*pgp, error) {
+ return &pgp{
+ pgpc: pgpc,
+ }, nil
+}
+
+func (p *pgp) Name() string {
+ return "PGP"
+}
+
+func (p *pgp) NextRun(now time.Time, lastRun bool) time.Time {
+ if lastRun {
+ return now.Add(1 * time.Minute)
+ }
+ return now.Add(15 * time.Minute)
+}
+
+func (p *pgp) RunAll(ctx context.Context, m model.Model) error {
+ keys, err := m.GetPGPKeysRequiringAttention(ctx)
+ if err != nil {
+ return fmt.Errorf("GetPGPKeysRequiringAttention: %v", err)
+ }
+
+ if len(keys) == 0 {
+ return nil
+ }
+
+ s := make(chan struct{}, 20)
+ errC := make(chan error, len(keys))
+ knownC := make(chan *model.PeerPGPKey, len(keys))
+ unknownC := make(chan *model.PeerPGPKey, len(keys))
+
+ var wg sync.WaitGroup
+ wg.Add(len(keys))
+
+ for _, key := range keys {
+ go func(k *model.PeerPGPKey) {
+ s <- struct{}{}
+ defer func() {
+ wg.Done()
+ <-s
+ }()
+
+ glog.Infof("PGP: Processing %v", *k)
+
+ // HACK(q3k)
+ if k.State == "known" {
+ knownC <- k
+ return
+ }
+
+ fp, err := hex.DecodeString(k.Fingerprint)
+ if err != nil {
+ errC <- fmt.Errorf("could not decode fingerprint %q: %v", k.Fingerprint, err)
+ return
+ }
+
+ req := &pb.KeyInfoRequest{
+ Fingerprint: fp,
+ Caching: pb.KeyInfoRequest_CACHING_FORCE_REMOTE,
+ }
+
+ _, err = p.pgpc.KeyInfo(ctx, req)
+ s, ok := status.FromError(err)
+ switch {
+ case err == nil:
+ knownC <- k
+ case ok && s.Code() == codes.NotFound:
+ unknownC <- k
+ default:
+ errC <- err
+ }
+ }(key)
+ }
+
+ wg.Wait()
+ close(errC)
+ close(knownC)
+ close(unknownC)
+
+ pcr := []*model.PeerCheckResult{}
+
+ positive := []string{}
+ for p := range knownC {
+ positive = append(positive, p.Fingerprint)
+ pcr = append(pcr, &model.PeerCheckResult{
+ PeerASN: p.PeerASN,
+ CheckName: "pgp",
+ Time: time.Now(),
+ Status: model.PeerCheckStatus_Okay,
+ })
+ }
+ negative := []string{}
+ for n := range unknownC {
+ negative = append(negative, n.Fingerprint)
+ pcr = append(pcr, &model.PeerCheckResult{
+ PeerASN: n.PeerASN,
+ CheckName: "pgp",
+ Time: time.Now(),
+ Status: model.PeerCheckStatus_Failed,
+ Message: fmt.Sprintf("key %q not found on keyservers", n.Fingerprint),
+ })
+ }
+
+ glog.Infof("%v, %v", positive, negative)
+
+ if len(positive) > 0 || len(negative) > 0 {
+ err := m.ValidatePGPKeys(ctx, positive, negative)
+ if err != nil {
+ return fmt.Errorf("ValidatePGPKeys(%v, %v): %v", positive, negative, err)
+ }
+ }
+
+ if len(pcr) > 0 {
+ err = m.SubmitPeerCheckResults(ctx, "pgp", pcr)
+ if err != nil {
+ return err
+ }
+ }
+
+ errs := []error{}
+ for err := range errC {
+ errs = append(errs, err)
+ }
+
+ if len(errs) > 0 {
+ glog.Errorf("Errors while processing keys: %v", errs)
+ return fmt.Errorf("Errors ocurred while processing keys")
+ }
+
+ return nil
+
+}