Skip to content

Commit

Permalink
feat(aws): add PolicyNames for ELB to change listener's security policy
Browse files Browse the repository at this point in the history
  • Loading branch information
FrankYang0529 committed Nov 19, 2020
1 parent 374f4bb commit 93dcadd
Show file tree
Hide file tree
Showing 14 changed files with 66 additions and 4 deletions.
5 changes: 4 additions & 1 deletion docs/cluster_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The `Cluster` resource contains the specification of the cluster itself.

The complete list of keys can be found at the [Cluster](https://pkg.go.dev/k8s.io/kops/pkg/apis/kOps#ClusterSpec) reference page.
The complete list of keys can be found at the [Cluster](https://pkg.go.dev/k8s.io/kops/pkg/apis/kops#ClusterSpec) reference page.

On this page, we will expand on the more important configuration keys.

Expand Down Expand Up @@ -49,6 +49,8 @@ spec:

You can use a valid SSL Certificate for your API Server Load Balancer. Currently, only AWS is supported.

Also, you can change listener's [security policy](https://docs.aws.amazon.com/sdk-for-go/api/service/elbv2/#CreateListenerInput) by `sslPolicy`. Currently, only AWS Network Load Balancer is supported.

Note that when using `sslCertificate`, client certificate authentication, such as with the credentials generated via `kOps export kubecfg`, will not work through the load balancer. As of kOps 1.19, a `kubecfg` that bypasses the load balancer may be created with the `--internal` flag to `kops update cluster` or `kOps export kubecfg`. Security groups may need to be opened to allow access from the clients to the master instances' port TCP/443, for example by using the `additionalSecurityGroups` field on the master instance groups.

```yaml
Expand All @@ -57,6 +59,7 @@ spec:
loadBalancer:
type: Public
sslCertificate: arn:aws:acm:<region>:<accountId>:certificate/<uuid>
sslPolicy: ELBSecurityPolicy-TLS-1-2-2017-01
```

*Openstack only*
Expand Down
3 changes: 3 additions & 0 deletions k8s/crds/kops.k8s.io_clusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ spec:
sslCertificate:
description: SSLCertificate allows you to specify the ACM cert to be used the LB
type: string
sslPolicy:
description: SSLPolicy allows you to overwrite the LB listener's Security Policy
type: string
type:
description: Type of load balancer to create may Public or Internal.
type: string
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/kops/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ type LoadBalancerAccessSpec struct {
UseForInternalApi bool `json:"useForInternalApi,omitempty"`
// SSLCertificate allows you to specify the ACM cert to be used the LB
SSLCertificate string `json:"sslCertificate,omitempty"`
// SSLPolicy allows you to overwrite the LB listener's Security Policy
SSLPolicy *string `json:"sslPolicy,omitempty"`
// CrossZoneLoadBalancing allows you to enable the cross zone load balancing
CrossZoneLoadBalancing *bool `json:"crossZoneLoadBalancing,omitempty"`
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/kops/v1alpha2/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ type LoadBalancerAccessSpec struct {
UseForInternalApi bool `json:"useForInternalApi,omitempty"`
// SSLCertificate allows you to specify the ACM cert to be used the LB
SSLCertificate string `json:"sslCertificate,omitempty"`
// SSLPolicy allows you to overwrite the LB listener's Security Policy
SSLPolicy *string `json:"sslPolicy,omitempty"`
// CrossZoneLoadBalancing allows you to enable the cross zone load balancing
CrossZoneLoadBalancing *bool `json:"crossZoneLoadBalancing,omitempty"`
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/kops/v1alpha2/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions pkg/apis/kops/validation/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func awsValidateCluster(c *kops.Cluster) field.ErrorList {
if c.Spec.API != nil {
if c.Spec.API.LoadBalancer != nil {
allErrs = append(allErrs, awsValidateAdditionalSecurityGroups(field.NewPath("spec", "api", "loadBalancer", "additionalSecurityGroups"), c.Spec.API.LoadBalancer.AdditionalSecurityGroups)...)
allErrs = append(allErrs, awsValidateSSLPolicy(field.NewPath("spec", "api", "loadBalancer", "sslPolicy"), c.Spec.API.LoadBalancer)...)
}
}

Expand Down Expand Up @@ -142,3 +143,18 @@ func awsValidateMixedInstancesPolicy(path *field.Path, spec *kops.MixedInstances

return errs
}

func awsValidateSSLPolicy(fieldPath *field.Path, spec *kops.LoadBalancerAccessSpec) field.ErrorList {
allErrs := field.ErrorList{}

if spec.SSLPolicy != nil {
if spec.Class != kops.LoadBalancerClassNetwork {
allErrs = append(allErrs, field.Forbidden(fieldPath, "sslPolicy should be specified with Network Load Balancer"))
}
if spec.SSLCertificate == "" {
allErrs = append(allErrs, field.Forbidden(fieldPath, "sslPolicy should not be specified without SSLCertificate"))
}
}

return allErrs
}
5 changes: 5 additions & 0 deletions pkg/apis/kops/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions pkg/model/awsmodel/api_loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,16 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
if lbSpec.SSLCertificate != "" {
listeners["443"].SSLCertificateID = lbSpec.SSLCertificate
nlbListeners[0].Port = 8443
nlbListeners = append(nlbListeners, &awstasks.NetworkLoadBalancerListener{

nlbListener := &awstasks.NetworkLoadBalancerListener{
Port: 443,
TargetGroupName: b.NLBTargetGroupName("tls"),
SSLCertificateID: lbSpec.SSLCertificate,
})
}
if lbSpec.SSLPolicy != nil {
nlbListener.SSLPolicy = *lbSpec.SSLPolicy
}
nlbListeners = append(nlbListeners, nlbListener)
}

if lbSpec.SecurityGroupOverride != nil {
Expand Down
3 changes: 2 additions & 1 deletion tests/integration/update_cluster/complex/cloudformation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,8 @@
"Ref": "AWSElasticLoadBalancingV2LoadBalancerapicomplexexamplecom"
},
"Port": 443,
"Protocol": "TLS"
"Protocol": "TLS",
"SslPolicy": "ELBSecurityPolicy-2016-08"
}
},
"AWSElasticLoadBalancingV2Listenerapicomplexexamplecom8443": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ spec:
crossZoneLoadBalancing: true
class: Network
sslCertificate: arn:aws:acm:us-test-1:000000000000:certificate/123456789012-1234-1234-1234-12345678
sslPolicy: ELBSecurityPolicy-2016-08
kubernetesApiAccess:
- 1.1.1.0/24
- 2001:0:8500::/40
Expand Down
1 change: 1 addition & 0 deletions tests/integration/update_cluster/complex/in-v1alpha2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ spec:
crossZoneLoadBalancing: true
class: Network
sslCertificate: arn:aws:acm:us-test-1:000000000000:certificate/123456789012-1234-1234-1234-12345678
sslPolicy: ELBSecurityPolicy-2016-08
kubernetesApiAccess:
- 1.1.1.0/24
- 2001:0:8500::/40
Expand Down
1 change: 1 addition & 0 deletions tests/integration/update_cluster/complex/kubernetes.tf
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ resource "aws_lb_listener" "api-complex-example-com-443" {
load_balancer_arn = aws_lb.api-complex-example-com.id
port = 443
protocol = "TLS"
ssl_policy = "ELBSecurityPolicy-2016-08"
}

resource "aws_lb_listener" "api-complex-example-com-8443" {
Expand Down
15 changes: 15 additions & 0 deletions upup/pkg/fi/cloudup/awstasks/network_load_balancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type NetworkLoadBalancerListener struct {
Port int
TargetGroupName string
SSLCertificateID string
SSLPolicy string
}

func (e *NetworkLoadBalancerListener) mapToAWS(targetGroups []*TargetGroup, loadBalancerArn string) (*elbv2.CreateListenerInput, error) {
Expand Down Expand Up @@ -110,6 +111,9 @@ func (e *NetworkLoadBalancerListener) mapToAWS(targetGroups []*TargetGroup, load
CertificateArn: aws.String(e.SSLCertificateID),
})
l.Protocol = aws.String(elbv2.ProtocolEnumTls)
if e.SSLPolicy != "" {
l.SslPolicy = aws.String(e.SSLPolicy)
}
} else {
l.Protocol = aws.String(elbv2.ProtocolEnumTcp)
}
Expand Down Expand Up @@ -369,6 +373,9 @@ func (e *NetworkLoadBalancer) Find(c *fi.Context) (*NetworkLoadBalancer, error)
actualListener.Port = int(aws.Int64Value(l.Port))
if len(l.Certificates) != 0 {
actualListener.SSLCertificateID = aws.StringValue(l.Certificates[0].CertificateArn) // What if there is more then one certificate, can we just grab the default certificate? we don't set it as default, we only set the one.
if l.SslPolicy != nil {
actualListener.SSLPolicy = aws.StringValue(l.SslPolicy)
}
}

// This will need to be rearranged when we recognized multiple listeners and target groups per NLB
Expand Down Expand Up @@ -689,6 +696,7 @@ type terraformNetworkLoadBalancerListener struct {
Port int64 `json:"port" cty:"port"`
Protocol string `json:"protocol" cty:"protocol"`
CertificateARN *string `json:"certificate_arn,omitempty" cty:"certificate_arn"`
SSLPolicy *string `json:"ssl_policy,omitempty" cty:"ssl_policy"`
DefaultAction []terraformNetworkLoadBalancerListenerAction `json:"default_action" cty:"default_action"`
}

Expand Down Expand Up @@ -730,6 +738,9 @@ func (_ *NetworkLoadBalancer) RenderTerraform(t *terraform.TerraformTarget, a, e
if listener.SSLCertificateID != "" {
listenerTF.CertificateARN = &listener.SSLCertificateID
listenerTF.Protocol = elbv2.ProtocolEnumTls
if listener.SSLPolicy != "" {
listenerTF.SSLPolicy = &listener.SSLPolicy
}
} else {
listenerTF.Protocol = elbv2.ProtocolEnumTcp
}
Expand Down Expand Up @@ -764,6 +775,7 @@ type cloudformationNetworkLoadBalancerListener struct {
LoadBalancerARN *cloudformation.Literal `json:"LoadBalancerArn"`
Port int64 `json:"Port"`
Protocol string `json:"Protocol"`
SSLPolicy *string `json:"SslPolicy,omitempty"`
}

type cloudformationNetworkLoadBalancerListenerCertificate struct {
Expand Down Expand Up @@ -811,6 +823,9 @@ func (_ *NetworkLoadBalancer) RenderCloudformation(t *cloudformation.Cloudformat
{CertificateArn: listener.SSLCertificateID},
}
listenerCF.Protocol = elbv2.ProtocolEnumTls
if listener.SSLPolicy != "" {
listenerCF.SSLPolicy = &listener.SSLPolicy
}
} else {
listenerCF.Protocol = elbv2.ProtocolEnumTcp
}
Expand Down

0 comments on commit 93dcadd

Please sign in to comment.