AWS Security ChangesHomeSearch

AWS code-library documentation change

Service: code-library · 2025-08-01 · Documentation low

File: code-library/latest/ug/java_2_cloudfront_code_examples.md

Summary

Added multiple Java code examples demonstrating creation of multi-tenant CloudFront distributions and tenants with various certificate configurations (wildcard certs, ACM certs, CloudFront-managed certs, self-hosted certs)

Security assessment

The changes demonstrate security-related configurations like SSL/TLS certificate management (SNI_ONLY method), domain validation, and certificate requirements, but there is no evidence these changes address a specific security vulnerability. They document standard security practices for certificate handling in CloudFront multi-tenant setups.

Diff

diff --git a/code-library/latest/ug/java_2_cloudfront_code_examples.md b/code-library/latest/ug/java_2_cloudfront_code_examples.md
index 907ae12c6..9e65ebf9f 100644
--- a//code-library/latest/ug/java_2_cloudfront_code_examples.md
+++ b//code-library/latest/ug/java_2_cloudfront_code_examples.md
@@ -522,0 +523,379 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+The following code example shows how to create a multi-tenant distribution and distribution tenant with various configurations.
+
+**SDK for Java 2.x**
+    
+
+###### Note
+
+There's more on GitHub. Find the complete example and learn how to set up and run in the [AWS Code Examples Repository](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/cloudfront#code-examples). 
+
+The following example demonstrates how to create a multi-tenant distribution with parameters and wildcard certificate.
+    
+    
+    import software.amazon.awssdk.core.internal.waiters.ResponseOrException;
+    import software.amazon.awssdk.services.cloudfront.CloudFrontClient;
+    import software.amazon.awssdk.services.cloudfront.model.ConnectionMode;
+    import software.amazon.awssdk.services.cloudfront.model.CreateDistributionResponse;
+    import software.amazon.awssdk.services.cloudfront.model.Distribution;
+    import software.amazon.awssdk.services.cloudfront.model.GetDistributionResponse;
+    import software.amazon.awssdk.services.cloudfront.model.HttpVersion;
+    import software.amazon.awssdk.services.cloudfront.model.Method;
+    import software.amazon.awssdk.services.cloudfront.model.SSLSupportMethod;
+    import software.amazon.awssdk.services.cloudfront.model.ViewerProtocolPolicy;
+    import software.amazon.awssdk.services.cloudfront.waiters.CloudFrontWaiter;
+    import software.amazon.awssdk.services.s3.S3Client;
+    
+    import java.time.Instant;
+    
+    public class CreateMultiTenantDistribution {
+        public static Distribution CreateMultiTenantDistributionWithCert(CloudFrontClient cloudFrontClient,
+                                                                         S3Client s3Client,
+                                                                         final String bucketName,
+                                                                         final String certificateArn) {
+            // fetch the origin info if necessary
+            final String region = s3Client.headBucket(b -> b.bucket(bucketName)).sdkHttpResponse().headers()
+                    .get("x-amz-bucket-region").get(0);
+            final String originDomain = bucketName + ".s3." + region + ".amazonaws.com";
+            String originId = originDomain; // Use the originDomain value for the originId.
+    
+            CreateDistributionResponse createDistResponse = cloudFrontClient.createDistribution(builder -> builder
+                    .distributionConfig(b1 -> b1
+                            .httpVersion(HttpVersion.HTTP2)
+                            .enabled(true)
+                            .comment("Template Distribution with cert built with java")
+                            .connectionMode(ConnectionMode.TENANT_ONLY)
+                            .callerReference(Instant.now().toString())
+                            .viewerCertificate(certBuilder -> certBuilder
+                                    .acmCertificateArn(certificateArn)
+                                    .sslSupportMethod(SSLSupportMethod.SNI_ONLY))
+                            .origins(b2 -> b2
+                                    .quantity(1)
+                                    .items(b3 -> b3
+                                            .domainName(originDomain)
+                                            .id(originId)
+                                            .originPath("/{{tenantName}}")
+                                            .s3OriginConfig(builder4 -> builder4
+                                                    .originAccessIdentity(
+                                                            ""))))
+                            .tenantConfig(b5 -> b5
+                                    .parameterDefinitions(b6 -> b6
+                                            .name("tenantName")
+                                            .definition(b7 -> b7
+                                                    .stringSchema(b8 -> b8
+                                                            .comment("tenantName value")
+                                                            .defaultValue("root")
+                                                            .required(false)))))
+                            .defaultCacheBehavior(b2 -> b2
+                                    .viewerProtocolPolicy(ViewerProtocolPolicy.ALLOW_ALL)
+                                    .targetOriginId(originId)
+                                    .cachePolicyId("658327ea-f89d-4fab-a63d-7e88639e58f6") // CachingOptimized Policy
+                                    .allowedMethods(b4 -> b4
+                                            .quantity(2)
+                                            .items(Method.HEAD, Method.GET)))
+                    ));
+    
+            final Distribution distribution = createDistResponse.distribution();
+            try (CloudFrontWaiter cfWaiter = CloudFrontWaiter.builder().client(cloudFrontClient).build()) {
+                ResponseOrException<GetDistributionResponse> responseOrException = cfWaiter
+                        .waitUntilDistributionDeployed(builder -> builder.id(distribution.id()))
+                        .matched();
+                responseOrException.response()
+                        .orElseThrow(() -> new RuntimeException("Distribution not created"));
+            }
+            return distribution;
+        }
+    
+        public static Distribution CreateMultiTenantDistributionNoCert(CloudFrontClient cloudFrontClient,
+                                                                 S3Client s3Client,
+                                                                 final String bucketName) {
+            // fetch the origin info if necessary
+            final String region = s3Client.headBucket(b -> b.bucket(bucketName)).sdkHttpResponse().headers()
+                    .get("x-amz-bucket-region").get(0);
+            final String originDomain = bucketName + ".s3." + region + ".amazonaws.com";
+            String originId = originDomain; // Use the originDomain value for the originId.
+    
+            CreateDistributionResponse createDistResponse = cloudFrontClient.createDistribution(builder -> builder
+                    .distributionConfig(b1 -> b1
+                            .httpVersion(HttpVersion.HTTP2)
+                            .enabled(true)
+                            .comment("Template Distribution with cert built with java")
+                            .connectionMode(ConnectionMode.TENANT_ONLY)
+                            .callerReference(Instant.now().toString())
+                            .origins(b2 -> b2
+                                    .quantity(1)
+                                    .items(b3 -> b3
+                                            .domainName(originDomain)
+                                            .id(originId)
+                                            .originPath("/{{tenantName}}")
+                                            .s3OriginConfig(builder4 -> builder4
+                                                    .originAccessIdentity(
+                                                            ""))))
+                            .tenantConfig(b5 -> b5
+                                    .parameterDefinitions(b6 -> b6
+                                            .name("tenantName")
+                                            .definition(b7 -> b7
+                                                    .stringSchema(b8 -> b8
+                                                            .comment("tenantName value")
+                                                            .defaultValue("root")
+                                                            .required(false)))))
+                            .defaultCacheBehavior(b2 -> b2
+                                    .viewerProtocolPolicy(ViewerProtocolPolicy.ALLOW_ALL)
+                                    .targetOriginId(originId)
+                                    .cachePolicyId("658327ea-f89d-4fab-a63d-7e88639e58f6") // CachingOptimized Policy
+                                    .allowedMethods(b4 -> b4
+                                            .quantity(2)
+                                            .items(Method.HEAD, Method.GET)))
+                    ));
+    
+            final Distribution distribution = createDistResponse.distribution();
+            try (CloudFrontWaiter cfWaiter = CloudFrontWaiter.builder().client(cloudFrontClient).build()) {
+                ResponseOrException<GetDistributionResponse> responseOrException = cfWaiter
+                        .waitUntilDistributionDeployed(builder -> builder.id(distribution.id()))
+                        .matched();
+                responseOrException.response()
+                        .orElseThrow(() -> new RuntimeException("Distribution not created"));
+            }
+            return distribution;
+        }
+    }
+    
+    
+
+The following example demonstrates how to create a distribution tenant associated with that template, including utilizing the parameter we declared above. Note that we don't need to add certificate info here because our domain is already covered by the parent template.
+    
+    
+    import software.amazon.awssdk.services.cloudfront.CloudFrontClient;
+    import software.amazon.awssdk.services.cloudfront.model.CreateConnectionGroupResponse;
+    import software.amazon.awssdk.services.cloudfront.model.CreateDistributionTenantResponse;
+    import software.amazon.awssdk.services.cloudfront.model.DistributionTenant;
+    import software.amazon.awssdk.services.cloudfront.model.GetConnectionGroupResponse;
+    import software.amazon.awssdk.services.cloudfront.model.ValidationTokenHost;
+    import software.amazon.awssdk.services.route53.Route53Client;
+    import software.amazon.awssdk.services.route53.model.RRType;
+    
+    import java.time.Instant;
+    
+    public class CreateDistributionTenant {
+    
+        public static DistributionTenant createDistributionTenantNoCert(CloudFrontClient cloudFrontClient,
+                                                                        Route53Client route53Client,
+                                                                        String distributionId,
+                                                                        String domain,
+                                                                        String hostedZoneId) {
+            CreateDistributionTenantResponse createResponse = cloudFrontClient.createDistributionTenant(builder -> builder
+                    .distributionId(distributionId)
+                    .domains(b1 -> b1
+                            .domain(domain))
+                    .parameters(b2 -> b2
+                            .name("tenantName")
+                            .value("myTenant"))
+                    .enabled(false)
+                    .name("no-cert-tenant")
+            );
+    
+            final DistributionTenant distributionTenant = createResponse.distributionTenant();
+    
+            // Then update the Route53 hosted zone to point your domain at the distribution tenant
+            // We fetch the RoutingEndpoint to point to via the default connection group that was created for your tenant
+            final GetConnectionGroupResponse fetchedConnectionGroup = cloudFrontClient.getConnectionGroup(builder -> builder
+                    .identifier(distributionTenant.connectionGroupId()));
+    
+            route53Client.changeResourceRecordSets(builder -> builder
+                    .hostedZoneId(hostedZoneId)
+                    .changeBatch(b1 -> b1
+                            .comment("ChangeBatch comment")
+                            .changes(b2 -> b2
+                                    .resourceRecordSet(b3 -> b3
+                                            .name(domain)
+                                            .type("CNAME")
+                                            .ttl(300L)
+                                            .resourceRecords(b4 -> b4
+                                                    .value(fetchedConnectionGroup.connectionGroup().routingEndpoint())))
+                                    .action("CREATE"))
+                    ));
+            return distributionTenant;
+        }