Throughout the security holiday calendar, we’ve looked at modules for enforcing security requirements. Writing the policy to achieve these security hardening goals is easy. By learning how, you can write policy (or modules) for any requirements, including those specific to your organization. In this blog post, we’ll take a look at five beginner-level examples to get you started, focusing on the most common resources to manage with CFEngine; files and packages. All file names, package names, etc. are just examples and should be easy to modify to your desire.
The examples are available in this repository:
https://github.com/olehermanse/five-security-hardening-examples
If you are unsure about how to write and deploy policy, we recommend the getting started guide in our docs.
Installing a package
This policy ensures the aide
package is installed, using the default package manager (yum
, apt
, etc.) to install it if necessary:
bundle agent install_aide
{
packages:
"aide" -> { "OpenSCAP", "CCE-27096-7" }
policy => "present";
}
Hint: The stakeholders ( -> { "OpenSCAP", "CCE-27096-7" }
) document where this requirement comes from.
It’s purely for documentation purposes, the policy would behave the same without this part.
Uninstalling a package
It is quite common to want to get rid of packages and configuration files to eliminate potential security issues and reduce attack surface.
squid
is an example of a package you don’t want installed, as running a proxy server can open you up for attack and circumvent network security measures.
From the example above, just switch present
with absent
, to ensure the package is not installed:
bundle agent uninstall_squid
{
packages:
"squid" -> { "OpenSCAP", "CCE-80286-8" }
policy => "absent";
}
Hint: CFEngine checks the current state to determine if it needs to make changes.
For this promise, if squid
is not installed, nothing will be done.
Deleting a file
Ensuring a file does not exist is quite similar to the example with a package:
bundle agent delete_shosts_equiv
{
files:
"/etc/ssh/shosts.equiv" -> { "OpenSCAP", "CCE-80513-5" }
delete => tidy;
}
Enforcing access to a file
Many system-wide configuration files can leak information or be used for privilege escalation. Enforcing strict access to them, through file ownership and permission bits is important:
bundle agent etc_cron_allow_access
{
files:
"/etc/cron.allow" -> { "OpenSCAP", "NIST", "CCI-000366" }
perms => mog("640", "root", "root"),
if => fileexists("/etc/cron.allow");
}
There are different ways of specifying the perms
for a file.
In the example above, we’ve used mog
to specify the Mode, Owner, and Group.
Hint: Checking if the file exists is often not strictly necessary. Adding it can make your policy more explicit and easy to understand. Even someone completely unfamiliar with CFEngine can read the snippet above, and understand that this is only relevant when the file actually exists.
Managing the content of a file
The /etc/motd
file is used to show useful information to users after logging in.
CFEngine can ensure both the content and the permissions of this file are correct:
bundle agent etc_motd
{
files:
"/etc/motd" -> { "OpenSCAP", "CCE-83737-7", "CCE-83727-8", "CCE-83337-6" }
perms => mog("644", "root", "root"),
content => "$(sys.host) - Contact: Alice@example.com";
}
Hint: In the example above, we’ve used variable expansion;
$(sys.host)
gets replaced by the hostname on each machine in the infrastructure.
Testing it
In order to test our policy, we can introduce some issues and watch CFEngine fix them:
touch /etc/ssh/shosts.equiv
touch /etc/cron.allow
chmod 0777 /etc/cron.allow
echo "blah" > /etc/motd
apt install -y squid >/dev/null 2>/dev/null
apt remove -y aide >/dev/null 2>/dev/null
cf-agent -KI
Running the script above we see that CFEngine fixes 5 issues:
info: Deleted file '/etc/ssh/shosts.equiv'
info: Object '/etc/cron.allow' had permissions 0777, changed it to 0640
info: Updated content of '/etc/motd' with content 'ip-172-31-6-47 - Contact: Alice@example.com'
info: Successfully installed package 'aide'
info: Successfully removed package 'squid'
Conclusion
Hopefully, these examples give you some ideas for how to improve the security of your infrastructure. This is just the beginning, take a look at processes, services, users, and even custom promise types for what other things you can work with.
Security recommendation: Implement reports and automation to enforce strict security requirements for your organization. When ready-to-use modules are not available, write policy to do exactly what you need. In addition to your certification requirements, look at STIGs, NIST / NCP, OpenSCAP, CIS benchmarks, Lynis, and other similar resources for ideas on what security checks to implement.