Question

I've been testing and experimenting a bit to find out how exactly to upload SSL Certificates to AWS's Elastic Load Balancer (figuring out issues with different key and certificate encodings).

Therefore I have quite a few test certificates on there that I've generated with either the wrong information, missing certificate chains or just bogus data.

As far as I can see there is no way to delete these certificates, or even update/replace the ones that are missing certain information. AWS's instructions to "updating a certificate" (http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/DeveloperGuide/US_UpdatingLoadBalancerSSL.html) actually just shows you how to change the load balancer listener to use a different certificate that is either already on there or that you can then upload as well! (that's exactly how I ended up with so many certificates on there in the first place).

Could someone please tell me that I'm wrong and there is a way to delete them? :D (and preferably also how to do that)

Was it helpful?

Solution

This is not possible. You have to delete the ELB and make a new one.

See: https://forums.aws.amazon.com/thread.jspa?threadID=57632

It is possible to remove them from the IAM but they do not always remove correctly from the ELB, and the ELB can continue to use an old one. I would definitely say the safest way is to create a new ELB and delete the old one

OTHER TIPS

You can delete the ELB associated certificate by using the following command

 aws iam delete-server-certificate --server-certificate-name certificate_object_name

There is a limit on the number of these certificates you can have [10].

Edit: Seven years later the commands have changed a bit:

aws iam delete-server-certificate --server-certificate-name <cert-name>

You can get the certificate name using:

aws iam list-server-certificates


You can use the command line tool iam-servercertdel to do this. You'll need to get the path first though:

iam-servercertlistbypath

Once you have that, you can delete it:

iam-servercertdel arn:aws:iam::10494620000:server-certificate/my-company-cert

However chantheman is correct in that AWS services can be flaky sometimes, so recreating the ELB is sometimes better.

Issue the following command using the amazon API tools:

iam-servercertdel -s SERVERCERTNAME

It is not possible through the Amazon console, but through API calls. http://docs.amazonwebservices.com/IAM/latest/APIReference/API_DeleteServerCertificate.html You may not have noticed this because they are under IAM, not EC2.

Your first step should be to stop using the certificate in the load balancer. Either swap all listeners to another certificate or don't use a certificate at all. @SDillard recommended in his answer that you should wait a few minutes before continuing on to delete the certificate.

You can delete a certificate using the following command in the AWS Powershell console (see the other answers for details of how to do this using other tools). Install the AWS SDK for .Net to get the console.

Remove-IAMServerCertificate <CertificateName>

Note that the <CertificateName> should not be the full resource identifier which looks like the following. The certificate name is the last segment.

arn:aws:iam::297826370175:server-certificate/

To get a list of all certificates, you can use the following command.

Get-IAMServerCertificates

Now when you return to the SSL certificate configuration for the listeners in the load balancer (within the AWS Management Console), you should no longer see the certificate that you deleted in the drop down box.

If for some reason, this does not work then you could also try recreating the load balancer (delete the existing one and create a new one). Be aware though, that this will probably mean that you need to make some changes related to DNS as the new load balancer will have different DNS names. Your CName records will probably need to be changed.

Update: It looks as though there have been some changes to the API since I first posted this answer. I was just able to remove a certificate that was currently being used by a listener. Although in the listener, certificate column it said 'Invalid Certificate' the old certificate continued to be returned when I browsed to the site - not sure if this was just a temporary thing.

If the certificate is not used on an ELB, use the IAM tools as mentioned in other answers. If it is, then you shouldn't delete it from IAM, but instead should set the new, correct one for the ELB then delete the unused certificate(s) using the IAM tools. I would also recommend waiting a few minutes after you change the certificate before you delete the old one, as it can take a little time for the correct certificate to propagate; simply do a dig on the ELB DNS name and hit each IP address to make sure it is returning the new certificate to be sure.

Also, the latest version of the AWS Console does support updating the certificate on an existing load balancer, but you still have to use the IAM tools to delete unneeded certificates.

As far as I can tell (at least with Boto3)

  • you can add a new certificate to the listener, but not as the default certificate (the isDefault attribute is rejected)
  • you cannot delete the existing "default" certificate while it is the default
  • you cannot modify which certificate is the default
  • an SSL listener may not have no certificates (you can't delete all the certificates and add a new default one).

Therefore, the only option left is either to delete the loadbalancer or delete the listener (what the hey!). Because the listener may be attached to a lot of routing information, this is a PITA. So, what I recommend is:

  • upload the certificate
  • retrieve the state of the listeners referencing the old SSL
  • make a note of their rules
  • delete those listeners
  • recreate them with just their CertificateArn changed (an pointing to your new certificate.

Something like this:

   import boto3

   def fixRule(rule): 
            """Copy a rule so that it can be submitted as a new rule"""
            rule = rule.copy()
            if rule["IsDefault"]:
                # The default rule is set at create_listener
                return None

            def fix_condition(c):
                c = c.copy()
                del c["Values"]
                return c
            rule["Conditions"] = [fix_condition(c) for c in rule.get("Conditions",())]
            # del rule["Priority"]
            del rule["RuleArn"]
            del rule["IsDefault"]
            # rule["Priority"] = rule["Priority"]
            try:
                rule["Priority"] = int(rule["Priority"])
            except:
                del rule["Priority"]
            return rule


   acmClient = session.client('acm')
   response = acmClient.import_certificate(
                Certificate=certificate,
                PrivateKey=privatekey,
                CertificateChain=chain
            )
   current_ssl_arn = response[ 'CertificateArn']

   session.client('resourcegroupstaggingapi').tag_resources(
                ResourceARNList=[
                    current_ssl_arn
                ],
                Tags={ ... whaterver }
                }
            )

   # Replace each SSL listener with one that has a new certificate.
   lbClient = session.client('elbv2')
   listeners = lbClient.describe_listeners(LoadBalancerArn=self.lb_arn["Listeners"]


   # Make existing listeners use the certificate
   # Delete exisiting listeners with SSL certificates
   # Create a new one with the same parameters and rules as the old one.
   for l in listeners:
            oldListenerArn = l["ListenerArn"]

            # Only deal with SSL listeners
            if l.get("SslPolicy")==None: continue

            _listener_certs = l.get("Certificates",())
            _listener_cert_arns = set(c['CertificateArn'] for c in _listener_certs)

            # Great! already up-to-date
            if current_ssl_arn in _listener_cert_arns: continue


            # Backup the rules
            oldRules = lbClient.describe_rules(ListenerArn=oldListenerArn)['Rules']

            # Recreate the listener with the new certificate
            print("Replacing listener")
            _ = lbClient.delete_listener(ListenerArn = oldListenerArn)

            l = l.copy()
            del l["ListenerArn"]
            l["Certificates"] = [{"CertificateArn":current_ssl_arn}]
            newListener = lbClient.create_listener(**l)["Listeners"][0]
            newListenerArn = newListener["ListenerArn"]

            print("Replacing listener .. copying ({}) rules ".format(len(oldRules)))
            for rule in oldRules:
                rule = fixRule(rule)
                if rule is None: continue
                _ = lbClient.create_rule(
                    ListenerArn=newListenerArn,
                    **rule)
            print("Replacing listener .. OK")

Its not ideal, since if anything goes wrong then there's downtime. Though I think this is the best with the tools Amazon provided.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top