hashicorp / vagrant

Vagrant is a tool for building and distributing development environments.
https://www.vagrantup.com
Other
26.32k stars 4.44k forks source link

'selinux' not supported in vagrant VM (Centos / Redhat 7.x) #6970

Closed jeff1evesque closed 8 years ago

jeff1evesque commented 8 years ago

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:

403

Note: though, this was attempted on Centos 7.x, it probably applies to Redhat 7.x.

jeff1evesque commented 8 years ago

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.

jeff1evesque commented 8 years ago

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/sda2 to 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 defcontext option defines that system_u:object_r:httpd_sys_content_t:s0 is "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_t type. 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.

jeff1evesque commented 8 years ago

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 the server:/export argument 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 vagrant mount_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 the sharename?

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

jeff1evesque commented 8 years ago

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']
...
jeff1evesque commented 8 years ago

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.
vagrant@127.0.0.1'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.
vagrant@127.0.0.1'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.
vagrant@127.0.0.1'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.
vagrant@127.0.0.1'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:
jeff1evesque commented 8 years ago

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':
vagrant@127.0.0.1'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
jeff1evesque commented 8 years ago

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.

jeff1evesque commented 8 years ago

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:

$ 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.

jeff1evesque commented 8 years ago

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
jeff1evesque commented 8 years ago

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:

server-error

jeff1evesque commented 8 years ago

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:

working

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']
...
jeff1evesque commented 8 years ago

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

jeff1evesque commented 8 years ago

Now, we can access our drupal webpage with selinux enabled:

drupal

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).

sethvargo commented 8 years ago

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?

jeff1evesque commented 8 years ago

Hi @sethvargo,

Yes sir. I wasn't sure initially, where this issue would lead me. Thank you!

zawnaingtun-mbridge commented 5 years ago

Finally, How to solve this error.I also have 403 forbidden error .

ghost commented 4 years ago

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.