# Post production SFTP solution ## Mapping out the users From the information given in the text I would create the following users and groups: We could write a script that takes a CSV file as input but I decided to go the oldschool way and just write a full script. First we add the groups we think we'll need. ```bash #!/bin/bash groupadd production groupadd planning groupadd script groupadd technical groupadd videoeditors groupadd audioengineers groupadd sftpjailed ``` Most of these are self explanitory, but the `production`, `technical` and `sftpjailed` require a bit more explanitation. They are *overarching* groups, meaning they group other groups. From a Linux standpoint they are no different from the normal groups, but we'll use the to group together the technical department and all users that don't need ssh. Next we'll add the users and we'll set their passwords to a *test* password. In order for them to share a `$HOME` directory we'll need to create one as well. ```bash #!/bin/bash # adding the groups groupadd production groupadd planning groupadd script groupadd technical groupadd videoeditors groupadd audioengineers groupadd sftpjailed # creating the shared home directory mkdir -p /home/postproduction # adding the users useradd marie echo "marie:test" | chpasswd usermod -d /home/postproduction marie useradd hugo echo "hugo:test" | chpasswd usermod -d /home/postproduction hugo useradd victor echo "victor:test" | chpasswd usermod -d /home/postproduction victor useradd camille echo "camille:test" | chpasswd usermod -d /home/postproduction camille useradd dave echo "dave:test" | chpasswd usermod -d /home/postproduction dave useradd sarah echo "sarah:test" | chpasswd usermod -d /home/postproduction sarah useradd ester echo "ester:test" | chpasswd usermod -d /home/postproduction ester useradd adam echo "adam:test" | chpasswd usermod -d /home/postproduction adam useradd eefje echo "eefje:test" | chpasswd usermod -d /home/postproduction eefje useradd alex echo "alex:test" | chpasswd usermod -d /home/postproduction alex ``` The quick ones among you probably see there is quite a lot of room for error here when typing the same names over and over again. We can optimise this with some easy variables. ```bash #!/bin/bash # the shared home for all users sharedhome="/home/postproduction" mkdir -p $sharedhome # adding the groups groupadd production groupadd planning groupadd script groupadd technical groupadd videoeditors groupadd audioengineers groupadd sftpjailed # adding the users username="marie" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username username="victor" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username username="camille" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username username="dave" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username username="sarah" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username username="ester" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username username="adam" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username username="eefje" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username username="alex" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username ``` Those who already did programming before see this is an ideal situation to create our own [functions](https://ryanstutorials.net/bash-scripting-tutorial/bash-functions.php). Try to optimise the script if you can with your own function! Next we need to add all the users to their groups. ```bash #!/bin/bash # the shared home for all users sharedhome="/home/postproduction" mkdir -p $sharedhome # adding the groups groupadd production groupadd planning groupadd script groupadd technical groupadd videoeditors groupadd audioengineers groupadd sftpjailed # adding the users username="marie" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G production $username usermod -a -G planning $username usermod -a -G script $username usermod -a -G technical $username usermod -a -G videoeditors $username usermod -a -G audioengineers $username usermod -a -G sftpjailed $username username="hugo" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G production $username usermod -a -G planning $username usermod -a -G script $username usermod -a -G sftpjailed $username username="victor" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G production $username usermod -a -G planning $username usermod -a -G sftpjailed $username username="camille" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G production $username usermod -a -G planning $username usermod -a -G sftpjailed $username username="dave" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G videoeditors $username usermod -a -G technical $username usermod -a -G sftpjailed $username username="sarah" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G videoeditors $username usermod -a -G technical $username usermod -a -G sftpjailed $username username="ester" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G videoeditors $username usermod -a -G technical $username usermod -a -G sftpjailed $username username="adam" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G audioengineers $username usermod -a -G technical $username usermod -a -G sftpjailed $username username="eefje" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G audioengineers $username usermod -a -G technical $username usermod -a -G sftpjailed $username username="alex" useradd $username echo "$username:test" | chpasswd usermod -d $sharedhome $username usermod -a -G production $username usermod -a -G planning $username usermod -a -G script $username usermod -a -G technical $username usermod -a -G videoeditors $username usermod -a -G audioengineers $username ``` When testing this out you'll quickly discover the need for a second script, one that removes all the users and groups from your system. I would advise something along these lines. ```bash #!/bin/bash sharedhome="/home/postproduction" # removing the groups groupdel production groupdel planning groupdel script groupdel technical groupdel videoeditors groupdel audioengineers groupdel sftpjailed # removing the users userdel marie userdel hugo userdel victor userdel camille userdel dave userdel sarah userdel ester userdel adam userdel eefje userdel alex # removing the groups created for the users groupdel marie groupdel hugo groupdel victor groupdel camille groupdel dave groupdel sarah groupdel ester groupdel adam groupdel eefje groupdel alex # removing the home rm -r $sharedhome ``` Both scripts together now give us a basic toolset to add and remove the users we need. They work quite nicely but are not *verbose* at all! To add debug messages with `echo` all around will become very prone to errors unless we start adding `for` loops and `functions`. Let's start with a for loop in the remove script. ```bash #!/bin/bash sharedhome="/home/postproduction" groups="production planning script technical videoeditors audioengineers sftpjailed" users="marie hugo victor camille dave sarah ester adam eefje alex" # removing the groups for group in $groups do echo "removing group $group" groupdel $group done # removing the users and their primary groups for user in $users do echo "removing user $user" userdel $user echo "removing group $user" groupdel $user done # removing the home rm -r $sharedhome ``` So much cleaner no? This is also a good place to start controlling our `STDERR` output. Can you think of a clean way to deal with the error messages? Remember what `$?` does? And you remember what `2> /dev/null` does? A combination of these two concepts can tame the error message output quite nicely. Have a test yourself! The script to create the users will be a bit more complicated as there are a lot more variables. A function would be ideal, but we'll try to deal with the problem without first! ```bash #!/bin/bash sharedhome="/home/postproduction" groups="production planning script technical videoeditors audioengineers sftpjailed" users="marie hugo victor camille dave sarah ester adam eefje alex" marie="production planning script technical videoeditors audioengineers sftpjailed" hugo="production planning script sftpjailed" victor="production planning sftpjailed" camille="production script sftpjailed" dave="technical videoeditors sftpjailed" sarah="technical videoeditors sftpjailed" ester="technical videoeditors sftpjailed" adam="technical audioengineers sftpjailed" eefje="technical audioengineers sftpjailed" alex="production planning script technical videoeditors audioengineers" # adding the home mkdir -p $sharedhome # adding the groups for group in $groups do echo "adding group $group" groupadd $group done # adding the users for user in $users do echo "adding user $user" useradd $user echo "setting the password for $user" echo "$user:test" | chpasswd done # adding the users to their groups for user in $users do echo "adding groups for $user" usergroups=$(eval echo \$$user) for group in $usergroups do echo "adding $user to $group" usermod -a -G $group $user done done ``` Two things worth pointing out in the above script are: 1. the loop in a loop 2. the `eval` statement The loop in a loop might look intimidating at first sight but it's not super exotic. For each user is the `$users` list we will look at each group they need to belong to. for each of those groups we add them with `usermod`. The `eval` is a bit trickier to explain and I would consider it a bit of a *hack* to make it all work. For each user in the `$users` list we also have a variable with their name. This variable contains the groups they need to belong to. The `eval` statement will *evaluate* the expression following and `\$` will interpretate the $ sign *litterally*. All of this serves to make a call to `$camille` and get `"production script sftpjailed"` in return so we can iterate over the groups. There are *cleaner* ways of doing this and I would advise you to look into bash [arrays](https://www.gnu.org/software/bash/manual/html_node/Arrays.html). If you decide to try this out, you *might* run into compatibility issues when testing in `zsh` but from inside a `bash` script you should be fine.