Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 1 | package pki |
| 2 | |
| 3 | import ( |
Serge Bazanski | ef2fbaf | 2020-08-01 22:01:33 +0200 | [diff] [blame] | 4 | "crypto/tls" |
| 5 | "crypto/x509" |
Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 6 | "fmt" |
| 7 | "io/ioutil" |
| 8 | "os" |
| 9 | |
| 10 | "github.com/golang/glog" |
| 11 | ) |
| 12 | |
| 13 | // DeveloperCredentialsLocation returns the path containing HSPKI credentials |
| 14 | // on developer machines. These are provisioned by //cluster/prodaccess, and |
| 15 | // are used if available. |
| 16 | func DeveloperCredentialsLocation() (string, error) { |
| 17 | cfgDir, err := os.UserConfigDir() |
| 18 | if err != nil { |
| 19 | glog.Exitf("UserConfigDir: %w", err) |
| 20 | } |
| 21 | |
| 22 | return fmt.Sprintf("%s/hspki", cfgDir), nil |
| 23 | } |
| 24 | |
Serge Bazanski | ef2fbaf | 2020-08-01 22:01:33 +0200 | [diff] [blame] | 25 | // DeveloperCredentialsPrincipal returns the principal/DN for which the local |
| 26 | // developer credentials are provisioned. |
| 27 | func DeveloperCredentialsPrincipal() (string, error) { |
| 28 | creds, err := loadDeveloperCredentials() |
| 29 | if err != nil { |
| 30 | return "", fmt.Errorf("when loading developer credentials: %w", err) |
| 31 | } |
| 32 | pair, err := tls.X509KeyPair(creds.cert, creds.key) |
| 33 | if err != nil { |
| 34 | return "", fmt.Errorf("when loading developer client cert: %w", err) |
| 35 | } |
| 36 | cert, err := x509.ParseCertificate(pair.Certificate[0]) |
| 37 | if err != nil { |
| 38 | return "", fmt.Errorf("when parsing developer client cert: %w", err) |
| 39 | } |
| 40 | return cert.Subject.CommonName, nil |
| 41 | } |
| 42 | |
Serge Bazanski | f3312ef | 2020-08-01 17:15:52 +0200 | [diff] [blame] | 43 | type creds struct { |
| 44 | ca []byte |
| 45 | cert []byte |
| 46 | key []byte |
| 47 | } |
| 48 | |
| 49 | func loadDeveloperCredentials() (*creds, error) { |
| 50 | path, err := DeveloperCredentialsLocation() |
| 51 | if err != nil { |
| 52 | return nil, fmt.Errorf("DeveloperCredentialsLocation: %w") |
| 53 | } |
| 54 | |
| 55 | c := creds{} |
| 56 | for _, el := range []struct { |
| 57 | target *[]byte |
| 58 | path string |
| 59 | }{ |
| 60 | {&c.ca, path + "/" + "ca.crt"}, |
| 61 | {&c.cert, path + "/" + "tls.crt"}, |
| 62 | {&c.key, path + "/" + "tls.key"}, |
| 63 | } { |
| 64 | data, err := ioutil.ReadFile(el.path) |
| 65 | if err != nil { |
| 66 | return nil, fmt.Errorf("ReadFile(%q): %w", el.path, err) |
| 67 | } |
| 68 | *el.target = data |
| 69 | } |
| 70 | |
| 71 | return &c, nil |
| 72 | } |
| 73 | |
| 74 | func loadFlagCredentials() (*creds, error) { |
| 75 | c := creds{} |
| 76 | for _, el := range []struct { |
| 77 | target *[]byte |
| 78 | path string |
| 79 | }{ |
| 80 | {&c.ca, flagCAPath}, |
| 81 | {&c.cert, flagCertificatePath}, |
| 82 | {&c.key, flagKeyPath}, |
| 83 | } { |
| 84 | data, err := ioutil.ReadFile(el.path) |
| 85 | if err != nil { |
| 86 | return nil, fmt.Errorf("ReadFile(%q): %w", el.path, err) |
| 87 | } |
| 88 | *el.target = data |
| 89 | } |
| 90 | |
| 91 | return &c, nil |
| 92 | } |
| 93 | |
| 94 | func loadCredentials() (*creds, error) { |
| 95 | dev, err := loadDeveloperCredentials() |
| 96 | if err == nil { |
| 97 | return dev, nil |
| 98 | } |
| 99 | glog.Warningf("Could not load developer PKI credentials: %v", err) |
| 100 | |
| 101 | fl, err := loadFlagCredentials() |
| 102 | if err == nil { |
| 103 | return fl, err |
| 104 | } |
| 105 | glog.Warningf("Could not load flag-defined PKI credentials: %v", err) |
| 106 | |
| 107 | return nil, fmt.Errorf("could not load any credentials") |
| 108 | } |