Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set permissions of privkey.pem to 0600 #1760

Closed
wants to merge 1 commit into from

Conversation

colincross
Copy link

Sendmail requires privkey.pem to be unreadable by anything except
root. Create privkey.pem as 0600, and make the permissions of the
certificate files explictly 0644.

Writing through the live symlink to the archive directory prevents
using O_EXCL | O_CREAT, so write directly to the archive instead.

Sendmail requires privkey.pem to be unreadable by anything except
root.  Create privkey.pem as 0600, and make the permissions of the
certificate files explictly 0644.

Writing through the live symlink to the archive directory prevents
using O_EXCL | O_CREAT, so write directly to the archive instead.
@colincross
Copy link
Author

Fixes #1473

@olivluca
Copy link
Contributor

olivluca commented Dec 5, 2015

That would break, e.g., cyrus-imapd, since it doesn't run as root (note that it doesn't work by default either unless I manually chgrp the certificates to mail and change the permission/group of the containing directories).
Maybe the owner/group/permissions shouldn't be hardcoded but configurable?

@kousu
Copy link

kousu commented Dec 6, 2015

The same problem breaks opensmtpd:

kousu@comms:~$ sudo /usr/sbin/smtpd -d
warn:  /etc/letsencrypt/live/comms.kousu.ca/privkey.pem: insecure permissions: must be at most rwx------ 
fatal: load_pki_tree: failed to load key file

I need to manually change the permissions to fix this:

root@comms:/etc/letsencrypt/live/comms.kousu.ca# chmod go-rwx privkey.pem 
root@comms:/etc/letsencrypt/live/comms.kousu.ca# ls -l privkey.pem
lrwxrwxrwx 1 root root 41 Dec  6 06:06 privkey.pem -> ../../archive/comms.kousu.ca/privkey2.pem
root@comms:/etc/letsencrypt/live/comms.kousu.ca# ls -l ../../archive/comms.kousu.ca/privkey2.pem 
-rw------- 1 root root 1704 Dec  6 06:06 ../../archive/comms.kousu.ca/privkey2.pem
root@comms:/etc/letsencrypt/live/comms.kousu.ca# 
root@comms:/etc/letsencrypt/live/comms.kousu.ca# smtpd -d
info: OpenSMTPD 5.4.2p1 starting
info: startup

There's something else strange here: the symlink's permissions are 777, even though the actual file isn't. The permissions of the symlinks should match the permissions of the files!

Some programs are going to be more or less picky about permissions than others, and I suspect some will flat out contradict (e.g. if a program assumes the certs are owned by its user, or difference of opinion about if certs should be read pre or post priv-dropping). #1504 argues that each specific piece of software should get a different adaptor script. I don't know what's best.

@schoen
Copy link
Contributor

schoen commented Dec 7, 2015

It seems we will want it to be configurable, but it's still not clear what the best default is. (When using a specific installer, the installer could maybe have a default that's appropriate for the software that the installer is integrating with, but we're not always using a specific installer because people also want certs for external software that we don't directly integrate with or that they don't want us to configure for them.)

@schoen
Copy link
Contributor

schoen commented Dec 7, 2015

If someone else reviews this, note also the parallel PR #1705 for the same purpose.

@pde pde assigned bmw Dec 10, 2015
@pde pde added this to the 0.1.1 milestone Dec 10, 2015
@bmw bmw modified the milestones: 1.0.0, 0.1.1 Dec 10, 2015
@bmw bmw removed their assignment Dec 10, 2015
@convissor
Copy link
Contributor

I'm surprised by Cyrus' behavior. Most other daemons (eg postfix, apache) start up as root to get the keys, then drop to a non-privileged user.

@kousu
Copy link

kousu commented Dec 25, 2015

👍 to avoiding knobs in letsencrypt. Daemons are not consistent and that is hard to support, but the more configuration in core letsencrypt the more chance for something to go wrong.

Maybe there should be a letsencrypt group (letsencrypt_private_key?) that daemon users can be placed in. Like, set the privkeys 0440 root:letsencrypt_private_key. Daemons that drop from root will keep working, other ones will need to have the install script check that their user is in that group.

@thomaszbz
Copy link
Contributor

Using Debian 8, there's a group ssl-cert for use with private keys. Maybe LE could go for this (or equivalent) as a default? Plus, configurable permissions would be nice (via cli.ini). Also see my comment at #1473 (comment) .

@Zash
Copy link

Zash commented Feb 3, 2016

Configurable permissions and ownership for certificates and files would be nice.

Another example: Prosody drops root long before it even starts. Even a hidden option somewhere to chown/chmod certificates and keys meant for it to a different user would make using Let's Encrypt with it much easier.

@kousu
Copy link

kousu commented Feb 19, 2016

I just renewed my certs and this issue bit me again. I cannot set up auto-renew because opensmtpd is prissy: I must go in and manually chmod g-o the keyfile or else it refuses to run, since it is designed to run briefly as root and then drop privs. But that chmod breaks other daemons that assume they will be run as the user they are supposed to be. I don't know what to do. OpenSMTPD is doing the more secure thing---certainly we won't convince them to change---by forcing the more restrictive permissions u+r go-r, but daemons that don't do priv-dropping instead require g+r and group configuration.

