Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

How custom SELinux policies secure servers and containers

October 10, 2023
Nikhil Mungale
Related topics:
ContainersLinuxSecurity
Related products:
Red Hat Enterprise Linux

Share:

    Security-Enhanced Linux (SELinux) is a robust security framework that enforces mandatory fine-grained access controls on Red Hat Enterprise Linux systems. When managing server fleets and running containers, the deployment of customized SELinux policies becomes essential for maintaining a strong security posture.

    Custom SELinux policies empower organizations to customize access controls according to their unique requirements. Although Linux distributions come with default SELinux policies, they may not address all the use cases or applications within an organization's environment. Deploying custom policies allows you to establish precise rules that align with your infrastructure and applications.

    This is the second article in our SELinux series. The first article described SELinux basics. This article demonstrates the creation and deployment of custom SELinux policies across server fleets and containerized environments, emphasizing the associated benefits and best practices.

    How to implement a custom policy

    Prerequisites:

    • RHEL server or workstation
    • Installed Podman

    The following example describes the steps to create custom policies for granting dedicated directory and file access to users and how to modify a policy file in the file's permissions and labels or context.

    1. Install the necessary dependency packages: policycoreutils, policycoreutils-devel, setools-console, setroubleshoot. Additionally, create a private_files directory to consolidate all content in one location.

    $mkdir private_files && cd private_files
    
    $sudo yum install policycoreutils policycoreutils-devel setools-console setroubleshoot -y
    Package policycoreutils-2.9-24.el8.x86_64 is already installed.
    Package policycoreutils-devel-2.9-24.el8.x86_64 is already installed.
    Package setools-console-4.3.0-3.el8.x86_64 is already installed.
    Package setroubleshoot-3.3.26-5.el8.x86_64 is already installed.
    Dependencies resolved.
    Nothing to do.
    Complete!

    2. Create a policy module file called private_files.te, where .te signifies type enforcement. Copy and paste the following content into the terminal to create the private_files.te file.

    cat <<'EOF' >> private_files.te
    policy_module(private_files, 1.0)
    require {
    type unconfined_t;
    type setroubleshootd_t;
    }
    type private_files_t;
    fs_associate(private_files_t);
    allow unconfined_t private_files_t:{dir file} relabelto;
    allow setroubleshootd_t private_files_t:{ dir file } getattr;
    EOF
    • policy_module: Module name.
    • require: Specify the domains that must be defined within the policy.
    • type: Declares new type.
    • fs_associate: Associate type with filesystem.
    • allow: Define specific allow rules for permitted actions while blocking all other actions.

    Establish a symbolic link to the makefile using these commands. This will ensure that the make command references the correct file.

    # ln -s /usr/share/selinux/devel/Makefile.
    # ls -l
    total 4
    lrwxrwxrwx. 1 root root  33 Aug 30 11:04 Makefile -> /usr/share/selinux/devel/Makefile
    -rwxrwxrwx. 1 root root 283 Aug 30 10:59 private_files.te

    3. Compile the policy files using the make command. This will produce a private_files.pp output file, which reads private_files.te and generates all required dependency files.

    # make private_files.pp
    Compiling targeted private_files module
    Creating targeted private_files.pp policy package
    rm tmp/private_files.mod tmp/private_files.mod.fc
    
    # ls
    Makefile  private_files.fc  private_files.if  private_files.pp  private_files.te  tmp

    4. Install the compiled file using the semodule -i command:

    # semodule -i private_files.pp

    5. Create a file to test the policies and assign full read and write permissions to it.

    # mkdir -m 777 /private

    6. Impose the label to a private directory using the chcon command:

    [root@SElinux private_files]# chcon -t private_files_t /private
    
    [root@SElinux private_files]# ls -Z /private
    ls: cannot access '/private': Permission denied

    Your statement is clear and effectively conveys the expected behavior of the custom policy.

    Fix the permissions

    7. Make changes in the policy file to grant access to the file and directory using the getattr (get attribute) syntax.

    policy_module(private_files, 1.0)
    require {
    type unconfined_t;
    type setroubleshootd_t;
    }
    
    type private_files_t;
    fs_associate(private_files_t);
    allow unconfined_t private_files_t:{dir file} { relabelto getattr };
    allow setroubleshootd_t private_files_t:{ dir file } getattr;

    8. As shown below, compile a new policy file with the make command.

    [root@SElinux private_files]# make private_files.pp
    Compiling targeted private_files module
    Creating targeted private_files.pp policy package
    rm tmp/private_files.mod tmp/private_files.mod.fc

    9. Uninstall the previous modules using the following command:

    [root@SElinux private_files]# semodule -r private_files
    libsemanage.semanage_direct_remove_key: Removing last private_files module (no other private_files module exists at another priority).

    10. Deploy the recently compiled.pp file by utilizing the -i flag.

    [root@SElinux private_files]# semodule -i private_files.pp

    11. To modify the label or context of a private folder, employ the chcon command.

    [root@SElinux private_files]# chcon -t private_files_t /private

    Inspect the labels of the following directory by employing the -Z flag.

    [root@SElinux private_files]# ls -Z /private
    ls: cannot open directory '/private': Permission denied

    12. Determine the root cause of the issue using the ausearch command, which conducts audits to identify problems and provide resolutions.

    [root@SElinux private_files]# ausearch -m avc -ts recent | audit2allow
    #============= setroubleshootd_t ==============
    #!!!! This avc is allowed in the current policy
    allow setroubleshootd_t private_files_t:dir getattr;
    
    #============= unconfined_t ==============
    
    #!!!! This avc is allowed in the current policy
    allow unconfined_t private_files_t:dir getattr;
    allow unconfined_t private_files_t:dir read;

    13. Transition SELinux to the permissive mode by executing the following command:

    [root@SElinux private_files]# setenforce 0

    14. Develop a bash script to facilitate all filesystem-related tasks seamlessly.

    cat << EOF >> test_script.sh
    ls -lZ /private
    chmod 1777 /private
    touch /private/file1
    echo hello > /private/file1
    echo hello >> /private/file1
    chmod o= /private/file1
    mkdir /private/dir1
    rmdir /private/dir1
    rm -f /private/file1
    chcon -t unconfined_t /private
    EOF

    15. Set permissions of the bash script to execute it using the bash command.

    [root@SElinux private_files]# chmod 777 test_script.sh
    [root@SElinux private_files]# bash test_script.sh
    total 0

    16. Conduct another audit of the activity within the private directory and determine the resolution.

    [root@SElinux private_files]# ausearch -m avc -ts recent | audit2allow
    #============= unconfined_t ==============
    allow unconfined_t private_files_t:dir { add_name create open read relabelfrom remove_name rmdir search setattr write };
    allow unconfined_t private_files_t:file { append create open setattr unlink write };
    allow unconfined_t self:dir relabelto;

    17. Apply the policy resolutions to the private_files.te file by executing the following command:

    [root@SElinux private_files]# ausearch -m avc -ts recent | audit2allow >> private_files.te

    18. After updating private_files.te, it will appear as follows:

    [root@SElinux private_files]# cat private_files.te
    policy_module(private_files, 1.0)
    require {
    type unconfined_t;
    type setroubleshootd_t;
    }
    
    type private_files_t;
    fs_associate(private_files_t);
    allow unconfined_t private_files_t:{dir file} { relabelto getattr };
    allow setroubleshootd_t private_files_t:{ dir file } getattr;
    allow unconfined_t private_files_t:dir { add_name create open read relabelfrom remove_name rmdir search setattr write };
    allow unconfined_t private_files_t:file { append create open setattr unlink write };
    allow unconfined_t self:dir relabelto;

    [Note: Remove the #== unconfined_t == line from the private_files.te file. ]

    19. Recompile the updated private_file.pp file once more to pull the newly made changes in the system.

    [root@SElinux private_files]# make private_files.pp
    Compiling targeted private_files module
    Creating targeted private_files.pp policy package
    rm tmp/private_files.mod tmp/private_files.mod.fc

    20. Uninstall the previous modules using the semodule -r command.

    [root@SElinux private_files]# semodule -r  private_files
    libsemanage.semanage_direct_remove_key: Removing last private_files module (no other private_files module exists at another priority).

    21. Apply the latest updates from private_file.pp.

    [root@SElinux private_files]# semodule -i private_files.pp

    22. Attempt to relabel it once more for a private directory.

    [root@SElinux private_files]# chcon -t private_files_t /private

    23. Re-enable the enforcing mode and assess the accessibility of directories and files.

    [root@SElinux private_files]# setenforce 1

    24. Check the file permissions using the following command:

    [root@SElinux private_files]# ls -lZd /private
    drwxrwxrwt. 2 root root unconfined_u:object_r:private_files_t:s0 6 Aug 30 11:44 /private

    25. As anticipated, we can now access the files and directories and make changes as needed. After manipulating the SELinux policies.

    [root@SElinux private_files]# touch /private/file1
    [root@SElinux private_files]# echo hello > /private/file1
    [root@SElinux private_files]# cat /private/file1
    hello

    Deploy SELinux configurations to multiple systems

    To uphold the highest level of security practices, it is essential to keep the server updated and maintain consistent security configurations. However, manually performing this process can be time-consuming and labor-intensive. To address the challenges associated with such scenarios, the semanage utility proves invaluable. This utility enables the effortless import and export of configuration files (.mode), simplifying the management of security configurations.

    1. Before proceeding, please install the following dependency packages.

    #yum install policycoreutils-python-utils

    2. Use semanage to generate the configuration file with a.mod extension.

    #semanage export -f./my-selinux-settings.mod

    3. Use semanage to generate the configuration file with a.mod extension. To transfer.mod files across fleets of servers, various methods such as FTP, SFTP, SCP, and others can be employed. In this instance, we will utilize the scp command.

    #scp./my-selinux-settings.mod new-system-hostname:
    Or
    #scp -t server_a.pem my-selinux-settings.mod user@servera:/home/user/

    4. After transferring the files, access the new server using the SSH command.

    #ssh root@server_a
    Or
    #ssh -i server.pem user@server_a

    5. Use the semanage command to import the configuration file onto the new system.

    #semanage import -f./my-selinux-settings.mod

    [Note: This shared configuration file is compatible only with specific OS versions, such as RHEL 9 to RHEL 9 and RHEL 8 to RHEL 8.]

    Apply SELinux to the containers

    SELinux policies can be generated for containers using the udica package in the UBI8 image. The udica package enables you to create a customized security policy for precise control over a container's access to host system resources, including storage, devices, and the network. This capability helps prevent security violations and simplifies regulatory compliance when deploying containers.

    1. Before proceeding, please install the necessary dependency packages.

    #yum install -y udica

    2. Install a containerization tool such as Podman or Docker. We will be using Podman as the container tool.

    # yum install podman -y

    3. Launch the container using a UBI8 image with volume mounts for the /home directory (read-only permissions) and the /var/spool directory (read and write permissions). Additionally, expose port 80.

    #podman run --env container=podman -v /home:/home:ro -v /var/spool:/var/spool:rw -p 80:80 -dit ubi8 bash

    4. Inspect the running container using the provided Podman command and collect the CONTAINER ID.

    #podman ps

    5. Gather all running container policies into a .json file.

    # podman inspect 567a363etfle > container.json
    
    # udica -j container.json my_container
    Policy my_container with container id 567a363etfle created!

    6. Load the policy module from the udica output in the previous step.

    #semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}

    7. Stop the container using the podman stop command, and then start it again with the --security-opt label=type:my_container.process option.

    #podman stop 567a363etfle
    
    #podman run --security-opt label=type:my_container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -p 80:80 -dit ubi8 bash

    Validating SELinux in containers

    8. Verify that the container is running with the my_container.process type, and access the running container using exec.

    # ps -efZ | grep my_container.process
    
    # podman exec -it 567a363etfle bash

    9. Verify that SELinux is functioning properly. Proceed to perform vulnerability testing activities within the running container.

    Install the nmap-ncat package in the container and attempt to redirect port 80 to port 2567.

    [root@567a363etfle]# cd /var/spool
    [root@567a363etfle]# yum install nmap-ncat
    [root@567a363etfle]# nc -lvp 80
    ...
    Ncat: Listening on :::80
    Ncat: Listening on 0.0.0.0:80
    [root@567a363etfle]# nc -lv- 2567
    ...
    Ncat: bind to :::2567: Permission denied. QUITTING.

    As expected, SELinux is successfully preventing security risk activities within the containers as well.

    Find more resources

    For a deeper and practical understanding of Red Hat Enterprise Linux, you can engage in thoughtfully curated hands-on labs by Red Hat. Red Hat Universal Base Images (UBI) are container-based and operating system images with complementary runtime languages and packages. Try Red Hat UBI on curated Red Hat UBI hands-on lab.

    In this article, we have meticulously crafted bespoke SELinux policies and seamlessly deployed them across an extensive fleet of servers. Additionally, we have seamlessly integrated these policies into containers leveraging the UBI8 container image.

    Furthermore, you have the option to obtain tailored Red Hat Enterprise Linux images designed for AWS, Google Cloud Platform, Microsoft Azure, and VMware, facilitating their seamless deployment on your chosen platform.

    Related Posts

    • How SELinux improves Red Hat Enterprise Linux security

    • 3 steps toward improving container security

    • How the new RHEL 9.2 improves the developer experience

    Recent Posts

    • How to run AI models in cloud development environments

    • How Trilio secures OpenShift virtual machines and containers

    • How to implement observability with Node.js and Llama Stack

    • How to encrypt RHEL images for Azure confidential VMs

    • How to manage RHEL virtual machines with Podman Desktop

    What’s up next?

    Read Podman in Action for easy-to-follow examples to help you learn Podman quickly, including steps to deploy a complete containerized web service.

    Get the e-book
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue