k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/gencred/README.md (about)

     1  # Gencred
     2  
     3  ## Description
     4  
     5  `gencred` is a simple tool used to generate cluster auth credentials (w/ [**cluster-admin**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) permissions) for authenticating to a Kubernetes cluster.
     6  > **NOTE:** since `gencred` creates credentials with `cluster-admin` level access, the kube context used **must** also be bound to the `cluster-admin` role.
     7  
     8  ## Usage
     9  
    10  ### Script
    11  
    12  ```console
    13  $ go run k8s.io/test-infra/gencred <options>
    14  ```
    15  
    16  The following is a list of supported options for the `gencred` CLI. All options are *optional*. 
    17  
    18  ```console
    19    -c, --certificate      Authorize with a client certificate and key.
    20        --context string   The name of the kubeconfig context to use.
    21    -n, --name string      Context name for the kubeconfig entry. (default "build")
    22    -o, --output string    Output path for generated kubeconfig file. (default "/dev/stdout")
    23        --overwrite        Overwrite (rather than merge) output file if exists.
    24    -s, --serviceaccount   Authorize with a service account. (default true)
    25    -d, --duration         How many days the cred is valid. (default 7)
    26  ```
    27  
    28  Create a kubeconfig entry with context name `mycluster` using `serviceaccount` authorization and output to a file `config.yaml`.
    29  > `serviceaccount` authorization is the *default* if neither `-s, --serviceaccount` nor `-c, --certificate` is specified.
    30   
    31  ```console
    32  $ gencred --context my-current-context --name mycluster --output ./config.yaml --serviceaccount
    33  ```
    34  
    35  The kubeconfig contents will be `output` to  `./config.yaml`:
    36  
    37  ```yaml
    38  apiVersion: v1
    39  clusters:
    40  - cluster:
    41      certificate-authority-data: fake-ca-data
    42      server: https://1.2.3.4
    43    name: mycluster
    44  contexts:
    45  - context:
    46      cluster: mycluster
    47      user: mycluster
    48    name: mycluster
    49  current-context: mycluster
    50  kind: Config
    51  preferences: {}
    52  users:
    53  - name: mycluster
    54    user:
    55      token: fake-token
    56  ```
    57  
    58  Create a kubeconfig entry with **default** context name `build` using `certificate` authorization and output to the **default** `stdout`.
    59  
    60  ```console
    61  $ gencred --context my-current-context --certificate
    62  ```
    63  
    64  The kubeconfig contents will be `output` to `stdout`:
    65  
    66  ```yaml
    67  apiVersion: v1
    68  clusters:
    69  - cluster:
    70      certificate-authority-data: fake-ca-data
    71      server: https://1.2.3.4
    72    name: build
    73  contexts:
    74  - context:
    75      cluster: build
    76      user: build
    77    name: build
    78  current-context: build
    79  kind: Config
    80  preferences: {}
    81  users:
    82  - name: build
    83    user:
    84      client-certificate-data: fake-cert-data
    85      client-key-data: fake-key-data
    86  ```
    87  
    88  Specify the `--overwrite` flag to *replace* the `output` file if it exists.
    89  
    90  ```console
    91  $ gencred --context my-current-context --output ./existing.yaml --overwrite
    92  ```
    93  
    94  Omit the `--overwrite` flag to *merge* the `output` file if it exists.
    95  > Entries from the *existing* file take precedence on conflicts.
    96  
    97  ```console
    98  $ gencred --context my-current-context --name oldcluster --output ./existing.yaml
    99  $ gencred --context my-current-context --name newcluster --output ./existing.yaml
   100  ```
   101  
   102  The kubeconfig contents will be `output` to  `./existing.yaml`:
   103  
   104  ```yaml
   105  apiVersion: v1
   106  clusters:
   107  - cluster:
   108      certificate-authority-data: fake-ca-data
   109      server: https://1.2.3.4
   110    name: oldcluster
   111  - cluster:
   112      certificate-authority-data: fake-ca-data
   113      server: https://1.2.3.4
   114    name: newcluster
   115  contexts:
   116  - context:
   117      cluster: oldcluster
   118      user: oldcluster
   119    name: oldcluster
   120  - context:
   121      cluster: newcluster
   122      user: newcluster
   123    name: newcluster
   124  users:
   125  - name: oldcluster
   126    user:
   127      client-certificate-data: fake-cert-data
   128      client-key-data: fake-key-data
   129  - name: newcluster
   130    user:
   131      client-certificate-data: fake-cert-data
   132      client-key-data: fake-key-data
   133  ```
   134  
   135  #### Merging into a kubeconfig in a Kubernetes secret.
   136  If 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`](/gencred/merge_kubeconfig_secret.py) to merge the kubeconfig produced by `gencred` into the secret.
   137  
   138  ```shell
   139  # Generate a kubeconfig.yaml as described and shown above.
   140  ./merge_kubeconfig_secret.py --auto --context=my-kube-context kubeconfig.yaml
   141  # Note: The first time the script is used you may be prompted to rerun it with --src-key specified.
   142  # Finish by updating references (e.g. `--kubeconfig` flags in Prow deployment files) to point to the updated secret key. The script will indicate which key was updated in its output.
   143  ```
   144  
   145  The script exposes optional flags to override the secret namespace, name, keys, and pruning behavior. Run `./merge_kubeconfig_secret.py --help` to view all options.
   146  
   147  ### Library
   148  
   149  #### Generate a service account token for a cluster. 
   150  ✅ **PREFERRED** method.
   151  
   152  ```go
   153  // Import serviceaccount
   154  import "k8s.io/test-infra/gencred/pkg/serviceaccount"
   155  
   156  //...
   157  
   158  // Create a Kubernetes clientset for interacting with the cluster.
   159  // In this case we are simply using the `current-context` defined in our local `~/.kube/config`.
   160  homedir, _ := os.UserHomeDir()
   161  kubeconfig := filepath.Join(homedir, ".kube", "config")
   162  config, _ := clientcmd.BuildConfigFromFlags("", kubeconfig)
   163  clientset, _ := kubernetes.NewForConfig(config)
   164  
   165  // Generate a service account token, as well as return the certificate authority that issued the token.
   166  token, caPEM, err := serviceaccount.CreateClusterServiceAccountCredentials(clientset)
   167  ```  
   168  
   169  `token` will contain the **service account access token** and `caPEM` will contain the **server certificate authority**.
   170  
   171  This requests a token valid for one week or until the service account is deleted.
   172  
   173  ```go
   174  import "encoding/base64"
   175  
   176  //...
   177  
   178  // Cast the `token` to a string to use in a kubeconfig.
   179  accessToken := string(token)
   180  // Base64 encode the `caPEM` to use in a kubeconfig.
   181  ca := base64.StdEncoding.EncodeToString(caPEM)
   182  
   183  fmt.Println("token:", accessToken)
   184  fmt.Println("ca:", ca)
   185  ```
   186  
   187  ```text
   188  token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3Mit...
   189  ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURER...
   190  ```
   191  
   192  #### Generate a client key and certificate for a cluster.
   193  ❌ **DEPRECATED** method.
   194  
   195  ```go
   196  // Import certificate
   197  import "k8s.io/test-infra/gencred/pkg/certificate"
   198  
   199  //...
   200  
   201  // Create a Kubernetes clientset for interacting with the cluster.
   202  // In this case we are simply using the `current-context` defined in our local `~/.kube/config`.
   203  homedir, _ := os.UserHomeDir()
   204  kubeconfig := filepath.Join(homedir, ".kube", "config")
   205  config, _ := clientcmd.BuildConfigFromFlags("", kubeconfig)
   206  clientset, _ := kubernetes.NewForConfig(config)
   207  
   208  // Generate a client key and certificate, as well as return the certificate authority that issued the certificate.
   209  certPEM, keyPEM, caPEM, err := certificate.CreateClusterCertificateCredentials(clientset)
   210  ```  
   211  
   212  `certPEM` will contain the **client certificate**, `keyPEM` will contain the **client key**, and `caPEM` will contain the **server certificate authority**.
   213  
   214  ```go
   215  import "encoding/base64"
   216  
   217  //...
   218  
   219  // Base64 encode the `certPEM`, `keyPEM`, and `caPEM` to use in a kubeconfig.
   220  cert := base64.StdEncoding.EncodeToString(certPEM)
   221  key := base64.StdEncoding.EncodeToString(keyPEM)
   222  ca := base64.StdEncoding.EncodeToString(caPEM)
   223  
   224  fmt.Println("cert:", cert)
   225  fmt.Println("key:", key)
   226  fmt.Println("ca:", ca)
   227  ```
   228  
   229  ```text
   230  cert: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1...
   231  key: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNL...
   232  ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURER...
   233  ```
   234  
   235  #### Caveats to using client certificates:
   236  * The use of [x509 client certificate](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) with [super-user](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) privileges for cluster authentication/authorization has several drawbacks:
   237      - Certificates **cannot** be revoked ([kubernetes/kubernetes#60917](https://github.com/kubernetes/kubernetes/issues/60917))
   238      - Authorization roles are essentially *global* and thus **cannot** be tweaked at the node level.
   239      - Unless setup with near expiry and explicit rotation, certificates are *long-lived* and **increase** the risk of exposure.
   240  
   241  * Client certificate authentication will be deprecated in future versions of Prow  ([kubernetes/test-infra#13972](https://github.com/kubernetes/test-infra/issues/13972)).