I see that since I last checked in, letsencrypt now sets privkey$N.pem to 0640 (rw-r-----), supporting the latter case. I like that, I think, but I also like opensmtpd.

I could use hard-links to effectively lie to smtpd about the permissions:

$ N=3  #which edition this cert is
$ cd /etc/letsencrypt/archive/comms.kousu.ca/
$ sudo ln privkey${N}.pem privkey${N}.paranoid.pem
$ sudo chmod 0600 privkey${N}.paranoid.pem 

and arrange for smtpd to use the stable address of /etc/letsencrypt/live/comms.kousu.ca/privkey_.pem

$ cd /etc/letsencrypt/archive/comms.kousu.ca/
$ sudo ln -s ../../archive/comms.kousu.ca/privkey${N}.paranoid.pem privkey.paranoid.pem

but this requires me to redo it every time I renew and for each domain vhosted.
Does anyone have any better ideas?

@kousu
Copy link

kousu commented Feb 19, 2016

Oh wait scratch that I don't know how hardlinks work: permissions are on the inode, not the directory entry, so hardlinks share permissions. Which I guess makes sense.

So instead of ln I need to do this:

$ sudo cp privkey${N}.pem privkey${N}.paranoid.pem
$ sudo chmod g-r *paranoid.pem

@FelixSchwarz
Copy link
Contributor

@convissor: As noted in this thread there are many daemons not reading key material with "root". Exim is another notable example. So we need a solution for them.

@kousu: While less knobs in letsencrypt are generally a good idea I think we need some here. The ability to screw up can be mitigated by a safe default which is "mode=0600" with uid/gid root/root. Hence most people will be safe by default and admins can opt in to set an unsafe default.

@FelixSchwarz
Copy link
Contributor

but this requires me to redo it every time I renew and for each domain vhosted.
Does anyone have any better ideas?

@kousu: renew hooks were merged today (3d26048). This might be best workaround to set permissions/ownership short of a specialized config option (which I still prefer, seems to be harder to mess up on the admin side + doesn't require admins to write the same logic over and over again).

@LukeShu
Copy link

LukeShu commented Jun 28, 2016

Setting the permissions as a post hook is a terrible, broken idea; that means that the permissions are temporarily too permissive.

A better workaround would be to just set the umask to something more restrictive.

@blendmaster
Copy link

Friendly bump. Also just got burned by opensmtpd on this:

warn: /etc/letsencrypt/live/example.com/privkey.pem: insecure permissions: must be at most rwxr-----

@LukeShu
Copy link

LukeShu commented Oct 31, 2016

FWIW, I think that the best solution is just to configure the process' umask appropriately.

If running certbot from a systemd service, stick the line UMask=0077 into the .service file, which would make the permissions be 0600.

At the end of the day, setting the process' umask is the standard, configurable, way to control the permissions files created by a process. It's not a hack, it's the standard Unix administration way of doing it.

Meanwhile, if it set the permissions to 0600 explicitly in the source, then I would have to resort to hacks to get a nice 0640 permission allowing services (nginx, smtpd, et c.) never need root, but just to be a member of the special cert-reading group.

On the other hand, having them be 0644 by default is antagonistic to certbot's goal of being as close to magical and zero-setup as possible, as 0644 is pretty wrong. Perhaps the best thing to do is to set the umask explicitly at program startup, and add a --umask flag that changes the umask away from the default 0077.

@kousu
Copy link

kousu commented Oct 31, 2016

👍 to @LukeShu

@blendmaster
Copy link

Re: umask on the process, won't that affect the operation of --webroot, which presumably has to write files readable by the web server? I'll test it out next time I get a chance.

I think I agree in principle that umask 0077 is a good default, but considering all the automagical stuff that certbot-auto does inside of its black box (like webroot), a very specific config flag for permissions on privkey.pem seems like the most immediate way to hack around the "services don't agree on the appropriate privkey permissions" problem. Certainly a little depressing, but not all programs can be elegant paragons of the Unix Philosophy™.

@LukeShu
Copy link

LukeShu commented Nov 1, 2016

@blendmaster You are right, 0077 might interfere with webroot.

On the other hand, you could use FACLs on the certs directory to set a default permission on the directory itself (essentially setting a per-directory umask, instead of a per-process umask). But yes, a flag is probably the best option.

@blendmaster
Copy link

On the other hand, you could use FACLs on the certs directory to set a default permission on the directory itself (essentially setting a per-directory umask, instead of a per-process umask). But yes, a flag is probably the best option.

Thanks for this suggestion. I did:

setfacl -d -m 'group: :0' -m 'other: :0' /etc/letsencrypt/archive/example.com

and renewed certs do get created at 600. The public key and chain are unfortunately also only root-accessible now, but at least for me, that's fine.

@jsha
Copy link
Contributor

jsha commented Mar 7, 2017

This PR and #1705 both block on a design decision (#1473) about how exactly we want configuration of ownership and permissions to work. Closing for now; we can make or solicit a new PR once we've reached a conclusion on #1473.

@jsha jsha closed this Mar 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet