Making TAK User Accounts Easy

Sometimes making a TAK account on your TAK Server isn't easy. You must change the user session, navigate to a directory, and execute a script. Then after that, you have to move it and change ownership. The bottom line up front - it's a process. It can be daunting to the new administrator who doesn't know his way around the Linux command line. To help new administrators in the process I created a little script that will perform that task for them with ease. I will attempt to break it down and explain the process so you too can implement this in your own environment.

📓
Note: This method and script will only apply if your TAK Server is acting as the certificate authority for your clients.

The basics

Before any script, we are going to add shell interpreter language at the top. #!/bin/bash. I'm sure it goes by a more "official name" - I'm self-taught not educated. 😁

For my script to work, I need to create some environmental variables. This way I don't have to type out the complete commands or paths but the alias. This just has the basic directories and commands we wish to reference and execute later on. Here I am going to reference the TAK installation directory, the makeCert.sh script that is already present and then we want to pull the current user. It will look like this:

dir=/opt/tak
certs=$dir/certs/files
makeCerts=$dir/certs/makeCert.sh
curuser=$(printenv SUDO_USER)

The reason we have printenv SUDO_USER is that when we execute the command we need to invoke root as part of the process. In the end process, we are going to copy our compiled certificate to our home directory. However, since we invoked root that home directory will be /root and not /home/useraccount. This command will pull the user who invoked root and save it as our variable for later on.

Next, I want to verify the user is root or can invoke root and then display the script usage options as well if something is wrong or not values are entered. This can be referenced using the [ "$UID" -eq 0 ] || exec sudo "$0" "$@" command. I'm sure there is probably another way to do this but I've found this effective in my deployments. The display_usage() function is where we want to display output on how to use the script and some examples. We additionally want to do some logic checks to display our usage examples if something isn't right. These lines will look like this:

# Determine if the user is root; else, use sudo
[ "$UID" -eq 0 ] || exec sudo "$0" "$@"

