Issue certs using CA KeypairID in NodeupConfig

This commit is contained in:
John Gardiner Myers 2021-07-10 22:16:47 -07:00
parent 6ddccf5f79
commit 68041a4f73
9 changed files with 89 additions and 34 deletions

View File

@ -214,10 +214,11 @@ func (c *NodeupModelContext) KubeletKubeConfig() string {
// BuildIssuedKubeconfig generates a kubeconfig with a locally issued client certificate.
func (c *NodeupModelContext) BuildIssuedKubeconfig(name string, subject nodetasks.PKIXName, ctx *fi.ModelBuilderContext) *fi.TaskDependentResource {
issueCert := &nodetasks.IssueCert{
Name: name,
Signer: fi.CertificateIDCA,
Type: "client",
Subject: subject,
Name: name,
Signer: fi.CertificateIDCA,
KeypairID: c.NodeupConfig.KeypairIDs[fi.CertificateIDCA],
Type: "client",
Subject: subject,
}
ctx.AddTask(issueCert)
certResource, keyResource, caResource := issueCert.GetResources()

View File

@ -56,6 +56,7 @@ func (b *KopsControllerBuilder) Build(c *fi.ModelBuilderContext) error {
issueCert := &nodetasks.IssueCert{
Name: "kops-controller",
Signer: fi.CertificateIDCA,
KeypairID: b.NodeupConfig.KeypairIDs[fi.CertificateIDCA],
Type: "server",
Subject: nodetasks.PKIXName{CommonName: "kops-controller"},
AlternateNames: []string{"kops-controller.internal." + b.Cluster.ObjectMeta.Name},

View File

@ -116,9 +116,10 @@ func (b *KubeAPIServerBuilder) Build(c *fi.ModelBuilderContext) error {
kubeAPIServer.EtcdCAFile = filepath.Join(pathSrvKAPI, "etcd-ca.crt")
issueCert := &nodetasks.IssueCert{
Name: "etcd-client",
Signer: "etcd-clients-ca",
Type: "client",
Name: "etcd-client",
Signer: "etcd-clients-ca",
KeypairID: b.NodeupConfig.KeypairIDs["etcd-clients-ca"],
Type: "client",
Subject: nodetasks.PKIXName{
CommonName: "kube-apiserver",
},
@ -145,9 +146,10 @@ func (b *KubeAPIServerBuilder) Build(c *fi.ModelBuilderContext) error {
kubeAPIServer.RequestheaderClientCAFile = filepath.Join(pathSrvKAPI, "apiserver-aggregator-ca.crt")
issueCert := &nodetasks.IssueCert{
Name: "apiserver-aggregator",
Signer: "apiserver-aggregator-ca",
Type: "client",
Name: "apiserver-aggregator",
Signer: "apiserver-aggregator-ca",
KeypairID: b.NodeupConfig.KeypairIDs["apiserver-aggregator-ca"],
Type: "client",
// Must match RequestheaderAllowedNames
Subject: nodetasks.PKIXName{CommonName: "aggregator"},
}
@ -186,10 +188,11 @@ func (b *KubeAPIServerBuilder) Build(c *fi.ModelBuilderContext) error {
}
issueCert := &nodetasks.IssueCert{
Name: "kubelet-api",
Signer: fi.CertificateIDCA,
Type: "client",
Subject: nodetasks.PKIXName{CommonName: "kubelet-api"},
Name: "kubelet-api",
Signer: fi.CertificateIDCA,
KeypairID: b.NodeupConfig.KeypairIDs[fi.CertificateIDCA],
Type: "client",
Subject: nodetasks.PKIXName{CommonName: "kubelet-api"},
}
c.AddTask(issueCert)
err := issueCert.AddFileTasks(c, b.PathSrvKubernetes(), "kubelet-api", "", nil)
@ -308,10 +311,11 @@ func (b *KubeAPIServerBuilder) writeAuthenticationConfig(c *fi.ModelBuilderConte
{
issueCert := &nodetasks.IssueCert{
Name: id,
Signer: fi.CertificateIDCA,
Type: "server",
Subject: nodetasks.PKIXName{CommonName: id},
Name: id,
Signer: fi.CertificateIDCA,
KeypairID: b.NodeupConfig.KeypairIDs[fi.CertificateIDCA],
Type: "server",
Subject: nodetasks.PKIXName{CommonName: id},
AlternateNames: []string{
"localhost",
"127.0.0.1",

View File

@ -82,9 +82,10 @@ func (b *KubeAPIServerBuilder) addHealthcheckSidecarTasks(c *fi.ModelBuilderCont
}
issueCert := &nodetasks.IssueCert{
Name: id,
Signer: fi.CertificateIDCA,
Type: "client",
Name: id,
Signer: fi.CertificateIDCA,
KeypairID: b.NodeupConfig.KeypairIDs[fi.CertificateIDCA],
Type: "client",
Subject: nodetasks.PKIXName{
CommonName: id,
},

View File

@ -552,7 +552,6 @@ func (b *KubeletBuilder) buildKubeletServingCertificate(c *fi.ModelBuilderContex
if b.UseKopsControllerForNodeBootstrap() {
name := "kubelet-server"
dir := b.PathSrvKubernetes()
signer := fi.CertificateIDCA
nodeName, err := b.NodeName()
if err != nil {
@ -580,9 +579,10 @@ func (b *KubeletBuilder) buildKubeletServingCertificate(c *fi.ModelBuilderContex
} else {
issueCert := &nodetasks.IssueCert{
Name: name,
Signer: signer,
Type: "server",
Name: name,
Signer: fi.CertificateIDCA,
KeypairID: b.NodeupConfig.KeypairIDs[fi.CertificateIDCA],
Type: "server",
Subject: nodetasks.PKIXName{
CommonName: nodeName,
},

View File

@ -109,11 +109,12 @@ func (b *CiliumBuilder) buildCiliumEtcdSecrets(c *fi.ModelBuilderContext) error
Type: nodetasks.FileType_File,
Mode: fi.String("0600"),
})
if b.IsMaster {
if b.HasAPIServer {
issueCert := &nodetasks.IssueCert{
Name: name,
Signer: signer,
Type: "client",
Name: name,
Signer: signer,
KeypairID: b.NodeupConfig.KeypairIDs[signer],
Type: "client",
Subject: nodetasks.PKIXName{
CommonName: "cilium",
},

View File

@ -119,6 +119,7 @@ func (b *SecretBuilder) Build(c *fi.ModelBuilderContext) error {
issueCert := &nodetasks.IssueCert{
Name: "master",
Signer: fi.CertificateIDCA,
KeypairID: b.NodeupConfig.KeypairIDs[fi.CertificateIDCA],
Type: "server",
Subject: nodetasks.PKIXName{CommonName: "kubernetes-master"},
AlternateNames: alternateNames,

View File

@ -1284,6 +1284,7 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, apiserverAddit
useGossip := dns.IsGossipHostname(cluster.Spec.MasterInternalName)
isMaster := role == kops.InstanceGroupRoleMaster
hasAPIServer := isMaster || role == kops.InstanceGroupRoleAPIServer
config, bootConfig := nodeup.NewConfig(cluster, ig)
@ -1299,7 +1300,7 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, apiserverAddit
return nil, nil, err
}
if caTasks["etcd-clients-ca-cilium"] != nil {
if err := getTasksCertificate(caTasks, "etcd-clients-ca-cilium", config, false); err != nil {
if err := getTasksCertificate(caTasks, "etcd-clients-ca-cilium", config, hasAPIServer); err != nil {
return nil, nil, err
}
}
@ -1330,12 +1331,12 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, apiserverAddit
}
}
if isMaster || role == kops.InstanceGroupRoleAPIServer {
if err := getTasksCertificate(caTasks, "apiserver-aggregator-ca", config, false); err != nil {
if hasAPIServer {
if err := getTasksCertificate(caTasks, "apiserver-aggregator-ca", config, true); err != nil {
return nil, nil, err
}
if caTasks["etcd-clients-ca"] != nil {
if err := getTasksCertificate(caTasks, "etcd-clients-ca", config, false); err != nil {
if err := getTasksCertificate(caTasks, "etcd-clients-ca", config, true); err != nil {
return nil, nil, err
}
}

View File

@ -50,6 +50,7 @@ type IssueCert struct {
Name string
Signer string `json:"signer"`
KeypairID string `json:"keypairID"`
Type string `json:"type"`
Subject PKIXName `json:"subject"`
AlternateNames []string `json:"alternateNames,omitempty"`
@ -152,8 +153,13 @@ func (e *IssueCert) Run(c *fi.Context) error {
Validity: time.Hour * time.Duration(validHours),
}
keystore, err := newStaticKeystore(e.Signer, e.KeypairID, c.Keystore)
if err != nil {
return err
}
klog.Infof("signing certificate for %q", e.Name)
certificate, privateKey, caCertificate, err := pki.IssueCert(req, c.Keystore)
certificate, privateKey, caCertificate, err := pki.IssueCert(req, keystore)
if err != nil {
return err
}
@ -193,3 +199,42 @@ func (a asBytesResource) Open() (io.Reader, error) {
}
return bytes.NewReader(data), nil
}
type staticKeystore struct {
keyset string
certificate *pki.Certificate
key *pki.PrivateKey
}
func (s staticKeystore) FindPrimaryKeypair(name string) (*pki.Certificate, *pki.PrivateKey, error) {
if name != s.keyset {
return nil, nil, fmt.Errorf("wrong signer: expected %q got %q", s.keyset, name)
}
return s.certificate, s.key, nil
}
func newStaticKeystore(signer string, keypairID string, keystore fi.Keystore) (pki.Keystore, error) {
if signer == "" {
return nil, nil
}
if keypairID == "" {
return nil, fmt.Errorf("missing keypairID for %s", signer)
}
keyset, err := keystore.FindKeyset(signer)
if err != nil {
return nil, fmt.Errorf("reading keyset for %s: %v", signer, err)
}
item := keyset.Items[keypairID]
if item == nil {
return nil, fmt.Errorf("no keypair with id %s for %s", keypairID, signer)
}
return &staticKeystore{
keyset: signer,
certificate: item.Certificate,
key: item.PrivateKey,
}, nil
}