Augeas-augtool: Manipulate configuration files programmatically

ยท

7 min read

Background

Part of my tasks at work includes ensuring configurations aligns with organisation compliance policies. I faced some difficulties in attempting to programmatically update the sshd_config file to configure our remote SSH access settings. I was required to update specific settings such as:

  • Denying specific users from being able to have remote access via SSH (/etc/ssh/sshd_config)
  • Restricting su access (/etc/sudoers)

Blockers

I typically tries to avoid installing additional dependencies and use native commands to perform the automation steps through shell-scripting.

While I have an account with elevated privileges (but not root), I seemingly faced some permission issues despite using sudo. Hence, I could not use conventional means such as echo or sed to add and/or update the existing values.

Another issue I faced was configuration files may already have some settings, and it may not be as easer to try to search and replace values without using some complex regex to retrieve the values.

Why Augeas-augtool

I stumbled upon the augeas-augtool when searching for alternatives for automated configuration means. Augeas is a configuration editing tool by parising the configuration files and transform them into a tree.

In PythonLearner's answer in this StackOverflow post, I could consider to use

  • Configuration Management Tools such as Puppet, Chef and Cfengine
  • Augeas

As I wanted to avoid the hassle of setting up for the configuration management tools for this small use case, I decided to go with Augeas as it has a command line tool augtool. Furthermore, within the same StackOverflow post, Cristian Ciupitu's answer provided some insights on how the CLI tool could be used.


Setup

Environment

I am running a Ubuntu instance on AWS on ubuntu user for this walkthrough.

Just in case you do not have access to such file, you can create a local file using this generic default sshd_config file here.๐Ÿ˜ฌ

Installation

To install augtool on Ubuntu, run the following commands

# Get the latest package information
sudo apt-get update -y

# Install Augeas
sudo apt-get install -y augeas-tools

Deepdive into augtool's features

Modes of augtool

  • Non-interactive: This runs augtool as command and you pass augtool specific parameters to parse. You can also use augtool in combination with other native commands such as grep. However, it can be difficult to debug as nothing is printed when there is error in the command.
  • Interactive: This is useful for testing and verifying the nodes to retrieve and update. You can enter interactive mode by entering augtool command in the terminal. Remember to run the save command if you want your changes to be saved!. To exit the augtool CLI, enter quit.
  • Via command file: The -f option in augtool will read commands from a file. You can test and consolidate the commands executed in interactive mode into an external file and used as part of your automation process. This is especially useful if you would like to manage the augtool commands and the main automation scripts separately.
# General Syntax
sudo augtool -s -f "<filename>"

## Example: commands.txt is where all the augtool command used in interactive mode is saved in
sudo augtool -s -f "commands.txt"

"CRUD" Operations

We can take a look at augtool's operations in reading, creating, updating and deleting specific values in the config files. I will be covering the commands used in non-interactive mode.

  • The -s option is included to automatically save all changes at the end of the session. This is important as the changes will not be applied by default.
  • If you would like to try running the commands in the interactive mode, you can do by only using the parameters after the augtool CLI parameters.
## E.g. Printing the setup for /etc/ssh/sshd_config file
## Non-interactive mode
sudo augtool print "/files/etc/ssh/sshd_config"

### Interactive mode
print "/files/etc/ssh/sshd_config"

Read Operation

To get the current setup of your target configuration file

# General Syntax
sudo augtool print "/files/<filename>"

## E.g. Printing the setup for /etc/ssh/sshd_config file
sudo augtool print "/files/etc/ssh/sshd_config"

From here, you will be able to view the hierarchy structure and path to the intended values. AugtoolPrint.png

Create Operation

In my use case, I needed to configure DenyUsers to block specific users from remote SSH access to the instance.

As this parameter does not exists by default, I need to insert a new node into the configuration file. Some caveats for sshd_config file:

  • By default, Augeas will write new parameters at the end of the file
  • In sshd_config, the Match blocks must be located at the end of the file.
  • Augeas will refuse to save the changes in sshd_config file if the Match blocks are not located at the end of the file.
  • To create a new parameter as the right place, you must first create a new Augeas node before the Match section.

