Question: How to create a user account which cannot write to any file on the system? In other words, how to create a read-only user account in CentOS/RHEL 7?
Linux does not provide a role-level classification of accounts. Access permission is controlled at the I-node level which implies permissions for each individual file or directory separately.
If we may restate the problem slightly, there are at least two techniques that may give the desired operation. Instead of thinking in terms of the user account, think in terms of files and directories. This allows us some alternative methods of achieving much the same result. Each item below shows an alternative implementation which provides slightly different protection which may be useful in some use cases.
Create a non-privileged, anonymous account
Each file or directory in Linux has three sets of read/write/execute permissions, one each for the file owner, other users in the same group as the original owner, and all others. A new account can be created with a unique user ID and group ID and this new account be used as the read-only account. Since the account would own no files outside its home directory, the only access permission it would be the “other” permissions, which typically omit permitting write access.
# useradd -c 'Mostly R/O Account' roaccount
The roaccount will have a unique user ID and group ID assigned, which forces any file outside its home directory to be controlled by the “other” access permissions. The O/S already has a least-privilege account nobody but this account is treated specially by the system. A separate account is recommended for R/O usage.
The flaw in this scheme is that it relies on every file and every directory on the server and storage to have its “other” permissions correctly set. This can be done manually or by having the umask of the creating process set to at least 0002 (which blocks setting the “other” write permissions).
Receive notification when certain files are written.
If the goal is to determine all files written by a given user, the auditctl tool may be useful. A watch can be set on the write system call that triggers when done by a particular user. For example a setting:
# auditctl -a always,exit -S write -F auid=1000
would trigger an audit trail entry whenever user ID 1000 write to any file. The audit trail subsystem is quite expressive in the conditions that can be expressed.
Find more documentation on the audit.rules man page.
# man audit.rules
Use access control lists (ACLs) to override permissions.
Some filesystem handlers support access control lists (ACL) that are finer-grained permissions than the owner/group/other divisions allow. Individual files or directories can use an ACL to select a certain set of users, not necessarily in the same group, and give just those users the desired file access permissions.
For example, we want to give userA, userB, and userC read-only access to directory /secret-files/ and below. We can do that like this:
# setfacl -Rd -m u:userA:rx -m u:userB:rx -m u:userC:rx /secret-files # setfacl -R -m u:userA:rx -m u:userB:rx -m u:userC:rx /secret-files
The first line sets a default ACL which will apply to any new files or directories created under /secret-files in the future. The second file applies the ACL to any existing content in the /secret-files tree and below.
For more details about this feature check the aclman page.
# man acl