mirror of
https://github.com/k3s-io/k3s.git
synced 2024-06-07 19:41:36 +00:00
Add missing node name entry to apiserver SAN list
Also honor node-ip when adding the node address to the SAN list, instead of hardcoding the autodetected IP address. Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
This commit is contained in:
parent
74196acaea
commit
cf12a13175
@ -9,7 +9,7 @@ import (
|
|||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
sysnet "net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -31,7 +31,6 @@ import (
|
|||||||
"github.com/rancher/wrangler/pkg/slice"
|
"github.com/rancher/wrangler/pkg/slice"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"k8s.io/apimachinery/pkg/util/json"
|
"k8s.io/apimachinery/pkg/util/json"
|
||||||
"k8s.io/apimachinery/pkg/util/net"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -89,7 +88,7 @@ func Request(path string, info *clientaccess.Info, requester HTTPRequester) ([]b
|
|||||||
return requester(u.String(), clientaccess.GetHTTPClient(info.CACerts), info.Username, info.Password)
|
return requester(u.String(), clientaccess.GetHTTPClient(info.CACerts), info.Username, info.Password)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNodeNamedCrt(nodeName string, nodeIPs []sysnet.IP, nodePasswordFile string) HTTPRequester {
|
func getNodeNamedCrt(nodeName string, nodeIPs []net.IP, nodePasswordFile string) HTTPRequester {
|
||||||
return func(u string, client *http.Client, username, password string) ([]byte, error) {
|
return func(u string, client *http.Client, username, password string) ([]byte, error) {
|
||||||
req, err := http.NewRequest(http.MethodGet, u, nil)
|
req, err := http.NewRequest(http.MethodGet, u, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -169,7 +168,7 @@ func upgradeOldNodePasswordPath(oldNodePasswordFile, newNodePasswordFile string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getServingCert(nodeName string, nodeIPs []sysnet.IP, servingCertFile, servingKeyFile, nodePasswordFile string, info *clientaccess.Info) (*tls.Certificate, error) {
|
func getServingCert(nodeName string, nodeIPs []net.IP, servingCertFile, servingKeyFile, nodePasswordFile string, info *clientaccess.Info) (*tls.Certificate, error) {
|
||||||
servingCert, err := Request("/v1-"+version.Program+"/serving-kubelet.crt", info, getNodeNamedCrt(nodeName, nodeIPs, nodePasswordFile))
|
servingCert, err := Request("/v1-"+version.Program+"/serving-kubelet.crt", info, getNodeNamedCrt(nodeName, nodeIPs, nodePasswordFile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -232,7 +231,7 @@ func splitCertKeyPEM(bytes []byte) (certPem []byte, keyPem []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNodeNamedHostFile(filename, keyFile, nodeName string, nodeIPs []sysnet.IP, nodePasswordFile string, info *clientaccess.Info) error {
|
func getNodeNamedHostFile(filename, keyFile, nodeName string, nodeIPs []net.IP, nodePasswordFile string, info *clientaccess.Info) error {
|
||||||
basename := filepath.Base(filename)
|
basename := filepath.Base(filename)
|
||||||
fileBytes, err := Request("/v1-"+version.Program+"/"+basename, info, getNodeNamedCrt(nodeName, nodeIPs, nodePasswordFile))
|
fileBytes, err := Request("/v1-"+version.Program+"/"+basename, info, getNodeNamedCrt(nodeName, nodeIPs, nodePasswordFile))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -249,42 +248,6 @@ func getNodeNamedHostFile(filename, keyFile, nodeName string, nodeIPs []sysnet.I
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHostnameAndIPs(info cmds.Agent) (string, []sysnet.IP, error) {
|
|
||||||
ips := []sysnet.IP{}
|
|
||||||
if len(info.NodeIP) == 0 {
|
|
||||||
hostIP, err := net.ChooseHostInterface()
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
ips = append(ips, hostIP)
|
|
||||||
} else {
|
|
||||||
for _, hostIP := range info.NodeIP {
|
|
||||||
for _, v := range strings.Split(hostIP, ",") {
|
|
||||||
ip := sysnet.ParseIP(v)
|
|
||||||
if ip == nil {
|
|
||||||
return "", nil, fmt.Errorf("invalid node-ip %s", v)
|
|
||||||
}
|
|
||||||
ips = append(ips, ip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
name := info.NodeName
|
|
||||||
if name == "" {
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
name = hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use lower case hostname to comply with kubernetes constraint:
|
|
||||||
// https://github.com/kubernetes/kubernetes/issues/71140
|
|
||||||
name = strings.ToLower(name)
|
|
||||||
|
|
||||||
return name, ips, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isValidResolvConf(resolvConfFile string) bool {
|
func isValidResolvConf(resolvConfFile string) bool {
|
||||||
file, err := os.Open(resolvConfFile)
|
file, err := os.Open(resolvConfFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -297,7 +260,7 @@ func isValidResolvConf(resolvConfFile string) bool {
|
|||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
ipMatch := nameserver.FindStringSubmatch(scanner.Text())
|
ipMatch := nameserver.FindStringSubmatch(scanner.Text())
|
||||||
if len(ipMatch) == 2 {
|
if len(ipMatch) == 2 {
|
||||||
ip := sysnet.ParseIP(ipMatch[1])
|
ip := net.ParseIP(ipMatch[1])
|
||||||
if ip == nil || !ip.IsGlobalUnicast() {
|
if ip == nil || !ip.IsGlobalUnicast() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -350,9 +313,9 @@ func get(ctx context.Context, envInfo *cmds.Agent, proxy proxy.Proxy) (*config.N
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var flannelIface *sysnet.Interface
|
var flannelIface *net.Interface
|
||||||
if !envInfo.NoFlannel && len(envInfo.FlannelIface) > 0 {
|
if !envInfo.NoFlannel && len(envInfo.FlannelIface) > 0 {
|
||||||
flannelIface, err = sysnet.InterfaceByName(envInfo.FlannelIface)
|
flannelIface, err = net.InterfaceByName(envInfo.FlannelIface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "unable to find interface")
|
return nil, errors.Wrapf(err, "unable to find interface")
|
||||||
}
|
}
|
||||||
@ -384,7 +347,7 @@ func get(ctx context.Context, envInfo *cmds.Agent, proxy proxy.Proxy) (*config.N
|
|||||||
newNodePasswordFile := filepath.Join(nodeConfigPath, "password")
|
newNodePasswordFile := filepath.Join(nodeConfigPath, "password")
|
||||||
upgradeOldNodePasswordPath(oldNodePasswordFile, newNodePasswordFile)
|
upgradeOldNodePasswordPath(oldNodePasswordFile, newNodePasswordFile)
|
||||||
|
|
||||||
nodeName, nodeIPs, err := getHostnameAndIPs(*envInfo)
|
nodeName, nodeIPs, err := util.GetHostnameAndIPs(envInfo.NodeName, envInfo.NodeIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -498,7 +461,7 @@ func get(ctx context.Context, envInfo *cmds.Agent, proxy proxy.Proxy) (*config.N
|
|||||||
|
|
||||||
for _, externalIP := range envInfo.NodeExternalIP {
|
for _, externalIP := range envInfo.NodeExternalIP {
|
||||||
for _, v := range strings.Split(externalIP, ",") {
|
for _, v := range strings.Split(externalIP, ",") {
|
||||||
ip := sysnet.ParseIP(v)
|
ip := net.ParseIP(v)
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return nil, fmt.Errorf("invalid node-external-ip %s", v)
|
return nil, fmt.Errorf("invalid node-external-ip %s", v)
|
||||||
}
|
}
|
||||||
@ -546,7 +509,7 @@ func get(ctx context.Context, envInfo *cmds.Agent, proxy proxy.Proxy) (*config.N
|
|||||||
|
|
||||||
if controlConfig.ClusterIPRange != nil {
|
if controlConfig.ClusterIPRange != nil {
|
||||||
nodeConfig.AgentConfig.ClusterCIDR = controlConfig.ClusterIPRange
|
nodeConfig.AgentConfig.ClusterCIDR = controlConfig.ClusterIPRange
|
||||||
nodeConfig.AgentConfig.ClusterCIDRs = []*sysnet.IPNet{controlConfig.ClusterIPRange}
|
nodeConfig.AgentConfig.ClusterCIDRs = []*net.IPNet{controlConfig.ClusterIPRange}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(controlConfig.ClusterIPRanges) > 0 {
|
if len(controlConfig.ClusterIPRanges) > 0 {
|
||||||
@ -555,7 +518,7 @@ func get(ctx context.Context, envInfo *cmds.Agent, proxy proxy.Proxy) (*config.N
|
|||||||
|
|
||||||
if controlConfig.ServiceIPRange != nil {
|
if controlConfig.ServiceIPRange != nil {
|
||||||
nodeConfig.AgentConfig.ServiceCIDR = controlConfig.ServiceIPRange
|
nodeConfig.AgentConfig.ServiceCIDR = controlConfig.ServiceIPRange
|
||||||
nodeConfig.AgentConfig.ServiceCIDRs = []*sysnet.IPNet{controlConfig.ServiceIPRange}
|
nodeConfig.AgentConfig.ServiceCIDRs = []*net.IPNet{controlConfig.ServiceIPRange}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(controlConfig.ServiceIPRanges) > 0 {
|
if len(controlConfig.ServiceIPRanges) > 0 {
|
||||||
@ -567,7 +530,7 @@ func get(ctx context.Context, envInfo *cmds.Agent, proxy proxy.Proxy) (*config.N
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(controlConfig.ClusterDNSs) == 0 {
|
if len(controlConfig.ClusterDNSs) == 0 {
|
||||||
nodeConfig.AgentConfig.ClusterDNSs = []sysnet.IP{controlConfig.ClusterDNS}
|
nodeConfig.AgentConfig.ClusterDNSs = []net.IP{controlConfig.ClusterDNS}
|
||||||
} else {
|
} else {
|
||||||
nodeConfig.AgentConfig.ClusterDNSs = controlConfig.ClusterDNSs
|
nodeConfig.AgentConfig.ClusterDNSs = controlConfig.ClusterDNSs
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
|
|||||||
serverConfig.ControlConfig.KubeConfigOutput = cfg.KubeConfigOutput
|
serverConfig.ControlConfig.KubeConfigOutput = cfg.KubeConfigOutput
|
||||||
serverConfig.ControlConfig.KubeConfigMode = cfg.KubeConfigMode
|
serverConfig.ControlConfig.KubeConfigMode = cfg.KubeConfigMode
|
||||||
serverConfig.Rootless = cfg.Rootless
|
serverConfig.Rootless = cfg.Rootless
|
||||||
serverConfig.ControlConfig.SANs = knownIPs(cfg.TLSSan)
|
serverConfig.ControlConfig.SANs = cfg.TLSSan
|
||||||
serverConfig.ControlConfig.BindAddress = cfg.BindAddress
|
serverConfig.ControlConfig.BindAddress = cfg.BindAddress
|
||||||
serverConfig.ControlConfig.SupervisorPort = cfg.SupervisorPort
|
serverConfig.ControlConfig.SupervisorPort = cfg.SupervisorPort
|
||||||
serverConfig.ControlConfig.HTTPSPort = cfg.HTTPSPort
|
serverConfig.ControlConfig.HTTPSPort = cfg.HTTPSPort
|
||||||
@ -215,6 +215,18 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
|
|||||||
serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, serverConfig.ControlConfig.AdvertiseIP)
|
serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, serverConfig.ControlConfig.AdvertiseIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that we add the localhost name/ip and node name/ip to the SAN list. This list is shared by the
|
||||||
|
// certs for the supervisor, kube-apiserver cert, and etcd. DNS entries for the in-cluster kubernetes
|
||||||
|
// service endpoint are added later when the certificates are created.
|
||||||
|
nodeName, nodeIPs, err := util.GetHostnameAndIPs(cmds.AgentConfig.NodeName, cmds.AgentConfig.NodeIP)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, "127.0.0.1", "localhost", nodeName)
|
||||||
|
for _, ip := range nodeIPs {
|
||||||
|
serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, ip.String())
|
||||||
|
}
|
||||||
|
|
||||||
// configure ClusterIPRanges
|
// configure ClusterIPRanges
|
||||||
if len(cmds.ServerConfig.ClusterCIDR) == 0 {
|
if len(cmds.ServerConfig.ClusterCIDR) == 0 {
|
||||||
cmds.ServerConfig.ClusterCIDR.Set("10.42.0.0/16")
|
cmds.ServerConfig.ClusterCIDR.Set("10.42.0.0/16")
|
||||||
@ -464,15 +476,6 @@ func validateNetworkConfiguration(serverConfig server.Config) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func knownIPs(ips []string) []string {
|
|
||||||
ips = append(ips, "127.0.0.1")
|
|
||||||
ip, err := utilnet.ChooseHostInterface()
|
|
||||||
if err == nil {
|
|
||||||
ips = append(ips, ip.String())
|
|
||||||
}
|
|
||||||
return ips
|
|
||||||
}
|
|
||||||
|
|
||||||
func getArgValueFromList(searchArg string, argList []string) string {
|
func getArgValueFromList(searchArg string, argList []string) string {
|
||||||
var value string
|
var value string
|
||||||
for _, arg := range argList {
|
for _, arg := range argList {
|
||||||
|
@ -45,7 +45,7 @@ func (c *Cluster) newListener(ctx context.Context) (net.Listener, http.Handler,
|
|||||||
return dynamiclistener.NewListener(tcp, storage, cert, key, dynamiclistener.Config{
|
return dynamiclistener.NewListener(tcp, storage, cert, key, dynamiclistener.Config{
|
||||||
ExpirationDaysCheck: config.CertificateRenewDays,
|
ExpirationDaysCheck: config.CertificateRenewDays,
|
||||||
Organization: []string{version.Program},
|
Organization: []string{version.Program},
|
||||||
SANs: append(c.config.SANs, "localhost", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc."+c.config.ClusterDomain),
|
SANs: append(c.config.SANs, "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc."+c.config.ClusterDomain),
|
||||||
CN: version.Program,
|
CN: version.Program,
|
||||||
TLSConfig: &tls.Config{
|
TLSConfig: &tls.Config{
|
||||||
ClientAuth: tls.RequestClientCert,
|
ClientAuth: tls.RequestClientCert,
|
||||||
|
@ -25,7 +25,6 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1"
|
apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1"
|
||||||
"k8s.io/kubernetes/pkg/controlplane"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -370,14 +369,8 @@ func genServerCerts(config *config.Control, runtime *config.ControlRuntime) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, apiServerServiceIP, err := controlplane.ServiceIPRange(*config.ServiceIPRange)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
altNames := &certutil.AltNames{
|
altNames := &certutil.AltNames{
|
||||||
DNSNames: []string{"localhost", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc." + config.ClusterDomain},
|
DNSNames: []string{"kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc." + config.ClusterDomain},
|
||||||
IPs: []net.IP{apiServerServiceIP},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addSANs(altNames, config.SANs)
|
addSANs(altNames, config.SANs)
|
||||||
@ -402,9 +395,7 @@ func genETCDCerts(config *config.Control, runtime *config.ControlRuntime) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
altNames := &certutil.AltNames{
|
altNames := &certutil.AltNames{}
|
||||||
DNSNames: []string{"localhost"},
|
|
||||||
}
|
|
||||||
addSANs(altNames, config.SANs)
|
addSANs(altNames, config.SANs)
|
||||||
|
|
||||||
if _, err := createClientCertKey(regen, "etcd-server", nil,
|
if _, err := createClientCertKey(regen, "etcd-server", nil,
|
||||||
|
@ -2,8 +2,13 @@ package util
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
apinet "k8s.io/apimachinery/pkg/util/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JoinIPs stringifies and joins a list of IP addresses with commas.
|
// JoinIPs stringifies and joins a list of IP addresses with commas.
|
||||||
@ -85,3 +90,41 @@ func JoinIP6Nets(elems []*net.IPNet) string {
|
|||||||
}
|
}
|
||||||
return strings.Join(strs, ",")
|
return strings.Join(strs, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHostnameAndIPs takes a node name and list of IPs, usually from CLI args.
|
||||||
|
// If set, these are used to return the node's name and addresses. If not set,
|
||||||
|
// the system hostname and primary interface address are returned instead.
|
||||||
|
func GetHostnameAndIPs(name string, nodeIPs cli.StringSlice) (string, []net.IP, error) {
|
||||||
|
ips := []net.IP{}
|
||||||
|
if len(nodeIPs) == 0 {
|
||||||
|
hostIP, err := apinet.ChooseHostInterface()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
ips = append(ips, hostIP)
|
||||||
|
} else {
|
||||||
|
for _, hostIP := range nodeIPs {
|
||||||
|
for _, v := range strings.Split(hostIP, ",") {
|
||||||
|
ip := net.ParseIP(v)
|
||||||
|
if ip == nil {
|
||||||
|
return "", nil, fmt.Errorf("invalid node-ip %s", v)
|
||||||
|
}
|
||||||
|
ips = append(ips, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
hostname, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
name = hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use lower case hostname to comply with kubernetes constraint:
|
||||||
|
// https://github.com/kubernetes/kubernetes/issues/71140
|
||||||
|
name = strings.ToLower(name)
|
||||||
|
|
||||||
|
return name, ips, nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user