// TestNew verifies that the New function returns a Master // using the configuration properly. func TestNew(t *testing.T) { master, etcdserver, config, assert := newMaster(t) defer etcdserver.Terminate(t) // Verify many of the variables match their config counterparts assert.Equal(master.enableCoreControllers, config.EnableCoreControllers) assert.Equal(master.tunneler, config.Tunneler) assert.Equal(master.RequestContextMapper(), config.RequestContextMapper) assert.Equal(master.ClusterIP, config.PublicAddress) // these values get defaulted _, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24") serviceReadWriteIP, _ := ipallocator.GetIndexedIP(serviceClusterIPRange, 1) assert.Equal(master.MasterCount, 1) assert.Equal(master.PublicReadWritePort, 6443) assert.Equal(master.ServiceReadWriteIP, serviceReadWriteIP) // These functions should point to the same memory location masterDialer, _ := utilnet.Dialer(master.ProxyTransport) masterDialerFunc := fmt.Sprintf("%p", masterDialer) configDialerFunc := fmt.Sprintf("%p", config.ProxyDialer) assert.Equal(masterDialerFunc, configDialerFunc) assert.Equal(master.ProxyTransport.(*http.Transport).TLSClientConfig, config.ProxyTLSClientConfig) }
// TestNew verifies that the New function returns a GenericAPIServer // using the configuration properly. func TestNew(t *testing.T) { s, etcdserver, config, assert := newMaster(t) defer etcdserver.Terminate(t) // Verify many of the variables match their config counterparts assert.Equal(s.enableSwaggerSupport, config.EnableSwaggerSupport) assert.Equal(s.legacyAPIPrefix, config.APIPrefix) assert.Equal(s.apiPrefix, config.APIGroupPrefix) assert.Equal(s.admissionControl, config.AdmissionControl) assert.Equal(s.RequestContextMapper(), config.RequestContextMapper) assert.Equal(s.ClusterIP, config.PublicAddress) // these values get defaulted _, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24") serviceReadWriteIP, _ := ipallocator.GetIndexedIP(serviceClusterIPRange, 1) assert.Equal(s.ServiceReadWriteIP, serviceReadWriteIP) assert.Equal(s.ExternalAddress, net.JoinHostPort(config.PublicAddress.String(), "6443")) assert.Equal(s.PublicReadWritePort, 6443) // These functions should point to the same memory location serverDialer, _ := utilnet.Dialer(s.ProxyTransport) serverDialerFunc := fmt.Sprintf("%p", serverDialer) configDialerFunc := fmt.Sprintf("%p", config.ProxyDialer) assert.Equal(serverDialerFunc, configDialerFunc) assert.Equal(s.ProxyTransport.(*http.Transport).TLSClientConfig, config.ProxyTLSClientConfig) }
func newServerKeyAndCert(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate, caKey *rsa.PrivateKey, altNames certutil.AltNames) (*rsa.PrivateKey, *x509.Certificate, error) { key, err := certutil.NewPrivateKey() if err != nil { return nil, nil, fmt.Errorf("unabel to create private key [%v]", err) } internalAPIServerFQDN := []string{ "kubernetes", "kubernetes.default", "kubernetes.default.svc", fmt.Sprintf("kubernetes.default.svc.%s", s.InitFlags.Services.DNSDomain), } internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(&s.InitFlags.Services.CIDR, 1) if err != nil { return nil, nil, fmt.Errorf("unable to allocate IP address for the API server from the given CIDR (%q) [%v]", &s.InitFlags.Services.CIDR, err) } altNames.IPs = append(altNames.IPs, internalAPIServerVirtualIP) altNames.DNSNames = append(altNames.DNSNames, internalAPIServerFQDN...) config := certutil.Config{ CommonName: "kube-apiserver", AltNames: altNames, } cert, err := certutil.NewSignedCert(config, key, caCert, caKey) if err != nil { return nil, nil, fmt.Errorf("unable to sign certificate [%v]", err) } return key, cert, nil }
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver. func (c *Config) Complete() completedConfig { if c.ServiceClusterIPRange == nil { defaultNet := "10.0.0.0/24" glog.Warningf("Network range for service cluster IPs is unspecified. Defaulting to %v.", defaultNet) _, serviceClusterIPRange, err := net.ParseCIDR(defaultNet) if err != nil { glog.Fatalf("Unable to parse CIDR: %v", err) } if size := ipallocator.RangeSize(serviceClusterIPRange); size < 8 { glog.Fatalf("The service cluster IP range must be at least %d IP addresses", 8) } c.ServiceClusterIPRange = serviceClusterIPRange } if c.ServiceReadWriteIP == nil { // Select the first valid IP from ServiceClusterIPRange to use as the GenericAPIServer service IP. serviceReadWriteIP, err := ipallocator.GetIndexedIP(c.ServiceClusterIPRange, 1) if err != nil { glog.Fatalf("Failed to generate service read-write IP for GenericAPIServer service: %v", err) } glog.V(4).Infof("Setting GenericAPIServer service IP to %q (read-write).", serviceReadWriteIP) c.ServiceReadWriteIP = serviceReadWriteIP } if c.ServiceReadWritePort == 0 { c.ServiceReadWritePort = 443 } if c.ServiceNodePortRange.Size == 0 { // TODO: Currently no way to specify an empty range (do we need to allow this?) // We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE) // but then that breaks the strict nestedness of ServiceType. // Review post-v1 c.ServiceNodePortRange = options.DefaultServiceNodePortRange glog.Infof("Node port range unspecified. Defaulting to %v.", c.ServiceNodePortRange) } if c.MasterCount == 0 { // Clearly, there will be at least one GenericAPIServer. c.MasterCount = 1 } if c.ReadWritePort == 0 { c.ReadWritePort = 6443 } if c.CacheTimeout == 0 { c.CacheTimeout = 5 * time.Second } if c.RequestContextMapper == nil { c.RequestContextMapper = api.NewRequestContextMapper() } if len(c.ExternalHost) == 0 && c.PublicAddress != nil { hostAndPort := c.PublicAddress.String() if c.ReadWritePort != 0 { hostAndPort = net.JoinHostPort(hostAndPort, strconv.Itoa(c.ReadWritePort)) } c.ExternalHost = hostAndPort } if c.BuildHandlerChainsFunc == nil { c.BuildHandlerChainsFunc = DefaultBuildHandlerChain } return completedConfig{c} }
// TestNew verifies that the New function returns a Master // using the configuration properly. func TestNew(t *testing.T) { master, etcdserver, _, assert := newMaster(t) defer etcdserver.Terminate(t) // these values get defaulted _, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24") serviceReadWriteIP, _ := ipallocator.GetIndexedIP(serviceClusterIPRange, 1) assert.Equal(master.GenericAPIServer.MasterCount, 1) assert.Equal(master.GenericAPIServer.ServiceReadWriteIP, serviceReadWriteIP) }
// TestNew verifies that the New function returns a GenericAPIServer // using the configuration properly. func TestNew(t *testing.T) { s, etcdserver, config, assert := newMaster(t) defer etcdserver.Terminate(t) // Verify many of the variables match their config counterparts assert.Equal(s.enableSwaggerSupport, config.EnableSwaggerSupport) assert.Equal(s.legacyAPIGroupPrefixes, config.LegacyAPIGroupPrefixes) assert.Equal(s.admissionControl, config.AdmissionControl) assert.Equal(s.RequestContextMapper(), config.RequestContextMapper) // these values get defaulted _, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24") serviceReadWriteIP, _ := ipallocator.GetIndexedIP(serviceClusterIPRange, 1) assert.Equal(s.ServiceReadWriteIP, serviceReadWriteIP) assert.Equal(s.ExternalAddress, net.JoinHostPort(config.PublicAddress.String(), "6443")) }
func createKubeDNSServiceSpec(s *kubeadmapi.KubeadmConfig) (*api.ServiceSpec, error) { ip, err := ipallocator.GetIndexedIP(&s.InitFlags.Services.CIDR, 10) if err != nil { return nil, fmt.Errorf("unable to allocate IP address for kube-dns addon from the given CIDR (%q) [%v]", s.InitFlags.Services.CIDR, err) } svc := &api.ServiceSpec{ Selector: map[string]string{"name": "kube-dns"}, Ports: []api.ServicePort{ {Name: "dns", Port: 53, Protocol: api.ProtocolUDP}, {Name: "dns-tcp", Port: 53, Protocol: api.ProtocolTCP}, }, ClusterIP: ip.String(), } return svc, nil }
// TestNew verifies that the New function returns a Master // using the configuration properly. func TestNew(t *testing.T) { master, etcdserver, config, assert := newMaster(t) defer etcdserver.Terminate(t) // these values get defaulted _, serviceClusterIPRange, _ := net.ParseCIDR("10.0.0.0/24") serviceReadWriteIP, _ := ipallocator.GetIndexedIP(serviceClusterIPRange, 1) assert.Equal(master.GenericAPIServer.MasterCount, 1) assert.Equal(master.GenericAPIServer.ServiceReadWriteIP, serviceReadWriteIP) // These functions should point to the same memory location masterDialer, _ := utilnet.Dialer(master.GenericAPIServer.ProxyTransport) masterDialerFunc := fmt.Sprintf("%p", masterDialer) configDialerFunc := fmt.Sprintf("%p", config.GenericConfig.ProxyDialer) assert.Equal(masterDialerFunc, configDialerFunc) assert.Equal(master.GenericAPIServer.ProxyTransport.(*http.Transport).TLSClientConfig, config.GenericConfig.ProxyTLSClientConfig) }
func createKubeDNSServiceSpec(cfg *kubeadmapi.MasterConfiguration) (*v1.ServiceSpec, error) { _, n, err := net.ParseCIDR(cfg.Networking.ServiceSubnet) if err != nil { return nil, fmt.Errorf("could not parse %q: %v", cfg.Networking.ServiceSubnet, err) } ip, err := ipallocator.GetIndexedIP(n, 10) if err != nil { return nil, fmt.Errorf("unable to allocate IP address for kube-dns addon from the given CIDR %q: [%v]", cfg.Networking.ServiceSubnet, err) } return &v1.ServiceSpec{ Selector: map[string]string{"name": KubeDNS}, Ports: []v1.ServicePort{ {Name: "dns", Port: 53, Protocol: v1.ProtocolUDP}, {Name: "dns-tcp", Port: 53, Protocol: v1.ProtocolTCP}, }, ClusterIP: ip.String(), }, nil }
// DefaultServiceIPRange takes a the serviceIPRange flag and returns the defaulted service ip range (if needed), // api server service IP, and an error // TODO move this out of the genericapiserver package func DefaultServiceIPRange(passedServiceClusterIPRange net.IPNet) (net.IPNet, net.IP, error) { serviceClusterIPRange := passedServiceClusterIPRange if passedServiceClusterIPRange.IP == nil { defaultNet := "10.0.0.0/24" glog.Infof("Network range for service cluster IPs is unspecified. Defaulting to %v.", defaultNet) _, defaultServiceClusterIPRange, err := net.ParseCIDR(defaultNet) if err != nil { return net.IPNet{}, net.IP{}, err } serviceClusterIPRange = *defaultServiceClusterIPRange } if size := ipallocator.RangeSize(&serviceClusterIPRange); size < 8 { return net.IPNet{}, net.IP{}, fmt.Errorf("The service cluster IP range must be at least %d IP addresses", 8) } // Select the first valid IP from ServiceClusterIPRange to use as the GenericAPIServer service IP. apiServerServiceIP, err := ipallocator.GetIndexedIP(&serviceClusterIPRange, 1) if err != nil { return net.IPNet{}, net.IP{}, err } glog.V(4).Infof("Setting service IP to %q (read-write).", apiServerServiceIP) return serviceClusterIPRange, apiServerServiceIP, nil }
func newServerKeyAndCert(cfg *kubeadmapi.MasterConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey, altNames certutil.AltNames) (*rsa.PrivateKey, *x509.Certificate, error) { key, err := certutil.NewPrivateKey() if err != nil { return nil, nil, fmt.Errorf("unabel to create private key [%v]", err) } internalAPIServerFQDN := []string{ "kubernetes", "kubernetes.default", "kubernetes.default.svc", fmt.Sprintf("kubernetes.default.svc.%s", cfg.Networking.DNSDomain), } _, n, err := net.ParseCIDR(cfg.Networking.ServiceSubnet) if err != nil { return nil, nil, fmt.Errorf("error parsing CIDR %q: %v", cfg.Networking.ServiceSubnet, err) } internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(n, 1) if err != nil { return nil, nil, fmt.Errorf("unable to allocate IP address for the API server from the given CIDR (%q) [%v]", &cfg.Networking.ServiceSubnet, err) } altNames.IPs = append(altNames.IPs, internalAPIServerVirtualIP) altNames.DNSNames = append(altNames.DNSNames, internalAPIServerFQDN...) config := certutil.Config{ CommonName: "kube-apiserver", AltNames: altNames, } cert, err := certutil.NewSignedCert(config, key, caCert, caKey) if err != nil { return nil, nil, fmt.Errorf("unable to sign certificate [%v]", err) } return key, cert, nil }
// CreatePKIAssets will create and write to disk all PKI assets necessary to establish the control plane. // It first generates a self-signed CA certificate, a server certificate (signed by the CA) and a key for // signing service account tokens. It returns CA key and certificate, which is convenient for use with // client config funcs. func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiPath string) (*x509.Certificate, error) { altNames := certutil.AltNames{} // First, define all domains this cert should be signed for internalAPIServerFQDN := []string{ "kubernetes", "kubernetes.default", "kubernetes.default.svc", fmt.Sprintf("kubernetes.default.svc.%s", cfg.Networking.DNSDomain), } hostname, err := os.Hostname() if err != nil { return nil, fmt.Errorf("couldn't get the hostname: %v", err) } altNames.DNSNames = append(cfg.API.ExternalDNSNames, hostname) altNames.DNSNames = append(altNames.DNSNames, internalAPIServerFQDN...) // then, add all IP addresses we're bound to for _, a := range cfg.API.AdvertiseAddresses { if ip := net.ParseIP(a); ip != nil { altNames.IPs = append(altNames.IPs, ip) } else { return nil, fmt.Errorf("could not parse ip %q", a) } } // and lastly, extract the internal IP address for the API server _, n, err := net.ParseCIDR(cfg.Networking.ServiceSubnet) if err != nil { return nil, fmt.Errorf("error parsing CIDR %q: %v", cfg.Networking.ServiceSubnet, err) } internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(n, 1) if err != nil { return nil, fmt.Errorf("unable to allocate IP address for the API server from the given CIDR (%q) [%v]", &cfg.Networking.ServiceSubnet, err) } altNames.IPs = append(altNames.IPs, internalAPIServerVirtualIP) caKey, caCert, err := newCertificateAuthority() if err != nil { return nil, fmt.Errorf("failure while creating CA keys and certificate [%v]", err) } if err := writeKeysAndCert(pkiPath, "ca", caKey, caCert); err != nil { return nil, fmt.Errorf("failure while saving CA keys and certificate [%v]", err) } fmt.Println("[certificates] Generated Certificate Authority key and certificate.") apiKey, apiCert, err := newServerKeyAndCert(caCert, caKey, altNames) if err != nil { return nil, fmt.Errorf("failure while creating API server keys and certificate [%v]", err) } if err := writeKeysAndCert(pkiPath, "apiserver", apiKey, apiCert); err != nil { return nil, fmt.Errorf("failure while saving API server keys and certificate [%v]", err) } fmt.Println("[certificates] Generated API Server key and certificate") // Generate a private key for service accounts saKey, err := certutil.NewPrivateKey() if err != nil { return nil, fmt.Errorf("failure while creating service account signing keys [%v]", err) } if err := writeKeysAndCert(pkiPath, "sa", saKey, nil); err != nil { return nil, fmt.Errorf("failure while saving service account signing keys [%v]", err) } fmt.Println("[certificates] Generated Service Account signing keys") fmt.Printf("[certificates] Created keys and certificates in %q\n", pkiPath) return caCert, nil }
// Complete fills in any fields not set that are required to have valid data and can be derived // from other fields. If you're going to `ApplyOptions`, do that first. It's mutating the receiver. func (c *Config) Complete() completedConfig { if c.ServiceClusterIPRange == nil || c.ServiceClusterIPRange.IP == nil { defaultNet := "10.0.0.0/24" glog.Warningf("Network range for service cluster IPs is unspecified. Defaulting to %v.", defaultNet) _, serviceClusterIPRange, err := net.ParseCIDR(defaultNet) if err != nil { glog.Fatalf("Unable to parse CIDR: %v", err) } if size := ipallocator.RangeSize(serviceClusterIPRange); size < 8 { glog.Fatalf("The service cluster IP range must be at least %d IP addresses", 8) } c.ServiceClusterIPRange = serviceClusterIPRange } if c.ServiceReadWriteIP == nil { // Select the first valid IP from ServiceClusterIPRange to use as the GenericAPIServer service IP. serviceReadWriteIP, err := ipallocator.GetIndexedIP(c.ServiceClusterIPRange, 1) if err != nil { glog.Fatalf("Failed to generate service read-write IP for GenericAPIServer service: %v", err) } glog.V(4).Infof("Setting GenericAPIServer service IP to %q (read-write).", serviceReadWriteIP) c.ServiceReadWriteIP = serviceReadWriteIP } if c.ServiceNodePortRange.Size == 0 { // TODO: Currently no way to specify an empty range (do we need to allow this?) // We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE) // but then that breaks the strict nestedness of ServiceType. // Review post-v1 c.ServiceNodePortRange = options.DefaultServiceNodePortRange glog.Infof("Node port range unspecified. Defaulting to %v.", c.ServiceNodePortRange) } if len(c.ExternalHost) == 0 && c.PublicAddress != nil { hostAndPort := c.PublicAddress.String() if c.ReadWritePort != 0 { hostAndPort = net.JoinHostPort(hostAndPort, strconv.Itoa(c.ReadWritePort)) } c.ExternalHost = hostAndPort } // All APIs will have the same authentication for now. if c.OpenAPIConfig != nil && c.OpenAPIConfig.SecurityDefinitions != nil { c.OpenAPIConfig.DefaultSecurity = []map[string][]string{} keys := []string{} for k := range *c.OpenAPIConfig.SecurityDefinitions { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { c.OpenAPIConfig.DefaultSecurity = append(c.OpenAPIConfig.DefaultSecurity, map[string][]string{k: {}}) } if c.OpenAPIConfig.CommonResponses == nil { c.OpenAPIConfig.CommonResponses = map[int]spec.Response{} } if _, exists := c.OpenAPIConfig.CommonResponses[http.StatusUnauthorized]; !exists { c.OpenAPIConfig.CommonResponses[http.StatusUnauthorized] = spec.Response{ ResponseProps: spec.ResponseProps{ Description: "Unauthorized", }, } } } return completedConfig{c} }