Skip to content

Commit 4727a7b

Browse files
authored
chore: add NLB cert validator and custom domain to CFN template (#3166)
This PR: 1. Upload NLB cert validator and custom domain lambda scripts to S3 bucket, if DNS delegation is enabled. This is because if we pass the scripts as code into the CFN template, the two scripts together would make the template too large -> so we need to upload them to s3 and refer to the s3 location instead. 2. Add cert validator custom resource and custom domain custom resource to NLB template, conditionally. 3. Add supporting resources to the custom resource, such as roles to invoke lambda. 4. Removed the outdated script from #3157. Preceding PR: #3157 By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the Apache 2.0 License.
1 parent d825580 commit 4727a7b

File tree

14 files changed

+495
-1842
lines changed

14 files changed

+495
-1842
lines changed

cf-custom-resources/lib/nlb-cert-manager.js

Lines changed: 0 additions & 788 deletions
This file was deleted.

cf-custom-resources/test/nlb-cert-manager-test.js

Lines changed: 0 additions & 854 deletions
This file was deleted.

internal/pkg/cli/interfaces.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ type uploader interface {
314314
type customResourcesUploader interface {
315315
UploadEnvironmentCustomResources(upload s3.CompressAndUploadFunc) (map[string]string, error)
316316
UploadRequestDrivenWebServiceCustomResources(upload s3.CompressAndUploadFunc) (map[string]string, error)
317+
UploadNetworkLoadBalancedWebServiceCustomResources(upload s3.CompressAndUploadFunc) (map[string]string, error)
317318
}
318319

319320
type bucketEmptier interface {

internal/pkg/cli/mocks/mock_interfaces.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/pkg/cli/svc_deploy.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ func (o *deploySvcOpts) runtimeConfig() (*stack.RuntimeConfig, error) {
575575
}, nil
576576
}
577577

578-
func uploadCustomResources(o *uploadCustomResourcesOpts, appEnvResources *stack.AppRegionalResources) (map[string]string, error) {
578+
func uploadRDWSCustomResources(o *uploadCustomResourcesOpts, appEnvResources *stack.AppRegionalResources) (map[string]string, error) {
579579
s3Client, err := o.newS3Uploader()
580580
if err != nil {
581581
return nil, err
@@ -591,6 +591,22 @@ func uploadCustomResources(o *uploadCustomResourcesOpts, appEnvResources *stack.
591591
return urls, nil
592592
}
593593

594+
func uploadNLBWSCustomResources(o *uploadCustomResourcesOpts, appEnvResources *stack.AppRegionalResources) (map[string]string, error) {
595+
s3Client, err := o.newS3Uploader()
596+
if err != nil {
597+
return nil, err
598+
}
599+
600+
urls, err := o.uploader.UploadNetworkLoadBalancedWebServiceCustomResources(func(key string, objects ...s3.NamedBinary) (string, error) {
601+
return s3Client.ZipAndUpload(appEnvResources.S3Bucket, key, objects...)
602+
})
603+
if err != nil {
604+
return nil, fmt.Errorf("upload custom resources to bucket %s: %w", appEnvResources.S3Bucket, err)
605+
}
606+
607+
return urls, nil
608+
}
609+
594610
func (o *deploySvcOpts) stackConfiguration() (cloudformation.StackConfiguration, error) {
595611
mft, err := o.manifest()
596612
if err != nil {
@@ -645,6 +661,17 @@ func (o *deploySvcOpts) stackConfiguration() (cloudformation.StackConfiguration,
645661
return nil, err
646662
}
647663
opts = append(opts, stack.WithNLB(cidrBlocks))
664+
665+
if o.targetApp.RequiresDNSDelegation() {
666+
if err = o.retrieveAppResourcesForEnvRegion(); err != nil {
667+
return nil, err
668+
}
669+
urls, err := uploadNLBWSCustomResources(o.uploadOpts, o.appEnvResources)
670+
if err != nil {
671+
return nil, err
672+
}
673+
opts = append(opts, stack.WithNLBCustomResources(urls))
674+
}
648675
}
649676
conf, err = stack.NewLoadBalancedWebService(t, o.targetEnvironment.Name, o.targetEnvironment.App, *rc, opts...)
650677
case *manifest.RequestDrivenWebService:
@@ -686,7 +713,7 @@ func (o *deploySvcOpts) stackConfiguration() (cloudformation.StackConfiguration,
686713
if err = o.retrieveAppResourcesForEnvRegion(); err != nil {
687714
return nil, err
688715
}
689-
if urls, err = uploadCustomResources(o.uploadOpts, o.appEnvResources); err != nil {
716+
if urls, err = uploadRDWSCustomResources(o.uploadOpts, o.appEnvResources); err != nil {
690717
return nil, err
691718
}
692719
conf, err = stack.NewRequestDrivenWebServiceWithAlias(t, o.targetEnvironment.Name, appInfo, *rc, urls)

internal/pkg/cli/svc_deploy_test.go

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/aws/aws-sdk-go/aws/session"
1515
"github.com/aws/copilot-cli/internal/pkg/addon"
1616
"github.com/aws/copilot-cli/internal/pkg/aws/cloudformation"
17+
"github.com/aws/copilot-cli/internal/pkg/aws/ec2"
1718
"github.com/aws/copilot-cli/internal/pkg/aws/ecs"
1819
"github.com/aws/copilot-cli/internal/pkg/aws/identity"
1920
"github.com/aws/copilot-cli/internal/pkg/deploy"
@@ -48,6 +49,7 @@ type deploySvcMocks struct {
4849
mockS3Svc *mocks.Mockuploader
4950
mockAddons *mocks.Mocktemplater
5051
mockIdentity *mocks.MockidentityService
52+
mockUploader *mocks.MockcustomResourcesUploader
5153
}
5254

5355
type mockWorkloadMft struct {
@@ -827,6 +829,45 @@ func TestSvcDeployOpts_deploySvc(t *testing.T) {
827829
},
828830
wantErr: fmt.Errorf(`alias "v1.v2.mockDomain" is not supported in hosted zones managed by Copilot`),
829831
},
832+
"fail to upload NLB custom resource scripts": {
833+
inNLB: manifest.NetworkLoadBalancerConfiguration{
834+
Port: aws.String("80"),
835+
Aliases: manifest.Alias{String: aws.String("v1.mockDomain")},
836+
},
837+
inEnvironment: &config.Environment{
838+
Name: mockEnvName,
839+
Region: "us-west-2",
840+
},
841+
inApp: &config.Application{
842+
Name: mockAppName,
843+
Domain: "mockDomain",
844+
},
845+
mock: func(m *deploySvcMocks) {
846+
m.mockWs.EXPECT().ReadWorkloadManifest(mockSvcName).Return([]byte{}, nil)
847+
m.mockInterpolator.EXPECT().Interpolate("").Return("", nil)
848+
m.mockAppVersionGetter.EXPECT().Version().Return("v1.0.0", nil)
849+
m.mockEndpointGetter.EXPECT().ServiceDiscoveryEndpoint().Return("mockApp.local", nil)
850+
m.mockIdentity.EXPECT().Get().Return(identity.Caller{
851+
RootUserARN: "1234",
852+
}, nil)
853+
m.mockEnvDescriber.EXPECT().Describe().Return(&describe.EnvDescription{
854+
EnvironmentVPC: describe.EnvironmentVPC{
855+
ID: "mockVPCID",
856+
},
857+
}, nil)
858+
m.mockSubnetLister.EXPECT().ListVPCSubnets("mockVPCID").Return(&ec2.VPCSubnets{
859+
Public: []ec2.Subnet{{CIDRBlock: "cidr1"}, {CIDRBlock: "cidr2"}},
860+
}, nil)
861+
m.mockAppResourcesGetter.EXPECT().GetAppResourcesByRegion(&config.Application{
862+
Name: mockAppName,
863+
Domain: "mockDomain",
864+
}, "us-west-2").Return(&stack.AppRegionalResources{
865+
S3Bucket: "mockBucket",
866+
}, nil)
867+
m.mockUploader.EXPECT().UploadNetworkLoadBalancedWebServiceCustomResources(gomock.Any()).Return(nil, errors.New("some error"))
868+
},
869+
wantErr: fmt.Errorf("upload custom resources to bucket mockBucket: some error"),
870+
},
830871
"error if fail to deploy service": {
831872
inEnvironment: &config.Environment{
832873
Name: mockEnvName,
@@ -1043,6 +1084,7 @@ func TestSvcDeployOpts_deploySvc(t *testing.T) {
10431084
mockEnvDescriber: mocks.NewMockenvDescriber(ctrl),
10441085
mockSubnetLister: mocks.NewMockvpcSubnetLister(ctrl),
10451086
mockIdentity: mocks.NewMockidentityService(ctrl),
1087+
mockUploader: mocks.NewMockcustomResourcesUploader(ctrl),
10461088
}
10471089
tc.mock(m)
10481090

@@ -1098,6 +1140,12 @@ func TestSvcDeployOpts_deploySvc(t *testing.T) {
10981140
now: func() time.Time {
10991141
return mockNowTime
11001142
},
1143+
uploadOpts: &uploadCustomResourcesOpts{
1144+
uploader: m.mockUploader,
1145+
newS3Uploader: func() (uploader, error) {
1146+
return nil, nil
1147+
},
1148+
},
11011149
}
11021150

11031151
gotErr := opts.deploySvc()
@@ -1152,7 +1200,6 @@ func TestSvcDeployOpts_rdWebServiceStackConfiguration(t *testing.T) {
11521200
m.mockWorkspace.EXPECT().ReadWorkloadManifest(mockSvcName).Return([]byte{}, nil)
11531201
m.mockInterpolator.EXPECT().Interpolate("").Return("", nil)
11541202
m.mockEndpointGetter.EXPECT().ServiceDiscoveryEndpoint().Return("mockApp.local", nil)
1155-
11561203
},
11571204

11581205
wantErr: errors.New("alias specified when application is not associated with a domain"),

internal/pkg/cli/svc_package.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func newPackageSvcOpts(vars packageSvcVars) (*packageSvcOpts, error) {
160160
if err != nil {
161161
return nil, fmt.Errorf("get application %s resources from region %s: %w", app.Name, env.Region, err)
162162
}
163-
urls, err := uploadCustomResources(&uploadCustomResourcesOpts{
163+
urls, err := uploadRDWSCustomResources(&uploadCustomResourcesOpts{
164164
uploader: template.New(),
165165
newS3Uploader: func() (uploader, error) {
166166
envRegion := env.Region

internal/pkg/deploy/cloudformation/stack/lb_web_svc.go

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const (
2121
lbWebSvcRulePriorityGeneratorPath = "custom-resources/alb-rule-priority-generator.js"
2222
desiredCountGeneratorPath = "custom-resources/desired-count-delegation.js"
2323
envControllerPath = "custom-resources/env-controller.js"
24-
nlbCertManagerPath = "custom-resources/nlb-cert-validator-updater.js"
2524
)
2625

2726
// Parameter logical IDs for a load balanced web service.
@@ -52,9 +51,10 @@ type LoadBalancedWebService struct {
5251
// `httpsEnabled` has the same value with `dnsDelegationEnabled`, because we enabled https
5352
// automatically the app is associated with a domain. When an ALB is disabled, `httpsEnabled`
5453
// should always be false; hence they could have different values at this time.
55-
dnsDelegationEnabled bool
56-
publicSubnetCIDRBlocks []string
57-
appInfo deploy.AppInformation
54+
dnsDelegationEnabled bool
55+
publicSubnetCIDRBlocks []string
56+
appInfo deploy.AppInformation
57+
nlbCustomResourceS3URLs map[string]string
5858

5959
parser loadBalancedWebSvcReadParser
6060
}
@@ -78,6 +78,13 @@ func WithNLB(cidrBlocks []string) func(s *LoadBalancedWebService) {
7878
}
7979
}
8080

81+
// WithNLBDNSCustomResources includes NLB custom resource URLs in a LoadBalancedWebService.
82+
func WithNLBCustomResources(urls map[string]string) func(s *LoadBalancedWebService) {
83+
return func(s *LoadBalancedWebService) {
84+
s.nlbCustomResourceS3URLs = urls
85+
}
86+
}
87+
8188
// WithDNSDelegation enables DNS delegation for a LoadBalancedWebService.
8289
func WithDNSDelegation(app deploy.AppInformation) func(s *LoadBalancedWebService) {
8390
return func(s *LoadBalancedWebService) {
@@ -196,40 +203,42 @@ func (s *LoadBalancedWebService) Template() (string, error) {
196203
return "", err
197204
}
198205
content, err := s.parser.ParseLoadBalancedWebService(template.WorkloadOpts{
199-
Variables: s.manifest.TaskConfig.Variables,
200-
Secrets: s.manifest.TaskConfig.Secrets,
201-
Aliases: aliases,
202-
NestedStack: addonsOutputs,
203-
AddonsExtraParams: addonsParams,
204-
Sidecars: sidecars,
205-
LogConfig: convertLogging(s.manifest.Logging),
206-
DockerLabels: s.manifest.ImageConfig.Image.DockerLabels,
207-
Autoscaling: autoscaling,
208-
CapacityProviders: capacityProviders,
209-
DesiredCountOnSpot: desiredCountOnSpot,
210-
ExecuteCommand: convertExecuteCommand(&s.manifest.ExecuteCommand),
211-
WorkloadType: manifest.LoadBalancedWebServiceType,
212-
HealthCheck: convertContainerHealthCheck(s.manifest.ImageConfig.HealthCheck),
213-
HTTPHealthCheck: convertHTTPHealthCheck(&s.manifest.HealthCheck),
214-
DeregistrationDelay: deregistrationDelay,
215-
AllowedSourceIps: allowedSourceIPs,
216-
RulePriorityLambda: rulePriorityLambda.String(),
217-
DesiredCountLambda: desiredCountLambda.String(),
218-
EnvControllerLambda: envControllerLambda.String(),
219-
NLBCertManagerFunctionLambda: nlbConfig.certManagerLambda,
220-
Storage: convertStorageOpts(s.manifest.Name, s.manifest.Storage),
221-
Network: convertNetworkConfig(s.manifest.Network),
222-
EntryPoint: entrypoint,
223-
Command: command,
224-
DependsOn: convertDependsOn(s.manifest.ImageConfig.Image.DependsOn),
225-
CredentialsParameter: aws.StringValue(s.manifest.ImageConfig.Image.Credentials),
226-
ServiceDiscoveryEndpoint: s.rc.ServiceDiscoveryEndpoint,
227-
Publish: publishers,
228-
Platform: convertPlatform(s.manifest.Platform),
229-
HTTPVersion: convertHTTPVersion(s.manifest.ProtocolVersion),
230-
NLB: nlbConfig.settings,
231-
AppDNSName: nlbConfig.appDNSName,
232-
AppDNSDelegationRole: nlbConfig.appDNSDelegationRole,
206+
Variables: s.manifest.TaskConfig.Variables,
207+
Secrets: s.manifest.TaskConfig.Secrets,
208+
Aliases: aliases,
209+
NestedStack: addonsOutputs,
210+
AddonsExtraParams: addonsParams,
211+
Sidecars: sidecars,
212+
LogConfig: convertLogging(s.manifest.Logging),
213+
DockerLabels: s.manifest.ImageConfig.Image.DockerLabels,
214+
Autoscaling: autoscaling,
215+
CapacityProviders: capacityProviders,
216+
DesiredCountOnSpot: desiredCountOnSpot,
217+
ExecuteCommand: convertExecuteCommand(&s.manifest.ExecuteCommand),
218+
WorkloadType: manifest.LoadBalancedWebServiceType,
219+
HealthCheck: convertContainerHealthCheck(s.manifest.ImageConfig.HealthCheck),
220+
HTTPHealthCheck: convertHTTPHealthCheck(&s.manifest.HealthCheck),
221+
DeregistrationDelay: deregistrationDelay,
222+
AllowedSourceIps: allowedSourceIPs,
223+
RulePriorityLambda: rulePriorityLambda.String(),
224+
DesiredCountLambda: desiredCountLambda.String(),
225+
EnvControllerLambda: envControllerLambda.String(),
226+
Storage: convertStorageOpts(s.manifest.Name, s.manifest.Storage),
227+
Network: convertNetworkConfig(s.manifest.Network),
228+
EntryPoint: entrypoint,
229+
Command: command,
230+
DependsOn: convertDependsOn(s.manifest.ImageConfig.Image.DependsOn),
231+
CredentialsParameter: aws.StringValue(s.manifest.ImageConfig.Image.Credentials),
232+
ServiceDiscoveryEndpoint: s.rc.ServiceDiscoveryEndpoint,
233+
Publish: publishers,
234+
Platform: convertPlatform(s.manifest.Platform),
235+
HTTPVersion: convertHTTPVersion(s.manifest.ProtocolVersion),
236+
NLB: nlbConfig.settings,
237+
AppDNSName: nlbConfig.appDNSName,
238+
AppDNSDelegationRole: nlbConfig.appDNSDelegationRole,
239+
ScriptBucketName: nlbConfig.bucket,
240+
NLBCertValidatorFunctionLambda: nlbConfig.certValidatorLambda,
241+
NLBCustomDomainFunctionLambda: nlbConfig.customDomainLambda,
233242
})
234243
if err != nil {
235244
return "", err

internal/pkg/deploy/cloudformation/stack/transformers.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,9 @@ type networkLoadBalancerConfig struct {
264264
// If a domain is associated these values are not empty.
265265
appDNSDelegationRole *string
266266
appDNSName *string
267-
certManagerLambda string
267+
bucket *string
268+
certValidatorLambda string
269+
customDomainLambda string
268270
}
269271

270272
func (s *LoadBalancedWebService) convertNetworkLoadBalancer() (networkLoadBalancerConfig, error) {
@@ -329,11 +331,13 @@ func (s *LoadBalancedWebService) convertNetworkLoadBalancer() (networkLoadBalanc
329331
config.appDNSName = dnsName
330332
config.appDNSDelegationRole = dnsDelegationRole
331333

332-
nlbCertManagerLambda, err := s.parser.Read(nlbCertManagerPath)
334+
bucket, urls, err := parseS3URLs(s.nlbCustomResourceS3URLs)
333335
if err != nil {
334-
return networkLoadBalancerConfig{}, fmt.Errorf("read network load balancer certificate manager lambda: %w", err)
336+
return networkLoadBalancerConfig{}, err
335337
}
336-
config.certManagerLambda = nlbCertManagerLambda.String()
338+
config.bucket = bucket
339+
config.certValidatorLambda = aws.StringValue(urls[template.NLBCertValidatorLambdaFileName])
340+
config.customDomainLambda = aws.StringValue(urls[template.NLBCustomDomainLambdaFileName])
337341
}
338342
return config, nil
339343
}

0 commit comments

Comments
 (0)