1package client 2 3import ( 4 "bytes" 5 "crypto/x509" 6 "io/ioutil" 7 "net" 8 "os" 9 10 "github.com/hashicorp/vault/sdk/helper/certutil" 11) 12 13const ( 14 // These environment variables aren't set by default. 15 // Vault may read them in if set through these environment variables. 16 // Example here: 17 // https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/ 18 // The client itself does nothing directly with these variables, it's 19 // up to the caller. However, they live here so they'll be consistently 20 // named should the client ever be reused. 21 // We generally recommend preferring environmental settings over configured 22 // ones, allowing settings from the Downward API to override hard-coded 23 // ones. 24 EnvVarKubernetesNamespace = "VAULT_K8S_NAMESPACE" 25 EnvVarKubernetesPodName = "VAULT_K8S_POD_NAME" 26 27 // The service host and port environment variables are 28 // set by default inside a Kubernetes environment. 29 EnvVarKubernetesServiceHost = "KUBERNETES_SERVICE_HOST" 30 EnvVarKubernetesServicePort = "KUBERNETES_SERVICE_PORT" 31) 32 33var ( 34 // These are presented as variables so they can be updated 35 // to point at test fixtures if needed. They aren't passed 36 // into inClusterConfig to avoid dependency injection. 37 Scheme = "https://" 38 TokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token" 39 RootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" 40) 41 42// inClusterConfig returns a config object which uses the service account 43// kubernetes gives to services. It's intended for clients that expect to be 44// running inside a service running on kubernetes. It will return ErrNotInCluster 45// if called from a process not running in a kubernetes environment. 46// inClusterConfig is based on this: 47// https://github.com/kubernetes/client-go/blob/a56922badea0f2a91771411eaa1173c9e9243908/rest/config.go#L451 48func inClusterConfig() (*Config, error) { 49 host, port := os.Getenv(EnvVarKubernetesServiceHost), os.Getenv(EnvVarKubernetesServicePort) 50 if len(host) == 0 || len(port) == 0 { 51 return nil, ErrNotInCluster 52 } 53 54 token, err := ioutil.ReadFile(TokenFile) 55 if err != nil { 56 return nil, err 57 } 58 59 caBytes, err := ioutil.ReadFile(RootCAFile) 60 if err != nil { 61 return nil, err 62 } 63 pool, err := certutil.NewCertPool(bytes.NewReader(caBytes)) 64 if err != nil { 65 return nil, err 66 } 67 return &Config{ 68 Host: Scheme + net.JoinHostPort(host, port), 69 CACertPool: pool, 70 BearerToken: string(token), 71 BearerTokenFile: TokenFile, 72 }, nil 73} 74 75// This config is based on the one returned here: 76// https://github.com/kubernetes/client-go/blob/a56922badea0f2a91771411eaa1173c9e9243908/rest/config.go#L451 77// It is pared down to the absolute minimum fields used by this code. 78// The CACertPool is promoted to the top level from being originally on the TLSClientConfig 79// because it is the only parameter of the TLSClientConfig used by this code. 80// Also, it made more sense to simply reuse the pool rather than holding raw values 81// and parsing it repeatedly. 82type Config struct { 83 CACertPool *x509.CertPool 84 85 // Host must be a host string, a host:port pair, or a URL to the base of the apiserver. 86 // If a URL is given then the (optional) Path of that URL represents a prefix that must 87 // be appended to all request URIs used to access the apiserver. This allows a frontend 88 // proxy to easily relocate all of the apiserver endpoints. 89 Host string 90 91 // Server requires Bearer authentication. This client will not attempt to use 92 // refresh tokens for an OAuth2 flow. 93 BearerToken string 94 95 // Path to a file containing a BearerToken. 96 // If set, checks for a new token in the case of authorization errors. 97 BearerTokenFile string 98} 99