Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Security Policy for Listener in Application load balancer #4099

Merged
merged 9 commits into from Oct 22, 2022
10 changes: 10 additions & 0 deletions internal/pkg/deploy/cloudformation/stack/env.go
Expand Up @@ -405,13 +405,15 @@ func (e *EnvStackConfig) publicHTTPConfig() (template.HTTPConfig, error) {
CIDRPrefixListIDs: e.in.CIDRPrefixListIDs,
ImportedCertARNs: e.importPublicCertARNs(),
ELBAccessLogs: elbAccessLogsConfig,
SSLPolicy: e.getPublicSSLPolicy(),
}, nil
}

func (e *EnvStackConfig) privateHTTPConfig() template.HTTPConfig {
return template.HTTPConfig{
ImportedCertARNs: e.importPrivateCertARNs(),
CustomALBSubnets: e.internalALBSubnets(),
SSLPolicy: e.getPrivateSSLPolicy(),
}
}

Expand Down Expand Up @@ -524,3 +526,11 @@ func (e *EnvStackConfig) internalALBSubnets() []string {
// Fallthrough to SSM config.
return e.in.InternalALBSubnets
}

func (e *EnvStackConfig) getPublicSSLPolicy() *string {
return e.in.Mft.EnvironmentConfig.HTTPConfig.Public.SSLPolicy
}

func (e *EnvStackConfig) getPrivateSSLPolicy() *string {
return e.in.Mft.EnvironmentConfig.HTTPConfig.Public.SSLPolicy
KollaAdithya marked this conversation as resolved.
Show resolved Hide resolved
}
Expand Up @@ -153,7 +153,7 @@ network:

wantedFileName: "template-with-custom-security-group.yml",
},
"generate template with embedded manifest file with empty security groups rules added by the customer": {
"generate template with embedded manifest file with imported certificates and SSL Policy and empty security groups rules added by the customer": {
input: func() *deploy.CreateEnvironmentInput {
rawMft := `name: test
type: Environment
Expand All @@ -163,6 +163,7 @@ http:
certificates:
- cert-1
- cert-2
ssl_policy: ELBSecurityPolicy-FS-1-1-2019-08
observability:
container_insights: true # Enable container insights.
security_group:
Expand Down Expand Up @@ -190,7 +191,7 @@ security_group:
}
}(),

wantedFileName: "template-with-custom-empty-security-group.yml",
wantedFileName: "template-with-imported-certs-sslpolicy-custom-empty-security-group.yml",
},
"generate template with custom resources": {
input: func() *deploy.CreateEnvironmentInput {
Expand Down
Expand Up @@ -11,6 +11,7 @@ Metadata:
certificates:
- cert-1
- cert-2
ssl_policy: ELBSecurityPolicy-FS-1-1-2019-08
observability:
container_insights: true # Enable container insights.
security_group:
Expand Down Expand Up @@ -400,6 +401,7 @@ Resources:
LoadBalancerArn: !Ref PublicLoadBalancer
Port: 443
Protocol: HTTPS
SslPolicy: ELBSecurityPolicy-FS-1-1-2019-08
HTTPSImportCertificate2:
Type: AWS::ElasticLoadBalancingV2::ListenerCertificate
Condition: ExportHTTPSListener
Expand Down Expand Up @@ -456,6 +458,7 @@ Resources:
LoadBalancerArn: !Ref InternalLoadBalancer
Port: 443
Protocol: HTTPS
SslPolicy: ELBSecurityPolicy-FS-1-1-2019-08
InternalWorkloadsHostedZone:
Metadata:
'aws:copilot:description': 'A hosted zone named test.demo.internal for backends behind a private load balancer'
Expand Down
6 changes: 4 additions & 2 deletions internal/pkg/manifest/env.go
Expand Up @@ -443,6 +443,7 @@ type PublicHTTPConfig struct {
Certificates []string `yaml:"certificates,omitempty"`
ELBAccessLogs ELBAccessLogsArgsOrBool `yaml:"access_logs,omitempty"`
Ingress RestrictiveIngress `yaml:"ingress,omitempty"`
SSLPolicy *string `yaml:"ssl_policy,omitempty"`
}

// ELBAccessLogsArgsOrBool is a custom type which supports unmarshaling yaml which
Expand Down Expand Up @@ -527,19 +528,20 @@ func (i RestrictiveIngress) IsEmpty() bool {

// IsEmpty returns true if there is no customization to the public ALB.
func (cfg PublicHTTPConfig) IsEmpty() bool {
return len(cfg.Certificates) == 0 && cfg.DeprecatedSG.IsEmpty() && cfg.ELBAccessLogs.isEmpty() && cfg.Ingress.IsEmpty()
return len(cfg.Certificates) == 0 && cfg.DeprecatedSG.IsEmpty() && cfg.ELBAccessLogs.isEmpty() && cfg.Ingress.IsEmpty() && cfg.SSLPolicy == nil
}

type privateHTTPConfig struct {
InternalALBSubnets []string `yaml:"subnets,omitempty"`
Certificates []string `yaml:"certificates,omitempty"`
DeprecatedSG DeprecatedALBSecurityGroupsConfig `yaml:"security_groups,omitempty"` // Deprecated. This field is now available in Ingress.
Ingress RelaxedIngress `yaml:"ingress,omitempty"`
SSLPolicy *string `yaml:"ssl_policy,omitempty"`
}

// IsEmpty returns true if there is no customization to the internal ALB.
func (cfg privateHTTPConfig) IsEmpty() bool {
return len(cfg.InternalALBSubnets) == 0 && len(cfg.Certificates) == 0 && cfg.DeprecatedSG.IsEmpty() && cfg.Ingress.IsEmpty()
return len(cfg.InternalALBSubnets) == 0 && len(cfg.Certificates) == 0 && cfg.DeprecatedSG.IsEmpty() && cfg.Ingress.IsEmpty() && cfg.SSLPolicy == nil
}

// HasVPCIngress returns true if the private ALB allows ingress from within the VPC.
Expand Down
14 changes: 12 additions & 2 deletions internal/pkg/manifest/env_test.go
Expand Up @@ -895,11 +895,16 @@ func TestPublicHTTPConfig_IsEmpty(t *testing.T) {
"empty": {
wanted: true,
},
"not empty": {
"not empty when Certificates are attached": {
in: PublicHTTPConfig{
Certificates: []string{"mock-cert-1"},
},
},
"not empty when SSL Policy is present": {
in: PublicHTTPConfig{
SSLPolicy: aws.String("mock-ELB-ELBSecurityPolicy"),
},
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
Expand All @@ -917,11 +922,16 @@ func TestPrivateHTTPConfig_IsEmpty(t *testing.T) {
"empty": {
wanted: true,
},
"not empty": {
"not empty when Certificates are attached": {
in: privateHTTPConfig{
InternalALBSubnets: []string{"mock-subnet-1"},
},
},
"not empty when SSL Policy is present": {
in: privateHTTPConfig{
SSLPolicy: aws.String("mock-ELB-ELBSecurityPolicy"),
},
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions internal/pkg/template/env.go
Expand Up @@ -135,6 +135,7 @@ type HTTPConfig struct {
ImportedCertARNs []string
CustomALBSubnets []string
ELBAccessLogs *ELBAccessLogs
SSLPolicy *string
}

// ELBAccessLogs represents configuration for ELB access logs S3 bucket.
Expand Down
6 changes: 6 additions & 0 deletions internal/pkg/template/templates/environment/cf.yml
Expand Up @@ -356,6 +356,9 @@ Resources:
LoadBalancerArn: !Ref PublicLoadBalancer
Port: 443
Protocol: HTTPS
{{ if .PublicHTTPConfig.SSLPolicy }}
SslPolicy: {{ .PublicHTTPConfig.SSLPolicy }}
KollaAdithya marked this conversation as resolved.
Show resolved Hide resolved
{{ end }}
{{- range $ind, $arn := .PublicHTTPConfig.ImportedCertARNs}}
{{- if gt $ind 0}}
HTTPSImportCertificate{{inc $ind}}:
Expand Down Expand Up @@ -432,6 +435,9 @@ Resources:
LoadBalancerArn: !Ref InternalLoadBalancer
Port: 443
Protocol: HTTPS
{{ if .PublicHTTPConfig.SSLPolicy }}
SslPolicy: {{ .PublicHTTPConfig.SSLPolicy }}
KollaAdithya marked this conversation as resolved.
Show resolved Hide resolved
{{ end }}
{{- range $ind, $arn := .PrivateHTTPConfig.ImportedCertARNs}}
{{- if gt $ind 0}}
InternalHTTPSImportCertificate{{inc $ind}}:
Expand Down