github.com/kubernetes-incubator/kube-aws@v0.16.4/credential/generator.go (about)

     1  package credential
     2  
     3  import (
     4  	"crypto/rsa"
     5  	"crypto/x509"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net"
     9  	"time"
    10  
    11  	"github.com/kubernetes-incubator/kube-aws/logger"
    12  	"github.com/kubernetes-incubator/kube-aws/netutil"
    13  	"github.com/kubernetes-incubator/kube-aws/pki"
    14  )
    15  
    16  type Generator struct {
    17  	TLSCADurationDays                int
    18  	TLSCertDurationDays              int
    19  	TLSBootstrapEnabled              bool
    20  	ManageCertificates               bool
    21  	Region                           string
    22  	APIServerExternalDNSNames        []string
    23  	APIServerAdditionalDNSSans       []string
    24  	APIServerAdditionalIPAddressSans []string
    25  	EtcdNodeDNSNames                 []string
    26  	ServiceCIDR                      string
    27  }
    28  
    29  type GeneratorOptions struct {
    30  	AwsDebug   bool
    31  	GenerateCA bool
    32  	CaCertPath string
    33  	CommonName string
    34  	// Paths for private certificate keys.
    35  	AdminKeyPath                 string
    36  	ApiServerAggregatorKeyPath   string
    37  	ApiServerKeyPath             string
    38  	CaKeyPath                    string
    39  	EtcdClientKeyPath            string
    40  	EtcdKeyPath                  string
    41  	KubeControllerManagerKeyPath string
    42  	KubeSchedulerKeyPath         string
    43  	ServiceAccountKeyPath        string
    44  	WorkerKeyPath                string
    45  }
    46  
    47  func (c Generator) GenerateAssetsOnDisk(dir string, o GeneratorOptions) (*RawAssetsOnDisk, error) {
    48  	logger.Info("Generating credentials...")
    49  	var caKey *rsa.PrivateKey
    50  	var caCert *x509.Certificate
    51  	if o.GenerateCA {
    52  		var err error
    53  		caKey, caCert, err = pki.NewCA(c.TLSCADurationDays, o.CommonName)
    54  		if err != nil {
    55  			return nil, fmt.Errorf("failed generating cluster CA: %v", err)
    56  		}
    57  		logger.Info("-> Generating new TLS CA\n")
    58  	} else {
    59  		logger.Info("-> Parsing existing TLS CA\n")
    60  		if caKeyBytes, err := ioutil.ReadFile(o.CaKeyPath); err != nil {
    61  			return nil, fmt.Errorf("failed reading ca key file %s : %v", o.CaKeyPath, err)
    62  		} else {
    63  			if caKey, err = pki.DecodePrivateKeyPEM(caKeyBytes); err != nil {
    64  				return nil, fmt.Errorf("failed parsing ca key: %v", err)
    65  			}
    66  		}
    67  		if caCertBytes, err := ioutil.ReadFile(o.CaCertPath); err != nil {
    68  			return nil, fmt.Errorf("failed reading ca cert file %s : %v", o.CaCertPath, err)
    69  		} else {
    70  			if caCert, err = pki.DecodeCertificatePEM(caCertBytes); err != nil {
    71  				return nil, fmt.Errorf("failed parsing ca cert: %v", err)
    72  			}
    73  		}
    74  	}
    75  
    76  	logger.Info("-> Generating new assets")
    77  	assets, err := c.GenerateAssetsOnMemory(caKey, caCert, o)
    78  	if err != nil {
    79  		return nil, fmt.Errorf("Error generating default assets: %v", err)
    80  	}
    81  
    82  	logger.Infof("--> Summarizing the configuration\n    TLS certificates managed by kube-aws=%v, CA key required on controller nodes=%v\n", c.ManageCertificates, true)
    83  
    84  	logger.Info("--> Writing to the storage")
    85  	alsoWriteCAKey := o.GenerateCA || c.ManageCertificates
    86  	if err := assets.WriteToDir(dir, alsoWriteCAKey); err != nil {
    87  		return nil, fmt.Errorf("Error creating assets: %v", err)
    88  	}
    89  
    90  	{
    91  		logger.Info("--> Verifying the result")
    92  		verified, err := ReadRawAssets(dir, c.ManageCertificates, c.ManageCertificates)
    93  
    94  		if err != nil {
    95  			return nil, fmt.Errorf("failed verifying the result: %v", err)
    96  		}
    97  
    98  		return verified, nil
    99  	}
   100  }
   101  
   102  func getOrCreatePrivateKey(keyPath string) (*rsa.PrivateKey, error) {
   103  	if keyPath != "" {
   104  		keyBytes, err := ioutil.ReadFile(keyPath)
   105  		if err != nil {
   106  			return nil, fmt.Errorf("failed reading key file %s : %v", keyPath, err)
   107  		}
   108  
   109  		key, err := pki.DecodePrivateKeyPEM(keyBytes)
   110  		if err != nil {
   111  			return nil, fmt.Errorf("failed parsing key: %v", err)
   112  		}
   113  		return key, nil
   114  	}
   115  	return pki.NewPrivateKey()
   116  }
   117  
   118  func (c Generator) GenerateAssetsOnMemory(caKey *rsa.PrivateKey, caCert *x509.Certificate, generatorOptions GeneratorOptions) (*RawAssetsOnMemory, error) {
   119  	// Convert from days to time.Duration
   120  	certDuration := time.Duration(c.TLSCertDurationDays) * 24 * time.Hour
   121  
   122  	// Generate keys for the various components.
   123  	privateKeys := map[string]*rsa.PrivateKey{
   124  		generatorOptions.ApiServerKeyPath:             nil,
   125  		generatorOptions.KubeControllerManagerKeyPath: nil,
   126  		generatorOptions.KubeSchedulerKeyPath:         nil,
   127  		generatorOptions.WorkerKeyPath:                nil,
   128  		generatorOptions.AdminKeyPath:                 nil,
   129  		generatorOptions.EtcdKeyPath:                  nil,
   130  		generatorOptions.EtcdClientKeyPath:            nil,
   131  		generatorOptions.ServiceAccountKeyPath:        nil,
   132  		generatorOptions.ApiServerAggregatorKeyPath:   nil,
   133  	}
   134  
   135  	for key := range privateKeys {
   136  		var err error
   137  		if privateKeys[key], err = getOrCreatePrivateKey(key); err != nil {
   138  			return nil, err
   139  		}
   140  	}
   141  
   142  	// Compute kubernetesServiceIP from serviceCIDR
   143  	_, serviceNet, err := net.ParseCIDR(c.ServiceCIDR)
   144  	if err != nil {
   145  		return nil, fmt.Errorf("invalid serviceCIDR: %v", err)
   146  	}
   147  	kubernetesServiceIPAddr := netutil.IncrementIP(serviceNet.IP)
   148  
   149  	dnsNames := append(
   150  		[]string{
   151  			"kubernetes",
   152  			"kubernetes.default",
   153  			"kubernetes.default.svc",
   154  			"kubernetes.default.svc.cluster.local",
   155  		}, c.APIServerExternalDNSNames...)
   156  
   157  	// 127.0.0.1 also allows control plane components to reach the apiserver via HTTPS at localhost
   158  	ipAddresses := []string{kubernetesServiceIPAddr.String(), "127.0.0.1"}
   159  
   160  	apiServerConfig := pki.ServerCertConfig{
   161  		CommonName:  "kube-apiserver",
   162  		DNSNames:    append(dnsNames, c.APIServerExternalDNSNames...),
   163  		IPAddresses: append(ipAddresses, c.APIServerAdditionalIPAddressSans...),
   164  		Duration:    certDuration,
   165  	}
   166  	apiServerCert, err := pki.NewSignedServerCertificate(apiServerConfig, privateKeys[generatorOptions.ApiServerKeyPath], caCert, caKey)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	etcdConfig := pki.ServerCertConfig{
   172  		CommonName: "kube-etcd",
   173  		DNSNames:   c.EtcdNodeDNSNames,
   174  		// etcd https client/peer interfaces are not exposed externally
   175  		// but anyway we'll make it valid for the same duration as other certs just because it is easy to implement.
   176  		Duration: certDuration,
   177  	}
   178  
   179  	etcdCert, err := pki.NewSignedServerCertificate(etcdConfig, privateKeys[generatorOptions.EtcdKeyPath], caCert, caKey)
   180  	if err != nil {
   181  		return nil, err
   182  	}
   183  
   184  	workerConfig := pki.ClientCertConfig{
   185  		CommonName: "kube-worker",
   186  		DNSNames: []string{
   187  			fmt.Sprintf("*.%s.compute.internal", c.Region),
   188  			"*.ec2.internal",
   189  		},
   190  		Duration: certDuration,
   191  	}
   192  	workerCert, err := pki.NewSignedClientCertificate(workerConfig, privateKeys[generatorOptions.WorkerKeyPath], caCert, caKey)
   193  	if err != nil {
   194  		return nil, err
   195  	}
   196  
   197  	etcdClientConfig := pki.ClientCertConfig{
   198  		CommonName: "kube-etcd-client",
   199  		Duration:   certDuration,
   200  	}
   201  
   202  	etcdClientCert, err := pki.NewSignedClientCertificate(etcdClientConfig, privateKeys[generatorOptions.EtcdClientKeyPath], caCert, caKey)
   203  	if err != nil {
   204  		return nil, err
   205  	}
   206  
   207  	adminConfig := pki.ClientCertConfig{
   208  		CommonName:   "kube-admin",
   209  		Organization: []string{"system:masters"},
   210  		Duration:     certDuration,
   211  	}
   212  	adminCert, err := pki.NewSignedClientCertificate(adminConfig, privateKeys[generatorOptions.AdminKeyPath], caCert, caKey)
   213  	if err != nil {
   214  		return nil, err
   215  	}
   216  
   217  	kubeControllerManagerConfig := pki.ClientCertConfig{
   218  		CommonName: "system:kube-controller-manager",
   219  		Duration:   certDuration,
   220  	}
   221  	kubeControllerManagerCert, err := pki.NewSignedClientCertificate(kubeControllerManagerConfig, privateKeys[generatorOptions.KubeControllerManagerKeyPath], caCert, caKey)
   222  	if err != nil {
   223  		return nil, err
   224  	}
   225  
   226  	kubeSchedulerConfig := pki.ClientCertConfig{
   227  		CommonName: "system:kube-scheduler",
   228  		Duration:   certDuration,
   229  	}
   230  	kubeSchedulerCert, err := pki.NewSignedClientCertificate(kubeSchedulerConfig, privateKeys[generatorOptions.KubeSchedulerKeyPath], caCert, caKey)
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  
   235  	apiServerAggregatorConfig := pki.ClientCertConfig{
   236  		CommonName: "aggregator",
   237  		Duration:   certDuration,
   238  	}
   239  	apiServerAggregatorCert, err := pki.NewSignedClientCertificate(apiServerAggregatorConfig, privateKeys[generatorOptions.ApiServerAggregatorKeyPath], caCert, caKey)
   240  	if err != nil {
   241  		return nil, err
   242  	}
   243  
   244  	authTokens := ""
   245  	tlsBootstrapToken, err := RandomTokenString()
   246  	if err != nil {
   247  		return nil, err
   248  	}
   249  
   250  	encryptionConfig, err := EncryptionConfig()
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  
   255  	r := &RawAssetsOnMemory{
   256  		CACert:                    pki.EncodeCertificatePEM(caCert),
   257  		APIServerCert:             pki.EncodeCertificatePEM(apiServerCert),
   258  		KubeControllerManagerCert: pki.EncodeCertificatePEM(kubeControllerManagerCert),
   259  		KubeSchedulerCert:         pki.EncodeCertificatePEM(kubeSchedulerCert),
   260  		WorkerCert:                pki.EncodeCertificatePEM(workerCert),
   261  		AdminCert:                 pki.EncodeCertificatePEM(adminCert),
   262  		EtcdCert:                  pki.EncodeCertificatePEM(etcdCert),
   263  		EtcdClientCert:            pki.EncodeCertificatePEM(etcdClientCert),
   264  		APIServerAggregatorCert:   pki.EncodeCertificatePEM(apiServerAggregatorCert),
   265  		CAKey:                     pki.EncodePrivateKeyPEM(caKey),
   266  		APIServerKey:              pki.EncodePrivateKeyPEM(privateKeys[generatorOptions.ApiServerKeyPath]),
   267  		KubeControllerManagerKey:  pki.EncodePrivateKeyPEM(privateKeys[generatorOptions.KubeControllerManagerKeyPath]),
   268  		KubeSchedulerKey:          pki.EncodePrivateKeyPEM(privateKeys[generatorOptions.KubeSchedulerKeyPath]),
   269  		WorkerKey:                 pki.EncodePrivateKeyPEM(privateKeys[generatorOptions.WorkerKeyPath]),
   270  		AdminKey:                  pki.EncodePrivateKeyPEM(privateKeys[generatorOptions.AdminKeyPath]),
   271  		EtcdKey:                   pki.EncodePrivateKeyPEM(privateKeys[generatorOptions.EtcdKeyPath]),
   272  		EtcdClientKey:             pki.EncodePrivateKeyPEM(privateKeys[generatorOptions.EtcdClientKeyPath]),
   273  		ServiceAccountKey:         pki.EncodePrivateKeyPEM(privateKeys[generatorOptions.ServiceAccountKeyPath]),
   274  		APIServerAggregatorKey:    pki.EncodePrivateKeyPEM(privateKeys[generatorOptions.ApiServerAggregatorKeyPath]),
   275  
   276  		AuthTokens:        []byte(authTokens),
   277  		TLSBootstrapToken: []byte(tlsBootstrapToken),
   278  		EncryptionConfig:  []byte(encryptionConfig),
   279  	}
   280  
   281  	return r, nil
   282  }