Search code examples
google-app-enginesslgoogle-cloud-platformopensslcloudflare

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

Solution

  • 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