public async Task MapBinaryRoutesInCloudFrontAsync(string beanstalkUrl, string subdomain, string deploymentEnvironmentName)
{
var distributionResponse = await GetDistributionByCNAMEAsync();
var domainHost = GetHostFromUrl(beanstalkUrl);
if (distributionResponse.Distribution == null)
{
loggerProvider.GetLogger().Debug($"No action being taken, could not find distribution associated with CNAME. [CNAME: {cfConfigurationProvider.CNAME}]");
return;
}
bool originAdded = false;
var origin = distributionResponse.Distribution.DistributionConfig.Origins.Items.FirstOrDefault(o => o.DomainName == domainHost);
if (origin == null)
{
loggerProvider.GetLogger().Debug($"Origin not found. Creating new origin. [DomainName: {domainHost}]");
origin = new Origin
{
Id = $"{Capitalize(subdomain)} API {Capitalize(deploymentEnvironmentName)} Beanstalk",
DomainName = domainHost,
OriginPath = string.Empty,
CustomOriginConfig = new CustomOriginConfig
{
HTTPPort = 80,
HTTPSPort = 443,
OriginProtocolPolicy = new OriginProtocolPolicy("https-only"),
OriginSslProtocols = new OriginSslProtocols
{
Items = new List<string> { "TLSv1", "TLSv1.1", "TLSv1.2" },
Quantity = 3
}
},
CustomHeaders = new CustomHeaders
{
Quantity = 1,
Items = new List<OriginCustomHeader>
{
new OriginCustomHeader { HeaderName = "x-mat-gateway-secret", HeaderValue = cfConfigurationProvider.MaterialGatewaySecret}
}
}
};
distributionResponse.Distribution.DistributionConfig.Origins.Items.Add(origin);
distributionResponse.Distribution.DistributionConfig.Origins.Quantity++;
originAdded = true;
}
bool cacheBehaviorAdded = false;
var routes = GetListOfBinaryRoutesAsync();
foreach(var route in routes)
{
var cacheBehavior = distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Items.FirstOrDefault(behavior => behavior.TargetOriginId == origin.Id && behavior.PathPattern.IsEqualIgnoreCase(route));
if(cacheBehavior == null)
{
loggerProvider.GetLogger().Debug($"Cache Behavior not found. Creating new Cache behavior. [OriginId: {origin.Id}] [Route: {route}]");
cacheBehavior = new CacheBehavior
{
TargetOriginId = origin.Id,
PathPattern = route,
AllowedMethods = new AllowedMethods
{
Items = new List<string> {"GET","HEAD","POST","PUT","PATCH","OPTIONS","DELETE"},
Quantity = 7,
CachedMethods = new CachedMethods
{
Items = new List<string> { "GET", "HEAD", "OPTIONS" },
Quantity = 3
}
},
ForwardedValues = new ForwardedValues
{
QueryString = true,
Cookies = new CookiePreference
{
Forward = new ItemSelection("none"),
WhitelistedNames = new CookieNames
{
Quantity = 0
}
},
Headers = new Headers
{
Items = new List<string> {"x-vol-tenant", "x-vol-test", "accept", "authorization"},
Quantity = 4
}
},
ViewerProtocolPolicy = new ViewerProtocolPolicy("redirect-to-https"),
TrustedSigners = new TrustedSigners
{
Enabled = false,
Quantity = 0
},
MinTTL = 0,
MaxTTL = 0,
DefaultTTL = 0,
Compress = true,
SmoothStreaming = false
};
distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Items.Add(cacheBehavior);
distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Quantity++;
cacheBehaviorAdded = true;
}
}
loggerProvider.GetLogger().Debug("Removing CacheBehavior routes that are no longer listed in the binary routes path.");
var originalList = distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Items;
distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Items = originalList.Where(behavior => behavior.TargetOriginId != origin.Id || (behavior.TargetOriginId == origin.Id && routes.Contains(behavior.PathPattern))).ToList();
var itemsRemoved = originalList.Count != distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Items.Count;
if (cacheBehaviorAdded || originAdded || itemsRemoved)
{
loggerProvider.GetLogger().Debug($"New Origin or Cache Behavior. Updating CloudFront instance. [CacheBehaviorAdded: {cacheBehaviorAdded}] [OriginAdded: {originAdded}] [ItemsRemoved: {itemsRemoved}]");
loggerProvider.GetLogger().Debug("Sorting order of cache behaviors.");
//verify that new cacheBehaviors are ahead of their API Gateway cache behaviors for order of precendent issues!!
distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Items = new List<CacheBehavior>(distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Items.OrderByDescending(behavior => behavior.PathPattern));
distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Quantity = distributionResponse.Distribution.DistributionConfig.CacheBehaviors.Items.Count;
//update distribution
using (var client = new AmazonCloudFrontClient(cfConfigurationProvider.AccessKey, cfConfigurationProvider.SecretKey, cfConfigurationProvider.RegionEndpoint))
{
var response = await client.UpdateDistributionAsync(new UpdateDistributionRequest { DistributionConfig = distributionResponse.Distribution.DistributionConfig, Id = distributionResponse.Distribution.Id, IfMatch = distributionResponse.ETag });
await WaitUntilDistributionIsDeployedAsync(response.Distribution);
loggerProvider.GetLogger().Debug("Finished updating/verifying the cloudfront distribution.");
}
}
}