I have a centos 7.2 instance, and attempted to change the system context on the mounted vagrant/ directory, in order to allow httpd to serve php based pages. The motivation for this, is because I have repointed the document root, via /etc/httpd/conf/httpd.conf to /vagrant/webroot, from the default /var/www/html.
Note: this issue is predicated on drupal-demonstration, with selinux manually enabled, since the default vagrant box implemented, has it disabled.
Before proceeding I reviewed the system context of my local project root:
[root@localhost /]# ls -lZ /vagrant
drwxrwxrwx. vagrant vagrant system_u:object_r:vmblock_t:s0 log
drwxrwxrwx. vagrant vagrant system_u:object_r:vmblock_t:s0 puppet
drwxrwxrwx. vagrant vagrant system_u:object_r:vmblock_t:s0 src
-rwxrwxrwx. vagrant vagrant system_u:object_r:vmblock_t:s0 vagrant
-rwxrwxrwx. vagrant vagrant system_u:object_r:vmblock_t:s0 Vagrantfile
drwxrwxrwx. vagrant vagrant system_u:object_r:vmblock_t:s0 webroot
So, I attempted to recursively change the system context on the vagrant/ directory:
[root@localhost /]# chcon -R -t httpd_sys_content_t vagrant
chcon: failed to change context of ‘COMMIT_EDITMSG’ to ‘system_u:object_r:httpd_sys_content_t:s0’: Operation not supported
chcon: failed to change context of ‘config’ to ‘system_u:object_r:httpd_sys_content_t:s0’: Operation not supported
chcon: failed to change context of ‘description’ to ‘system_u:object_r:httpd_sys_content_t:s0’: Operation not supported
...
Note: we terminated the above chcon command, while it was running, because there are a lot of files nested in the vagrant/ directory.
Since, I am unable to change the system context on the vagrant/ directory, if I delete, or move /etc/httpd/conf.d/welcome.conf, I get the following 403 error:
Note: though, this was attempted on Centos 7.x, it probably applies to Redhat 7.x.
Is this solution possible within vagrant, or should I try to customize selinux. More specifically, try to define any mounted directory to the system context of httpd_sys_content_t. If I get that working, then try to be more specific, such that only the vagrant/ directory defaults to the httpd_sys_content_t context?
Note: I've changed the document root for httpd (via httpd.conf), from the default /var/www/html, to /vagrant/webroot, as implemented within the drupal-demonstration repository.
IRC #centos (02/03/16 ~ 2:15pm EST):
jeffreylevesque: i wonder if i can write a selinux rule, so mounted directory default to httpd system context?
billings: jeffreylevesque: it wouldn't help, because the mountpoint would be mounted on top of the filesystem
billings: however vagrant is running 'mount' on the centos side, it needs to include a context= in the mount options.
Perhaps the mount command needs to be incorporated either within vagrant, or manually provisioned via puppet (or equivalent).
The following example mounts a newly-created file system on
/dev/sda2to the newly-created/vagrant/directory. It assumes that there are no rules in/etc/selinux/targeted/contexts/files/that define a context for the/vagrant/directory$ mount /dev/sda2 /vagrant/ -o defcontext=system_u:object_r:httpd_sys_content_t:s0"the
defcontextoption defines thatsystem_u:object_r:httpd_sys_content_t:s0is "the default security context for unlabeled files"
Though, I'm not sure what to do with the above /dev/sda2/ argument, with respect to vagrant. However, if we are to take the approach suggested by billings (from #centos):
If you would like to mount an NFS volume and read or export that file system with another service, use the context option when mounting to override the
nfs_ttype. Use the following context option to mount NFS volumes so that they can be shared via the Apache HTTP Server:mount server:/export /vagrant -o context="system_u:object_r:httpd_sys_content_t:s0"Since these changes are not written to disk, the context specified with this option does not persist between mounts. Therefore, this option must be used with the same context specified during every mount to retain the desired context.
Though, in this case, I'm not sure how I would need to change the server:/export argument, with respect to the vagrant implementation.
Note: the above command was attained from Redhat 7 documentation on _Mounting File Systems_.
We may be able to implement the vagrant mount_options, with respect to the above Redhat / Centos mount command:
IRC #centos (02/03/16 ~ 3:00pm EST):
jeffreylevesque: anyone familiar with
mount server:/export /vagrant -o context="system_u:object_r:httpd_sys_content_t:s0"?
jeffreylevesque: does theserver:/exportargument follow a certain convention?billings: jeffreylevesque: that's an NFS mountpoint
billings: jeffreylevesque: most liekly you'll use something like this
billings: https://www.vagrantup.com/docs/synced-folders/basic_usage.html#mount_options...
jeffreylevesque: so,
mount /vagrant -o context="system_u:object_r:httpd_sys_content_t:s0"to be incorporated into vagrantmount_options?billings: no
billings: mount -t vboxsf -o context="system_u:object_r:httpd_sys_content_t:s0" sharename /path/to/mountpoint
billings: and, the mount_options would just be context="system_u:object_r:httpd_sys_content_t:s0"jeffreylevesque: ok, this gives me direction
jeffreylevesque: what's thesharename?
IRC #centos (02/03/16 ~ 3:30pm EST):
sehh: a bit late to the party but...
sehh: the above command given by billings, is actually the way we mount VirtualBox shares
sehh: these require that the VirtualBox Additions has been installed, which provide the mount.vboxsf
sehh: the "sharename" is what you type in the "folder name" when you setup the shared folder in VirtualBox settings
We will try the following addition to our Vagrantfile:
...
config.vm.synced_folder './', '/vagrant',
owner: 'vagrant',
group: 'vagrant',
mount_options: ['dmode=775','fmode=664','context=system_u:object_r:httpd_sys_content_t:s0']
...
We tested the following within our Vagrantfile, which simply sets permission, and ownership, and completes without error for simple vagrant up build:
...
## set general project ownership, and permission
config.vm.synced_folder './', '/vagrant',
owner: 'vagrant',
group: 'vagrant',
mount_options: ['dmode=755', 'fmode=664']
## set permission for drupal 'settings*.php'
config.vm.synced_folder './src/default', '/vagrant/webroot/sites/default',
owner: 'vagrant',
group: 'apache',
mount_options: ['dmode=775', 'fmode=444']
## allow 'sites/default/files/' to be writeable for drupal install
config.vm.synced_folder './webroot/sites/default/files', '/vagrant/webroot/sites/default/files',
owner: 'vagrant',
group: 'apache',
mount_options: ['dmode=775', 'fmode=775']
...
However, it doesn't fix overall apache not rendering drupal webpage, if we remove /etc/httpd/conf.d/welcome.conf. So, we adjusted the above Vagrantfile snippet, to the following, and ensured that the apache user exists prior to vagrant reload:
...
## set general project ownership, and permission
config.vm.synced_folder './', '/vagrant',
owner: 'vagrant',
group: 'vagrant',
mount_options: ['dmode=755', 'fmode=664']
## set general project ownership, and permission
config.vm.synced_folder './webroot', '/vagrant/webroot',
owner: 'vagrant',
group: 'apache',
mount_options: ['dmode=755', 'fmode=664','context=system_u:object_r:httpd_sys_content_t:s0']
## set permission for drupal 'settings*.php'
config.vm.synced_folder './src/default', '/vagrant/webroot/sites/default',
owner: 'vagrant',
group: 'apache',
mount_options: ['dmode=775', 'fmode=444']
## allow 'sites/default/files/' to be writeable for drupal install
config.vm.synced_folder './webroot/sites/default/files', '/vagrant/webroot/sites/default/files',
owner: 'vagrant',
group: 'apache',
mount_options: ['dmode=775', 'fmode=775']
...
Upon vagrant reload get the following traceback error:
$ vagrant reload
==> default: vagrant-r10k: Building the r10k module path with puppet provisioner module_path "puppet/environment/development/modules". (if module_path is an array, first element is used)
==> default: vagrant-r10k: Beginning r10k deploy of puppet modules into /path/to/drupal-demonstration/puppet/environment/development/modules using /path/to/drupal-demonstration/puppet/environment/development/Puppetfile
==> default: vagrant-r10k: Deploy finished
==> default: Attempting graceful shutdown of VM...
Text will be echoed in the clear. Please install the HighLine or Termios libraries to suppress echoed text.
[email protected]'s password:myVagrantUserPassword
default:
default: Inserting generated public key within guest...
default: Removing insecure key from the guest if it's present...
default: Key inserted! Disconnecting and reconnecting using new SSH key...
Text will be echoed in the clear. Please install the HighLine or Termios libraries to suppress echoed text.
[email protected]'s password:myVagrantUserPassword
==> default: Clearing any previously set forwarded ports...
==> default: vagrant-r10k: Building the r10k module path with puppet provisioner module_path "puppet/environment/development/modules". (if module_path is an array, first element is used)
==> default: vagrant-r10k: Beginning r10k deploy of puppet modules into /path/to/drupal-demonstration/puppet/environment/development/modules using /path/to/drupal-demonstration/puppet/environment/development/Puppetfile
==> default: vagrant-r10k: Deploy finished
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 80 => 8333 (adapter 1)
default: 443 => 8334 (adapter 1)
default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: password
default: Warning: Connection timeout. Retrying...
default: Warning: Remote connection disconnect. Retrying...
Text will be echoed in the clear. Please install the HighLine or Termios libraries to suppress echoed text.
[email protected]'s password:
default: Warning: Connection timeout. Retrying...
Text will be echoed in the clear. Please install the HighLine or Termios libraries to suppress echoed text.
[email protected]'s password:myVagrantUserPassword
==> default: Machine booted and ready!
GuestAdditions 5.0.12 running --- OK.
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
default: /vagrant => /path/to/drupal-demonstration
default: /vagrant/webroot => /path/to/drupal-demonstration/webroot
Failed to mount folders in Linux guest. This is usually because
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:
mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group apache | cut -d: -f3`,dmode=755,fmode=664,context=system_u:object_r:httpd_sys_content_t:s0 vagrant_webroot /vagrant/webroot
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g apache`,dmode=755,fmode=664,context=system_u:object_r:httpd_sys_content_t:s0 vagrant_webroot /vagrant/webroot
The error output from the last command was:
I checked to see if guest additions are properly installed:
$ vagrant ssh
==> default: The machine you're attempting to SSH into is configured to use
==> default: password-based authentication. Vagrant can't script entering the
==> default: password for you. If you're prompted for a password, please enter
==> default: the same password you have configured in the Vagrantfile.
Enter passphrase for key '/path/to/.ssh/id_rsa':
[email protected]'s password:
Last login: Thu Feb 4 13:53:20 2016 from gateway
[vagrant@localhost ~]$ lsmod | grep -i vbox
vboxsf 39741 1
vboxvideo 12658 0
vboxguest 297222 2 vboxsf
drm 349210 2 vboxvideo
[vagrant@localhost ~]$ lsmod | grep -io vboxguest | xargs modinfo | grep -iw
version
version: 5.0.12
I forgot to mention (just fixed the main issue body), that I have repointed the document root, via /etc/httpd/conf/httpd.conf as /vagrant/webroot. Reestablishing /var/www/html as the document root, and adding a trivial index.html, with just <div>hello world</div> prints out to the corresponding localhost browser page:
[vagrant@localhost html]$ pwd
/var/www/html
[vagrant@localhost html] sudo vi index.html
[vagrant@localhost html]$ ls -Z
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
I may consider symlinking from /vagrant/webroot into /var/www/html, if no other solution is present. Though, I'm not sure if the symlink will have adequate system context, since the original context on /vagrant/webroot is not the required httpd_sys_content_t.
We may consider using the audit2allow module, to create custom policies. These custom policies can be created on the current vagrant centos vm, then possibly moved to the original virtualbox VM, which will allow us to regenerate the custom vagrant base box, with the policies loaded. Specifically, we will attempt to allow apache access to vmblock_t through a custom policy:
/var/log/audit/audit.logaudit.log in human-readable format:
$ audit2allow -w -a
- which, will allow us to see what rules would allow access:
audit2allow -a
- then, we create the policy based on the above generated rules, with respect to
vmblock_t:
$ grep vmblock_t /var/log/audit/audit.log | audit2allow -M httpd_vboxsf
Now, a _Type Enforcement_ file, httpd_vboxsf.te, and a policy package file, httpd_vboxsf.pp, have been generated in the current working directory. So, we proceed to install the new policy module as follows:
$ semodule -i httpd_vboxsf.pp
Note: we will install audit2allow via the setroubleshoot package.
When I run sudo audit2allow -w -a (from above), one of the many (repeated) entries include:
...
type=AVC msg=audit(**********.***:****): avc: denied { getattr } for pid=****
comm="httpd" path="/vagrant/webroot/index.php" dev="vboxsf" ino=** scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:vmblock_t:s0 tclass=file
Was caused by:
Missing type enforcement (TE) allow rule.
You can use audit2allow to generate a loadable module to allow this access
...
Note: the many repeated entries, have different pid, and audit values. But, the same ino value.
However, index.php has the following system context:
[vagrant@localhost webroot]$ pwd
/vagrant/webroot
[vagrant@localhost webroot]$ ls -aZ
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 .
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 ..
-rw-rw-r--. vagrant apache system_u:object_r:vmblock_t:s0 authorize.php
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 config
-rw-rw-r--. vagrant apache system_u:object_r:vmblock_t:s0 cron.php
-rw-rw-r--. vagrant apache system_u:object_r:vmblock_t:s0 error_redirect.php
-rw-rw-r--. vagrant apache system_u:object_r:vmblock_t:s0 .htaccess
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 includes
-rw-rw-r--. vagrant apache system_u:object_r:vmblock_t:s0 index.php
-rw-rw-r--. vagrant apache system_u:object_r:vmblock_t:s0 install.php
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 misc
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 modules
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 profiles
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 publication
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 scripts
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 sites
drwxr-xr-x. vagrant apache system_u:object_r:vmblock_t:s0 themes
-rw-rw-r--. vagrant apache system_u:object_r:vmblock_t:s0 update.php
-rw-rw-r--. vagrant apache system_u:object_r:vmblock_t:s0 web.config
-rw-rw-r--. vagrant apache system_u:object_r:vmblock_t:s0 xmlrpc.php
We attempted to create our own _Type Enforcement rule_:
[vagrant@localhost webroot]$ pwd
/vagrant/webroot
[vagrant@localhost webroot]$ sudo audit2allow -a
#============= httpd_t ==============
allow httpd_t vmblock_t:file getattr;
#============= unconfined_t ==============
allow unconfined_t init_t:service { enable disable };
[vagrant@localhost webroot]$ sudo audit2allow -a -M httpd_t
******************** IMPORTANT ***********************
To make this policy package active, execute:
semodule -i httpd_t.pp
[vagrant@localhost webroot]$ sudo semodule -i httpd_t.pp
[vagrant@localhost webroot]$ sudo audit2allow -a
#============= httpd_t ==============
allow httpd_t vmblock_t:file read;
#!!!! This avc is allowed in the current policy
allow httpd_t vmblock_t:file getattr;
#============= unconfined_t ==============
#!!!! This avc is allowed in the current policy
allow unconfined_t init_t:service { enable disable };
Then, we sudo systemctl restart httpd, just to be safe, and receive a 500 Server Error:
We will disable the selinux policy, we created above, then remove the corresponding file(s):
[vagrant@localhost webroot]$ semodule -d httpd_t
[vagrant@localhost webroot]$ rm httpd_t.pp httpd_t.te
Then, we'll set selinux to permissive mode:
[vagrant@localhost webroot]$ sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
[vagrant@localhost webroot]$ sudo setenforce permissive
[vagrant@localhost webroot]$ sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: permissive
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
this will allow us to install drupal, to allow the httpd stack to run through the motions, before we create the policy from the logged AVC's:
This also means that I need to temporarily change the Vagrantfile from:
...
## set permission for drupal 'settings*.php'
config.vm.synced_folder './src/default', '/vagrant/webroot/sites/default',
owner: 'vagrant',
group: 'apache',
mount_options: ['dmode=775', 'fmode=444']
...
to the following, with a successive vagrant reload command, in order to allow drupal to complete an installation:
...
## set permission for drupal 'settings*.php'
config.vm.synced_folder './src/default', '/vagrant/webroot/sites/default',
owner: 'vagrant',
group: 'apache',
mount_options: ['dmode=775', 'fmode=664']
...
We created our policy, loaded it, then enabled it:
[vagrant@localhost webroot]$ sudo grep httpd_t /var/log/audit/audit.log | audit2allow -M httpd_t
[vagrant@localhost webroot]$ sudo semodule -i httpd_t.pp
[vagrant@localhost webroot]$ sudo semodule -e httpd_t
Then, we enabled selinux:
[vagrant@localhost webroot]$ sudo setenforce enforcing
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
and, notice that the policies are being implemented:
[vagrant@localhost ~]$ sudo audit2allow -a
#============= httpd_t ==============
#!!!! This avc is allowed in the current policy
allow httpd_t postfix_etc_t:file { read getattr open };
#!!!! This avc is allowed in the current policy
allow httpd_t postfix_master_t:unix_stream_socket connectto;
#!!!! This avc is allowed in the current policy
allow httpd_t postfix_public_t:sock_file { write getattr };
#!!!! This avc is allowed in the current policy
allow httpd_t postfix_spool_t:dir { write remove_name add_name };
#!!!! This avc is allowed in the current policy
allow httpd_t postfix_spool_t:file { rename write getattr setattr read create open };
#!!!! This avc is allowed in the current policy
allow httpd_t unreserved_port_t:tcp_socket name_connect;
#!!!! This avc is allowed in the current policy
allow httpd_t vmblock_t:dir { write rmdir setattr read remove_name create add_name };
#!!!! This avc is allowed in the current policy
allow httpd_t vmblock_t:file { write getattr setattr read create open };
#============= unconfined_t ==============
allow unconfined_t init_t:service { enable disable };
The big trivial take-away, remember to enable the policy rule created via sudo semodule -e httpd_t
Now, we can access our drupal webpage with selinux enabled:
The selinux configurations are persistent, across vagrant halt, followed by vagrant up. So, we'll create a puppet script to run our httpd_t.pp selinux file (created earlier), along with enabling the corresponding module, containing our custom policy rule(s).
Hi @jeff1evesque
Thank you for opening an issue. I read through the thread, and it sounds like you were able to get things enabled, and it looks like the issue was related to selinux and httpd, not Vagrant. Is that correct?
Hi @sethvargo,
Yes sir. I wasn't sure initially, where this issue would lead me. Thank you!
Finally, How to solve this error.I also have 403 forbidden error .
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
We will disable the selinux policy, we created above, then remove the corresponding file(s):
Then, we'll set selinux to permissive mode:
this will allow us to install drupal, to allow the
httpdstack to run through the motions, before we create the policy from the logged AVC's:This also means that I need to temporarily change the
Vagrantfilefrom:to the following, with a successive
vagrant reloadcommand, in order to allow drupal to complete an installation: