A while back, I had to adjust the policy of all Elastic Load Balancers in my organization to disable SSLv3 due to the POODLE exploit. This can be an error-prone task if done by hand, especially if your architecture spans multiple regions and/or more than a handful of ELBs. The nice thing about cloud architecture, is that nearly everything can be automated and/or scripted. For that reason, I went ahead and wrote a PowerShell script to handle this.
Most other write-ups I have seen do not take into account Stickiness policies, which are also applied to listeners. If you run the Set-ELBLoadBalancerPolicyOfListener cmdlet with only an SSL policy applied, it will remove any other existing listener policies. It is important to check the ELB for other policies, and make sure they are reapplied. There is logic in this script that handles that.
It is important to note that this script makes use of Amazon’s template SSL Negotation Policies, but could be adapted to make use of your own.
As of 4/9/15, you cannot simply set the ELB policy to a newer reference policy, although AWS documentation states otherwise. For this reason, a new policy must be created which references the AWS Reference-Security-Policy of choice. You can retrieve a list of available reference policies with the Get-ELBLoadBalancerPolicy cmdlet.
Code also available on my GitHub
# AWS Global ELB SSL Policy
# Brian Dwyer - Intelligent Digital Services - 4/5/15
# Variables
$PolicyName="SSL-POLICY--$(Get-Date -Format yy-MM-ddTHHmmss)"
$ELBReferencePolicy='ELBSecurityPolicy-2015-03'
# Dependencies
Import-Module AWSPowerShell
Write-Host 'Finding AWS Regions containing ELBs...'
$RegionsWithELBs = @{}
ForEach ( $region in (Get-EC2Region).RegionName )
{
$ELB_Count = (Get-ELBLoadBalancer -Region $region).count
if ( $ELB_Count -ge 1 )
{
$RegionsWithELBs.Add($region, $ELB_Count)
}
}
# Display ELB Regions & Count
$tformat = @{Expression={$_.Name};Label="Region"}, @{Expression={$_.Value};Label="ELB Count"}
$RegionsWithELBs.GetEnumerator() | Sort-Object Value -Descending | Format-Table $tformat -AutoSize
ForEach ( $region in $RegionsWithELBs.Keys )
{
# Verify reference policy existence in region
if ( (Get-ELBLoadBalancerPolicy -Region $region).PolicyName -contains $ELBReferencePolicy )
{
Write-Host "Modifying ELBs in region: '$region'"
# Loop through the ELBs
ForEach ( $lb in (Get-ELBLoadBalancer -Region $region ).LoadBalancerName )
{
# Verify ELB serves HTTPS
if ( (Get-ELBLoadBalancer -Region $region -LoadBalancerName $lb).ListenerDescriptions.Listener.Protocol -contains 'HTTPS' )
{
# Find Existing Policies (App/Cookie Stickiness, etc.)
$PoliciesToApply = @($PolicyName)
ForEach ( $currentpolicy in ((Get-ELBLoadBalancer -Region $region -LoadBalancerName $lb).ListenerDescriptions | Where-Object { $_.Listener.Protocol -contains 'HTTPS'}).PolicyNames )
{
if ( (Get-ELBLoadBalancerPolicy -Region $region -LoadBalancerName $lb -PolicyName $currentpolicy).PolicyTypeName -ne 'SSLNegotiationPolicyType' )
{
$PoliciesToApply += @($currentpolicy)
}
}
# Configure SSL Policy
Write-Host "Creating '$PolicyName' from '$ELBReferencePolicy' for $lb"
New-ELBLoadBalancerPolicy -Region $region -LoadBalancerName $lb -PolicyName $PolicyName `
-PolicyTypeName SSLNegotiationPolicyType `
-PolicyAttribute @{ AttributeName="Reference-Security-Policy";AttributeValue="$ELBReferencePolicy"} `
-Force
Write-Host "Activating policy '$PolicyName' for ELB: $lb"
Set-ELBLoadBalancerPolicyOfListener -Region "$region" -LoadBalancerName "$lb" -LoadBalancerPort 443 -PolicyName $PoliciesToApply
# Cleanup Old Policies
ForEach ($policy in (Get-ELBLoadBalancerPolicy -Region "$region" -LoadBalancerName "$lb" | Where-Object {$_.PolicyTypeName -eq 'SSLNegotiationPolicyType'}).PolicyName)
{
if ( $policy -ne $PolicyName -and $policy -ne $ELBReferencePolicy )
{
Write-Host "Removing old policy '$policy' from ELB: $lb"
Remove-ELBLoadBalancerPolicy -Region "$region" -LoadBalancerName "$lb" -PolicyName $policy -Force
}
}
}
}
}
Else
{
Write-Host "Region $region does not contain policy $ELBReferencePolicy"
}
}