*: 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")
+}