Skip to content

Commit

Permalink
Merge pull request #1149 from weaveworks/toggle-public-private-endpoi…
Browse files Browse the repository at this point in the history
…nt-access

Enable management of access to public/private API endpoints
  • Loading branch information
D3nn authored Oct 9, 2019
2 parents fc38c39 + dc11d25 commit 37106d3
Show file tree
Hide file tree
Showing 26 changed files with 906 additions and 14 deletions.
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ require (
github.com/goreleaser/goreleaser v0.110.0
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.9.2 // indirect
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 // indirect
github.com/instrumenta/kubeval v0.0.0-20190804145309-805845b47dfc
github.com/justinbarrick/go-k8s-portforward v1.0.4-0.20190722134107-d79fe1b9d79d
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
Expand Down Expand Up @@ -60,7 +61,7 @@ require (

github.com/spf13/cobra v0.0.4

github.com/spf13/pflag v1.0.3
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.3.2
github.com/spotinst/spotinst-sdk-go v0.0.0-20181012192533-fed4677dbf8f // indirect
github.com/stretchr/testify v1.3.0
Expand All @@ -77,6 +78,7 @@ require (
go.etcd.io/bbolt v1.3.3 // indirect
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/zap v1.10.0 // indirect
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1 // indirect
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59
google.golang.org/grpc v1.21.1 // indirect
gopkg.in/gcfg.v1 v1.2.3 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ github.com/aws/aws-sdk-go v1.16.23/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi
github.com/aws/aws-sdk-go v1.19.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.23.15 h1:ut2ZzO0A34Ds18NXvvkWWKyO4aZqQ9uZquslWzCQvGU=
github.com/aws/aws-sdk-go v1.23.15/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.23.17 h1:IGNAvtR7ckMEHhy+ObG9xw6DFqEE4Ual0LYXsVTZSLQ=
github.com/aws/aws-sdk-go v1.23.18 h1:ADU/y1EO8yPzUJJYjcvJ0V9/suezxPh0u6hb5bSYIGQ=
github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
Expand Down Expand Up @@ -403,6 +405,7 @@ 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/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57 h1:eqyIo2HjKhKe/mJzTG8n4VqvLXIOEG+SLdDqX7xGtkY=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/subcommands v0.0.0-20181012225330-46f0354f6315/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
Expand Down Expand Up @@ -527,6 +530,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.4 h1:mKkfHkZWD8dC7WxKx3N9WCF0Y+dLau45704YQmY6H94=
github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
Expand Down Expand Up @@ -900,6 +905,8 @@ github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.1.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
Expand Down Expand Up @@ -1023,6 +1030,8 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
gocloud.dev v0.13.0 h1:q3j7dq8MH48LxQ5tu1e05eqTtjthFXRN7TB5/VIObtc=
gocloud.dev v0.13.0/go.mod h1:WbTmzqihM0aICJgj1Z702dckfPW1XcCV6RQnoi3OpQA=
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1 h1:A71BZbKSu+DtCNry/x5JKn20C+64DirDHmePEA8k0FY=
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
Expand Down Expand Up @@ -1338,6 +1347,7 @@ modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
pack.ag/amqp v0.8.0/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
pack.ag/amqp v0.10.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/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=
Expand Down
211 changes: 211 additions & 0 deletions integration/cluster_api_endpoints_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
// +build integration

package integration_test

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"

awseks "github.com/aws/aws-sdk-go/service/eks"
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"

. "github.com/weaveworks/eksctl/integration/matchers"
. "github.com/weaveworks/eksctl/integration/runner"

"github.com/weaveworks/eksctl/pkg/ctl/cmdutils"

api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5"
)

const (
createCluster = `Create`
updateCluster = `Update`
deleteCluster = `Delete`
endpointPubTmpl = `EndpointPublicAccess: %v`
endpointPrivTmpl = `EndpointPrivateAccess: %v`
)

func setEndpointConfig(cfg *api.ClusterConfig, privateAccess, publicAccess bool) {
cfg.VPC.ClusterEndpoints.PrivateAccess = &privateAccess
cfg.VPC.ClusterEndpoints.PublicAccess = &publicAccess
}

func generateName(prefix string) string {
if clusterName == "" {
clusterName = cmdutils.ClusterName("", "")
}
return fmt.Sprintf("%v-%v", prefix, clusterName)
}

func setMetadata(cfg *api.ClusterConfig, name, region string) {
cfg.Metadata.Name = name
cfg.Metadata.Region = region
}

var _ = Describe("(Integration) Create and Update Cluster with Endpoint Configs", func() {

type endpointAccessCase struct {
Name string
Private bool
Public bool
Type string
Fails bool
}

DescribeTable("Can create/update Cluster Endpoint Access",
func(e endpointAccessCase) {
//create clusterconfig
cfg := api.NewClusterConfig()
clName := generateName(e.Name)
setEndpointConfig(cfg, e.Private, e.Public)
setMetadata(cfg, clName, region)

// create and populate config file from clusterconfig
bytes, err := json.Marshal(cfg)
Expect(err).ToNot(HaveOccurred())
Expect(len(bytes)).ToNot(BeZero())
tmpfile, err := ioutil.TempFile("", "clusterendpointtests")
Expect(err).ToNot(HaveOccurred())

defer os.Remove(tmpfile.Name())

_, err = tmpfile.Write(bytes)
Expect(err).ToNot(HaveOccurred())
err = tmpfile.Close()
Expect(err).ToNot(HaveOccurred())

// create cluster with config file
if e.Type == createCluster {
cmd := eksctlCreateCmd.WithArgs(
"cluster",
"--verbose", "2",
"--config-file", tmpfile.Name(),
"--without-nodegroup",
).WithoutArg("--region", region)
if e.Fails {
Expect(cmd).ShouldNot(RunSuccessfully())
return
}
Expect(cmd).Should(RunSuccessfully())
awsSession := NewSession(region)
Eventually(awsSession, timeOut, pollInterval).Should(
HaveExistingCluster(clName, awseks.ClusterStatusActive, version))
} else if e.Type == updateCluster {
utilsCmd := eksctlUtilsCmd.WithArgs(
"update-cluster-endpoints",
"--name", clName,
fmt.Sprintf("--private-access=%v", e.Private),
fmt.Sprintf("--public-access=%v", e.Public),
"--approve")
if e.Fails {
Expect(utilsCmd).ShouldNot(RunSuccessfully())
return
}
Expect(utilsCmd).Should(RunSuccessfully())
}
getCmd := eksctlGetCmd.WithArgs(
"cluster",
"--name", clName,
"-o", "yaml",
)
Expect(getCmd).To(RunSuccessfullyWithOutputStringLines(
ContainElement(ContainSubstring(endpointPubTmpl, e.Public)),
ContainElement(ContainSubstring(endpointPrivTmpl, e.Private)),
))
if e.Type == deleteCluster {
// nned to update public access to allow access to delete when it isn't allowed
if e.Public == false {
utilsCmd := eksctlUtilsCmd.WithArgs(
"update-cluster-endpoints",
"--name", clName,
fmt.Sprintf("--public-access=%v", true),
fmt.Sprintf("--approve"),
)
Expect(utilsCmd).Should(RunSuccessfully())
}
deleteCmd := eksctlDeleteCmd.WithArgs(
"cluster",
"--name", clName,
)
Expect(deleteCmd).Should(RunSuccessfully())
awsSession := NewSession(region)
Eventually(awsSession, timeOut, pollInterval).
ShouldNot(HaveExistingCluster(clName, awseks.ClusterStatusActive, version))
}
},
Entry("Create cluster1, Private=false, Public=true, should succeed", endpointAccessCase{
Name: "cluster1",
Private: false,
Public: true,
Type: createCluster,
Fails: false,
}),
Entry("Create cluster2, Private=true, Public=false, should not succeed", endpointAccessCase{
Name: "cluster2",
Private: true,
Public: false,
Type: createCluster,
Fails: true,
}),
Entry("Create cluster3, Private=true, Public=true, should succeed", endpointAccessCase{
Name: "cluster3",
Private: true,
Public: true,
Type: createCluster,
Fails: false,
}),
Entry("Create cluster4, Private=false, Public=false, should not succeed", endpointAccessCase{
Name: "cluster4",
Private: false,
Public: false,
Type: createCluster,
Fails: true,
}),
Entry("Update cluster1 to Private=true, Public=false, should succeed", endpointAccessCase{
Name: "cluster1",
Private: true,
Public: false,
Type: updateCluster,
Fails: false,
}),
Entry("Update cluster3 to Private=true, Public=false, should succeed", endpointAccessCase{
Name: "cluster3",
Private: true,
Public: false,
Type: updateCluster,
Fails: false,
}),
Entry("Update cluster3 to Private=false, Public=false, should not succeed", endpointAccessCase{
Name: "cluster3",
Private: false,
Public: false,
Type: updateCluster,
Fails: true,
}),
Entry("Update cluster3 to Private=false, Public=true, should succeed", endpointAccessCase{
Name: "cluster3",
Private: false,
Public: true,
Type: updateCluster,
Fails: false,
}),
Entry("Delete cluster1, should succeed (test case updates access)", endpointAccessCase{
Name: "cluster1",
Private: true,
Public: false,
Type: deleteCluster,
Fails: false,
}),
Entry("Delete cluster3, succeed", endpointAccessCase{
Name: "cluster3",
Private: false,
Public: true,
Type: deleteCluster,
Fails: false,
}),
)
})
20 changes: 20 additions & 0 deletions integration/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,26 @@ func (c Cmd) WithArgs(args ...string) Cmd {
return c
}

// WithoutArg removes an existing argument
func (c Cmd) WithoutArg(arg, val string) Cmd {
var argIdx int
var found bool
for i, earg := range c.args {
if arg == earg {
argIdx = i
found = true
}
}
if found {
endIdx := argIdx + 1
if val != "" {
endIdx = argIdx + 2
}
c.args = append(c.args[:argIdx], c.args[endIdx:]...)
}
return c
}

// WithEnv returns a copy of the command with new environment variables
func (c Cmd) WithEnv(env ...string) Cmd {
c.env = append(c.env, env...)
Expand Down
8 changes: 8 additions & 0 deletions pkg/apis/eksctl.io/v1alpha5/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,11 @@ func DefaultClusterNAT() *ClusterNAT {
Gateway: &single,
}
}

// ClusterEndpointAccessDefaults returns a ClusterEndpoints pointer with default values set.
func ClusterEndpointAccessDefaults() *ClusterEndpoints {
return &ClusterEndpoints{
PrivateAccess: Disabled(),
PublicAccess: Enabled(),
}
}
1 change: 1 addition & 0 deletions pkg/apis/eksctl.io/v1alpha5/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ func NewClusterVPC() *ClusterVPC {
},
NAT: DefaultClusterNAT(),
AutoAllocateIPv6: Disabled(),
ClusterEndpoints: ClusterEndpointAccessDefaults(),
}
}

