diff --git a/pkg/asset/ignition/bootstrap/bootstrap.go b/pkg/asset/ignition/bootstrap/bootstrap.go index fcc1ff25001..6b9009b575c 100644 --- a/pkg/asset/ignition/bootstrap/bootstrap.go +++ b/pkg/asset/ignition/bootstrap/bootstrap.go @@ -62,23 +62,50 @@ var _ asset.WritableAsset = (*Bootstrap)(nil) func (a *Bootstrap) Dependencies() []asset.Asset { return []asset.Asset{ &installconfig.InstallConfig{}, - &tls.RootCA{}, - &tls.EtcdCA{}, - &tls.KubeCA{}, + &kubeconfig.Admin{}, + &kubeconfig.AdminClient{}, + &kubeconfig.Kubelet{}, + &kubeconfig.KubeletClient{}, + &machines.Master{}, + &manifests.Manifests{}, + &manifests.Openshift{}, &tls.AggregatorCA{}, - &tls.EtcdClientCertKey{}, + &tls.AggregatorCABundle{}, + &tls.AggregatorClientCertKey{}, + &tls.AggregatorSignerCertKey{}, &tls.APIServerCertKey{}, &tls.APIServerProxyCertKey{}, - &tls.AdminCertKey{}, + &tls.EtcdCA{}, + &tls.EtcdCABundle{}, + &tls.EtcdClientCertKey{}, + &tls.EtcdSignerCertKey{}, + &tls.EtcdSignerClientCertKey{}, + &tls.JournalCertKey{}, + &tls.KubeAPIServerLBCABundle{}, + &tls.KubeAPIServerLBServerCertKey{}, + &tls.KubeAPIServerLBSignerCertKey{}, + &tls.KubeAPIServerLocalhostCABundle{}, + &tls.KubeAPIServerLocalhostServerCertKey{}, + &tls.KubeAPIServerLocalhostSignerCertKey{}, + &tls.KubeAPIServerServiceNetworkCABundle{}, + &tls.KubeAPIServerServiceNetworkServerCertKey{}, + &tls.KubeAPIServerServiceNetworkSignerCertKey{}, + &tls.KubeAPIServerToKubeletCABundle{}, + &tls.KubeAPIServerToKubeletClientCertKey{}, + &tls.KubeAPIServerToKubeletSignerCertKey{}, + &tls.KubeCA{}, + &tls.KubeControlPlaneCABundle{}, + &tls.KubeControlPlaneKubeControllerManagerClientCertKey{}, + &tls.KubeControlPlaneKubeSchedulerClientCertKey{}, + &tls.KubeControlPlaneSignerCertKey{}, &tls.KubeletCertKey{}, + &tls.KubeletClientCABundle{}, + &tls.KubeletClientCertKey{}, + &tls.KubeletCSRSignerCertKey{}, + &tls.KubeletServingCABundle{}, &tls.MCSCertKey{}, + &tls.RootCA{}, &tls.ServiceAccountKeyPair{}, - &tls.JournalCertKey{}, - &kubeconfig.Admin{}, - &kubeconfig.Kubelet{}, - &machines.Master{}, - &manifests.Manifests{}, - &manifests.Openshift{}, } } @@ -333,31 +360,54 @@ func readFile(name string, reader io.Reader, templateData interface{}) (finalNam } func (a *Bootstrap) addParentFiles(dependencies asset.Parents) { - mfsts := &manifests.Manifests{} - openshiftManifests := &manifests.Openshift{} - dependencies.Get(mfsts, openshiftManifests) - - a.Config.Storage.Files = append( - a.Config.Storage.Files, - ignition.FilesFromAsset(rootDir, "root", 0644, mfsts)..., - ) - a.Config.Storage.Files = append( - a.Config.Storage.Files, - ignition.FilesFromAsset(rootDir, "root", 0644, openshiftManifests)..., - ) + for _, asset := range []asset.WritableAsset{ + &manifests.Manifests{}, + &manifests.Openshift{}, + &machines.Master{}, + } { + dependencies.Get(asset) + a.Config.Storage.Files = append(a.Config.Storage.Files, ignition.FilesFromAsset(rootDir, "root", 0644, asset)...) + } for _, asset := range []asset.WritableAsset{ &kubeconfig.Admin{}, + &kubeconfig.AdminClient{}, &kubeconfig.Kubelet{}, - &machines.Master{}, - &tls.KubeCA{}, + &kubeconfig.KubeletClient{}, + &kubeconfig.KubeletClient{}, &tls.AggregatorCA{}, - &tls.EtcdCA{}, - &tls.EtcdClientCertKey{}, + &tls.AggregatorCABundle{}, + &tls.AggregatorClientCertKey{}, + &tls.AggregatorSignerCertKey{}, &tls.APIServerCertKey{}, &tls.APIServerProxyCertKey{}, - &tls.AdminCertKey{}, + &tls.EtcdCA{}, + &tls.EtcdCABundle{}, + &tls.EtcdClientCertKey{}, + &tls.EtcdSignerCertKey{}, + &tls.EtcdSignerClientCertKey{}, + &tls.KubeAPIServerLBCABundle{}, + &tls.KubeAPIServerLBServerCertKey{}, + &tls.KubeAPIServerLBSignerCertKey{}, + &tls.KubeAPIServerLocalhostCABundle{}, + &tls.KubeAPIServerLocalhostServerCertKey{}, + &tls.KubeAPIServerLocalhostSignerCertKey{}, + &tls.KubeAPIServerServiceNetworkCABundle{}, + &tls.KubeAPIServerServiceNetworkServerCertKey{}, + &tls.KubeAPIServerServiceNetworkSignerCertKey{}, + &tls.KubeAPIServerToKubeletCABundle{}, + &tls.KubeAPIServerToKubeletClientCertKey{}, + &tls.KubeAPIServerToKubeletSignerCertKey{}, + &tls.KubeCA{}, + &tls.KubeControlPlaneCABundle{}, + &tls.KubeControlPlaneKubeControllerManagerClientCertKey{}, + &tls.KubeControlPlaneKubeSchedulerClientCertKey{}, + &tls.KubeControlPlaneSignerCertKey{}, &tls.KubeletCertKey{}, + &tls.KubeletClientCABundle{}, + &tls.KubeletClientCertKey{}, + &tls.KubeletCSRSignerCertKey{}, + &tls.KubeletServingCABundle{}, &tls.MCSCertKey{}, &tls.ServiceAccountKeyPair{}, } { diff --git a/pkg/asset/kubeconfig/admin.go b/pkg/asset/kubeconfig/admin.go index 2af06c9304e..ffb359f7628 100644 --- a/pkg/asset/kubeconfig/admin.go +++ b/pkg/asset/kubeconfig/admin.go @@ -9,10 +9,12 @@ import ( ) var ( - kubeconfigAdminPath = filepath.Join("auth", "kubeconfig") + kubeconfigAdminPath = filepath.Join("auth", "kubeconfig") + kubeconfigAdminClientPath = filepath.Join("auth", "kubeconfig-admin") ) // Admin is the asset for the admin kubeconfig. +// [DEPRECATED] type Admin struct { kubeconfig } @@ -53,3 +55,45 @@ func (k *Admin) Name() string { func (k *Admin) Load(f asset.FileFetcher) (found bool, err error) { return k.load(f, kubeconfigAdminPath) } + +// AdminClient is the asset for the admin kubeconfig. +type AdminClient struct { + kubeconfig +} + +var _ asset.WritableAsset = (*AdminClient)(nil) + +// Dependencies returns the dependency of the kubeconfig. +func (k *AdminClient) Dependencies() []asset.Asset { + return []asset.Asset{ + &tls.AdminKubeConfigClientCertKey{}, + &tls.AdminKubeConfigCABundle{}, + &installconfig.InstallConfig{}, + } +} + +// Generate generates the kubeconfig. +func (k *AdminClient) Generate(parents asset.Parents) error { + ca := &tls.AdminKubeConfigCABundle{} + clientCertKey := &tls.AdminKubeConfigClientCertKey{} + installConfig := &installconfig.InstallConfig{} + parents.Get(ca, clientCertKey, installConfig) + + return k.kubeconfig.generate( + ca, + clientCertKey, + installConfig.Config, + "admin", + kubeconfigAdminClientPath, + ) +} + +// Name returns the human-friendly name of the asset. +func (k *AdminClient) Name() string { + return "Kubeconfig Admin Client" +} + +// Load returns the kubeconfig from disk. +func (k *AdminClient) Load(f asset.FileFetcher) (found bool, err error) { + return k.load(f, kubeconfigAdminClientPath) +} diff --git a/pkg/asset/kubeconfig/kubeconfig.go b/pkg/asset/kubeconfig/kubeconfig.go index 4df217164a8..73e39ca8a32 100644 --- a/pkg/asset/kubeconfig/kubeconfig.go +++ b/pkg/asset/kubeconfig/kubeconfig.go @@ -20,7 +20,7 @@ type kubeconfig struct { // generate generates the kubeconfig. func (k *kubeconfig) generate( - rootCA tls.CertKeyInterface, + ca tls.CertInterface, clientCertKey tls.CertKeyInterface, installConfig *types.InstallConfig, userName string, @@ -32,7 +32,7 @@ func (k *kubeconfig) generate( Name: installConfig.ObjectMeta.Name, Cluster: clientcmd.Cluster{ Server: fmt.Sprintf("https://api.%s:6443", installConfig.ClusterDomain()), - CertificateAuthorityData: []byte(rootCA.Cert()), + CertificateAuthorityData: ca.Cert(), }, }, }, @@ -40,8 +40,8 @@ func (k *kubeconfig) generate( { Name: userName, AuthInfo: clientcmd.AuthInfo{ - ClientCertificateData: []byte(clientCertKey.Cert()), - ClientKeyData: []byte(clientCertKey.Key()), + ClientCertificateData: clientCertKey.Cert(), + ClientKeyData: clientCertKey.Key(), }, }, }, diff --git a/pkg/asset/kubeconfig/kubelet.go b/pkg/asset/kubeconfig/kubelet.go index 62b3a12ce5e..5b64ad2acda 100644 --- a/pkg/asset/kubeconfig/kubelet.go +++ b/pkg/asset/kubeconfig/kubelet.go @@ -9,10 +9,12 @@ import ( ) var ( - kubeconfigKubeletPath = filepath.Join("auth", "kubeconfig-kubelet") + kubeconfigKubeletPath = filepath.Join("auth", "kubeconfig-kubelet") + kubeconfigKubeletClientPath = filepath.Join("auth", "kubeconfig-kubelet-client") ) // Kubelet is the asset for the kubelet kubeconfig. +// [DEPRECATED] type Kubelet struct { kubeconfig } @@ -53,3 +55,45 @@ func (k *Kubelet) Name() string { func (k *Kubelet) Load(asset.FileFetcher) (bool, error) { return false, nil } + +// KubeletClient is the asset for the kubelet kubeconfig. +type KubeletClient struct { + kubeconfig +} + +var _ asset.WritableAsset = (*KubeletClient)(nil) + +// Dependencies returns the dependency of the kubeconfig. +func (k *KubeletClient) Dependencies() []asset.Asset { + return []asset.Asset{ + &tls.KubeletClientCABundle{}, + &tls.KubeletClientCertKey{}, + &installconfig.InstallConfig{}, + } +} + +// Generate generates the kubeconfig. +func (k *KubeletClient) Generate(parents asset.Parents) error { + ca := &tls.KubeletClientCABundle{} + clientcertkey := &tls.KubeletClientCertKey{} + installConfig := &installconfig.InstallConfig{} + parents.Get(ca, clientcertkey, installConfig) + + return k.kubeconfig.generate( + ca, + clientcertkey, + installConfig.Config, + "kubelet", + kubeconfigKubeletClientPath, + ) +} + +// Name returns the human-friendly name of the asset. +func (k *KubeletClient) Name() string { + return "Kubeconfig Kubelet Client" +} + +// Load is a no-op because kubelet kubeconfig is not written to disk. +func (k *KubeletClient) Load(asset.FileFetcher) (bool, error) { + return false, nil +} diff --git a/pkg/asset/manifests/operators.go b/pkg/asset/manifests/operators.go index 4b14a420f4a..d0ddcbade29 100644 --- a/pkg/asset/manifests/operators.go +++ b/pkg/asset/manifests/operators.go @@ -60,11 +60,8 @@ func (m *Manifests) Dependencies() []asset.Asset { &Networking{}, &tls.RootCA{}, &tls.EtcdCA{}, - &tls.IngressCertKey{}, - &tls.KubeCA{}, &tls.EtcdClientCertKey{}, &tls.MCSCertKey{}, - &tls.KubeletCertKey{}, &bootkube.KubeCloudConfig{}, &bootkube.MachineConfigServerTLSSecret{}, @@ -126,7 +123,6 @@ func (m *Manifests) generateBootKubeManifests(dependencies asset.Parents) []*ass clusterID := &installconfig.ClusterID{} installConfig := &installconfig.InstallConfig{} etcdCA := &tls.EtcdCA{} - kubeCA := &tls.KubeCA{} mcsCertKey := &tls.MCSCertKey{} etcdClientCertKey := &tls.EtcdClientCertKey{} rootCA := &tls.RootCA{} @@ -135,7 +131,6 @@ func (m *Manifests) generateBootKubeManifests(dependencies asset.Parents) []*ass installConfig, etcdCA, etcdClientCertKey, - kubeCA, mcsCertKey, rootCA, ) @@ -150,8 +145,6 @@ func (m *Manifests) generateBootKubeManifests(dependencies asset.Parents) []*ass EtcdCaCert: string(etcdCA.Cert()), EtcdClientCert: base64.StdEncoding.EncodeToString(etcdClientCertKey.Cert()), EtcdClientKey: base64.StdEncoding.EncodeToString(etcdClientCertKey.Key()), - KubeCaCert: base64.StdEncoding.EncodeToString(kubeCA.Cert()), - KubeCaKey: base64.StdEncoding.EncodeToString(kubeCA.Key()), McsTLSCert: base64.StdEncoding.EncodeToString(mcsCertKey.Cert()), McsTLSKey: base64.StdEncoding.EncodeToString(mcsCertKey.Key()), PullSecretBase64: base64.StdEncoding.EncodeToString([]byte(installConfig.Config.PullSecret)), diff --git a/pkg/asset/manifests/template.go b/pkg/asset/manifests/template.go index 1652ec727c4..c2cf0769dbe 100644 --- a/pkg/asset/manifests/template.go +++ b/pkg/asset/manifests/template.go @@ -21,8 +21,6 @@ type bootkubeTemplateData struct { EtcdCaCert string EtcdClientCert string EtcdClientKey string - KubeCaCert string - KubeCaKey string McsTLSCert string McsTLSKey string PullSecretBase64 string diff --git a/pkg/asset/tls/admincertkey.go b/pkg/asset/tls/admincertkey.go deleted file mode 100644 index 5866a8f19d1..00000000000 --- a/pkg/asset/tls/admincertkey.go +++ /dev/null @@ -1,44 +0,0 @@ -package tls - -import ( - "crypto/x509" - "crypto/x509/pkix" - - "github.com/openshift/installer/pkg/asset" -) - -//AdminCertKey is the asset that generates the admin key/cert pair. -type AdminCertKey struct { - CertKey -} - -var _ asset.WritableAsset = (*AdminCertKey)(nil) - -// Dependencies returns the dependency of the the cert/key pair, which includes -// the parent CA, and install config if it depends on the install config for -// DNS names, etc. -func (a *AdminCertKey) Dependencies() []asset.Asset { - return []asset.Asset{ - &KubeCA{}, - } -} - -// Generate generates the cert/key pair based on its dependencies. -func (a *AdminCertKey) Generate(dependencies asset.Parents) error { - kubeCA := &KubeCA{} - dependencies.Get(kubeCA) - - cfg := &CertCfg{ - Subject: pkix.Name{CommonName: "system:admin", Organization: []string{"system:masters"}}, - KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, - Validity: ValidityTenYears, - } - - return a.CertKey.Generate(cfg, kubeCA, "admin", DoNotAppendParent) -} - -// Name returns the human-friendly name of the asset. -func (a *AdminCertKey) Name() string { - return "Certificate (system:admin)" -} diff --git a/pkg/asset/tls/adminkubeconfig.go b/pkg/asset/tls/adminkubeconfig.go new file mode 100644 index 00000000000..9b0e071ca70 --- /dev/null +++ b/pkg/asset/tls/adminkubeconfig.go @@ -0,0 +1,143 @@ +package tls + +import ( + "crypto/x509" + "crypto/x509/pkix" + + "github.com/openshift/installer/pkg/asset" +) + +//AdminCertKey is the asset that generates the admin key/cert pair. +// [DEPRECATED] +type AdminCertKey struct { + SignedCertKey +} + +var _ asset.WritableAsset = (*AdminCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *AdminCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeCA{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *AdminCertKey) Generate(dependencies asset.Parents) error { + kubeCA := &KubeCA{} + dependencies.Get(kubeCA) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:admin", Organization: []string{"system:masters"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + Validity: ValidityTenYears, + } + + return a.SignedCertKey.Generate(cfg, kubeCA, "admin", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *AdminCertKey) Name() string { + return "Certificate (system:admin)" +} + +// AdminKubeConfigSignerCertKey is a key/cert pair that signs the admin kubeconfig client certs. +type AdminKubeConfigSignerCertKey struct { + SelfSignedCertKey +} + +var _ asset.WritableAsset = (*AdminKubeConfigSignerCertKey)(nil) + +// Dependencies returns the dependency of the root-ca, which is empty. +func (c *AdminKubeConfigSignerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{} +} + +// Generate generates the root-ca key and cert pair. +func (c *AdminKubeConfigSignerCertKey) Generate(parents asset.Parents) error { + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "admin-kubeconfig-signer", OrganizationalUnit: []string{"openshift"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityTenYears, + IsCA: true, + } + + return c.SelfSignedCertKey.Generate(cfg, "admin-kubeconfig-signer") +} + +// Name returns the human-friendly name of the asset. +func (c *AdminKubeConfigSignerCertKey) Name() string { + return "Certificate (admin-kubeconfig-signer)" +} + +// AdminKubeConfigCABundle is the asset the generates the admin-kubeconfig-ca-bundle, +// which contains all the individual client CAs. +type AdminKubeConfigCABundle struct { + CertBundle +} + +var _ asset.Asset = (*AdminKubeConfigCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *AdminKubeConfigCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &AdminKubeConfigSignerCertKey{}, + &KubeAPIServerLBSignerCertKey{}, + &KubeAPIServerLocalhostSignerCertKey{}, + &KubeAPIServerServiceNetworkSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *AdminKubeConfigCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("admin-kubeconfig-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *AdminKubeConfigCABundle) Name() string { + return "Certificate (admin-kubeconfig-ca-bundle)" +} + +//AdminKubeConfigClientCertKey is the asset that generates the key/cert pair for admin client to apiserver. +type AdminKubeConfigClientCertKey struct { + SignedCertKey +} + +var _ asset.WritableAsset = (*AdminKubeConfigClientCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *AdminKubeConfigClientCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &AdminKubeConfigSignerCertKey{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *AdminKubeConfigClientCertKey) Generate(dependencies asset.Parents) error { + ca := &AdminKubeConfigSignerCertKey{} + dependencies.Get(ca) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:admin", Organization: []string{"system:masters"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + Validity: ValidityTenYears, + } + + return a.SignedCertKey.Generate(cfg, ca, "admin-kubeconfig-client", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *AdminKubeConfigClientCertKey) Name() string { + return "Certificate (admin-kubeconfig-client)" +} diff --git a/pkg/asset/tls/aggregator.go b/pkg/asset/tls/aggregator.go new file mode 100644 index 00000000000..02366d9fe93 --- /dev/null +++ b/pkg/asset/tls/aggregator.go @@ -0,0 +1,175 @@ +package tls + +import ( + "crypto/x509" + "crypto/x509/pkix" + + "github.com/openshift/installer/pkg/asset" +) + +// AggregatorCA is the asset that generates the aggregator-ca key/cert pair. +// [DEPRECATED] +type AggregatorCA struct { + SignedCertKey +} + +var _ asset.Asset = (*AggregatorCA)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *AggregatorCA) Dependencies() []asset.Asset { + return []asset.Asset{ + &RootCA{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *AggregatorCA) Generate(dependencies asset.Parents) error { + rootCA := &RootCA{} + dependencies.Get(rootCA) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "aggregator", OrganizationalUnit: []string{"bootkube"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityOneDay, + IsCA: true, + } + + return a.SignedCertKey.Generate(cfg, rootCA, "aggregator-ca", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *AggregatorCA) Name() string { + return "Certificate (aggregator)" +} + +// APIServerProxyCertKey is the asset that generates the API server proxy key/cert pair. +// [DEPRECATED] +type APIServerProxyCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*APIServerProxyCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *APIServerProxyCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &AggregatorCA{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *APIServerProxyCertKey) Generate(dependencies asset.Parents) error { + aggregatorCA := &AggregatorCA{} + dependencies.Get(aggregatorCA) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:kube-apiserver-proxy", Organization: []string{"kube-master"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + Validity: ValidityOneDay, + } + + return a.SignedCertKey.Generate(cfg, aggregatorCA, "apiserver-proxy", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *APIServerProxyCertKey) Name() string { + return "Certificate (system:kube-apiserver-proxy)" +} + +// AggregatorSignerCertKey is a key/cert pair that signs the aggregator client certs. +type AggregatorSignerCertKey struct { + SelfSignedCertKey +} + +var _ asset.WritableAsset = (*AggregatorSignerCertKey)(nil) + +// Dependencies returns the dependency of the root-ca, which is empty. +func (c *AggregatorSignerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{} +} + +// Generate generates the root-ca key and cert pair. +func (c *AggregatorSignerCertKey) Generate(parents asset.Parents) error { + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "aggregator-signer", OrganizationalUnit: []string{"openshift"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityOneDay, + IsCA: true, + } + + return c.SelfSignedCertKey.Generate(cfg, "aggregator-signer") +} + +// Name returns the human-friendly name of the asset. +func (c *AggregatorSignerCertKey) Name() string { + return "Certificate (aggregator-signer)" +} + +// AggregatorCABundle is the asset the generates the aggregator-ca-bundle, +// which contains all the individual client CAs. +type AggregatorCABundle struct { + CertBundle +} + +var _ asset.Asset = (*AggregatorCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *AggregatorCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &AggregatorSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *AggregatorCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("aggregator-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *AggregatorCABundle) Name() string { + return "Certificate (aggregator-ca-bundle)" +} + +// AggregatorClientCertKey is the asset that generates the API server proxy key/cert pair. +type AggregatorClientCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*AggregatorClientCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair +func (a *AggregatorClientCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &AggregatorSignerCertKey{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *AggregatorClientCertKey) Generate(dependencies asset.Parents) error { + ca := &AggregatorSignerCertKey{} + dependencies.Get(ca) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:kube-apiserver-proxy", Organization: []string{"kube-master"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + Validity: ValidityOneDay, + } + + return a.SignedCertKey.Generate(cfg, ca, "apiserver-proxy", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *AggregatorClientCertKey) Name() string { + return "Certificate (system:kube-apiserver-proxy)" +} diff --git a/pkg/asset/tls/aggregatorca.go b/pkg/asset/tls/aggregatorca.go deleted file mode 100644 index 632c4b159c5..00000000000 --- a/pkg/asset/tls/aggregatorca.go +++ /dev/null @@ -1,44 +0,0 @@ -package tls - -import ( - "crypto/x509" - "crypto/x509/pkix" - - "github.com/openshift/installer/pkg/asset" -) - -// AggregatorCA is the asset that generates the aggregator-ca key/cert pair. -type AggregatorCA struct { - CertKey -} - -var _ asset.Asset = (*AggregatorCA)(nil) - -// Dependencies returns the dependency of the the cert/key pair, which includes -// the parent CA, and install config if it depends on the install config for -// DNS names, etc. -func (a *AggregatorCA) Dependencies() []asset.Asset { - return []asset.Asset{ - &RootCA{}, - } -} - -// Generate generates the cert/key pair based on its dependencies. -func (a *AggregatorCA) Generate(dependencies asset.Parents) error { - rootCA := &RootCA{} - dependencies.Get(rootCA) - - cfg := &CertCfg{ - Subject: pkix.Name{CommonName: "aggregator", OrganizationalUnit: []string{"bootkube"}}, - KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - Validity: ValidityTenYears, - IsCA: true, - } - - return a.CertKey.Generate(cfg, rootCA, "aggregator-ca", DoNotAppendParent) -} - -// Name returns the human-friendly name of the asset. -func (a *AggregatorCA) Name() string { - return "Certificate (aggregator)" -} diff --git a/pkg/asset/tls/apiserver.go b/pkg/asset/tls/apiserver.go new file mode 100644 index 00000000000..a5196f05c06 --- /dev/null +++ b/pkg/asset/tls/apiserver.go @@ -0,0 +1,456 @@ +package tls + +import ( + "crypto/x509" + "crypto/x509/pkix" + "net" + + "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/installconfig" + "github.com/pkg/errors" +) + +// APIServerCertKey is the asset that generates the API server key/cert pair. +// [DEPRECATED] +type APIServerCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*APIServerCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *APIServerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeCA{}, + &installconfig.InstallConfig{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *APIServerCertKey) Generate(dependencies asset.Parents) error { + kubeCA := &KubeCA{} + installConfig := &installconfig.InstallConfig{} + dependencies.Get(kubeCA, installConfig) + + apiServerAddress, err := cidrhost(installConfig.Config.Networking.ServiceCIDR.IPNet, 1) + if err != nil { + return errors.Wrap(err, "failed to get API Server address from InstallConfig") + } + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:kube-apiserver", Organization: []string{"kube-master"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + Validity: ValidityTenYears, + DNSNames: []string{ + apiAddress(installConfig.Config), + "kubernetes", "kubernetes.default", + "kubernetes.default.svc", + "kubernetes.default.svc.cluster.local", + "localhost", + }, + IPAddresses: []net.IP{net.ParseIP(apiServerAddress), net.ParseIP("127.0.0.1")}, + } + + return a.SignedCertKey.Generate(cfg, kubeCA, "apiserver", AppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *APIServerCertKey) Name() string { + return "Certificate (kube-apiaserver)" +} + +// KubeAPIServerToKubeletSignerCertKey is a key/cert pair that signs the kube-apiserver to kubelet client certs. +type KubeAPIServerToKubeletSignerCertKey struct { + SelfSignedCertKey +} + +var _ asset.WritableAsset = (*KubeAPIServerToKubeletSignerCertKey)(nil) + +// Dependencies returns the dependency of the root-ca, which is empty. +func (c *KubeAPIServerToKubeletSignerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{} +} + +// Generate generates the root-ca key and cert pair. +func (c *KubeAPIServerToKubeletSignerCertKey) Generate(parents asset.Parents) error { + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "kube-apiserver-to-kubelet-signer", OrganizationalUnit: []string{"openshift"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityOneYear, + IsCA: true, + } + + return c.SelfSignedCertKey.Generate(cfg, "kube-apiserver-to-kubelet-signer") +} + +// Name returns the human-friendly name of the asset. +func (c *KubeAPIServerToKubeletSignerCertKey) Name() string { + return "Certificate (kube-apiserver-to-kubelet-signer)" +} + +// KubeAPIServerToKubeletCABundle is the asset the generates the kube-apiserver-to-kubelet-ca-bundle, +// which contains all the individual client CAs. +type KubeAPIServerToKubeletCABundle struct { + CertBundle +} + +var _ asset.Asset = (*KubeAPIServerToKubeletCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *KubeAPIServerToKubeletCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeAPIServerToKubeletSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *KubeAPIServerToKubeletCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("kube-apiserver-to-kubelet-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeAPIServerToKubeletCABundle) Name() string { + return "Certificate (kube-apiserver-to-kubelet-ca-bundle)" +} + +// KubeAPIServerToKubeletClientCertKey is the asset that generates the kube-apiserver to kubelet client key/cert pair. +type KubeAPIServerToKubeletClientCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*KubeAPIServerToKubeletClientCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair +func (a *KubeAPIServerToKubeletClientCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeAPIServerToKubeletSignerCertKey{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *KubeAPIServerToKubeletClientCertKey) Generate(dependencies asset.Parents) error { + ca := &KubeAPIServerToKubeletSignerCertKey{} + dependencies.Get(ca) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:kube-apiserver", Organization: []string{"kube-master"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + Validity: ValidityOneYear, + } + + return a.SignedCertKey.Generate(cfg, ca, "kube-apiserver-to-kubelet-client", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeAPIServerToKubeletClientCertKey) Name() string { + return "Certificate (kube-apiserver-to-kubelet-client)" +} + +// KubeAPIServerLocalhostSignerCertKey is a key/cert pair that signs the kube-apiserver server cert for SNI localhost. +type KubeAPIServerLocalhostSignerCertKey struct { + SelfSignedCertKey +} + +var _ asset.WritableAsset = (*KubeAPIServerLocalhostSignerCertKey)(nil) + +// Dependencies returns the dependency of the root-ca, which is empty. +func (c *KubeAPIServerLocalhostSignerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{} +} + +// Generate generates the root-ca key and cert pair. +func (c *KubeAPIServerLocalhostSignerCertKey) Generate(parents asset.Parents) error { + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "kube-apiserver-localhost-signer", OrganizationalUnit: []string{"openshift"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityTenYears, + IsCA: true, + } + + return c.SelfSignedCertKey.Generate(cfg, "kube-apiserver-localhost-signer") +} + +// Name returns the human-friendly name of the asset. +func (c *KubeAPIServerLocalhostSignerCertKey) Name() string { + return "Certificate (kube-apiserver-localhost-signer)" +} + +// KubeAPIServerLocalhostCABundle is the asset the generates the kube-apiserver-localhost-ca-bundle, +// which contains all the individual client CAs. +type KubeAPIServerLocalhostCABundle struct { + CertBundle +} + +var _ asset.Asset = (*KubeAPIServerLocalhostCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *KubeAPIServerLocalhostCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeAPIServerLocalhostSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *KubeAPIServerLocalhostCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("kube-apiserver-localhost-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeAPIServerLocalhostCABundle) Name() string { + return "Certificate (kube-apiserver-localhost-ca-bundle)" +} + +// KubeAPIServerLocalhostServerCertKey is the asset that generates the kube-apiserver serving key/cert pair for SNI localhost. +type KubeAPIServerLocalhostServerCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*KubeAPIServerLocalhostServerCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair +func (a *KubeAPIServerLocalhostServerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeAPIServerLocalhostSignerCertKey{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *KubeAPIServerLocalhostServerCertKey) Generate(dependencies asset.Parents) error { + ca := &KubeAPIServerLocalhostSignerCertKey{} + dependencies.Get(ca) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:kube-apiserver", Organization: []string{"kube-master"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + Validity: ValidityOneDay, + DNSNames: []string{ + "localhost", + }, + IPAddresses: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}, + } + + return a.SignedCertKey.Generate(cfg, ca, "kube-apiserver-localhost-server", AppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeAPIServerLocalhostServerCertKey) Name() string { + return "Certificate (kube-apiserver-localhost-server)" +} + +// KubeAPIServerServiceNetworkSignerCertKey is a key/cert pair that signs the kube-apiserver server cert for SNI service network. +type KubeAPIServerServiceNetworkSignerCertKey struct { + SelfSignedCertKey +} + +var _ asset.WritableAsset = (*KubeAPIServerServiceNetworkSignerCertKey)(nil) + +// Dependencies returns the dependency of the root-ca, which is empty. +func (c *KubeAPIServerServiceNetworkSignerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{} +} + +// Generate generates the root-ca key and cert pair. +func (c *KubeAPIServerServiceNetworkSignerCertKey) Generate(parents asset.Parents) error { + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "kube-apiserver-service-network-signer", OrganizationalUnit: []string{"openshift"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityTenYears, + IsCA: true, + } + + return c.SelfSignedCertKey.Generate(cfg, "kube-apiserver-service-network-signer") +} + +// Name returns the human-friendly name of the asset. +func (c *KubeAPIServerServiceNetworkSignerCertKey) Name() string { + return "Certificate (kube-apiserver-service-network-signer)" +} + +// KubeAPIServerServiceNetworkCABundle is the asset the generates the kube-apiserver-service-network-ca-bundle, +// which contains all the individual client CAs. +type KubeAPIServerServiceNetworkCABundle struct { + CertBundle +} + +var _ asset.Asset = (*KubeAPIServerServiceNetworkCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *KubeAPIServerServiceNetworkCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeAPIServerServiceNetworkSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *KubeAPIServerServiceNetworkCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("kube-apiserver-service-network-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeAPIServerServiceNetworkCABundle) Name() string { + return "Certificate (kube-apiserver-service-network-ca-bundle)" +} + +// KubeAPIServerServiceNetworkServerCertKey is the asset that generates the kube-apiserver serving key/cert pair for SNI service network. +type KubeAPIServerServiceNetworkServerCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*KubeAPIServerServiceNetworkServerCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair +func (a *KubeAPIServerServiceNetworkServerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeAPIServerServiceNetworkSignerCertKey{}, + &installconfig.InstallConfig{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *KubeAPIServerServiceNetworkServerCertKey) Generate(dependencies asset.Parents) error { + ca := &KubeAPIServerServiceNetworkSignerCertKey{} + installConfig := &installconfig.InstallConfig{} + dependencies.Get(ca, installConfig) + serviceAddress, err := cidrhost(installConfig.Config.Networking.ServiceCIDR.IPNet, 1) + if err != nil { + return errors.Wrap(err, "failed to get service address for kube-apiserver from InstallConfig") + } + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:kube-apiserver", Organization: []string{"kube-master"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + Validity: ValidityOneDay, + DNSNames: []string{ + "kubernetes", "kubernetes.default", + "kubernetes.default.svc", + "kubernetes.default.svc.cluster.local", + }, + IPAddresses: []net.IP{net.ParseIP(serviceAddress)}, + } + + return a.SignedCertKey.Generate(cfg, ca, "kube-apiserver-service-network-server", AppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeAPIServerServiceNetworkServerCertKey) Name() string { + return "Certificate (kube-apiserver-service-network-server)" +} + +// KubeAPIServerLBSignerCertKey is a key/cert pair that signs the kube-apiserver server cert for SNI load balancer. +type KubeAPIServerLBSignerCertKey struct { + SelfSignedCertKey +} + +var _ asset.WritableAsset = (*KubeAPIServerLBSignerCertKey)(nil) + +// Dependencies returns the dependency of the root-ca, which is empty. +func (c *KubeAPIServerLBSignerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{} +} + +// Generate generates the root-ca key and cert pair. +func (c *KubeAPIServerLBSignerCertKey) Generate(parents asset.Parents) error { + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "kube-apiserver-lb-signer", OrganizationalUnit: []string{"openshift"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityTenYears, + IsCA: true, + } + + return c.SelfSignedCertKey.Generate(cfg, "kube-apiserver-lb-signer") +} + +// Name returns the human-friendly name of the asset. +func (c *KubeAPIServerLBSignerCertKey) Name() string { + return "Certificate (kube-apiserver-lb-signer)" +} + +// KubeAPIServerLBCABundle is the asset the generates the kube-apiserver-lb-ca-bundle, +// which contains all the individual client CAs. +type KubeAPIServerLBCABundle struct { + CertBundle +} + +var _ asset.Asset = (*KubeAPIServerLBCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *KubeAPIServerLBCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeAPIServerLBSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *KubeAPIServerLBCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("kube-apiserver-lb-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeAPIServerLBCABundle) Name() string { + return "Certificate (kube-apiserver-lb-ca-bundle)" +} + +// KubeAPIServerLBServerCertKey is the asset that generates the kube-apiserver serving key/cert pair for SNI load balancer. +type KubeAPIServerLBServerCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*KubeAPIServerLBServerCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair +func (a *KubeAPIServerLBServerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeAPIServerLBSignerCertKey{}, + &installconfig.InstallConfig{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *KubeAPIServerLBServerCertKey) Generate(dependencies asset.Parents) error { + ca := &KubeAPIServerLBSignerCertKey{} + installConfig := &installconfig.InstallConfig{} + dependencies.Get(ca, installConfig) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:kube-apiserver", Organization: []string{"kube-master"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + Validity: ValidityOneDay, + DNSNames: []string{ + apiAddress(installConfig.Config), + }, + } + + return a.SignedCertKey.Generate(cfg, ca, "kube-apiserver-lb-server", AppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeAPIServerLBServerCertKey) Name() string { + return "Certificate (kube-apiserver-lb-server)" +} diff --git a/pkg/asset/tls/apiservercertkey.go b/pkg/asset/tls/apiservercertkey.go deleted file mode 100644 index 34870066d43..00000000000 --- a/pkg/asset/tls/apiservercertkey.go +++ /dev/null @@ -1,63 +0,0 @@ -package tls - -import ( - "crypto/x509" - "crypto/x509/pkix" - "net" - - "github.com/pkg/errors" - - "github.com/openshift/installer/pkg/asset" - "github.com/openshift/installer/pkg/asset/installconfig" -) - -// APIServerCertKey is the asset that generates the API server key/cert pair. -type APIServerCertKey struct { - CertKey -} - -var _ asset.Asset = (*APIServerCertKey)(nil) - -// Dependencies returns the dependency of the the cert/key pair, which includes -// the parent CA, and install config if it depends on the install config for -// DNS names, etc. -func (a *APIServerCertKey) Dependencies() []asset.Asset { - return []asset.Asset{ - &KubeCA{}, - &installconfig.InstallConfig{}, - } -} - -// Generate generates the cert/key pair based on its dependencies. -func (a *APIServerCertKey) Generate(dependencies asset.Parents) error { - kubeCA := &KubeCA{} - installConfig := &installconfig.InstallConfig{} - dependencies.Get(kubeCA, installConfig) - - apiServerAddress, err := cidrhost(installConfig.Config.Networking.ServiceCIDR.IPNet, 1) - if err != nil { - return errors.Wrap(err, "failed to get API Server address from InstallConfig") - } - - cfg := &CertCfg{ - Subject: pkix.Name{CommonName: "system:kube-apiserver", Organization: []string{"kube-master"}}, - KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, - Validity: ValidityTenYears, - DNSNames: []string{ - apiAddress(installConfig.Config), - "kubernetes", "kubernetes.default", - "kubernetes.default.svc", - "kubernetes.default.svc.cluster.local", - "localhost", - }, - IPAddresses: []net.IP{net.ParseIP(apiServerAddress), net.ParseIP("127.0.0.1")}, - } - - return a.CertKey.Generate(cfg, kubeCA, "apiserver", DoNotAppendParent) -} - -// Name returns the human-friendly name of the asset. -func (a *APIServerCertKey) Name() string { - return "Certificate (kube-apiaserver)" -} diff --git a/pkg/asset/tls/apiserverproxycertkey.go b/pkg/asset/tls/apiserverproxycertkey.go deleted file mode 100644 index 76f6fe5dc44..00000000000 --- a/pkg/asset/tls/apiserverproxycertkey.go +++ /dev/null @@ -1,44 +0,0 @@ -package tls - -import ( - "crypto/x509" - "crypto/x509/pkix" - - "github.com/openshift/installer/pkg/asset" -) - -// APIServerProxyCertKey is the asset that generates the API server proxy key/cert pair. -type APIServerProxyCertKey struct { - CertKey -} - -var _ asset.Asset = (*APIServerProxyCertKey)(nil) - -// Dependencies returns the dependency of the the cert/key pair, which includes -// the parent CA, and install config if it depends on the install config for -// DNS names, etc. -func (a *APIServerProxyCertKey) Dependencies() []asset.Asset { - return []asset.Asset{ - &AggregatorCA{}, - } -} - -// Generate generates the cert/key pair based on its dependencies. -func (a *APIServerProxyCertKey) Generate(dependencies asset.Parents) error { - aggregatorCA := &AggregatorCA{} - dependencies.Get(aggregatorCA) - - cfg := &CertCfg{ - Subject: pkix.Name{CommonName: "system:kube-apiserver-proxy", Organization: []string{"kube-master"}}, - KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - Validity: ValidityTenYears, - } - - return a.CertKey.Generate(cfg, aggregatorCA, "apiserver-proxy", DoNotAppendParent) -} - -// Name returns the human-friendly name of the asset. -func (a *APIServerProxyCertKey) Name() string { - return "Certificate (system:kube-apiserver-proxy)" -} diff --git a/pkg/asset/tls/cabundle.go b/pkg/asset/tls/cabundle.go new file mode 100644 index 00000000000..5667f776e78 --- /dev/null +++ b/pkg/asset/tls/cabundle.go @@ -0,0 +1,56 @@ +package tls + +import ( + "bytes" + "encoding/pem" + + "github.com/openshift/installer/pkg/asset" + "github.com/pkg/errors" +) + +// CertBundle contains a multiple certificates in a bundle. +type CertBundle struct { + BundleRaw []byte + FileList []*asset.File +} + +// Cert returns the certificate bundle. +func (b *CertBundle) Cert() []byte { + return b.BundleRaw +} + +// Generate generates the cert bundle from certs. +func (b *CertBundle) Generate(filename string, certs ...CertInterface) error { + if len(certs) < 1 { + return errors.New("atleast one certificate required for a bundle") + } + + buf := bytes.Buffer{} + for _, c := range certs { + cert, err := PemToCertificate(c.Cert()) + if err != nil { + return errors.Wrap(err, "decoding certificate from PEM") + } + if err := pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}); err != nil { + return errors.Wrap(err, "encoding certificate to PEM") + } + } + b.BundleRaw = buf.Bytes() + b.FileList = []*asset.File{ + { + Filename: assetFilePath(filename + ".crt"), + Data: b.BundleRaw, + }, + } + return nil +} + +// Files returns the files generated by the asset. +func (b *CertBundle) Files() []*asset.File { + return b.FileList +} + +// Load is a no-op because TLS assets are not written to disk. +func (b *CertBundle) Load(asset.FileFetcher) (bool, error) { + return false, nil +} diff --git a/pkg/asset/tls/cabundle_test.go b/pkg/asset/tls/cabundle_test.go new file mode 100644 index 00000000000..03048c8d0da --- /dev/null +++ b/pkg/asset/tls/cabundle_test.go @@ -0,0 +1,142 @@ +package tls + +import ( + "fmt" + "testing" + + "github.com/openshift/installer/pkg/asset" + + "github.com/stretchr/testify/assert" +) + +type mockCertKey struct { + cert string + key string +} + +func (mck *mockCertKey) Cert() []byte { return []byte(mck.cert) } +func (mck *mockCertKey) Key() []byte { return []byte(mck.key) } + +func Test_CertBundleGenerate(t *testing.T) { + + tests := []struct { + input []string + + expBundle string + expErr string + }{{ + expErr: "atleast one certificate required for a bundle", + }, { + input: []string{`-----BEGIN CERTIFICATE----- +MIICYTCCAcqgAwIBAgIJAI2kA+uXAbhOMA0GCSqGSIb3DQEBCwUAMEgxCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEUMBIG +A1UECgwLUmVkIEhhdCBJbmMwHhcNMTkwMjEyMTkzMjUzWhcNMTkwMjEzMTkzMjUz +WjBIMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFu +Y2lzY28xFDASBgNVBAoMC1JlZCBIYXQgSW5jMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC+HOC0mKig/oINAKPo88LqxDJ4l7lozdLtp5oGeqWrLUXSfkvXAkQY +2QYdvPAjpRfH7Ii7G0Asx+HTKdvula7B5fXDjc6NYKuEpTJZRV1ugntI97bozF/E +C2BBmxxEnJN3+Xe8RYXMjz5Q4aqPw9vZhlWN+0hrREl1Ea/zHuWFIQIDAQABo1Mw +UTAdBgNVHQ4EFgQUvTS1XjlvOdsufSyWxukyQu3LriEwHwYDVR0jBBgwFoAUvTS1 +XjlvOdsufSyWxukyQu3LriEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF +AAOBgQB9gFcOXnzJrM65QqxeCB9Z5l5JMjp45UFC9Bj2cgwDHP80Zvi4omlaacC6 +aavmnLd67zm9PbYDWRaOIWAMeB916Iwaw/v6I0jwhAk/VxX5Fl6cGlZu9jZ3zbFE +2sDqkwzIuSjCG2A23s6d4M1S3IXCCydoCSLMu+WhLkbboK6jEg== +-----END CERTIFICATE-----`}, + + expBundle: `-----BEGIN CERTIFICATE----- +MIICYTCCAcqgAwIBAgIJAI2kA+uXAbhOMA0GCSqGSIb3DQEBCwUAMEgxCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEUMBIG +A1UECgwLUmVkIEhhdCBJbmMwHhcNMTkwMjEyMTkzMjUzWhcNMTkwMjEzMTkzMjUz +WjBIMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFu +Y2lzY28xFDASBgNVBAoMC1JlZCBIYXQgSW5jMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC+HOC0mKig/oINAKPo88LqxDJ4l7lozdLtp5oGeqWrLUXSfkvXAkQY +2QYdvPAjpRfH7Ii7G0Asx+HTKdvula7B5fXDjc6NYKuEpTJZRV1ugntI97bozF/E +C2BBmxxEnJN3+Xe8RYXMjz5Q4aqPw9vZhlWN+0hrREl1Ea/zHuWFIQIDAQABo1Mw +UTAdBgNVHQ4EFgQUvTS1XjlvOdsufSyWxukyQu3LriEwHwYDVR0jBBgwFoAUvTS1 +XjlvOdsufSyWxukyQu3LriEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF +AAOBgQB9gFcOXnzJrM65QqxeCB9Z5l5JMjp45UFC9Bj2cgwDHP80Zvi4omlaacC6 +aavmnLd67zm9PbYDWRaOIWAMeB916Iwaw/v6I0jwhAk/VxX5Fl6cGlZu9jZ3zbFE +2sDqkwzIuSjCG2A23s6d4M1S3IXCCydoCSLMu+WhLkbboK6jEg== +-----END CERTIFICATE----- +`, + }, { + input: []string{`-----BEGIN CERTIFICATE----- +MIICYTCCAcqgAwIBAgIJAI2kA+uXAbhOMA0GCSqGSIb3DQEBCwUAMEgxCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEUMBIG +A1UECgwLUmVkIEhhdCBJbmMwHhcNMTkwMjEyMTkzMjUzWhcNMTkwMjEzMTkzMjUz +WjBIMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFu +Y2lzY28xFDASBgNVBAoMC1JlZCBIYXQgSW5jMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC+HOC0mKig/oINAKPo88LqxDJ4l7lozdLtp5oGeqWrLUXSfkvXAkQY +2QYdvPAjpRfH7Ii7G0Asx+HTKdvula7B5fXDjc6NYKuEpTJZRV1ugntI97bozF/E +C2BBmxxEnJN3+Xe8RYXMjz5Q4aqPw9vZhlWN+0hrREl1Ea/zHuWFIQIDAQABo1Mw +UTAdBgNVHQ4EFgQUvTS1XjlvOdsufSyWxukyQu3LriEwHwYDVR0jBBgwFoAUvTS1 +XjlvOdsufSyWxukyQu3LriEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF +AAOBgQB9gFcOXnzJrM65QqxeCB9Z5l5JMjp45UFC9Bj2cgwDHP80Zvi4omlaacC6 +aavmnLd67zm9PbYDWRaOIWAMeB916Iwaw/v6I0jwhAk/VxX5Fl6cGlZu9jZ3zbFE +2sDqkwzIuSjCG2A23s6d4M1S3IXCCydoCSLMu+WhLkbboK6jEg== +-----END CERTIFICATE-----`, `-----BEGIN CERTIFICATE----- +MIICVTCCAb6gAwIBAgIJAKDi1rywgIWHMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV +BAYTAlVTMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQg +Q29tcGFueSBMdGQwHhcNMTkwMjEyMTkzNTA5WhcNMTkwMjEzMTkzNTA5WjBCMQsw +CQYDVQQGEwJVUzEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZh +dWx0IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0IwdO +//CIUspBaLVDVPlcvbE4koN5v4dx/G0ClcfDDDcUFhw3yu/MiAt/EwDDzucHoM+l +mVrNZV3A4+QjswHxwl7jKAeZ/bpTsDh7j/r5zpoY8hD5za9+BZ5Pr0k5q3ONS6Iy +Uu8VHCPjIzMETcEJ+LCB0iD4xMAvb7daNmimVQIDAQABo1MwUTAdBgNVHQ4EFgQU +pKgTmnFxt741aiUOMy2bbcEP2AgwHwYDVR0jBBgwFoAUpKgTmnFxt741aiUOMy2b +bcEP2AgwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQBW/U1DAbEX +0zk4FNxl4d/82ax44MVaZ5Owrhgr6kWBXDR2kRyYlq1yfLVHLjMqIkCe5VcBBfwy +s5Q0Xv1T6UKcWvIHwNNxo/dYDtnmjdllrEeVKKW0kmotCCsGLU/ZBa++Rl/GYpwv +CjH8bTNT3u6KYZKRVH0A2/EpJHC+TSSe3A== +-----END CERTIFICATE-----`}, + expBundle: `-----BEGIN CERTIFICATE----- +MIICYTCCAcqgAwIBAgIJAI2kA+uXAbhOMA0GCSqGSIb3DQEBCwUAMEgxCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEUMBIG +A1UECgwLUmVkIEhhdCBJbmMwHhcNMTkwMjEyMTkzMjUzWhcNMTkwMjEzMTkzMjUz +WjBIMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFu +Y2lzY28xFDASBgNVBAoMC1JlZCBIYXQgSW5jMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC+HOC0mKig/oINAKPo88LqxDJ4l7lozdLtp5oGeqWrLUXSfkvXAkQY +2QYdvPAjpRfH7Ii7G0Asx+HTKdvula7B5fXDjc6NYKuEpTJZRV1ugntI97bozF/E +C2BBmxxEnJN3+Xe8RYXMjz5Q4aqPw9vZhlWN+0hrREl1Ea/zHuWFIQIDAQABo1Mw +UTAdBgNVHQ4EFgQUvTS1XjlvOdsufSyWxukyQu3LriEwHwYDVR0jBBgwFoAUvTS1 +XjlvOdsufSyWxukyQu3LriEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsF +AAOBgQB9gFcOXnzJrM65QqxeCB9Z5l5JMjp45UFC9Bj2cgwDHP80Zvi4omlaacC6 +aavmnLd67zm9PbYDWRaOIWAMeB916Iwaw/v6I0jwhAk/VxX5Fl6cGlZu9jZ3zbFE +2sDqkwzIuSjCG2A23s6d4M1S3IXCCydoCSLMu+WhLkbboK6jEg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICVTCCAb6gAwIBAgIJAKDi1rywgIWHMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV +BAYTAlVTMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQg +Q29tcGFueSBMdGQwHhcNMTkwMjEyMTkzNTA5WhcNMTkwMjEzMTkzNTA5WjBCMQsw +CQYDVQQGEwJVUzEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZh +dWx0IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0IwdO +//CIUspBaLVDVPlcvbE4koN5v4dx/G0ClcfDDDcUFhw3yu/MiAt/EwDDzucHoM+l +mVrNZV3A4+QjswHxwl7jKAeZ/bpTsDh7j/r5zpoY8hD5za9+BZ5Pr0k5q3ONS6Iy +Uu8VHCPjIzMETcEJ+LCB0iD4xMAvb7daNmimVQIDAQABo1MwUTAdBgNVHQ4EFgQU +pKgTmnFxt741aiUOMy2bbcEP2AgwHwYDVR0jBBgwFoAUpKgTmnFxt741aiUOMy2b +bcEP2AgwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQBW/U1DAbEX +0zk4FNxl4d/82ax44MVaZ5Owrhgr6kWBXDR2kRyYlq1yfLVHLjMqIkCe5VcBBfwy +s5Q0Xv1T6UKcWvIHwNNxo/dYDtnmjdllrEeVKKW0kmotCCsGLU/ZBa++Rl/GYpwv +CjH8bTNT3u6KYZKRVH0A2/EpJHC+TSSe3A== +-----END CERTIFICATE----- +`, + }} + for idx, test := range tests { + t.Run(fmt.Sprintf("#%d", idx), func(t *testing.T) { + var certkeys []CertInterface + for _, c := range test.input { + certkeys = append(certkeys, &mockCertKey{cert: c}) + } + + bundle := CertBundle{} + err := bundle.Generate("test-bundle", certkeys...) + if test.expErr == "" { + assert.NoError(t, err) + assert.Equal(t, string(bundle.BundleRaw), test.expBundle) + assert.Equal(t, bundle.FileList, []*asset.File{{Filename: "tls/test-bundle.crt", Data: []byte(test.expBundle)}}) + } else { + assert.EqualError(t, err, test.expErr) + } + }) + } +} diff --git a/pkg/asset/tls/certkey.go b/pkg/asset/tls/certkey.go index 508d1ed3760..f93a7c973f4 100644 --- a/pkg/asset/tls/certkey.go +++ b/pkg/asset/tls/certkey.go @@ -10,27 +10,20 @@ import ( "github.com/openshift/installer/pkg/asset" ) -// AppendParentChoice dictates whether the parent's cert is to be added to the -// cert. -type AppendParentChoice bool - -const ( - // AppendParent indicates that the parent's cert should be added. - AppendParent AppendParentChoice = true - // DoNotAppendParent indicates that the parent's cert should not be added. - DoNotAppendParent AppendParentChoice = false -) +// CertInterface contains cert. +type CertInterface interface { + // Cert returns the certificate. + Cert() []byte +} // CertKeyInterface contains a private key and the associated cert. type CertKeyInterface interface { - // Cert returns the certificate. - Cert() []byte + CertInterface // Key returns the private key. Key() []byte } -// CertKey contains the private key and the cert that's -// signed by the parent CA. +// CertKey contains the private key and the cert. type CertKey struct { CertRaw []byte KeyRaw []byte @@ -47,8 +40,53 @@ func (c *CertKey) Key() []byte { return c.KeyRaw } +// Files returns the files generated by the asset. +func (c *CertKey) Files() []*asset.File { + return c.FileList +} + +// CertFile returns the certificate file. +func (c *CertKey) CertFile() *asset.File { + return c.FileList[1] +} + +func (c *CertKey) generateFiles(filenameBase string) { + c.FileList = []*asset.File{ + { + Filename: assetFilePath(filenameBase + ".key"), + Data: c.KeyRaw, + }, + { + Filename: assetFilePath(filenameBase + ".crt"), + Data: c.CertRaw, + }, + } +} + +// Load is a no-op because TLS assets are not written to disk. +func (c *CertKey) Load(asset.FileFetcher) (bool, error) { + return false, nil +} + +// AppendParentChoice dictates whether the parent's cert is to be added to the +// cert. +type AppendParentChoice bool + +const ( + // AppendParent indicates that the parent's cert should be added. + AppendParent AppendParentChoice = true + // DoNotAppendParent indicates that the parent's cert should not be added. + DoNotAppendParent AppendParentChoice = false +) + +// SignedCertKey contains the private key and the cert that's +// signed by the parent CA. +type SignedCertKey struct { + CertKey +} + // Generate generates a cert/key pair signed by the specified parent CA. -func (c *CertKey) Generate( +func (c *SignedCertKey) Generate( cfg *CertCfg, parentCA CertKeyInterface, filenameBase string, @@ -68,9 +106,9 @@ func (c *CertKey) Generate( return errors.Wrap(err, "failed to parse x509 certificate") } - key, crt, err = GenerateCert(caKey, caCert, cfg) + key, crt, err = GenerateSignedCertificate(caKey, caCert, cfg) if err != nil { - return errors.Wrap(err, "failed to generate cert/key pair") + return errors.Wrap(err, "failed to generate signed cert/key pair") } c.KeyRaw = PrivateKeyToPem(key) @@ -85,30 +123,25 @@ func (c *CertKey) Generate( return nil } -// Files returns the files generated by the asset. -func (c *CertKey) Files() []*asset.File { - return c.FileList +// SelfSignedCertKey contains the private key and the cert that's self-signed. +type SelfSignedCertKey struct { + CertKey } -// CertFile returns the certificate file. -func (c *CertKey) CertFile() *asset.File { - return c.FileList[1] -} - -func (c *CertKey) generateFiles(filenameBase string) { - c.FileList = []*asset.File{ - { - Filename: assetFilePath(filenameBase + ".key"), - Data: c.KeyRaw, - }, - { - Filename: assetFilePath(filenameBase + ".crt"), - Data: c.CertRaw, - }, +// Generate generates a cert/key pair signed by the specified parent CA. +func (c *SelfSignedCertKey) Generate( + cfg *CertCfg, + filenameBase string, +) error { + key, crt, err := GenerateSelfSignedCertificate(cfg) + if err != nil { + return errors.Wrap(err, "failed to generate self-signed cert/key pair") } -} -// Load is a no-op because TLS assets are not written to disk. -func (c *CertKey) Load(asset.FileFetcher) (bool, error) { - return false, nil + c.KeyRaw = PrivateKeyToPem(key) + c.CertRaw = CertToPem(crt) + + c.generateFiles(filenameBase) + + return nil } diff --git a/pkg/asset/tls/certkey_test.go b/pkg/asset/tls/certkey_test.go index ecfb4167dd1..5634f7211be 100644 --- a/pkg/asset/tls/certkey_test.go +++ b/pkg/asset/tls/certkey_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestCertKeyGenerate(t *testing.T) { +func TestSignedCertKeyGenerate(t *testing.T) { tests := []struct { name string certCfg *CertCfg @@ -48,7 +48,7 @@ func TestCertKeyGenerate(t *testing.T) { err := rootCA.Generate(nil) assert.NoError(t, err, "failed to generate root CA") - certKey := &CertKey{} + certKey := &SignedCertKey{} err = certKey.Generate(tt.certCfg, rootCA, tt.filenameBase, tt.appendParent) if err != nil { assert.EqualErrorf(t, err, tt.errString, tt.name) diff --git a/pkg/asset/tls/etcd.go b/pkg/asset/tls/etcd.go new file mode 100644 index 00000000000..9870362aca7 --- /dev/null +++ b/pkg/asset/tls/etcd.go @@ -0,0 +1,177 @@ +package tls + +import ( + "crypto/x509" + "crypto/x509/pkix" + + "github.com/openshift/installer/pkg/asset" +) + +// EtcdCA is the asset that generates the etcd-ca key/cert pair. +// [DEPRECATED] +type EtcdCA struct { + SignedCertKey +} + +var _ asset.Asset = (*EtcdCA)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *EtcdCA) Dependencies() []asset.Asset { + return []asset.Asset{ + &RootCA{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *EtcdCA) Generate(dependencies asset.Parents) error { + rootCA := &RootCA{} + dependencies.Get(rootCA) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "etcd", OrganizationalUnit: []string{"etcd"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityTenYears, + IsCA: true, + } + + return a.SignedCertKey.Generate(cfg, rootCA, "etcd-client-ca", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *EtcdCA) Name() string { + return "Certificate (etcd)" +} + +// EtcdClientCertKey is the asset that generates the etcd client key/cert pair. +// [DEPRECATED] +type EtcdClientCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*EtcdClientCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *EtcdClientCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &EtcdCA{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *EtcdClientCertKey) Generate(dependencies asset.Parents) error { + etcdCA := &EtcdCA{} + dependencies.Get(etcdCA) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "etcd", OrganizationalUnit: []string{"etcd"}}, + KeyUsages: x509.KeyUsageKeyEncipherment, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + Validity: ValidityTenYears, + } + + return a.SignedCertKey.Generate(cfg, etcdCA, "etcd-client", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *EtcdClientCertKey) Name() string { + return "Certificate (etcd)" +} + +// EtcdSignerCertKey is a key/cert pair that signs the etcd client and peer certs. +type EtcdSignerCertKey struct { + SelfSignedCertKey +} + +var _ asset.WritableAsset = (*EtcdSignerCertKey)(nil) + +// Dependencies returns the dependency of the root-ca, which is empty. +func (c *EtcdSignerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{} +} + +// Generate generates the root-ca key and cert pair. +func (c *EtcdSignerCertKey) Generate(parents asset.Parents) error { + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "etcd-signer", OrganizationalUnit: []string{"openshift"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityTenYears, + IsCA: true, + } + + return c.SelfSignedCertKey.Generate(cfg, "etcd-signer") +} + +// Name returns the human-friendly name of the asset. +func (c *EtcdSignerCertKey) Name() string { + return "Certificate (etcd-signer)" +} + +// EtcdCABundle is the asset the generates the etcd-ca-bundle, +// which contains all the individual client CAs. +type EtcdCABundle struct { + CertBundle +} + +var _ asset.Asset = (*EtcdCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *EtcdCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &EtcdSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *EtcdCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("etcd-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *EtcdCABundle) Name() string { + return "Certificate (etcd-ca-bundle)" +} + +// EtcdSignerClientCertKey is the asset that generates the etcd client key/cert pair. +type EtcdSignerClientCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*EtcdSignerClientCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *EtcdSignerClientCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &EtcdSignerCertKey{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *EtcdSignerClientCertKey) Generate(dependencies asset.Parents) error { + ca := &EtcdSignerCertKey{} + dependencies.Get(ca) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "etcd", OrganizationalUnit: []string{"etcd"}}, + KeyUsages: x509.KeyUsageKeyEncipherment, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + Validity: ValidityTenYears, + } + + return a.SignedCertKey.Generate(cfg, ca, "etcd-signer-client", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *EtcdSignerClientCertKey) Name() string { + return "Certificate (etcd-signer-client)" +} diff --git a/pkg/asset/tls/etcdca.go b/pkg/asset/tls/etcdca.go deleted file mode 100644 index ca1f58884e6..00000000000 --- a/pkg/asset/tls/etcdca.go +++ /dev/null @@ -1,44 +0,0 @@ -package tls - -import ( - "crypto/x509" - "crypto/x509/pkix" - - "github.com/openshift/installer/pkg/asset" -) - -// EtcdCA is the asset that generates the etcd-ca key/cert pair. -type EtcdCA struct { - CertKey -} - -var _ asset.Asset = (*EtcdCA)(nil) - -// Dependencies returns the dependency of the the cert/key pair, which includes -// the parent CA, and install config if it depends on the install config for -// DNS names, etc. -func (a *EtcdCA) Dependencies() []asset.Asset { - return []asset.Asset{ - &RootCA{}, - } -} - -// Generate generates the cert/key pair based on its dependencies. -func (a *EtcdCA) Generate(dependencies asset.Parents) error { - rootCA := &RootCA{} - dependencies.Get(rootCA) - - cfg := &CertCfg{ - Subject: pkix.Name{CommonName: "etcd", OrganizationalUnit: []string{"etcd"}}, - KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - Validity: ValidityTenYears, - IsCA: true, - } - - return a.CertKey.Generate(cfg, rootCA, "etcd-client-ca", DoNotAppendParent) -} - -// Name returns the human-friendly name of the asset. -func (a *EtcdCA) Name() string { - return "Certificate (etcd)" -} diff --git a/pkg/asset/tls/etcdclientcertkey.go b/pkg/asset/tls/etcdclientcertkey.go deleted file mode 100644 index d9c90258d17..00000000000 --- a/pkg/asset/tls/etcdclientcertkey.go +++ /dev/null @@ -1,44 +0,0 @@ -package tls - -import ( - "crypto/x509" - "crypto/x509/pkix" - - "github.com/openshift/installer/pkg/asset" -) - -// EtcdClientCertKey is the asset that generates the etcd client key/cert pair. -type EtcdClientCertKey struct { - CertKey -} - -var _ asset.Asset = (*EtcdClientCertKey)(nil) - -// Dependencies returns the dependency of the the cert/key pair, which includes -// the parent CA, and install config if it depends on the install config for -// DNS names, etc. -func (a *EtcdClientCertKey) Dependencies() []asset.Asset { - return []asset.Asset{ - &EtcdCA{}, - } -} - -// Generate generates the cert/key pair based on its dependencies. -func (a *EtcdClientCertKey) Generate(dependencies asset.Parents) error { - etcdCA := &EtcdCA{} - dependencies.Get(etcdCA) - - cfg := &CertCfg{ - Subject: pkix.Name{CommonName: "etcd", OrganizationalUnit: []string{"etcd"}}, - KeyUsages: x509.KeyUsageKeyEncipherment, - ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - Validity: ValidityTenYears, - } - - return a.CertKey.Generate(cfg, etcdCA, "etcd-client", DoNotAppendParent) -} - -// Name returns the human-friendly name of the asset. -func (a *EtcdClientCertKey) Name() string { - return "Certificate (etcd)" -} diff --git a/pkg/asset/tls/ingresscertkey.go b/pkg/asset/tls/ingresscertkey.go deleted file mode 100644 index 69141ae2ad0..00000000000 --- a/pkg/asset/tls/ingresscertkey.go +++ /dev/null @@ -1,54 +0,0 @@ -package tls - -import ( - "crypto/x509" - "crypto/x509/pkix" - "fmt" - - "github.com/openshift/installer/pkg/asset" - "github.com/openshift/installer/pkg/asset/installconfig" -) - -// IngressCertKey is the asset that generates the ingress key/cert pair. -type IngressCertKey struct { - CertKey -} - -var _ asset.Asset = (*IngressCertKey)(nil) - -// Dependencies returns the dependency of the the cert/key pair, which includes -// the parent CA, and install config if it depends on the install config for -// DNS names, etc. -func (a *IngressCertKey) Dependencies() []asset.Asset { - return []asset.Asset{ - &KubeCA{}, - &installconfig.InstallConfig{}, - } -} - -// Generate generates the cert/key pair based on its dependencies. -func (a *IngressCertKey) Generate(dependencies asset.Parents) error { - kubeCA := &KubeCA{} - installConfig := &installconfig.InstallConfig{} - dependencies.Get(kubeCA, installConfig) - - baseAddress := fmt.Sprintf("%s.%s", installConfig.Config.ObjectMeta.Name, installConfig.Config.BaseDomain) - - cfg := &CertCfg{ - Subject: pkix.Name{CommonName: baseAddress, Organization: []string{"ingress"}}, - KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, - Validity: ValidityTenYears, - DNSNames: []string{ - baseAddress, - fmt.Sprintf("*.%s", baseAddress), - }, - } - - return a.CertKey.Generate(cfg, kubeCA, "ingress", AppendParent) -} - -// Name returns the human-friendly name of the asset. -func (a *IngressCertKey) Name() string { - return "Certificate (ingress)" -} diff --git a/pkg/asset/tls/journalcertkey.go b/pkg/asset/tls/journalcertkey.go index a4ef3a39741..0f641abc937 100644 --- a/pkg/asset/tls/journalcertkey.go +++ b/pkg/asset/tls/journalcertkey.go @@ -10,7 +10,7 @@ import ( // JournalCertKey is the asset that generates the key/cert pair that is used to // authenticate with journal-gatewayd on the bootstrap node. type JournalCertKey struct { - CertKey + SignedCertKey } var _ asset.WritableAsset = (*JournalCertKey)(nil) @@ -36,7 +36,7 @@ func (a *JournalCertKey) Generate(dependencies asset.Parents) error { Validity: ValidityTenYears, } - return a.CertKey.Generate(cfg, ca, "journal-gatewayd", DoNotAppendParent) + return a.SignedCertKey.Generate(cfg, ca, "journal-gatewayd", DoNotAppendParent) } // Name returns the human-friendly name of the asset. diff --git a/pkg/asset/tls/kubeca.go b/pkg/asset/tls/kubeca.go index aeca7126862..a519f4b7f07 100644 --- a/pkg/asset/tls/kubeca.go +++ b/pkg/asset/tls/kubeca.go @@ -5,12 +5,12 @@ import ( "crypto/x509/pkix" "github.com/openshift/installer/pkg/asset" - "github.com/pkg/errors" ) // KubeCA is the asset that generates the kube-ca key/cert pair. +// [DEPRECATED] type KubeCA struct { - CertKey + SelfSignedCertKey } var _ asset.Asset = (*KubeCA)(nil) @@ -32,17 +32,7 @@ func (a *KubeCA) Generate(dependencies asset.Parents) error { IsCA: true, } - key, crt, err := GenerateRootCertKey(cfg) - if err != nil { - return errors.Wrap(err, "failed to generate Kube CA") - } - - a.KeyRaw = PrivateKeyToPem(key) - a.CertRaw = CertToPem(crt) - - a.generateFiles("kube-ca") - - return nil + return a.SelfSignedCertKey.Generate(cfg, "kube-ca") } // Name returns the human-friendly name of the asset. diff --git a/pkg/asset/tls/kubecontrolplane.go b/pkg/asset/tls/kubecontrolplane.go new file mode 100644 index 00000000000..19a168986d7 --- /dev/null +++ b/pkg/asset/tls/kubecontrolplane.go @@ -0,0 +1,138 @@ +package tls + +import ( + "crypto/x509" + "crypto/x509/pkix" + + "github.com/openshift/installer/pkg/asset" +) + +// KubeControlPlaneSignerCertKey is a key/cert pair that signs the kube control-plane client certs. +type KubeControlPlaneSignerCertKey struct { + SelfSignedCertKey +} + +var _ asset.WritableAsset = (*KubeControlPlaneSignerCertKey)(nil) + +// Dependencies returns the dependency of the root-ca, which is empty. +func (c *KubeControlPlaneSignerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{} +} + +// Generate generates the root-ca key and cert pair. +func (c *KubeControlPlaneSignerCertKey) Generate(parents asset.Parents) error { + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "kube-control-plane-signer", OrganizationalUnit: []string{"openshift"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityOneYear, + IsCA: true, + } + + return c.SelfSignedCertKey.Generate(cfg, "kube-control-plane-signer") +} + +// Name returns the human-friendly name of the asset. +func (c *KubeControlPlaneSignerCertKey) Name() string { + return "Certificate (kube-control-plane-signer)" +} + +// KubeControlPlaneCABundle is the asset the generates the kube-control-plane-ca-bundle, +// which contains all the individual client CAs. +type KubeControlPlaneCABundle struct { + CertBundle +} + +var _ asset.Asset = (*KubeControlPlaneCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *KubeControlPlaneCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeControlPlaneSignerCertKey{}, + &KubeAPIServerLBSignerCertKey{}, + &KubeAPIServerLocalhostSignerCertKey{}, + &KubeAPIServerServiceNetworkSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *KubeControlPlaneCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("kube-control-plane-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeControlPlaneCABundle) Name() string { + return "Certificate (kube-control-plane-ca-bundle)" +} + +// KubeControlPlaneKubeControllerManagerClientCertKey is the asset that generates the kube-controller-manger client key/cert pair. +type KubeControlPlaneKubeControllerManagerClientCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*KubeControlPlaneKubeControllerManagerClientCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair +func (a *KubeControlPlaneKubeControllerManagerClientCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeControlPlaneSignerCertKey{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *KubeControlPlaneKubeControllerManagerClientCertKey) Generate(dependencies asset.Parents) error { + ca := &KubeControlPlaneSignerCertKey{} + dependencies.Get(ca) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:admin", Organization: []string{"system:masters"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + Validity: ValidityOneYear, + } + + return a.SignedCertKey.Generate(cfg, ca, "kube-control-plane-kube-controller-manager-client", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeControlPlaneKubeControllerManagerClientCertKey) Name() string { + return "Certificate (kube-control-plane-kube-controller-manager-client)" +} + +// KubeControlPlaneKubeSchedulerClientCertKey is the asset that generates the kube-scheduler client key/cert pair. +type KubeControlPlaneKubeSchedulerClientCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*KubeControlPlaneKubeSchedulerClientCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair +func (a *KubeControlPlaneKubeSchedulerClientCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeControlPlaneSignerCertKey{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *KubeControlPlaneKubeSchedulerClientCertKey) Generate(dependencies asset.Parents) error { + ca := &KubeControlPlaneSignerCertKey{} + dependencies.Get(ca) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:admin", Organization: []string{"system:masters"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + Validity: ValidityOneYear, + } + + return a.SignedCertKey.Generate(cfg, ca, "kube-control-plane-kube-scheduler-client", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeControlPlaneKubeSchedulerClientCertKey) Name() string { + return "Certificate (kube-control-plane-kube-scheduler-client)" +} diff --git a/pkg/asset/tls/kubelet.go b/pkg/asset/tls/kubelet.go new file mode 100644 index 00000000000..8e1f5fd781d --- /dev/null +++ b/pkg/asset/tls/kubelet.go @@ -0,0 +1,172 @@ +package tls + +import ( + "crypto/x509" + "crypto/x509/pkix" + + "github.com/openshift/installer/pkg/asset" +) + +// KubeletCertKey is the asset that generates the kubelet key/cert pair. +// [DEPRECATED] +type KubeletCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*KubeletCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *KubeletCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeCA{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *KubeletCertKey) Generate(dependencies asset.Parents) error { + kubeCA := &KubeCA{} + dependencies.Get(kubeCA) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:serviceaccount:openshift-machine-config-operator:node-bootstrapper", Organization: []string{"system:serviceaccounts:openshift-machine-config-operator"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + Validity: ValidityOneDay, + } + + return a.SignedCertKey.Generate(cfg, kubeCA, "kubelet", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeletCertKey) Name() string { + return "Certificate (system:serviceaccount:openshift-machine-config-operator:node-bootstrapper)" +} + +// KubeletCSRSignerCertKey is a key/cert pair that signs the kubelet client certs. +type KubeletCSRSignerCertKey struct { + SelfSignedCertKey +} + +var _ asset.WritableAsset = (*KubeletCSRSignerCertKey)(nil) + +// Dependencies returns the dependency of the root-ca, which is empty. +func (c *KubeletCSRSignerCertKey) Dependencies() []asset.Asset { + return []asset.Asset{} +} + +// Generate generates the root-ca key and cert pair. +func (c *KubeletCSRSignerCertKey) Generate(parents asset.Parents) error { + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "kubelet-signer", OrganizationalUnit: []string{"openshift"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + Validity: ValidityOneDay, + IsCA: true, + } + + return c.SelfSignedCertKey.Generate(cfg, "kubelet-signer") +} + +// Name returns the human-friendly name of the asset. +func (c *KubeletCSRSignerCertKey) Name() string { + return "Certificate (kubelet-signer)" +} + +// KubeletClientCABundle is the asset the generates the kubelet-client-ca-bundle, +// which contains all the individual client CAs. +type KubeletClientCABundle struct { + CertBundle +} + +var _ asset.Asset = (*KubeletClientCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *KubeletClientCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeletCSRSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *KubeletClientCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("kubelet-client-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeletClientCABundle) Name() string { + return "Certificate (kubelet-client-ca-bundle)" +} + +// KubeletServingCABundle is the asset the generates the kubelet-serving-ca-bundle, +// which contains all the individual client CAs. +type KubeletServingCABundle struct { + CertBundle +} + +var _ asset.Asset = (*KubeletServingCABundle)(nil) + +// Dependencies returns the dependency of the cert bundle. +func (a *KubeletServingCABundle) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeletCSRSignerCertKey{}, + } +} + +// Generate generates the cert bundle based on its dependencies. +func (a *KubeletServingCABundle) Generate(deps asset.Parents) error { + var certs []CertInterface + for _, asset := range a.Dependencies() { + deps.Get(asset) + certs = append(certs, asset.(CertInterface)) + } + return a.CertBundle.Generate("kubelet-serving-ca-bundle", certs...) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeletServingCABundle) Name() string { + return "Certificate (kubelet-serving-ca-bundle)" +} + +// KubeletClientCertKey is the asset that generates the key/cert pair for kubelet client to apiserver. +type KubeletClientCertKey struct { + SignedCertKey +} + +var _ asset.Asset = (*KubeletClientCertKey)(nil) + +// Dependencies returns the dependency of the the cert/key pair, which includes +// the parent CA, and install config if it depends on the install config for +// DNS names, etc. +func (a *KubeletClientCertKey) Dependencies() []asset.Asset { + return []asset.Asset{ + &KubeletCSRSignerCertKey{}, + &KubeAPIServerLBSignerCertKey{}, + &KubeAPIServerLocalhostSignerCertKey{}, + } +} + +// Generate generates the cert/key pair based on its dependencies. +func (a *KubeletClientCertKey) Generate(dependencies asset.Parents) error { + ca := &KubeletCSRSignerCertKey{} + dependencies.Get(ca) + + cfg := &CertCfg{ + Subject: pkix.Name{CommonName: "system:serviceaccount:openshift-machine-config-operator:node-bootstrapper", Organization: []string{"system:serviceaccounts:openshift-machine-config-operator"}}, + KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + Validity: ValidityOneDay, + } + + return a.SignedCertKey.Generate(cfg, ca, "kubelet-client", DoNotAppendParent) +} + +// Name returns the human-friendly name of the asset. +func (a *KubeletClientCertKey) Name() string { + return "Certificate (kubelet-client)" +} diff --git a/pkg/asset/tls/kubeletcertkey.go b/pkg/asset/tls/kubeletcertkey.go deleted file mode 100644 index e0bac6d2073..00000000000 --- a/pkg/asset/tls/kubeletcertkey.go +++ /dev/null @@ -1,44 +0,0 @@ -package tls - -import ( - "crypto/x509" - "crypto/x509/pkix" - - "github.com/openshift/installer/pkg/asset" -) - -// KubeletCertKey is the asset that generates the kubelet key/cert pair. -type KubeletCertKey struct { - CertKey -} - -var _ asset.Asset = (*KubeletCertKey)(nil) - -// Dependencies returns the dependency of the the cert/key pair, which includes -// the parent CA, and install config if it depends on the install config for -// DNS names, etc. -func (a *KubeletCertKey) Dependencies() []asset.Asset { - return []asset.Asset{ - &KubeCA{}, - } -} - -// Generate generates the cert/key pair based on its dependencies. -func (a *KubeletCertKey) Generate(dependencies asset.Parents) error { - kubeCA := &KubeCA{} - dependencies.Get(kubeCA) - - cfg := &CertCfg{ - Subject: pkix.Name{CommonName: "system:serviceaccount:openshift-machine-config-operator:node-bootstrapper", Organization: []string{"system:serviceaccounts:openshift-machine-config-operator"}}, - KeyUsages: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - Validity: ValidityOneDay, - } - - return a.CertKey.Generate(cfg, kubeCA, "kubelet", DoNotAppendParent) -} - -// Name returns the human-friendly name of the asset. -func (a *KubeletCertKey) Name() string { - return "Certificate (system:serviceaccount:kube-system:default)" -} diff --git a/pkg/asset/tls/mcscertkey.go b/pkg/asset/tls/mcscertkey.go index 9463d6c2673..021e2982551 100644 --- a/pkg/asset/tls/mcscertkey.go +++ b/pkg/asset/tls/mcscertkey.go @@ -10,7 +10,7 @@ import ( // MCSCertKey is the asset that generates the MCS key/cert pair. type MCSCertKey struct { - CertKey + SignedCertKey } var _ asset.Asset = (*MCSCertKey)(nil) @@ -27,9 +27,9 @@ func (a *MCSCertKey) Dependencies() []asset.Asset { // Generate generates the cert/key pair based on its dependencies. func (a *MCSCertKey) Generate(dependencies asset.Parents) error { - rootCA := &RootCA{} + ca := &RootCA{} installConfig := &installconfig.InstallConfig{} - dependencies.Get(rootCA, installConfig) + dependencies.Get(ca, installConfig) hostname := apiAddress(installConfig.Config) @@ -40,7 +40,7 @@ func (a *MCSCertKey) Generate(dependencies asset.Parents) error { DNSNames: []string{hostname}, } - return a.CertKey.Generate(cfg, rootCA, "machine-config-server", DoNotAppendParent) + return a.SignedCertKey.Generate(cfg, ca, "machine-config-server", DoNotAppendParent) } // Name returns the human-friendly name of the asset. diff --git a/pkg/asset/tls/root.go b/pkg/asset/tls/root.go index 3651f15391e..4467961a3ff 100644 --- a/pkg/asset/tls/root.go +++ b/pkg/asset/tls/root.go @@ -5,13 +5,12 @@ import ( "crypto/x509/pkix" "github.com/openshift/installer/pkg/asset" - "github.com/pkg/errors" ) // RootCA contains the private key and the cert that's // self-signed as the root CA. type RootCA struct { - CertKey + SelfSignedCertKey } var _ asset.WritableAsset = (*RootCA)(nil) @@ -30,17 +29,7 @@ func (c *RootCA) Generate(parents asset.Parents) error { IsCA: true, } - key, crt, err := GenerateRootCertKey(cfg) - if err != nil { - return errors.Wrap(err, "failed to generate RootCA") - } - - c.KeyRaw = PrivateKeyToPem(key) - c.CertRaw = CertToPem(crt) - - c.generateFiles("root-ca") - - return nil + return c.SelfSignedCertKey.Generate(cfg, "root-ca") } // Name returns the human-friendly name of the asset. diff --git a/pkg/asset/tls/tls.go b/pkg/asset/tls/tls.go index 3297bb69121..076f3449725 100644 --- a/pkg/asset/tls/tls.go +++ b/pkg/asset/tls/tls.go @@ -21,12 +21,14 @@ import ( const ( keySize = 2048 - // ValidityTenYears sets the validity of a cert to 10 years. - ValidityTenYears = time.Hour * 24 * 365 * 10 - // ValidityOneDay sets the validity of a cert to 24 hours. - // This is for the kubelet bootstrap. ValidityOneDay = time.Hour * 24 + + // ValidityOneYear sets the validity of a cert to 1 year. + ValidityOneYear = ValidityOneDay * 365 + + // ValidityTenYears sets the validity of a cert to 10 years. + ValidityTenYears = ValidityOneYear * 10 ) // CertCfg contains all needed fields to configure a new certificate @@ -56,17 +58,19 @@ func PrivateKey() (*rsa.PrivateKey, error) { return rsaKey, nil } -// SelfSignedCACert Creates a self signed CA certificate -func SelfSignedCACert(cfg *CertCfg, key *rsa.PrivateKey) (*x509.Certificate, error) { - var err error - +// SelfSignedCertificate creates a self signed certificate +func SelfSignedCertificate(cfg *CertCfg, key *rsa.PrivateKey) (*x509.Certificate, error) { + serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) + if err != nil { + return nil, err + } cert := x509.Certificate{ BasicConstraintsValid: true, IsCA: cfg.IsCA, KeyUsage: cfg.KeyUsages, NotAfter: time.Now().Add(cfg.Validity), NotBefore: time.Now(), - SerialNumber: new(big.Int).SetInt64(0), + SerialNumber: serial, Subject: cfg.Subject, } // verifies that the CN and/or OU for the cert is set @@ -144,11 +148,8 @@ func generateSubjectKeyID(pub crypto.PublicKey) ([]byte, error) { return hash[:], nil } -// GenerateCert creates a key, csr & a signed cert -// This is useful for apiserver and openshift-apiser cert which will be -// authenticated by the kubeconfig using root-ca. -func GenerateCert(caKey *rsa.PrivateKey, - caCert *x509.Certificate, +// GenerateSignedCertificate generate a key and cert defined by CertCfg and signed by CA. +func GenerateSignedCertificate(caKey *rsa.PrivateKey, caCert *x509.Certificate, cfg *CertCfg) (*rsa.PrivateKey, *x509.Certificate, error) { // create a private key @@ -169,45 +170,23 @@ func GenerateCert(caKey *rsa.PrivateKey, } // create a cert - cert, err := GenerateSignedCert(cfg, csr, key, caKey, caCert) + cert, err := SignedCertificate(cfg, csr, key, caCert, caKey) if err != nil { return nil, nil, errors.Wrap(err, "failed to create a signed certificate") } return key, cert, nil } -// GenerateRootCA creates and returns the root CA -func GenerateRootCA(key *rsa.PrivateKey, cfg *CertCfg) (*x509.Certificate, error) { - cert, err := SelfSignedCACert(cfg, key) - if err != nil { - return nil, errors.Wrap(err, "failed to generate self signed certificate") - } - return cert, nil -} - -// GenerateSignedCert generates a signed certificate. -func GenerateSignedCert(cfg *CertCfg, - csr *x509.CertificateRequest, - key *rsa.PrivateKey, - caKey *rsa.PrivateKey, - caCert *x509.Certificate) (*x509.Certificate, error) { - cert, err := SignedCertificate(cfg, csr, key, caCert, caKey) - if err != nil { - return nil, errors.Wrap(err, "failed to create a signed certificate") - } - return cert, nil -} - -// GenerateRootCertKey generates a root key/cert pair. -func GenerateRootCertKey(cfg *CertCfg) (*rsa.PrivateKey, *x509.Certificate, error) { +// GenerateSelfSignedCertificate generates a key/cert pair defined by CertCfg. +func GenerateSelfSignedCertificate(cfg *CertCfg) (*rsa.PrivateKey, *x509.Certificate, error) { key, err := PrivateKey() if err != nil { return nil, nil, errors.Wrap(err, "failed to generate private key") } - crt, err := GenerateRootCA(key, cfg) + crt, err := SelfSignedCertificate(cfg, key) if err != nil { - return nil, nil, errors.Wrap(err, "failed to create root CA certificate") + return nil, nil, errors.Wrap(err, "failed to create self-signed certificate") } return key, crt, nil } diff --git a/pkg/asset/tls/tls_test.go b/pkg/asset/tls/tls_test.go index 57d727c77c3..116cf046fb3 100644 --- a/pkg/asset/tls/tls_test.go +++ b/pkg/asset/tls/tls_test.go @@ -8,7 +8,7 @@ import ( "time" ) -func TestSelfSignedCACert(t *testing.T) { +func TestSelfSignedCertificate(t *testing.T) { key, err := PrivateKey() if err != nil { t.Fatalf("Failed to generate Private Key: %v", err) @@ -50,7 +50,7 @@ func TestSelfSignedCACert(t *testing.T) { }, } for i, c := range cases { - if _, err := SelfSignedCACert(c.cfg, key); (err != nil) != c.err { + if _, err := SelfSignedCertificate(c.cfg, key); (err != nil) != c.err { no := "no" if c.err { no = "an"