diff --git a/cmd/cluster.go b/cmd/cluster.go index a2fde46c..3fe57ffc 100644 --- a/cmd/cluster.go +++ b/cmd/cluster.go @@ -8,6 +8,7 @@ import ( "net" "net/http" "os" + "slices" "sort" "strconv" "strings" @@ -314,6 +315,8 @@ func newClusterCmd(c *config) *cobra.Command { clusterCreateCmd.Flags().String("cni", "", "the network plugin used in this cluster, defaults to calico. please note that cilium support is still Alpha and we are happy to receive feedback. [optional]") clusterCreateCmd.Flags().BoolP("enable-node-local-dns", "", false, "enables node local dns cache on the cluster nodes. [optional].") clusterCreateCmd.Flags().BoolP("disable-forwarding-to-upstream-dns", "", false, "disables direct forwarding of queries to external dns servers when node-local-dns is enabled. All dns queries will go through coredns. [optional].") + clusterCreateCmd.Flags().StringSlice("kube-apiserver-acl-allowed-cidrs", []string{}, "comma-separated list of external CIDRs allowed to connect to the kube-apiserver (e.g. \"212.34.68.0/24,212.34.89.0/27\")") + clusterCreateCmd.Flags().Bool("enable-kube-apiserver-acl", false, "restricts access from outside to the kube-apiserver to the source ip addresses set by --kube-apiserver-acl-allowed-cidrs [optional].") must(clusterCreateCmd.MarkFlagRequired("name")) must(clusterCreateCmd.MarkFlagRequired("project")) @@ -400,6 +403,10 @@ func newClusterCmd(c *config) *cobra.Command { clusterUpdateCmd.Flags().BoolP("disable-custom-default-storage-class", "", false, "if set to true, no default class is deployed, you have to set one of your storageclasses manually to default") clusterUpdateCmd.Flags().BoolP("enable-node-local-dns", "", false, "enables node local dns cache on the cluster nodes. [optional]. WARNING: changing this value will lead to rolling of the worker nodes [optional]") clusterUpdateCmd.Flags().BoolP("disable-forwarding-to-upstream-dns", "", false, "disables direct forwarding of queries to external dns servers when node-local-dns is enabled. All dns queries will go through coredns [optional].") + clusterUpdateCmd.Flags().StringSlice("kube-apiserver-acl-set-allowed-cidrs", []string{}, "comma-separated list of external CIDRs allowed to connect to the kube-apiserver (e.g. \"212.34.68.0/24,212.34.89.0/27\")") + clusterUpdateCmd.Flags().StringSlice("kube-apiserver-acl-add-to-allowed-cidrs", []string{}, "comma-separated list of external CIDRs to add to the allowed CIDRs to connect to the kube-apiserver (e.g. \"212.34.68.0/24,212.34.89.0/27\")") + clusterUpdateCmd.Flags().StringSlice("kube-apiserver-acl-remove-from-allowed-cidrs", []string{}, "comma-separated list of external CIDRs to be removed from the allowed CIDRs to connect to the kube-apiserver (e.g. \"212.34.68.0/24,212.34.89.0/27\")") + clusterUpdateCmd.Flags().Bool("enable-kube-apiserver-acl", false, "restricts access from outside to the kube-apiserver to the source ip addresses set by --kube-apiserver-acl-* [optional].") must(clusterUpdateCmd.RegisterFlagCompletionFunc("version", c.comp.VersionListCompletion)) must(clusterUpdateCmd.RegisterFlagCompletionFunc("workerversion", c.comp.VersionListCompletion)) @@ -716,6 +723,26 @@ func (c *config) clusterCreate() error { scr.SystemComponents.NodeLocalDNS.DisableForwardToUpstreamDNS = &disableForwardToUpstreamDNS } + if viper.IsSet("kube-apiserver-acl-allowed-cidrs") || viper.IsSet("enable-kube-apiserver-acl") { + + if !viper.GetBool("yes-i-really-mean-it") && viper.IsSet("enable-kube-apiserver-acl") { + return fmt.Errorf("--enable-kube-apiserver-acl is set but you forgot to add --yes-i-really-mean-it") + } + + if viper.GetBool("enable-kube-apiserver-acl") { + fmt.Println("WARNING: Restricting access to the kube-apiserver prevents FI-TS operators from helping you in case of any issues in your cluster.") + err = helper.Prompt("Are you sure? (y/n)", "y") + if err != nil { + return err + } + } + + scr.KubeAPIServerACL = &models.V1KubeAPIServerACL{ + CIDRs: viper.GetStringSlice("kube-apiserver-acl-allowed-cidrs"), + Disabled: pointer.Pointer(!viper.GetBool("enable-kube-apiserver-acl")), + } + } + egressRules := makeEgressRules(egress) if len(egressRules) > 0 { scr.EgressRules = egressRules @@ -1203,6 +1230,48 @@ func (c *config) updateCluster(args []string) error { cur.AdditionalNetworks = firewallNetworks } + if viper.IsSet("kube-apiserver-acl-set-allowed-cidrs") || viper.IsSet("enable-kube-apiserver-acl") || + viper.IsSet("kube-apiserver-acl-add-to-allowed-cidrs") || viper.IsSet("kube-apiserver-acl-remove-from-allowed-cidrs") { + + newACL := current.KubeAPIServerACL + if newACL == nil { + newACL = &models.V1KubeAPIServerACL{ + CIDRs: []string{}, + Disabled: pointer.Pointer(true), + } + } + + if viper.IsSet("enable-kube-apiserver-acl") { + if !viper.GetBool("yes-i-really-mean-it") { + return fmt.Errorf("--enable-kube-apiserver-acl is set but you forgot to add --yes-i-really-mean-it") + } + newACL.Disabled = pointer.Pointer(!viper.GetBool("enable-kube-apiserver-acl")) + } + + if viper.IsSet("enable-kube-apiserver-acl") && viper.GetBool("enable-kube-apiserver-acl") { + fmt.Println("WARNING: Restricting access to the kube-apiserver prevents FI-TS operators from helping you in case of any issues in your cluster.") + err = helper.Prompt("Are you sure? (y/n)", "y") + if err != nil { + return err + } + } + + for _, r := range viper.GetStringSlice("kube-apiserver-acl-remove-from-allowed-cidrs") { + newACL.CIDRs = slices.DeleteFunc(newACL.CIDRs, func(s string) bool { + return s == r + }) + } + newACL.CIDRs = append(newACL.CIDRs, viper.GetStringSlice("kube-apiserver-acl-add-to-allowed-cidrs")...) + + if viper.IsSet("kube-apiserver-acl-set-allowed-cidrs") { + newACL.CIDRs = viper.GetStringSlice("kube-apiserver-acl-set-allowed-cidrs") + } + + slices.Sort(newACL.CIDRs) + newACL.CIDRs = slices.Compact(newACL.CIDRs) + cur.KubeAPIServerACL = newACL + } + if purpose != "" { if *cur.Maintenance.AutoUpdate.KubernetesVersion && *current.Purpose == string(v1beta1.ShootPurposeEvaluation) && purpose != string(v1beta1.ShootPurposeEvaluation) { fmt.Print("\nHint: Kubernetes auto updates will still be enabled after this update.\n\n") diff --git a/cmd/output/shootprinter.go b/cmd/output/shootprinter.go index 1165cb7e..a47ef837 100644 --- a/cmd/output/shootprinter.go +++ b/cmd/output/shootprinter.go @@ -147,6 +147,9 @@ func (s ShootIssuesTablePrinter) Print(data []*models.V1ClusterResponse) { func shootData(shoot *models.V1ClusterResponse, withIssues bool) ([]string, []string, []string) { shootStats := newShootStats(shoot.Status) + if (*shoot).KubeAPIServerACL != nil && !*shoot.KubeAPIServerACL.Disabled { + shootStats.apiServer += "🔒" + } maintainEmoji := "" var issues []string diff --git a/go.mod b/go.mod index 4deaee5c..d7de08ae 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,7 @@ require ( github.com/dcorbe/termui-dpc v0.0.0-20211125210512-9d2673a82dd6 github.com/dustin/go-humanize v1.0.1 github.com/fatih/color v1.15.0 - // TODO: pin to cloud-go from no-reversed-vpn cloud-api PR - github.com/fi-ts/cloud-go v0.22.1 + github.com/fi-ts/cloud-go v0.22.4 github.com/gardener/gardener v1.65.0 github.com/gardener/machine-controller-manager v0.49.3 github.com/go-openapi/strfmt v0.21.7 diff --git a/go.sum b/go.sum index e2f72718..e3f33b37 100644 --- a/go.sum +++ b/go.sum @@ -152,8 +152,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/fi-ts/cloud-go v0.22.1 h1:VKzwA5I8G+MNmBu4XTVjG1hahkk/7xcte6UvawXG0dk= -github.com/fi-ts/cloud-go v0.22.1/go.mod h1:BYrXp1jTvfxYRiL0B+LE+6ZDp3GF110y9Sr2tuRJo5c= +github.com/fi-ts/cloud-go v0.22.4 h1:2tmPFZV9g1+oPljVusJx9OhAbq7XOGZXiqNwzJIrj60= +github.com/fi-ts/cloud-go v0.22.4/go.mod h1:BYrXp1jTvfxYRiL0B+LE+6ZDp3GF110y9Sr2tuRJo5c= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=