Move pki.go into code.hackerspace.pl/q3k/hspki
diff --git a/grpc.go b/grpc.go
index a47877e..9569ee5 100644
--- a/grpc.go
+++ b/grpc.go
@@ -9,6 +9,7 @@
 	"net"
 	"net/http"
 
+	"code.hackerspace.pl/q3k/hspki"
 	"github.com/golang/glog"
 	"github.com/q3k/statusz"
 	"golang.org/x/net/trace"
@@ -25,7 +26,6 @@
 	tlsCAPath          string
 	tlsCertificatePath string
 	tlsKeyPath         string
-	pkiRealm           string
 }
 
 type server struct {
@@ -110,7 +110,7 @@
 func (s *server) serveForever() {
 	grpc.EnableTracing = true
 
-	if err := s.setupGRPC(grpc.UnaryInterceptor(s.unaryInterceptor)); err != nil {
+	if err := s.setupGRPC(hspki.WithServerHSPKI()); err != nil {
 		glog.Exitf("Could not setup GRPC server: %v", err)
 	}
 	pb.RegisterAristaProxyServer(s.grpc.server, s)
diff --git a/main.go b/main.go
index deb34d5..66e8d94 100644
--- a/main.go
+++ b/main.go
@@ -15,7 +15,6 @@
 	flagCAPath          string
 	flagCertificatePath string
 	flagKeyPath         string
-	flagPKIRealm        string
 )
 
 type aristaClient struct {
@@ -47,7 +46,6 @@
 	flag.StringVar(&flagCAPath, "tls_ca_path", "pki/ca.pem", "Path to PKI CA certificate")
 	flag.StringVar(&flagCertificatePath, "tls_certificate_path", "pki/service.pem", "Path to PKI service certificate")
 	flag.StringVar(&flagKeyPath, "tls_key_path", "pki/service-key.pem", "Path to PKI service private key")
-	flag.StringVar(&flagPKIRealm, "pki_realm", "svc.cluster.local", "PKI realm")
 	flag.Set("logtostderr", "true")
 	flag.Parse()
 
@@ -61,7 +59,6 @@
 		tlsCAPath:          flagCAPath,
 		tlsCertificatePath: flagCertificatePath,
 		tlsKeyPath:         flagKeyPath,
-		pkiRealm:           flagPKIRealm,
 	}
 	server, err := newServer(opts, arista)
 	if err != nil {
diff --git a/pki.go b/pki.go
deleted file mode 100644
index fdb4e34..0000000
--- a/pki.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package main
-
-import (
-	"context"
-	"fmt"
-	"strings"
-
-	"golang.org/x/net/trace"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/credentials"
-	"google.golang.org/grpc/peer"
-	"google.golang.org/grpc/status"
-)
-
-type clientPKIInfo struct {
-	realm     string
-	principal string
-	job       string
-}
-
-func (c *clientPKIInfo) String() string {
-	return fmt.Sprintf("job=%q, principal=%q, realm=%q", c.job, c.principal, c.realm)
-}
-
-func parseClientName(realm, name string) (*clientPKIInfo, error) {
-	if !strings.HasSuffix(name, "."+realm) {
-		return nil, fmt.Errorf("invalid realm")
-	}
-	service := strings.TrimSuffix(name, "."+realm)
-	parts := strings.Split(service, ".")
-	if len(parts) != 2 {
-		return nil, fmt.Errorf("invalid service")
-	}
-	return &clientPKIInfo{
-		realm:     realm,
-		principal: parts[1],
-		job:       parts[0],
-	}, nil
-}
-
-const (
-	ctxKeyPKIInfo = "hscloud-pki-info"
-)
-
-func withPKIInfo(ctx context.Context, c *clientPKIInfo) context.Context {
-	tr, ok := trace.FromContext(ctx)
-	if ok {
-		tr.LazyPrintf("PKI Peer: %s", c.String())
-	}
-	return context.WithValue(ctx, ctxKeyPKIInfo, c)
-}
-
-func (s *server) unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
-	peer, ok := peer.FromContext(ctx)
-	if !ok {
-		s.trace(ctx, "Could not establish identity of peer.")
-		return nil, status.Error(codes.InvalidArgument, "no peer info")
-	}
-
-	authInfo, ok := peer.AuthInfo.(credentials.TLSInfo)
-	if !ok {
-		s.trace(ctx, "Could not establish TLS identity of peer.")
-		return nil, status.Error(codes.InvalidArgument, "no TLS peer info")
-	}
-
-	chains := authInfo.State.VerifiedChains
-	if len(chains) != 1 {
-		s.trace(ctx, "No trusted chain found.")
-		return nil, status.Error(codes.InvalidArgument, "invalid TLS certificate")
-	}
-	chain := chains[0]
-
-	certDNs := make([]string, len(chain))
-	for i, cert := range chain {
-		certDNs[i] = cert.Subject.String()
-	}
-	s.trace(ctx, "TLS chain: %s", strings.Join(certDNs, ", "))
-
-	clientInfo, err := parseClientName(s.opts.pkiRealm, chain[0].Subject.CommonName)
-	if err != nil {
-		s.trace(ctx, "Could not parse certificate DN: %v", err)
-		return nil, status.Error(codes.InvalidArgument, "invalid TLS CommonName")
-	}
-	ctx = withPKIInfo(ctx, clientInfo)
-
-	return handler(ctx, req)
-}