display_usage() {
    echo "./makeCert.sh <commonname> [<certdays>] [<group>] [admin]"
    echo "Optional parameters enclosed with []"
    echo "Example: ./makeCert ATAK01 30 Group1"
}
# If no arguements presented display usage
if [[ ($# -le 0)]]; then
    display_usage
    exit 1
fi

# Check if user supplied --help or -h.  If yes display usage
if [[ ($@ == "--help") || $@ == "-h" ]]; then
    display_usage
    exit 0
fi

Input validation

With our script we have 4 options or values that need to be present, the last [admin] is like a hidden gem. The [admin] block when referenced will make that certificate role an administrator. Our first input is the <commonname> this is the name that is going to be given to the issued certificate. If no <commonname> is given the script defaults to display_usage function. Next, our second value is <certdays>. By default certificates are valid for 730 days; however, in some cases, we want to issue a certificate for less than that so this is where that comes into play. If the <commonname> is the only thing present on execution the script will keep the defaults for <certdays> and <group> which is 730 days and __ANON__ as the group. We also conduct some validation checks to ensure that the input <certdays> is a number and not a name.

Certificate Days

To change the default 730 days for the certificates we use the sed command to search a file and replace any found values. Here by default, it's looking for 730 and then going to replace it with whatever value is in <certdays>. If a 0 (zero) is present this will also retain the default days of 730. This is used as a placeholder when referencing the [admin] option.

# Conduct input verification
# Input 2 Cert Days
# Verify value is a number
if [[ $2 ]]; then 
    if ! [[ "$2" =~ ^[0-9]+$ ]]; then
        printf "Value must be a number.\n"
        display_usage
        exit 0
    elif [[ "$2" == 0 ]]; then
        #do nothing, skip me
        $true
    # Change the default certificate validity days
    elif [[ -n "$2" ]]; then
        sed -i "s/-days 730/-days $2/g" $makeCert
    fi
else 
    #do nothing, skip me
    $true
fi

Certificate Group

For our third input, we have <group> which tells TAK what filter group this certificate needs to be in. If no value is present or 0 (zero) is present the default group is applied __ANON__. The value that is set is certgroup which is referenced later on within the script.

# Input 3 Group Assignment
default_group="java -jar $dir/utils/UserManager.jar certmod -g __ANON__ $certs/"$1".pem"
if [[ "$3" == 0 ]]; then
    certgroup=$default_group
elif [[ -n $3 ]]; then
    certgroup="java -jar $dir/utils/UserManager.jar certmod -g "$3" $certs/"$1".pem"
else
    certgroup=$default_group
fi

Apply the role of admin

Our final check is to determine if this certificate is an admin or not. By default this value is not referenced unless it is called upon. A boolean value is set for admin if this option is referenced.

# Input 4 Admin Check
if [[ "$4" ]]; then
    if [[ "$4" == "admin" || "$4" == "Admin" ]]; then
        admin="true"
    else
        printf "Invalid Value.\n"
        display_usage
        exit 0
    fi
else
    admin="false"
fi

Creating the certificate

After all the input validations are done it's time to create the certificate. This is a multi-step process that involves creating the certificate, applying the groups, and then checking if it should be an admin or not. After completion, we need to set the default <certdays> back to 730 if it was changed. This allows us to easily reference and change the makeCert.sh script that is used when creating the certificates. Again we are inspecting option two and looking at what days were input as the value or it was a 0 (zero).

# Create the client certificate
$makeCert client "$1"

# Add the certificate to a group
$certgroup

# Certificate is an admin
if [[ $admin == "true" ]]; then
    java -jar $dir/utils/UserManager.jar certmod -A $certs/"$1".pem
fi

# Return to certificate validity days default
if [[ "$2" ]]; then 
    if [[ "$2" == 0 ]];then
        #do nothing
        $true
    else
        sed -i "s/-days $2/-days 730/g" $makeCert
    fi
else
    #do nothing
    $true    
fi

Performing some cleanup

After was have created our certificate we need to restore the TAK directory to defaults if anything has changed. This is more of a safeguard than anything. Next, we need to copy over our newly created certificate to our home profile. This is where the variable curuser is referenced from the start of our script. After we have copied over the new certificate we need to change the permissions so that we can move it to our TAK client. Finally, we print "Task Complete." to give the administrator some piece of mind that the task is done. the \n afterward forces a new line after this command so that it doesn't interfere with the console. Without this "Task Complete." will be present alongside the command prompt.

# Restore ownership
chown -R tak:tak $dir

cp $certs/"$1".p12 /home/"$curuser"/
chown -R "$curuser":"$curuser" /home/"$curuser"

printf "Task Complete.\n"
exit

Putting it all together

If you followed along the script is fairly simple and straightforward. When you install or copy this to your TAK Server you will need to add the executable option to the file to make it work. To do so you will use the chmod command with +x to add the option. In the example below our script is called makeCert.sh.

chmod +x makeCert.sh

The Code:

#!/bin/bash
#Version 1.5
#JR @myTeckNet.com
#Global Variables
dir=/opt/tak
certs=$dir/certs/files
makeCert=$dir/certs/makeCert.sh
curuser=$(printenv SUDO_USER)

# Determine if the user is root; else, use sudo
[ "$UID" -eq 0 ] || exec sudo "$0" "$@"

display_usage() {
    echo "./makeCert.sh <commonname> [<certdays>] [<group>] [admin]"
    echo "Optional parameters enclosed with []"
    echo "Example: ./makeCert ATAK01 30 Group1"
}
# If no arguements presented display usage
if [[ ($# -le 0)]]; then
    display_usage
    exit 1
fi

# Check if user supplied --help or -h.  If yes display usage
if [[ ($@ == "--help") || $@ == "-h" ]]; then
    display_usage
    exit 0
fi

cd $dir/certs || exit

# Conduct input verification
# Input 2 Cert Days
# Verify value is a number
if [[ $2 ]]; then 
    if ! [[ "$2" =~ ^[0-9]+$ ]]; then
        printf "Value must be a number.\n"
        display_usage
        exit 0
    elif [[ "$2" == 0 ]]; then
        #do nothing, skip me
        $true
    # Change the default certificate validity days
    elif [[ -n "$2" ]]; then
        sed -i "s/-days 730/-days $2/g" $makeCert
    fi
else 
    #do nothing, skip me
    $true
fi
# Input 3 Group Assignment
default_group="java -jar $dir/utils/UserManager.jar certmod -g __ANON__ $certs/"$1".pem"
if [[ "$3" == 0 ]]; then
    certgroup=$default_group
elif [[ -n $3 ]]; then
    certgroup="java -jar $dir/utils/UserManager.jar certmod -g "$3" $certs/"$1".pem"
else
    certgroup=$default_group
fi
# Input 4 Admin Check
if [[ "$4" ]]; then
    if [[ "$4" == "admin" || "$4" == "Admin" ]]; then
        admin="true"
    else
        printf "Invalid Value.\n"
        display_usage
        exit 0
    fi
else
    admin="false"
fi

# Create the client certificate
$makeCert client "$1"

# Add the certificate to a group
$certgroup

# Certificate is an admin
if [[ $admin == "true" ]]; then
    java -jar $dir/utils/UserManager.jar certmod -A $certs/"$1".pem
fi

# Return to certificate validity days default
if [[ "$2" ]]; then 
    if [[ "$2" == 0 ]];then
        #do nothing
        $true
    else
        sed -i "s/-days $2/-days 730/g" $makeCert
    fi
else
    #do nothing
    $true    
fi

# Restore ownership
chown -R tak:tak $dir

cp $certs/"$1".p12 /home/"$curuser"/
chown -R "$curuser":"$curuser" /home/"$curuser"

printf "Task Complete.\n"
exit

Example Outputs

./makeCert.sh ATAK01 30 Group2
./makeCert.sh ATAK02 0 0 admin
I hope this makes your TAK administration a bit easier 😊