From 89d4fb757ef585b9a900e1a69c592d23470107be Mon Sep 17 00:00:00 2001 From: Nicolas Vanheuverzwijn Date: Wed, 15 Apr 2020 18:55:53 -0400 Subject: [PATCH 1/4] feat: allow additional security groups on bastion ELB --- pkg/apis/kops/bastion.go | 6 ++++++ pkg/apis/kops/v1alpha2/bastion.go | 7 ++++++- pkg/model/bastion.go | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pkg/apis/kops/bastion.go b/pkg/apis/kops/bastion.go index 51023976bb..b8723b02e4 100644 --- a/pkg/apis/kops/bastion.go +++ b/pkg/apis/kops/bastion.go @@ -20,4 +20,10 @@ type BastionSpec struct { BastionPublicName string `json:"bastionPublicName,omitempty"` // IdleTimeoutSeconds is the bastion's Loadbalancer idle timeout IdleTimeoutSeconds *int64 `json:"idleTimeoutSeconds,omitempty"` + + LoadBalancer *BastionLoadBalancerSpec `json:"loadBalancer,omitempty"` +} + +type BastionLoadBalancerSpec struct { + AdditionalSecurityGroups []string `json:"additionalSecurityGroups,omitempty"` } diff --git a/pkg/apis/kops/v1alpha2/bastion.go b/pkg/apis/kops/v1alpha2/bastion.go index a0fe839595..b4197d12e1 100644 --- a/pkg/apis/kops/v1alpha2/bastion.go +++ b/pkg/apis/kops/v1alpha2/bastion.go @@ -19,5 +19,10 @@ package v1alpha2 type BastionSpec struct { BastionPublicName string `json:"bastionPublicName,omitempty"` // IdleTimeoutSeconds is the bastion's Loadbalancer idle timeout - IdleTimeoutSeconds *int64 `json:"idleTimeoutSeconds,omitempty"` + IdleTimeoutSeconds *int64 `json:"idleTimeoutSeconds,omitempty"` + LoadBalancer *BastionLoadBalancerSpec `json:"loadBalancer,omitempty"` +} + +type BastionLoadBalancerSpec struct { + AdditionalSecurityGroups []string `json:"additionalSecurityGroups,omitempty"` } diff --git a/pkg/model/bastion.go b/pkg/model/bastion.go index 863a6e8274..20c495a674 100644 --- a/pkg/model/bastion.go +++ b/pkg/model/bastion.go @@ -244,6 +244,21 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error { Tags: tags, } + // Add additional security groups to the ELB + if b.Cluster.Spec.Topology != nil && b.Cluster.Spec.Topology.Bastion != nil && b.Cluster.Spec.Topology.Bastion.LoadBalancer != nil && b.Cluster.Spec.Topology.Bastion.LoadBalancer.AdditionalSecurityGroups != nil { + for _, id := range b.Cluster.Spec.Topology.Bastion.LoadBalancer.AdditionalSecurityGroups { + t := &awstasks.SecurityGroup{ + Name: fi.String(id), + Lifecycle: b.SecurityLifecycle, + ID: fi.String(id), + Shared: fi.Bool(true), + } + if err := c.EnsureTask(t); err != nil { + return err + } + elb.SecurityGroups = append(elb.SecurityGroups, t) + } + } c.AddTask(elb) } From 3e74f722d49d6e9b3949babcf33c0feba58a0e67 Mon Sep 17 00:00:00 2001 From: Nicolas Vanheuverzwijn Date: Wed, 15 Apr 2020 18:58:18 -0400 Subject: [PATCH 2/4] doc: document new field 'cluster.topology.bastion.loadBalancer' --- docs/bastion.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/bastion.md b/docs/bastion.md index 93e2f7f2dd..0e6be8b103 100644 --- a/docs/bastion.md +++ b/docs/bastion.md @@ -73,6 +73,19 @@ spec: bastionPublicName: bastion.mycluster.example.com ``` +### Additional security groups to ELB +If you want to add security groups to the bastion ELB + +```yaml +spec: + topology: + bastion: + bastionPublicName: bastion.mycluster.example.com + loadBalancer: + additionalSecurityGroups: + - "sg-***" +``` + ### Access when using gossip (k8s.local) When using gossip mode, there is no DNS zone where we can configure a From 4ceb324f0a9aae0df06cb08c761777d3f4dfa331 Mon Sep 17 00:00:00 2001 From: Nicolas Vanheuverzwijn Date: Wed, 15 Apr 2020 18:58:29 -0400 Subject: [PATCH 3/4] refresh apis --- k8s/crds/kops.k8s.io_clusters.yaml | 7 +++ .../kops/v1alpha2/zz_generated.conversion.go | 48 +++++++++++++++++++ .../kops/v1alpha2/zz_generated.deepcopy.go | 26 ++++++++++ pkg/apis/kops/zz_generated.deepcopy.go | 26 ++++++++++ 4 files changed, 107 insertions(+) diff --git a/k8s/crds/kops.k8s.io_clusters.yaml b/k8s/crds/kops.k8s.io_clusters.yaml index 42a48128fd..46ee9f3649 100644 --- a/k8s/crds/kops.k8s.io_clusters.yaml +++ b/k8s/crds/kops.k8s.io_clusters.yaml @@ -3419,6 +3419,13 @@ spec: idle timeout format: int64 type: integer + loadBalancer: + properties: + additionalSecurityGroups: + items: + type: string + type: array + type: object type: object dns: description: DNS configures options relating to DNS, in particular diff --git a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go index d614201645..8b20fa1783 100644 --- a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go @@ -113,6 +113,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*BastionLoadBalancerSpec)(nil), (*kops.BastionLoadBalancerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha2_BastionLoadBalancerSpec_To_kops_BastionLoadBalancerSpec(a.(*BastionLoadBalancerSpec), b.(*kops.BastionLoadBalancerSpec), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*kops.BastionLoadBalancerSpec)(nil), (*BastionLoadBalancerSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_kops_BastionLoadBalancerSpec_To_v1alpha2_BastionLoadBalancerSpec(a.(*kops.BastionLoadBalancerSpec), b.(*BastionLoadBalancerSpec), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*BastionSpec)(nil), (*kops.BastionSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha2_BastionSpec_To_kops_BastionSpec(a.(*BastionSpec), b.(*kops.BastionSpec), scope) }); err != nil { @@ -1190,9 +1200,38 @@ func Convert_kops_AwsAuthenticationSpec_To_v1alpha2_AwsAuthenticationSpec(in *ko return autoConvert_kops_AwsAuthenticationSpec_To_v1alpha2_AwsAuthenticationSpec(in, out, s) } +func autoConvert_v1alpha2_BastionLoadBalancerSpec_To_kops_BastionLoadBalancerSpec(in *BastionLoadBalancerSpec, out *kops.BastionLoadBalancerSpec, s conversion.Scope) error { + out.AdditionalSecurityGroups = in.AdditionalSecurityGroups + return nil +} + +// Convert_v1alpha2_BastionLoadBalancerSpec_To_kops_BastionLoadBalancerSpec is an autogenerated conversion function. +func Convert_v1alpha2_BastionLoadBalancerSpec_To_kops_BastionLoadBalancerSpec(in *BastionLoadBalancerSpec, out *kops.BastionLoadBalancerSpec, s conversion.Scope) error { + return autoConvert_v1alpha2_BastionLoadBalancerSpec_To_kops_BastionLoadBalancerSpec(in, out, s) +} + +func autoConvert_kops_BastionLoadBalancerSpec_To_v1alpha2_BastionLoadBalancerSpec(in *kops.BastionLoadBalancerSpec, out *BastionLoadBalancerSpec, s conversion.Scope) error { + out.AdditionalSecurityGroups = in.AdditionalSecurityGroups + return nil +} + +// Convert_kops_BastionLoadBalancerSpec_To_v1alpha2_BastionLoadBalancerSpec is an autogenerated conversion function. +func Convert_kops_BastionLoadBalancerSpec_To_v1alpha2_BastionLoadBalancerSpec(in *kops.BastionLoadBalancerSpec, out *BastionLoadBalancerSpec, s conversion.Scope) error { + return autoConvert_kops_BastionLoadBalancerSpec_To_v1alpha2_BastionLoadBalancerSpec(in, out, s) +} + func autoConvert_v1alpha2_BastionSpec_To_kops_BastionSpec(in *BastionSpec, out *kops.BastionSpec, s conversion.Scope) error { out.BastionPublicName = in.BastionPublicName out.IdleTimeoutSeconds = in.IdleTimeoutSeconds + if in.LoadBalancer != nil { + in, out := &in.LoadBalancer, &out.LoadBalancer + *out = new(kops.BastionLoadBalancerSpec) + if err := Convert_v1alpha2_BastionLoadBalancerSpec_To_kops_BastionLoadBalancerSpec(*in, *out, s); err != nil { + return err + } + } else { + out.LoadBalancer = nil + } return nil } @@ -1204,6 +1243,15 @@ func Convert_v1alpha2_BastionSpec_To_kops_BastionSpec(in *BastionSpec, out *kops func autoConvert_kops_BastionSpec_To_v1alpha2_BastionSpec(in *kops.BastionSpec, out *BastionSpec, s conversion.Scope) error { out.BastionPublicName = in.BastionPublicName out.IdleTimeoutSeconds = in.IdleTimeoutSeconds + if in.LoadBalancer != nil { + in, out := &in.LoadBalancer, &out.LoadBalancer + *out = new(BastionLoadBalancerSpec) + if err := Convert_kops_BastionLoadBalancerSpec_To_v1alpha2_BastionLoadBalancerSpec(*in, *out, s); err != nil { + return err + } + } else { + out.LoadBalancer = nil + } return nil } diff --git a/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go index d893ebf068..9443c39563 100644 --- a/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go @@ -224,6 +224,27 @@ func (in *AwsAuthenticationSpec) DeepCopy() *AwsAuthenticationSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BastionLoadBalancerSpec) DeepCopyInto(out *BastionLoadBalancerSpec) { + *out = *in + if in.AdditionalSecurityGroups != nil { + in, out := &in.AdditionalSecurityGroups, &out.AdditionalSecurityGroups + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BastionLoadBalancerSpec. +func (in *BastionLoadBalancerSpec) DeepCopy() *BastionLoadBalancerSpec { + if in == nil { + return nil + } + out := new(BastionLoadBalancerSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BastionSpec) DeepCopyInto(out *BastionSpec) { *out = *in @@ -232,6 +253,11 @@ func (in *BastionSpec) DeepCopyInto(out *BastionSpec) { *out = new(int64) **out = **in } + if in.LoadBalancer != nil { + in, out := &in.LoadBalancer, &out.LoadBalancer + *out = new(BastionLoadBalancerSpec) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/apis/kops/zz_generated.deepcopy.go b/pkg/apis/kops/zz_generated.deepcopy.go index e169e05c15..3df5b9876f 100644 --- a/pkg/apis/kops/zz_generated.deepcopy.go +++ b/pkg/apis/kops/zz_generated.deepcopy.go @@ -240,6 +240,27 @@ func (in *AwsAuthenticationSpec) DeepCopy() *AwsAuthenticationSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BastionLoadBalancerSpec) DeepCopyInto(out *BastionLoadBalancerSpec) { + *out = *in + if in.AdditionalSecurityGroups != nil { + in, out := &in.AdditionalSecurityGroups, &out.AdditionalSecurityGroups + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BastionLoadBalancerSpec. +func (in *BastionLoadBalancerSpec) DeepCopy() *BastionLoadBalancerSpec { + if in == nil { + return nil + } + out := new(BastionLoadBalancerSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BastionSpec) DeepCopyInto(out *BastionSpec) { *out = *in @@ -248,6 +269,11 @@ func (in *BastionSpec) DeepCopyInto(out *BastionSpec) { *out = new(int64) **out = **in } + if in.LoadBalancer != nil { + in, out := &in.LoadBalancer, &out.LoadBalancer + *out = new(BastionLoadBalancerSpec) + (*in).DeepCopyInto(*out) + } return } From bcb141ab7420be86a250b41ebab0051ac8433012 Mon Sep 17 00:00:00 2001 From: Nicolas Vanheuverzwijn Date: Thu, 16 Apr 2020 10:56:02 -0400 Subject: [PATCH 4/4] bastion: add test for loadbalancer.additionalSecurityGroups --- .../bastionadditional_user-data/in-v1alpha2.yaml | 4 ++++ .../update_cluster/bastionadditional_user-data/kubernetes.tf | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/integration/update_cluster/bastionadditional_user-data/in-v1alpha2.yaml b/tests/integration/update_cluster/bastionadditional_user-data/in-v1alpha2.yaml index 3169a30d00..c35c2938ac 100644 --- a/tests/integration/update_cluster/bastionadditional_user-data/in-v1alpha2.yaml +++ b/tests/integration/update_cluster/bastionadditional_user-data/in-v1alpha2.yaml @@ -30,6 +30,10 @@ spec: sshAccess: - 0.0.0.0/0 topology: + bastion: + loadBalancer: + additionalSecurityGroups: + - sg-exampleid masters: private nodes: private subnets: diff --git a/tests/integration/update_cluster/bastionadditional_user-data/kubernetes.tf b/tests/integration/update_cluster/bastionadditional_user-data/kubernetes.tf index 3e7c741486..3fe438b720 100644 --- a/tests/integration/update_cluster/bastionadditional_user-data/kubernetes.tf +++ b/tests/integration/update_cluster/bastionadditional_user-data/kubernetes.tf @@ -306,7 +306,7 @@ resource "aws_elb" "bastion-bastionuserdata-example-com" { ssl_certificate_id = "" } name = "bastion-bastionuserdata-e-4grhsv" - security_groups = [aws_security_group.bastion-elb-bastionuserdata-example-com.id] + security_groups = [aws_security_group.bastion-elb-bastionuserdata-example-com.id, "sg-exampleid"] subnets = [aws_subnet.utility-us-test-1a-bastionuserdata-example-com.id] tags = { "KubernetesCluster" = "bastionuserdata.example.com"