SAML-Toolkits / php-saml

Simple SAML toolkit for PHP
MIT License
1.24k stars 471 forks source link

Use let's encrypt certificates in Docker-setups #574

Open PentaPaetzold opened 10 months ago

PentaPaetzold commented 10 months ago

I am using a project using php-saml (https://www.kimai.org/) in docker which authenticates to authentik (https://goauthentik.io) via SAML. All works fine, when i manually set x509cert to the value of our authentik certificate which is generated by lets encrpyt. If i omit the x509cert- Value, the request fails and won't authenticate. Also if i set the wrong value there.

As let's encrypt certificates are often changing, i need to manually convert the certificates value in some x509cert- string and replace the value every view weeks plus refreshing the application cache, which is annoying. The certificate- folder of letsencrypt is containing the pem- files and crt and key- files like authentik.domain.tld.key But when i set /etc/ssl/certs of kimai to those files, only an error is thrown from saml-php.

The folder /etc/ssl in kimai looks like

c5f1961d9c51:/etc/ssl# ls -l
total 52
lrwxrwxrwx  1 root root    25 Nov 30 09:32 cert.pem -> certs/ca-certificates.crt
drwxr-xr-x 11 1000 1000  4096 Jan 23 14:39 certs
-rw-r--r--  1 root root   412 Nov 11 00:00 ct_log_list.cnf
-rw-r--r--  1 root root   412 Nov 11 00:00 ct_log_list.cnf.dist
drwxr-xr-x  2 root root  4096 Nov 30 09:32 misc
-rw-r--r--  1 root root 12324 Nov 11 00:00 openssl.cnf
-rw-r--r--  1 root root 12324 Nov 11 00:00 openssl.cnf.dist
drwxr-xr-x  2 root root  4096 Nov 30 09:32 private

whereas cert.pem won't resolve to let's encrypts files, as ca-ertificates.crt is not existent.

Does anybody have a quick solution how to use the let's encrypted certificates that way, that i do not need the x509cert- Value in php-saml config?

pitbulk commented 9 months ago

The toolkit is able to read certs and private keys from the certs folder, so you don't need to inject the content in the SAML settings, instead place the cert and private key in the certs folder and rename them as the toolkit expects.

I guess you should be able to create some link between the /etc/ssl and your saml toolkit cert. Or maybe some script that detect changes on such folder and sync the certs one

PentaPaetzold commented 9 months ago

Thank you, that was my expectation too. But what exactly do "as the toolkit expects" mean? If you look at my example, that what my system looks like. What do i have to change to make it work?

Edit: To ask more precise. Which Files are needed where and what should be the content. This is, what the let's' encrypt companion creates an how my Foler /etc/ssl/certs looks like exactly now:

96128343810c:/etc/ssl/certs# ls -la
total 56
drwxr-xr-x 11 1000 1000 4096 Feb  8 20:12 .
drwxr-xr-x  1 root root 4096 Nov 30 09:32 ..
drwxr-xr-x  2 root root 4096 May 31  2023 authentik.penta-home.site
lrwxrwxrwx  1 root root   37 Feb  8 20:12 authentik.penta-home.site.chain.pem -> ./authentik.penta-home.site/chain.pem
lrwxrwxrwx  1 root root   41 Feb  8 20:12 authentik.penta-home.site.crt -> ./authentik.penta-home.site/fullchain.pem
lrwxrwxrwx  1 root root   13 Feb  8 20:12 authentik.penta-home.site.dhparam.pem -> ./dhparam.pem
lrwxrwxrwx  1 root root   35 Feb  8 20:12 authentik.penta-home.site.key -> ./authentik.penta-home.site/key.pem
-rw-r--r--  1 1000 1000 1870 May 30  2023 default.crt
-rw-------  1 1000 1000 3272 May 30  2023 default.key
-rw-r--r--  1 1000 1000  769 May 30  2023 dhparam.pem
drwxr-xr-x  2 root root 4096 Jun 16  2023 kimai.penta-home.site
lrwxrwxrwx  1 root root   33 Feb  8 20:12 kimai.penta-home.site.chain.pem -> ./kimai.penta-home.site/chain.pem
lrwxrwxrwx  1 root root   37 Feb  8 20:12 kimai.penta-home.site.crt -> ./kimai.penta-home.site/fullchain.pem
lrwxrwxrwx  1 root root   13 Feb  8 20:12 kimai.penta-home.site.dhparam.pem -> ./dhparam.pem
lrwxrwxrwx  1 root root   31 Feb  8 20:12 kimai.penta-home.site.key -> ./kimai.penta-home.site/key.pem
drwxr-xr-x  2 root root 4096 May 30  2023 nextcloud.penta-home.site
lrwxrwxrwx  1 root root   37 Feb  8 20:12 nextcloud.penta-home.site.chain.pem -> ./nextcloud.penta-home.site/chain.pem
lrwxrwxrwx  1 root root   41 Feb  8 20:12 nextcloud.penta-home.site.crt -> ./nextcloud.penta-home.site/fullchain.pem
lrwxrwxrwx  1 root root   13 Feb  8 20:12 nextcloud.penta-home.site.dhparam.pem -> ./dhparam.pem
lrwxrwxrwx  1 root root   35 Feb  8 20:12 nextcloud.penta-home.site.key -> ./nextcloud.penta-home.site/key.pem
drwxr-xr-x  2 1000 1000 4096 May 31  2023 penta-home.site
drwxr-xr-x  2 root root 4096 May 30  2023 pgadmin.penta-home.site
lrwxrwxrwx  1 root root   35 Feb  8 10:24 pgadmin.penta-home.site.chain.pem -> ./pgadmin.penta-home.site/chain.pem
lrwxrwxrwx  1 root root   39 Feb  8 20:12 pgadmin.penta-home.site.crt -> ./pgadmin.penta-home.site/fullchain.pem
lrwxrwxrwx  1 root root   13 Feb  8 10:24 pgadmin.penta-home.site.dhparam.pem -> ./dhparam.pem
lrwxrwxrwx  1 root root   33 Feb  8 10:24 pgadmin.penta-home.site.key -> ./pgadmin.penta-home.site/key.pem
drwxr-xr-x  2 root root 4096 Jun 16  2023 phpmyadmin.penta-home.site
lrwxrwxrwx  1 root root   38 Feb  8 10:24 phpmyadmin.penta-home.site.chain.pem -> ./phpmyadmin.penta-home.site/chain.pem
lrwxrwxrwx  1 root root   42 Feb  8 10:24 phpmyadmin.penta-home.site.crt -> ./phpmyadmin.penta-home.site/fullchain.pem
lrwxrwxrwx  1 root root   13 Feb  8 10:24 phpmyadmin.penta-home.site.dhparam.pem -> ./dhparam.pem
lrwxrwxrwx  1 root root   36 Feb  8 10:24 phpmyadmin.penta-home.site.key -> ./phpmyadmin.penta-home.site/key.pem
drwxr-xr-x  2 root root 4096 May 30  2023 portainer.penta-home.site
lrwxrwxrwx  1 root root   37 Feb  8 10:24 portainer.penta-home.site.chain.pem -> ./portainer.penta-home.site/chain.pem
lrwxrwxrwx  1 root root   41 Feb  8 10:24 portainer.penta-home.site.crt -> ./portainer.penta-home.site/fullchain.pem
lrwxrwxrwx  1 root root   13 Feb  8 10:24 portainer.penta-home.site.dhparam.pem -> ./dhparam.pem
lrwxrwxrwx  1 root root   35 Feb  8 10:24 portainer.penta-home.site.key -> ./portainer.penta-home.site/key.pem
drwxr-xr-x  2 root root 4096 Jun  7  2023 signaling.penta-home.site
lrwxrwxrwx  1 root root   37 Feb  8 10:24 signaling.penta-home.site.chain.pem -> ./signaling.penta-home.site/chain.pem
lrwxrwxrwx  1 root root   41 Feb  8 10:24 signaling.penta-home.site.crt -> ./signaling.penta-home.site/fullchain.pem
lrwxrwxrwx  1 root root   13 Feb  8 10:24 signaling.penta-home.site.dhparam.pem -> ./dhparam.pem
lrwxrwxrwx  1 root root   35 Feb  8 10:24 signaling.penta-home.site.key -> ./signaling.penta-home.site/key.pem
drwxr-xr-x  2 root root 4096 May 31  2023 www.penta-home.site
lrwxrwxrwx  1 root root   31 Feb  8 10:24 www.penta-home.site.chain.pem -> ./www.penta-home.site/chain.pem
lrwxrwxrwx  1 root root   35 Feb  8 10:24 www.penta-home.site.crt -> ./www.penta-home.site/fullchain.pem
lrwxrwxrwx  1 root root   13 Feb  8 10:24 www.penta-home.site.dhparam.pem -> ./dhparam.pem
lrwxrwxrwx  1 root root   29 Feb  8 10:24 www.penta-home.site.key -> ./www.penta-home.site/key.pem

So as you can see, the files are in the certs folder named by service, whereas i found out, that the value of the parameter x509cert needs to be changed to the first section of the file authentik.penta-home.site.crt to make signing work.

So how to make php-saml read that value from that file instead of the parameter?

pitbulk commented 9 months ago

From documentation:

certs/
SAML requires a x509 cert to sign and encrypt elements like NameID, Message, Assertion, Metadata.

If our environment requires sign or encrypt support, this folder may contain the x509 cert and the private key that the SP will use:

sp.crt - The public cert of the SP
sp.key - The private key of the SP

But this certs folder is not /etc/ssl/certs, by default the certs folder looked by the toolkit has the relative path:

/certs/ as you can see in the code [here](https://github.com/SAML-Toolkits/php-saml/blob/4.x-dev/src/Saml2/Settings.php#L164C23-L164C40). You can configure your own path for the settings and the certs folder by defining the ONELOGIN_CUSTOMPATH env. The toolkit will try to read SP private key from sp.key and public cert from sp.crt, so you will need to rename the files you have. As it seems you are trying to setup SAML on a multi-instance environment where you gonna have several SPs, I propose you to create the following structure: php-saml\ certs\ authentik \certs kimai \certs nextcloud \certs pgadmin \certs phpmyadmin \certs portainer \certs signaling \certs penta \certs And: 1. Create some script to copy and rename properly the files from `/etc/ssl/certs` to the right target. 2. In your SAML controller built dynamically the ONELOGIN_CUSTOMPATH and depending on the SP to be loaded, set the right value for the path. That said, another option is to not use those let's encrypt certificates, and simply use a self-signed cert with less rate of rotation.
PentaPaetzold commented 9 months ago

Thanks, so for testing i tried:

  1. make a new directory /etc/ssl/kimai
  2. made a copy of the both files:
    
    cp ../certs/authentik.penta-home.site.crt sp.crt
    cp ../certs/authentik.penta-home.site.key sp.key
3. changed the ownership of the files to be readable by apache
4. Set env to be:

echo ${ONELOGIN_CUSTOMPATH}

/etc/ssl/kimai

ls -l ${ONELOGIN_CUSTOMPATH}/sp.*

-rw-r--r-- 1 root root 5890 Feb 12 10:50 /etc/ssl/kimai/sp.crt -rw-r--r-- 1 root root 3243 Feb 12 10:50 /etc/ssl/kimai/sp.key

cat ${ONELOGIN_CUSTOMPATH}/sp.crt

-----BEGIN CERTIFICATE----- MIIF/zCCBOegAwIBAgISBI2yNE3KVJFzjUFHSLYxfUMcMA0GCSqGS

5. Removed Value x509cert in config

Now restartet kimai/fpm.

[2024-02-12T11:08:22.144516+00:00] request.INFO: Matched route "saml_acs". {"route":"saml_acs","route_parameters":{"_route":"saml_acs","_controller":"App\Controller\Auth\SamlController::assertionConsumerServiceAction"},"request_uri":"http://kimai.penta-home.site/auth/saml/acs","method":"POST"} {"channel":"request"} [2024-02-12T11:08:22.157370+00:00] request.CRITICAL: Uncaught PHP Exception OneLogin\Saml2\Error: "Invalid array settings: idp_cert_or_fingerprint_not_found_and_required" at /opt/kimai/vendor/onelogin/php-saml/src/Saml2/Settings.php line 141 {"exception":"[object] (OneLogin\Saml2\Error(code: 2): Invalid array settings: idp_cert_or_fingerprint_not_found_and_required at /opt/kimai/vendor/onelogin/php-saml/src/Saml2/Settings.php:141)"} {"channel":"request"}


-> is it really name sp.crt or should "sp" be replaced by something else?
-> any way to look behind the scenes and see 1. if there was a try to find the file 2. if the file has been detected 3. if there was some value and what prevented it from beeing used?
pitbulk commented 9 months ago

Notice the error you are receiving now is not related to the SP, but related to the IdP:

idp_cert_or_fingerprint_not_found_and_required

Make sure you configure the IdP x59cert parameter in the settings.

PentaPaetzold commented 9 months ago

i see - a missunderstanding. The Value x509cert which i was talking about is always under section idp. I have never given values in sp- section to make it work. This may explain, why i always needed the value of authentik and not of kimai and only the crt, not the private key itself.

So i want to have empty value for ipd- parameter x509cert in config and have saml authenticate to authentik. Currently it stills does only work when i set idp x509cert to value of authentik crt, which make work because that key is often changing.

Cloud it be archived be naming the file to idp.crt ?

Edit: Or maybe could i use some other Value of the chain like let's encrypts CA to always trust the connection (as any browser would do)?

pitbulk commented 9 months ago

Yes, idp.crt should work

PentaPaetzold commented 9 months ago

not yet:

# cat ${ONELOGIN_CUSTOMPATH}/idp.crt
-----BEGIN CERTIFICATE-----
MIIF/zCCBOegAwIBAgISBI2y...
# ls -l ${ONELOGIN_CUSTOMPATH}/idp.crt
-rw-r--r-- 1 root root 5890 Feb 12 10:50 /etc/ssl/kimai/idp.crt
[2024-02-12T17:42:06.439047+00:00] request.INFO: Matched route "saml_acs". {"route":"saml_acs","route_parameters":{"_route":"saml_acs","_controller":"App\\Controller\\Auth\\SamlController::assertionConsumerServiceAction"},"request_uri":"http://kimai.penta-home.site/auth/saml/acs","method":"POST"} {"channel":"request"}
[2024-02-12T17:42:06.516777+00:00] cache.INFO: Lock acquired, now computing item "configurations" {"key":"configurations"} {"channel":"cache"}
[2024-02-12T17:42:06.563007+00:00] request.CRITICAL: Uncaught PHP Exception OneLogin\Saml2\Error: "Invalid array settings: idp_cert_or_fingerprint_not_found_and_required" at /opt/kimai/vendor/onelogin/php-saml/src/Saml2/Settings.php line 141 {"exception":"[object] (OneLogin\\Saml2\\Error(code: 2): Invalid array settings: idp_cert_or_fingerprint_not_found_and_required at /opt/kimai/vendor/onelogin/php-saml/src/Saml2/Settings.php:141)"} {"channel":"request"}

i have the impression, that the env may not reach php, or the file is not searched for.

Can i set some debug flag in settings to see what saml is doing?