{"id":21475148,"url":"https://github.com/snapp-incubator/cluster-machine-approver","last_synced_at":"2025-07-15T09:32:17.033Z","repository":{"id":39440486,"uuid":"448061888","full_name":"snapp-incubator/cluster-machine-approver","owner":"snapp-incubator","description":"A modified version of https://github.com/openshift/cluster-machine-approver","archived":false,"fork":false,"pushed_at":"2024-06-01T03:08:16.000Z","size":40397,"stargazers_count":11,"open_issues_count":2,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-06-12T08:53:01.287Z","etag":null,"topics":["fork","golang","k8s-controller","kubernetes","oss","runtime","snappcloud"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/snapp-incubator.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-14T18:02:10.000Z","updated_at":"2024-08-06T04:30:13.000Z","dependencies_parsed_at":"2023-02-17T01:30:49.527Z","dependency_job_id":"8439a3eb-0ce8-4f51-beb6-3620d5545961","html_url":"https://github.com/snapp-incubator/cluster-machine-approver","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/snapp-incubator/cluster-machine-approver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fcluster-machine-approver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fcluster-machine-approver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fcluster-machine-approver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fcluster-machine-approver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/snapp-incubator","download_url":"https://codeload.github.com/snapp-incubator/cluster-machine-approver/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fcluster-machine-approver/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265425320,"owners_count":23762900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fork","golang","k8s-controller","kubernetes","oss","runtime","snappcloud"],"created_at":"2024-11-23T10:37:52.152Z","updated_at":"2025-07-15T09:32:14.577Z","avatar_url":"https://github.com/snapp-incubator.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cluster-machine-approver\n\nThis controller provides the following functionality:\n - Watch the CSR endpoint for CSR requests\n - Decide if the CSR should be allowed or denied\n - Approve or deny and update CSR status\n\n## Introduction\n\nKubernetes includes support for [TLS\nbootstrapping](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/)\nfor Nodes, which OpenShift makes use of.\n\nKubelet needs two certificates for its normal operation:\n\n* **Client certificate** - for securely communicating with the Kubernetes API\n  server\n* **Server certificate** - for use in its own local https endpoint, [used by\n  the API server to talk back to\n  kubelet](https://kubernetes.io/docs/concepts/architecture/master-node-communication/#apiserver-to-kubelet)\n\nWhen a new host is provisioned, kubelet will start and communicates to the CSR\n(Certificate Signing Request) API endpoint to request signed client and server\ncertificates.  It issues this request using [bootstrap\ncredentials](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#initial-bootstrap-authentication)\nthat it finds on its local filesystem.\n\nAt this point, these CSRs must be approved.  They can be manually [approved\nthrough the API using\nkubectl](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#kubectl-approval),\nor [kube-controller-manager can be configured to approve\nthem](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#kube-controller-manager-configuration).\nAlternatively, some custom component could be built to approve CSRs through the\nAPI, which is what OpenShift has done.\n\n## OpenShift and CSRs\n\nOpenShift includes a custom component to approve CSRs: the\n`cluster-machine-approver`.  The `cluster-machine-approver` is used to\nautomatically approve CSRs, but with more strict criteria than what was\nsupported in `kube-controller-manager`.\n\nNote that the `cluster-machine-approver` only kicks in post-install.  During\nthe cluster bootstrapping phase, the [approve-csr service on the bootstrap\nnode](https://github.com/openshift/installer/commit/c5d4d0f3ab3b0e65cb8d6af3ff6dfb3162dfa1d6)\nautomatically approves all CSRs.  This bootstrap service will end up approving\nthe CSRs for the control plane nodes, while `cluster-machine-approver` will\ntake over for future new CSRs from worker nodes.\n\n### Disabling Node Client CSR Approvals\n\nIt is possible to disable node client CSR approvals completely.  This is done\nusing a `ConfigMap` resource, as shown in [this PR\ncomment](https://github.com/openshift/cluster-machine-approver/pull/26#issuecomment-492782189).\n\n```yaml\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: machine-approver-config\n  namespace: machine-approver\ndata:\n  config.yaml: |-\n    nodeClientCert:\n      disabled: true\n```\n\nThis may be useful if you explicitly want to only allow manual CSR approvals\nfor new nodes.\n\n### Node Client CSR Approval Workflow\n\nCSR approval details can be found in [csr_check.go](https://github.com/openshift/cluster-machine-approver/blob/master/pkg/controller/csr_check.go).  Assuming\nthis has not been disabled, the following criteria must be met for the client\nCSR to be approved:\n\n* The user must be the node bootstrapper\n  * The username in the CSR must be\n    `system:serviceaccount:openshift-machine-config-operator:node-bootstrapper`\n  * The groups in the CSR must be\n    `system:serviceaccounts:openshift-machine-config-operator`,\n    `system:serviceaccounts`, and `system:authenticated`.\n* A `Node` object must not yet exist for the node that created the CSR.\n* The `Machine` API is used to do a sanity check.  A `Machine` must exist with\n  a `NodeInternalDNS` address in its `Status` that matches the future name of\n  the `Node`, as found in the CSR.\n* This `Machine` must not have a `NodeRef` set.\n* The CSR creation timestamp must be close to the `Machine` creation timestamp\n  (currently within 2 hours)\n* The CSR is for node client auth.\n\n### Node Server CSR Approval Workflow\n\nDetails of this workflow can be found in the same file as the client workflow,\n[csr_check.go](https://github.com/openshift/cluster-machine-approver/blob/master/pkg/controller/csr_check.go).\n\nFor this workflow, it is assumed that the `Node` is now up and running, and the\n`Node` object exists in the API.  Validation for the server CSR is different\nthan the client case and is based primarily on matching addresses between\nassociated `Node` and `Machine` objects.\n\nFirst, there must be a `Machine` object with a `NodeRef` field set to the\n`Node` that sent this CSR.  The `NodeRef` is set by a `Node` controller under\nthe [machine-api-operator](https://github.com/openshift/machine-api-operator).\n\nOnce a `Node`-`Machine` pair has been identified, validation is done on all of\nthe `Addresses` in the `Status` field of the `Machine`.  The CSR requests a\ncertificate with the [SAN (Subject Alternate Names)\nextension](https://geekflare.com/san-ssl-certificate/).  The resulting\ncertificate will be valid for every address or hostname listed on the `Node`\nresource to validate this request, the `cluster-machine-approver` ensures that\nevery DNS name or IP address in the CSR matches a (`NodeInternalDNS`,\n`NodeExternalDNS`, `NodeHostName`) or (`NodeInternalIP`, `NodeExternalIP`)\naddress on the corresponding `Machine` object.\n\n### Requirements for Cluster API Providers\n\nAs discussed in previous sections, `cluster-machine-approver` imposes some\nrequirements on each Cluster API provider used with the\n[machine-api-operator](https://github.com/openshift/machine-api-operator).\nThis section serves as a summary of those requirements.\n\n* A `Machine` must have a `NodeInternalDNS` set in `Status.Addresses` that\n  matches the name of the `Node`.  The `NodeInternalDNS` entry **must** be\n  present, even before the `Node` resource is created.\n* A `Machine` must also have matching `NodeInternalDNS`, `NodeExternalDNS`,\n  `NodeHostName`, `NodeInternalIP`, and `NodeExternalIP` addresses as those\n  listed on the `Node` resource.  All of these addresses are placed in the CSR\n  and are validated against the addresses on the `Machine` object.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnapp-incubator%2Fcluster-machine-approver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnapp-incubator%2Fcluster-machine-approver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnapp-incubator%2Fcluster-machine-approver/lists"}