2020-08-01 15:15:52 +00:00
package pki
import (
2020-08-01 20:01:33 +00:00
"crypto/tls"
"crypto/x509"
2020-08-01 15:15:52 +00:00
"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 {
2021-03-17 23:26:30 +00:00
return "" , fmt . Errorf ( "UserConfigDir: %w" , err )
2020-08-01 15:15:52 +00:00
}
return fmt . Sprintf ( "%s/hspki" , cfgDir ) , nil
}
2020-08-01 20:01:33 +00:00
// 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
}
2020-08-01 15:15:52 +00:00
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 )
2023-08-05 17:01:28 +00:00
return nil , fmt . Errorf ( "could not load PKI credentials (hint: run `prodaccess` to set up developer certs or add `-- -hspki_disable` to bazel run command)" )
2020-08-01 15:15:52 +00:00
}