Using Security-Enhanced Linux for ThingWorx Docker
Security-Enhanced Linux (SELinux) is a set of kernel modifications and user-space tools that are added to various Linux distributions. SELinux architecture enables the separation of the enforcement of security decisions from the security policy, and streamlines the amount of software involved with security policy enforcement. The key concepts underlying SELinux can be traced to several earlier projects by the United States National Security Agency (NSA).
SELinux users and roles do not have to be related to the actual system users and roles. For every current user or process, SELinux assigns a three-string context that includes a user name, role, and domain (or type). This system is more flexible than normally required; as a rule, most of the real users share the same SELinux user name, and all access control is managed through the third tag, the domain. You must configure the circumstances for allowing a process into a certain domain in the policies. Although you can use the runcon command to start a process in an explicitly specified context (user, role and domain), SELinux can deny the transition if it is not approved by the policy.
Files, network ports, and other hardware also have a SELinux context that includes a name, role (seldom used), and type. In the case of file systems, mapping between files and the security contexts is referred to as labeling. The labeling is defined in policy files, but you can also adjust it manually without changing the policies. Hardware types are also detailed, for instance, bin_t (all files in the folder /bin) or postgresql_port_t (PostgreSQL port, 5432). You can specify the SELinux context for a remote file system explicitly at mount time.
SELinux adds the -Z switch to the shell commands ls, ps, and some others, allowing the security context of the files or process to be seen.
Typically, policy rules consist of explicit permissions, such as which domains the user must possess to be able to perform certain actions with the given target. Examples of these actions are read, execute, and in the case of network port, bind or connect. More complex mappings that involve roles and security levels are also possible.
A typical policy consists of a mapping (labeling) file, a rule file, and an interface file that define the domain transition. These three files must be compiled with the SELinux tools to produce a single policy file. The resulting policy file can be loaded into the kernel, making it active. Loading and unloading policies do not require a reboot. The policy files are either developed manually or can be generated from the more user-friendly SELinux management tool. These file are typically tested in permissive mode first, where violations are logged but allowed. You can use the audit2allow tool later to produce additional rules that extend the policy to allow all legitimate activities of the application being confined.
Common SELinux Issues
The most common issue with SELinux is that permission is denied, indicating that SELinux is not working. Permission denied error messages appear when are you are trying to access a system object that is not associated with the program or the user credentials you use for accessing that object. These errors are challenging to resolve; however, there are tools that can help you troubleshoot.
Installing Setools and Setroubleshoot
To install these tools on your system:
1. Log in to your server or desktop using an account granted administrative rights.
2. Open a command shell.
3. Install setroubleshoot packages using Yum:
yum install setroubleshoot setools
SELinux Alerts
Use the sealert tool to analyze the audit log used by SELinux. This tool scans the log file and the report, and then generates a report with all discovered SELinux issues.
To run sealert from the command-line, point it to the SELinux audit log. See the following example:
sealert -a /var/log/audit/audit.log
A report describes each issue and explains how to resolve it. Following is a truncated example of the output generated by sealert:
100% done found 1 alerts in /var/log/audit/audit.log
--------------------------------------------------------------------------------
SELinux is preventing /usr/sbin/httpd from getattr access on the file
/myapps/app1/html/index.html.
***** Plugin catchall_labels (83.8 confidence) suggests ********************
If you want to allow httpd to have getattr access on the index.html file
Then you need to change the label on /myapps/app1/html/index.html
Do
# semanage fcontext -a -t FILE_TYPE '/myapps/app1/html/index.html'
where FILE_TYPE is one of the following: sssd_var_lib_t, public_content_t, anon_inodefs_t,
[..truncated..]
httpd_sys_ra_content_t, httpd_sys_rw_content_t, httpd_sys_rw_content_t,
httpd_w3c_validator_content_t.
Then execute:
restorecon -v '/myapps/app1/html/index.html'
***** Plugin catchall (17.1 confidence) suggests ***************************
If you believe that httpd should be allowed getattr access on the index.html file by
default. Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# grep httpd /var/log/audit/audit.log | audit2allow -M mypol
# semodule -i mypol.pp
The most important part of the report that explains how to resolve the issue appears at the end of each alert. For example, the report above shows the following solution:
If you believe that httpd should be allowed getattr access on the index.html file by
default. Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# grep httpd /var/log/audit/audit.log | audit2allow -M mypol
# semodule -i mypol.pp
The proposed solution creates an SELinux policy to be applied to the problematic file. In this example, an HTML file was assigned the wrong SELinux file context.
Following are more examples for potential issues with the ThingWorx Docker containers.
This example illustrates an issue with PostgreSQL. In this case, sealert produces the following alert:
found 1 alerts in /var/log/audit/audit.log
--------------------------------------------------------------------------------
SELinux is preventing /bin/chown from setattr access on the directory data.
***** Plugin catchall_labels (83.8 confidence) suggests *******************
If you want to allow chown to have setattr access on the data directory
Then you need to change the label on data
Do
# semanage fcontext -a -t FILE_TYPE 'data'
where FILE_TYPE is one of the following: cgroup_t, nfs_t, svirt_home_t,
svirt_sandbox_file_t.
Then execute:
restorecon -v 'data'
***** Plugin catchall (17.1 confidence) suggests **************************
If you believe that chown should be allowed setattr access on the data directory by
default. Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# ausearch -c 'chown' --raw | audit2allow -M my-chown
# semodule -i my-chown.pp
Additional Information:
Source Context system_u:system_r:svirt_lxc_net_t:s0:c459,c1008
Target Context unconfined_u:object_r:usr_t:s0
Target Objects data [ dir ]
Source chown
Source Path /bin/chown
Port <Unknown>
Host <Unknown>
Source RPM Packages
Target RPM Packages
Policy RPM selinux-policy-3.13.1-166.el7_4.9.noarch
Selinux Enabled True
Policy Type targeted
Enforcing Mode Enforcing
Host Name ip-10-99-0-109.ec2.internal
Platform Linux ip-10-99-0-109.ec2.internal
3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20
20:32:50 UTC 2017 x86_64 x86_64
Alert Count 9
First Seen 2018-04-02 17:08:08 UTC
Last Seen 2018-04-02 17:08:27 UTC
Local ID 65bb52e5-bde9-4ec5-ba44-f0752ffef319
Raw Audit Messages
type=AVC msg=audit(1522688907.927:619): avc: denied { setattr } for pid=12142
comm="initdb" name="data" dev="nvme0n1p1" ino=826278009 scontext=system_u:system_r:
svirt_lxc_net_t:s0:c459,c1008 tcontext=unconfined_u:object_r:usr_t:s0 tclass=dir
type=SYSCALL msg=audit(1522688907.927:619): arch=x86_64 syscall=chmod success=no
exit=EACCES a0=5633eefb7310 a1=1c0 a2=0 a3=7f3c78d1d6a0 items=0 ppid=12116 pid=12142
auid=4294967295 uid=1001 gid=0 euid=1001 suid=1001 fsuid=1001 egid=0 sgid=0 fsgid=0
tty=(none) ses=4294967295 comm=initdb exe=/usr/lib/postgresql/9.4/bin/initdb
subj=system_u:system_r:svirt_lxc_net_t:s0:c459,c1008 key=(null)
Hash: chown,svirt_lxc_net_t,usr_t,dir,setattr
This report shows the following suggested solution:
If you want to allow chown to have setattr access on the data directory
Then you need to change the label on data
Do
# semanage fcontext -a -t FILE_TYPE 'data'
where FILE_TYPE is one of the following: cgroup_t, nfs_t, svirt_home_t,
svirt_sandbox_file_t.
Then execute:
restorecon -v 'data'
Following is the command you would enter to implement this solution:
semanage fcontext -a -t svirt_sandbox_file_t "/opt/postgresql-storage(/.*)?" restorecon -R /opt/postgresql-storage
Note that the suggested solution was to apply the permissions only to the data folder for PostgreSQL. However, because you need write access for the ThingWorx tablespace, you must grant the same permissions to everything in that folder.
This example illustrates an issue with the ThingWorx platform. In this case, sealert produces the following alert:
found 1 alerts in /var/log/audit/audit.log
--------------------------------------------------------------------------------
SELinux is preventing /bin/mv from write access on the directory ThingworxStorage.
***** Plugin catchall_labels (83.8 confidence) suggests *******************
If you want to allow mv to have write access on the ThingworxStorage directory
Then you need to change the label on ThingworxStorage
Do
# semanage fcontext -a -t FILE_TYPE 'ThingworxStorage'
where FILE_TYPE is one of the following: cgroup_t, container_var_lib_t, nfs_t,
svirt_home_t, svirt_sandbox_file_t, tmpfs_t, virt_home_t.
Then execute:
restorecon -v 'ThingworxStorage'
***** Plugin catchall (17.1 confidence) suggests **************************
If you believe that mv should be allowed write access on the ThingworxStorage
directory by default.
Then you should report this as a bug.
You can generate a local policy module to allow this access.
Do
allow this access for now by executing:
# ausearch -c 'mv' --raw | audit2allow -M my-mv
# semodule -i my-mv.pp
Additional Information:
Source Context system_u:system_r:svirt_lxc_net_t:s0:c320,c876
Target Context unconfined_u:object_r:usr_t:s0
Target Objects ThingworxStorage [ dir ]
Source mv
Source Path /bin/mv
Port <Unknown>
Host <Unknown>
Source RPM Packages
Target RPM Packages
Policy RPM selinux-policy-3.13.1-166.el7_4.9.noarch
Selinux Enabled True
Policy Type targeted
Enforcing Mode Enforcing
Host Name ip-10-99-0-109.ec2.internal
Platform Linux ip-10-99-0-109.ec2.internal
3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20
20:32:50 UTC 2017 x86_64 x86_64
Alert Count 13
First Seen 2018-04-02 17:13:18 UTC
Last Seen 2018-04-02 17:13:23 UTC
Local ID 1759a007-f347-4d80-99e8-ee414eae7602
Raw Audit Messages
type=AVC msg=audit(1522689203.86:708): avc: denied { write } forpid=14905
comm="java" name="ThingworxStorage" dev="nvme0n1p1" ino=864027929
scontext=system_u:system_r:svirt_lxc_net_t:s0:c320,c876
tcontext=unconfined_u:object_r:usr_t:s0 tclass=dir
type=SYSCALL msg=audit(1522689203.86:708): arch=x86_64 syscall=mkdir success=no
exit=EACCES a0=7f6480f76e80 a1=1ff a2=7f6480f76e80 a3=b items=0 ppid=14734
pid=14905 auid=4294967295 uid=1337 gid=1337 euid=1337 suid=1337 fsuid=1337
egid=1337 sgid=1337 fsgid=1337 tty=(none) ses=4294967295 comm=java exe=/opt/
jdk1.8.0_121/bin/java subj=system_u:system_r:svirt_lxc_net_t:s0:c320,c876 key=(null)
Hash: mv,svirt_lxc_net_t,usr_t,dir,write
This report shows the following suggested solution:
# semanage fcontext -a -t FILE_TYPE 'ThingworxStorage'
where FILE_TYPE is one of the following: cgroup_t, container_var_lib_t, nfs_t,
svirt_home_t, svirt_sandbox_file_t, tmpfs_t, virt_home_t.
Then execute:
restorecon -v 'ThingworxStorage'
Following is the command you use to implement this solution:
semanage fcontext -a -t svirt_sandbox_file_t "/opt/thingworx-storage(/.*)?"
restorecon -R /opt/thingworx-storage