Users, Groups, and Permissions in Bash (UNIX based Operating Systems)
Tags: bash
Published: 2020-10-18 21:24:31

_Note: This tutorial applies to the BASH shell and UNIX based operating systems. Windows OS will be different._

Many tutorials cover the topic of permissions within a UNIX based operating system, but often overlooked is the topic of users and groups. For individual users, it is difficult to understand what the usefulness of this architecture is. In this short tutorial, I will be walking through the reason why we have permissions, how to set permissions, and how to manage your users and groups that these permissions apply to.

{% youtube 9HT16EIQHRQ %}

## What is a User?

A user _profile_ can be defined as an entity that can own processes, run files, and who is associated with a username and home directory. On a fresh install of any UNIX based operating system, there is a default `root` user setup with no password. This user is far too important to gloss over, so let's dig in and get a better idea of what `root` is and why it is useful.

### The Root User

To enter a shell as the root user in bash, just run the following command.

```bash
su
```

This will prompt you for a password and once you have entered it, you will be running as `root`. There is just one problem with this given the default Ubuntu settings...

**There is no root password**

The default Ubuntu setup creates the root user without a password, which is actually a security feature given the fact that a hacker cannot break into a system without a password. In order to run the `su` command successfully, you would need to setup the password with the root user, which is _highly discouraged_. The proper way to run a command as the `root` user is by prepending the `sudo` command in front of the command you are trying to run. As long as your current user is allowed to operate as root, it will ask you for your current user's password and successfully run the command. For example, type the following commands into the terminal.

```bash
cat /etc/sudoers
# cat: /etc/sudoers: Permission denied

sudo cat /etc/sudoers
# output ---
```

The `sudoers` file in the `/etc` directory is not readable by a non-root user, so when we try to print its contents with our user, it does not allow it. We simply need to prepend the `root` keyword to the command and it will then print out.

The ability to use `sudo` is great, but why would we ever need to use it? Among others, here are a few main reasons why you would need to use the root user.

1. To edit system configuration files
2. To install global programs
3. Change ownership of files and directories

The true benefit of the root user is when you are managing multiple users on a system in a corporate work environment. Although most workplaces user Windows, the same concept applies. Most employees will not be given root privileges ("administrator on Windows"), and therefore they cannot install programs at their discretion. When companies purchase laptops for their employees, the last thing they want is the employee installing malicious programs that could expose their internal data, so they give each employee the minimum privileges that they need to do their job (which is rarely superuser privileges).

### Getting more information about a user

Now that we understand the `root` user and its basic functions, lets take a look at some commands that will help us understand the user system a little better. Naturally, the first thing I want to know about my machine is what users exist? To get all of the local users on your system, you can run the following command.

```bash
cut -d: -f1 /etc/passwd
```

At the top of this list is the root user, and you will also be able to search for the current user you are operating as. To figure out who you are operating as, you can run the following command.

```bash
whoami
```

As you can see, there are quite a few users on your computer already, and this is by design. Remember, users are simply entities that can own processes and run files. If you had MySQL installed on your system, you wouldn't want the `mysql` user to have access to everything; you just want it to have access to the files and folders required to run its server.

If you want to find out more about a user, you will need to dig into some of the system configuration files. Run the following two commands to find out more about the root user and your current user.

```bash
sudo cat /etc/passwd | grep 'root'
#   1  2 3 4  5      6      7
# root:x:0:0:root:/root:/bin/bash

# My current user is ubuntu
sudo cat /etc/passwd | grep 'ubuntu'
#    1   2   3    4  5      6           7
# ubuntu:x:1000:1000::/home/ubuntu:/bin/bash
```

I have labeled the output, so let's walk through it by number.

1. The first part of the output specifies the name of the user
2. If the second part is an "x", this means that this user's password is stored in the /etc/shadow file
3. User id (root is always 0)
4. User group id (root is always 0)
5. The users full name (as entered -- notice the ubuntu user does not have a full name, but that is okay)
6. The user's home directory path
7. The shell that the user is using

## What is a Group?

Before we look at the groups that your user is part of, what is a group anyways? To my knowledge, there is one primary purpose for having groups, and that is to make permissioning of files and folders simpler. Let's say you are the administrator for a corporation's IT system and you noticed that your employees are having wifi connectivity issues. You go ahead and write a script that resolves these issues, but by default, your employees will not be able to execute this script. You have to give them permission to do so. One method would be to get a list of all the employees and give them execute privileges over this script file. This would be extremely tedious when there are thousands of employees. Instead, it would make more sense to give the "employees" group execute privileges on this script. At this point, we haven't covered how to set permissions for a file or directory, but hopefully this example clarifies the purpose of having groups.

To find out what groups your user is a part of, type the following command.

```bash
groups
```

This will list all the groups that your user is a part of. You can also list all the groups on the system with the following command.

```bash
sudo cat /etc/group

# Only print root group
sudo cat /etc/group | grep 'root'
#  1   2 3 4
# root:x:0:
```

The group output is as follows:

1. Name of group
2. Group password (rarely used)
3. Group ID (remember, root is always 0)
4. Optional users that are part of the group (in addition to what is specified in the /etc/passwd file)

## Setting permissions

<iframe width="560" height="315" src="https://www.youtube.com/embed/YWoI8FjvNn0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

There truly aren't a whole lot of permission commands to remember if you understand what it means to permission something and the three permission modes. For starters, the reason we would permission a file or directory is to isolate different spaces in your filesystem for different users and groups. For example, most of the files at the path `/sbin` are considered system call scripts or binaries and therefore only the root user should be able to modify them. Therefore, they have a permission set of `-rwxr-xr-x`. What does this mean??

There are four parts to a permission set:

1. Type - is this a file (-), directory (d), or symlink (l)?
2. Owner permissions
3. Group permissions
4. Rest of world permissions

Below is a table that explains how we got to our permission set. As you can see, the code `755` corresponds to the `-rwxr-xr-x` permission set.

<div id="before-table"></div>

|                       Type                       |               User permissions               |              Group Permissions               |          Rest of World Permissions           |
| :----------------------------------------------: | :------------------------------------------: | :------------------------------------------: | :------------------------------------------: |
| Could be directory (d), file (-), or symlink (l) | Could be read (r), write (w), or execute (x) | Could be read (r), write (w), or execute (x) | Could be read (r), write (w), or execute (x) |
|                   Letter Code                    |                     rwx                      |                     r-x                      |                     r-x                      |
|                   Number Code                    |                      7                       |                      5                       |                      5                       |
|                   Calculation                    |       rwx = r (4) + w (2) + x (1) = 7        |         r-x = r (4) + 0 + x (1) = 5          |         r-x = r (4) + 0 + x (1) = 5          |

If we print out the full permissioning of a single file in `/sbin` such as the `unix_update` binary, we get the following output.

```bash
ls -l /sbin/unix_update
# -rwxr-xr-x 1 root root 31376 Mar 16  2016 /sbin/unix_update*
```

We can break this down as follows... The permission set is `-rwxr-xr-x`, which can also be expressed as `755` based on the table above. The `root` user is the owner of the file, and the `root` _group_ is the group owner of the file. The rest of the line is just file info!

So we know we can print the permissions of a file with the `ls -l` command, but how do we set them? And what should we set them too? A general rule of thumb:

- For files, set the permissions to 644 (i.e. `drw-r--r--`)
- For directories, set the permissions to 755 (i.e. `-rwxr-xr-x`)

Directories and files have slightly different permissioning rules, which is why we must set them to different default permissions. With directories, if the executable permission is disabled, the user will not be able to see any of the files in that directory or cd into that directory. With these default settings, only the user that owns the file or directory will have write permissions.

To change the permission of a file or directory, we use the `chmod` command. The syntax is as follows:

```bash
# Add sudo to front of command if necessary
chmod <permission-code> <file-or-directory>

# Example
chmod 775 test-script.sh
```

To check the current permission, remember that you can always use the `ls -l <file>` command. To change the _owner_ of a directory or file, you can use the `chown` command:

```bash
# Use sudo if necessary
chown <user>:<group> <file-or-directory>
```

Oftentimes, you will want to change the ownership of multiple files within a single directory, which can be done using the `-R` flag on the `chown` command.

```bash
# This will change the ownership of every file in the parent-dir/ to have ubuntu as the owner and ubuntu as the group
chown -R ubuntu:ubuntu parent-dir/
```

## .bashrc, .bash_profile, .bash_login, .profile

We have covered many concepts in the bash shell and UNIX based operating system, but what about the configuration file that controls how your bash shell runs? There are actually several configuration files and they do not have an intuitive hierarchy in terms of which one takes precedence over another. To make things more complicated, some of the config files run for "login shells" while others run in "non-login, interactive shells". What is a login shell? What is an interactive shell? In video below, I clarify what all these files do and when they should be used.

{% youtube yIuPu4iLcY4 %}