blog

Using ClusterControl Advisor to Create Checks for SELinux and Meltdown/Spectre: Part One

Paul Namuag

Published

We previously showed you how to create your first database advisor in ClusterControl. Now let’s see how we can create a security advisor to check for SELinux and Meltdown/Spectre. We will be using the ClusterControl Developer Studio for this. The ClusterControl DSL handles the call for our shell scripts to be invoked and do the checks.

Since this is a larger topic, we have separated into two parts. First part, let’s try to embed SELinux check and see how we can achieve this. Basically, there are certain cases where we do not need SELinux enabled, specially with database nodes such MySQL/MariaDB/MongoDB/PostgreSQL. When running these nodes in production, they are best kept within a private network. This blog does not advocate that you should disable SELinux everywhere, but in certain cases, this security module can cause issues with your production databases. So let’s begin!

If you have been through our previous blogs, ClusterControl Developer Studio relies on ClusterControl Domain Specific Language, or CCDSL or DSL for short. Part of the functions that DSL provides is host.system(cmd) function. You can check our DSL page for more functions and get familiar with its language specification. This is where we rely on simply invoking the shell command and manage it through our Developer Studio and handle the command output through CCDSL.

First, let’s create the file. Go to Cluster > Manage > Developer Studio > New and do the following:

This will create a folder and a sub-folder “myadvisors/host” and a file called selinux-checker.js.

For this exercise, I have uploaded the scripts to github which can be found here https://github.com/paulnamuag/s9s_CCDSL_scripts. So let’s paste the contents of the file selinux-checker.js from the repository I have uploaded.

Always do not forget to frequently save your work here if you are working on the Developer Studio workspace, otherwise you’ll lose your modifications/changes if you lose your session or if you accidentally close the browser or tab.

Now let’s go to the code tackling the important ones that I would like to share with you! If you look from lines 3 – 8,

var DESCRIPTION="This advisor is to check if SELinux is set to Enforcing otherwise"
                " it's disabled or set as Permissive";
var TITLE="SELinux Check";
var ADVICE_WARNING="Warning!!! getenforce reveals it is set to Enforcing. Run "setenforce permissive" "
                   "or edit /etc/selinux/config and set SELINUX=disabled but this requires a host restart" ;
var ADVICE_OK="SELinux is Permissive or disabled" ;

these are similar to the JavaScript variable initialization which is, in this case, declared as global. However, the use in this script is important as it’s being purposely assigned to be used in the Advisors results page which we will see in the following section.

Going through the main() function, in line 12, we are invoking:

var hosts     = cluster::mySqlNodes();

since I want only to check my MySQL nodes excluding the ClusterControl monitor host. So if you want to check and grab all the nodes, then use cluster::hosts(). More of these functions are in the Cluster Functions section of the CCDSL manual.

The script is very easy to understand if you are a JavaScript programmer or at least understand how JavaScript works. So we’ll take a shortcut and move on to line 33,

retval = host.system("/sbin/getenforce |tr -d 'n'");

The line above will invoke /sbin/getenforce |tr -d 'n' Linux command which basically means to retrieve SELinux state and then remove a trailing newline. The host.system() will return an array value consisting of key names which are “success”, “result”, and “errorMessage”.

The lines from 35 – 79, this if/else statement basically handles the return value from function host.system(). If we focus on lines 42 – 44,

advice.setSeverity(Ok);
advice.setJustification(msg);
advice.setAdvice("Nothing to do.");

we’re setting the properties for the object advice variable of type CmonAdvice(). These properties are used to setup our Advisor alerts. Take note that there are 4 types of enumerated types of Severity, these are Undefined, Ok, Warning, and Critical. These are used to set messages in our Advisor results page. Lastly, let’s move on to lines 75 – 78,

advice.setHost(host);
advice.setTitle(TITLE);
advisorMap[idx]= advice;
print(advice.toString("%E"));

advice.setHost() defines which host is currently being checked for SELinux. Then advice.setTitle(<title>) is the name or title used in our Advisors results page. Line 77 sets the advisorMap associative array with the object advice which is being returned to our CMON API as seen in line 80. Then in line 78, we are printing the advice object in multi line description which contains multiple properties.

Now, let’s hit button “Compile and run“. This would print in the Messages tab as seen below:

Looking good now? Well, let’s see and schedule the advisor, let say run this check for every 30 minutes and set tags as myadvisors;host;selinux-checker.

The Advisors Results

Since we had the our SELinux Check advisor scheduled, let’s now go to Cluster > Performance > Advisors. Then select the tags we had previously defined which are myadvisors and selinux-checker.

You’ll see here all of your advisors, whether they are provided by Severalnines or are custom-made by you. Once it’s scheduled, it’ll be viewed here. This is one of the coolest part, because here you can check and monitor the advisors that you want to focus on. You can prioritise the most important ones by enabling them, and disable the ones that you no longer need.

In Part 2 of this blog, we’ll go over creating a more challenging one to check for Meltdown/Spectre and incorporate alarms. We’ll also show you how to debug your CCDSL code like a pro.

Subscribe below to be notified of fresh posts