Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add answerfile SELinux mode option #61

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions example.answerfile.ini
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ disk_image=/root/OracleLinux-R8-U7-x86_64-dvd.iso
distro=ol
version=8.7
kernel=5.4.17-2136.302.6.1.el8uek.x86_64
# SELinuxMode can be 'enforcing', 'permissive' or 'disabled'. Default is "enforcing".
#selinuxmode=enforcing

# Generic. If a node.XX section does not have one of these options, they are obtained here.
# Comment if you don't want to use generic options. In this case, you MUST fulfill all the node.XX options.
Expand Down
3 changes: 3 additions & 0 deletions include/cloysterhpc/answerfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef CLOYSTERHPC_ANSWERFILE_H_
#define CLOYSTERHPC_ANSWERFILE_H_

#include "cluster.h"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

< >

#include "os.h"
#include <boost/asio.hpp>
#include <cloysterhpc/inifile.h>
Expand Down Expand Up @@ -52,6 +53,7 @@ class AnswerFile {
OS::Distro distro;
std::string version;
std::string kernel;
Cluster::SELinuxMode selinuxmode;
};

struct AFNode {
Expand Down Expand Up @@ -91,6 +93,7 @@ class AnswerFile {
void loadNodes();
AFNode loadNode(const std::string& section);
AFNode validateNode(AFNode node);
Cluster::SELinuxMode checkSELinuxMode(const std::string& mode);

template <typename T>
void validateAttribute(const std::string& sectionName,
Expand Down
2 changes: 2 additions & 0 deletions include/cloysterhpc/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ void backupFile(std::string_view filename);
void changeValueInConfigurationFile(
const std::string&, const std::string&, std::string_view);
void addStringToFile(std::string_view filename, std::string_view string);
void setFilePermissions(
const std::string& filename, mode_t mode = S_IRUSR | S_IWUSR);

} /* namespace cloyster */

Expand Down
22 changes: 22 additions & 0 deletions include/cloysterhpc/selinux/selinux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Created by Lucas Gracioso <[email protected]>
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef CLOYSTERHPC_SELINUX_H_
#define CLOYSTERHPC_SELINUX_H_

#include "cloysterhpc/cluster.h"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

< >

#include <cloysterhpc/selinux/xCAT/xcatpolicies.h>

class SELinux {
private:
void configurexCATPolicies();
void configurexCATPolicyFile();
void configurexCATgenimagePolicyFile();
void configurexCATrsyncPolicyFile();
public:
void configureProvisioner(Cluster::Provisioner provisioner);
};

#endif // CLOYSTERHPC_SELINUX_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module xCAT-genimage-ldconfig-rw-tmpdir 1.0;

require {
type initrc_tmp_t;
type ldconfig_t;
class lnk_file { create getattr unlink };
class file { create rename setattr };
class dir { add_name read remove_name write };
}

#============= ldconfig_t ==============

allow ldconfig_t initrc_tmp_t:dir { add_name read remove_name write };
allow ldconfig_t initrc_tmp_t:file { create rename setattr };
allow ldconfig_t initrc_tmp_t:lnk_file create;
allow ldconfig_t initrc_tmp_t:lnk_file { getattr unlink };
12 changes: 12 additions & 0 deletions include/cloysterhpc/selinux/xCAT/xCAT-httpd-read-tftpdir.te
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module xCAT-httpd-read-tftpdir 1.0;

require {
type httpd_t;
type tftpdir_t;
class dir read;
class file { getattr open read };
}

#============= httpd_t ==============
allow httpd_t tftpdir_t:dir read;
allow httpd_t tftpdir_t:file { getattr open read };
68 changes: 68 additions & 0 deletions include/cloysterhpc/selinux/xCAT/xCAT-rsync.te
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
module xCAT-rsync 2.0;

require {
class capability dac_override;
class chr_file write;
class dir { getattr search write };
class file { execute execute_no_trans getattr map open read };
class lnk_file read;
class tcp_socket name_connect;
type bin_t;
type dhcpd_t;
type etc_t;
type groupadd_t;
type httpd_sys_content_t;
type kpatch_exec_t;
type krb5_keytab_t;
type rhsmcertd_t;
type root_t;
type rsync_t;
type rsync_t;
type setfiles_t;
type shell_exec_t;
type ssh_exec_t;
type ssh_home_t;
type ssh_keysign_exec_t;
type ssh_port_t;
type sshd_key_t;
type sysctl_net_t;
type useradd_t;
}

#============= rsync_t ==============

allow rsync_t bin_t:file map;
allow rsync_t bin_t:file { execute execute_no_trans map };
allow rsync_t bin_t:file { execute execute_no_trans };
allow rsync_t etc_t:dir write;
allow rsync_t krb5_keytab_t:dir search;
allow rsync_t self:capability dac_override;
allow rsync_t shell_exec_t:file map;
allow rsync_t shell_exec_t:file { execute execute_no_trans map };
allow rsync_t shell_exec_t:file { execute execute_no_trans };
allow rsync_t ssh_exec_t:file { execute execute_no_trans map open read };
allow rsync_t ssh_home_t:dir { getattr search };
allow rsync_t ssh_home_t:file { getattr open read };
allow rsync_t ssh_keysign_exec_t:file { execute execute_no_trans getattr map open read };
allow rsync_t ssh_keysign_exec_t:file { execute execute_no_trans };
allow rsync_t ssh_keysign_exec_t:file { getattr map open read };
allow rsync_t ssh_port_t:tcp_socket name_connect;
allow rsync_t sshd_key_t:file { getattr open read };

#============= dhcpd_t ==============
allow dhcpd_t sysctl_net_t:dir search;

#============= groupadd_t ==============
allow groupadd_t httpd_sys_content_t:chr_file write;
allow groupadd_t httpd_sys_content_t:lnk_file read;

#============= rhsmcertd_t ==============
allow rhsmcertd_t kpatch_exec_t:file getattr;
allow rhsmcertd_t root_t:file read;

#============= setfiles_t ==============
allow setfiles_t httpd_sys_content_t:chr_file write;

#============= useradd_t ==============
allow useradd_t httpd_sys_content_t:chr_file write;
allow useradd_t httpd_sys_content_t:lnk_file read;
21 changes: 21 additions & 0 deletions include/cloysterhpc/selinux/xCAT/xcatpolicies.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Created by Lucas Gracioso <[email protected]>
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef CLOYSTERHPC_XCATPOLICIES_H_
#define CLOYSTERHPC_XCATPOLICIES_H_

constexpr const char* xCATSELinuxPolicyFile =
#include "cloysterhpc/selinux/xCAT/xCAT-httpd-read-tftpdir.te"
;

constexpr const char* xCATgenimageSELinuxPolicyFile =
#include "cloysterhpc/selinux/xCAT/xCAT-genimage-ldconfig-rw-tmpdir.te"
;

constexpr const char* xCATrsyncSELinuxPolicyFile =
#include "cloysterhpc/selinux/xCAT/xCAT-rsync.te"
;

#endif // CLOYSTERHPC_XCATPOLICIES_H_
15 changes: 15 additions & 0 deletions src/answerfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,19 @@ void AnswerFile::loadHostnameSettings()
= m_ini.getValue("hostname", "domain_name", false, false);
}

Cluster::SELinuxMode AnswerFile::checkSELinuxMode(const std::string& mode)
{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a switch case statement.

if (mode == "enforcing") {
return Cluster::SELinuxMode::Enforcing;
} else if (mode == "permissive") {
return Cluster::SELinuxMode::Permissive;
} else if (mode == "disabled") {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have a method to ignore case when comparing strings. It will avoid bugs where the user selects Disabled and disabled. That should not be an issue in a TUI interface, but on an answerfile it is.

return Cluster::SELinuxMode::Disabled;
} else {
return Cluster::SELinuxMode::Enforcing;
}
}

void AnswerFile::loadSystemSettings()
{
system.disk_image = m_ini.getValue("system", "disk_image", false, false);
Expand All @@ -185,6 +198,8 @@ void AnswerFile::loadSystemSettings()

system.version = m_ini.getValue("system", "version", false, false);
system.kernel = m_ini.getValue("system", "kernel", false, false);
system.selinuxmode = checkSELinuxMode(
m_ini.getValue("system", "selinuxmode", true, false));
}

AnswerFile::AFNode AnswerFile::loadNode(const std::string& section)
Expand Down
8 changes: 8 additions & 0 deletions src/cluster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <regex>

#ifndef NDEBUG
#include "cloysterhpc/selinux/selinux.h"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it's inside NDEBUG?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDE did it when included. I'll change.

#include <fmt/format.h>
#endif

Expand Down Expand Up @@ -503,6 +504,7 @@ void Cluster::fillData(const std::string& answerfilePath)

setTimezone(answerfile.time.timezone);
setLocale(answerfile.time.locale);
setSELinux(answerfile.system.selinuxmode);

this->m_headnode.setHostname(answerfile.hostname.hostname);
setDomainName(answerfile.hostname.domain_name);
Expand Down Expand Up @@ -605,6 +607,12 @@ void Cluster::fillData(const std::string& answerfilePath)
setProvisioner(Provisioner::xCAT);
m_headnode.setOS(nodeOS);

// SELinux policies
if (getSELinux() != SELinuxMode::Disabled) {
SELinux SELinuxConfigurer;
SELinuxConfigurer.configureProvisioner(getProvisioner());
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Configurer is a very bad word. Usually the term used is Setup.

}

LOG_TRACE("Configure Nodes")
for (auto node : answerfile.nodes.nodes) {

Expand Down
13 changes: 13 additions & 0 deletions src/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,17 @@ void addStringToFile(std::string_view filename, std::string_view string)
LOG_DEBUG("Added line(s):\n{}\n => to file: {}", string, filename)
}

/**
*
* @param filename The filename
* @param mode The wanted permissions (mode). By default it is set to 0600.
*/
void setFilePermissions(const std::string& filename, mode_t mode)
{
if (chmod(filename.c_str(), mode) != 0) {
throw std::runtime_error(
fmt::format("Error setting permissions on file: {}", filename));
}
}

} // namespace cloyster
82 changes: 82 additions & 0 deletions src/services/selinux.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Created by Lucas Gracioso <[email protected]>
* SPDX-License-Identifier: Apache-2.0
*/

