gencred is a simple tool used to generate cluster auth credentials (w/ cluster-admin permissions) for authenticating to a Kubernetes cluster.
NOTE: since
gencredcreates credentials withcluster-adminlevel access, the kube context used must also be bound to thecluster-adminrole.
Run using Bazel:
$ bazel run //gencred -- <options>Run using Golang:
$ go run k8s.io/test-infra/gencred <options>The following is a list of supported options for the gencred CLI. All options are optional.
-c, --certificate Authorize with a client certificate and key.
--context string The name of the kubeconfig context to use.
-n, --name string Context name for the kubeconfig entry. (default "build")
-o, --output string Output path for generated kubeconfig file. (default "/dev/stdout")
--overwrite Overwrite (rather than merge) output file if exists.
-s, --serviceaccount Authorize with a service account. (default true)Create a kubeconfig entry with context name mycluster using serviceaccount authorization and output to a file config.yaml.
serviceaccountauthorization is the default if neither-s, --serviceaccountnor-c, --certificateis specified.
$ gencred --context my-current-context --name mycluster --output ./config.yaml --serviceaccountThe kubeconfig contents will be output to ./config.yaml:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: fake-ca-data
server: https://1.2.3.4
name: mycluster
contexts:
- context:
cluster: mycluster
user: mycluster
name: mycluster
current-context: mycluster
kind: Config
preferences: {}
users:
- name: mycluster
user:
token: fake-tokenCreate a kubeconfig entry with default context name build using certificate authorization and output to the default stdout.
$ gencred --context my-current-context --certificateThe kubeconfig contents will be output to stdout:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: fake-ca-data
server: https://1.2.3.4
name: build
contexts:
- context:
cluster: build
user: build
name: build
current-context: build
kind: Config
preferences: {}
users:
- name: build
user:
client-certificate-data: fake-cert-data
client-key-data: fake-key-dataSpecify the --overwrite flag to replace the output file if it exists.
$ gencred --context my-current-context --output ./existing.yaml --overwriteOmit the --overwrite flag to merge the output file if it exists.
Entries from the existing file take precedence on conflicts.
$ gencred --context my-current-context --name oldcluster --output ./existing.yaml
$ gencred --context my-current-context --name newcluster --output ./existing.yamlThe kubeconfig contents will be output to ./existing.yaml:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: fake-ca-data
server: https://1.2.3.4
name: oldcluster
- cluster:
certificate-authority-data: fake-ca-data
server: https://1.2.3.4
name: newcluster
contexts:
- context:
cluster: oldcluster
user: oldcluster
name: oldcluster
- context:
cluster: newcluster
user: newcluster
name: newcluster
users:
- name: oldcluster
user:
client-certificate-data: fake-cert-data
client-key-data: fake-key-data
- name: newcluster
user:
client-certificate-data: fake-cert-data
client-key-data: fake-key-dataIf you store kubeconfig files in kubernetes secrets to allow pods to access other kubernetes clusters (like many of Prow's components require) consider using merge_kubeconfig_secret.py to merge the kubeconfig produced by gencred into the secret.
# Generate a kubeconfig.yaml as described and shown above, then run something like:
./merge_kubeconfig_secret.py --src-key=config-old --dest-key=config-new kubeconfig.yaml
# Update references (e.g. `--kubeconfig` flags) to point to config-new instead of config-old.✅ PREFERRED method.
// Import serviceaccount
import "k8s.io/test-infra/gencred/pkg/serviceaccount"
//...
// Create a Kubernetes clientset for interacting with the cluster.
// In this case we are simply using the `current-context` defined in our local `~/.kube/config`.
homedir, _ := os.UserHomeDir()
kubeconfig := filepath.Join(homedir, ".kube", "config")
config, _ := clientcmd.BuildConfigFromFlags("", kubeconfig)
clientset, _ := kubernetes.NewForConfig(config)
// Generate a service account token, as well as return the certificate authority that issued the token.
token, caPEM, err := serviceaccount.CreateClusterServiceAccountCredentials(clientset)token will contain the service account access token and caPEM will contain the server certificate authority.
import "encoding/base64"
//...
// Cast the `token` to a string to use in a kubeconfig.
accessToken := string(token)
// Base64 encode the `caPEM` to use in a kubeconfig.
ca := base64.StdEncoding.EncodeToString(caPEM)
fmt.Println("token:", accessToken)
fmt.Println("ca:", ca)token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3Mit...
ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURER...
❌ DEPRECATED method.
// Import certificate
import "k8s.io/test-infra/gencred/pkg/certificate"
//...
// Create a Kubernetes clientset for interacting with the cluster.
// In this case we are simply using the `current-context` defined in our local `~/.kube/config`.
homedir, _ := os.UserHomeDir()
kubeconfig := filepath.Join(homedir, ".kube", "config")
config, _ := clientcmd.BuildConfigFromFlags("", kubeconfig)
clientset, _ := kubernetes.NewForConfig(config)
// Generate a client key and certificate, as well as return the certificate authority that issued the certificate.
certPEM, keyPEM, caPEM, err := certificate.CreateClusterCertificateCredentials(clientset)certPEM will contain the client certificate, keyPEM will contain the client key, and caPEM will contain the server certificate authority.
import "encoding/base64"
//...
// Base64 encode the `certPEM`, `keyPEM`, and `caPEM` to use in a kubeconfig.
cert := base64.StdEncoding.EncodeToString(certPEM)
key := base64.StdEncoding.EncodeToString(keyPEM)
ca := base64.StdEncoding.EncodeToString(caPEM)
fmt.Println("cert:", cert)
fmt.Println("key:", key)
fmt.Println("ca:", ca)cert: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1...
key: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNL...
ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURER...
-
The use of x509 client certificate with super-user privileges for cluster authentication/authorization has several drawbacks:
- Certificates cannot be revoked (kubernetes/kubernetes#60917)
- Authorization roles are essentially global and thus cannot be tweaked at the node level.
- Unless setup with near expiry and explicit rotation, certificates are long-lived and increase the risk of exposure.
-
Client certificate authentication will be deprecated in future versions of Prow (kubernetes/test-infra#13972).