In this practice exercise, we will run a set of steps to check the knowledge you have acquired throughout this book. As opposed to previous chapters, not all steps will be indicated, and it’s therefore left to your discretion to perform the steps required to accomplish your desired goals. It is recommended to avoid referencing past chapters for guidance. Instead, try to use your memory or the tools available in the system. This exercise, if performed correctly, will train you effectively for official exams.
It is strongly advised to start this exercise with a clock to keep track of time.
All the practice exercises in this chapter require the use of a virtual machine (VM), running Red Hat Enterprise Linux 9 (RHEL 9) installed with the base installation. Additionally, new virtual drives will be required for storage operations.
For the exercises, it is assumed you possess the following:
This is a list of general recommendations for any test, and most fall under the category of common sense, but it’s always important to have them in our mind before performing any such test:
Important Note
The following exercise has, by design, been created so that there will be no highlights on commands, packages, and so on. Remember what you’ve learned so far in order to detect the keywords to see what needs to be done.
Don’t jump into the walk-through too early. Try to remember what was covered.
Ip6: 2001:db8:0:1::c000:207/64 g
gateway 2001:db8:0:1::1
Ipv4 192.0.1.3/24
gateway 192.0.1.1
For this section, we’ll copy each item in the list of goals, and then provide an explanation below it, using proper syntax highlighting and explanations.
We can check the current system date by executing the date command. At the very last part of the line that is subsequently printed, the time zone will be shown. In order to configure it, we can use the timedatectl command, or alter the /etc/localtime symbolic link.
So, to achieve this goal, we can use one of the following:
Now, date should report the proper time zone.
Doing this will require the following:
First, let’s tackle this with SSH, as seen in the following code snippet:
dnf –y install openssh-server; systemctl enable sshd; systemctl start sshd
Now, let’s generate an SSH key by pressing Enter to accept all defaults, like so:
ssh-keygen
Now, let’s add the generated key (/root/.ssh/id_rsa) to the authorized keys, like so:
cd; cd .ssh; cat id_rsa.pub >> authorized_keys; chmod 600 authorized_keys
To validate this, we can execute ssh localhost date, after which we will be able to get our current system’s date and time without providing a password.
This requires creating a user and an SSH key that is added in a similar fashion to the root user. The next options will also be relevant to a user, but for the purposes of this demonstration, we will tackle them as separate tasks:
useradd user
su – user
Now, let’s generate an SSH key by pressing Enter to accept all defaults, like so:
ssh-keygen
Now, let’s add the generated key (/root/.ssh/id_rsa) to the authorized keys, as follows:
cd; cd .ssh; cat id_rsa.pub >> authorized_keys; chmod 600 authorized_keys
To validate this, we can execute ssh localhost date, and we will be able to get the current system date and time without providing a password.
Then, use logout to return to our root user.
This requires us to tune the user restrictions, as follows:
chage –W 2 user
chage –I 1 user
chage -M 7 user
This requires two steps. The first is to enable user with the root user’s authorized key, and then tune the sshd daemon, as follows:
cat /root/.ssh/id_rsa.pub >> ~user/.ssh/authorized_keys
Edit the /etc/ssh/sshd_config file and add or replace the PermitRootLogin line so that it looks like this:
PermitRootLogin prohibit-password
Save and then restart the sshd daemon, like so:
systemctl restart sshd
This means configuring the /etc/sudoers file by adding the following line:
user ALL=(ALL) NOPASSWD:ALL
Create a file—for example, /etc/ssh/banner—with the message to display: for example, "Get out of here".
Modify /etc/ssh/sshd_config and set the Banner /etc/ssh/banner line, then restart the sshd daemon with systemctl restart sshd.
This is a tricky one. The first step is to alter /etc/ssh/sshd_config and define port 22222. Once this is done, restart sshd with the following command:
systemctl restart sshd
This, of course, will fail... why?
The firewall must be configured, like this:
firewall-cmd –-add-port=22222/tcp --permanent
firewall-cmd –-add-port=22222/tcp
SELinux must then be configured, like so:
semanage port -a -t ssh_port_t -p tcp 22222
Now, the sshd daemon can be restarted by running the following command:
systemctl restart sshd
Use the following command:
groupadd devel
Use the following command:
usermod –G devel user
Use the following command:
id user > ~user/userids
We altered the default SSH port to be 22222.
Create a file named .ssh/config for both user and root, with the following contents:
Host localhost Port 22222 Compression yes
Man pages are stored in /usr/share/man. Therefore, use the following command:
find /usr/share/man/ -type f > manpages.txt
The following command first builds a list of users in the system with the nologin shell:
for user in $(cat /etc/passwd| grep nologin|cut -d ":" -f 1)
do
echo "$user -- $(grep $user /etc/group|cut -d ":" -f 1|xargs)"
done
From that list, check the membership in the /etc/group file, leaving only the group name and using xargs to concatenate them into a string to be printed.
The previous example makes use of for loops and inline execution of commands, via $().
The ideal way to monitor something would be cron, but as we’re told not to use it, this only leaves us with systemd timers. (You can check the files tested via the following link: https://github.com/PacktPublishing/Red-Hat-Enterprise-Linux-RHEL-9-Administration/tree/main/chapter-18-exercise1.)
Create a /etc/systemd/system/monitorresources.service file with the following contents:
[Unit] Description=Monitor system resources [Service] Type=oneshot ExecStart=/root/myresources.sh
Create a /etc/systemd/system/monitorresources.timer file with the following contents:
[Unit] Description=Monitor system resources [Timer] OnCalendar=*-*-* *:0,5,10,15,20,25,30,35,40,45,50,55:00 Persistent=true [Install] WantedBy=timers.target
Create a /root/myresources.sh file with the following contents:
#!/bin/bash df > /root/resources.log
Enable the new timer, as follows:
systemctl daemon-reload
systemctl enable --now monitorresources.timer
Does it work? If not, journalctl –f will give some details. SELinux prevents us from executing a root file, so let’s convert it into a binary type and mark it as executable, as shown in the following snippet:
chcon –t bin_t /root/myresources.sh
chmod +x /root/myresources.sh
df reports used disk space and available space, so we need to do some math.
This will report the mounted location, size, used space, and available space, with ; as a separator. Refer to the following example:
df|awk '{print $6";"$2";"$3";"$4}'
bash allows us to do some math operations, but these lack fractional parts. Luckily, we can do a trick—we will be looping over it, as follows:
for each in $(df|awk '{print $6";"$2";"$3";"$4}'|grep -v "Mounted") do FREE=$(echo $each|cut -d ";" -f 4) TOTAL=$(echo $each|cut -d ";" -f 2) echo "$each has $((FREE*100/TOTAL)) free" done
The for loop will check all the available data, grab some specific fields, separate them with ;, and then run the loop for each line, stored in the $each variable.
We cut the output and then get the fourth field. This is the available space.
We cut the output and then we get the second field. This is the total number of blocks.
As bash can do integer divisions, we can multiply by 100 and then divide to get the percentage and add a string as part of the output.
Alternatively (but not as illustrative), we could have discounted to 100 the percentage used already given by df and saved some steps of the calculation.
We also need to store the output in a file. To do this, we can either wrap the whole loop in a redirection or add it in the echo line so that it appends to a file.
And we also need to do it via cron—we show the full solution next.
Create a /root/myfreespace.sh script with the following contents:
for each in $(df|awk '{print $6";"$2";"$3";"$4}'|grep -v "Mounted") do FREE=$(echo $each|cut -d ";" -f 4) TOTAL=$(echo $each|cut -d ";" -f 2) echo "$each has $((FREE*100/TOTAL)) free" done
Then, use chmod 755 /root/myfreespace.sh to make it executable.
Run crontab -e to edit root’s crontab, and add the following line:
*/1 * * * * /root/myfreespace.sh >> /root/freespace.log
This can be done by editing /etc/logrorate.conf, with the following settings:
daily rotate 3
Remove other occurrences of weekly, monthly, and so on, to leave only the one we want.
Create a /etc/logrotate.d/rotateroot file, with the following contents:
/root/freespace.log { missingok notifempty sharedscripts copytruncate } /root/resources.log { missingok notifempty sharedscripts copytruncate }
Edit /etc/chrony.conf and add the following line:
pool pool.ntp.org iburst
Then, run the following command:
systemctl restart chronyd
Edit /etc/chrony.conf by adding the following line:
Allow 172.22.0.1/24
Then, run the following command:
systemctl restart chronyd
Run the following command:
dnf –y install sysstat
We now need to modify /usr/lib/systemd/system/sysstat-collect.timer. Let’s do this by creating an override, as follows:
cp /usr/lib/systemd/system/sysstat-collect.timer /etc/systemd/system/
Edit /etc/systemd/system/sysstat-collect.timer by replacing the OnCalendar value so that it looks like this:
OnCalendar=*:00/1
Then, reload the units with the following command:
systemctl daemon-reload
Edit /etc/security/pwquality.conf with the following line:
minlen = 12
To do this, run the following:
adduser privacy
su – privacy
echo "umask 0077" >> .bashrc
This resolution uses umask to remove permissions from others on all newly created files.
To do this, run the following:
mkdir /shared
chown root:devel /shared
chmod 777 /shared
chmod +s /shared
See the following snippet for how to accomplish this:
nmcli con add con-name mynic type ethernet ifname eth0 ipv6.address 2001:db8:0:1::c000:207/64 ipv6.gateway 2001:db8:0:1::1 ipv4.address 192.0.1.3/24 ipv4.gateway 192.0.1.1
Run and record the IPs obtained, as shown here:
ping www.google.com
ping www.redhat.com
Note down the IPs obtained previously.
Edit /etc/hosts by adding the following:
IPFORGOOGLE google IPFORREDHAT redhat
Then, save and exit.
See the following snippet for how to accomplish this:
rpm -Va > /root/altered.txt
This is a complex one, so let’s examine it step by step.
Install http and enable it using the following code:
dnf –y install httpd
firewall-cmd --add-service=http –permanent
firewall-cmd --add-service=http
systemctl start httpd
systemctl enable httpd
Create a folder under /mirror, then copy the source media packages and make them available over http, like so:
mkdir /mirror /var/www/html/mirror
mount /dev/cdrom /mnt
rsync –avr –progress /mnt/ /mirror/
mount –o bind /mirror /var/www/html/mirror
chcon -R -t httpd_sys_content_t /var/www/html/mirror/
Remove the kernel packages, as follows:
find /mirror -name kernel* -exec rm '{}' ;
Create repository file metadata by using the following commands:
dnf –y install createrepo
cd /mirror
createrepo .
Create a repository file using the repository we created, and set it up on the system, ignoring the glibc* packages from it.
Edit /etc/yum.repos.d/mymirror.repo by adding the following contents:
[mymirror] name=My RHEL9 Mirror baseurl=http://localhost/mirror/ enabled=1 gpgcheck=0 exclude=glibc*
See the following snippet for how to accomplish this:
su – user
crontab –e
Edit crontab and add the following line:
@daily rsync -avr –-progress –-delete root@localhost:/root/ /home/user/root/
See the following snippet for how to accomplish this:
dnf –y install openscap scap-security-guide openscap-utils
oscap xccdf eval --report pci-dss-report.html --profile pci-dss /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
Compression and deduplication in this sentence mean Virtual Data Optimizer (VDO). We need to move the mirror we currently have to it and make the old mirror, we had, go there instead.
If we have the installation media, we can choose to copy it over and repeat the kernel removal or transfer. To do so, let’s first create a VDO volume in a partition in our new hard drive (sdb), like so:
fdisk /dev/sdb
n <enter>
p <enter>
1 <enter>
<enter>
+15G <enter>
w <enter>
q <enter>
This will create a partition of 15 GB from the start. Let’s create a VDO volume on it, by using the following command:
dnf –y install vdo kmod-kvdo
pvcreate /dev/sdb1
vgcreate myvdo /dev/sdb1
lvcreate --type vdo --name myvdo vdo -L 15G
mkfs.xfs /dev/myvdo/vdo
# Let's umount cdrom if it was still mounted
umount /mnt
# Mount vdo under /mnt and copy files over
mount /dev/myvdo/vdo/mnt
rsync –avr –progress /mirror/ /mnt/mirror/
# Delete the original mirror once copy has finished
rm –Rfv /mirror
umount /mnt
mount /dev/myvdo/vdomyvol /mirror
At this point, the old mirror was copied into a mirror folder on the VDO volume. This is mounted under /mirror, hence it has the original mirror under /mirror/mirror as requested. We might need to perform the following actions:
Adjust the repository file we created to point to the new path.
See the following snippet for how to accomplish this:
rsync –avr –progress /mirror/mirror/ /mirror/mytailormirror/
find /mirror/mytailormirror/ -name "k*" -type f –exec rm '{}' ;
cd /mirror/mytailormirror/
createrepo .
See the following snippet for how to accomplish this:
fdisk /dev/sdb
n <enter>
p <enter>
<enter>
<enter>
w <enter>
q <enter>
pvcreate /dev/sdb2
# run vgscan to find out the volume name to use (avoid myvdo as is the VDO from above)
vgextend $MYROOTVG /dev/sdb2
# run lvscan to find out the LV storing the root filesystem and pvscan to find the maximum available space
lvresize –L +15G /dev/rhel/root
See the following snippet for how to accomplish this:
grubby --args="systemd.unit=emergency.target" --update-kernel=/boot/vmlinuz-$(uname –r)
Refer to the following command:
dnf –y install tuned
mkdir –p /etc/tuned/myprofile
Edit the /etc/tuned/myprofile/tuned.conf file by adding the following contents:
[main] summary=My custom tuned profile [sysctl] vm.panic_on_oom=1 [main_disk] type=disk devices=sda readahead=>4096 [data_disk] type=disk devices=!sda readahead=>1024
See the following snippet for how to accomplish this:
dnf remove -y httpd
dnf –y install podman
podman login registry.redhat.io # provide RHN credentials
podman pull registry.redhat.io/rhel9/httpd-24
mkdir /var/www #only if it doesn't exist
podman run -d --name httpd –p 80:8080 -v /var/www:/var/www:Z registry.redhat.io/rhel9/httpd-24
3.144.18.4