ebekker / ACMESharp

An ACME client library and PowerShell client for the .NET platform (Let's Encrypt)
https://pkisharp.github.io/ACMESharp-docs/
1.21k stars 185 forks source link

AWS CloudFront certificates #36

Open amlynnworth opened 8 years ago

amlynnworth commented 8 years ago

My use case is trying to make a letsencrypt closed-beta cert for use on Amazon CloudFront, without involving Elastic Beanstalk. I'm running the POSH files on Windows 10. Here are some questions and feedback on the process.

  1. Is there a way to obtain the "cert chain" for use with AWS, such that the result is publicly trusted? Probably this is a feature request for Get-ACMECertificate, to have a way to write out the cert chain file, in case someone wants to use AWS command line interface "CLI" directly. What I did was to use Notepad to combine the isrgrootx1.pem and letsencryptauthorityx1.pem (downloaded from letsencrypt.org) into a "chain" file, and included that file in the upload to AWS CloudFront (using AWS CLI). All that was accepted by CloudFront and -- retesting a few minutes ago -- the end result seems 100% okay (this is a big improvement compared to testing last week).
  2. The reason I used AWS CLI is that I got stuck on the very last steps of the example syntax for the AWS certs. In particular,

Install-ACMECertificateToAWS

gave me this yesterday:

Get-ACMECertificate : The file 'C:(snip)\tmp4F87.tmp' already exists. At (snip)letsencrypt-win\letsencrypt-win\LetsEncrypt.ACME.POSH\ACMEPowerShell-AWS\ACMEPowerShell-AWS.psm1:73 char:2

SerialNumber : 009813F47513E5750B43E7431E971E44BD Thumbprint : 3EAE91937EC85D74483FF4B77B07B43E2AF36BF4 Signature : 3EAE91937EC85D74483FF4B77B07B43E2AF36BF4 SignatureAlgorithm : sha256RSA CrtPemFile : ca-009813F47513E5750B43E7431E971E44BD-crt.pem CrtDerFile : ca-009813F47513E5750B43E7431E971E44BD-crt.der

Publish-IAMServerCertificate : A parameter cannot be found that matches parameter name 'Credentials'. At (snip)\letsencrypt-win\letsencrypt-win\LetsEncrypt.ACME.POSH\ACMEPowerShell-AWS\ACMEPowerShell-AWS.psm1:140 char:57

Complete-ACMEChallenge

it turns out that I have to adjust properties on the /.well-known/ acme challenge file with a public ACL, and then continue with the next step, Submit-ACMEChallenge. I find that both parent "folders" are public but the challenge file itself is not public.

I hope all this info helps! I am fairly new to github so please tell me if I should be sending this type of info through another channel.

ebekker commented 8 years ago

So, let me address (1) first -- you can use Get-ACMECertificate to gain access to the issued certificate for your domain, and Get-ACMEIssuerCertificate to get the immediate signer (CA) certificate. In the case of LE, for BETA/PROD, they use one intermediate cert (e.g. "Let's Encrypt Authority X1") to directly sign our requested certificates. That cert is in turn signed by a trusted root CA (e.g. "DST Root CA X3" which I believe is the CA that is owned by Identrust. Use the -ExportCertificatePEM or -ExportCerticitedDER switches to to the cmdlets above to get the certificates in the format you desire.

For the LE STAGE environment, they simply use a top-level fake CA of their own to sign your cert, so the issuer and trusted CA are the same.

Now, when you install a certificate chain to a web server for serving up to a client, you should install it with your certificate first, then the immediate signer of your cert, followed by its signer, and so on until you get to the root CA. _Technically_, you should not install the root CA certificate because that is the one that should already be in the client's trusted root store, but most servers allow you to, and most clients will accept it and simply ignore it.

ebekker commented 8 years ago

Regarding the second issue, I'll need to rerun the test for that scenario -- there have been lots of changes in the underlying library and PS module so I could have broken something.

amlynnworth commented 8 years ago

Thank you. I missed that detail about skipping the root in the chain.
That makes sense and rechecking the aws docs, they do say not to include the root cert.

On November 27, 2015 10:42:01 PM Eugene Bekker notifications@github.com wrote:

So, let me address (1) first -- you can use Get-ACMECertificate to gain access to the issued certificate for your domain, and Get-ACMEIssuerCertificate to get the immediate signer (CA) certificate.
In the case of LE, for BETA/PROD, they use one intermediate cert (e.g. "Let's Encrypt Authority X1") to directly sign our requested certificates.
That cert is in turn signed by a trusted root CA (e.g. "DST Root CA X3" which I believe is the CA that is owned by Identrust. Use the -ExportCertificatePEM or -ExportCerticitedDER switches to to the cmdlets above to get the certificates in the format you desire.

For the LE STAGE environment, they simply use a top-level fake CA of their own to sign your cert, so the issuer and trusted CA are the same.

Now, when you install a certificate chain to a web server for serving up to a client, you should install it with your certificate first, then the immediate signer of your cert, followed by its signer, and so on until you get to the root CA. _Technically_, you should not install the root CA certificate because that is the one that should already be in the client's trusted root store, but most servers allow you to, and most clients will accept it and simply ignore it.


Reply to this email directly or view it on GitHub: https://github.com/ebekker/ACMESharp/issues/36#issuecomment-160121401

amlynnworth commented 8 years ago

As I (re)read these docs today on Amazon, they indicate that the root certificate SHOULD be included in the cert chain:

http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_server-certs_manage.html#UploadSignedCert

If you have been able to get a cert to work on Amazon (CloudFront), I would be very interested in the exact contents of your cert chain file. I am finding that many people have errors reported in their browser for my attempt. I tried again today with the most recent ACMESharp files.

For discussion, here is an example URL on one of my CloudFront subdomains: https://img.href.com/img256/photo_redwood.jpg

ebekker commented 8 years ago

Their doc is a bit confusing. In one part they say to include the root CA and in another they have this bullet:

''' Although the root certificate is optional, you can include it so that you can run full chain of trust verifications, such as SSL Checker. '''

The truth is it shouldn't be required as it should already be in the trusted root store but of course LE is a new CA and it may not be yet. But they cross signed it with another well known CA so you may need to include their root because of this caveat.

amlynnworth commented 8 years ago

@ebekker Do you have an AWS example working, yourself? Could you share your cert chain file? I think it would have to be the same for everyone because it's intermediate + optional root. I started out using the combination, had trouble, went to using just the intermediate, still having trouble (some users, some browsers, and not simply based on browser version). I obtained my intermediate and root pem files directly from the LE web site.
Right now I am wondering whether for AWS CloudFront the cross-signing root needs to be included, in addition to, or instead of, the LE root. Could this be something that needs to be escalated to the attention of Amazon, where their http server should "provide" the root(s) certs when handshaking with browsers? The same browsers work with the LE signed certs when the content comes from IIS, but not when the content comes from AWS CloudFront.

amlynnworth commented 8 years ago

Going back to https://letsencrypt.org/certificates/, I see that for Let’s Encrypt Authority X1 there are 2 PEM files available.

  1. IdenTrust cross-signed
  2. Signed by ISRG Root X1.
    Which of those do you use in the cert chain file you upload to Amazon? I was using (2). Now trying (1). Seems obvious in retrospect!
lennybacon commented 8 years ago

Try this one. It contains:

With these 4 certificates you have all you need.\

chain.txt

lennybacon commented 8 years ago

I just had a look at some of the issued certificates (https://crt.sh/?Identity=%25&iCAID=7395). Seems like the DST is the only relevant chain.

untitled

amlynnworth commented 8 years ago

@lennybacon Thank you. I ended up using just the cross-signed PEM ( https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem ) (as you say, with DST Root CA X3 at the top) and that works. Hooray.

ghost commented 8 years ago

Hello, I've the same problem, but my certificate doesn't work!

fullchain.txt

I tried to copy the certificates as descripted above, but all I get is: The index within the chain of the invalid certificate is: 2

Does somebody has an Idea?

JulesWebb commented 8 years ago

\ UPDATE 03-07-2016 ** Though I was successful in uploading the cert to AWS, the cert is NOT valid. If I find a way to successfully upload a cert and it's valid I'll add another update. If anyone else has some feedback I'd love to hear it.


The solution I found was to create a self-signed certificate using OpenSSL. cite: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/ssl-server-cert.html

Since everyone uses different tools it's very hard to deliver a "This is how you do it" answer. But here's what worked for me.

To be clear these are the steps I took AFTER I successfully went through all the instructions and exported certs from https://github.com/ebekker/ACMESharp/wiki/Quick-Start

Tools I'm using

SET WHICH IAM PROFILE USER CREDENTIALS WILL BE USING C:\Windows\system32>set AWS_DEFAULT_PROFILE=myusername

CHECK WHICH USER PROFILE IS BEING USED C:\Windows\system32>aws configure list

CHANGE DIRECTORY INTO OPENSSL FOLDER C:\Windows\system32>cd C:\openssl-0.9.8k_X64

SET PATH TO OPENSSL INSTALLATION/FOLDER C:\openssl-0.9.8k_X64>set OpenSSL_HOME=C:\openssl-0.9.8k_X64

POINT TO CNF FILE > MAKE SURE FILE PATH IS CORRECT C:\openssl-0.9.8k_X64>set OpenSSL_CONF=C:\openssl-0.9.8k_X64\openssl.cnf

SET PATH C:\openssl-0.9.8k_X64>set Path=%Path%;%OpenSSL_HOME%\

#######################

NOTE: AWS did not accept mayalias_cert.crt Needed to create a self-signed certificate, using cmd below. It also game me an RSA PRIVATE KEY that didn't flag any "mismatch" errors CITE: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/ssl-server-cert.html

C:\openssl-0.9.8k_X64>openssl x509 -req -days 365 -in mayalias_cert.csr.pem -signkey mayalias_private-key.pem -out mayalias_chain.pem

#######################

CREATE LOCAL CSR NOTE: myalias_private-key.pem is the RSA PRIVATE KEY that was created from the cmd above C:\openssl-0.9.8k_X64>openssl req -new -key myalias_private-key.pem -out myalias_csr-from-private-key.pem

BELOW IS WHAT WILL PRESENT AND THE QUESTIONS THAT WILL BE ASKED

Loading 'screen' into random state - done
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:**ENTER YOUR STATE**
Locality Name (eg, city) []:**ENTER YOUR CITY**
Organization Name (eg, company) [Internet Widgits Pty Ltd]: **I LEFT BLANK**
Organizational Unit Name (eg, section) []: **I LEFT BLANK**
Common Name (eg, YOUR name) []:**I ENTERED MY DOMAIN NAME**
Email Address []:**ENTER CONTACT EMAIL ADDRESS**

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:**ENTER YOUR PASSWORD**
An optional company name []:**ENTER YOUR COMAPNY NAME**

FINAL CMD TO UPLOAD CERT TO AWS C:\openssl-0.9.8k_X64>aws iam upload-server-certificate --server-certificate-name mayaliasServerCertName --certificate-body file://mayalias_chain.pem --private-key file://mayalias_private-key.pem --certificate-chain file://mayalias_chain.pem --path /cloudfront/myfoldername/

NOTE: YOU MUST INCLUDE TRAILING SLASH AFTER myfoldername/ ABOVE

BELOW ARE THE RESULTES.

{
    "ServerCertificateMetadata": {
         "ServerCertificateId": "MYCERTID",
         "ServerCertificateName": "mayaliasServerCertName",
         "Expiration": "2017-03-05T21:50:49Z",
         "Path": "/cloudfront/myfoldername/",
         "Arn": "arn:aws:iam::##########:server-certificate/cloudfront/myfoldername/mayaliasServerCertName",
         "UploadDate": "2016-03-06T20:27:05.560Z"
 }
}

VERIFY aws iam get-server-certificate --server-certificate-name mayaliasServerCertName

#################

When I was done I logged into my AWS account and verified that the cert was there.

Cheers! jules

brianherman commented 7 years ago

https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt This is the current cross sign certificate.

devinbost commented 6 years ago

What in the world am I supposed to do with that "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt" file? I'm trying to solve this same problem... My SSL certificate is using "Fake LE Intermediate X1" and I'm not sure how to change it... except I'm using a manual handler with dns-01 challenge.

ebekker commented 6 years ago

@devinbost -- are you going against Let's Encrypt PROD or STAGING?

devinbost commented 6 years ago

After feeling like I was going to lose my mind for hours, I finally discovered that the defaults for the latest version of ACMESharp set to staging.... and after running probably 100 Google searches, I finally discovered how to actually change the environment with the line: Initialize-ACMEVault -BaseURI https://acme-v01.api.letsencrypt.org/ Why this isn't hardly documented anywhere and why the default settings are basically non-functional are quite astonishing and very disappointing. I don't think I've felt so frustrated in at least two years...

devinbost commented 6 years ago

If a breaking change needs to be pushed to a library that people are using to support their websites on, the professional thing to do is at least ensure that the breaking change is adequately documented so that people don't end up getting their website into a state with the red screen of SSL death only to discover that it's because a breaking change was pushed out but wasn't at all documented, leaving users with no idea how to obtain a functional SSL state aside from restoring backup certificates...

ebekker commented 6 years ago

Actually, the default is pointing to PROD.

There is a switch -BaseService that allows you to set to one of 2 predefined endpoints, either LetsEncrypt or LetsEncrypt-STAGING. The default for this parameter is the former, so it will point to PROD if you do not specify anyting.

The -BaseURI setting that you're referring to is only used if you want to point to an ACME CA server other than one of these two predefined ones.

Now, you're saying that you initially started with initializing a Vault without specifying either of these and you Vault was pointing to STAGING?

devinbostIL commented 6 years ago

I didn't even know how to point anything to staging because I definitely couldn't find any documentation on that. If this is a bug, it's a pretty serious issue. If I had known I was going to waste so much time on this, I would have just paid $200 for an SSL certificate....

ebekker commented 6 years ago

Sorry to waste so much of your time, our goal here at ACMESharp, Inc. is complete customer satisfaction, I will issue you a full refund for everything you paid for ACMESharp.

devinbostIL commented 6 years ago

Haha I was waiting for something like that. Well, consider ACMESharp forgiven.

But seriously, a bug like that is capable of killing momentum in a growing project.

ebekker commented 6 years ago

What version of ACMESharp are you using?

devinbostIL commented 6 years ago

It was latest version pulled from powershell. I can get you more detailed information after I get some sleep.

ebekker commented 6 years ago

So if you do Get-Module ACMESharp you're seeing version 0.9.1.x, correct?

devinbostIL commented 6 years ago

I think so, if I remember correctly.

devinbost commented 6 years ago

Yes, I get: Binary 0.9.1.326 ACMESharp from running that command.

Also, I'm sure that I ran Initialize-ACMEVault with default settings when I got the problem because I had actually renamed the directory, C:\ProgramData\ACMESharp\ to C:\ProgramData\ACMESharp-old\ to ensure that the directory would be rebuilt because I upgraded from I think version 0.8.x something and was getting bugs that I suspected were from using old data with the newer version of the library. (It was after I renamed that directory and re-initialied the ACMEVault that I experienced the staging issue.)

BTW, I apologize for venting my frustration earlier. The library is quite impressive overall and is a great project and has done a lot of good and has opened doors for many people. Obviously, it can be hard to anticipate an unexpected bug, and if nobody else has reported it, then you wouldn't even know about the problem. However, I suspect that I'm not the only one who ran into this issue because Sebastiaan Janssen from Umbraco posted:

"Next up: pointing to the public beta server that will give you a real, trusted certificate. At first the URL I had here was still pointing at the staging server which gives you cerificates issued by "happy hacker fake CA". Needless to say: I can't use those in production."

on his blog about ACMESharp (https://cultiv.nl/blog/lets-encrypt-on-windows/) back in December of 2015. I just think it's bizarre that I didn't run into this issue when I previously ran ACMESharp back before I ran the update that upgraded my version to 0.9.1.326.

ebekker commented 6 years ago

All is forgiven.

So back in 2015, that may have been the case, but since then there have been numerous changes at LE as well as ACMESharp. I ran through the default use cases a few times, and at least for me, when running Initiailize-ACMEVault without giving it any additional parameters, it always initialized pointing to LE PROD.

In the actual Vault directory path, there is a file 00-VAULT that stores the structural content and detail of the vault. It's a JSON file, and near the top (usually) you'll find a couple properties which should have the following values:

I wonder if you would be willing to give it a try once more and see what your results are?

You don't have to blow away or overwrite your existing vault directory if you already have stuff in there. You can just create a new Vault Profile and point it to some temporary folder and use that instead. If you want to do that, here is how you would go about doing that:

PS> $vaultTestPath = 'c:\temp\TestVault1' ## Adjust this as necessary
PS> Set-ACMEVaultProfile -ProfileName test1 -Provider local -VaultParameters @{ RootPath = $vaultTestPath ; CreatePath = $true }
PS> Initialize-ACMEVault -VaultProfile test1
PS> cat "$vaultTestPath\00-VAULT" | ? { $_ -like '*base*' }