#include "cloysterhpc/selinux/selinux.h"
#include "cloysterhpc/functions.h"
#include "cloysterhpc/services/log.h"

void SELinux::configurexCATPolicies()
{
LOG_TRACE("Configuring xCAT SELinux policies")
configurexCATPolicyFile();
configurexCATgenimagePolicyFile();
configurexCATrsyncPolicyFile();
}

void SELinux::configurexCATPolicyFile()
{
// Create SELinux policy file for xCAT
const std::string file = "/root/xCAT-httpd-read-tftpdir.te";
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a /opt/cloysterhpc directory right? We should use it instead of /root.

cloyster::addStringToFile(file, xCATSELinuxPolicyFile);
cloyster::setFilePermissions(file);

// Install SELinux policy file for xCAT
std::string combinedCommands
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing constexpr.

= "checkmodule -M -m -o /root/xCAT-httpd-read-tftpdir.mod "
"/root/xCAT-httpd-read-tftpdir.te && "
"semodule_package -o /root/xCAT-httpd-read-tftpdir.pp -m "
"/root/xCAT-httpd-read-tftpdir.mod && "
"semodule -i /root/xCAT-httpd-read-tftpdir.pp && "
"semanage fcontext -a -t httpd_sys_content_t '/install(/.*)?' && "
"restorecon -R /install && "
"rm -rf /root/xCAT-httpd-read-tftpdir*";

cloyster::runCommand(combinedCommands);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work? && is a shell thing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats wrong with it?

}

