| package pki |
| |
| import ( |
| "crypto/tls" |
| "crypto/x509" |
| "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 |
| } |
| |
| // DeveloperCredentialsPrincipal returns the principal/DN for which the local |
| // developer credentials are provisioned. |
| func DeveloperCredentialsPrincipal() (string, error) { |
| creds, err := loadDeveloperCredentials() |
| if err != nil { |
| return "", fmt.Errorf("when loading developer credentials: %w", err) |
| } |
| pair, err := tls.X509KeyPair(creds.cert, creds.key) |
| if err != nil { |
| return "", fmt.Errorf("when loading developer client cert: %w", err) |
| } |
| cert, err := x509.ParseCertificate(pair.Certificate[0]) |
| if err != nil { |
| return "", fmt.Errorf("when parsing developer client cert: %w", err) |
| } |
| return cert.Subject.CommonName, 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") |
| } |