Keeping your server secure
Puppet Master must be protected well. It is a high-risk asset. With Puppet, you can install software on all your servers and clients. Puppet agents on Linux and Windows run with root and admin rights respectively. Think about a scenario where a hacker gets control of it. He can easily run any command, install backdoors, and fully compromise your IT infrastructure.
I suggest using the Ubuntu Server version that does not have a graphical user interface. This will ensure that there will not be much unnecessary software on your Puppet Master. Having only the necessary software on it helps you to have a more secure server, and also to keep the performance higher.
Note
Security rule:
Do not install any software that is not necessary. If vulnerable software does not exist, it cannot be attacked.
Backups
Keep frequent backups of your server.
There are many good backup solutions such as Backup Exec and Veeam. There are also hardware level backup solutions for storage devices. As a last option, you can also use free backup solutions such as Burp backup or a version control system (VCS). VCS will only back up your code and configuration.
Backup solutions and how to handle them is out of the scope of the book. Every company and system administrator has or should have their backup solution. If you do not have one, it is really time to implement one of the solutions as soon as possible. Without backups, your most important concern and risk will be business continuity.
Keeping your server up to date
Every day we see that there are new vulnerabilities, and with new security updates they are patched. So you must have a good policy of updates. The updates are very easy with Ubuntu; you only run two commands, as follows:
$ sudo apt-get update $ sudo apt-get upgrade
I will not explain these commands again. You can check the section Installing Puppet in this chapter to see the details if you need.
Before updating your server, ensure that in case of problems, you can go back. If you are using a virtual machine, such as Puppet Master, take a snapshot before the updates. If you use hardware, take a new backup before you start.
Lastly, it is also a good idea to have a development environment. Testing the updates in development and then updating the production server would be a good practice.
Do not enable root account
Some administrators do not feel happy about entering a sudo
command and password whenever there is a need for root privilege. To simply bypass this problem, they enable the root account and use it for every task.
The problem with using the root account is that, you have many processes and software running with root privileges. Assuming that one of them is vulnerable, and a hacker targets your server. When the hacker uses this vulnerability and opens a shell, the privileges that he will have are directly related to the process. So, if the process runs with root privileges, the hacker gains root access. Root access implies total control of the server. If the process is using a limited user account, the hacker will gain these privileges. This means that he still has a long way to go and find some way to escalate the privileges.
Also, when you use the root account, you also need to protect the server from yourself. The root account can do everything; with great power comes great responsibility. If you do something wrong, accidentally, you may need to restore your server from a backup. If you do not have a backup, things may get worse.
Always use a limited account and use sudo
only when needed. This will protect you from hackers and also from yourself.
Check status of the root account, as follows:
$ sudopasswd root -S
If not locked, lock it using the following:
$ sudopasswd root –l
Note
From now on, in this chapter, all the following details are not related to the implementation and installation of Puppet. However, it is suggested to complete these steps in a live environment. When learning in a test environment, security may not be your initial concern. In this case, simply go to Chapter 2, Installing Puppet Agents
The user password policy
Another important point is to have a decent password policy. With the correct password policy, we will make it harder for the passwords to be cracked. In the Windows Group Policy, there are also settings for password policy. Thus, the Windows administrators can easily understand its necessity. Here are some points to improve upon.
Do not use old passwords that have been used before
To limit the old passwords that can be used, we need to edit the /etc/pam.d/common-password
file. PAM is Pluggable Authentication Modules. PAM enables us to change the authentication process of Linux.
$ sudonano /etc/pam.d/common-password password [success=1 default=ignore] pam_unix.so obscure sha512 remember=5
pam_unix.so
is the default PAM moduleobscure sha512
will encrypt the new passwords withsha512
success=1
skips the next ruleremember=5
will prevent the user from using the last five passwords
Using at least a 10 char complex password
To set more complex passwords, we will install the libpam-cracklib
library, as follows:
$ sudo apt-get install libpam-cracklib
After this, we again edit the /etc/pam.d/common-password
file as follows:
$ sudonano/etc/pam.d/common-password password requisite pam_cracklib.so retry=3 minlen=10 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1
retry=3
ensures that while setting the password, if the user cannot successfully set a password three times, thepasswd
command will abortminlen=10
is the minimum length for the passworddifok=3
is the minimum number of characters that must be different from those of the previous passworducredit=-1
sets the minimum number of required uppercase characters to 1lcredit=-1
sets the minimum number of required lowercase characters to 1dcredit=-1
sets the minimum number of required digits to 1ocredit=-1
sets the minimum number of required symbols to 1
Here are the /etc/pam.d/common-password
details after the changes:
Expiring password in 90 days
The password expiration details are in the /etc/login.defs
file. Change the value of PASS_MAX_DAYS
to 90
and it will be forced to update the password every 90 days, as follows:
$ sudonano/etc/login.defs PASS_MAX_DAYS 90
Locking account
This policy makes sure that any brute force attempt will fail, or need too much time to complete. We will lock the user account for 10 minutes, if five times there are consecutive login failures. For this purpose, we need to modify the /etc/pam.d/common-auth
file. After the lock and wait time, if the user successfully logs in with the correct password, the failed attempts counter will be reset to zero. Otherwise, each failed attempt after the lock will cause another 10 minutes of lock. So, I suggest here that you keep a backup user with the sudo rights, as follows:
$ sudonano/etc/pam.d/common-auth auth required pam_tally2.so deny=5 onerr=fail unlock_time=600
pam_tally2.so
is the PAM module that comes with Ubuntu installation and used for account locks.deny=5
is the setting used to set the number of failed logins to lock an account.onerr=fail
if something weird happens, the PAM login status will befail
orsuccess
. The default status isfail
.unlock_time=600
is the number of seconds after which the account will be unlocked.
After completing all the changes, restart your server with the reboot
command for all the changes to be applied. This is done as follows:
$ sudo reboot
You can check a user's login attempts with the following command:
$ sudo pam_tally2 -u username
pam_tally2
is the command for the login counter PAM-u
is used to set the user
Here is an example output after two unsuccessful login attempts:
If you want to reset the counter and unlock the user, you can use the following command. -r
switch is used to reset the failures counter.
$ sudo pam_tally2 -u username -r
Using SSH with key file to connect
This step makes sure that even if somebody gets your password, it will not be usable. Thus, we will use the SSH key files. The SSH key files are used to identify yourself to an SSH server using the public-key cryptography and challenge-response authentication. We will disable the password logon option and it will be only possible to connect with a key file. We will also put a password to the key file, to make sure that it is also not usable without the password.
Creating the public and private key
Use the ssh-keygen
command to generate the keys, as follows:
$ ssh-keygen
ssh-keygen
first asks for the folder to save the keys. Just push the Enter key and continue. The next question is the passphrase. Make sure that you enter a password. Using the password with your key makes sure that, when somebody gets your key, it will be unusable.
Now go to the .ssh
folder, as follows:
$ cd .ssh
Under this folder, you will see these two files:
id_rsa
: Private keyid_rsa.pub
: Public key
We need to add the details of the public key to a file called authorized_keys
. This will make it possible to log in with the private key.
$ cat id_rsa.pub >authorized_keys
- The
cat
command displays the content of a file in the terminal - The
>
symbol adds the content of a command output to a file and if the file has content, it will be overwritten - The
authorized_keys
is the file that will be required for thessh
connection with a key
Here is an example screenshot:
Change the authorized_keys file permissions, otherwise the key will not work. This is done as follows:
$ chmod 600 authorized_keys
This command will allow only the user to edit and write the file; any group or other users will not be able to change it.
Getting the key to your computer and converting it into the PuTTY format
Now, we need to get the contents of id_rsa
to our computer that we will use to connect to Puppet Master.
To do this, you can use FileZilla to connect and download the file. Or you can use any FTP client with SFTP support. Here is a screenshot for the SFTP connection definition:
You need to enter the following:
- Host: The server IP is
10.10.10.10
. This is the IP that we gave to our Puppet Master server while installing. - Protocol: SFTP.
- Logon Type: Normal.
- User: Your username.
- Password: Your password.
After you have filled the details, click the Connect button. When you connect, you will see your user folder and the .ssh
folder, as follows:
Download the id_rsa
file to your documents folder. After this, you need to convert the file with PuTTYgen.exe
. Open PuTTYgen.exe
and click the Load button. You also need to select the All Files (*.*) option, as shown here:
After you click it open, it will ask for the password. After this, click on Save private key and give a name to your key. I saved it as puppetmaster.ppk
. Now, we are ready to use this key to connect to Puppet Master.
To do it, first fill in the details as follows:
- Host Name:
username@ipaddress
- Port:
22
- Saved Sessions: Give a name for the session
Now go to SSH | Auth. Select the key file, as follows:
After this, go back to Session from the Category section and use the Save button. This will make sure that you can reuse the connection and do not have to define the same settings again.
Now you will be able to connect by double-clicking your saved session name. It will ask for the key file password and then you will be able to connect.
Connecting from Linux
To connect from Linux systems, you do not need to convert the private key. You can just connect from the terminal with the ssh
command, as follows:
$ sshusername@serverip -ikeyfile
When I change this command to my example, it will b
[email protected] -iid_rsa
Disabling the SSH logins with a password
This is our last step for SSH. After disabling the password login option, there will be no possibility for an hacker to use brute force against an account. Also, there will be no possibility to log in, even if the hacker knows the password.
We need to change the /etc/ssh/sshd_config
file to disable password, as follows:
$ sudonano /etc/ssh/sshd_config
Find the PasswordAuthentication
text, uncomment it, and set the value to no
.
After changing the value and saving the file, restart the ssh
service, as shown here:
$ sudo service ssh restart
Now, here is the output when I try to log in without the key:
The firewall rules
For the servers and clients, the rule for security is: "Deny all incoming connections and allow only those needed." Here are the steps:
- Check which ports to keep open
- Define the firewall rules
- Make the firewall rules persistent
Checking which ports to keep open
We will use netstat
to check the listening ports and running services. Here, we already know that for administrative purposes, we need to keep the SSH port 22 open. But we also need to check other ports that Puppet and Foreman are using. The command to check the listening ports and services is as follows:
$ sudonetstat -nlput
netstat
: The command to check network connections.n
flag: This shows addresses in the numeric formatl
flag: This shows only the listening portsp
flag: This shows the PID name of the program that the socket belongs tou
flag: This shows the UDP portst
flag: This shows the TCP ports
Here are the ports that we need to keep open:
22
:ssh
80,445
: HTTP and HTPPS ports to connect Foreman8443
: Foreman proxy is running on this port as a proxy8140
: Puppet Master listens to this port
You can also remember that in the section Installing Foreman when the installation finishes, it gives the details about the 8443
and 8140
ports.
Defining firewall rules
We will use iptables as the firewall. It comes preinstalled on the Ubuntu Server. First, let's check the rules that we have. If no rules are defined previously, all the policies will be in the ACCEPT
state. The commands to check the iptables rules are as follows:
$ sudoiptables -L -v
iptables
: This is the command to manage the firewallL
flag: This lists all rulesv
flag: Verbose output. This shows the rule options and packet counters
Allowing ingress traffic for the SSH port 22
We will accept traffic from any source when the destination port is port 22
. Here is the command:
$ sudoiptables -A INPUT -p tcp --dport 22 -j ACCEPT
-A
flag is used for adding rules.-p tcp
, herep
flag is for the protocol definition and TCP is the protocol.--dport 22
, here,dport
is the destination port definitions and the port is 22.-j ACCEPT
, here,j
flag tells what to do. Here, we accept the packet, if it matches the rule.
Allowing ingress traffic for HTTP port 80
We will accept traffic from any source when the destination port is port 80. Here is the command:
$ sudoiptables -A INPUT -p tcp --dport 80 -j ACCEPT
Allowing ingress traffic for HTTPS port 443
We will accept traffic from any source when the destination port is port 443. Here is the command:
$ sudoiptables -A INPUT -p tcp --dport 443 -j ACCEPT
Allowing ingress traffic for Foreman proxy port 8443
We will accept traffic from any source when the destination port is port 8443. Here is the command:
$ sudoiptables -A INPUT -p tcp --dport 8443 -j ACCEPT
Allowing ingress traffic for Puppetmaster port 8140
We will accept traffic from any source when the destination port is port 8140. Here is the command:
$ sudoiptables -A INPUT -p tcp --dport 8140 -j ACCEPT
Allowing all that is established from us
We need to define this rule. Otherwise, any traffic connection will not be complete. We will be able to send traffic outside, but never be able to get answers back. So, we will allow any incoming packet that is related to our outgoing traffic.
$ sudoiptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-m
: This flag is used to match certain conditions. It can be used with different types of modules.state --state ESTABLISHED,RELATED
:state
is the module name that checks the statuses of a connection. Here, we allow any connection that is related to the established and related connections.
Denying all the incoming traffic
This time, we do not give any protocol or port number. So, this means that all the input traffic will be dropped.
$ sudoiptables -P INPUT DROP
After completing the rules, let's check the iptables rules again:
As you can see in the preceding screenshot, all the rules are defined in the order that we defined.
Note
IMPORTANT:
Define the "deny all" rule last. The order of the rules is important. The first rule will be applied first. So, if you first define the "deny all" rule, you will not be able to connect with SSH and your connection will drop.
Making the iptables rules persistent
The rules we defined are not persistent. So whenever you restart your server, the rules will be lost. To prevent this, we will install iptables-persistent
. This software will keep our rules and will enable them at the startup. First install it using the following command:
$ sudoapt-get install iptables-persistent
While installing, it will ask you to save the current configuration to a file name such as /etc/iptables/rules.v4
. Answer this with a yes
. The second question will be about IPv6. We did not define any rules for it, so answer no
for this.
After completing the setup, reboot your server and list the rules of iptables to see that they are still there.