| package certs |
| |
| import ( |
| "net" |
| "time" |
| ) |
| |
| // Certificates is the set of certificates required to run our Kubernetes |
| // production. |
| type Certificates struct { |
| CAs CAs |
| |
| ProdviderIntermediateCA *Certificate |
| |
| Global Global |
| PerNode map[string]PerNode |
| } |
| |
| type ensurer interface { |
| Ensure() error |
| } |
| |
| // Ensure checks that all the Kubernetes production certificates and keys are |
| // present on disk, generating them as necessary. |
| // |
| // If the user has not decrypted cluster/secrets, an error will be returned. |
| // However, deeper sync checks are not currently performed. |
| func (c *Certificates) Ensure() error { |
| sub := []ensurer{ |
| &c.CAs, |
| c.ProdviderIntermediateCA, |
| &c.Global, |
| } |
| for _, pn := range c.PerNode { |
| sub = append(sub, &pn) |
| } |
| for _, s := range sub { |
| if err := s.Ensure(); err != nil { |
| return err |
| } |
| } |
| return nil |
| } |
| |
| // CAs are the root certificate authorities we use. |
| type CAs struct { |
| // EtcdPeer is used by etcd member nodes to authenticate peers. |
| EtcdPeer *Certificate |
| // Etcd is used by etcd membrer nodes to authenticate clients (ie. |
| // kube-apiservers). |
| Etcd *Certificate |
| // Kube is the main Kubernetes 'identity' CA, used to identify components |
| // and users. |
| Kube *Certificate |
| // KubeFront is the proxy/aggregation CA used by external apiservices to |
| // authenticate incoming apiserver connections. |
| KubeFront *Certificate |
| // Admitomatic is the CA used by the admitomatic webhook to authenticate |
| // incoming apiserver connections. |
| Admitomatic *Certificate |
| } |
| |
| func (c *CAs) Ensure() error { |
| sub := []ensurer{ |
| c.EtcdPeer, |
| c.Etcd, |
| c.Kube, |
| c.KubeFront, |
| c.Admitomatic, |
| } |
| for _, s := range sub { |
| if err := s.Ensure(); err != nil { |
| return err |
| } |
| } |
| return nil |
| } |
| |
| // Global are all the non-per-node certificates we use. |
| type Global struct { |
| // EtcdKube is used by kubernetes apiservers to authenticate to etcd |
| // members. |
| EtcdKube *Certificate |
| |
| // KubeApiserver is used by kubernetes apiservers to authenticate to other |
| // kubernetes components/users. |
| KubeApiserver *Certificate |
| // KubeControllerManager is used by kubernetes controller managers to |
| // authenticate to the kubernetes apiservers. |
| KubeControllerManager *Certificate |
| // KubeScheduler is used by the kubernetes schedulers to authenticate to |
| // the kubernetes apiservers. |
| KubeScheduler *Certificate |
| |
| // KubefrontApiserver is used by the kubernetes apiserver to authenticate |
| // to external apiservices. |
| KubefrontApiserver *Certificate |
| |
| // AdmitomaticWebhook is used by the admitomatic webhook to authenticate to |
| // the Kubernetes apiservers. |
| AdmitomaticWebhook *Certificate |
| } |
| |
| func (g *Global) Ensure() error { |
| sub := []ensurer{ |
| g.EtcdKube, |
| g.KubeApiserver, |
| g.KubeControllerManager, |
| g.KubeScheduler, |
| g.KubefrontApiserver, |
| g.AdmitomaticWebhook, |
| } |
| for _, s := range sub { |
| if err := s.Ensure(); err != nil { |
| return err |
| } |
| } |
| return nil |
| } |
| |
| func (c *Certificates) MakeKubeEmergencyCreds(root, breadcrumb string) *Certificate { |
| return &Certificate{ |
| name: "emergency", |
| duration: 7 * 24 * time.Hour, |
| root: root, |
| kind: kindClient, |
| cn: "admin", |
| san: []string{"admin", breadcrumb}, |
| o: "system:masters", |
| issuer: c.CAs.Kube, |
| } |
| } |
| |
| // Per node are all the per-node certificates we use. |
| type PerNode struct { |
| // EtcdPeer is used by etcd members to authenticate to other etcd members. |
| EtcdPeer *Certificate |
| // EtcdClient is used by etcd members to authenticate to their clients. |
| EtcdClient *Certificate |
| |
| // Kubelet is used by kubelets to authenticate to other kubernetes |
| // components. |
| Kubelet *Certificate |
| } |
| |
| func (p *PerNode) Ensure() error { |
| sub := []ensurer{ |
| p.EtcdPeer, |
| p.EtcdClient, |
| p.Kubelet, |
| } |
| for _, s := range sub { |
| if err := s.Ensure(); err != nil { |
| return err |
| } |
| } |
| return nil |
| } |
| |
| func mkCA(root, name, cn string) *Certificate { |
| return &Certificate{ |
| name: name, |
| root: root, |
| kind: kindCA, |
| cn: cn, |
| } |
| } |
| |
| // Prepare builds our Certificates structure at a given location on the |
| // filesystem, for the given nodes. |
| // |
| // Calling Ensure() on the returned Certificates will actually engage |
| // generation logic. Before that, no disk accesses are performed. |
| func Prepare(root string, fqdns []string) Certificates { |
| certs := Certificates{ |
| CAs: CAs{ |
| EtcdPeer: mkCA(root, "ca-etcdpeer", "etcd peer ca"), |
| Etcd: mkCA(root, "ca-etcd", "etcd ca"), |
| Kube: mkCA(root, "ca-kube", "kubernetes main CA"), |
| KubeFront: mkCA(root, "ca-kubefront", "kubernetes frontend CA"), |
| Admitomatic: mkCA(root, "ca-admitomatic", "admitomatic webhook CA"), |
| }, |
| PerNode: make(map[string]PerNode), |
| } |
| |
| certs.ProdviderIntermediateCA = &Certificate{ |
| name: "ca-kube-prodvider", |
| root: root, |
| kind: kindProdvider, |
| cn: "kubernetes prodvider intermediate", |
| issuer: certs.CAs.Kube, |
| } |
| certs.Global = Global{ |
| EtcdKube: &Certificate{ |
| name: "etcd-kube", |
| root: root, |
| kind: kindClient, |
| cn: "kube etcd client certificate", |
| san: []string{"kube"}, |
| issuer: certs.CAs.Etcd, |
| }, |
| KubeApiserver: &Certificate{ |
| name: "kube-apiserver", |
| root: root, |
| kind: kindClientServer, |
| cn: "k0.hswaw.net", |
| san: []string{ |
| "k0.hswaw.net", |
| "kubernetes.default.svc.k0.hswaw.net", |
| }, |
| ips: []net.IP{ |
| {10, 10, 12, 1}, |
| }, |
| issuer: certs.CAs.Kube, |
| }, |
| KubeControllerManager: &Certificate{ |
| name: "kube-controllermanager", |
| root: root, |
| kind: kindClientServer, |
| cn: "system:kube-controller-manager", |
| san: []string{"system:kube-controller-manager"}, |
| o: "system:kube-controller-manager", |
| issuer: certs.CAs.Kube, |
| }, |
| KubeScheduler: &Certificate{ |
| name: "kube-scheduler", |
| root: root, |
| kind: kindClientServer, |
| cn: "system:kube-scheduler", |
| san: []string{"system:kube-scheduler"}, |
| o: "system:kube-scheduler", |
| issuer: certs.CAs.Kube, |
| }, |
| KubefrontApiserver: &Certificate{ |
| name: "kubefront-apiserver", |
| root: root, |
| kind: kindClientServer, |
| cn: "Kubernetes Frontend", |
| san: []string{"apiserver"}, |
| issuer: certs.CAs.KubeFront, |
| }, |
| AdmitomaticWebhook: &Certificate{ |
| name: "admitomatic-webhook", |
| root: root, |
| kind: kindServer, |
| cn: "Admitomatic Webhook", |
| san: []string{"admitomatic.admitomatic.svc"}, |
| issuer: certs.CAs.Admitomatic, |
| }, |
| } |
| for _, fqdn := range fqdns { |
| certs.PerNode[fqdn] = PerNode{ |
| EtcdPeer: &Certificate{ |
| name: "etcdpeer-" + fqdn, |
| root: root, |
| kind: kindClientServer, |
| cn: "node etcd peer certificate", |
| san: []string{fqdn}, |
| issuer: certs.CAs.EtcdPeer, |
| }, |
| EtcdClient: &Certificate{ |
| name: "etcd-" + fqdn, |
| root: root, |
| // etcd seems to need client too, as it's connecting to itself |
| // for... some reason? |
| // https://github.com/etcd-io/etcd/issues/9785 |
| kind: kindClientServer, |
| cn: "node etcd server certificate", |
| san: []string{fqdn}, |
| issuer: certs.CAs.Etcd, |
| }, |
| Kubelet: &Certificate{ |
| name: "kube-kubelet-" + fqdn, |
| root: root, |
| kind: kindClientServer, |
| cn: "system:node:" + fqdn, |
| o: "system:nodes", |
| san: []string{ |
| "system:node:" + fqdn, |
| fqdn, |
| }, |
| issuer: certs.CAs.Kube, |
| }, |
| } |
| } |
| |
| return certs |
| } |