synfinatic / aws-sso-cli

A powerful tool for using AWS Identity Center for the CLI and web console.
https://synfinatic.github.io/aws-sso-cli/
GNU General Public License v3.0
477 stars 59 forks source link

Let's Encrypt for ECS Server #956

Open synfinatic opened 4 months ago

synfinatic commented 4 months ago

Overview

Asking users to create/manage their own CA/SSL certificates for the ecs server running on localhost really sucks. Right now users can't use self-signed certs or certs signed by an internal-CA, but must use a public trusted CA by the AWS SDK. This will become more painful, as Google/etc are pushing for even shorter certificate lifetimes.

What I would like to do is be able to help users to get valid certificates signed by Let's Encrypt for a custom FQDN which points at 127.0.0.1/localhost in a secure manner. This way, a user would point at custom-host.aws-sso-cli.org or something like that and only they would be able to get a signed cert for that FQDN.

Since the private key would never leave the aws-sso SecureStore, there is no risk (more on that later) of MITM attacks due to DNS poisoning.

Solution

  1. User would create an account on aws-sso-cli.org and choose a unique hostname.
  2. User would be issued an API Key by the service.
  3. User would run aws-sso ecs ssl configure --api-key $API_KEY --hostname $UNIQUE_HOSTNAME
  4. User would run something like aws-sso ecs ssl renew -- would generate a new private key, CSR and upload it to the aws-sso-cli.org service.
  5. aws-sso-cli.org service would validate the API key and the CSR match a valid account
  6. aws-sso-cli.org would make a request to Let's Encrypt to sign the CSR based on control of DNS (linode, Cloudflare, etc)
  7. Signed certificate would be returned to the aws-sso client and stored in the SecureStore for future use.

Benefits

  1. Everything is easier from a user perspective
    1. Users don't need to own a domain that is hosted in a CSP
    2. Users don't need to create Let's Encrypt account
    3. Users don't need to figure out how to get ACME to work with their CSP/API/credentials.
  2. Secure enough? It's not perfect though. Some people will balk.
  3. Don't need to wait for AWS to do anything

Challenges

  1. Only DNS-01 is possible from an ACME perspective.
  2. DNS-01 is the slowest/most fragile form of proof of ownership
  3. DNS-01 authentication does not support IP addresses.

Risks

  1. This web service is granted a great deal of trust, being an intermediary between Let's Encrypt and the ultimate customer. This makes it a security target by nation state actors/etc. A compromise would allow anyone to issue signed certificates for any customer to enable MITM attack. Basically, a web service like this is indistinguishable from a CA which seems... bad?
  2. Users have to assume I don't MITM requests/backdoor the code. To be fair, MITM requests would be obvious/public and the code is open source, but stranger things have happened?
  3. DDoS attacks of the web service would prevent users from renewing certificates and unable to run the ECS server locally.
  4. https://letsencrypt.org/docs/certificates-for-localhost/ -- Is not relevant, because the issue they have with https://localhost.example.com is that they assume the app ships with the private key and can be extracted so someone else can generate a valid SSL cert and perform a MITM attack.
  5. Another DoS risk: Let's Encrypt notices that the IP address points to 127.0.0.1 and will not renew the cert or adds it to the CRL.

Other Options

  1. Require/let each user deploy their own LE CA gateway/web service and point it to their own domain/LE account. This is obviously a lot more work and will not work for many.
  2. Skip the middleman, and embed the ACME part directly into the aws-sso client. User will need to create their own LE account, own their own domain, etc. Less work for people, but still assumes a lot of users.
  3. Provide directions or even some kind of feature which modifies the AWS SDK CA bundle and inserts the aws-sso CA.
  4. Do nothing and wait for AWS to fix their bug.

Conclusion

Letting users manually manage their SSL key/certificate lets savvy users who are very concerned with their security to deploy and manage this with strong security. But I suspect most users will not be able to easily get a signed cert by a trusted CA easily and will need something else.

It might be semi-possible to figure out how to manually add a custom CA to the botocore/cacert.pem file, but the location of this is highly dependent on a lot of variables. Not sure if there is an easy/programatic way to ask python to tell us. The downside of this is that every time the user updates their aws-cli package, we will need to re-add the CA.

Probably best to wait a bit and see what AWS does with my bug report and see if they take it seriously?

synfinatic commented 4 months ago

Updating the existing cacert.pem

I'm guessing the two primary AWS SDK's people use aws-sso is Boto3 and Go. What is interesting is they handle the CA bundle very differently.

The key thing here is that these files may or may not be under the control of the user. Users may find their company's endpoint software manages these files (inserting a corporate CA for MITM/etc) or whatever. So while it might be acceptable to document this for users, actually making it easy for them seems like a bad idea since the requirements will be all over the map

synfinatic commented 4 months ago

Looks like someone already built this, but it is EOL: https://github.com/mdbraber/acmeproxy

There are a few forks with some changes which implement some fixes it seems? One of them may work already? Seems like if I were to build my own, it should be based on https://github.com/mholt/acmez