Expand Down
41 changes: 41 additions & 0 deletions pkg/apis/eksctl.io/v1alpha5/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,25 @@ import (
"fmt"
"strings"

"github.com/pkg/errors"

"k8s.io/apimachinery/pkg/util/validation"
)

var (
// ErrClusterEndpointNoAccess indicates the config prevents API access
ErrClusterEndpointNoAccess = errors.New("Kubernetes API access must have one of public or private clusterEndpoints enabled")

// ErrClusterEndpointPrivateOnly warns private-only access requires changes
// to AWS resource configuration in order to effectively use clients in the VPC
ErrClusterEndpointPrivateOnly = errors.New("warning, having public access disallowed will subsequently interfere with some " +
"features of eksctl. This will require running subsequent eksctl (and Kubernetes) " +
"commands/API calls from within the VPC. Running these in the VPC requires making " +
"updates to some AWS resources. See: " +
"https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html#private-access " +
"for more details")
)

// NOTE: we don't use k8s.io/apimachinery/pkg/util/sets here to keep API package free of dependencies
type nameSet map[string]struct{}

Expand Down Expand Up @@ -63,9 +79,34 @@ func ValidateClusterConfig(cfg *ClusterConfig) error {
}
}

if !cfg.HasClusterEndpointAccess() {
return ErrClusterEndpointNoAccess
}
return nil
}

// ValidateClusterEndpointConfig checks the endpoint configuration for potential issues
func (c *ClusterConfig) ValidateClusterEndpointConfig() error {
endpts := c.VPC.ClusterEndpoints
if NoAccess(endpts) {
return ErrClusterEndpointNoAccess
}
if PrivateOnly(endpts) {
return ErrClusterEndpointPrivateOnly
}
return nil
}

// NoAccess returns true if neither public are private cluster endpoint access is enabled and false otherwise
func NoAccess(ces *ClusterEndpoints) bool {
return !(*ces.PublicAccess || *ces.PrivateAccess)
}

// PrivateOnly returns true if public cluster endpoint access is disabled and private cluster endpoint access is enabled, and false otherwise
func PrivateOnly(ces *ClusterEndpoints) bool {
return !*ces.PublicAccess && *ces.PrivateAccess
}

// ValidateNodeGroup checks compatible fields of a given nodegroup
func ValidateNodeGroup(i int, ng *NodeGroup) error {
path := fmt.Sprintf("nodeGroups[%d]", i)
Expand Down
Loading

0 comments on commit 37106d3

Please sign in to comment.