Skip to content

Commit

Permalink
add dualstack support (#209)
Browse files Browse the repository at this point in the history
* add dualstack support

Signed-off-by: Sandor Szücs <[email protected]>

* fix as commented and use defined const instead of strings

Signed-off-by: Sandor Szücs <[email protected]>
  • Loading branch information
szuecs authored Sep 3, 2018
1 parent 7a0c4ff commit cafbfeb
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 21 deletions.
17 changes: 16 additions & 1 deletion aws/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type Adapter struct {
stackTerminationProtection bool
controllerID string
sslPolicy string
ipAddressType string
}

type manifest struct {
Expand Down Expand Up @@ -85,8 +86,11 @@ const (
// accepted by an SSL endpoint.
// See; https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies
DefaultSslPolicy = "ELBSecurityPolicy-2016-08"
// DefaultIpAddressType sets IpAddressType to "ipv4", it is either ipv4 or dualstack
DefaultIpAddressType = "ipv4"

nameTag = "Name"
ipAddressTypeDualstack = "dualstack"
nameTag = "Name"

customTagFilterEnvVarName = "CUSTOM_FILTERS"
)
Expand Down Expand Up @@ -150,6 +154,7 @@ func NewAdapter() (adapter *Adapter, err error) {
obsoleteInstances: make([]string, 0),
controllerID: DefaultControllerID,
sslPolicy: DefaultSslPolicy,
ipAddressType: DefaultIpAddressType,
}

adapter.manifest, err = buildManifest(adapter)
Expand Down Expand Up @@ -243,6 +248,14 @@ func (a *Adapter) WithStackTerminationProtection(terminationProtection bool) *Ad
return a
}

// WithIpAddressType returns the receiver with ipv4 or dualstack configuration, defaults to ipv4.
func (a *Adapter) WithIpAddressType(ipAddressType string) *Adapter {
if ipAddressType == ipAddressTypeDualstack {
a.ipAddressType = ipAddressType
}
return a
}

// ClusterID returns the ClusterID tag that all resources from the same Kubernetes cluster share.
// It's taken from the current ec2 instance.
func (a *Adapter) ClusterID() string {
Expand Down Expand Up @@ -402,6 +415,7 @@ func (a *Adapter) CreateStack(certificateARNs []string, scheme, owner string) (s
idleConnectionTimeoutSeconds: uint(a.idleConnectionTimeout.Seconds()),
controllerID: a.controllerID,
sslPolicy: a.sslPolicy,
ipAddressType: a.ipAddressType,
}

return createStack(a.cloudformation, spec)
Expand All @@ -427,6 +441,7 @@ func (a *Adapter) UpdateStack(stackName string, certificateARNs map[string]time.
idleConnectionTimeoutSeconds: uint(a.idleConnectionTimeout.Seconds()),
controllerID: a.controllerID,
sslPolicy: a.sslPolicy,
ipAddressType: a.ipAddressType,
}

return updateStack(a.cloudformation, spec)
Expand Down
4 changes: 4 additions & 0 deletions aws/cf.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ const (
parameterTargetGroupVPCIDParameter = "TargetGroupVPCIDParameter"
parameterListenerCertificatesParameter = "ListenerCertificatesParameter"
parameterListenerSslPolicyParameter = "ListenerSslPolicyParameter"
parameterIpAddressTypeParameter = "IpAddressType"
)

type stackSpec struct {
Expand All @@ -124,6 +125,7 @@ type stackSpec struct {
idleConnectionTimeoutSeconds uint
controllerID string
sslPolicy string
ipAddressType string
}

type healthCheck struct {
Expand All @@ -148,6 +150,7 @@ func createStack(svc cloudformationiface.CloudFormationAPI, spec *stackSpec) (st
cfParam(parameterTargetGroupVPCIDParameter, spec.vpcID),
cfParam(parameterTargetTargetPortParameter, fmt.Sprintf("%d", spec.targetPort)),
cfParam(parameterListenerSslPolicyParameter, spec.sslPolicy),
cfParam(parameterIpAddressTypeParameter, spec.ipAddressType),
},
Tags: []*cloudformation.Tag{
cfTag(kubernetesCreatorTag, spec.controllerID),
Expand Down Expand Up @@ -197,6 +200,7 @@ func updateStack(svc cloudformationiface.CloudFormationAPI, spec *stackSpec) (st
cfParam(parameterTargetGroupVPCIDParameter, spec.vpcID),
cfParam(parameterTargetTargetPortParameter, fmt.Sprintf("%d", spec.targetPort)),
cfParam(parameterListenerSslPolicyParameter, spec.sslPolicy),
cfParam(parameterIpAddressTypeParameter, spec.ipAddressType),
},
Tags: []*cloudformation.Tag{
cfTag(kubernetesCreatorTag, spec.controllerID),
Expand Down
45 changes: 26 additions & 19 deletions aws/cf_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import (
"time"

"crypto/sha256"
"github.com/mweagle/go-cloudformation"
"sort"

"github.com/mweagle/go-cloudformation"
)

func hashARNs(certARNs []string) []byte {
Expand All @@ -25,48 +26,53 @@ func generateTemplate(certs map[string]time.Time, idleConnectionTimeoutSeconds u
template := cloudformation.NewTemplate()
template.Description = "Load Balancer for Kubernetes Ingress"
template.Parameters = map[string]*cloudformation.Parameter{
"LoadBalancerSchemeParameter": &cloudformation.Parameter{
parameterLoadBalancerSchemeParameter: &cloudformation.Parameter{
Type: "String",
Description: "The Load Balancer scheme - 'internal' or 'internet-facing'",
Default: "internet-facing",
},
"LoadBalancerSecurityGroupParameter": &cloudformation.Parameter{
parameterLoadBalancerSecurityGroupParameter: &cloudformation.Parameter{
Type: "List<AWS::EC2::SecurityGroup::Id>",
Description: "The security group ID for the Load Balancer",
},
"LoadBalancerSubnetsParameter": &cloudformation.Parameter{
parameterLoadBalancerSubnetsParameter: &cloudformation.Parameter{
Type: "List<AWS::EC2::Subnet::Id>",
Description: "The list of subnets IDs for the Load Balancer",
},
"TargetGroupHealthCheckPathParameter": &cloudformation.Parameter{
parameterTargetGroupHealthCheckPathParameter: &cloudformation.Parameter{
Type: "String",
Description: "The healthcheck path",
Default: "/kube-system/healthz",
},
"TargetGroupHealthCheckPortParameter": &cloudformation.Parameter{
parameterTargetGroupHealthCheckPortParameter: &cloudformation.Parameter{
Type: "Number",
Description: "The healthcheck port",
Default: "9999",
},
"TargetGroupTargetPortParameter": &cloudformation.Parameter{
parameterTargetTargetPortParameter: &cloudformation.Parameter{
Type: "Number",
Description: "The target port",
Default: "9999",
},
"TargetGroupHealthCheckIntervalParameter": &cloudformation.Parameter{
parameterTargetGroupHealthCheckIntervalParameter: &cloudformation.Parameter{
Type: "Number",
Description: "The healthcheck interval",
Default: "10",
},
"TargetGroupVPCIDParameter": &cloudformation.Parameter{
parameterTargetGroupVPCIDParameter: &cloudformation.Parameter{
Type: "AWS::EC2::VPC::Id",
Description: "The VPCID for the TargetGroup",
},
"ListenerSslPolicyParameter": &cloudformation.Parameter{
parameterListenerSslPolicyParameter: &cloudformation.Parameter{
Type: "String",
Description: "The HTTPS SSL Security Policy Name",
Default: "ELBSecurityPolicy-2016-08",
},
parameterIpAddressTypeParameter: &cloudformation.Parameter{
Type: "String",
Description: "IP Address Type, 'ipv4' or 'dualstack'",
Default: "ipv4",
},
}
template.AddResource("HTTPListener", &cloudformation.ElasticLoadBalancingV2Listener{
DefaultActions: &cloudformation.ElasticLoadBalancingV2ListenerActionList{
Expand Down Expand Up @@ -106,7 +112,7 @@ func generateTemplate(certs map[string]time.Time, idleConnectionTimeoutSeconds u
LoadBalancerArn: cloudformation.Ref("LB").String(),
Port: cloudformation.Integer(443),
Protocol: cloudformation.String("HTTPS"),
SslPolicy: cloudformation.Ref("ListenerSslPolicyParameter").String(),
SslPolicy: cloudformation.Ref(parameterListenerSslPolicyParameter).String(),
})

// Add a ListenerCertificate resource with all of the certificates, including the default one
Expand Down Expand Up @@ -134,9 +140,10 @@ func generateTemplate(certs map[string]time.Time, idleConnectionTimeoutSeconds u
},
},

Scheme: cloudformation.Ref("LoadBalancerSchemeParameter").String(),
SecurityGroups: cloudformation.Ref("LoadBalancerSecurityGroupParameter").StringList(),
Subnets: cloudformation.Ref("LoadBalancerSubnetsParameter").StringList(),
IPAddressType: cloudformation.Ref(parameterIpAddressTypeParameter).String(),
Scheme: cloudformation.Ref(parameterLoadBalancerSchemeParameter).String(),
SecurityGroups: cloudformation.Ref(parameterLoadBalancerSecurityGroupParameter).StringList(),
Subnets: cloudformation.Ref(parameterLoadBalancerSubnetsParameter).StringList(),
Tags: &cloudformation.TagList{
{
Key: cloudformation.String("StackName"),
Expand All @@ -145,12 +152,12 @@ func generateTemplate(certs map[string]time.Time, idleConnectionTimeoutSeconds u
},
})
template.AddResource("TG", &cloudformation.ElasticLoadBalancingV2TargetGroup{
HealthCheckIntervalSeconds: cloudformation.Ref("TargetGroupHealthCheckIntervalParameter").Integer(),
HealthCheckPath: cloudformation.Ref("TargetGroupHealthCheckPathParameter").String(),
HealthCheckPort: cloudformation.Ref("TargetGroupHealthCheckPortParameter").String(),
Port: cloudformation.Ref("TargetGroupTargetPortParameter").Integer(),
HealthCheckIntervalSeconds: cloudformation.Ref(parameterTargetGroupHealthCheckIntervalParameter).Integer(),
HealthCheckPath: cloudformation.Ref(parameterTargetGroupHealthCheckPathParameter).String(),
HealthCheckPort: cloudformation.Ref(parameterTargetGroupHealthCheckPortParameter).String(),
Port: cloudformation.Ref(parameterTargetTargetPortParameter).Integer(),
Protocol: cloudformation.String("HTTP"),
VPCID: cloudformation.Ref("TargetGroupVPCIDParameter").String(),
VPCID: cloudformation.Ref(parameterTargetGroupVPCIDParameter).String(),
})

template.Outputs = map[string]*cloudformation.Output{
Expand Down
5 changes: 4 additions & 1 deletion controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ var (
sslPolicy string
blacklistCertARN string
blacklistCertArnMap map[string]bool
ipAddressType string
)

func loadSettings() error {
Expand Down Expand Up @@ -92,6 +93,7 @@ func loadSettings() error {
fmt.Sprintf("sets the maximum number of certificates to be attached to an ALB. Cannot be higher than %d", aws.DefaultMaxCertsPerALB))
flag.StringVar(&sslPolicy, "ssl-policy", aws.DefaultSslPolicy, "Security policy that will define the protocols/ciphers accepts by the SSL listener")
flag.StringVar(&blacklistCertARN, "blacklist-certificate-arns", "", "Certificate ARNs to not consider by the controller: arn1,arn2,..")
flag.StringVar(&ipAddressType, "ip-addr-type", aws.DefaultIpAddressType, "IP Address type to use, one of 'ipv4' or 'dualstack'")

flag.Parse()

Expand Down Expand Up @@ -196,7 +198,8 @@ func main() {
WithStackTerminationProtection(stackTerminationProtection).
WithIdleConnectionTimeout(idleConnectionTimeout).
WithControllerID(controllerID).
WithSslPolicy(sslPolicy)
WithSslPolicy(sslPolicy).
WithIpAddressType(ipAddressType)

certificatesProvider, err := certs.NewCachingProvider(
certPollingInterval,
Expand Down

0 comments on commit cafbfeb

Please sign in to comment.