From ba240d06119a9de9f546c37f7777d96ccc2e37be Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Sat, 26 Oct 2019 22:53:25 -0700 Subject: [PATCH 1/3] Refactor tokens, bootstrap, and cli args --- manifests/rolebindings.yaml | 50 ++++ pkg/agent/config/config.go | 35 ++- pkg/agent/flannel/setup.go | 21 +- pkg/agent/netpol/network_policy.go | 2 +- pkg/agent/run.go | 120 +++++---- pkg/agent/tunnel/tunnel.go | 49 ++-- pkg/apis/k3s.cattle.io/v1/types.go | 11 - pkg/bootstrap/bootstrap.go | 80 ++++++ pkg/cli/agent/agent.go | 28 +-- pkg/cli/cmds/agent.go | 108 ++++---- pkg/cli/cmds/log.go | 8 +- pkg/cli/cmds/nocluster.go | 7 + pkg/cli/cmds/server.go | 380 ++++++++++++++++------------- pkg/cli/server/server.go | 54 ++-- pkg/clientaccess/clientaccess.go | 52 ++-- pkg/cluster/cluster.go | 48 ++++ pkg/cluster/https.go | 81 ++++++ pkg/cluster/join.go | 74 ++++++ pkg/cluster/nocluster.go | 17 ++ pkg/cluster/router.go | 25 ++ pkg/codegen/main.go | 1 - pkg/daemons/config/types.go | 96 ++++---- pkg/daemons/control/bootstrap.go | 100 -------- pkg/daemons/control/server.go | 237 ++++++++---------- pkg/daemons/control/tunnel.go | 12 +- pkg/datadir/datadir.go | 3 +- pkg/passwd/passwd.go | 151 ++++++++++++ pkg/server/auth.go | 22 +- pkg/server/context.go | 1 - pkg/server/router.go | 91 +++---- pkg/server/server.go | 143 +++++------ pkg/server/types.go | 2 - pkg/token/read.go | 39 +++ 33 files changed, 1292 insertions(+), 856 deletions(-) create mode 100644 pkg/bootstrap/bootstrap.go create mode 100644 pkg/cli/cmds/nocluster.go create mode 100644 pkg/cluster/cluster.go create mode 100644 pkg/cluster/https.go create mode 100644 pkg/cluster/join.go create mode 100644 pkg/cluster/nocluster.go create mode 100644 pkg/cluster/router.go delete mode 100644 pkg/daemons/control/bootstrap.go create mode 100644 pkg/passwd/passwd.go create mode 100644 pkg/token/read.go diff --git a/manifests/rolebindings.yaml b/manifests/rolebindings.yaml index d048eee998..36bc949367 100644 --- a/manifests/rolebindings.yaml +++ b/manifests/rolebindings.yaml @@ -10,3 +10,53 @@ subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: kube-apiserver + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: system:k3s-controller +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - get +- apiGroups: + - "" + resources: + - namespaces + verbs: + - list + - watch +- apiGroups: + - "networking.k8s.io" + resources: + - networkpolicies + verbs: + - list + - watch +- apiGroups: + - "" + resources: + - endpoints + - pods + verbs: + - list + - get + - watch + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: system:k3s-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:k3s-controller +subjects: + - apiGroup: rbac.authorization.k8s.io + kind: User + name: system:k3s-controller diff --git a/pkg/agent/config/config.go b/pkg/agent/config/config.go index 0a001b18c4..1dba940439 100644 --- a/pkg/agent/config/config.go +++ b/pkg/agent/config/config.go @@ -6,7 +6,6 @@ import ( cryptorand "crypto/rand" "crypto/tls" "encoding/hex" - "encoding/pem" "fmt" "io/ioutil" sysnet "net" @@ -27,7 +26,6 @@ import ( "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/net" - "k8s.io/client-go/util/cert" "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" ) @@ -183,17 +181,6 @@ func getHostnameAndIP(info cmds.Agent) (string, string, error) { return name, ip, nil } -func writeKubeConfig(envInfo *cmds.Agent, info clientaccess.Info, tlsCert *tls.Certificate) (string, error) { - os.MkdirAll(envInfo.DataDir, 0700) - kubeConfigPath := filepath.Join(envInfo.DataDir, "kubeconfig.yaml") - info.CACerts = pem.EncodeToMemory(&pem.Block{ - Type: cert.CertificateBlockType, - Bytes: tlsCert.Certificate[1], - }) - - return kubeConfigPath, info.WriteKubeConfig(kubeConfigPath) -} - func isValidResolvConf(resolvConfFile string) bool { file, err := os.Open(resolvConfFile) if err != nil { @@ -293,11 +280,6 @@ func get(envInfo *cmds.Agent) (*config.Node, error) { return nil, err } - kubeconfigNode, err := writeKubeConfig(envInfo, *info, servingCert) - if err != nil { - return nil, err - } - clientKubeletCert := filepath.Join(envInfo.DataDir, "client-kubelet.crt") if err := getNodeNamedHostFile(clientKubeletCert, nodeName, nodePasswordFile, info); err != nil { return nil, err @@ -328,6 +310,21 @@ func get(envInfo *cmds.Agent) (*config.Node, error) { return nil, err } + clientK3sControllerCert := filepath.Join(envInfo.DataDir, "client-k3s-controller.crt") + if err := getHostFile(clientK3sControllerCert, info); err != nil { + return nil, err + } + + clientK3sControllerKey := filepath.Join(envInfo.DataDir, "client-k3s-controller.key") + if err := getHostFile(clientK3sControllerKey, info); err != nil { + return nil, err + } + + kubeconfigK3sController := filepath.Join(envInfo.DataDir, "k3scontroller.kubeconfig") + if err := control.KubeConfig(kubeconfigK3sController, info.URL, serverCAFile, clientK3sControllerCert, clientK3sControllerKey); err != nil { + return nil, err + } + nodeConfig := &config.Node{ Docker: envInfo.Docker, ContainerRuntimeEndpoint: envInfo.ContainerRuntimeEndpoint, @@ -345,9 +342,9 @@ func get(envInfo *cmds.Agent) (*config.Node, error) { nodeConfig.AgentConfig.ResolvConf = locateOrGenerateResolvConf(envInfo) nodeConfig.AgentConfig.ClientCA = clientCAFile nodeConfig.AgentConfig.ListenAddress = "0.0.0.0" - nodeConfig.AgentConfig.KubeConfigNode = kubeconfigNode nodeConfig.AgentConfig.KubeConfigKubelet = kubeconfigKubelet nodeConfig.AgentConfig.KubeConfigKubeProxy = kubeconfigKubeproxy + nodeConfig.AgentConfig.KubeConfigK3sController = kubeconfigK3sController if envInfo.Rootless { nodeConfig.AgentConfig.RootDir = filepath.Join(envInfo.DataDir, "kubelet") } diff --git a/pkg/agent/flannel/setup.go b/pkg/agent/flannel/setup.go index bc354ef92e..d0101da279 100644 --- a/pkg/agent/flannel/setup.go +++ b/pkg/agent/flannel/setup.go @@ -13,8 +13,7 @@ import ( "github.com/rancher/k3s/pkg/daemons/config" "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/clientcmd" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" ) const ( @@ -74,21 +73,11 @@ func Prepare(ctx context.Context, nodeConfig *config.Node) error { return createFlannelConf(nodeConfig) } -func Run(ctx context.Context, nodeConfig *config.Node) error { +func Run(ctx context.Context, nodeConfig *config.Node, nodes v1.NodeInterface) error { nodeName := nodeConfig.AgentConfig.NodeName - restConfig, err := clientcmd.BuildConfigFromFlags("", nodeConfig.AgentConfig.KubeConfigNode) - if err != nil { - return err - } - - client, err := kubernetes.NewForConfig(restConfig) - if err != nil { - return err - } - for { - node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) + node, err := nodes.Get(nodeName, metav1.GetOptions{}) if err == nil && node.Spec.PodCIDR != "" { break } @@ -101,11 +90,11 @@ func Run(ctx context.Context, nodeConfig *config.Node) error { } go func() { - err := flannel(ctx, nodeConfig.FlannelIface, nodeConfig.FlannelConf, nodeConfig.AgentConfig.KubeConfigNode) + err := flannel(ctx, nodeConfig.FlannelIface, nodeConfig.FlannelConf, nodeConfig.AgentConfig.KubeConfigKubelet) logrus.Fatalf("flannel exited: %v", err) }() - return err + return nil } func createCNIConf(dir string) error { diff --git a/pkg/agent/netpol/network_policy.go b/pkg/agent/netpol/network_policy.go index 97eac08a90..65e93c6abe 100644 --- a/pkg/agent/netpol/network_policy.go +++ b/pkg/agent/netpol/network_policy.go @@ -10,7 +10,7 @@ import ( ) func Run(ctx context.Context, nodeConfig *config.Node) error { - restConfig, err := clientcmd.BuildConfigFromFlags("", nodeConfig.AgentConfig.KubeConfigNode) + restConfig, err := clientcmd.BuildConfigFromFlags("", nodeConfig.AgentConfig.KubeConfigK3sController) if err != nil { return err } diff --git a/pkg/agent/run.go b/pkg/agent/run.go index aaf24976c7..7bdb358dbe 100644 --- a/pkg/agent/run.go +++ b/pkg/agent/run.go @@ -9,6 +9,7 @@ import ( "strings" "time" + systemd "github.com/coreos/go-systemd/daemon" "github.com/rancher/k3s/pkg/agent/config" "github.com/rancher/k3s/pkg/agent/containerd" "github.com/rancher/k3s/pkg/agent/flannel" @@ -21,10 +22,11 @@ import ( "github.com/rancher/k3s/pkg/daemons/agent" daemonconfig "github.com/rancher/k3s/pkg/daemons/config" "github.com/rancher/k3s/pkg/rootless" - "github.com/rancher/wrangler-api/pkg/generated/controllers/core" - corev1 "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" - "github.com/rancher/wrangler/pkg/start" "github.com/sirupsen/logrus" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/clientcmd" ) @@ -64,14 +66,18 @@ func run(ctx context.Context, cfg cmds.Agent, lb *loadbalancer.LoadBalancer) err return err } + coreClient, err := coreClient(nodeConfig.AgentConfig.KubeConfigKubelet) + if err != nil { + return err + } if !nodeConfig.NoFlannel { - if err := flannel.Run(ctx, nodeConfig); err != nil { + if err := flannel.Run(ctx, nodeConfig, coreClient.CoreV1().Nodes()); err != nil { return err } } if !nodeConfig.AgentConfig.DisableCCM { - if err := syncAddressesLabels(ctx, &nodeConfig.AgentConfig); err != nil { + if err := syncAddressesLabels(ctx, &nodeConfig.AgentConfig, coreClient.CoreV1().Nodes()); err != nil { return err } } @@ -86,6 +92,15 @@ func run(ctx context.Context, cfg cmds.Agent, lb *loadbalancer.LoadBalancer) err return ctx.Err() } +func coreClient(cfg string) (kubernetes.Interface, error) { + restConfig, err := clientcmd.BuildConfigFromFlags("", cfg) + if err != nil { + return nil, err + } + + return kubernetes.NewForConfig(restConfig) +} + func Run(ctx context.Context, cfg cmds.Agent) error { if err := validate(); err != nil { return err @@ -100,10 +115,6 @@ func Run(ctx context.Context, cfg cmds.Agent) error { cfg.DataDir = filepath.Join(cfg.DataDir, "agent") os.MkdirAll(cfg.DataDir, 0700) - if cfg.ClusterSecret != "" { - cfg.Token = "K10node:" + cfg.ClusterSecret - } - lb, err := loadbalancer.Setup(ctx, cfg) if err != nil { return err @@ -113,7 +124,7 @@ func Run(ctx context.Context, cfg cmds.Agent) error { } for { - tmpFile, err := clientaccess.AgentAccessInfoToTempKubeConfig("", cfg.ServerURL, cfg.Token) + newToken, err := clientaccess.NormalizeAndValidateTokenForUser(cfg.ServerURL, cfg.Token, "node") if err != nil { logrus.Error(err) select { @@ -123,10 +134,11 @@ func Run(ctx context.Context, cfg cmds.Agent) error { } continue } - os.Remove(tmpFile) + cfg.Token = newToken break } + systemd.SdNotify(true, "READY=1\n") return run(ctx, cfg, lb) } @@ -149,73 +161,51 @@ func validate() error { return nil } -func syncAddressesLabels(ctx context.Context, agentConfig *daemonconfig.Agent) error { +func syncAddressesLabels(ctx context.Context, agentConfig *daemonconfig.Agent, nodes v1.NodeInterface) error { for { - nodeController, nodeCache, err := startNodeController(ctx, agentConfig) + node, err := nodes.Get(agentConfig.NodeName, metav1.GetOptions{}) if err != nil { logrus.Infof("Waiting for kubelet to be ready on node %s: %v", agentConfig.NodeName, err) time.Sleep(1 * time.Second) continue } - nodeCached, err := nodeCache.Get(agentConfig.NodeName) - if err != nil { - logrus.Infof("Waiting for kubelet to be ready on node %s: %v", agentConfig.NodeName, err) - time.Sleep(1 * time.Second) - continue - } - node := nodeCached.DeepCopy() - updated := updateLabelMap(ctx, agentConfig, node.Labels) - if updated { - _, err = nodeController.Update(node) - if err == nil { - logrus.Infof("addresses labels has been set succesfully on node: %s", agentConfig.NodeName) - break + + newLabels, update := updateLabelMap(agentConfig, node.Labels) + if update { + node.Labels = newLabels + if _, err := nodes.Update(node); err != nil { + logrus.Infof("Failed to update node %s: %v", agentConfig.NodeName, err) + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(time.Second): + continue + } } - logrus.Infof("Failed to update node %s: %v", agentConfig.NodeName, err) - time.Sleep(1 * time.Second) - continue + logrus.Infof("addresses labels has been set successfully on node: %s", agentConfig.NodeName) + } else { + logrus.Infof("addresses labels has already been set successfully on node: %s", agentConfig.NodeName) } - logrus.Infof("addresses labels has already been set succesfully on node: %s", agentConfig.NodeName) - return nil + + break } + return nil } -func startNodeController(ctx context.Context, agentConfig *daemonconfig.Agent) (corev1.NodeController, corev1.NodeCache, error) { - restConfig, err := clientcmd.BuildConfigFromFlags("", agentConfig.KubeConfigKubelet) - if err != nil { - return nil, nil, err - } - coreFactory := core.NewFactoryFromConfigOrDie(restConfig) - nodeController := coreFactory.Core().V1().Node() - nodeCache := nodeController.Cache() - if err := start.All(ctx, 1, coreFactory); err != nil { - return nil, nil, err +func updateLabelMap(agentConfig *daemonconfig.Agent, nodeLabels map[string]string) (map[string]string, bool) { + result := map[string]string{} + for k, v := range nodeLabels { + result[k] = v } - return nodeController, nodeCache, nil -} + result[InternalIPLabel] = agentConfig.NodeIP + result[HostnameLabel] = agentConfig.NodeName + if agentConfig.NodeExternalIP == "" { + delete(result, ExternalIPLabel) + } else { + result[ExternalIPLabel] = agentConfig.NodeExternalIP + } -func updateLabelMap(ctx context.Context, agentConfig *daemonconfig.Agent, nodeLabels map[string]string) bool { - if nodeLabels == nil { - nodeLabels = make(map[string]string) - } - updated := false - if internalIPLabel, ok := nodeLabels[InternalIPLabel]; !ok || internalIPLabel != agentConfig.NodeIP { - nodeLabels[InternalIPLabel] = agentConfig.NodeIP - updated = true - } - if hostnameLabel, ok := nodeLabels[HostnameLabel]; !ok || hostnameLabel != agentConfig.NodeName { - nodeLabels[HostnameLabel] = agentConfig.NodeName - updated = true - } - nodeExternalIP := agentConfig.NodeExternalIP - if externalIPLabel := nodeLabels[ExternalIPLabel]; externalIPLabel != nodeExternalIP && nodeExternalIP != "" { - nodeLabels[ExternalIPLabel] = nodeExternalIP - updated = true - } else if nodeExternalIP == "" && externalIPLabel != "" { - delete(nodeLabels, ExternalIPLabel) - updated = true - } - return updated + return result, !equality.Semantic.DeepEqual(nodeLabels, result) } diff --git a/pkg/agent/tunnel/tunnel.go b/pkg/agent/tunnel/tunnel.go index c139129557..d219236b29 100644 --- a/pkg/agent/tunnel/tunnel.go +++ b/pkg/agent/tunnel/tunnel.go @@ -3,11 +3,8 @@ package tunnel import ( "context" "crypto/tls" - "crypto/x509" - "encoding/base64" "fmt" "net" - "net/http" "reflect" "sync" "time" @@ -21,8 +18,8 @@ import ( "k8s.io/apimachinery/pkg/fields" watchtypes "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - "k8s.io/client-go/transport" ) var ( @@ -54,12 +51,7 @@ func getAddresses(endpoint *v1.Endpoints) []string { } func Setup(ctx context.Context, config *config.Node, onChange func([]string)) error { - restConfig, err := clientcmd.BuildConfigFromFlags("", config.AgentConfig.KubeConfigNode) - if err != nil { - return err - } - - transportConfig, err := restConfig.TransportConfig() + restConfig, err := clientcmd.BuildConfigFromFlags("", config.AgentConfig.KubeConfigK3sController) if err != nil { return err } @@ -69,6 +61,16 @@ func Setup(ctx context.Context, config *config.Node, onChange func([]string)) er return err } + nodeRestConfig, err := clientcmd.BuildConfigFromFlags("", config.AgentConfig.KubeConfigKubelet) + if err != nil { + return err + } + + tlsConfig, err := rest.TLSConfigFor(nodeRestConfig) + if err != nil { + return err + } + addresses := []string{config.ServerAddress} endpoint, _ := client.CoreV1().Endpoints("default").Get("kubernetes", metav1.GetOptions{}) @@ -84,7 +86,7 @@ func Setup(ctx context.Context, config *config.Node, onChange func([]string)) er wg := &sync.WaitGroup{} for _, address := range addresses { if _, ok := disconnect[address]; !ok { - disconnect[address] = connect(ctx, wg, address, config, transportConfig) + disconnect[address] = connect(ctx, wg, address, tlsConfig) } } @@ -132,7 +134,7 @@ func Setup(ctx context.Context, config *config.Node, onChange func([]string)) er for _, address := range addresses { validEndpoint[address] = true if _, ok := disconnect[address]; !ok { - disconnect[address] = connect(ctx, nil, address, config, transportConfig) + disconnect[address] = connect(ctx, nil, address, tlsConfig) } } @@ -164,25 +166,10 @@ func Setup(ctx context.Context, config *config.Node, onChange func([]string)) er return nil } -func connect(rootCtx context.Context, waitGroup *sync.WaitGroup, address string, config *config.Node, transportConfig *transport.Config) context.CancelFunc { +func connect(rootCtx context.Context, waitGroup *sync.WaitGroup, address string, tlsConfig *tls.Config) context.CancelFunc { wsURL := fmt.Sprintf("wss://%s/v1-k3s/connect", address) - headers := map[string][]string{ - "X-K3s-NodeName": {config.AgentConfig.NodeName}, - } - ws := &websocket.Dialer{} - - if len(config.CACerts) > 0 { - pool := x509.NewCertPool() - pool.AppendCertsFromPEM(config.CACerts) - ws.TLSClientConfig = &tls.Config{ - RootCAs: pool, - } - } - - if transportConfig.Username != "" { - auth := transportConfig.Username + ":" + transportConfig.Password - auth = base64.StdEncoding.EncodeToString([]byte(auth)) - headers["Authorization"] = []string{"Basic " + auth} + ws := &websocket.Dialer{ + TLSClientConfig: tlsConfig, } once := sync.Once{} @@ -194,7 +181,7 @@ func connect(rootCtx context.Context, waitGroup *sync.WaitGroup, address string, go func() { for { - remotedialer.ClientConnect(ctx, wsURL, http.Header(headers), ws, func(proto, address string) bool { + remotedialer.ClientConnect(ctx, wsURL, nil, ws, func(proto, address string) bool { host, port, err := net.SplitHostPort(address) return err == nil && proto == "tcp" && ports[port] && host == "127.0.0.1" }, func(_ context.Context) error { diff --git a/pkg/apis/k3s.cattle.io/v1/types.go b/pkg/apis/k3s.cattle.io/v1/types.go index 50353e7470..d1f1fed6cb 100644 --- a/pkg/apis/k3s.cattle.io/v1/types.go +++ b/pkg/apis/k3s.cattle.io/v1/types.go @@ -1,7 +1,6 @@ package v1 import ( - "github.com/rancher/dynamiclistener" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -9,16 +8,6 @@ import ( // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type ListenerConfig struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Status dynamiclistener.ListenerStatus `json:"status,omitempty"` -} - -// +genclient -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - type Addon struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/pkg/bootstrap/bootstrap.go b/pkg/bootstrap/bootstrap.go new file mode 100644 index 0000000000..832d1a7061 --- /dev/null +++ b/pkg/bootstrap/bootstrap.go @@ -0,0 +1,80 @@ +package bootstrap + +import ( + "encoding/json" + "io" + "io/ioutil" + "net/http" + "os" + "path/filepath" + + "github.com/pkg/errors" + "github.com/rancher/k3s/pkg/daemons/config" +) + +func Handler(bootstrap *config.ControlRuntimeBootstrap) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + rw.Header().Set("Content-Type", "application/json") + Write(rw, bootstrap) + }) +} + +func Write(w io.Writer, bootstrap *config.ControlRuntimeBootstrap) error { + paths, err := objToMap(bootstrap) + if err != nil { + return nil + } + + dataMap := map[string][]byte{} + for pathKey, path := range paths { + if path == "" { + continue + } + data, err := ioutil.ReadFile(path) + if err != nil { + return errors.Wrapf(err, "failed to read %s", path) + } + + dataMap[pathKey] = data + } + + return json.NewEncoder(w).Encode(dataMap) +} + +func Read(r io.Reader, bootstrap *config.ControlRuntimeBootstrap) error { + paths, err := objToMap(bootstrap) + if err != nil { + return err + } + + files := map[string][]byte{} + if err := json.NewDecoder(r).Decode(&files); err != nil { + return err + } + + for pathKey, data := range files { + path, ok := paths[pathKey] + if !ok { + continue + } + + if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { + return errors.Wrapf(err, "failed to mkdir %s", filepath.Dir(path)) + } + + if err := ioutil.WriteFile(path, data, 0600); err != nil { + return errors.Wrapf(err, "failed to write to %s", path) + } + } + + return nil +} + +func objToMap(obj interface{}) (map[string]string, error) { + bytes, err := json.Marshal(obj) + if err != nil { + return nil, err + } + data := map[string]string{} + return data, json.Unmarshal(bytes, &data) +} diff --git a/pkg/cli/agent/agent.go b/pkg/cli/agent/agent.go index bda1df8e35..40c4636a30 100644 --- a/pkg/cli/agent/agent.go +++ b/pkg/cli/agent/agent.go @@ -3,39 +3,18 @@ package agent import ( "context" "fmt" - "io/ioutil" "os" - "strings" - "time" - systemd "github.com/coreos/go-systemd/daemon" "github.com/rancher/k3s/pkg/agent" "github.com/rancher/k3s/pkg/cli/cmds" "github.com/rancher/k3s/pkg/datadir" "github.com/rancher/k3s/pkg/netutil" + "github.com/rancher/k3s/pkg/token" "github.com/rancher/wrangler/pkg/signals" "github.com/sirupsen/logrus" "github.com/urfave/cli" ) -func readToken(path string) (string, error) { - if path == "" { - return "", nil - } - - for { - tokenBytes, err := ioutil.ReadFile(path) - if err == nil { - return strings.TrimSpace(string(tokenBytes)), nil - } else if os.IsNotExist(err) { - logrus.Infof("Waiting for %s to be available\n", path) - time.Sleep(2 * time.Second) - } else { - return "", err - } - } -} - func Run(ctx *cli.Context) error { if err := cmds.InitLogging(); err != nil { return err @@ -45,14 +24,14 @@ func Run(ctx *cli.Context) error { } if cmds.AgentConfig.TokenFile != "" { - token, err := readToken(cmds.AgentConfig.TokenFile) + token, err := token.ReadFile(cmds.AgentConfig.TokenFile) if err != nil { return err } cmds.AgentConfig.Token = token } - if cmds.AgentConfig.Token == "" && cmds.AgentConfig.ClusterSecret == "" { + if cmds.AgentConfig.Token == "" { return fmt.Errorf("--token is required") } @@ -76,7 +55,6 @@ func Run(ctx *cli.Context) error { cfg.DataDir = dataDir contextCtx := signals.SetupSignalHandler(context.Background()) - systemd.SdNotify(true, "READY=1\n") return agent.Run(contextCtx, cfg) } diff --git a/pkg/cli/cmds/agent.go b/pkg/cli/cmds/agent.go index b376009c2a..8f43666476 100644 --- a/pkg/cli/cmds/agent.go +++ b/pkg/cli/cmds/agent.go @@ -17,7 +17,6 @@ type Agent struct { NodeIP string NodeExternalIP string NodeName string - ClusterSecret string PauseImage string Docker bool ContainerRuntimeEndpoint string @@ -44,82 +43,82 @@ var ( AgentConfig Agent NodeIPFlag = cli.StringFlag{ Name: "node-ip,i", - Usage: "(agent) IP address to advertise for node", + Usage: "(agent/networking) IP address to advertise for node", Destination: &AgentConfig.NodeIP, } NodeExternalIPFlag = cli.StringFlag{ Name: "node-external-ip", - Usage: "(agent) External IP address to advertise for node", + Usage: "(agent/networking) External IP address to advertise for node", Destination: &AgentConfig.NodeExternalIP, } NodeNameFlag = cli.StringFlag{ Name: "node-name", - Usage: "(agent) Node name", + Usage: "(agent/node) Node name", EnvVar: "K3S_NODE_NAME", Destination: &AgentConfig.NodeName, } DockerFlag = cli.BoolFlag{ Name: "docker", - Usage: "(agent) Use docker instead of containerd", + Usage: "(agent/runtime) Use docker instead of containerd", Destination: &AgentConfig.Docker, } + CRIEndpointFlag = cli.StringFlag{ + Name: "container-runtime-endpoint", + Usage: "(agent/runtime) Disable embedded containerd and use alternative CRI implementation", + Destination: &AgentConfig.ContainerRuntimeEndpoint, + } + PrivateRegistryFlag = cli.StringFlag{ + Name: "private-registry", + Usage: "(agent/runtime) Private registry configuration file", + Destination: &AgentConfig.PrivateRegistry, + Value: "/etc/rancher/k3s/registries.yaml", + } + PauseImageFlag = cli.StringFlag{ + Name: "pause-image", + Usage: "(agent/runtime) Customized pause image for containerd sandbox", + Destination: &AgentConfig.PauseImage, + } FlannelFlag = cli.BoolFlag{ Name: "no-flannel", - Usage: "(agent) Disable embedded flannel", + Usage: "(deprecated) use --flannel-backend=none", Destination: &AgentConfig.NoFlannel, } FlannelIfaceFlag = cli.StringFlag{ Name: "flannel-iface", - Usage: "(agent) Override default flannel interface", + Usage: "(agent/networking) Override default flannel interface", Destination: &AgentConfig.FlannelIface, } FlannelConfFlag = cli.StringFlag{ Name: "flannel-conf", - Usage: "(agent) (experimental) Override default flannel config file", + Usage: "(agent/networking) Override default flannel config file", Destination: &AgentConfig.FlannelConf, } - CRIEndpointFlag = cli.StringFlag{ - Name: "container-runtime-endpoint", - Usage: "(agent) Disable embedded containerd and use alternative CRI implementation", - Destination: &AgentConfig.ContainerRuntimeEndpoint, - } - PauseImageFlag = cli.StringFlag{ - Name: "pause-image", - Usage: "(agent) Customized pause image for containerd sandbox", - Destination: &AgentConfig.PauseImage, - } ResolvConfFlag = cli.StringFlag{ Name: "resolv-conf", - Usage: "(agent) Kubelet resolv.conf file", + Usage: "(agent/networking) Kubelet resolv.conf file", EnvVar: "K3S_RESOLV_CONF", Destination: &AgentConfig.ResolvConf, } ExtraKubeletArgs = cli.StringSliceFlag{ Name: "kubelet-arg", - Usage: "(agent) Customized flag for kubelet process", + Usage: "(agent/flags) Customized flag for kubelet process", Value: &AgentConfig.ExtraKubeletArgs, } ExtraKubeProxyArgs = cli.StringSliceFlag{ Name: "kube-proxy-arg", - Usage: "(agent) Customized flag for kube-proxy process", + Usage: "(agent/flags) Customized flag for kube-proxy process", Value: &AgentConfig.ExtraKubeProxyArgs, } NodeTaints = cli.StringSliceFlag{ Name: "node-taint", - Usage: "(agent) Registering kubelet with set of taints", + Usage: "(agent/node) Registering kubelet with set of taints", Value: &AgentConfig.Taints, } NodeLabels = cli.StringSliceFlag{ Name: "node-label", - Usage: "(agent) Registering kubelet with set of labels", + Usage: "(agent/node) Registering kubelet with set of labels", Value: &AgentConfig.Labels, } - PrivateRegistryFlag = cli.StringFlag{ - Name: "private-registry", - Usage: "(agent) Private registry configuration file", - Destination: &AgentConfig.PrivateRegistry, - Value: "/etc/rancher/k3s/registries.yaml", - } ) func NewAgentCommand(action func(ctx *cli.Context) error) cli.Command { @@ -135,54 +134,57 @@ func NewAgentCommand(action func(ctx *cli.Context) error) cli.Command { AlsoLogToStderr, cli.StringFlag{ Name: "token,t", - Usage: "Token to use for authentication", + Usage: "(cluster) Token to use for authentication", EnvVar: "K3S_TOKEN", Destination: &AgentConfig.Token, }, cli.StringFlag{ Name: "token-file", - Usage: "Token file to use for authentication", + Usage: "(cluster) Token file to use for authentication", EnvVar: "K3S_TOKEN_FILE", Destination: &AgentConfig.TokenFile, }, cli.StringFlag{ Name: "server,s", - Usage: "Server to connect to", + Usage: "(cluster) Server to connect to", EnvVar: "K3S_URL", Destination: &AgentConfig.ServerURL, }, cli.StringFlag{ Name: "data-dir,d", - Usage: "Folder to hold state", + Usage: "(agent/data) Folder to hold state", Destination: &AgentConfig.DataDir, Value: "/var/lib/rancher/k3s", }, - cli.StringFlag{ - Name: "cluster-secret", - Usage: "Shared secret used to bootstrap a cluster", - Destination: &AgentConfig.ClusterSecret, - EnvVar: "K3S_CLUSTER_SECRET", - }, + NodeNameFlag, + NodeLabels, + NodeTaints, + DockerFlag, + CRIEndpointFlag, + PauseImageFlag, + PrivateRegistryFlag, + NodeIPFlag, + NodeExternalIPFlag, + ResolvConfFlag, + FlannelIfaceFlag, + FlannelConfFlag, + ExtraKubeletArgs, + ExtraKubeProxyArgs, cli.BoolFlag{ Name: "rootless", Usage: "(experimental) Run rootless", Destination: &AgentConfig.Rootless, }, - DockerFlag, + + // Deprecated/hidden below + FlannelFlag, - FlannelIfaceFlag, - FlannelConfFlag, - NodeNameFlag, - NodeIPFlag, - CRIEndpointFlag, - PauseImageFlag, - ResolvConfFlag, - ExtraKubeletArgs, - ExtraKubeProxyArgs, - NodeLabels, - NodeTaints, - PrivateRegistryFlag, - NodeExternalIPFlag, + cli.StringFlag{ + Name: "cluster-secret", + Usage: "(deprecated) use --token", + Destination: &AgentConfig.Token, + EnvVar: "K3S_CLUSTER_SECRET", + }, }, } } diff --git a/pkg/cli/cmds/log.go b/pkg/cli/cmds/log.go index cf86687dd3..3ae6803db5 100644 --- a/pkg/cli/cmds/log.go +++ b/pkg/cli/cmds/log.go @@ -25,22 +25,22 @@ var ( VLevel = cli.IntFlag{ Name: "v", - Usage: "Number for the log level verbosity", + Usage: "(logging) Number for the log level verbosity", Destination: &LogConfig.VLevel, } VModule = cli.StringFlag{ Name: "vmodule", - Usage: "Comma-separated list of pattern=N settings for file-filtered logging", + Usage: "(logging) Comma-separated list of pattern=N settings for file-filtered logging", Destination: &LogConfig.VModule, } LogFile = cli.StringFlag{ Name: "log,l", - Usage: "Log to file", + Usage: "(logging) Log to file", Destination: &LogConfig.LogFile, } AlsoLogToStderr = cli.BoolFlag{ Name: "alsologtostderr", - Usage: "Log to standard error as well as file (if set)", + Usage: "(logging) Log to standard error as well as file (if set)", Destination: &LogConfig.AlsoLogToStderr, } ) diff --git a/pkg/cli/cmds/nocluster.go b/pkg/cli/cmds/nocluster.go new file mode 100644 index 0000000000..946b60f0c4 --- /dev/null +++ b/pkg/cli/cmds/nocluster.go @@ -0,0 +1,7 @@ +// +build !dqlite + +package cmds + +const ( + hideDqlite = true +) diff --git a/pkg/cli/cmds/server.go b/pkg/cli/cmds/server.go index 8d5a85bc84..00481da625 100644 --- a/pkg/cli/cmds/server.go +++ b/pkg/cli/cmds/server.go @@ -9,12 +9,14 @@ import ( type Server struct { ClusterCIDR string - ClusterSecret string + AgentToken string + AgentTokenFile string + Token string + TokenFile string ServiceCIDR string ClusterDNS string ClusterDomain string HTTPSPort int - HTTPPort int DataDir string DisableAgent bool KubeConfigOutput string @@ -26,7 +28,6 @@ type Server struct { ExtraControllerArgs cli.StringSlice ExtraCloudControllerArgs cli.StringSlice Rootless bool - StoreBootstrap bool StorageEndpoint string StorageCAFile string StorageCertFile string @@ -34,10 +35,13 @@ type Server struct { AdvertiseIP string AdvertisePort int DisableScheduler bool + ServerURL string FlannelBackend string DefaultLocalStoragePath string DisableCCM bool DisableNPC bool + ClusterInit bool + ClusterReset bool } var ServerConfig Server @@ -55,190 +59,236 @@ func NewServerCommand(action func(*cli.Context) error) cli.Command { AlsoLogToStderr, cli.StringFlag{ Name: "bind-address", - Usage: "k3s bind address (default: localhost)", + Usage: "(listener) k3s bind address (default: 0.0.0.0)", Destination: &ServerConfig.BindAddress, }, cli.IntFlag{ Name: "https-listen-port", - Usage: "HTTPS listen port", + Usage: "(listener) HTTPS listen port", Value: 6443, Destination: &ServerConfig.HTTPSPort, }, + cli.StringFlag{ + Name: "advertise-address", + Usage: "(listener) IP address that apiserver uses to advertise to members of the cluster (default: node-external-ip/node-ip)", + Destination: &ServerConfig.AdvertiseIP, + }, cli.IntFlag{ - Name: "http-listen-port", - Usage: "HTTP listen port (for /healthz, HTTPS redirect, and port for TLS terminating LB)", - Value: 0, - Destination: &ServerConfig.HTTPPort, + Name: "advertise-port", + Usage: "(listener) Port that apiserver uses to advertise to members of the cluster (default: listen-port)", + Destination: &ServerConfig.AdvertisePort, + }, + cli.StringSliceFlag{ + Name: "tls-san", + Usage: "(listener) Add additional hostname or IP as a Subject Alternative Name in the TLS cert", + Value: &ServerConfig.TLSSan, }, cli.StringFlag{ Name: "data-dir,d", - Usage: "Folder to hold state default /var/lib/rancher/k3s or ${HOME}/.rancher/k3s if not root", + Usage: "(data) Folder to hold state default /var/lib/rancher/k3s or ${HOME}/.rancher/k3s if not root", Destination: &ServerConfig.DataDir, }, + cli.StringFlag{ + Name: "cluster-cidr", + Usage: "(networking) Network CIDR to use for pod IPs", + Destination: &ServerConfig.ClusterCIDR, + Value: "10.42.0.0/16", + }, + cli.StringFlag{ + Name: "service-cidr", + Usage: "(networking) Network CIDR to use for services IPs", + Destination: &ServerConfig.ServiceCIDR, + Value: "10.43.0.0/16", + }, + cli.StringFlag{ + Name: "cluster-dns", + Usage: "(networking) Cluster IP for coredns service. Should be in your service-cidr range (default: 10.43.0.10)", + Destination: &ServerConfig.ClusterDNS, + Value: "", + }, + cli.StringFlag{ + Name: "cluster-domain", + Usage: "(networking) Cluster Domain", + Destination: &ServerConfig.ClusterDomain, + Value: "cluster.local", + }, + cli.StringFlag{ + Name: "flannel-backend", + Usage: fmt.Sprintf("(networking) One of '%s', '%s', '%s', or '%s'", config.FlannelBackendNone, config.FlannelBackendVXLAN, config.FlannelBackendIPSEC, config.FlannelBackendWireguard), + Destination: &ServerConfig.FlannelBackend, + Value: config.FlannelBackendVXLAN, + }, + cli.StringFlag{ + Name: "token,t", + Usage: "(cluster) Shared secret used to join a server or agent to a cluster", + Destination: &ServerConfig.Token, + EnvVar: "K3S_CLUSTER_SECRET,K3S_TOKEN", + }, + cli.StringFlag{ + Name: "token-file", + Usage: "(cluster) File containing the cluster-secret/token", + Destination: &ServerConfig.TokenFile, + EnvVar: "K3S_TOKEN_FILE", + }, + cli.StringFlag{ + Name: "agent-token", + Usage: "(cluster) Shared secret used to join agents to the cluster, but not agents", + Destination: &ServerConfig.AgentToken, + EnvVar: "K3S_AGENT_TOKEN", + }, + cli.StringFlag{ + Name: "agent-token-file", + Usage: "(cluster) File containing the agent secret", + Destination: &ServerConfig.AgentTokenFile, + EnvVar: "K3S_AGENT_TOKEN_FILE", + }, + cli.StringFlag{ + Name: "server,s", + Usage: "(cluster) Server to connect to, used to join a cluster", + EnvVar: "K3S_URL", + Destination: &ServerConfig.ServerURL, + }, + cli.BoolFlag{ + Name: "new-cluster", + Hidden: hideDqlite, + Usage: "(cluster) Initialize new cluster master", + EnvVar: "K3S_CLUSTER_INIT", + Destination: &ServerConfig.ClusterInit, + }, + cli.BoolFlag{ + Name: "reset-cluster", + Hidden: hideDqlite, + Usage: "(cluster) Forget all peers and become a single cluster new cluster master", + EnvVar: "K3S_CLUSTER_RESET", + Destination: &ServerConfig.ClusterReset, + }, + cli.StringFlag{ + Name: "write-kubeconfig,o", + Usage: "(client) Write kubeconfig for admin client to this file", + Destination: &ServerConfig.KubeConfigOutput, + EnvVar: "K3S_KUBECONFIG_OUTPUT", + }, + cli.StringFlag{ + Name: "write-kubeconfig-mode", + Usage: "(client) Write kubeconfig with this mode", + Destination: &ServerConfig.KubeConfigMode, + EnvVar: "K3S_KUBECONFIG_MODE", + }, + cli.StringSliceFlag{ + Name: "kube-apiserver-arg", + Usage: "(flags) Customized flag for kube-apiserver process", + Value: &ServerConfig.ExtraAPIArgs, + }, + cli.StringSliceFlag{ + Name: "kube-scheduler-arg", + Usage: "(flags) Customized flag for kube-scheduler process", + Value: &ServerConfig.ExtraSchedulerArgs, + }, + cli.StringSliceFlag{ + Name: "kube-controller-manager-arg", + Usage: "(flags) Customized flag for kube-controller-manager process", + Value: &ServerConfig.ExtraControllerArgs, + }, + cli.StringSliceFlag{ + Name: "kube-cloud-controller-manager-arg", + Usage: "(flags) Customized flag for kube-cloud-controller-manager process", + Value: &ServerConfig.ExtraCloudControllerArgs, + }, + cli.StringFlag{ + Name: "storage-endpoint", + Usage: "(db) Specify etcd, Mysql, Postgres, or Sqlite (default) data source name", + Destination: &ServerConfig.StorageEndpoint, + EnvVar: "K3S_STORAGE_ENDPOINT", + }, + cli.StringFlag{ + Name: "storage-cafile", + Usage: "(db) SSL Certificate Authority file used to secure storage backend communication", + Destination: &ServerConfig.StorageCAFile, + EnvVar: "K3S_STORAGE_CAFILE", + }, + cli.StringFlag{ + Name: "storage-certfile", + Usage: "(db) SSL certification file used to secure storage backend communication", + Destination: &ServerConfig.StorageCertFile, + EnvVar: "K3S_STORAGE_CERTFILE", + }, + cli.StringFlag{ + Name: "storage-keyfile", + Usage: "(db) SSL key file used to secure storage backend communication", + Destination: &ServerConfig.StorageKeyFile, + EnvVar: "K3S_STORAGE_KEYFILE", + }, + cli.StringFlag{ + Name: "default-local-storage-path", + Usage: "(storage) Default local storage path for local provisioner storage class", + Destination: &ServerConfig.DefaultLocalStoragePath, + }, + cli.StringSliceFlag{ + Name: "no-deploy", + Usage: "(components) Do not deploy packaged components (valid items: coredns, servicelb, traefik, local-storage)", + }, + cli.BoolFlag{ + Name: "disable-scheduler", + Usage: "(components) Disable Kubernetes default scheduler", + Destination: &ServerConfig.DisableScheduler, + }, + cli.BoolFlag{ + Name: "disable-cloud-controller", + Usage: "(components) Disable k3s default cloud controller manager", + Destination: &ServerConfig.DisableCCM, + }, + cli.BoolFlag{ + Name: "disable-network-policy", + Usage: "(components) Disable k3s default network policy controller", + Destination: &ServerConfig.DisableNPC, + }, + NodeNameFlag, + NodeLabels, + NodeTaints, + DockerFlag, + CRIEndpointFlag, + PauseImageFlag, + PrivateRegistryFlag, + NodeIPFlag, + NodeExternalIPFlag, + ResolvConfFlag, + FlannelIfaceFlag, + FlannelConfFlag, + ExtraKubeletArgs, + ExtraKubeProxyArgs, + cli.BoolFlag{ + Name: "rootless", + Usage: "(experimental) Run rootless", + Destination: &ServerConfig.Rootless, + }, + + // Hidden/Deprecated flags below + + FlannelFlag, + cli.StringFlag{ + Name: "cluster-secret", + Usage: "(deprecated) use --token", + Destination: &ServerConfig.Token, + EnvVar: "K3S_CLUSTER_SECRET", + }, cli.BoolFlag{ Name: "disable-agent", Usage: "Do not run a local agent and register a local kubelet", Hidden: true, Destination: &ServerConfig.DisableAgent, }, - cli.StringFlag{ - Name: "cluster-cidr", - Usage: "Network CIDR to use for pod IPs", - Destination: &ServerConfig.ClusterCIDR, - Value: "10.42.0.0/16", - }, - cli.StringFlag{ - Name: "cluster-secret", - Usage: "Shared secret used to bootstrap a cluster", - Destination: &ServerConfig.ClusterSecret, - EnvVar: "K3S_CLUSTER_SECRET", - }, - cli.StringFlag{ - Name: "service-cidr", - Usage: "Network CIDR to use for services IPs", - Destination: &ServerConfig.ServiceCIDR, - Value: "10.43.0.0/16", - }, - cli.StringFlag{ - Name: "cluster-dns", - Usage: "Cluster IP for coredns service. Should be in your service-cidr range", - Destination: &ServerConfig.ClusterDNS, - Value: "", - }, - cli.StringFlag{ - Name: "cluster-domain", - Usage: "Cluster Domain", - Destination: &ServerConfig.ClusterDomain, - Value: "cluster.local", + cli.StringSliceFlag{ + Hidden: true, + Name: "kube-controller-arg", + Usage: "(flags) Customized flag for kube-controller-manager process", + Value: &ServerConfig.ExtraControllerArgs, }, cli.StringSliceFlag{ - Name: "no-deploy", - Usage: "Do not deploy packaged components (valid items: coredns, servicelb, traefik)", + Hidden: true, + Name: "kube-cloud-controller-arg", + Usage: "(flags) Customized flag for kube-cloud-controller-manager process", + Value: &ServerConfig.ExtraCloudControllerArgs, }, - cli.StringFlag{ - Name: "write-kubeconfig,o", - Usage: "Write kubeconfig for admin client to this file", - Destination: &ServerConfig.KubeConfigOutput, - EnvVar: "K3S_KUBECONFIG_OUTPUT", - }, - cli.StringFlag{ - Name: "write-kubeconfig-mode", - Usage: "Write kubeconfig with this mode", - Destination: &ServerConfig.KubeConfigMode, - EnvVar: "K3S_KUBECONFIG_MODE", - }, - cli.StringSliceFlag{ - Name: "tls-san", - Usage: "Add additional hostname or IP as a Subject Alternative Name in the TLS cert", - Value: &ServerConfig.TLSSan, - }, - cli.StringSliceFlag{ - Name: "kube-apiserver-arg", - Usage: "Customized flag for kube-apiserver process", - Value: &ServerConfig.ExtraAPIArgs, - }, - cli.StringSliceFlag{ - Name: "kube-scheduler-arg", - Usage: "Customized flag for kube-scheduler process", - Value: &ServerConfig.ExtraSchedulerArgs, - }, - cli.StringSliceFlag{ - Name: "kube-controller-arg", - Usage: "Customized flag for kube-controller-manager process", - Value: &ServerConfig.ExtraControllerArgs, - }, - cli.StringSliceFlag{ - Name: "kube-cloud-controller-arg", - Usage: "Customized flag for kube-cloud-controller-manager process", - Value: &ServerConfig.ExtraCloudControllerArgs, - }, - cli.BoolFlag{ - Name: "rootless", - Usage: "(experimental) Run rootless", - Destination: &ServerConfig.Rootless, - }, - cli.BoolFlag{ - Name: "bootstrap-save", - Usage: "(experimental) Save bootstrap information in the storage endpoint", - Hidden: true, - Destination: &ServerConfig.StoreBootstrap, - }, - cli.StringFlag{ - Name: "storage-endpoint", - Usage: "Specify etcd, Mysql, Postgres, or Sqlite (default) data source name", - Destination: &ServerConfig.StorageEndpoint, - EnvVar: "K3S_STORAGE_ENDPOINT", - }, - cli.StringFlag{ - Name: "storage-cafile", - Usage: "SSL Certificate Authority file used to secure storage backend communication", - Destination: &ServerConfig.StorageCAFile, - EnvVar: "K3S_STORAGE_CAFILE", - }, - cli.StringFlag{ - Name: "storage-certfile", - Usage: "SSL certification file used to secure storage backend communication", - Destination: &ServerConfig.StorageCertFile, - EnvVar: "K3S_STORAGE_CERTFILE", - }, - cli.StringFlag{ - Name: "storage-keyfile", - Usage: "SSL key file used to secure storage backend communication", - Destination: &ServerConfig.StorageKeyFile, - EnvVar: "K3S_STORAGE_KEYFILE", - }, - cli.StringFlag{ - Name: "advertise-address", - Usage: "IP address that apiserver uses to advertise to members of the cluster", - Destination: &ServerConfig.AdvertiseIP, - }, - cli.IntFlag{ - Name: "advertise-port", - Usage: "Port that apiserver uses to advertise to members of the cluster", - Value: 0, - Destination: &ServerConfig.AdvertisePort, - }, - cli.BoolFlag{ - Name: "disable-scheduler", - Usage: "Disable Kubernetes default scheduler", - Destination: &ServerConfig.DisableScheduler, - }, - cli.BoolFlag{ - Name: "disable-cloud-controller", - Usage: "Disable k3s default cloud controller manager", - Destination: &ServerConfig.DisableCCM, - }, - cli.BoolFlag{ - Name: "disable-network-policy", - Usage: "Disable k3s default network policy controller", - Destination: &ServerConfig.DisableNPC, - }, - cli.StringFlag{ - Name: "flannel-backend", - Usage: fmt.Sprintf("(experimental) One of '%s', '%s', '%s', or '%s'", config.FlannelBackendNone, config.FlannelBackendVXLAN, config.FlannelBackendIPSEC, config.FlannelBackendWireguard), - Destination: &ServerConfig.FlannelBackend, - Value: config.FlannelBackendVXLAN, - }, - cli.StringFlag{ - Name: "default-local-storage-path", - Usage: "Default local storage path for local provisioner storage class", - Destination: &ServerConfig.DefaultLocalStoragePath, - }, - NodeIPFlag, - NodeNameFlag, - DockerFlag, - FlannelFlag, - FlannelIfaceFlag, - FlannelConfFlag, - CRIEndpointFlag, - PauseImageFlag, - ResolvConfFlag, - ExtraKubeletArgs, - ExtraKubeProxyArgs, - NodeLabels, - NodeTaints, - PrivateRegistryFlag, - NodeExternalIPFlag, }, } } diff --git a/pkg/cli/server/server.go b/pkg/cli/server/server.go index 22dcff2a2c..9699471485 100644 --- a/pkg/cli/server/server.go +++ b/pkg/cli/server/server.go @@ -16,6 +16,7 @@ import ( "github.com/rancher/k3s/pkg/netutil" "github.com/rancher/k3s/pkg/rootless" "github.com/rancher/k3s/pkg/server" + "github.com/rancher/k3s/pkg/token" "github.com/rancher/wrangler/pkg/signals" "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -56,23 +57,28 @@ func run(app *cli.Context, cfg *cmds.Server) error { serverConfig := server.Config{} serverConfig.DisableAgent = cfg.DisableAgent - serverConfig.ControlConfig.ClusterSecret = cfg.ClusterSecret + serverConfig.ControlConfig.Token = cfg.Token + serverConfig.ControlConfig.AgentToken = cfg.AgentToken + serverConfig.ControlConfig.JoinURL = cfg.ServerURL + if cfg.AgentTokenFile != "" { + serverConfig.ControlConfig.AgentToken, err = token.ReadFile(cfg.AgentTokenFile) + if err != nil { + return err + } + } + if cfg.TokenFile != "" { + serverConfig.ControlConfig.Token, err = token.ReadFile(cfg.TokenFile) + if err != nil { + return err + } + } serverConfig.ControlConfig.DataDir = cfg.DataDir serverConfig.ControlConfig.KubeConfigOutput = cfg.KubeConfigOutput serverConfig.ControlConfig.KubeConfigMode = cfg.KubeConfigMode serverConfig.ControlConfig.NoScheduler = cfg.DisableScheduler serverConfig.Rootless = cfg.Rootless - serverConfig.TLSConfig.HTTPSPort = cfg.HTTPSPort - serverConfig.TLSConfig.HTTPPort = cfg.HTTPPort - for _, san := range knownIPs(cfg.TLSSan) { - addr := net2.ParseIP(san) - if addr != nil { - serverConfig.TLSConfig.KnownIPs = append(serverConfig.TLSConfig.KnownIPs, san) - } else { - serverConfig.TLSConfig.Domains = append(serverConfig.TLSConfig.Domains, san) - } - } - serverConfig.TLSConfig.BindAddress = cfg.BindAddress + serverConfig.ControlConfig.SANs = knownIPs(cfg.TLSSan) + serverConfig.ControlConfig.BindAddress = cfg.BindAddress serverConfig.ControlConfig.HTTPSPort = cfg.HTTPSPort serverConfig.ControlConfig.ExtraAPIArgs = cfg.ExtraAPIArgs serverConfig.ControlConfig.ExtraControllerArgs = cfg.ExtraControllerArgs @@ -84,21 +90,25 @@ func run(app *cli.Context, cfg *cmds.Server) error { serverConfig.ControlConfig.Storage.KeyFile = cfg.StorageKeyFile serverConfig.ControlConfig.AdvertiseIP = cfg.AdvertiseIP serverConfig.ControlConfig.AdvertisePort = cfg.AdvertisePort - serverConfig.ControlConfig.BootstrapReadOnly = !cfg.StoreBootstrap serverConfig.ControlConfig.FlannelBackend = cfg.FlannelBackend serverConfig.ControlConfig.ExtraCloudControllerArgs = cfg.ExtraCloudControllerArgs serverConfig.ControlConfig.DisableCCM = cfg.DisableCCM serverConfig.ControlConfig.DisableNPC = cfg.DisableNPC + serverConfig.ControlConfig.ClusterInit = cfg.ClusterInit + serverConfig.ControlConfig.ClusterReset = cfg.ClusterReset if cmds.AgentConfig.FlannelIface != "" && cmds.AgentConfig.NodeIP == "" { cmds.AgentConfig.NodeIP = netutil.GetIPFromInterface(cmds.AgentConfig.FlannelIface) } + if serverConfig.ControlConfig.AdvertiseIP == "" && cmds.AgentConfig.NodeExternalIP != "" { + serverConfig.ControlConfig.AdvertiseIP = cmds.AgentConfig.NodeExternalIP + } if serverConfig.ControlConfig.AdvertiseIP == "" && cmds.AgentConfig.NodeIP != "" { serverConfig.ControlConfig.AdvertiseIP = cmds.AgentConfig.NodeIP } if serverConfig.ControlConfig.AdvertiseIP != "" { - serverConfig.TLSConfig.KnownIPs = append(serverConfig.TLSConfig.KnownIPs, serverConfig.ControlConfig.AdvertiseIP) + serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, serverConfig.ControlConfig.AdvertiseIP) } _, serverConfig.ControlConfig.ClusterIPRange, err = net2.ParseCIDR(cfg.ClusterCIDR) @@ -114,7 +124,7 @@ func run(app *cli.Context, cfg *cmds.Server) error { if err != nil { return err } - serverConfig.TLSConfig.KnownIPs = append(serverConfig.TLSConfig.KnownIPs, apiServerServiceIP.String()) + serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, apiServerServiceIP.String()) // If cluster-dns CLI arg is not set, we set ClusterDNS address to be ServiceCIDR network + 10, // i.e. when you set service-cidr to 192.168.0.0/16 and don't provide cluster-dns, it will be set to 192.168.0.10 @@ -160,8 +170,7 @@ func run(app *cli.Context, cfg *cmds.Server) error { os.Unsetenv("NOTIFY_SOCKET") ctx := signals.SetupSignalHandler(context.Background()) - certs, err := server.StartServer(ctx, &serverConfig) - if err != nil { + if err := server.StartServer(ctx, &serverConfig); err != nil { return err } @@ -175,12 +184,17 @@ func run(app *cli.Context, cfg *cmds.Server) error { <-ctx.Done() return nil } - ip := serverConfig.TLSConfig.BindAddress + + ip := serverConfig.ControlConfig.BindAddress if ip == "" { ip = "127.0.0.1" } - url := fmt.Sprintf("https://%s:%d", ip, serverConfig.TLSConfig.HTTPSPort) - token := server.FormatToken(serverConfig.ControlConfig.Runtime.NodeToken, certs) + + url := fmt.Sprintf("https://%s:%d", ip, serverConfig.ControlConfig.HTTPSPort) + token, err := server.FormatToken(serverConfig.ControlConfig.Runtime.AgentToken, serverConfig.ControlConfig.Runtime.ServerCA) + if err != nil { + return err + } agentConfig := cmds.AgentConfig agentConfig.Debug = app.GlobalBool("bool") diff --git a/pkg/clientaccess/clientaccess.go b/pkg/clientaccess/clientaccess.go index 8fcaf5ad44..1d403c19f8 100644 --- a/pkg/clientaccess/clientaccess.go +++ b/pkg/clientaccess/clientaccess.go @@ -9,7 +9,6 @@ import ( "io/ioutil" "net/http" "net/url" - "os" "strings" "github.com/pkg/errors" @@ -35,21 +34,6 @@ type clientToken struct { password string } -func AgentAccessInfoToTempKubeConfig(tempDir, server, token string) (string, error) { - f, err := ioutil.TempFile(tempDir, "tmp-") - if err != nil { - return "", err - } - if err := f.Close(); err != nil { - return "", err - } - err = accessInfoToKubeConfig(f.Name(), server, token) - if err != nil { - os.Remove(f.Name()) - } - return f.Name(), err -} - func AgentAccessInfoToKubeConfig(destFile, server, token string) error { return accessInfoToKubeConfig(destFile, server, token) } @@ -62,6 +46,10 @@ type Info struct { Token string `json:"token,omitempty"` } +func (i *Info) ToToken() string { + return fmt.Sprintf("K10%s::%s:%s", hashCA(i.CACerts), i.username, i.password) +} + func (i *Info) WriteKubeConfig(destFile string) error { return clientcmd.WriteToFile(*i.KubeConfig(), destFile) } @@ -98,6 +86,22 @@ func (i *Info) KubeConfig() *clientcmdapi.Config { return config } +func NormalizeAndValidateTokenForUser(server, token, user string) (string, error) { + if !strings.HasPrefix(token, "K10") { + token = "K10::" + user + ":" + token + } + info, err := ParseAndValidateToken(server, token) + if err != nil { + return "", err + } + + if info.username != user { + info.username = user + } + + return info.ToToken(), nil +} + func ParseAndValidateToken(server, token string) (*Info, error) { url, err := url.Parse(server) if err != nil { @@ -132,13 +136,17 @@ func ParseAndValidateToken(server, token string) (*Info, error) { return nil, err } - return &Info{ + i := &Info{ URL: url.String(), CACerts: cacerts, username: parsedToken.username, password: parsedToken.password, Token: token, - }, nil + } + + // normalize token + i.Token = i.ToToken() + return i, nil } func accessInfoToKubeConfig(destFile, server, token string) error { @@ -164,11 +172,15 @@ func validateCACerts(cacerts []byte, hash string) (bool, string, string) { return true, "", "" } - digest := sha256.Sum256([]byte(cacerts)) - newHash := hex.EncodeToString(digest[:]) + newHash := hashCA(cacerts) return hash == newHash, hash, newHash } +func hashCA(cacerts []byte) string { + digest := sha256.Sum256(cacerts) + return hex.EncodeToString(digest[:]) +} + func ParseUsernamePassword(token string) (string, string, bool) { parsed, err := parseToken(token) if err != nil { diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go new file mode 100644 index 0000000000..d5372dae0c --- /dev/null +++ b/pkg/cluster/cluster.go @@ -0,0 +1,48 @@ +package cluster + +import ( + "context" + + "github.com/rancher/k3s/pkg/clientaccess" + "github.com/rancher/k3s/pkg/daemons/config" +) + +type Cluster struct { + token string + clientAccessInfo *clientaccess.Info + config *config.Control + runtime *config.ControlRuntime + db interface{} +} + +func (c *Cluster) Start(ctx context.Context) error { + join, err := c.shouldJoin() + if err != nil { + return err + } + + if join { + if err := c.join(); err != nil { + return err + } + } + + if err := c.startClusterAndHTTPS(ctx); err != nil { + return err + } + + if join { + if err := c.postJoin(ctx); err != nil { + return err + } + } + + return c.joined() +} + +func New(config *config.Control) *Cluster { + return &Cluster{ + config: config, + runtime: config.Runtime, + } +} diff --git a/pkg/cluster/https.go b/pkg/cluster/https.go new file mode 100644 index 0000000000..d57c7f7af5 --- /dev/null +++ b/pkg/cluster/https.go @@ -0,0 +1,81 @@ +package cluster + +import ( + "context" + "crypto/tls" + "net" + "net/http" + "path/filepath" + + "github.com/rancher/dynamiclistener" + "github.com/rancher/dynamiclistener/factory" + "github.com/rancher/dynamiclistener/storage/file" + "github.com/rancher/dynamiclistener/storage/kubernetes" + "github.com/rancher/dynamiclistener/storage/memory" + "github.com/rancher/k3s/pkg/daemons/config" + "github.com/rancher/wrangler-api/pkg/generated/controllers/core" + "github.com/sirupsen/logrus" +) + +func (c *Cluster) newListener(ctx context.Context) (net.Listener, http.Handler, error) { + tcp, err := dynamiclistener.NewTCPListener(c.config.BindAddress, c.config.HTTPSPort) + if err != nil { + return nil, nil, err + } + + cert, key, err := factory.LoadCerts(c.runtime.ServerCA, c.runtime.ServerCAKey) + if err != nil { + return nil, nil, err + } + + storage := tlsStorage(ctx, c.config.DataDir, c.runtime) + return dynamiclistener.NewListener(tcp, storage, cert, key, dynamiclistener.Config{ + CN: "k3s", + Organization: []string{"k3s"}, + TLSConfig: tls.Config{ + ClientAuth: tls.RequestClientCert, + }, + SANs: c.config.SANs, + }) +} + +func (c *Cluster) startClusterAndHTTPS(ctx context.Context) error { + l, handler, err := c.newListener(ctx) + if err != nil { + return err + } + + handler, err = c.getHandler(handler) + if err != nil { + return err + } + + l, handler, err = c.initClusterDB(ctx, l, handler) + if err != nil { + return err + } + + server := http.Server{ + Handler: handler, + } + + go func() { + err := server.Serve(l) + logrus.Fatalf("server stopped: %v", err) + }() + + go func() { + <-ctx.Done() + server.Shutdown(context.Background()) + }() + + return nil +} + +func tlsStorage(ctx context.Context, dataDir string, runtime *config.ControlRuntime) dynamiclistener.TLSStorage { + fileStorage := file.New(filepath.Join(dataDir, "tls/dynamic-cert.json")) + cache := memory.NewBacked(fileStorage) + return kubernetes.New(ctx, func() *core.Factory { + return runtime.Core + }, "kube-system", "k3s-serving", cache) +} diff --git a/pkg/cluster/join.go b/pkg/cluster/join.go new file mode 100644 index 0000000000..99d1bdecdf --- /dev/null +++ b/pkg/cluster/join.go @@ -0,0 +1,74 @@ +package cluster + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + + "github.com/rancher/k3s/pkg/bootstrap" + "github.com/rancher/k3s/pkg/clientaccess" + "github.com/sirupsen/logrus" +) + +func (c *Cluster) shouldJoin() (bool, error) { + if c.config.JoinURL == "" { + return false, nil + } + + stamp := filepath.Join(c.config.DataDir, "db/joined") + if _, err := os.Stat(stamp); err == nil { + logrus.Info("Already joined to cluster, not rejoining") + return false, nil + } + + if c.config.Token == "" { + return false, fmt.Errorf("K3S_TOKEN is required to join a cluster") + } + + return true, nil +} + +func (c *Cluster) joined() error { + if err := os.MkdirAll(filepath.Dir(c.joinStamp()), 0700); err != nil { + return err + } + + if _, err := os.Stat(c.joinStamp()); err == nil { + return nil + } + + f, err := os.Create(c.joinStamp()) + if err != nil { + return err + } + + return f.Close() +} + +func (c *Cluster) join() error { + c.runtime.Cluster.Join = true + + token, err := clientaccess.NormalizeAndValidateTokenForUser(c.config.JoinURL, c.config.Token, "server") + if err != nil { + return err + } + c.token = token + + info, err := clientaccess.ParseAndValidateToken(c.config.JoinURL, token) + if err != nil { + return err + } + c.clientAccessInfo = info + + content, err := clientaccess.Get("/v1-k3s/server-bootstrap", info) + if err != nil { + return err + } + + return bootstrap.Read(bytes.NewBuffer(content), &c.runtime.ControlRuntimeBootstrap) +} + +func (c *Cluster) joinStamp() string { + return filepath.Join(c.config.DataDir, "db/joined") +} diff --git a/pkg/cluster/nocluster.go b/pkg/cluster/nocluster.go new file mode 100644 index 0000000000..ce5029156a --- /dev/null +++ b/pkg/cluster/nocluster.go @@ -0,0 +1,17 @@ +// +build !dqlite + +package cluster + +import ( + "context" + "net" + "net/http" +) + +func (c *Cluster) initClusterDB(ctx context.Context, l net.Listener, handler http.Handler) (net.Listener, http.Handler, error) { + return l, handler, nil +} + +func (c *Cluster) postJoin(ctx context.Context) error { + return nil +} diff --git a/pkg/cluster/router.go b/pkg/cluster/router.go new file mode 100644 index 0000000000..48b14b94ee --- /dev/null +++ b/pkg/cluster/router.go @@ -0,0 +1,25 @@ +package cluster + +import ( + "net/http" +) + +func (c *Cluster) getHandler(handler http.Handler) (http.Handler, error) { + next := c.router() + + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + handler.ServeHTTP(rw, req) + next.ServeHTTP(rw, req) + }), nil +} + +func (c *Cluster) router() http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + if c.runtime.Handler == nil { + http.Error(rw, "starting", http.StatusServiceUnavailable) + return + } + + c.runtime.Handler.ServeHTTP(rw, req) + }) +} diff --git a/pkg/codegen/main.go b/pkg/codegen/main.go index 45101cb9d9..5d802b1665 100644 --- a/pkg/codegen/main.go +++ b/pkg/codegen/main.go @@ -70,7 +70,6 @@ func main() { Groups: map[string]args.Group{ "k3s.cattle.io": { Types: []interface{}{ - v1.ListenerConfig{}, v1.Addon{}, }, GenerateTypes: true, diff --git a/pkg/daemons/config/types.go b/pkg/daemons/config/types.go index 655dc816cd..8c41740c33 100644 --- a/pkg/daemons/config/types.go +++ b/pkg/daemons/config/types.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/rancher/kine/pkg/endpoint" - + "github.com/rancher/wrangler-api/pkg/generated/controllers/core" "k8s.io/apiserver/pkg/authentication/authenticator" ) @@ -47,40 +47,36 @@ type Containerd struct { } type Agent struct { - NodeName string - ClientKubeletCert string - ClientKubeletKey string - ClientKubeProxyCert string - ClientKubeProxyKey string - ServingKubeletCert string - ServingKubeletKey string - ClusterCIDR net.IPNet - ClusterDNS net.IP - ClusterDomain string - ResolvConf string - RootDir string - KubeConfigNode string - KubeConfigKubelet string - KubeConfigKubeProxy string - NodeIP string - NodeExternalIP string - RuntimeSocket string - ListenAddress string - ClientCA string - CNIBinDir string - CNIConfDir string - ExtraKubeletArgs []string - ExtraKubeProxyArgs []string - PauseImage string - CNIPlugin bool - NodeTaints []string - NodeLabels []string - IPSECPSK string - StrongSwanDir string - PrivateRegistry string - DisableCCM bool - DisableNPC bool - Rootless bool + NodeName string + ServingKubeletCert string + ServingKubeletKey string + ClusterCIDR net.IPNet + ClusterDNS net.IP + ClusterDomain string + ResolvConf string + RootDir string + KubeConfigKubelet string + KubeConfigKubeProxy string + KubeConfigK3sController string + NodeIP string + NodeExternalIP string + RuntimeSocket string + ListenAddress string + ClientCA string + CNIBinDir string + CNIConfDir string + ExtraKubeletArgs []string + ExtraKubeProxyArgs []string + PauseImage string + CNIPlugin bool + NodeTaints []string + NodeLabels []string + IPSECPSK string + StrongSwanDir string + PrivateRegistry string + DisableCCM bool + DisableNPC bool + Rootless bool } type Control struct { @@ -88,7 +84,8 @@ type Control struct { AdvertiseIP string ListenPort int HTTPSPort int - ClusterSecret string + AgentToken string + Token string ClusterIPRange *net.IPNet ServiceIPRange *net.IPNet ClusterDNS net.IP @@ -98,19 +95,24 @@ type Control struct { KubeConfigMode string DataDir string Skips []string - BootstrapReadOnly bool Storage endpoint.Config NoScheduler bool ExtraAPIArgs []string ExtraControllerArgs []string - ExtraSchedulerAPIArgs []string ExtraCloudControllerArgs []string + ExtraSchedulerAPIArgs []string NoLeaderElect bool + JoinURL string FlannelBackend string IPSECPSK string DefaultLocalStoragePath string DisableCCM bool DisableNPC bool + ClusterInit bool + ClusterReset bool + + BindAddress string + SANs []string Runtime *ControlRuntime `json:"-"` } @@ -124,9 +126,6 @@ type ControlRuntimeBootstrap struct { PasswdFile string RequestHeaderCA string RequestHeaderCAKey string - ClientKubeletKey string - ClientKubeProxyKey string - ServingKubeletKey string IPSECKey string } @@ -145,8 +144,10 @@ type ControlRuntime struct { ServingKubeAPICert string ServingKubeAPIKey string + ServingKubeletKey string ClientToken string - NodeToken string + ServerToken string + AgentToken string Handler http.Handler Tunnel http.Handler Authenticator authenticator.Request @@ -161,8 +162,19 @@ type ControlRuntime struct { ClientSchedulerCert string ClientSchedulerKey string ClientKubeProxyCert string + ClientKubeProxyKey string + ClientKubeletKey string ClientCloudControllerCert string ClientCloudControllerKey string + ClientK3sControllerCert string + ClientK3sControllerKey string + + Cluster ClusterConfig + Core *core.Factory +} + +type ClusterConfig struct { + Join bool } type ArgString []string diff --git a/pkg/daemons/control/bootstrap.go b/pkg/daemons/control/bootstrap.go deleted file mode 100644 index 8dedee6c2a..0000000000 --- a/pkg/daemons/control/bootstrap.go +++ /dev/null @@ -1,100 +0,0 @@ -package control - -import ( - "context" - "encoding/json" - "io/ioutil" - "os" - "path/filepath" - - "github.com/pkg/errors" - "github.com/rancher/k3s/pkg/daemons/config" - "github.com/rancher/kine/pkg/client" - "github.com/sirupsen/logrus" -) - -const ( - k3sRuntimeEtcdPath = "/k3s/runtime" -) - -// fetchBootstrapData copies the bootstrap data (certs, keys, passwords) -// from etcd to individual files specified by cfg.Runtime. -func fetchBootstrapData(ctx context.Context, cfg *config.Control, c client.Client) error { - logrus.Info("Fetching bootstrap data from etcd") - gr, err := c.Get(ctx, k3sRuntimeEtcdPath) - if err != nil { - return err - } - if gr.Modified == 0 { - return nil - } - - paths, err := objToMap(&cfg.Runtime.ControlRuntimeBootstrap) - if err != nil { - return err - } - - files := map[string][]byte{} - if err := json.Unmarshal(gr.Data, &files); err != nil { - return err - } - - for pathKey, data := range files { - path, ok := paths[pathKey] - if !ok { - continue - } - - if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { - return errors.Wrapf(err, "failed to mkdir %s", filepath.Dir(path)) - } - - if err := ioutil.WriteFile(path, data, 0700); err != nil { - return errors.Wrapf(err, "failed to write to %s", path) - } - } - - return nil -} - -// storeBootstrapData copies the bootstrap data in the opposite direction to -// fetchBootstrapData. -func storeBootstrapData(ctx context.Context, cfg *config.Control, client client.Client) error { - if cfg.BootstrapReadOnly { - return nil - } - - paths, err := objToMap(&cfg.Runtime.ControlRuntimeBootstrap) - if err != nil { - return nil - } - - dataMap := map[string][]byte{} - for pathKey, path := range paths { - if path == "" { - continue - } - data, err := ioutil.ReadFile(path) - if err != nil { - return errors.Wrapf(err, "failed to read %s", path) - } - - dataMap[pathKey] = data - } - - bytes, err := json.Marshal(dataMap) - if err != nil { - return err - } - - return client.Put(ctx, k3sRuntimeEtcdPath, bytes) -} - -func objToMap(obj interface{}) (map[string]string, error) { - bytes, err := json.Marshal(obj) - if err != nil { - return nil, err - } - data := map[string]string{} - return data, json.Unmarshal(bytes, &data) -} diff --git a/pkg/daemons/control/server.go b/pkg/daemons/control/server.go index d7a7d655ff..40999f6aad 100644 --- a/pkg/daemons/control/server.go +++ b/pkg/daemons/control/server.go @@ -3,13 +3,9 @@ package control import ( "context" "crypto" - cryptorand "crypto/rand" "crypto/x509" - "encoding/csv" - "encoding/hex" "fmt" "html/template" - "io" "io/ioutil" "math/rand" "net" @@ -21,11 +17,14 @@ import ( "strings" "time" - certutil "github.com/rancher/dynamiclistener/cert" // registering k3s cloud provider _ "github.com/rancher/k3s/pkg/cloudprovider" + + certutil "github.com/rancher/dynamiclistener/cert" + "github.com/rancher/k3s/pkg/cluster" "github.com/rancher/k3s/pkg/daemons/config" - "github.com/rancher/kine/pkg/client" + "github.com/rancher/k3s/pkg/passwd" + "github.com/rancher/k3s/pkg/token" "github.com/rancher/kine/pkg/endpoint" "github.com/rancher/wrangler-api/pkg/generated/controllers/rbac" "github.com/sirupsen/logrus" @@ -121,6 +120,10 @@ func controllerManager(cfg *config.Control, runtime *config.ControlRuntime) { "cluster-signing-cert-file": runtime.ServerCA, "cluster-signing-key-file": runtime.ServerCAKey, } + offset := cfg.HTTPSPort - 6443 + if offset > 0 { + argsMap["port"] = strconv.Itoa(10252 + offset) + } if cfg.NoLeaderElect { argsMap["leader-elect"] = "false" } @@ -143,6 +146,10 @@ func scheduler(cfg *config.Control, runtime *config.ControlRuntime) { "bind-address": "127.0.0.1", "secure-port": "0", } + offset := cfg.HTTPSPort - 6443 + if offset > 0 { + argsMap["port"] = strconv.Itoa(10251 + offset) + } if cfg.NoLeaderElect { argsMap["leader-elect"] = "false" } @@ -291,6 +298,8 @@ func prepare(ctx context.Context, config *config.Control, runtime *config.Contro runtime.ClientKubeAPIKey = path.Join(config.DataDir, "tls", "client-kube-apiserver.key") runtime.ClientKubeProxyCert = path.Join(config.DataDir, "tls", "client-kube-proxy.crt") runtime.ClientKubeProxyKey = path.Join(config.DataDir, "tls", "client-kube-proxy.key") + runtime.ClientK3sControllerCert = path.Join(config.DataDir, "tls", "client-k3s-controller.crt") + runtime.ClientK3sControllerKey = path.Join(config.DataDir, "tls", "client-k3s-controller.key") runtime.ServingKubeAPICert = path.Join(config.DataDir, "tls", "serving-kube-apiserver.crt") runtime.ServingKubeAPIKey = path.Join(config.DataDir, "tls", "serving-kube-apiserver.key") @@ -301,20 +310,14 @@ func prepare(ctx context.Context, config *config.Control, runtime *config.Contro runtime.ClientAuthProxyCert = path.Join(config.DataDir, "tls", "client-auth-proxy.crt") runtime.ClientAuthProxyKey = path.Join(config.DataDir, "tls", "client-auth-proxy.key") - etcdClient, err := prepareStorageBackend(ctx, config) - if err != nil { - return err - } - defer etcdClient.Close() - - if err := fetchBootstrapData(ctx, config, etcdClient); err != nil { - return err - } - if err := genCerts(config, runtime); err != nil { return err } + if err := cluster.New(config).Start(ctx); err != nil { + return err + } + if err := genServiceAccount(runtime); err != nil { return err } @@ -327,124 +330,44 @@ func prepare(ctx context.Context, config *config.Control, runtime *config.Contro return err } - if err := storeBootstrapData(ctx, config, etcdClient); err != nil { + if err := prepareStorageBackend(ctx, config); err != nil { return err } return readTokens(runtime) } -func prepareStorageBackend(ctx context.Context, config *config.Control) (client.Client, error) { +func prepareStorageBackend(ctx context.Context, config *config.Control) error { etcdConfig, err := endpoint.Listen(ctx, config.Storage) if err != nil { - return nil, err + return err } config.Storage.Config = etcdConfig.TLSConfig config.Storage.Endpoint = strings.Join(etcdConfig.Endpoints, ",") config.NoLeaderElect = !etcdConfig.LeaderElect - return client.New(etcdConfig) -} - -func readTokenFile(passwdFile string) (map[string]string, error) { - f, err := os.Open(passwdFile) - if err != nil { - return nil, err - } - defer f.Close() - - reader := csv.NewReader(f) - reader.FieldsPerRecord = -1 - - tokens := map[string]string{} - - for { - record, err := reader.Read() - if err == io.EOF { - break - } - if err != nil { - return nil, err - } - if len(record) < 2 { - continue - } - tokens[record[1]] = record[0] - } - return tokens, nil + return nil } func readTokens(runtime *config.ControlRuntime) error { - tokens, err := readTokenFile(runtime.PasswdFile) + tokens, err := passwd.Read(runtime.PasswdFile) if err != nil { return err } - if nodeToken, ok := tokens["node"]; ok { - runtime.NodeToken = "node:" + nodeToken + if nodeToken, ok := tokens.Pass("node"); ok { + runtime.AgentToken = "node:" + nodeToken } - if clientToken, ok := tokens["admin"]; ok { + if serverToken, ok := tokens.Pass("server"); ok { + runtime.AgentToken = "server:" + serverToken + } + if clientToken, ok := tokens.Pass("admin"); ok { runtime.ClientToken = "admin:" + clientToken } return nil } -func ensureNodeToken(config *config.Control, runtime *config.ControlRuntime) error { - if config.ClusterSecret == "" { - return nil - } - - f, err := os.Open(runtime.PasswdFile) - if err != nil { - return err - } - defer f.Close() - - records := [][]string{} - reader := csv.NewReader(f) - for { - record, err := reader.Read() - if err == io.EOF { - break - } - if err != nil { - return err - } - if len(record) < 3 { - return fmt.Errorf("password file '%s' must have at least 3 columns (password, user name, user uid), found %d", runtime.PasswdFile, len(record)) - } - if record[1] == "node" { - if record[0] == config.ClusterSecret { - return nil - } - record[0] = config.ClusterSecret - } - records = append(records, record) - } - - f.Close() - return WritePasswords(runtime.PasswdFile, records) -} - -func WritePasswords(passwdFile string, records [][]string) error { - out, err := os.Create(passwdFile + ".tmp") - if err != nil { - return err - } - defer out.Close() - - if err := out.Chmod(0600); err != nil { - return err - } - - if err := csv.NewWriter(out).WriteAll(records); err != nil { - return err - } - - return os.Rename(passwdFile+".tmp", passwdFile) -} - func genEncryptedNetworkInfo(controlConfig *config.Control, runtime *config.ControlRuntime) error { if s, err := os.Stat(runtime.IPSECKey); err == nil && s.Size() > 0 { psk, err := ioutil.ReadFile(runtime.IPSECKey) @@ -455,7 +378,7 @@ func genEncryptedNetworkInfo(controlConfig *config.Control, runtime *config.Cont return nil } - psk, err := getToken(ipsecTokenSize) + psk, err := token.Random(ipsecTokenSize) if err != nil { return err } @@ -468,42 +391,71 @@ func genEncryptedNetworkInfo(controlConfig *config.Control, runtime *config.Cont return nil } -func genUsers(config *config.Control, runtime *config.ControlRuntime) error { - if s, err := os.Stat(runtime.PasswdFile); err == nil && s.Size() > 0 { - return ensureNodeToken(config, runtime) +func migratePassword(p *passwd.Passwd) error { + server, _ := p.Pass("server") + node, _ := p.Pass("node") + if server == "" && node != "" { + return p.EnsureUser("server", "k3s:server", node) } - - adminToken, err := getToken(userTokenSize) - if err != nil { - return err - } - systemToken, err := getToken(userTokenSize) - if err != nil { - return err - } - nodeToken, err := getToken(userTokenSize) - if err != nil { - return err - } - - if config.ClusterSecret != "" { - nodeToken = config.ClusterSecret - } - - return WritePasswords(runtime.PasswdFile, [][]string{ - {adminToken, "admin", "admin", "system:masters"}, - {systemToken, "system", "system", "system:masters"}, - {nodeToken, "node", "node", "system:masters"}, - }) + return nil } -func getToken(size int) (string, error) { - token := make([]byte, size, size) - _, err := cryptorand.Read(token) - if err != nil { - return "", err +func getServerPass(passwd *passwd.Passwd, config *config.Control) (string, error) { + var ( + err error + ) + + serverPass := config.Token + if serverPass == "" { + serverPass, _ = passwd.Pass("server") } - return hex.EncodeToString(token), err + if serverPass == "" { + serverPass, err = token.Random(16) + if err != nil { + return "", err + } + } + + return serverPass, nil +} + +func getNodePass(config *config.Control, serverPass string) string { + if config.AgentToken == "" { + return serverPass + } + return config.AgentToken +} + +func genUsers(config *config.Control, runtime *config.ControlRuntime) error { + passwd, err := passwd.Read(runtime.PasswdFile) + if err != nil { + return err + } + + if err := migratePassword(passwd); err != nil { + return err + } + + serverPass, err := getServerPass(passwd, config) + if err != nil { + return err + } + + nodePass := getNodePass(config, serverPass) + + if err := passwd.EnsureUser("admin", "system:masters", ""); err != nil { + return err + } + + if err := passwd.EnsureUser("node", "k3s:agent", nodePass); err != nil { + return err + } + + if err := passwd.EnsureUser("server", "k3s:server", serverPass); err != nil { + return err + } + + return passwd.Write(runtime.PasswdFile) } func genCerts(config *config.Control, runtime *config.ControlRuntime) error { @@ -578,7 +530,10 @@ func genClientCerts(config *config.Control, runtime *config.ControlRuntime) erro } } - if _, err = factory("system:kube-proxy", []string{"system:nodes"}, runtime.ClientKubeProxyCert, runtime.ClientKubeProxyKey); err != nil { + if _, err = factory("system:kube-proxy", nil, runtime.ClientKubeProxyCert, runtime.ClientKubeProxyKey); err != nil { + return err + } + if _, err = factory("system:k3s-controller", nil, runtime.ClientK3sControllerCert, runtime.ClientK3sControllerKey); err != nil { return err } diff --git a/pkg/daemons/control/tunnel.go b/pkg/daemons/control/tunnel.go index a304c4dd3d..6e1d591ac0 100644 --- a/pkg/daemons/control/tunnel.go +++ b/pkg/daemons/control/tunnel.go @@ -4,6 +4,7 @@ import ( "context" "net" "net/http" + "strings" "time" "github.com/rancher/remotedialer" @@ -37,14 +38,9 @@ func authorizer(req *http.Request) (clientKey string, authed bool, err error) { return "", false, nil } - if user.GetName() != "node" { - return "", false, nil + if strings.HasPrefix(user.GetName(), "system:node:") { + return strings.TrimPrefix(user.GetName(), "system:node:"), true, nil } - nodeName := req.Header.Get("X-K3s-NodeName") - if nodeName == "" { - return "", false, nil - } - - return nodeName, true, nil + return "", false, nil } diff --git a/pkg/datadir/datadir.go b/pkg/datadir/datadir.go index 0e80d3fb9c..298998d872 100644 --- a/pkg/datadir/datadir.go +++ b/pkg/datadir/datadir.go @@ -2,6 +2,7 @@ package datadir import ( "os" + "path/filepath" "github.com/pkg/errors" "github.com/rancher/wrangler/pkg/resolvehome" @@ -32,5 +33,5 @@ func LocalHome(dataDir string, forceLocal bool) (string, error) { return "", errors.Wrapf(err, "resolving %s", dataDir) } - return dataDir, nil + return filepath.Abs(dataDir) } diff --git a/pkg/passwd/passwd.go b/pkg/passwd/passwd.go new file mode 100644 index 0000000000..097a78dac6 --- /dev/null +++ b/pkg/passwd/passwd.go @@ -0,0 +1,151 @@ +package passwd + +import ( + "encoding/csv" + "fmt" + "io" + "os" + "strings" + + "github.com/rancher/k3s/pkg/token" +) + +type entry struct { + pass string + role string +} + +type Passwd struct { + changed bool + names map[string]entry +} + +func Read(file string) (*Passwd, error) { + result := &Passwd{ + names: map[string]entry{}, + } + + f, err := os.Open(file) + if err != nil { + if os.IsNotExist(err) { + return result, nil + } + return nil, err + } + defer f.Close() + + reader := csv.NewReader(f) + reader.FieldsPerRecord = -1 + for { + record, err := reader.Read() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + if len(record) < 3 { + return nil, fmt.Errorf("password file '%s' must have at least 3 columns (password, user name, user uid), found %d", file, len(record)) + } + e := entry{ + pass: record[0], + } + if len(record) > 3 { + e.role = record[3] + } + result.names[record[1]] = e + } + + return result, nil +} + +func (p *Passwd) Check(name, pass string) (matches bool, exists bool) { + e, ok := p.names[name] + if !ok { + return false, false + } + return e.pass == pass, true +} + +func (p *Passwd) EnsureUser(name, role, passwd string) error { + tokenPrefix := "::" + name + ":" + idx := strings.Index(passwd, tokenPrefix) + if idx > 0 && strings.HasPrefix(passwd, "K10") { + passwd = passwd[idx+len(tokenPrefix):] + } + + if e, ok := p.names[name]; ok { + if passwd != "" && e.pass != passwd { + p.changed = true + e.pass = passwd + } + + if e.role != role { + p.changed = true + e.role = role + } + + p.names[name] = e + return nil + } + + if passwd == "" { + token, err := token.Random(16) + if err != nil { + return err + } + passwd = token + } + + p.changed = true + p.names[name] = entry{ + pass: passwd, + role: role, + } + + return nil +} + +func (p *Passwd) Pass(name string) (string, bool) { + e, ok := p.names[name] + if !ok { + return "", false + } + return e.pass, true +} + +func (p *Passwd) Write(passwdFile string) error { + if !p.changed { + return nil + } + + var records [][]string + for name, e := range p.names { + records = append(records, []string{ + e.pass, + name, + name, + e.role, + }) + } + + return writePasswords(passwdFile, records) +} + +func writePasswords(passwdFile string, records [][]string) error { + out, err := os.Create(passwdFile + ".tmp") + if err != nil { + return err + } + defer out.Close() + + if err := out.Chmod(0600); err != nil { + return err + } + + if err := csv.NewWriter(out).WriteAll(records); err != nil { + return err + } + + return os.Rename(passwdFile+".tmp", passwdFile) +} diff --git a/pkg/server/auth.go b/pkg/server/auth.go index e0cb0a0d6d..34126f438f 100644 --- a/pkg/server/auth.go +++ b/pkg/server/auth.go @@ -9,9 +9,21 @@ import ( "k8s.io/apiserver/pkg/endpoints/request" ) -func doAuth(serverConfig *config.Control, next http.Handler, rw http.ResponseWriter, req *http.Request) { +func hasRole(mustRoles []string, roles []string) bool { + for _, check := range roles { + for _, role := range mustRoles { + if role == check { + return true + } + } + } + return false +} + +func doAuth(roles []string, serverConfig *config.Control, next http.Handler, rw http.ResponseWriter, req *http.Request) { if serverConfig == nil || serverConfig.Runtime.Authenticator == nil { - next.ServeHTTP(rw, req) + logrus.Errorf("authenticate not initialized") + rw.WriteHeader(http.StatusUnauthorized) return } @@ -22,7 +34,7 @@ func doAuth(serverConfig *config.Control, next http.Handler, rw http.ResponseWri return } - if !ok || resp.User.GetName() != "node" { + if !ok || !hasRole(roles, resp.User.GetGroups()) { rw.WriteHeader(http.StatusUnauthorized) return } @@ -32,10 +44,10 @@ func doAuth(serverConfig *config.Control, next http.Handler, rw http.ResponseWri next.ServeHTTP(rw, req) } -func authMiddleware(serverConfig *config.Control) mux.MiddlewareFunc { +func authMiddleware(serverConfig *config.Control, roles ...string) mux.MiddlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - doAuth(serverConfig, next, rw, req) + doAuth(roles, serverConfig, next, rw, req) }) } } diff --git a/pkg/server/context.go b/pkg/server/context.go index 9c65f19e36..eec39b39e3 100644 --- a/pkg/server/context.go +++ b/pkg/server/context.go @@ -62,7 +62,6 @@ func crds(ctx context.Context, config *rest.Config) error { } factory.BatchCreateCRDs(ctx, crd.NamespacedTypes( - "ListenerConfig.k3s.cattle.io/v1", "Addon.k3s.cattle.io/v1", "HelmChart.helm.cattle.io/v1")...) diff --git a/pkg/server/router.go b/pkg/server/router.go index e9cb680596..83ed3e06f0 100644 --- a/pkg/server/router.go +++ b/pkg/server/router.go @@ -3,70 +3,68 @@ package server import ( "crypto" "crypto/x509" - "encoding/csv" "errors" "fmt" - "io" "io/ioutil" "net" "net/http" - "os" "path/filepath" "strconv" "strings" "github.com/gorilla/mux" certutil "github.com/rancher/dynamiclistener/cert" + "github.com/rancher/k3s/pkg/bootstrap" "github.com/rancher/k3s/pkg/daemons/config" - "github.com/rancher/k3s/pkg/daemons/control" + "github.com/rancher/k3s/pkg/passwd" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/json" ) const ( - jsonMediaType = "application/json" - binaryMediaType = "application/octet-stream" - pbMediaType = "application/com.github.proto-openapi.spec.v2@v1.0+protobuf" - openapiPrefix = "openapi." - staticURL = "/static/" + staticURL = "/static/" ) -type CACertsGetter func() (string, error) - -func router(serverConfig *config.Control, tunnel http.Handler, cacertsGetter CACertsGetter) http.Handler { +func router(serverConfig *config.Control, tunnel http.Handler, ca []byte) http.Handler { authed := mux.NewRouter() - authed.Use(authMiddleware(serverConfig)) + authed.Use(authMiddleware(serverConfig, "k3s:agent")) authed.NotFoundHandler = serverConfig.Runtime.Handler - authed.Path("/v1-k3s/connect").Handler(tunnel) authed.Path("/v1-k3s/serving-kubelet.crt").Handler(servingKubeletCert(serverConfig)) authed.Path("/v1-k3s/serving-kubelet.key").Handler(fileHandler(serverConfig.Runtime.ServingKubeletKey)) authed.Path("/v1-k3s/client-kubelet.crt").Handler(clientKubeletCert(serverConfig)) authed.Path("/v1-k3s/client-kubelet.key").Handler(fileHandler(serverConfig.Runtime.ClientKubeletKey)) authed.Path("/v1-k3s/client-kube-proxy.crt").Handler(fileHandler(serverConfig.Runtime.ClientKubeProxyCert)) authed.Path("/v1-k3s/client-kube-proxy.key").Handler(fileHandler(serverConfig.Runtime.ClientKubeProxyKey)) + authed.Path("/v1-k3s/client-k3s-controller.crt").Handler(fileHandler(serverConfig.Runtime.ClientK3sControllerCert)) + authed.Path("/v1-k3s/client-k3s-controller.key").Handler(fileHandler(serverConfig.Runtime.ClientK3sControllerKey)) authed.Path("/v1-k3s/client-ca.crt").Handler(fileHandler(serverConfig.Runtime.ClientCA)) authed.Path("/v1-k3s/server-ca.crt").Handler(fileHandler(serverConfig.Runtime.ServerCA)) authed.Path("/v1-k3s/config").Handler(configHandler(serverConfig)) + nodeAuthed := mux.NewRouter() + nodeAuthed.Use(authMiddleware(serverConfig, "system:nodes")) + nodeAuthed.Path("/v1-k3s/connect").Handler(tunnel) + nodeAuthed.NotFoundHandler = authed + + serverAuthed := mux.NewRouter() + serverAuthed.Use(authMiddleware(serverConfig, "k3s:server")) + serverAuthed.NotFoundHandler = nodeAuthed + serverAuthed.Path("/v1-k3s/server-bootstrap").Handler(bootstrap.Handler(&serverConfig.Runtime.ControlRuntimeBootstrap)) + staticDir := filepath.Join(serverConfig.DataDir, "static") router := mux.NewRouter() - router.NotFoundHandler = authed + router.NotFoundHandler = serverAuthed router.PathPrefix(staticURL).Handler(serveStatic(staticURL, staticDir)) - router.Path("/cacerts").Handler(cacerts(cacertsGetter)) + router.Path("/cacerts").Handler(cacerts(ca)) router.Path("/ping").Handler(ping()) return router } -func cacerts(getter CACertsGetter) http.Handler { +func cacerts(ca []byte) http.Handler { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - content, err := getter() - if err != nil { - resp.WriteHeader(http.StatusInternalServerError) - resp.Write([]byte(err.Error())) - } resp.Header().Set("content-type", "text/plain") - resp.Write([]byte(content)) + resp.Write(ca) }) } @@ -242,38 +240,19 @@ func sendError(err error, resp http.ResponseWriter, status ...int) { resp.Write([]byte(err.Error())) } -func ensureNodePassword(passwdFile, nodeName, passwd string) error { - records := [][]string{} - - if _, err := os.Stat(passwdFile); !os.IsNotExist(err) { - f, err := os.Open(passwdFile) - if err != nil { - return err - } - defer f.Close() - reader := csv.NewReader(f) - for { - record, err := reader.Read() - if err == io.EOF { - break - } - if err != nil { - return err - } - if len(record) < 2 { - return fmt.Errorf("password file '%s' must have at least 2 columns (password, nodeName), found %d", passwdFile, len(record)) - } - if record[1] == nodeName { - if record[0] == passwd { - return nil - } - return fmt.Errorf("Node password validation failed for '%s', using passwd file '%s'", nodeName, passwdFile) - } - records = append(records, record) - } - f.Close() +func ensureNodePassword(passwdFile, nodeName, pass string) error { + passwd, err := passwd.Read(passwdFile) + if err != nil { + return err } - - records = append(records, []string{passwd, nodeName}) - return control.WritePasswords(passwdFile, records) + match, exists := passwd.Check(nodeName, pass) + if exists { + if !match { + return fmt.Errorf("Node password validation failed for '%s', using passwd file '%s'", nodeName, passwdFile) + } + return nil + } + // If user doesn't exist we save this password for future validation + passwd.EnsureUser(nodeName, "", pass) + return passwd.Write(passwdFile) } diff --git a/pkg/server/server.go b/pkg/server/server.go index 0243a26b74..2913c13b5a 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -14,7 +14,6 @@ import ( "time" "github.com/pkg/errors" - "github.com/rancher/dynamiclistener" "github.com/rancher/helm-controller/pkg/helm" "github.com/rancher/k3s/pkg/clientaccess" "github.com/rancher/k3s/pkg/daemons/config" @@ -25,10 +24,11 @@ import ( "github.com/rancher/k3s/pkg/rootlessports" "github.com/rancher/k3s/pkg/servicelb" "github.com/rancher/k3s/pkg/static" - "github.com/rancher/k3s/pkg/tls" + v1 "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" "github.com/rancher/wrangler/pkg/leader" "github.com/rancher/wrangler/pkg/resolvehome" "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/net" ) @@ -39,79 +39,67 @@ func resolveDataDir(dataDir string) (string, error) { return filepath.Join(dataDir, "server"), err } -func StartServer(ctx context.Context, config *Config) (string, error) { +func StartServer(ctx context.Context, config *Config) error { if err := setupDataDirAndChdir(&config.ControlConfig); err != nil { - return "", err + return err } if err := setNoProxyEnv(&config.ControlConfig); err != nil { - return "", err + return err } if err := control.Server(ctx, &config.ControlConfig); err != nil { - return "", errors.Wrap(err, "starting kubernetes") + return errors.Wrap(err, "starting kubernetes") } - certs, err := startWrangler(ctx, config) - if err != nil { - return "", errors.Wrap(err, "starting tls server") + if err := startWrangler(ctx, config); err != nil { + return errors.Wrap(err, "starting tls server") } - ip := net2.ParseIP(config.TLSConfig.BindAddress) + ip := net2.ParseIP(config.ControlConfig.BindAddress) if ip == nil { - ip, err = net.ChooseHostInterface() - if err != nil { + hostIP, err := net.ChooseHostInterface() + if err == nil { + ip = hostIP + } else { ip = net2.ParseIP("127.0.0.1") } } - printTokens(certs, ip.String(), &config.TLSConfig, &config.ControlConfig) - writeKubeConfig(certs, &config.TLSConfig, config) + if err := printTokens(ip.String(), &config.ControlConfig); err != nil { + return err + } - return certs, nil + return writeKubeConfig(config.ControlConfig.Runtime.ServerCA, config) } -func startWrangler(ctx context.Context, config *Config) (string, error) { +func startWrangler(ctx context.Context, config *Config) error { var ( err error - tlsConfig = &config.TLSConfig controlConfig = &config.ControlConfig ) - caBytes, err := ioutil.ReadFile(controlConfig.Runtime.ServerCA) + ca, err := ioutil.ReadFile(config.ControlConfig.Runtime.ServerCA) if err != nil { - return "", err - } - caKeyBytes, err := ioutil.ReadFile(controlConfig.Runtime.ServerCAKey) - if err != nil { - return "", err + return err } - certs := string(caBytes) - tlsConfig.CACerts = certs - tlsConfig.CAKey = string(caKeyBytes) - - tlsConfig.Handler = router(controlConfig, controlConfig.Runtime.Tunnel, func() (string, error) { - return certs, nil - }) + controlConfig.Runtime.Handler = router(controlConfig, controlConfig.Runtime.Tunnel, ca) sc, err := newContext(ctx, controlConfig.Runtime.KubeConfigAdmin) if err != nil { - return "", err + return err } if err := stageFiles(ctx, sc, controlConfig); err != nil { - return "", err + return err } - _, err = tls.NewServer(ctx, sc.K3s.K3s().V1().ListenerConfig(), *tlsConfig) - if err != nil { - return "", err + if err := sc.Start(ctx); err != nil { + return err } - if err := startNodeCache(ctx, sc); err != nil { - return "", err - } + controlConfig.Runtime.Core = sc.Core start := func(ctx context.Context) { if err := masterControllers(ctx, sc, config); err != nil { @@ -122,7 +110,7 @@ func startWrangler(ctx context.Context, config *Config) (string, error) { } } if !config.DisableAgent { - go setMasterRoleLabel(ctx, sc) + go setMasterRoleLabel(ctx, sc.Core.Core().V1().Node()) } if controlConfig.NoLeaderElect { go func() { @@ -134,7 +122,7 @@ func startWrangler(ctx context.Context, config *Config) (string, error) { go leader.RunOrDie(ctx, "", "k3s", sc.K8s, start) } - return certs, nil + return nil } func masterControllers(ctx context.Context, sc *Context, config *Config) error { @@ -162,7 +150,7 @@ func masterControllers(ctx context.Context, sc *Context, config *Config) error { } if !config.DisableServiceLB && config.Rootless { - return rootlessports.Register(ctx, sc.Core.Core().V1().Service(), config.TLSConfig.HTTPSPort) + return rootlessports.Register(ctx, sc.Core.Core().V1().Service(), config.ControlConfig.HTTPSPort) } return nil @@ -203,7 +191,7 @@ func HomeKubeConfig(write, rootless bool) (string, error) { return resolvehome.Resolve(datadir.HomeConfig) } -func printTokens(certs, advertiseIP string, tlsConfig *dynamiclistener.UserConfig, config *config.Control) { +func printTokens(advertiseIP string, config *config.Control) error { var ( nodeFile string ) @@ -212,26 +200,43 @@ func printTokens(certs, advertiseIP string, tlsConfig *dynamiclistener.UserConfi advertiseIP = "127.0.0.1" } - if len(config.Runtime.NodeToken) > 0 { - p := filepath.Join(config.DataDir, "node-token") - if err := writeToken(config.Runtime.NodeToken, p, certs); err == nil { + if len(config.Runtime.AgentToken) > 0 { + p := filepath.Join(config.DataDir, "token") + if err := writeToken(config.Runtime.AgentToken, p, config.Runtime.ServerCA); err == nil { logrus.Infof("Node token is available at %s", p) nodeFile = p } + + // backwards compatibility + np := filepath.Join(config.DataDir, "node-token") + if !isSymlink(np) { + if err := os.RemoveAll(np); err != nil { + return err + } + if err := os.Symlink(p, np); err != nil { + return err + } + } } if len(nodeFile) > 0 { - printToken(tlsConfig.HTTPSPort, advertiseIP, "To join node to cluster:", "agent") + printToken(config.HTTPSPort, advertiseIP, "To join node to cluster:", "agent") } + + return nil } -func writeKubeConfig(certs string, tlsConfig *dynamiclistener.UserConfig, config *Config) { - clientToken := FormatToken(config.ControlConfig.Runtime.ClientToken, certs) - ip := tlsConfig.BindAddress +func writeKubeConfig(certs string, config *Config) error { + clientToken, err := FormatToken(config.ControlConfig.Runtime.ClientToken, certs) + if err != nil { + return err + } + + ip := config.ControlConfig.BindAddress if ip == "" { ip = "127.0.0.1" } - url := fmt.Sprintf("https://%s:%d", ip, tlsConfig.HTTPSPort) + url := fmt.Sprintf("https://%s:%d", ip, config.ControlConfig.HTTPSPort) kubeConfig, err := HomeKubeConfig(true, config.Rootless) def := true if err != nil { @@ -274,6 +279,8 @@ func writeKubeConfig(certs string, tlsConfig *dynamiclistener.UserConfig, config if def { logrus.Infof("Run: %s kubectl", filepath.Base(os.Args[0])) } + + return nil } func setupDataDirAndChdir(config *config.Control) error { @@ -312,18 +319,22 @@ func printToken(httpsPort int, advertiseIP, prefix, cmd string) { logrus.Infof("%s k3s %s -s https://%s:%d -t ${NODE_TOKEN}", prefix, cmd, ip, httpsPort) } -func FormatToken(token string, certs string) string { +func FormatToken(token string, certFile string) (string, error) { if len(token) == 0 { - return token + return token, nil } prefix := "K10" - if len(certs) > 0 { - digest := sha256.Sum256([]byte(certs)) + if len(certFile) > 0 { + bytes, err := ioutil.ReadFile(certFile) + if err != nil { + return "", nil + } + digest := sha256.Sum256(bytes) prefix = "K10" + hex.EncodeToString(digest[:]) + "::" } - return prefix + token + return prefix + token, nil } func writeToken(token, file, certs string) error { @@ -331,7 +342,10 @@ func writeToken(token, file, certs string) error { return nil } - token = FormatToken(token, certs) + token, err := FormatToken(token, certs) + if err != nil { + return err + } return ioutil.WriteFile(file, []byte(token+"\n"), 0600) } @@ -364,26 +378,23 @@ func isSymlink(config string) bool { return false } -func setMasterRoleLabel(ctx context.Context, sc *Context) error { +func setMasterRoleLabel(ctx context.Context, nodes v1.NodeClient) error { for { nodeName := os.Getenv("NODE_NAME") - nodeController := sc.Core.Core().V1().Node() - nodeCache := nodeController.Cache() - nodeCached, err := nodeCache.Get(nodeName) + node, err := nodes.Get(nodeName, metav1.GetOptions{}) if err != nil { logrus.Infof("Waiting for master node %s startup: %v", nodeName, err) time.Sleep(1 * time.Second) continue } - if v, ok := nodeCached.Labels[MasterRoleLabelKey]; ok && v == "true" { + if v, ok := node.Labels[MasterRoleLabelKey]; ok && v == "true" { break } - node := nodeCached.DeepCopy() if node.Labels == nil { node.Labels = make(map[string]string) } node.Labels[MasterRoleLabelKey] = "true" - _, err = nodeController.Update(node) + _, err = nodes.Update(node) if err == nil { logrus.Infof("master role label has been set succesfully on node: %s", nodeName) break @@ -396,9 +407,3 @@ func setMasterRoleLabel(ctx context.Context, sc *Context) error { } return nil } - -func startNodeCache(ctx context.Context, sc *Context) error { - sc.Core.Core().V1().Node().Cache() - - return sc.Start(ctx) -} diff --git a/pkg/server/types.go b/pkg/server/types.go index 4bccf98fd8..cba0633e56 100644 --- a/pkg/server/types.go +++ b/pkg/server/types.go @@ -1,14 +1,12 @@ package server import ( - "github.com/rancher/dynamiclistener" "github.com/rancher/k3s/pkg/daemons/config" ) type Config struct { DisableAgent bool DisableServiceLB bool - TLSConfig dynamiclistener.UserConfig ControlConfig config.Control Rootless bool } diff --git a/pkg/token/read.go b/pkg/token/read.go new file mode 100644 index 0000000000..1789ef80bc --- /dev/null +++ b/pkg/token/read.go @@ -0,0 +1,39 @@ +package token + +import ( + cryptorand "crypto/rand" + "encoding/hex" + "io/ioutil" + "os" + "strings" + "time" + + "github.com/sirupsen/logrus" +) + +func Random(size int) (string, error) { + token := make([]byte, size, size) + _, err := cryptorand.Read(token) + if err != nil { + return "", err + } + return hex.EncodeToString(token), err +} + +func ReadFile(path string) (string, error) { + if path == "" { + return "", nil + } + + for { + tokenBytes, err := ioutil.ReadFile(path) + if err == nil { + return strings.TrimSpace(string(tokenBytes)), nil + } else if os.IsNotExist(err) { + logrus.Infof("Waiting for %s to be available\n", path) + time.Sleep(2 * time.Second) + } else { + return "", err + } + } +} From 609c5e5f51adb612c69336c0c1a850aa306bd78a Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Wed, 30 Oct 2019 19:08:26 -0700 Subject: [PATCH 2/3] Update generated code --- .../k3s.cattle.io/v1/zz_generated_deepcopy.go | 60 ----- .../v1/zz_generated_list_types.go | 17 -- .../k3s.cattle.io/v1/zz_generated_register.go | 5 +- pkg/deploy/zz_generated_bindata.go | 2 +- .../v1/fake/fake_k3s.cattle.io_client.go | 4 - .../v1/fake/fake_listenerconfig.go | 140 ---------- .../k3s.cattle.io/v1/generated_expansion.go | 2 - .../k3s.cattle.io/v1/k3s.cattle.io_client.go | 5 - .../typed/k3s.cattle.io/v1/listenerconfig.go | 191 -------------- .../controllers/k3s.cattle.io/v1/interface.go | 4 - .../k3s.cattle.io/v1/listenerconfig.go | 242 ------------------ .../informers/externalversions/generic.go | 2 - .../k3s.cattle.io/v1/interface.go | 7 - .../k3s.cattle.io/v1/listenerconfig.go | 89 ------- .../k3s.cattle.io/v1/expansion_generated.go | 8 - .../k3s.cattle.io/v1/listenerconfig.go | 94 ------- 16 files changed, 2 insertions(+), 870 deletions(-) delete mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_listenerconfig.go delete mode 100644 pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/listenerconfig.go delete mode 100644 pkg/generated/controllers/k3s.cattle.io/v1/listenerconfig.go delete mode 100644 pkg/generated/informers/externalversions/k3s.cattle.io/v1/listenerconfig.go delete mode 100644 pkg/generated/listers/k3s.cattle.io/v1/listenerconfig.go diff --git a/pkg/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go b/pkg/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go index 34011a1246..95f4b52019 100644 --- a/pkg/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go +++ b/pkg/apis/k3s.cattle.io/v1/zz_generated_deepcopy.go @@ -122,63 +122,3 @@ func (in *AddonStatus) DeepCopy() *AddonStatus { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ListenerConfig) DeepCopyInto(out *ListenerConfig) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Status.DeepCopyInto(&out.Status) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerConfig. -func (in *ListenerConfig) DeepCopy() *ListenerConfig { - if in == nil { - return nil - } - out := new(ListenerConfig) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ListenerConfig) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ListenerConfigList) DeepCopyInto(out *ListenerConfigList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ListenerConfig, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListenerConfigList. -func (in *ListenerConfigList) DeepCopy() *ListenerConfigList { - if in == nil { - return nil - } - out := new(ListenerConfigList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ListenerConfigList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} diff --git a/pkg/apis/k3s.cattle.io/v1/zz_generated_list_types.go b/pkg/apis/k3s.cattle.io/v1/zz_generated_list_types.go index cb33f020dd..5295502863 100644 --- a/pkg/apis/k3s.cattle.io/v1/zz_generated_list_types.go +++ b/pkg/apis/k3s.cattle.io/v1/zz_generated_list_types.go @@ -26,23 +26,6 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// ListenerConfigList is a list of ListenerConfig resources -type ListenerConfigList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata"` - - Items []ListenerConfig `json:"items"` -} - -func NewListenerConfig(namespace, name string, obj ListenerConfig) *ListenerConfig { - obj.APIVersion, obj.Kind = SchemeGroupVersion.WithKind("ListenerConfig").ToAPIVersionAndKind() - obj.Name = name - obj.Namespace = namespace - return &obj -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - // AddonList is a list of Addon resources type AddonList struct { metav1.TypeMeta `json:",inline"` diff --git a/pkg/apis/k3s.cattle.io/v1/zz_generated_register.go b/pkg/apis/k3s.cattle.io/v1/zz_generated_register.go index 584a0c1fdc..561772b763 100644 --- a/pkg/apis/k3s.cattle.io/v1/zz_generated_register.go +++ b/pkg/apis/k3s.cattle.io/v1/zz_generated_register.go @@ -28,8 +28,7 @@ import ( ) var ( - AddonResourceName = "addons" - ListenerConfigResourceName = "listenerconfigs" + AddonResourceName = "addons" ) // SchemeGroupVersion is group version used to register these objects @@ -55,8 +54,6 @@ func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &Addon{}, &AddonList{}, - &ListenerConfig{}, - &ListenerConfigList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/pkg/deploy/zz_generated_bindata.go b/pkg/deploy/zz_generated_bindata.go index 5ef0dbbb01..a1f299639f 100644 --- a/pkg/deploy/zz_generated_bindata.go +++ b/pkg/deploy/zz_generated_bindata.go @@ -141,7 +141,7 @@ func localStorageYaml() (*asset, error) { return a, nil } -var _rolebindingsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\xcf\xbd\x0a\xc2\x40\x10\x04\xe0\xfe\x9e\xe2\x5e\xe0\x22\x76\x72\xa5\x16\xf6\x01\xed\x37\xb9\x55\xd7\xdc\x1f\xbb\x7b\x01\x7d\x7a\x09\x48\x1a\x51\xb0\x1c\x18\xe6\x63\xa0\xd2\x19\x59\xa8\x64\x6f\x79\x80\xb1\x83\xa6\xb7\xc2\xf4\x04\xa5\x92\xbb\x69\x27\x1d\x95\xcd\xbc\x35\x13\xe5\xe0\xed\x21\x36\x51\xe4\xbe\x44\xdc\x53\x0e\x94\xaf\x26\xa1\x42\x00\x05\x6f\xac\xcd\x90\xd0\xdb\xa9\x0d\xe8\xa0\x92\x20\xcf\xc8\x6e\x89\x11\xd5\x41\x48\x94\x0d\x97\x88\x3d\x5e\x96\x36\x54\x3a\x72\x69\xf5\x87\x6c\xac\xfd\x80\x57\x47\x1e\xa2\x98\xfc\xba\x5f\xe9\x6d\x48\x1b\xee\x38\xaa\x78\xe3\xfe\x42\x4e\x82\xfc\xe5\x85\x79\x05\x00\x00\xff\xff\x54\xf2\x55\xe2\x29\x01\x00\x00") +var _rolebindingsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x92\x31\x6f\xe3\x30\x0c\x85\x77\xfd\x0a\x21\xbb\x72\x38\xdc\x72\xf0\xd8\x0e\xdd\x03\xb4\x3b\x6d\xb3\x09\x6b\x59\x14\x48\x2a\x41\xfb\xeb\x0b\xa7\x6e\x82\xa4\x76\x90\xb4\xdd\x24\x41\x7c\x1f\x1f\xf9\x20\xd3\x13\x8a\x12\xa7\xca\x4b\x0d\xcd\x12\x8a\x6d\x58\xe8\x0d\x8c\x38\x2d\xbb\xff\xba\x24\xfe\xb3\xfd\xeb\x3a\x4a\x6d\xe5\xef\x63\x51\x43\x59\x71\xc4\x3b\x4a\x2d\xa5\xb5\xeb\xd1\xa0\x05\x83\xca\x79\x9f\xa0\xc7\xca\x77\xa5\xc6\x00\x99\x14\x65\x8b\x12\x86\x6b\x44\x0b\xd0\xf6\x94\x9c\x70\xc4\x15\x3e\x0f\xbf\x21\xd3\x83\x70\xc9\x17\xc8\xce\xfb\x2f\xe0\x03\x47\x5f\xd5\xb0\xaf\x0e\xfa\x99\x46\x86\x96\xfa\x05\x1b\xd3\xca\x85\x9b\x20\x8f\x8a\x32\xe3\xc2\xb9\x10\x82\xfb\xfe\xb4\x26\xc6\xf4\xd9\xfe\x3f\x0d\x0d\x27\x13\x8e\x11\xc5\x49\x89\x78\xd2\xb8\x0e\x15\xc1\x2f\x16\xce\x7b\x41\xe5\x22\x0d\x8e\x6f\x89\x5b\x54\xe7\xfd\x16\xa5\x1e\x9f\xd6\x68\x57\xd6\x42\x8f\x9a\xa1\x39\x17\x88\xa4\xb6\x3f\xec\xc0\x9a\xcd\x84\x56\x42\xdb\xb1\x74\x94\xd6\xa3\xdf\x29\xf1\x8f\x3f\x99\x23\x35\x74\x33\x61\x42\x10\x53\x9b\x99\x92\xe9\xfe\x96\xb9\x9d\xd3\x1c\xfc\x1f\xb5\x7f\xb8\xb4\xf9\x88\xcf\xec\xee\xf7\xb3\x7d\x0a\x38\x06\x7b\xf0\x78\x1d\xe3\x2c\xdc\x97\x01\xef\x01\x00\x00\xff\xff\x46\xd3\x6d\x9d\x0f\x04\x00\x00") func rolebindingsYamlBytes() ([]byte, error) { return bindataRead( diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_k3s.cattle.io_client.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_k3s.cattle.io_client.go index 5ac52eb8cd..778ae547c8 100644 --- a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_k3s.cattle.io_client.go +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_k3s.cattle.io_client.go @@ -32,10 +32,6 @@ func (c *FakeK3sV1) Addons(namespace string) v1.AddonInterface { return &FakeAddons{c, namespace} } -func (c *FakeK3sV1) ListenerConfigs(namespace string) v1.ListenerConfigInterface { - return &FakeListenerConfigs{c, namespace} -} - // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeK3sV1) RESTClient() rest.Interface { diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_listenerconfig.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_listenerconfig.go deleted file mode 100644 index 98d6660b6b..0000000000 --- a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/fake/fake_listenerconfig.go +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by main. DO NOT EDIT. - -package fake - -import ( - k3scattleiov1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - schema "k8s.io/apimachinery/pkg/runtime/schema" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeListenerConfigs implements ListenerConfigInterface -type FakeListenerConfigs struct { - Fake *FakeK3sV1 - ns string -} - -var listenerconfigsResource = schema.GroupVersionResource{Group: "k3s.cattle.io", Version: "v1", Resource: "listenerconfigs"} - -var listenerconfigsKind = schema.GroupVersionKind{Group: "k3s.cattle.io", Version: "v1", Kind: "ListenerConfig"} - -// Get takes name of the listenerConfig, and returns the corresponding listenerConfig object, and an error if there is any. -func (c *FakeListenerConfigs) Get(name string, options v1.GetOptions) (result *k3scattleiov1.ListenerConfig, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(listenerconfigsResource, c.ns, name), &k3scattleiov1.ListenerConfig{}) - - if obj == nil { - return nil, err - } - return obj.(*k3scattleiov1.ListenerConfig), err -} - -// List takes label and field selectors, and returns the list of ListenerConfigs that match those selectors. -func (c *FakeListenerConfigs) List(opts v1.ListOptions) (result *k3scattleiov1.ListenerConfigList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(listenerconfigsResource, listenerconfigsKind, c.ns, opts), &k3scattleiov1.ListenerConfigList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &k3scattleiov1.ListenerConfigList{ListMeta: obj.(*k3scattleiov1.ListenerConfigList).ListMeta} - for _, item := range obj.(*k3scattleiov1.ListenerConfigList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested listenerConfigs. -func (c *FakeListenerConfigs) Watch(opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(listenerconfigsResource, c.ns, opts)) - -} - -// Create takes the representation of a listenerConfig and creates it. Returns the server's representation of the listenerConfig, and an error, if there is any. -func (c *FakeListenerConfigs) Create(listenerConfig *k3scattleiov1.ListenerConfig) (result *k3scattleiov1.ListenerConfig, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(listenerconfigsResource, c.ns, listenerConfig), &k3scattleiov1.ListenerConfig{}) - - if obj == nil { - return nil, err - } - return obj.(*k3scattleiov1.ListenerConfig), err -} - -// Update takes the representation of a listenerConfig and updates it. Returns the server's representation of the listenerConfig, and an error, if there is any. -func (c *FakeListenerConfigs) Update(listenerConfig *k3scattleiov1.ListenerConfig) (result *k3scattleiov1.ListenerConfig, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(listenerconfigsResource, c.ns, listenerConfig), &k3scattleiov1.ListenerConfig{}) - - if obj == nil { - return nil, err - } - return obj.(*k3scattleiov1.ListenerConfig), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeListenerConfigs) UpdateStatus(listenerConfig *k3scattleiov1.ListenerConfig) (*k3scattleiov1.ListenerConfig, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(listenerconfigsResource, "status", c.ns, listenerConfig), &k3scattleiov1.ListenerConfig{}) - - if obj == nil { - return nil, err - } - return obj.(*k3scattleiov1.ListenerConfig), err -} - -// Delete takes name of the listenerConfig and deletes it. Returns an error if one occurs. -func (c *FakeListenerConfigs) Delete(name string, options *v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteAction(listenerconfigsResource, c.ns, name), &k3scattleiov1.ListenerConfig{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeListenerConfigs) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(listenerconfigsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &k3scattleiov1.ListenerConfigList{}) - return err -} - -// Patch applies the patch and returns the patched listenerConfig. -func (c *FakeListenerConfigs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *k3scattleiov1.ListenerConfig, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(listenerconfigsResource, c.ns, name, pt, data, subresources...), &k3scattleiov1.ListenerConfig{}) - - if obj == nil { - return nil, err - } - return obj.(*k3scattleiov1.ListenerConfig), err -} diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/generated_expansion.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/generated_expansion.go index 21cf76ac09..1b681d3f1f 100644 --- a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/generated_expansion.go +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/generated_expansion.go @@ -19,5 +19,3 @@ limitations under the License. package v1 type AddonExpansion interface{} - -type ListenerConfigExpansion interface{} diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/k3s.cattle.io_client.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/k3s.cattle.io_client.go index f5154d6811..ac9dbd8634 100644 --- a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/k3s.cattle.io_client.go +++ b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/k3s.cattle.io_client.go @@ -27,7 +27,6 @@ import ( type K3sV1Interface interface { RESTClient() rest.Interface AddonsGetter - ListenerConfigsGetter } // K3sV1Client is used to interact with features provided by the k3s.cattle.io group. @@ -39,10 +38,6 @@ func (c *K3sV1Client) Addons(namespace string) AddonInterface { return newAddons(c, namespace) } -func (c *K3sV1Client) ListenerConfigs(namespace string) ListenerConfigInterface { - return newListenerConfigs(c, namespace) -} - // NewForConfig creates a new K3sV1Client for the given config. func NewForConfig(c *rest.Config) (*K3sV1Client, error) { config := *c diff --git a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/listenerconfig.go b/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/listenerconfig.go deleted file mode 100644 index 45be544478..0000000000 --- a/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1/listenerconfig.go +++ /dev/null @@ -1,191 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by main. DO NOT EDIT. - -package v1 - -import ( - "time" - - v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" - scheme "github.com/rancher/k3s/pkg/generated/clientset/versioned/scheme" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// ListenerConfigsGetter has a method to return a ListenerConfigInterface. -// A group's client should implement this interface. -type ListenerConfigsGetter interface { - ListenerConfigs(namespace string) ListenerConfigInterface -} - -// ListenerConfigInterface has methods to work with ListenerConfig resources. -type ListenerConfigInterface interface { - Create(*v1.ListenerConfig) (*v1.ListenerConfig, error) - Update(*v1.ListenerConfig) (*v1.ListenerConfig, error) - UpdateStatus(*v1.ListenerConfig) (*v1.ListenerConfig, error) - Delete(name string, options *metav1.DeleteOptions) error - DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error - Get(name string, options metav1.GetOptions) (*v1.ListenerConfig, error) - List(opts metav1.ListOptions) (*v1.ListenerConfigList, error) - Watch(opts metav1.ListOptions) (watch.Interface, error) - Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ListenerConfig, err error) - ListenerConfigExpansion -} - -// listenerConfigs implements ListenerConfigInterface -type listenerConfigs struct { - client rest.Interface - ns string -} - -// newListenerConfigs returns a ListenerConfigs -func newListenerConfigs(c *K3sV1Client, namespace string) *listenerConfigs { - return &listenerConfigs{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the listenerConfig, and returns the corresponding listenerConfig object, and an error if there is any. -func (c *listenerConfigs) Get(name string, options metav1.GetOptions) (result *v1.ListenerConfig, err error) { - result = &v1.ListenerConfig{} - err = c.client.Get(). - Namespace(c.ns). - Resource("listenerconfigs"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of ListenerConfigs that match those selectors. -func (c *listenerConfigs) List(opts metav1.ListOptions) (result *v1.ListenerConfigList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1.ListenerConfigList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("listenerconfigs"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested listenerConfigs. -func (c *listenerConfigs) Watch(opts metav1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("listenerconfigs"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch() -} - -// Create takes the representation of a listenerConfig and creates it. Returns the server's representation of the listenerConfig, and an error, if there is any. -func (c *listenerConfigs) Create(listenerConfig *v1.ListenerConfig) (result *v1.ListenerConfig, err error) { - result = &v1.ListenerConfig{} - err = c.client.Post(). - Namespace(c.ns). - Resource("listenerconfigs"). - Body(listenerConfig). - Do(). - Into(result) - return -} - -// Update takes the representation of a listenerConfig and updates it. Returns the server's representation of the listenerConfig, and an error, if there is any. -func (c *listenerConfigs) Update(listenerConfig *v1.ListenerConfig) (result *v1.ListenerConfig, err error) { - result = &v1.ListenerConfig{} - err = c.client.Put(). - Namespace(c.ns). - Resource("listenerconfigs"). - Name(listenerConfig.Name). - Body(listenerConfig). - Do(). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). - -func (c *listenerConfigs) UpdateStatus(listenerConfig *v1.ListenerConfig) (result *v1.ListenerConfig, err error) { - result = &v1.ListenerConfig{} - err = c.client.Put(). - Namespace(c.ns). - Resource("listenerconfigs"). - Name(listenerConfig.Name). - SubResource("status"). - Body(listenerConfig). - Do(). - Into(result) - return -} - -// Delete takes name of the listenerConfig and deletes it. Returns an error if one occurs. -func (c *listenerConfigs) Delete(name string, options *metav1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("listenerconfigs"). - Name(name). - Body(options). - Do(). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *listenerConfigs) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error { - var timeout time.Duration - if listOptions.TimeoutSeconds != nil { - timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Namespace(c.ns). - Resource("listenerconfigs"). - VersionedParams(&listOptions, scheme.ParameterCodec). - Timeout(timeout). - Body(options). - Do(). - Error() -} - -// Patch applies the patch and returns the patched listenerConfig. -func (c *listenerConfigs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ListenerConfig, err error) { - result = &v1.ListenerConfig{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("listenerconfigs"). - SubResource(subresources...). - Name(name). - Body(data). - Do(). - Into(result) - return -} diff --git a/pkg/generated/controllers/k3s.cattle.io/v1/interface.go b/pkg/generated/controllers/k3s.cattle.io/v1/interface.go index 640037cab7..89a3e7a345 100644 --- a/pkg/generated/controllers/k3s.cattle.io/v1/interface.go +++ b/pkg/generated/controllers/k3s.cattle.io/v1/interface.go @@ -27,7 +27,6 @@ import ( type Interface interface { Addon() AddonController - ListenerConfig() ListenerConfigController } func New(controllerManager *generic.ControllerManager, client clientset.K3sV1Interface, @@ -48,6 +47,3 @@ type version struct { func (c *version) Addon() AddonController { return NewAddonController(v1.SchemeGroupVersion.WithKind("Addon"), c.controllerManager, c.client, c.informers.Addons()) } -func (c *version) ListenerConfig() ListenerConfigController { - return NewListenerConfigController(v1.SchemeGroupVersion.WithKind("ListenerConfig"), c.controllerManager, c.client, c.informers.ListenerConfigs()) -} diff --git a/pkg/generated/controllers/k3s.cattle.io/v1/listenerconfig.go b/pkg/generated/controllers/k3s.cattle.io/v1/listenerconfig.go deleted file mode 100644 index c5359ff195..0000000000 --- a/pkg/generated/controllers/k3s.cattle.io/v1/listenerconfig.go +++ /dev/null @@ -1,242 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by main. DO NOT EDIT. - -package v1 - -import ( - "context" - - v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" - clientset "github.com/rancher/k3s/pkg/generated/clientset/versioned/typed/k3s.cattle.io/v1" - informers "github.com/rancher/k3s/pkg/generated/informers/externalversions/k3s.cattle.io/v1" - listers "github.com/rancher/k3s/pkg/generated/listers/k3s.cattle.io/v1" - "github.com/rancher/wrangler/pkg/generic" - "k8s.io/apimachinery/pkg/api/equality" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" -) - -type ListenerConfigHandler func(string, *v1.ListenerConfig) (*v1.ListenerConfig, error) - -type ListenerConfigController interface { - ListenerConfigClient - - OnChange(ctx context.Context, name string, sync ListenerConfigHandler) - OnRemove(ctx context.Context, name string, sync ListenerConfigHandler) - Enqueue(namespace, name string) - - Cache() ListenerConfigCache - - Informer() cache.SharedIndexInformer - GroupVersionKind() schema.GroupVersionKind - - AddGenericHandler(ctx context.Context, name string, handler generic.Handler) - AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) - Updater() generic.Updater -} - -type ListenerConfigClient interface { - Create(*v1.ListenerConfig) (*v1.ListenerConfig, error) - Update(*v1.ListenerConfig) (*v1.ListenerConfig, error) - UpdateStatus(*v1.ListenerConfig) (*v1.ListenerConfig, error) - Delete(namespace, name string, options *metav1.DeleteOptions) error - Get(namespace, name string, options metav1.GetOptions) (*v1.ListenerConfig, error) - List(namespace string, opts metav1.ListOptions) (*v1.ListenerConfigList, error) - Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) - Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ListenerConfig, err error) -} - -type ListenerConfigCache interface { - Get(namespace, name string) (*v1.ListenerConfig, error) - List(namespace string, selector labels.Selector) ([]*v1.ListenerConfig, error) - - AddIndexer(indexName string, indexer ListenerConfigIndexer) - GetByIndex(indexName, key string) ([]*v1.ListenerConfig, error) -} - -type ListenerConfigIndexer func(obj *v1.ListenerConfig) ([]string, error) - -type listenerConfigController struct { - controllerManager *generic.ControllerManager - clientGetter clientset.ListenerConfigsGetter - informer informers.ListenerConfigInformer - gvk schema.GroupVersionKind -} - -func NewListenerConfigController(gvk schema.GroupVersionKind, controllerManager *generic.ControllerManager, clientGetter clientset.ListenerConfigsGetter, informer informers.ListenerConfigInformer) ListenerConfigController { - return &listenerConfigController{ - controllerManager: controllerManager, - clientGetter: clientGetter, - informer: informer, - gvk: gvk, - } -} - -func FromListenerConfigHandlerToHandler(sync ListenerConfigHandler) generic.Handler { - return func(key string, obj runtime.Object) (ret runtime.Object, err error) { - var v *v1.ListenerConfig - if obj == nil { - v, err = sync(key, nil) - } else { - v, err = sync(key, obj.(*v1.ListenerConfig)) - } - if v == nil { - return nil, err - } - return v, err - } -} - -func (c *listenerConfigController) Updater() generic.Updater { - return func(obj runtime.Object) (runtime.Object, error) { - newObj, err := c.Update(obj.(*v1.ListenerConfig)) - if newObj == nil { - return nil, err - } - return newObj, err - } -} - -func UpdateListenerConfigOnChange(updater generic.Updater, handler ListenerConfigHandler) ListenerConfigHandler { - return func(key string, obj *v1.ListenerConfig) (*v1.ListenerConfig, error) { - if obj == nil { - return handler(key, nil) - } - - copyObj := obj.DeepCopy() - newObj, err := handler(key, copyObj) - if newObj != nil { - copyObj = newObj - } - if obj.ResourceVersion == copyObj.ResourceVersion && !equality.Semantic.DeepEqual(obj, copyObj) { - newObj, err := updater(copyObj) - if newObj != nil && err == nil { - copyObj = newObj.(*v1.ListenerConfig) - } - } - - return copyObj, err - } -} - -func (c *listenerConfigController) AddGenericHandler(ctx context.Context, name string, handler generic.Handler) { - c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, handler) -} - -func (c *listenerConfigController) AddGenericRemoveHandler(ctx context.Context, name string, handler generic.Handler) { - removeHandler := generic.NewRemoveHandler(name, c.Updater(), handler) - c.controllerManager.AddHandler(ctx, c.gvk, c.informer.Informer(), name, removeHandler) -} - -func (c *listenerConfigController) OnChange(ctx context.Context, name string, sync ListenerConfigHandler) { - c.AddGenericHandler(ctx, name, FromListenerConfigHandlerToHandler(sync)) -} - -func (c *listenerConfigController) OnRemove(ctx context.Context, name string, sync ListenerConfigHandler) { - removeHandler := generic.NewRemoveHandler(name, c.Updater(), FromListenerConfigHandlerToHandler(sync)) - c.AddGenericHandler(ctx, name, removeHandler) -} - -func (c *listenerConfigController) Enqueue(namespace, name string) { - c.controllerManager.Enqueue(c.gvk, c.informer.Informer(), namespace, name) -} - -func (c *listenerConfigController) Informer() cache.SharedIndexInformer { - return c.informer.Informer() -} - -func (c *listenerConfigController) GroupVersionKind() schema.GroupVersionKind { - return c.gvk -} - -func (c *listenerConfigController) Cache() ListenerConfigCache { - return &listenerConfigCache{ - lister: c.informer.Lister(), - indexer: c.informer.Informer().GetIndexer(), - } -} - -func (c *listenerConfigController) Create(obj *v1.ListenerConfig) (*v1.ListenerConfig, error) { - return c.clientGetter.ListenerConfigs(obj.Namespace).Create(obj) -} - -func (c *listenerConfigController) Update(obj *v1.ListenerConfig) (*v1.ListenerConfig, error) { - return c.clientGetter.ListenerConfigs(obj.Namespace).Update(obj) -} - -func (c *listenerConfigController) UpdateStatus(obj *v1.ListenerConfig) (*v1.ListenerConfig, error) { - return c.clientGetter.ListenerConfigs(obj.Namespace).UpdateStatus(obj) -} - -func (c *listenerConfigController) Delete(namespace, name string, options *metav1.DeleteOptions) error { - return c.clientGetter.ListenerConfigs(namespace).Delete(name, options) -} - -func (c *listenerConfigController) Get(namespace, name string, options metav1.GetOptions) (*v1.ListenerConfig, error) { - return c.clientGetter.ListenerConfigs(namespace).Get(name, options) -} - -func (c *listenerConfigController) List(namespace string, opts metav1.ListOptions) (*v1.ListenerConfigList, error) { - return c.clientGetter.ListenerConfigs(namespace).List(opts) -} - -func (c *listenerConfigController) Watch(namespace string, opts metav1.ListOptions) (watch.Interface, error) { - return c.clientGetter.ListenerConfigs(namespace).Watch(opts) -} - -func (c *listenerConfigController) Patch(namespace, name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ListenerConfig, err error) { - return c.clientGetter.ListenerConfigs(namespace).Patch(name, pt, data, subresources...) -} - -type listenerConfigCache struct { - lister listers.ListenerConfigLister - indexer cache.Indexer -} - -func (c *listenerConfigCache) Get(namespace, name string) (*v1.ListenerConfig, error) { - return c.lister.ListenerConfigs(namespace).Get(name) -} - -func (c *listenerConfigCache) List(namespace string, selector labels.Selector) ([]*v1.ListenerConfig, error) { - return c.lister.ListenerConfigs(namespace).List(selector) -} - -func (c *listenerConfigCache) AddIndexer(indexName string, indexer ListenerConfigIndexer) { - utilruntime.Must(c.indexer.AddIndexers(map[string]cache.IndexFunc{ - indexName: func(obj interface{}) (strings []string, e error) { - return indexer(obj.(*v1.ListenerConfig)) - }, - })) -} - -func (c *listenerConfigCache) GetByIndex(indexName, key string) (result []*v1.ListenerConfig, err error) { - objs, err := c.indexer.ByIndex(indexName, key) - if err != nil { - return nil, err - } - for _, obj := range objs { - result = append(result, obj.(*v1.ListenerConfig)) - } - return result, nil -} diff --git a/pkg/generated/informers/externalversions/generic.go b/pkg/generated/informers/externalversions/generic.go index 93d0c7a5a5..c7c1ef8605 100644 --- a/pkg/generated/informers/externalversions/generic.go +++ b/pkg/generated/informers/externalversions/generic.go @@ -55,8 +55,6 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource // Group=k3s.cattle.io, Version=v1 case v1.SchemeGroupVersion.WithResource("addons"): return &genericInformer{resource: resource.GroupResource(), informer: f.K3s().V1().Addons().Informer()}, nil - case v1.SchemeGroupVersion.WithResource("listenerconfigs"): - return &genericInformer{resource: resource.GroupResource(), informer: f.K3s().V1().ListenerConfigs().Informer()}, nil } diff --git a/pkg/generated/informers/externalversions/k3s.cattle.io/v1/interface.go b/pkg/generated/informers/externalversions/k3s.cattle.io/v1/interface.go index 5c896477ea..855c7c0b37 100644 --- a/pkg/generated/informers/externalversions/k3s.cattle.io/v1/interface.go +++ b/pkg/generated/informers/externalversions/k3s.cattle.io/v1/interface.go @@ -26,8 +26,6 @@ import ( type Interface interface { // Addons returns a AddonInformer. Addons() AddonInformer - // ListenerConfigs returns a ListenerConfigInformer. - ListenerConfigs() ListenerConfigInformer } type version struct { @@ -45,8 +43,3 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList func (v *version) Addons() AddonInformer { return &addonInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } - -// ListenerConfigs returns a ListenerConfigInformer. -func (v *version) ListenerConfigs() ListenerConfigInformer { - return &listenerConfigInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} -} diff --git a/pkg/generated/informers/externalversions/k3s.cattle.io/v1/listenerconfig.go b/pkg/generated/informers/externalversions/k3s.cattle.io/v1/listenerconfig.go deleted file mode 100644 index b1d1a38d21..0000000000 --- a/pkg/generated/informers/externalversions/k3s.cattle.io/v1/listenerconfig.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by main. DO NOT EDIT. - -package v1 - -import ( - time "time" - - k3scattleiov1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" - versioned "github.com/rancher/k3s/pkg/generated/clientset/versioned" - internalinterfaces "github.com/rancher/k3s/pkg/generated/informers/externalversions/internalinterfaces" - v1 "github.com/rancher/k3s/pkg/generated/listers/k3s.cattle.io/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" -) - -// ListenerConfigInformer provides access to a shared informer and lister for -// ListenerConfigs. -type ListenerConfigInformer interface { - Informer() cache.SharedIndexInformer - Lister() v1.ListenerConfigLister -} - -type listenerConfigInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewListenerConfigInformer constructs a new informer for ListenerConfig type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewListenerConfigInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredListenerConfigInformer(client, namespace, resyncPeriod, indexers, nil) -} - -// NewFilteredListenerConfigInformer constructs a new informer for ListenerConfig type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredListenerConfigInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.K3sV1().ListenerConfigs(namespace).List(options) - }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.K3sV1().ListenerConfigs(namespace).Watch(options) - }, - }, - &k3scattleiov1.ListenerConfig{}, - resyncPeriod, - indexers, - ) -} - -func (f *listenerConfigInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredListenerConfigInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *listenerConfigInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&k3scattleiov1.ListenerConfig{}, f.defaultInformer) -} - -func (f *listenerConfigInformer) Lister() v1.ListenerConfigLister { - return v1.NewListenerConfigLister(f.Informer().GetIndexer()) -} diff --git a/pkg/generated/listers/k3s.cattle.io/v1/expansion_generated.go b/pkg/generated/listers/k3s.cattle.io/v1/expansion_generated.go index 604e04b64a..b4881de9ef 100644 --- a/pkg/generated/listers/k3s.cattle.io/v1/expansion_generated.go +++ b/pkg/generated/listers/k3s.cattle.io/v1/expansion_generated.go @@ -25,11 +25,3 @@ type AddonListerExpansion interface{} // AddonNamespaceListerExpansion allows custom methods to be added to // AddonNamespaceLister. type AddonNamespaceListerExpansion interface{} - -// ListenerConfigListerExpansion allows custom methods to be added to -// ListenerConfigLister. -type ListenerConfigListerExpansion interface{} - -// ListenerConfigNamespaceListerExpansion allows custom methods to be added to -// ListenerConfigNamespaceLister. -type ListenerConfigNamespaceListerExpansion interface{} diff --git a/pkg/generated/listers/k3s.cattle.io/v1/listenerconfig.go b/pkg/generated/listers/k3s.cattle.io/v1/listenerconfig.go deleted file mode 100644 index 3c596beaac..0000000000 --- a/pkg/generated/listers/k3s.cattle.io/v1/listenerconfig.go +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by main. DO NOT EDIT. - -package v1 - -import ( - v1 "github.com/rancher/k3s/pkg/apis/k3s.cattle.io/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// ListenerConfigLister helps list ListenerConfigs. -type ListenerConfigLister interface { - // List lists all ListenerConfigs in the indexer. - List(selector labels.Selector) (ret []*v1.ListenerConfig, err error) - // ListenerConfigs returns an object that can list and get ListenerConfigs. - ListenerConfigs(namespace string) ListenerConfigNamespaceLister - ListenerConfigListerExpansion -} - -// listenerConfigLister implements the ListenerConfigLister interface. -type listenerConfigLister struct { - indexer cache.Indexer -} - -// NewListenerConfigLister returns a new ListenerConfigLister. -func NewListenerConfigLister(indexer cache.Indexer) ListenerConfigLister { - return &listenerConfigLister{indexer: indexer} -} - -// List lists all ListenerConfigs in the indexer. -func (s *listenerConfigLister) List(selector labels.Selector) (ret []*v1.ListenerConfig, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1.ListenerConfig)) - }) - return ret, err -} - -// ListenerConfigs returns an object that can list and get ListenerConfigs. -func (s *listenerConfigLister) ListenerConfigs(namespace string) ListenerConfigNamespaceLister { - return listenerConfigNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// ListenerConfigNamespaceLister helps list and get ListenerConfigs. -type ListenerConfigNamespaceLister interface { - // List lists all ListenerConfigs in the indexer for a given namespace. - List(selector labels.Selector) (ret []*v1.ListenerConfig, err error) - // Get retrieves the ListenerConfig from the indexer for a given namespace and name. - Get(name string) (*v1.ListenerConfig, error) - ListenerConfigNamespaceListerExpansion -} - -// listenerConfigNamespaceLister implements the ListenerConfigNamespaceLister -// interface. -type listenerConfigNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all ListenerConfigs in the indexer for a given namespace. -func (s listenerConfigNamespaceLister) List(selector labels.Selector) (ret []*v1.ListenerConfig, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1.ListenerConfig)) - }) - return ret, err -} - -// Get retrieves the ListenerConfig from the indexer for a given namespace and name. -func (s listenerConfigNamespaceLister) Get(name string) (*v1.ListenerConfig, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1.Resource("listenerconfig"), name) - } - return obj.(*v1.ListenerConfig), nil -} From 69949dda0a58f901d7cd87e5657f4e42d568dffc Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Wed, 30 Oct 2019 19:22:03 -0700 Subject: [PATCH 3/3] Update vendor --- go.mod | 2 +- go.sum | 10 +- .../go-windows-terminal-sequences/README.md | 1 - .../sequences_dummy.go | 11 - .../rancher/dynamiclistener/factory/ca.go | 80 +++ .../dynamiclistener/factory/cert_utils.go | 105 ++++ .../rancher/dynamiclistener/factory/gen.go | 164 ++++++ .../github.com/rancher/dynamiclistener/go.mod | 15 +- .../github.com/rancher/dynamiclistener/go.sum | 129 +++- .../rancher/dynamiclistener/listener.go | 198 +++++++ .../rancher/dynamiclistener/read.go | 50 -- .../rancher/dynamiclistener/redirect.go | 46 ++ .../rancher/dynamiclistener/server.go | 556 ------------------ .../dynamiclistener/storage/file/file.go | 42 ++ .../storage/kubernetes/controller.go | 109 ++++ .../dynamiclistener/storage/memory/memory.go | 42 ++ .../github.com/rancher/dynamiclistener/tcp.go | 38 ++ .../rancher/dynamiclistener/types.go | 63 -- .../rancher/kine/pkg/client/client.go | 107 ---- vendor/modules.txt | 79 +-- 20 files changed, 980 insertions(+), 867 deletions(-) delete mode 100644 vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go create mode 100644 vendor/github.com/rancher/dynamiclistener/factory/ca.go create mode 100644 vendor/github.com/rancher/dynamiclistener/factory/cert_utils.go create mode 100644 vendor/github.com/rancher/dynamiclistener/factory/gen.go create mode 100644 vendor/github.com/rancher/dynamiclistener/listener.go delete mode 100644 vendor/github.com/rancher/dynamiclistener/read.go create mode 100644 vendor/github.com/rancher/dynamiclistener/redirect.go delete mode 100644 vendor/github.com/rancher/dynamiclistener/server.go create mode 100644 vendor/github.com/rancher/dynamiclistener/storage/file/file.go create mode 100644 vendor/github.com/rancher/dynamiclistener/storage/kubernetes/controller.go create mode 100644 vendor/github.com/rancher/dynamiclistener/storage/memory/memory.go create mode 100644 vendor/github.com/rancher/dynamiclistener/tcp.go delete mode 100644 vendor/github.com/rancher/dynamiclistener/types.go delete mode 100644 vendor/github.com/rancher/kine/pkg/client/client.go diff --git a/go.mod b/go.mod index b53ae846d8..3fb3a5b930 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830 github.com/pkg/errors v0.8.1 github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 // indirect - github.com/rancher/dynamiclistener v0.1.1-0.20191010011134-8a2488bc860a + github.com/rancher/dynamiclistener v0.1.1-0.20191031022009-6224794ef3cb github.com/rancher/helm-controller v0.2.2 github.com/rancher/kine v0.0.0-00010101000000-000000000000 github.com/rancher/remotedialer v0.2.0 diff --git a/go.sum b/go.sum index 816b6305de..3cecdc1640 100644 --- a/go.sum +++ b/go.sum @@ -418,9 +418,8 @@ github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo github.com/knative/build v0.6.0/go.mod h1:/sU74ZQkwlYA5FwYDJhYTy61i/Kn+5eWfln2jDbw3Qo= github.com/knative/pkg v0.0.0-20190514205332-5e4512dcb2ca/go.mod h1:7Ijfhw7rfB+H9VtosIsDYvZQ+qYTz7auK3fHW/5z4ww= github.com/knative/serving v0.6.1/go.mod h1:ljvMfwQy2qanaM/8xnBSK4Mz3Vv2NawC2fo5kFRJS1A= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -563,8 +562,8 @@ github.com/rancher/containerd v1.3.0-k3s.4 h1:Vq9EJQEm01eeWaBtgU35KxWeuVU5LwW43E github.com/rancher/containerd v1.3.0-k3s.4/go.mod h1:ZMfzmqce2Z+QSEqdHMfeJs1TZ/UeJ1aDrazjpQT4ehM= github.com/rancher/cri-tools v1.16.1-k3s.1 h1:iporgQ46noE6dtLzq6fWcIO2qjyPZy2m42d2P+UnGJg= github.com/rancher/cri-tools v1.16.1-k3s.1/go.mod h1:TEKhKv2EJIZp+p9jnEy4C63g8CosJzsI4kyKKkHag+8= -github.com/rancher/dynamiclistener v0.1.1-0.20191010011134-8a2488bc860a h1:1bUYAv5U/Ky4YJ9o8gWxX+vNcjpIL3JWNBao70OlkFE= -github.com/rancher/dynamiclistener v0.1.1-0.20191010011134-8a2488bc860a/go.mod h1:8hbGf35mB7ormKEFqsAgjgeI5rLbj5N764jG41dNhps= +github.com/rancher/dynamiclistener v0.1.1-0.20191031022009-6224794ef3cb h1:bMoA9UHr1QNTWVrf0fSJCba6YDU1xmt2jmeohpiugKg= +github.com/rancher/dynamiclistener v0.1.1-0.20191031022009-6224794ef3cb/go.mod h1:fs/dxyNcB3YT6W9fVz4bDGfhmSQS17QQup6BIcGF++s= github.com/rancher/flannel v0.11.0-k3s.1 h1:mIwnfWDafjzQgFkZeJ1AkFrrAT3EdBaA1giE0eLJKo8= github.com/rancher/flannel v0.11.0-k3s.1/go.mod h1:Hn4ZV+eq0LhLZP63xZnxdGwXEoRSxs5sxELxu27M3UA= github.com/rancher/helm-controller v0.2.2 h1:MUqisy53/Ay1EYOF2uTCYBbGpgtZLNKKrI01BdxIbQo= @@ -682,7 +681,6 @@ github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRci github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stripe/safesql v0.2.0/go.mod h1:q7b2n0JmzM1mVGfcYpanfVb2j23cXZeWFxcILPn3JV4= github.com/syndtr/gocapability v0.0.0-20160928074757-e7cb7fa329f4/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8 h1:zLV6q4e8Jv9EHjNg/iHfzwDkCve6Ua5jCygptrtXHvI= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -741,7 +739,6 @@ golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -808,7 +805,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo= diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md index 195333e51d..949b77e304 100644 --- a/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md +++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md @@ -26,7 +26,6 @@ The tool is sponsored by the [marvin + konsorten GmbH](http://www.konsorten.de). We thank all the authors who provided code to this library: * Felix Kollmann -* Nicolas Perraut ## License diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go deleted file mode 100644 index df61a6f2f6..0000000000 --- a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build linux darwin - -package sequences - -import ( - "fmt" -) - -func EnableVirtualTerminalProcessing(stream uintptr, enable bool) error { - return fmt.Errorf("windows only package") -} diff --git a/vendor/github.com/rancher/dynamiclistener/factory/ca.go b/vendor/github.com/rancher/dynamiclistener/factory/ca.go new file mode 100644 index 0000000000..a35738ccb4 --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/factory/ca.go @@ -0,0 +1,80 @@ +package factory + +import ( + "crypto/ecdsa" + "crypto/x509" + "io/ioutil" + "os" +) + +func GenCA() (*x509.Certificate, *ecdsa.PrivateKey, error) { + caKey, err := NewPrivateKey() + if err != nil { + return nil, nil, err + } + + caCert, err := NewSelfSignedCACert(caKey, "dynamiclistener-ca", "dynamiclistener-org") + if err != nil { + return nil, nil, err + } + + return caCert, caKey, nil +} + +func LoadOrGenCA() (*x509.Certificate, *ecdsa.PrivateKey, error) { + cert, key, err := loadCA() + if err == nil { + return cert, key, nil + } + + cert, key, err = GenCA() + if err != nil { + return nil, nil, err + } + + certBytes, keyBytes, err := Marshal(cert, key) + if err != nil { + return nil, nil, err + } + + if err := os.MkdirAll("./certs", 0700); err != nil { + return nil, nil, err + } + + if err := ioutil.WriteFile("./certs/ca.pem", certBytes, 0600); err != nil { + return nil, nil, err + } + + if err := ioutil.WriteFile("./certs/ca.key", keyBytes, 0600); err != nil { + return nil, nil, err + } + + return cert, key, nil +} + +func loadCA() (*x509.Certificate, *ecdsa.PrivateKey, error) { + return LoadCerts("./certs/ca.pem", "./certs/ca.key") +} + +func LoadCerts(certFile, keyFile string) (*x509.Certificate, *ecdsa.PrivateKey, error) { + caPem, err := ioutil.ReadFile(certFile) + if err != nil { + return nil, nil, err + } + caKey, err := ioutil.ReadFile(keyFile) + if err != nil { + return nil, nil, err + } + + key, err := ParseECPrivateKeyPEM(caKey) + if err != nil { + return nil, nil, err + } + + cert, err := ParseCertPEM(caPem) + if err != nil { + return nil, nil, err + } + + return cert, key, nil +} diff --git a/vendor/github.com/rancher/dynamiclistener/factory/cert_utils.go b/vendor/github.com/rancher/dynamiclistener/factory/cert_utils.go new file mode 100644 index 0000000000..459bd2e849 --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/factory/cert_utils.go @@ -0,0 +1,105 @@ +package factory + +import ( + "crypto" + "crypto/ecdsa" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math" + "math/big" + "net" + "time" +) + +const ( + ECPrivateKeyBlockType = "EC PRIVATE KEY" + CertificateBlockType = "CERTIFICATE" +) + +func NewSelfSignedCACert(key crypto.Signer, cn string, org ...string) (*x509.Certificate, error) { + now := time.Now() + tmpl := x509.Certificate{ + BasicConstraintsValid: true, + IsCA: true, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + NotAfter: now.Add(time.Hour * 24 * 365 * 10).UTC(), + NotBefore: now.UTC(), + SerialNumber: new(big.Int).SetInt64(0), + Subject: pkix.Name{ + CommonName: cn, + Organization: org, + }, + } + + certDERBytes, err := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, key.Public(), key) + if err != nil { + return nil, err + } + + return x509.ParseCertificate(certDERBytes) +} + +func NewSignedCert(signer crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer, cn string, orgs []string, + domains []string, ips []net.IP) (*x509.Certificate, error) { + + serialNumber, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) + if err != nil { + return nil, err + } + + parent := x509.Certificate{ + DNSNames: domains, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + IPAddresses: ips, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + NotAfter: time.Now().Add(time.Hour * 24 * 365).UTC(), + NotBefore: caCert.NotBefore, + SerialNumber: serialNumber, + Subject: pkix.Name{ + CommonName: cn, + Organization: orgs, + }, + } + + cert, err := x509.CreateCertificate(rand.Reader, &parent, caCert, signer.Public(), caKey) + if err != nil { + return nil, err + } + + return x509.ParseCertificate(cert) +} + +func ParseECPrivateKeyPEM(keyData []byte) (*ecdsa.PrivateKey, error) { + var privateKeyPemBlock *pem.Block + for { + privateKeyPemBlock, keyData = pem.Decode(keyData) + if privateKeyPemBlock == nil { + break + } + + if privateKeyPemBlock.Type == ECPrivateKeyBlockType { + return x509.ParseECPrivateKey(privateKeyPemBlock.Bytes) + } + } + + return nil, fmt.Errorf("pem does not include a valid EC private key") +} + +func ParseCertPEM(pemCerts []byte) (*x509.Certificate, error) { + var pemBlock *pem.Block + for { + pemBlock, pemCerts = pem.Decode(pemCerts) + if pemBlock == nil { + break + } + + if pemBlock.Type == CertificateBlockType { + return x509.ParseCertificate(pemBlock.Bytes) + } + } + + return nil, fmt.Errorf("pem does not include a valid x509 cert") +} diff --git a/vendor/github.com/rancher/dynamiclistener/factory/gen.go b/vendor/github.com/rancher/dynamiclistener/factory/gen.go new file mode 100644 index 0000000000..2341748134 --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/factory/gen.go @@ -0,0 +1,164 @@ +package factory + +import ( + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "crypto/x509" + "encoding/hex" + "encoding/pem" + "net" + "sort" + "strings" + + v1 "k8s.io/api/core/v1" +) + +const ( + cnPrefix = "listener.cattle.io/cn-" + static = "listener.cattle.io/static" + hashKey = "listener.cattle.io/hash" +) + +type TLS struct { + CACert *x509.Certificate + CAKey crypto.Signer + CN string + Organization []string +} + +func collectCNs(secret *v1.Secret) (domains []string, ips []net.IP, hash string, err error) { + var ( + cns []string + digest = sha256.New() + ) + for k, v := range secret.Annotations { + if strings.HasPrefix(k, cnPrefix) { + cns = append(cns, v) + } + } + + sort.Strings(cns) + + for _, v := range cns { + digest.Write([]byte(v)) + ip := net.ParseIP(v) + if ip == nil { + domains = append(domains, v) + } else { + ips = append(ips, ip) + } + } + + hash = hex.EncodeToString(digest.Sum(nil)) + return +} + +func (t *TLS) AddCN(secret *v1.Secret, cn ...string) (*v1.Secret, bool, error) { + var ( + err error + ) + + if !NeedsUpdate(secret, cn...) { + return secret, false, nil + } + + secret = populateCN(secret, cn...) + + privateKey, err := getPrivateKey(secret) + if err != nil { + return nil, false, err + } + + domains, ips, hash, err := collectCNs(secret) + if err != nil { + return nil, false, err + } + + newCert, err := t.newCert(domains, ips, privateKey) + if err != nil { + return nil, false, err + } + + certBytes, keyBytes, err := Marshal(newCert, privateKey) + if err != nil { + return nil, false, err + } + + if secret.Data == nil { + secret.Data = map[string][]byte{} + } + secret.Data[v1.TLSCertKey] = certBytes + secret.Data[v1.TLSPrivateKeyKey] = keyBytes + secret.Annotations[hashKey] = hash + + return secret, true, nil +} + +func (t *TLS) newCert(domains []string, ips []net.IP, privateKey *ecdsa.PrivateKey) (*x509.Certificate, error) { + return NewSignedCert(privateKey, t.CACert, t.CAKey, t.CN, t.Organization, domains, ips) +} + +func populateCN(secret *v1.Secret, cn ...string) *v1.Secret { + secret = secret.DeepCopy() + if secret.Annotations == nil { + secret.Annotations = map[string]string{} + } + for _, cn := range cn { + secret.Annotations[cnPrefix+cn] = cn + } + return secret +} + +func NeedsUpdate(secret *v1.Secret, cn ...string) bool { + if secret.Annotations[static] == "true" { + return false + } + + for _, cn := range cn { + if secret.Annotations[cnPrefix+cn] == "" { + return true + } + } + + return false +} + +func getPrivateKey(secret *v1.Secret) (*ecdsa.PrivateKey, error) { + keyBytes := secret.Data[v1.TLSPrivateKeyKey] + if len(keyBytes) == 0 { + return NewPrivateKey() + } + + privateKey, err := ParseECPrivateKeyPEM(keyBytes) + if err == nil { + return privateKey, nil + } + + return NewPrivateKey() +} + +func Marshal(x509Cert *x509.Certificate, privateKey *ecdsa.PrivateKey) ([]byte, []byte, error) { + certBlock := pem.Block{ + Type: CertificateBlockType, + Bytes: x509Cert.Raw, + } + + keyBytes, err := x509.MarshalECPrivateKey(privateKey) + if err != nil { + return nil, nil, err + } + + keyBlock := pem.Block{ + Type: ECPrivateKeyBlockType, + Bytes: keyBytes, + } + + return pem.EncodeToMemory(&certBlock), pem.EncodeToMemory(&keyBlock), nil +} + +func NewPrivateKey() (*ecdsa.PrivateKey, error) { + return ecdsa.GenerateKey(elliptic.P256(), rand.Reader) +} diff --git a/vendor/github.com/rancher/dynamiclistener/go.mod b/vendor/github.com/rancher/dynamiclistener/go.mod index c1ca544194..f08bac29eb 100644 --- a/vendor/github.com/rancher/dynamiclistener/go.mod +++ b/vendor/github.com/rancher/dynamiclistener/go.mod @@ -3,16 +3,9 @@ module github.com/rancher/dynamiclistener go 1.12 require ( - github.com/hashicorp/golang-lru v0.5.1 - github.com/kisielk/gotool v1.0.0 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/rancher/wrangler v0.1.4 + github.com/rancher/wrangler-api v0.2.0 github.com/sirupsen/logrus v1.4.1 - github.com/stretchr/testify v1.3.0 // indirect - github.com/stripe/safesql v0.2.0 // indirect - golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284 - golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c // indirect - golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 // indirect - golang.org/x/text v0.3.2 // indirect - mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect - mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect + k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b + k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d ) diff --git a/vendor/github.com/rancher/dynamiclistener/go.sum b/vendor/github.com/rancher/dynamiclistener/go.sum index 77091287e4..b940275223 100644 --- a/vendor/github.com/rancher/dynamiclistener/go.sum +++ b/vendor/github.com/rancher/dynamiclistener/go.sum @@ -1,47 +1,132 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-containerregistry v0.0.0-20190617215043-876b8855d23c/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/jetstack/cert-manager v0.7.2/go.mod h1:nbddmhjWxYGt04bxvwVGUSeLhZ2PCyNvd7MpXdq+yWY= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knative/build v0.6.0/go.mod h1:/sU74ZQkwlYA5FwYDJhYTy61i/Kn+5eWfln2jDbw3Qo= +github.com/knative/pkg v0.0.0-20190514205332-5e4512dcb2ca/go.mod h1:7Ijfhw7rfB+H9VtosIsDYvZQ+qYTz7auK3fHW/5z4ww= +github.com/knative/serving v0.6.1/go.mod h1:ljvMfwQy2qanaM/8xnBSK4Mz3Vv2NawC2fo5kFRJS1A= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= +github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rancher/wrangler v0.1.4 h1:bdzBw4H9JKQhXPBPNp4eHbmrkA24+VII865VLiVWcw8= +github.com/rancher/wrangler v0.1.4/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= +github.com/rancher/wrangler-api v0.2.0 h1:VR7hLNnDrKykKLqthtwZ58pDDtUa9ijSNToPaJLEkWc= +github.com/rancher/wrangler-api v0.2.0/go.mod h1:zTPdNLZO07KvRaVOx6XQbKBSV55Fnn4s7nqmrMPJqd8= github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff h1:VARhShG49tiji6mdRNp7JTNDtJ0FhuprF93GBQ37xGU= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stripe/safesql v0.2.0 h1:xiefmCDd8c35PVSGrL2FhBiaKxviXnGziBDOpOejeBE= -github.com/stripe/safesql v0.2.0/go.mod h1:q7b2n0JmzM1mVGfcYpanfVb2j23cXZeWFxcILPn3JV4= +github.com/tektoncd/pipeline v0.4.0/go.mod h1:IZzJdiX9EqEMuUcgdnElozdYYRh0/ZRC+NKMLj1K3Yw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284 h1:rlLehGeYg6jfoyz/eDqDU1iRXLKfR42nnNh57ytKEWo= -golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA= +golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug= -golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b h1:aBGgKJUM9Hk/3AE8WaZIApnTxG35kbuQba2w+SXqezo= +k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE= +k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d h1:Jmdtdt1ZnoGfWWIIik61Z7nKYgO3J+swQJtPYsP9wHA= +k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= +k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible h1:U5Bt+dab9K8qaUmXINrkXO135kA11/i5Kg1RUydgaMQ= +k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= +k8s.io/code-generator v0.0.0-20190311093542-50b561225d70/go.mod h1:MYiN+ZJZ9HkETbgVZdWw2AsuAi9PZ4V80cwfuf2axe8= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503/go.mod h1:iU+ZGYsNlvU9XKUSso6SQfKTCCw7lFduMZy26Mgr2Fw= +k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y= +k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/vendor/github.com/rancher/dynamiclistener/listener.go b/vendor/github.com/rancher/dynamiclistener/listener.go new file mode 100644 index 0000000000..7ba1a6904a --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/listener.go @@ -0,0 +1,198 @@ +package dynamiclistener + +import ( + "crypto" + "crypto/tls" + "crypto/x509" + "net" + "net/http" + "sync" + + "github.com/rancher/dynamiclistener/factory" + "github.com/sirupsen/logrus" + v1 "k8s.io/api/core/v1" +) + +type TLSStorage interface { + Get() (*v1.Secret, error) + Update(secret *v1.Secret) error +} + +type Config struct { + CN string + Organization []string + TLSConfig tls.Config + SANs []string +} + +func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, caKey crypto.Signer, config Config) (net.Listener, http.Handler, error) { + if config.CN == "" { + config.CN = "dynamic" + } + if len(config.Organization) == 0 { + config.Organization = []string{"dynamic"} + } + + dynamicListener := &listener{ + factory: &factory.TLS{ + CACert: caCert, + CAKey: caKey, + CN: config.CN, + Organization: config.Organization, + }, + Listener: l, + storage: &nonNil{storage: storage}, + sans: config.SANs, + tlsConfig: config.TLSConfig, + } + dynamicListener.tlsConfig.GetCertificate = dynamicListener.getCertificate + + return tls.NewListener(dynamicListener, &dynamicListener.tlsConfig), dynamicListener.cacheHandler(), nil +} + +type listener struct { + sync.RWMutex + net.Listener + + factory *factory.TLS + storage TLSStorage + version string + tlsConfig tls.Config + cert *tls.Certificate + sans []string +} + +func (l *listener) Accept() (net.Conn, error) { + conn, err := l.Listener.Accept() + if err != nil { + return conn, err + } + + addr := conn.RemoteAddr() + if addr == nil { + return conn, nil + } + + host, _, err := net.SplitHostPort(addr.String()) + if err != nil { + logrus.Errorf("failed to parse network %s: %v", addr.Network(), err) + return conn, nil + } + + return conn, l.updateCert(host) +} + +func (l *listener) getCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { + if hello.ServerName != "" { + if err := l.updateCert(hello.ServerName); err != nil { + return nil, err + } + } + + return l.loadCert() +} + +func (l *listener) updateCert(cn string) error { + l.RLock() + defer l.RUnlock() + + secret, err := l.storage.Get() + if err != nil { + return err + } + + if !factory.NeedsUpdate(secret, append(l.sans, cn)...) { + return nil + } + + l.RUnlock() + l.Lock() + defer l.RLock() + defer l.Unlock() + + secret, updated, err := l.factory.AddCN(secret, append(l.sans, cn)...) + if err != nil { + return err + } + + if updated { + if err := l.storage.Update(secret); err != nil { + return err + } + // clear version to force cert reload + l.version = "" + } + + return nil +} + +func (l *listener) loadCert() (*tls.Certificate, error) { + l.RLock() + defer l.RUnlock() + + secret, err := l.storage.Get() + if err != nil { + return nil, err + } + if l.cert != nil && l.version == secret.ResourceVersion { + return l.cert, nil + } + + defer l.RLock() + l.RUnlock() + l.Lock() + defer l.Unlock() + + secret, err = l.storage.Get() + if err != nil { + return nil, err + } + if l.cert != nil && l.version == secret.ResourceVersion { + return l.cert, nil + } + + cert, err := tls.X509KeyPair(secret.Data[v1.TLSCertKey], secret.Data[v1.TLSPrivateKeyKey]) + if err != nil { + return nil, err + } + + l.cert = &cert + return l.cert, nil +} + +func (l *listener) cacheHandler() http.Handler { + return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + h, _, err := net.SplitHostPort(req.Host) + if err != nil { + h = req.Host + } + + ip := net.ParseIP(h) + if len(ip) > 0 { + l.updateCert(h) + } + }) +} + +type nonNil struct { + sync.Mutex + storage TLSStorage +} + +func (n *nonNil) Get() (*v1.Secret, error) { + n.Lock() + defer n.Unlock() + + s, err := n.storage.Get() + if err != nil || s == nil { + return &v1.Secret{}, err + } + return s, nil +} + +func (n *nonNil) Update(secret *v1.Secret) error { + n.Lock() + defer n.Unlock() + + return n.storage.Update(secret) +} diff --git a/vendor/github.com/rancher/dynamiclistener/read.go b/vendor/github.com/rancher/dynamiclistener/read.go deleted file mode 100644 index bf99514768..0000000000 --- a/vendor/github.com/rancher/dynamiclistener/read.go +++ /dev/null @@ -1,50 +0,0 @@ -package dynamiclistener - -import ( - "fmt" - "io/ioutil" - "path/filepath" -) - -func ReadTLSConfig(userConfig *UserConfig) error { - var err error - - path := userConfig.CertPath - - userConfig.CACerts, err = readPEM(filepath.Join(path, "cacerts.pem")) - if err != nil { - return err - } - - userConfig.Key, err = readPEM(filepath.Join(path, "key.pem")) - if err != nil { - return err - } - - userConfig.Cert, err = readPEM(filepath.Join(path, "cert.pem")) - if err != nil { - return err - } - - valid := false - if userConfig.Key != "" && userConfig.Cert != "" { - valid = true - } else if userConfig.Key == "" && userConfig.Cert == "" { - valid = true - } - - if !valid { - return fmt.Errorf("invalid SSL configuration found, please set cert/key, cert/key/cacerts, cacerts only, or none") - } - - return nil -} - -func readPEM(path string) (string, error) { - content, err := ioutil.ReadFile(path) - if err != nil { - return "", nil - } - - return string(content), nil -} diff --git a/vendor/github.com/rancher/dynamiclistener/redirect.go b/vendor/github.com/rancher/dynamiclistener/redirect.go new file mode 100644 index 0000000000..264efdee19 --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/redirect.go @@ -0,0 +1,46 @@ +package dynamiclistener + +import ( + "fmt" + "net" + "net/http" + "strconv" + "strings" +) + +// Approach taken from letsencrypt, except manglePort is specific to us +func HTTPRedirect(next http.Handler) http.Handler { + return http.HandlerFunc( + func(rw http.ResponseWriter, r *http.Request) { + fmt.Println("!!!!!", r.URL.String(), r.Header) + if r.Header.Get("x-Forwarded-Proto") == "https" || + r.Header.Get("x-Forwarded-Proto") == "wss" || + strings.HasPrefix(r.URL.Path, "/ping") || + strings.HasPrefix(r.URL.Path, "/health") { + next.ServeHTTP(rw, r) + return + } + if r.Method != "GET" && r.Method != "HEAD" { + http.Error(rw, "Use HTTPS", http.StatusBadRequest) + return + } + target := "https://" + manglePort(r.Host) + r.URL.RequestURI() + http.Redirect(rw, r, target, http.StatusFound) + }) +} + +func manglePort(hostport string) string { + host, port, err := net.SplitHostPort(hostport) + if err != nil { + return hostport + } + + portInt, err := strconv.Atoi(port) + if err != nil { + return hostport + } + + portInt = ((portInt / 1000) * 1000) + 443 + + return net.JoinHostPort(host, strconv.Itoa(portInt)) +} diff --git a/vendor/github.com/rancher/dynamiclistener/server.go b/vendor/github.com/rancher/dynamiclistener/server.go deleted file mode 100644 index 2c01dbf0b8..0000000000 --- a/vendor/github.com/rancher/dynamiclistener/server.go +++ /dev/null @@ -1,556 +0,0 @@ -package dynamiclistener - -import ( - "context" - "crypto" - "crypto/ecdsa" - "crypto/rsa" - "crypto/tls" - "crypto/x509" - "encoding/base64" - "encoding/pem" - "errors" - "fmt" - "log" - "net" - "net/http" - "reflect" - "strconv" - "strings" - "sync" - "time" - - cert "github.com/rancher/dynamiclistener/cert" - "github.com/sirupsen/logrus" -) - -type server struct { - sync.Mutex - - userConfig UserConfig - listenConfigStorage ListenerConfigStorage - tlsCert *tls.Certificate - - ips map[string]bool - domains map[string]bool - cn string - - listeners []net.Listener - servers []*http.Server - - activeCA *x509.Certificate - activeCAKey crypto.Signer -} - -func NewServer(listenConfigStorage ListenerConfigStorage, config UserConfig) (ServerInterface, error) { - s := &server{ - userConfig: config, - listenConfigStorage: listenConfigStorage, - cn: "cattle", - } - - s.ips = map[string]bool{} - s.domains = map[string]bool{} - - if err := s.userConfigure(); err != nil { - return nil, err - } - - lc, err := listenConfigStorage.Get() - if err != nil { - return nil, err - } - - return s, s.Update(lc) -} - -func (s *server) CACert() (string, error) { - if s.userConfig.NoCACerts { - return "", nil - } - if s.userConfig.CACerts != "" { - return s.userConfig.CACerts, nil - } - return "", fmt.Errorf("ca cert not found") -} - -func marshalPrivateKey(privateKey crypto.Signer) (string, []byte, error) { - var ( - keyType string - bytes []byte - err error - ) - if key, ok := privateKey.(*ecdsa.PrivateKey); ok { - keyType = cert.ECPrivateKeyBlockType - bytes, err = x509.MarshalECPrivateKey(key) - } else if key, ok := privateKey.(*rsa.PrivateKey); ok { - keyType = cert.RSAPrivateKeyBlockType - bytes = x509.MarshalPKCS1PrivateKey(key) - } else { - keyType = cert.PrivateKeyBlockType - bytes, err = x509.MarshalPKCS8PrivateKey(privateKey) - } - if err != nil { - logrus.Errorf("Unable to marshal private key: %v", err) - } - return keyType, bytes, err -} - -func newPrivateKey() (crypto.Signer, error) { - caKeyBytes, err := cert.MakeEllipticPrivateKeyPEM() - if err != nil { - return nil, err - } - caKeyIFace, err := cert.ParsePrivateKeyPEM(caKeyBytes) - if err != nil { - return nil, err - } - return caKeyIFace.(crypto.Signer), nil -} - -func (s *server) save() (_err error) { - defer func() { - if _err != nil { - logrus.Errorf("Saving cert error: %s", _err) - } - }() - - certStr, err := certToString(s.tlsCert) - if err != nil { - return err - } - cfg, err := s.listenConfigStorage.Get() - if err != nil { - return err - } - cfg.GeneratedCerts = map[string]string{s.cn: certStr} - - _, err = s.listenConfigStorage.Set(cfg) - return err -} - -func (s *server) userConfigure() error { - if s.userConfig.HTTPSPort == 0 { - s.userConfig.HTTPSPort = 8443 - } - - for _, d := range s.userConfig.Domains { - s.domains[d] = true - } - - for _, ip := range s.userConfig.KnownIPs { - if netIP := net.ParseIP(ip); netIP != nil { - s.ips[ip] = true - } - } - - if bindAddress := net.ParseIP(s.userConfig.BindAddress); bindAddress != nil { - s.ips[s.userConfig.BindAddress] = true - } - - if s.activeCA == nil && s.activeCAKey == nil { - if s.userConfig.CACerts != "" && s.userConfig.CAKey != "" { - ca, err := cert.ParseCertsPEM([]byte(s.userConfig.CACerts)) - if err != nil { - return err - } - key, err := cert.ParsePrivateKeyPEM([]byte(s.userConfig.CAKey)) - if err != nil { - return err - } - s.activeCA = ca[0] - s.activeCAKey = key.(crypto.Signer) - } else { - ca, key, err := genCA() - if err != nil { - return err - } - s.activeCA = ca - s.activeCAKey = key - } - } - - return nil -} - -func genCA() (*x509.Certificate, crypto.Signer, error) { - caKey, err := newPrivateKey() - if err != nil { - return nil, nil, err - } - - caCert, err := cert.NewSelfSignedCACert(cert.Config{ - CommonName: "k3s-ca", - Organization: []string{"k3s-org"}, - }, caKey) - if err != nil { - return nil, nil, err - } - - return caCert, caKey, nil -} - -func (s *server) Update(status *ListenerStatus) (_err error) { - s.Lock() - defer func() { - s.Unlock() - if _err != nil { - logrus.Errorf("Update cert error: %s", _err) - } - if s.tlsCert == nil { - s.getCertificate(&tls.ClientHelloInfo{ServerName: "localhost"}) - } - }() - - certString := status.GeneratedCerts[s.cn] - tlsCert, err := stringToCert(certString) - if err != nil { - logrus.Errorf("Update cert unable to convert string to cert: %s", err) - s.tlsCert = nil - } - if tlsCert != nil { - s.tlsCert = tlsCert - for i, certBytes := range tlsCert.Certificate { - parsedCert, err := x509.ParseCertificate(certBytes) - if err != nil { - logrus.Errorf("Update cert %d parse error: %s", i, err) - s.tlsCert = nil - break - } - isExpired := cert.IsCertExpired(parsedCert) - if isExpired { - logrus.Infof("certificate is about to expire") - s.tlsCert = nil - break - } - ips := map[string]bool{} - for _, ip := range parsedCert.IPAddresses { - ips[ip.String()] = true - } - - domains := map[string]bool{} - for _, domain := range parsedCert.DNSNames { - domains[domain] = true - } - - if !(reflect.DeepEqual(ips, s.ips) && reflect.DeepEqual(domains, s.domains)) { - subset := true - for ip := range s.ips { - if !ips[ip] { - subset = false - break - } - } - if subset { - for domain := range s.domains { - if !domains[domain] { - subset = false - break - } - } - } - if !subset { - s.tlsCert = nil - } - for ip := range ips { - s.ips[ip] = true - } - for domain := range domains { - s.domains[domain] = true - } - } - } - } - - return s.reload() -} - -func (s *server) shutdown() error { - for _, listener := range s.listeners { - if err := listener.Close(); err != nil { - return err - } - } - s.listeners = nil - - for _, server := range s.servers { - go server.Shutdown(context.Background()) - } - s.servers = nil - - return nil -} - -func (s *server) reload() error { - if len(s.listeners) > 0 { - return nil - } - - if err := s.shutdown(); err != nil { - return err - } - - if err := s.serveHTTPS(); err != nil { - return err - } - - return nil -} - -func (s *server) getCertificate(hello *tls.ClientHelloInfo) (_servingCert *tls.Certificate, _err error) { - s.Lock() - changed := false - - defer func() { - defer s.Unlock() - - if _err != nil { - logrus.Errorf("Get certificate error: %s", _err) - return - } - - if changed { - s.save() - } - }() - - if hello.ServerName != "" && !s.domains[hello.ServerName] { - s.tlsCert = nil - s.domains[hello.ServerName] = true - } - - if s.tlsCert != nil { - return s.tlsCert, nil - } - - ips := []net.IP{} - for ipStr := range s.ips { - if ip := net.ParseIP(ipStr); ip != nil { - ips = append(ips, ip) - } - } - - dnsNames := []string{} - for domain := range s.domains { - dnsNames = append(dnsNames, domain) - } - - cfg := cert.Config{ - CommonName: s.cn, - Organization: s.activeCA.Subject.Organization, - Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - AltNames: cert.AltNames{ - DNSNames: dnsNames, - IPs: ips, - }, - } - - key, err := newPrivateKey() - if err != nil { - return nil, err - } - - cert, err := cert.NewSignedCert(cfg, key, s.activeCA, s.activeCAKey) - if err != nil { - return nil, err - } - - tlsCert := &tls.Certificate{ - Certificate: [][]byte{ - cert.Raw, - }, - PrivateKey: key, - } - - changed = true - s.tlsCert = tlsCert - return tlsCert, nil -} - -func (s *server) cacheHandler(handler http.Handler) http.Handler { - return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - h, _, err := net.SplitHostPort(req.Host) - if err != nil { - h = req.Host - } - - s.Lock() - if ip := net.ParseIP(h); ip != nil { - if !s.ips[h] { - s.ips[h] = true - s.tlsCert = nil - } - } else { - if !s.domains[h] { - s.domains[h] = true - s.tlsCert = nil - } - } - s.Unlock() - - handler.ServeHTTP(resp, req) - }) -} - -func (s *server) serveHTTPS() error { - conf := &tls.Config{ - ClientAuth: tls.RequestClientCert, - GetCertificate: s.getCertificate, - PreferServerCipherSuites: true, - } - - listener, err := s.newListener(s.userConfig.BindAddress, s.userConfig.HTTPSPort, conf) - if err != nil { - return err - } - - logger := logrus.StandardLogger() - server := &http.Server{ - Handler: s.cacheHandler(s.Handler()), - ErrorLog: log.New(logger.WriterLevel(logrus.DebugLevel), "", log.LstdFlags), - } - - s.servers = append(s.servers, server) - s.startServer(listener, server) - - if s.userConfig.HTTPPort > 0 { - httpListener, err := s.newListener(s.userConfig.BindAddress, s.userConfig.HTTPPort, nil) - if err != nil { - return err - } - - httpServer := &http.Server{ - Handler: s.cacheHandler(httpRedirect(s.Handler())), - ErrorLog: log.New(logger.WriterLevel(logrus.DebugLevel), "", log.LstdFlags), - } - - s.servers = append(s.servers, httpServer) - s.startServer(httpListener, httpServer) - } - - return nil -} - -// Approach taken from letsencrypt, except manglePort is specific to us -func httpRedirect(next http.Handler) http.Handler { - return http.HandlerFunc( - func(rw http.ResponseWriter, r *http.Request) { - if r.Header.Get("x-Forwarded-Proto") == "https" || - strings.HasPrefix(r.URL.Path, "/ping") || - strings.HasPrefix(r.URL.Path, "/health") { - next.ServeHTTP(rw, r) - return - } - if r.Method != "GET" && r.Method != "HEAD" { - http.Error(rw, "Use HTTPS", http.StatusBadRequest) - return - } - target := "https://" + manglePort(r.Host) + r.URL.RequestURI() - http.Redirect(rw, r, target, http.StatusFound) - }) -} - -func manglePort(hostport string) string { - host, port, err := net.SplitHostPort(hostport) - if err != nil { - return hostport - } - - portInt, err := strconv.Atoi(port) - if err != nil { - return hostport - } - - portInt = ((portInt / 1000) * 1000) + 443 - - return net.JoinHostPort(host, strconv.Itoa(portInt)) -} - -func (s *server) startServer(listener net.Listener, server *http.Server) { - go func() { - if err := server.Serve(listener); err != nil { - logrus.Errorf("server on %v returned err: %v", listener.Addr(), err) - } - }() -} - -func (s *server) Handler() http.Handler { - return s.userConfig.Handler -} - -func (s *server) newListener(ip string, port int, config *tls.Config) (net.Listener, error) { - addr := fmt.Sprintf("%s:%d", ip, port) - l, err := net.Listen("tcp", addr) - if err != nil { - return nil, err - } - - l = tcpKeepAliveListener{l.(*net.TCPListener)} - - if config != nil { - l = tls.NewListener(l, config) - } - - s.listeners = append(s.listeners, l) - logrus.Info("Listening on ", addr) - return l, nil -} - -func stringToCert(certString string) (*tls.Certificate, error) { - parts := strings.Split(certString, "#") - if len(parts) != 2 { - return nil, errors.New("Unable to split cert into two parts") - } - - certPart, keyPart := parts[0], parts[1] - keyBytes, err := base64.StdEncoding.DecodeString(keyPart) - if err != nil { - return nil, err - } - - key, err := cert.ParsePrivateKeyPEM(keyBytes) - if err != nil { - return nil, err - } - - certBytes, err := base64.StdEncoding.DecodeString(certPart) - if err != nil { - return nil, err - } - - return &tls.Certificate{ - Certificate: [][]byte{certBytes}, - PrivateKey: key, - }, nil -} - -func certToString(cert *tls.Certificate) (string, error) { - keyType, keyBytes, err := marshalPrivateKey(cert.PrivateKey.(crypto.Signer)) - if err != nil { - return "", err - } - - privateKeyPemBlock := &pem.Block{ - Type: keyType, - Bytes: keyBytes, - } - pemBytes := pem.EncodeToMemory(privateKeyPemBlock) - - certString := base64.StdEncoding.EncodeToString(cert.Certificate[0]) - keyString := base64.StdEncoding.EncodeToString(pemBytes) - return certString + "#" + keyString, nil -} - -type tcpKeepAliveListener struct { - *net.TCPListener -} - -func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { - tc, err := ln.AcceptTCP() - if err != nil { - return - } - tc.SetKeepAlive(true) - tc.SetKeepAlivePeriod(3 * time.Minute) - return tc, nil -} diff --git a/vendor/github.com/rancher/dynamiclistener/storage/file/file.go b/vendor/github.com/rancher/dynamiclistener/storage/file/file.go new file mode 100644 index 0000000000..ba738bcdbe --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/storage/file/file.go @@ -0,0 +1,42 @@ +package file + +import ( + "encoding/json" + "github.com/rancher/dynamiclistener" + "k8s.io/api/core/v1" + "os" +) + +func New(file string) dynamiclistener.TLSStorage { + return &storage{ + file: file, + } +} + +type storage struct { + file string +} + +func (s *storage) Get() (*v1.Secret, error) { + f, err := os.Open(s.file) + if os.IsNotExist(err) { + return nil, nil + } else if err != nil { + return nil, err + } + defer f.Close() + + secret := v1.Secret{} + return &secret, json.NewDecoder(f).Decode(&secret) +} + +func (s *storage) Update(secret *v1.Secret) error { + f, err := os.Create(s.file) + if err != nil { + return err + } + defer f.Close() + + return json.NewEncoder(f).Encode(secret) +} + diff --git a/vendor/github.com/rancher/dynamiclistener/storage/kubernetes/controller.go b/vendor/github.com/rancher/dynamiclistener/storage/kubernetes/controller.go new file mode 100644 index 0000000000..d5198a2c9d --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/storage/kubernetes/controller.go @@ -0,0 +1,109 @@ +package kubernetes + +import ( + "context" + "sync" + "time" + + "github.com/rancher/dynamiclistener" + "github.com/rancher/wrangler-api/pkg/generated/controllers/core" + v1controller "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" + "github.com/rancher/wrangler/pkg/start" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" +) + +type CoreGetter func() *core.Factory + +func New(ctx context.Context, core CoreGetter, namespace, name string, backing dynamiclistener.TLSStorage) dynamiclistener.TLSStorage { + storage := &storage{ + name: name, + namespace: namespace, + storage: backing, + ctx: ctx, + } + + // lazy init + go func() { + for { + core := core() + if core != nil { + storage.init(core.Core().V1().Secret()) + start.All(ctx, 5, core) + return + } + + select { + case <-ctx.Done(): + return + case <-time.After(time.Second): + } + } + }() + + return storage +} + +type storage struct { + sync.Mutex + + namespace, name string + storage dynamiclistener.TLSStorage + secrets v1controller.SecretClient + ctx context.Context +} + +func (s *storage) init(secrets v1controller.SecretController) { + s.Lock() + defer s.Unlock() + + secrets.OnChange(s.ctx, "tls-storage", func(key string, secret *v1.Secret) (*v1.Secret, error) { + if secret == nil { + return nil, nil + } + if secret.Namespace == s.namespace && secret.Name == s.name { + if err := s.Update(secret); err != nil { + return nil, err + } + } + + return secret, nil + }) + s.secrets = secrets +} + +func (s *storage) Get() (*v1.Secret, error) { + s.Lock() + defer s.Unlock() + + return s.storage.Get() +} + +func (s *storage) Update(secret *v1.Secret) (err error) { + s.Lock() + defer s.Unlock() + + if s.secrets != nil { + if secret.UID == "" { + secret.Name = s.name + secret.Namespace = s.namespace + secret, err = s.secrets.Create(secret) + if err != nil { + return err + } + } else { + existingSecret, err := s.storage.Get() + if err != nil { + return err + } + if !equality.Semantic.DeepEqual(secret.Data, existingSecret.Data) { + secret, err = s.secrets.Update(secret) + if err != nil { + return err + } + } + } + } + + return s.storage.Update(secret) +} diff --git a/vendor/github.com/rancher/dynamiclistener/storage/memory/memory.go b/vendor/github.com/rancher/dynamiclistener/storage/memory/memory.go new file mode 100644 index 0000000000..079f180739 --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/storage/memory/memory.go @@ -0,0 +1,42 @@ +package memory + +import ( + "github.com/rancher/dynamiclistener" + v1 "k8s.io/api/core/v1" +) + +func New() dynamiclistener.TLSStorage { + return &memory{} +} + +func NewBacked(storage dynamiclistener.TLSStorage) dynamiclistener.TLSStorage { + return &memory{storage: storage} +} + +type memory struct { + storage dynamiclistener.TLSStorage + secret *v1.Secret +} + +func (m *memory) Get() (*v1.Secret, error) { + if m.secret == nil && m.storage != nil { + secret, err := m.storage.Get() + if err != nil { + return nil, err + } + m.secret = secret + } + + return m.secret, nil +} + +func (m *memory) Update(secret *v1.Secret) error { + if m.storage != nil { + if err := m.storage.Update(secret); err != nil { + return err + } + } + + m.secret = secret + return nil +} diff --git a/vendor/github.com/rancher/dynamiclistener/tcp.go b/vendor/github.com/rancher/dynamiclistener/tcp.go new file mode 100644 index 0000000000..3f41588ccc --- /dev/null +++ b/vendor/github.com/rancher/dynamiclistener/tcp.go @@ -0,0 +1,38 @@ +package dynamiclistener + +import ( + "fmt" + "net" + "reflect" + "time" +) + +func NewTCPListener(ip string, port int) (net.Listener, error) { + l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", ip, port)) + if err != nil { + return nil, err + } + + tcpListener, ok := l.(*net.TCPListener) + if !ok { + return nil, fmt.Errorf("wrong listener type: %v", reflect.TypeOf(tcpListener)) + } + + return tcpKeepAliveListener{ + TCPListener: tcpListener, + }, nil +} + +type tcpKeepAliveListener struct { + *net.TCPListener +} + +func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { + tc, err := ln.AcceptTCP() + if err != nil { + return + } + tc.SetKeepAlive(true) + tc.SetKeepAlivePeriod(3 * time.Minute) + return tc, nil +} diff --git a/vendor/github.com/rancher/dynamiclistener/types.go b/vendor/github.com/rancher/dynamiclistener/types.go deleted file mode 100644 index 7fabf1c950..0000000000 --- a/vendor/github.com/rancher/dynamiclistener/types.go +++ /dev/null @@ -1,63 +0,0 @@ -package dynamiclistener - -import ( - "net/http" -) - -type ListenerConfigStorage interface { - Set(*ListenerStatus) (*ListenerStatus, error) - Get() (*ListenerStatus, error) -} - -type ServerInterface interface { - Update(status *ListenerStatus) error - CACert() (string, error) -} - -type UserConfig struct { - // Required fields - - Handler http.Handler - HTTPPort int - HTTPSPort int - CertPath string - - // Optional fields - - KnownIPs []string - Domains []string - Mode string - NoCACerts bool - CACerts string - CAKey string - Cert string - Key string - BindAddress string -} - -type ListenerStatus struct { - Revision string `json:"revision,omitempty"` - CACert string `json:"caCert,omitempty"` - CAKey string `json:"caKey,omitempty"` - GeneratedCerts map[string]string `json:"generatedCerts" norman:"nocreate,noupdate"` - KnownIPs map[string]bool `json:"knownIps" norman:"nocreate,noupdate"` -} - -func (l *ListenerStatus) DeepCopyInto(t *ListenerStatus) { - t.Revision = l.Revision - t.CACert = l.CACert - t.CAKey = l.CAKey - t.GeneratedCerts = copyMap(t.GeneratedCerts) - t.KnownIPs = map[string]bool{} - for k, v := range l.KnownIPs { - t.KnownIPs[k] = v - } -} - -func copyMap(m map[string]string) map[string]string { - ret := map[string]string{} - for k, v := range m { - ret[k] = v - } - return ret -} diff --git a/vendor/github.com/rancher/kine/pkg/client/client.go b/vendor/github.com/rancher/kine/pkg/client/client.go deleted file mode 100644 index 1b41f73c58..0000000000 --- a/vendor/github.com/rancher/kine/pkg/client/client.go +++ /dev/null @@ -1,107 +0,0 @@ -package client - -import ( - "context" - "fmt" - "time" - - "github.com/coreos/etcd/clientv3" - "github.com/rancher/kine/pkg/endpoint" -) - -type Value struct { - Data []byte - Modified int64 -} - -type Client interface { - Get(ctx context.Context, key string) (Value, error) - Put(ctx context.Context, key string, value []byte) error - Create(ctx context.Context, key string, value []byte) error - Update(ctx context.Context, key string, revision int64, value []byte) error - Close() error -} - -type client struct { - c *clientv3.Client -} - -func New(config endpoint.ETCDConfig) (Client, error) { - tlsConfig, err := config.TLSConfig.ClientConfig() - if err != nil { - return nil, err - } - - c, err := clientv3.New(clientv3.Config{ - Endpoints: config.Endpoints, - DialTimeout: 5 * time.Second, - TLS: tlsConfig, - }) - if err != nil { - return nil, err - } - - return &client{ - c: c, - }, nil -} - -func (c *client) Get(ctx context.Context, key string) (Value, error) { - resp, err := c.c.Get(ctx, key) - if err != nil { - return Value{}, err - } - - if len(resp.Kvs) == 1 { - return Value{ - Data: resp.Kvs[0].Value, - Modified: resp.Kvs[0].ModRevision, - }, nil - } - - return Value{}, nil -} - -func (c *client) Put(ctx context.Context, key string, value []byte) error { - val, err := c.Get(ctx, key) - if err != nil { - return err - } - if val.Modified == 0 { - return c.Create(ctx, key, value) - } - return c.Update(ctx, key, val.Modified, value) -} - -func (c *client) Create(ctx context.Context, key string, value []byte) error { - resp, err := c.c.Txn(ctx). - If(clientv3.Compare(clientv3.ModRevision(key), "=", 0)). - Then(clientv3.OpPut(key, string(value))). - Commit() - if err != nil { - return err - } - if !resp.Succeeded { - return fmt.Errorf("key exists") - } - return nil -} - -func (c *client) Update(ctx context.Context, key string, revision int64, value []byte) error { - resp, err := c.c.Txn(ctx). - If(clientv3.Compare(clientv3.ModRevision(key), "=", revision)). - Then(clientv3.OpPut(key, string(value))). - Else(clientv3.OpGet(key)). - Commit() - if err != nil { - return err - } - if !resp.Succeeded { - return fmt.Errorf("revision %d doesnt match", revision) - } - return nil -} - -func (c *client) Close() error { - return c.c.Close() -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 48315445a4..2b20da90cf 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -479,9 +479,9 @@ github.com/godbus/dbus github.com/gogo/googleapis/google/rpc # github.com/gogo/protobuf v1.3.0 github.com/gogo/protobuf/types -github.com/gogo/protobuf/gogoproto github.com/gogo/protobuf/proto github.com/gogo/protobuf/sortkeys +github.com/gogo/protobuf/gogoproto github.com/gogo/protobuf/protoc-gen-gogo/descriptor # github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef github.com/golang/groupcache/lru @@ -617,7 +617,7 @@ github.com/json-iterator/go github.com/juju/errors # github.com/karrick/godirwalk v1.7.5 github.com/karrick/godirwalk -# github.com/konsorten/go-windows-terminal-sequences v1.0.2 +# github.com/konsorten/go-windows-terminal-sequences v1.0.1 github.com/konsorten/go-windows-terminal-sequences # github.com/kubernetes-sigs/cri-tools v0.0.0-00010101000000-000000000000 => github.com/rancher/cri-tools v1.16.1-k3s.1 github.com/kubernetes-sigs/cri-tools/cmd/crictl @@ -726,8 +726,12 @@ github.com/prometheus/procfs/internal/util # github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 github.com/rakelkar/gonetsh/netroute github.com/rakelkar/gonetsh/netsh -# github.com/rancher/dynamiclistener v0.1.1-0.20191010011134-8a2488bc860a +# github.com/rancher/dynamiclistener v0.1.1-0.20191031022009-6224794ef3cb github.com/rancher/dynamiclistener +github.com/rancher/dynamiclistener/factory +github.com/rancher/dynamiclistener/storage/file +github.com/rancher/dynamiclistener/storage/kubernetes +github.com/rancher/dynamiclistener/storage/memory github.com/rancher/dynamiclistener/cert # github.com/rancher/helm-controller v0.2.2 github.com/rancher/helm-controller/pkg/generated/controllers/helm.cattle.io @@ -745,7 +749,6 @@ github.com/rancher/helm-controller/pkg/generated/informers/externalversions/inte github.com/rancher/helm-controller/pkg/apis/helm.cattle.io # github.com/rancher/kine v0.0.0-00010101000000-000000000000 => github.com/ibuildthecloud/kine v0.1.0 github.com/rancher/kine/pkg/endpoint -github.com/rancher/kine/pkg/client github.com/rancher/kine/pkg/drivers/mysql github.com/rancher/kine/pkg/drivers/pgsql github.com/rancher/kine/pkg/drivers/sqlite @@ -758,8 +761,8 @@ github.com/rancher/kine/pkg/broadcaster # github.com/rancher/remotedialer v0.2.0 github.com/rancher/remotedialer # github.com/rancher/wrangler v0.2.0 -github.com/rancher/wrangler/pkg/start github.com/rancher/wrangler/pkg/signals +github.com/rancher/wrangler/pkg/start github.com/rancher/wrangler/pkg/controller-gen github.com/rancher/wrangler/pkg/controller-gen/args github.com/rancher/wrangler/pkg/cleanup @@ -1021,15 +1024,15 @@ google.golang.org/api/transport/http/internal/propagation # google.golang.org/appengine v1.5.0 google.golang.org/appengine/cloudsql google.golang.org/appengine/urlfetch +google.golang.org/appengine google.golang.org/appengine/internal google.golang.org/appengine/internal/urlfetch -google.golang.org/appengine +google.golang.org/appengine/internal/app_identity +google.golang.org/appengine/internal/modules google.golang.org/appengine/internal/base google.golang.org/appengine/internal/datastore google.golang.org/appengine/internal/log google.golang.org/appengine/internal/remote_api -google.golang.org/appengine/internal/app_identity -google.golang.org/appengine/internal/modules # google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 google.golang.org/genproto/googleapis/rpc/status google.golang.org/genproto/googleapis/api/annotations @@ -1092,12 +1095,14 @@ k8s.io/api/core/v1 k8s.io/api/extensions/v1beta1 k8s.io/api/networking/v1 k8s.io/api/apps/v1 +k8s.io/api/authentication/v1 +k8s.io/api/autoscaling/v1 +k8s.io/api/policy/v1beta1 k8s.io/api/apps/v1beta1 k8s.io/api/admissionregistration/v1 k8s.io/api/admissionregistration/v1beta1 k8s.io/api/apps/v1beta2 k8s.io/api/auditregistration/v1alpha1 -k8s.io/api/autoscaling/v1 k8s.io/api/autoscaling/v2beta1 k8s.io/api/autoscaling/v2beta2 k8s.io/api/batch/v1 @@ -1111,7 +1116,6 @@ k8s.io/api/events/v1beta1 k8s.io/api/networking/v1beta1 k8s.io/api/node/v1alpha1 k8s.io/api/node/v1beta1 -k8s.io/api/policy/v1beta1 k8s.io/api/rbac/v1 k8s.io/api/rbac/v1alpha1 k8s.io/api/rbac/v1beta1 @@ -1122,7 +1126,6 @@ k8s.io/api/settings/v1alpha1 k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 -k8s.io/api/authentication/v1 k8s.io/api/authentication/v1beta1 k8s.io/api/authorization/v1 k8s.io/api/authorization/v1beta1 @@ -1178,9 +1181,10 @@ k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensio k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1 k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1 # k8s.io/apimachinery v0.0.0 => github.com/rancher/kubernetes/staging/src/k8s.io/apimachinery v1.16.2-k3s.1 +k8s.io/apimachinery/pkg/api/equality +k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/apimachinery/pkg/util/json k8s.io/apimachinery/pkg/util/net -k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/apimachinery/pkg/labels k8s.io/apimachinery/pkg/util/intstr k8s.io/apimachinery/pkg/fields @@ -1193,20 +1197,20 @@ k8s.io/apimachinery/pkg/apis/meta/v1/unstructured k8s.io/apimachinery/pkg/util/yaml k8s.io/apimachinery/pkg/runtime/serializer k8s.io/apimachinery/pkg/util/runtime -k8s.io/apimachinery/pkg/api/equality +k8s.io/apimachinery/pkg/api/resource +k8s.io/apimachinery/pkg/conversion +k8s.io/apimachinery/pkg/selection k8s.io/apimachinery/pkg/util/errors k8s.io/apimachinery/pkg/util/validation k8s.io/apimachinery/pkg/util/sets k8s.io/apimachinery/pkg/util/wait k8s.io/apimachinery/pkg/util/strategicpatch -k8s.io/apimachinery/pkg/api/resource -k8s.io/apimachinery/pkg/conversion -k8s.io/apimachinery/pkg/selection k8s.io/apimachinery/pkg/api/meta k8s.io/apimachinery/pkg/util/cache k8s.io/apimachinery/pkg/util/clock k8s.io/apimachinery/pkg/util/diff k8s.io/apimachinery/pkg/util/naming +k8s.io/apimachinery/pkg/runtime/serializer/streaming k8s.io/apimachinery/pkg/conversion/queryparams k8s.io/apimachinery/pkg/api/validation/path k8s.io/apimachinery/pkg/apis/meta/internalversion @@ -1215,7 +1219,6 @@ k8s.io/apimachinery/pkg/util/rand k8s.io/apimachinery/pkg/util/jsonmergepatch k8s.io/apimachinery/pkg/util/validation/field k8s.io/apimachinery/pkg/version -k8s.io/apimachinery/pkg/runtime/serializer/streaming k8s.io/apimachinery/pkg/runtime/serializer/json k8s.io/apimachinery/pkg/runtime/serializer/protobuf k8s.io/apimachinery/pkg/runtime/serializer/recognizer @@ -1224,9 +1227,9 @@ k8s.io/apimachinery/pkg/util/waitgroup k8s.io/apimachinery/pkg/util/httpstream k8s.io/apimachinery/pkg/util/remotecommand k8s.io/apimachinery/pkg/util/httpstream/spdy +k8s.io/apimachinery/third_party/forked/golang/reflect k8s.io/apimachinery/pkg/util/mergepatch k8s.io/apimachinery/third_party/forked/golang/json -k8s.io/apimachinery/third_party/forked/golang/reflect k8s.io/apimachinery/pkg/util/version k8s.io/apimachinery/pkg/util/proxy k8s.io/apimachinery/pkg/apis/meta/v1beta1 @@ -1366,31 +1369,22 @@ k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/hash k8s.io/cli-runtime/pkg/kustomize/k8sdeps/transformer/patch k8s.io/cli-runtime/pkg/kustomize/k8sdeps/kv # k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible => github.com/rancher/kubernetes/staging/src/k8s.io/client-go v1.16.2-k3s.1 -k8s.io/client-go/tools/clientcmd -k8s.io/client-go/util/cert k8s.io/client-go/kubernetes +k8s.io/client-go/kubernetes/typed/core/v1 +k8s.io/client-go/tools/clientcmd k8s.io/client-go/informers k8s.io/client-go/listers/core/v1 k8s.io/client-go/tools/cache -k8s.io/client-go/transport +k8s.io/client-go/rest k8s.io/client-go/tools/clientcmd/api k8s.io/client-go/discovery -k8s.io/client-go/rest k8s.io/client-go/util/flowcontrol k8s.io/client-go/discovery/fake k8s.io/client-go/testing k8s.io/client-go/kubernetes/typed/apps/v1 -k8s.io/client-go/kubernetes/typed/core/v1 k8s.io/client-go/tools/portforward k8s.io/client-go/tools/remotecommand k8s.io/client-go/transport/spdy -k8s.io/client-go/informers/core -k8s.io/client-go/kubernetes/scheme -k8s.io/client-go/informers/core/v1 -k8s.io/client-go/tools/auth -k8s.io/client-go/tools/clientcmd/api/latest -k8s.io/client-go/util/homedir -k8s.io/client-go/util/keyutil k8s.io/client-go/kubernetes/typed/admissionregistration/v1 k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1 k8s.io/client-go/kubernetes/typed/apps/v1beta1 @@ -1427,6 +1421,11 @@ k8s.io/client-go/kubernetes/typed/settings/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1 k8s.io/client-go/kubernetes/typed/storage/v1alpha1 k8s.io/client-go/kubernetes/typed/storage/v1beta1 +k8s.io/client-go/kubernetes/scheme +k8s.io/client-go/tools/reference +k8s.io/client-go/tools/auth +k8s.io/client-go/tools/clientcmd/api/latest +k8s.io/client-go/util/homedir k8s.io/client-go/informers/admissionregistration k8s.io/client-go/informers/apps k8s.io/client-go/informers/auditregistration @@ -1434,6 +1433,7 @@ k8s.io/client-go/informers/autoscaling k8s.io/client-go/informers/batch k8s.io/client-go/informers/certificates k8s.io/client-go/informers/coordination +k8s.io/client-go/informers/core k8s.io/client-go/informers/discovery k8s.io/client-go/informers/events k8s.io/client-go/informers/extensions @@ -1447,10 +1447,17 @@ k8s.io/client-go/informers/settings k8s.io/client-go/informers/storage k8s.io/client-go/tools/pager k8s.io/client-go/util/retry +k8s.io/client-go/pkg/version +k8s.io/client-go/plugin/pkg/client/auth/exec +k8s.io/client-go/rest/watch +k8s.io/client-go/tools/metrics +k8s.io/client-go/transport +k8s.io/client-go/util/cert +k8s.io/client-go/informers/core/v1 k8s.io/client-go/tools/record k8s.io/client-go/util/certificate k8s.io/client-go/util/connrotation -k8s.io/client-go/tools/metrics +k8s.io/client-go/util/keyutil k8s.io/client-go/tools/leaderelection k8s.io/client-go/tools/leaderelection/resourcelock k8s.io/client-go/discovery/cached @@ -1460,13 +1467,9 @@ k8s.io/client-go/metadata k8s.io/client-go/metadata/metadatainformer k8s.io/client-go/restmapper k8s.io/client-go/scale -k8s.io/client-go/pkg/version -k8s.io/client-go/plugin/pkg/client/auth/exec -k8s.io/client-go/rest/watch k8s.io/client-go/util/workqueue k8s.io/client-go/informers/apps/v1 k8s.io/client-go/listers/apps/v1 -k8s.io/client-go/tools/reference k8s.io/client-go/util/exec k8s.io/client-go/tools/clientcmd/api/v1 k8s.io/client-go/informers/admissionregistration/v1 @@ -1501,6 +1504,9 @@ k8s.io/client-go/informers/settings/v1alpha1 k8s.io/client-go/informers/storage/v1 k8s.io/client-go/informers/storage/v1alpha1 k8s.io/client-go/informers/storage/v1beta1 +k8s.io/client-go/pkg/apis/clientauthentication +k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 +k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 k8s.io/client-go/tools/record/util k8s.io/client-go/util/certificate/csr k8s.io/client-go/listers/storage/v1beta1 @@ -1522,9 +1528,6 @@ k8s.io/client-go/listers/coordination/v1beta1 k8s.io/client-go/listers/autoscaling/v1 k8s.io/client-go/listers/storage/v1 k8s.io/client-go/tools/events -k8s.io/client-go/pkg/apis/clientauthentication -k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 -k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 k8s.io/client-go/discovery/cached/disk k8s.io/client-go/util/jsonpath k8s.io/client-go/listers/admissionregistration/v1