void SELinux::configurexCATgenimagePolicyFile()
{
// Create SELinux genimage policy file for xCAT
const std::string file = "/root/xCAT-genimage-ldconfig-rw-tmpdir.te";
cloyster::addStringToFile(file, xCATgenimageSELinuxPolicyFile);
cloyster::setFilePermissions(file);

// Install SELinux genimage policy file for xCAT
std::string combinedCommands
= "checkmodule -M -m -o /root/xCAT-genimage-ldconfig-rw-tmpdir.mod "
"/root/xCAT-genimage-ldconfig-rw-tmpdir.te && "
"semodule_package -o /root/xCAT-genimage-ldconfig-rw-tmpdir.pp -m "
"/root/xCAT-genimage-ldconfig-rw-tmpdir.mod && "
"semodule -i /root/xCAT-genimage-ldconfig-rw-tmpdir.pp && "
"rm -rf /root/xCAT-genimage-ldconfig*";

cloyster::runCommand(combinedCommands);
}

void SELinux::configurexCATrsyncPolicyFile()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really dislike this naming, it looks like procedural code. Because the function name is too long and too specific it's looks like a function, and not a method in the way we refer in OOP.

To be clear, the issue isn't exactly the name, the name is the result of the issue. That's not done as an OOP code.

{
// Create SELinux rsync policy file for xCAT
const std::string file = "/root/xCAT-rsync.te";
cloyster::addStringToFile(file, xCATrsyncSELinuxPolicyFile);
cloyster::setFilePermissions(file);

// Install SELinux rsync policy file for xCAT
std::string combinedCommands
= "checkmodule -M -m -o /root/xCAT-rsync.mod /root/xCAT-rsync.te && "
"semodule_package -o /root/xCAT-rsync.pp -m /root/xCAT-rsync.mod && "
"semodule -i /root/xCAT-rsync.pp && "
"rm -rf /root/xCAT-genimage-ldconfig*";

cloyster::runCommand(combinedCommands);
}

void SELinux::configureProvisioner(Cluster::Provisioner provisioner)
{
switch (provisioner) {
case Cluster::Provisioner::xCAT:
configurexCATPolicies();
break;
}
}
Loading