Scripts

This is a report for the Configuration Management Systems course taught by Tero Karvinen

Date: 28-11-2020

To start this off the goal was to create a simple hello world script so i added the shebang line in a file (called hello) and a simple echo command to go with it.

#!/bin/bash
echo 'Hello World'

Running the file with bash prints Hello World on the screen as expected. Next i added the executable bit to the file with chmod +x hello so it can be ran by running hello. Finally to run it from anywhere i added it to a folder in my path (/usr/local/bin). One last thing i did to it was changing the permissions with sudo chmod 755 /usr/local/bin/hello.

sudo mv hello /usr/local/bin/

.

-rwxr-xr-x 1 niko niko 31 marras 27 16:53 /usr/local/bin/hello

Now to automate this i used this state i created earlier.

/usr/local/bin/:
  file.recurse:
    - source: salt://hello/scripts/
    - file_mode: 755

This will take all files in /srv/salt/hello/scripts/ then copy them over to /usr/local/bin on the minions and set the permissions to 755. Applying the state was successful and so was running hello on the minion. Permissions for the file on the minion were correct as well.

-rwxr-xr-x 1 root root 31 Nov 27 15:10 hello

To create some script that gives relevant information all i could come up with at the moment was getting the time, cpu model and ip address. I created a simple a simple script as follows.

#!/bin/bash
echo "Time: $(date +'%H:%M')"
cpu=$(lscpu|grep 'Model '|awk -F':' '{print $2}')

# This way random whitespace is removed
echo $cpu|xargs echo 'CPU:'
echo "IP: $(hostname -I)"

Applying the state succeeded as expected so logged in to the target minion and tried running the command. This ran as expected as well.

Time: 08:42
CPU: AMD Ryzen 5 1600X Six-Core Processor
IP: 10.0.2.15 172.28.128.122

For a python script i wanted to use some script i wrote when i was studying some cryptography. I made my own CBC mode for AES encryption and packed it all up in a script that can encrypt files with a password. To make it work as a command i just added the python shebang line #!/usr/bin/python3 at the top of the file but running the file gave me the following error.

-bash: ./encrypt.py: /usr/bin/python3^M: bad interpreter: No such file or directory

Oddly enough running the script with python3 worked just fine but i believe ive seen this issue before. It might be a formatting issue because i copied over the whole python file from windows and i think windows uses some diffrent line terminators or something. After scratching my head for a minute i remembered that the easy way to fix this issue was to run the following command.

dos2unix encrypt.py

This command converts windows files to the linux format. Now running the file with ./encrypt.py -h gives the desired output.

usage: encrypt.py [-h] [-d] [-f IN_FILE] [-o OUT_FILE] -k KEY

Encrypt a file with AES-CBC

optional arguments:
  -h, --help            show this help message and exit
  -d, --decrypt         Decrypt the file
  -f IN_FILE, --file IN_FILE
                        Choose an input file (Default: stdin)
  -o OUT_FILE, --output OUT_FILE
                        Choose an outfile (Default: stdout)

Required arguments:
  -k KEY, --key KEY     The key for encryption and decryption

Now i just renamed the srcipt to encrypt and applied the state. At this point i wasnt expecting this to work yet because the minions dont have python3 installed as far as i know. Apparently i was wrong and my ubuntu 20.04 slaves have python3 installed so the script works as it should.

vagrant@slave-1:~$ encrypt -f /etc/passwd -o encrypted -k 'SaltIsCool'
vagrant@slave-1:~$ encrypt -f encrypted -k 'SaltIsCool' -d
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...

Intel

Here the goal was to look at some previously created modules for this course and describe them. I browsed terokarvinen.com and looked at a few reports.

Minecraft server

Source: https://github.com/rootElmo/Harjoitus-7/blob/master/text/harj7_report.md

First one i wanted to look into a bit was one created by Elmo Rouhula and his module setup a minecraft server for him. The module uses pillars to get users and their passwords setup on the target server and setup minecraft server as well.

Apache

Source: https://jorilinux.wordpress.com/palvelinten-hallinta-viikkotehtava-7/

This one was a relatively simple state that starts with installing a few things like git and curl then sets up apache with php. Most of the work is done through file.managed and file.symlink to add the required configuration files and symolic links. Finally the module checks if apache2 is running when the php configuretion file is changed.

Lamp

Source: https://elisalinux.wordpress.com/2018/12/10/palvelinten-hallinta-loppuprojekti/

This module mainly installs the software refered to as LAMP. This includes Apache, MySQL and PHP. The module installs everything automatically and sets everything up which includes enabling a mod, running apache, adding a default website and creating a database. There was also a short module to create a bunch of new users in a loop.

