diff --git a/pkg/cloudprovider/providers/aws/aws.go b/pkg/cloudprovider/providers/aws/aws.go index 37032009645..22486ff247d 100644 --- a/pkg/cloudprovider/providers/aws/aws.go +++ b/pkg/cloudprovider/providers/aws/aws.go @@ -69,15 +69,20 @@ const TagNameSubnetPublicELB = "kubernetes.io/role/elb" // This lets us define more advanced semantics in future. const ServiceAnnotationLoadBalancerInternal = "service.beta.kubernetes.io/aws-load-balancer-internal" -// Service annotation requesting a secure listener. Value is [InstanceProtocol=]CertARN -// If InstanceProtocol is `http` (default) or `https`, an HTTPS listener that terminates the connection and parses headers is created. -// If it is set to `ssl` or `tcp`, a "raw" SSL listener is used. +// Service annotation requesting a secure listener. Value is a valid certificate ARN. // For more, see http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-listener-config.html // CertARN is an IAM or CM certificate ARN, e.g. arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012 -const ServiceAnnotationLoadBalancerCertificate = "service.beta.kubernetes.io/aws-load-balancer-certarn" +const ServiceAnnotationLoadBalancerCertificate = "service.beta.kubernetes.io/aws-load-balancer-ssl-cert" -// Maps from instance protocol to ELB protocol -var protocolMapping = map[string]string{ +// Service annotation specifying the protocol spoken by the backend (pod) behind a secure listener. +// Only inspected when `aws-load-balancer-ssl-cert` is used. +// If `http` (default) or `https`, an HTTPS listener that terminates the connection and parses headers is created. +// If set to `ssl` or `tcp`, a "raw" SSL listener is used. + +const ServiceAnnotationLoadBalancerBEProtocol = "service.beta.kubernetes.io/aws-load-balancer-backend-protocol" + +// Maps from backend protocol to ELB protocol +var backendProtocolMapping = map[string]string{ "https": "https", "http": "https", "ssl": "ssl", @@ -2125,19 +2130,15 @@ func getListener(port api.ServicePort, annotations map[string]string) (*elb.List listener.LoadBalancerPort = &loadBalancerPort certID := annotations[ServiceAnnotationLoadBalancerCertificate] if certID != "" { - parts := strings.Split(certID, "=") - if len(parts) == 1 { + instanceProtocol = annotations[ServiceAnnotationLoadBalancerBEProtocol] + if instanceProtocol == "" { protocol = "https" instanceProtocol = "http" - } else if len(parts) == 2 { - instanceProtocol = strings.ToLower(parts[0]) - protocol = protocolMapping[instanceProtocol] - if protocol == "" { - return nil, fmt.Errorf("Invalid protocol %s in %s", instanceProtocol, certID) - } - certID = parts[1] } else { - return nil, fmt.Errorf("Invalid certificate annotation %s", certID) + protocol = backendProtocolMapping[instanceProtocol] + if protocol == "" { + return nil, fmt.Errorf("Invalid backend protocol %s in %s", instanceProtocol, certID) + } } listener.SSLCertificateId = &certID } diff --git a/pkg/cloudprovider/providers/aws/aws_test.go b/pkg/cloudprovider/providers/aws/aws_test.go index 56642e36937..aaf96e46bce 100644 --- a/pkg/cloudprovider/providers/aws/aws_test.go +++ b/pkg/cloudprovider/providers/aws/aws_test.go @@ -1204,54 +1204,54 @@ func TestGetListener(t *testing.T) { tests := []struct { name string - lbPort int64 - instancePort int64 - annotation string + lbPort int64 + instancePort int64 + backendProtocolAnnotation string + certAnnotation string expectError bool lbProtocol string instanceProtocol string certID string - //listener *elb.Listener }{ { - "No annotation, passthrough", - 80, 8000, "", + "No cert or BE protocol annotation, passthrough", + 80, 8000, "", "", false, "tcp", "tcp", "", }, { - "Invalid cert annotation, no protocol before equal sign", - 443, 8000, "=foo", + "BE protocol without cert annotation, passthrough", + 443, 8001, "https", "", + false, "tcp", "tcp", "", + }, + { + "Invalid cert annotation, bogus backend protocol", + 443, 8002, "bacon", "foo", true, "tcp", "tcp", "cert", }, { - "Invalid cert annotation, bogus protocol before equal sign", - 443, 8000, "bacon=foo", - true, "tcp", "tcp", "cert", - }, - { - "Invalid cert annotation, too many equal signs", - 443, 8000, "==", + "Invalid cert annotation, protocol followed by equal sign", + 443, 8003, "http=", "=", true, "tcp", "tcp", "cert", }, { "HTTPS->HTTPS", - 443, 8000, "https=cert", + 443, 8004, "https", "cert", false, "https", "https", "cert", }, { "HTTPS->HTTP", - 443, 8000, "http=cert", + 443, 8005, "http", "cert", false, "https", "http", "cert", }, { "SSL->SSL", - 443, 8000, "ssl=cert", + 443, 8006, "ssl", "cert", false, "ssl", "ssl", "cert", }, { "SSL->TCP", - 443, 8000, "tcp=cert", + 443, 8007, "tcp", "cert", false, "ssl", "tcp", "cert", }, } @@ -1259,8 +1259,11 @@ func TestGetListener(t *testing.T) { for _, test := range tests { t.Logf("Running test case %s", test.name) annotations := make(map[string]string) - if test.annotation != "" { - annotations[ServiceAnnotationLoadBalancerCertificate] = test.annotation + if test.backendProtocolAnnotation != "" { + annotations[ServiceAnnotationLoadBalancerBEProtocol] = test.backendProtocolAnnotation + } + if test.certAnnotation != "" { + annotations[ServiceAnnotationLoadBalancerCertificate] = test.certAnnotation } l, err := getListener(api.ServicePort{ NodePort: int(test.instancePort), @@ -1287,7 +1290,7 @@ func TestGetListener(t *testing.T) { SSLCertificateId: cert, } if !reflect.DeepEqual(l, expected) { - t.Errorf("Incorrect listener (%v vs %v) for case: %s", + t.Errorf("Incorrect listener (%v vs expected %v) for case: %s", l, expected, test.name) } }