Google App Engine SSL with Let's Encrypt "could not be inserted" - google-app-engine

When trying to "Add a new SSL certificate" using App Engine's Settings tab that was generated with Let's Encrypt via Google App Engine's console results in a dialog error and a 400 response to the POST request.
Error
"The SSL certificate provided could not be inserted."
A previously generated (about 2 months ago - not yet expired of course) SSL key/certificate via the exact same method is inserted just fine - but any newly generated one does not. I attempted both traditional Let's Encrypt and the relatively new Certbot method. Also tried multiple subdomains, naked domains, singular domains and each results in the same error.
I've seen several people spec that --rsa-key-size 2048 solved the same issue, but I've tried specifying that as well (even though it is the default for Certbot as is). Other answers have been "waiting 2 hours and now its working" - looking for a real solution as unreliable inserts and expired certs can become a real pain.

If you use certbot in Apache it defaults to 4096. So force key length to 2048.
certbot-auto --rsa-key-size 2048
From docs [https://certbot.eff.org/docs/using.html]
This creates PEM certificates in /etc/letsencrypt/live/example.net
Convert to RSA (change the url in cmd to your site).
sudo openssl rsa -inform pem -in /etc/letsencrypt/live/example.net/privkey.pem -outform pem > rsaprivatekey.pem
Above command is from this blog post http://blog.seafuj.com/lets-encrypt-on-google-app-engine. This also explains how to setup your webapp2 webserver.
Go to App Engine > Settings > SSL Certificates
Upload fullchain.pem
Upload rsaprivatekey.pem
The file upload button works fine - no need to paste unless its more secure.

I ran into similar problems as well a few weeks ago when trying to upload my new certificate using the same recipe I successfully used before.
What worked for me in the end was:
copy-pasting the entire content of the certificate file into the box marked Or paste the public key certificate in the box below:
and,
copy-pasting just the full key at the end of my private key .pem file into the box marked Or paste the RSA private key in the box below: (though I don't exactly recall if I included the leading -----BEGIN RSA PRIVATE KEY----- and tailing -----END RSA PRIVATE KEY----- lines or not).
I (kinda blindly) made several attempts for each of the 2 copy-paste operations with whatever crossed my mind - the success/failure feedback is immediate.
Side note - you may want to also double-check your certificate, in my case the 1st certificate file I managed to upload successfully was an incomplete one (missing intermediate entities), which appeared to be working fine from my desktop, but was failing when browsing from Android, I had to re-generate another one. I used digicert to confirm the problem and verify the 2nd certificate (following suggestions from an SO answer, of course ;)

I had this problem. I had generated the certificates in the Google Cloud Shell.
I was first trying to use the fullchain.pem, but this did not work.
/etc/letsencrypt/live/mydomain.com/cert.pem
I issued
sudo less /etc/letsencrypt/live/whysaurus.com/cert.pem
in the google cloud shell, and uploaded that as the pem 509 cert in appengine, and then it was accepted.

Related

Generating GCP compatible Cloudflare SSL certificate

I'm trying to configure SSL for Google Cloud's App Engine.
You can upload your own custom SSL certificate + private key in GCP (see screenshot).
I'm using Cloudflare for DNS, and would like to use the "Full (strict)" SSL policy in Cloudflare. This would mean I have to add a certificate and key, created by Cloudflare, in GCP (in same screenshot).
I've managed to convert the private key to a valid (PEM) format that GCP will accept. The only thing not working is the Certificate part.
When entering both certificate and key in GCP, upon clicking upload, the following error is returned:
The certificate data is invalid. Please ensure that the private key and public certificate match.
After some googling, I found the following resources on GCP's documentation, explaining I need a have the full certificate-chain uploaded in the certificate field. So next thing I tried, is to concat my certificate from cloudflare together with the root certificate of cloudflare itself, as explained in the GCP docs.
So I ran the following command to create this chain:
cat domain.crt cloudflare-root-ca.crt > concat.crt
... and uploaded that one in GCP in the certificate field.
That didn't work either, even while the checksums of both private key and the certificate-chain match as explained by GCP docs, by running:
openssl x509 -noout -modulus -in concat.crt | openssl md5
openssl rsa -noout -modulus -in myserver.key.pem | openssl md5
...and comparing the md5 outputs.
So now I'm completely without Idea's. GCP's error messages are limited to the one above, and one other saying your PK is not a valid format.
Same problems when trying via CLI (gcloud)
When trying this process through the cli gcloud, we get the same errors.
Trying the following command:
gcloud app ssl-certificates create --display-name example.com --certificate ./cloudflare-concat.crt --private-key cloudflare-pk.key
...yields the following error:
ERROR: (gcloud.app.ssl-certificates.create)
INVALID_ARGUMENT: Invalid certificate.
`CertificateRawData` must contain a PEM encoded x.509 public key certificate, with header and footer included,
and an unencrypted PEM encoded RSA private key, with header and footer included and with size at most 2048 bits.
The requested private key and public certificate must match.
Any help on uploading a valid certificate (from Cloudflare) and private key in GCP is much appreciated.
Update 1
I found this (cached) paged describing all the root and intermediate certs of Cloudflare. I've tried a couple of them to concatenate agains my domain cert, but no luck so far. It's also not clear which one to use...
Update 2
I've beginning to think that this won't work, ever. Because I'm using an 'Origin Certificate' from Cloudflare, I believe this is a self-signed cert from Cloudflare itself, meaning that App Engine won't ever recognize this as valid.
The reason I think this is the case, is because I tried to use the cfssl tool from cloudflare to 'create a bundle-cert' automatically. The response I get from running
cfssl bundle -cert domain.crt
Returns the following result:
[INFO] bundling certificate for {Country:[] Organization:[CloudFlare, Inc.] OrganizationalUnit:[CloudFlare Origin CA] Locality:[] Province:[] StreetAddress:[] PostalCode:[] SerialNumber: CommonName:CloudFlare Origin Certificate Names:[{Type:2.5.4.10 Value:CloudFlare, Inc.} {Type:2.5.4.11 Value:CloudFlare Origin CA} {Type:2.5.4.3 Value:CloudFlare Origin Certificate}] ExtraNames:[]}
{"code":1220,"message":"x509: certificate signed by unknown authority"}
Extra info
I'm using a free Cloudflare subscription.
Everything works fine when using the 'flexible' setting from Cloudflare,
But I would like to use the 'full (strict)' setting
I discovered a recent blogpost, describing how to solve this.
After following the steps described, the certificate was accepted in Google Cloud, and everything worked for the 'full (strict) ssl' option in cloudflare!
In short: it involved a bit of tweaking the keys, by manually adding 'RSA' to it, as described in the blogpost.
See this link:
https://blog.woohoosvcs.com/2019/11/running-google-app-engine-behind-cloudflare/
EDIT:
This is probably the same end-result as using the shell commands as described by #Andrei
Can you please verify you are using free Cloudflare or paid Cloudflare account.
Because if you are free using than I think SSL strict is not going to work make it flexible and redirect all HTTP request to https request.

Google Cloud Platform renewed SSL cert stops app from serving

Our GAE app has been serving from a custom domain for a year, using a GoDaddy SSL certificate that we uploaded a year ago. A few days ago they sent me an email saying we needed to renew it, so I did, and then I received an email on how to download it. They offered various server type choices, and since none were GAE, I chose "Other".
Next I tried to follow the instructions at https://cloud.google.com/appengine/docs/python/console/using-custom-domains-and-ssl#obtaining_a_certificate, the section "Obtaining a Certificate". (I started with https://www.digicert.com/ssl-certificate-installation-google-app-engine.htm, but that seemed useless to me because I have a Mac, not a PC).
The instructions under "Obtaining a Certificate" don't explicitly describe renewal. I was pretty sure I shouldn't create a new CSR, since I have to assume the renewal cert used my old CSR given that GoDaddy didn't ask for a new CSR. But I had saved the files from a year ago when I obtained the original cert.
So jumping to step 5, I proceeded as follows:
I unzipped the renewal certificate ZIP file I had obtained from GoDaddy.
I had already done step 6 a year ago and still had that file, so I skipped step 6.
I concatenated the CRT files from the renewal cert that had been inside the ZIP file.
I went to the "SSL" link in step 7. On that page:
I used the "Upload a new certificate" link, sending the two required files.
I tried pointing my browser to the domain, and it returned a warning page that that page was unsafe because the certificate was out of date.
So I deleted the old certificate.
Again I tried going to my domain, and now I'm getting a page that says "This webpage is not available." Presumably all the users of my app are getting that as well. :0(
I also used the "To verify that the private key and certificate match..." steps under "Obtaining a Certificate" and the two hex values matched.
I've tried a variety of online searches without finding anything that addresses my issue. I'm sorry if it's out there, but I couldn't find it. Anyone know how I can get my app serving again?
The solution was given in step 6 of a different section on the same page of my first link. After I had done everything else I described above, I still needed to do the following:
Click the name of the new certificate, which takes you to a new page.
Click the name of the domain.
Click Save.
None of this info appears on the SSL page, and the name you assigned to the uploaded certificate doesn't look like a link, but it is.

Specify CA chain in AppEngine

I am using a SSL certificate for my custom domain. This certificate needs five intermediate authorities to get to the root CA, and without them some browsers (pronounce: Chrome) will work, but others (Firefox, Android browsers) will fail.
Is there any way to specify more than two CAs in the PEM file? AppEngine complains when I try to put the whole certification chain (as documented, it accepts only two CAs in the PEM file). Is it my only option to drop my current certificate and go with Verisign?
Just to answer my own question, there is no way to do this at the present time. Switch to a CA that uses a single intermediate authority (DigiCert combines this with a superb technical support) and move on.
UPDATE: Starting today, GAE is supporting a chain of up to five CA authorities.

Encrypting connection strings in app.config for WinForms app

I'm using common database code between a web and WinForms app. I've researched and worked out how to encrypt the connection strings section of a web.config and app.config file. That part is ok. I have also worked out how to decrypt the connection strings in my Azure web app, that's ok. I can also read the connection strings in my WinForms app after loading the .pfx file into the machine's certificate store, but after I reboot it fails, because it can't find a private key in the pfx file.
I am using a certificate created with these commands:
makecert -r -pe -n "CN=myconfig" -sky exchange "myconfig.cer" -sv "myconfig.pvk"
pvk2pfx -pvk "myconfig.pvk" -spc "myconfig.cer" -pfx "myconfig.pfx" -pi
This gives me 3 files: myconfig.pvk, myconfig.cer, myconfig.pfx
I assume the problem is the private key isn't stored in the pfx file, and needs to be re-authenticated each time after a reboot- but I don't know enough about encryption to know how to do that. Further, the WinForms app is for very limited distribution onto controlled machines, so I'd like to install each certificate manually.
I'm an newbie to encryption and am stuck. Can I load a .pfx file onto a machine, enter the private key (which I know but won't tell the user) & have that stored persistently? Am I missing something- is there a different certificate file I should install, or way of generating it? I don't want to leave the private key accessible. If someone steals the app.config, I don't want them to be able to decrypt it.
Note: I have read about the RsaProtectedConfigurationProvider and DPAPIProtectedConfigurationProvider. I have chosen to use PKCS12ProtectedConfigurationProvider because it works with Azure, ref: http://blogs.msdn.com/b/sqlazure/archive/2010/09/07/10058942.aspx
I stumbled on the answer when I deployed the app to my local IIS & got the error "Failed to decrypt using provider 'CustomProvider'. Error message from the provider: Keyset does not exist"
There was a permissions problem with the private key, resolved with the help of this article:
CryptographicException 'Keyset does not exist', but only through WCF
The article includes a number of possible causes, the one which fixed my issue was fixing the permissions in 'Manage Private Keys' from the MMC Certificates snap-in (see link, the steps are well laid out).

The SSL certificate provided could not be inserted

I use google app engine trying to add ssl for custom domain. I use naked domain. After "PEM encoded X.509 public key certificate" and "Unencrypted PEM encoded RSA private key" uploaded. "The SSL certificate provided could not be inserted." is returned. I use https://www.sslchecker.com check private key/ssl match. It matches. What's wrong? I use key size "RSA 2048", nothing wrong ordering the concatenated certificates. Thank you.
I spent a long time working with this error and found a solution for my problem here:
http://qiita.com/yogurito/items/550b50b262418e93da22
If I understand correctly, the key file needed to be without a password, so running:
openssl rsa -in appengine.key -out appengine-nopass.key
provided a key that GAE liked.

Resources