Finally to try one of these modules i decided to go with the one that installs LAMP because all of the files were conveniently in a repository. I cloned the repository with git clone https://github.com/elisapa/smallnetwork.git then moved the state i wanted to the right place with sudo cp -R lamp/ /srv/salt/. My understanding is that this was tested on Ubuntu-16.04 while my slaves are running Ubuntu-20.04 so there could be some issues. As i suspected when i tried applying the state i got lots of errors most noteably these.

slave-3:                                                             
----------                                                       
          ID: installation
    Function: pkg.installed                                             
      Result: False                                                
     Comment: Problem encountered installing package(s). Additional info follows:

              errors:        
                  - Running scope as unit: run-r8b09459f40c94f5193628ca88f33dd01.scope                                                     
                    E: Unable to locate package libapache2-mod-php7.0                                                                      
                    E: Couldn't find any package by glob 'libapache2-mod-php7.0'                                                           
                    E: Couldn't find any package by regex 'libapache2-mod-php7.0'                                                          
                    E: Unable to locate package php7.0-mysql
                    E: Couldn't find any package by glob 'php7.0-mysql'                                                                    
                    E: Couldn't find any package by regex 'php7.0-mysql'                                                                   
     Started: 13:05:37.801265                                        
    Duration: 3389.913 ms

Seems like the issue was php7.0. I changed all instances of php7.0 to just php. With those changes everything installed without any issues but i still got an error.

          ID: cat /tmp/commands.sql|sudo mysql -u root       
    Function: cmd.run                 
      Result: False                 
     Comment: Command "cat /tmp/commands.sql|sudo mysql -u root" run
     Started: 13:11:17.212130         
    Duration: 447.681 ms                     
     Changes:                         
              ----------                         
              pid:             
                  25945                      
              retcode:                       
                  1                      
              stderr:               
                  ERROR 1064 (42000) at line 3: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IDENTIFIED BY '34iwacsn'' at line 1                                                             
              stdout:

Summary for slave-3                                         
------------                                   
Succeeded: 7 (changed=7)    
Failed:    1

Seems like the SQL comands have failed but luckily i have encountered this problem before and know that i just need to update the syntax in the commands. I looked at some of my other homework and it seems like the problem is with this line (again).

GRANT ALL ON lamp_database.* TO 'minion_lamp' IDENTIFIED BY '34iwacsn';

I changed it to these lines.

GRANT ALL ON lamp_database.* TO 'minion_lamp'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;

For some reason i was still getting errors so the seem to be some issues with the first line as well.

          ID: cat /tmp/commands.sql|sudo mysql -u root
    Function: cmd.run
      Result: False
     Comment: Command "cat /tmp/commands.sql|sudo mysql -u root" run
     Started: 13:19:04.719012
    Duration: 302.688 ms
     Changes:   
              ----------
              pid:
                  26014
              retcode:
                  1
              stderr:
                  ERROR 1396 (HY000) at line 1: Operation CREATE USER failed for 'minion_lamp'@'localhost'
              stdout:

Summary for slave-3

I logged in to the slave and tried something. I ran the same command salt was trying to run and that failed as expected but creating a user with a diffrent name succeeded.

mysql> CREATE USER 'minion_lamp'@'localhost' IDENTIFIED BY '34iwacsn';
ERROR 1396 (HY000): Operation CREATE USER failed for 'minion_lamp'@'localhost'
mysql> CREATE USER 'something_else'@'localhost' IDENTIFIED BY '34iwacsn';
Query OK, 0 rows affected (0.01 sec)

To solve this issue i changed the command to something more idempotent. Source: https://dev.mysql.com/doc/refman/8.0/en/create-user.html

CREATE USER IF NOT EXISTS 'minion_lamp'@'localhost' IDENTIFIED BY '34iwacsn';

Applying the state now gives me this error.

ERROR 1007 (HY000) at line 2: Can't create database 'lamp_database'; database exists

Seems like creating the database has the same issue so i tried the same solution.

CREATE DATABASE IF NOT EXISTS lamp_database;

Now everything runs just fine and is idempotent. To finally verify that the site is up i used curl because i dont have a graphical interface on my minions.

curl localhost|less

Running this command shows the default page for apache so everything seems to have worked just fine. I did also check that the database was created and MySQL was listening on port 3306 as it should.

...
This is the default welcome page used to test the correct
operation of the Apache2 server after installation on Ubuntu systems.
It is based on the equivalent page on Debian, from which the Ubuntu Apache
packaging is derived.
If you can read this page, it means that the Apache HTTP server installed at
this site is working properly. You should <b>replace this file</b> (located at
<tt>/var/www/html/index.html</tt>) before continuing to operate your HTTP server.
...

I also tried applying this state to a fresh minion as a sanity check and that seems to work just fine as well (event after applying it multiple times).