I decided to create a new node for the new parameter after the PasswordAuthentication parameter as it is located at the top of the file for ease of finding the parameters later. You can use the ins keyword to create a new node and after keyword to indicate the location of the new node after a specific node.

# General Syntax
sudo augtool -s ins "<param_node_to_insert>" after "<target_parameter_node>"

## Example: Creating new node for DenyUsers parameter to be inserted after the PasswordAuthentication parameter
sudo augtool -s ins "DenyUsers" after "/files/etc/ssh/sshd_config/PasswordAuthentication"

Update Operation

To update the value for the parameter, you can use the set keyword. I will be using an example users with the name user1 and user2 respectively for illustration.

# General Syntax
sudo augtool -s set "/files/<target_file>/<target_param>/<target_position>"

## Example: To configure to deny remote SSH access to user1 and user2
sudo augtool -s set "/files/etc/ssh/sshd_config/DenyUsers/1" "user1"
sudo augtool -s set "/files/etc/ssh/sshd_config/DenyUsers/2" "user2"

OutputFromAugtoolUpdate.png

Delete Operation

To remove a parameter node completely in your configuration, you can use the rm keyword. I will remove user2 from the DenyUsers parameter for illustration.

# General Syntax
 sudo augtool -s rm "/files/<target_file>/<target_param>/<target_position>"

## Example: To remove `user2` from the DenyUsers parameter
 sudo augtool -s rm "/files/etc/ssh/sshd_config/DenyUsers/2"

Other operations

Dynamic retrieval of path to target value

In some use cases, you may want your automation scripts to be able to retrieve the right parameter node. For example, you have multiple users as shown in the image below

AugtoolMultipleUsers.png

You can use the match keyword to find the path to your target node. You can use wildcard (*) if needed.

# General Syntax
sudo augtool match "/files/<target_file>/<target_param>" "<value_to_match>"

## Example trying to find user5
sudo augtool match "/files/etc/ssh/sshd_config/DenyUsers/*" "user5"

Sample Output AugtoolRetrieveSpecific.png

Increment by index

I wanted to append the !/bin/su for a user into the /etc/sudoers file. In the example below, I am using user1 for illustration.

# Original setting
user1      ALL=(ALL) ALL

# Intended setting
user1      ALL=(ALL) ALL,  !/bin/su

In this usage, it illustrates that order matters in the execution. I took reference from hercules-team from Github on how to add nodes to the tree.

# Get the base path
getBasePath=$(sudo augtool match "/files/etc/sudoers/*/user" "user1" | sed 's|\/user||g')

# Configure to restrict su access, get the last index & increment
sudo augtool -s set "$getBasePath/host_group/command[last()+1]" "/bin/su"

# Get the command index after configuring in order to add the negate tag
getCommandPath=$(sudo augtool match "$getBasePath/host_group/command" "/bin/su")
sudo augtool -s set "$getCommandPath/negate"

I initially thought that the negate symbol (!) should be indicated first just like typing the config manually, from left to right. Clearly, that's not how a computer would read ๐Ÿ™ˆ. So yes, the parameter node /bin/su should exists first before attaching the negate tag to it.


Final Thoughts

Depending on how stringent your environment is, augeas-augtool can be integrated into your automation script and may provide a more versatile way to manipulate changes in your configuration files.

In hindsight, I found out from a fellow engineer that the reason why sudo echo did not was due to the elevated privilege being tied to the command echo rather than the required configuration file. I could have used something like echo <some_value> | sudo tee -a <filename> whereby the output is duplicated and append into the target file. Nonetheless, I am grateful to have tried out augeas-augtool.๐Ÿซฐ๐Ÿผ

Hope this article can help you kickstart in using augeas-augtool! Cheers๐Ÿป

Resources

General

Documentation

Did you find this article valuable?

Support Bernice Choy by becoming a sponsor. Any amount is appreciated!

ย