Preserve security when service cannot access certificates

I have successfully received certificates using docker compose (thanks again to the community)

I have issues using the certificates due to a Permission denied exception. The process accessing the certificates must not be run with elevated rights.


A little more detail about the concrete problem:

I am trying to use Gitea over https with these certificates. For this I created the docker compose file so that the certbot container would expose the certificates through ./etc/letsencrypt which is mapped to /etc/letsencrypt in the certbot container and the Gitea container. The certbot certificates are available to Gitea (I confirmed this).

The issue is that the Gitea process must not be run using elevated rights (i.e. as root) and consequently it cannot access the certificates, (i.e. Permission Denied)

(For more details please check my thread in the gitea community)


I received the following proposal for a solution:

You could setup a certbot renewal hook that copies the certificates to Gitea’s directory and allows Gitea to read them.

This feels very wrong to me, since I would have to make the certificate available to non-root users. I am no expert, so I cannot tell if this is a valid security concern or paranoia.

So in short: Is it a security risk to copy the certificates into an insecure location and provide access through a non-root user? If this is fine, are there any sources on how to do this well?

Certificates are public already. The private key is the issue. Non-root users aren't a problem, as long as you don't publish the key.

3 Likes

Of course, it is.
Any time you copy the cert anywhere you increase the risk of its' exposure.

It may be the path of least resistance [exposure].
I see no issue with copying the cert and key to a location that only Gitea can access.
That said, I have no link to any source on how to.

4 Likes

I ran into this running NTS servers with ntpsec

Basically you have two options. Regardless of how you do it, if your non-privileged user or associated server process is compromised, your certificate will be compromised. Make sure your certificate covers only the domains/subdomains your non-privileged process actually needs, i.e. if it only needs a specific subdomain, issue the certificate only for that subdomain, not your apex domain or a wildcard subdomain. This will limit the potential damage.

  1. Copy the certificate files out of /etc/letsencrypt and carefully set permissions on the files and directories so that only the user in question can access them.

You can automate this by putting a script in /etc/letsencrypt/renewal-hooks

  1. Set group ownership & permissions on the /etc/letsencrypt/ so that your unprivileged process can access the files for the certificate it needs (and only that certificate)

For example, I wanted to give ntpsec access to certificate "master" only; the ntpsec user is the sole member of group "ntpsec", so I set group permissions like this:

chown -R root:root /etc/letsencrypt/archive/* /etc/letsencrypt/live/*
chgrp ntpsec /etc/letsencrypt/archive /etc/letsencrypt/live /etc/letsencrypt/live/master /etc/letsencrypt/archive/master /etc/letsencrypt/archive/master/*
chmod 0750 /etc/letsencrypt/archive /etc/letsencrypt/live
chmod 00700 /etc/letsencrypt/live/* /etc/letsencrypt/archive/*
chmod 0600 /etc/letsencrypt/live/README
chmod 2750 /etc/letsencrypt/live/master /etc/letsencrypt/archive/master
chmod 0640 /etc/letsencrypt/archive/master/*

Note, I set the "sticky" bit on on certain directories so that files created in those directories will have the "ntpsec" group by default.

You might think, does this need to be done after every renewal, and no, it does not. On renewals, certbot will copy the permissions of the old files onto the new files.

Going this route, there's no need to use a renewal hook, although I use one anyway to send a HUP to my ntpsec process, to ensure it switches over to the new certificate quickly. If your server process already HUPs or restarts itself (or if it's restarted by logrotate or something) you don't necessarily have to do that.

EDIT: you could also do custom ACLs instead of messing with group ownership but I find them a pain to work with.

2 Likes

This solution seems very invasive since it modifies existing files.

I now went with a script that would deploy the files to a determined folder and
make the only readable (i.e. 400) by the required user.

I hope that is appropriate. Thank you guys for your help.

3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.