*: developer machine HSPKI credentials

In addition to k8s certificates, prodaccess now issues HSPKI
certificates, with DN=$username.sso.hswaw.net. These are installed into
XDG_CONFIG_HOME (or os equiv).

//go/pki will now automatically attempt to load these certificates. This
means you can now run any pki-dependant tool with -hspki_disable, and
with automatic mTLS!

Change-Id: I5b28e193e7c968d621bab0d42aabd6f0510fed6d
diff --git a/go/pki/locate.go b/go/pki/locate.go
new file mode 100644
index 0000000..e48e013
--- /dev/null
+++ b/go/pki/locate.go
@@ -0,0 +1,88 @@
+package pki
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+
+	"github.com/golang/glog"
+)
+
+// DeveloperCredentialsLocation returns the path containing HSPKI credentials
+// on developer machines. These are provisioned by //cluster/prodaccess, and
+// are used if available.
+func DeveloperCredentialsLocation() (string, error) {
+	cfgDir, err := os.UserConfigDir()
+	if err != nil {
+		glog.Exitf("UserConfigDir: %w", err)
+	}
+
+	return fmt.Sprintf("%s/hspki", cfgDir), nil
+}
+
+type creds struct {
+	ca   []byte
+	cert []byte
+	key  []byte
+}
+
+func loadDeveloperCredentials() (*creds, error) {
+	path, err := DeveloperCredentialsLocation()
+	if err != nil {
+		return nil, fmt.Errorf("DeveloperCredentialsLocation: %w")
+	}
+
+	c := creds{}
+	for _, el := range []struct {
+		target *[]byte
+		path   string
+	}{
+		{&c.ca, path + "/" + "ca.crt"},
+		{&c.cert, path + "/" + "tls.crt"},
+		{&c.key, path + "/" + "tls.key"},
+	} {
+		data, err := ioutil.ReadFile(el.path)
+		if err != nil {
+			return nil, fmt.Errorf("ReadFile(%q): %w", el.path, err)
+		}
+		*el.target = data
+	}
+
+	return &c, nil
+}
+
+func loadFlagCredentials() (*creds, error) {
+	c := creds{}
+	for _, el := range []struct {
+		target *[]byte
+		path   string
+	}{
+		{&c.ca, flagCAPath},
+		{&c.cert, flagCertificatePath},
+		{&c.key, flagKeyPath},
+	} {
+		data, err := ioutil.ReadFile(el.path)
+		if err != nil {
+			return nil, fmt.Errorf("ReadFile(%q): %w", el.path, err)
+		}
+		*el.target = data
+	}
+
+	return &c, nil
+}
+
+func loadCredentials() (*creds, error) {
+	dev, err := loadDeveloperCredentials()
+	if err == nil {
+		return dev, nil
+	}
+	glog.Warningf("Could not load developer PKI credentials: %v", err)
+
+	fl, err := loadFlagCredentials()
+	if err == nil {
+		return fl, err
+	}
+	glog.Warningf("Could not load flag-defined PKI credentials: %v", err)
+
+	return nil, fmt.Errorf("could not load any credentials")
+}