aboutsummaryrefslogtreecommitdiff

infrastructure

A shell-based configuration management framework for unix-like systems.

boxconf

boxconf is an extremely simple config management system written in shell. As long as you can SSH to the remote system (or "box") as root, the only requirement is a POSIX-compliant sh(1) and coreutils. It was inspired by many years of frustration with Ansible.

Running boxconf

To execute boxconf on a target host, just run the following:

./boxconf $HOSTNAME

A deployment tarball will be generated and SCP'd to the remote box, where boxconf will re-exec itself. After gathering some information about the target system (such as the operating system, IP address, etc), boxconf will source your scripts in the following order:

     vars/common
site/vars/common
     vars/os/${os}
site/vars/os/${os}
     vars/distro/${distro}
site/vars/distro/${distro}
     vars/hostclass/${hostclass}
site/vars/hostclass/${hostclass}
     vars/hostname/${hostname}
site/vars/hostname/${hostname}

     scripts/common
site/scripts/common
     scripts/os/${os}
site/scripts/os/${os}
     scripts/distro/${distro}
site/scripts/distro/${distro}
     scripts/hostclass/${hostclass}
site/scripts/hostclass/${hostclass}
     scripts/hostname/${hostname}
site/scripts/hostname/${hostname}

If any of those paths point to a directory, boxconf will source all files in that directory in glob order.

The site/ directory does not exist in this repo. Its purpose is to hold personal site-specific variables and scripts that you would rather not share in a public git repo. Ideally, you would use git submodules for this.

If the hostname does not exist in DNS, you can manually specify the SSH target by passing the -s $IP_ADDRESS option to boxconf.

The hostclass value is matched based on the regular expressions listed in the hostclasses file.

Encrypting source files

boxconf supports encrypting any script or file using OpenSSL's pbkdf2. The encrypted file will be automatically decrypted when generating the deployment tarball. The encryption password is read from the BOXCONF_VAULT_PASSWORD environment variable or the .vault_password file. If nether is set, you will be prompted for the password interactively.

The vault script in the root of this directory can be used to manage encrypted files.

Copying files to the remote host

From your boxconf scripts, you can copy files in the files/ (or site/files/) directory to the target system using the install_file function. The source file should have the same path as the remote path, and it can be tailored to the remote system by adding a custom suffix. For example, if you ran the following code:

install_file -m 0644 /etc/passwd

Then the following paths would be searched to find a suitable file to copy into the target system (the first match wins):

site/files/etc/passwd.${hostname}
     files/etc/passwd.${hostname}
site/files/etc/passwd.${hostclass}.${distro}
     files/etc/passwd.${hostclass}.${distro}
site/files/etc/passwd.${distro}.${hostclass}
     files/etc/passwd.${distro}.${hostclass}
site/files/etc/passwd.${hostclass}.${os}
     files/etc/passwd.${hostclass}.${os}
site/files/etc/passwd.${os}.${hostclass}
     files/etc/passwd.${os}.${hostclass}
site/files/etc/passwd.${hostclass}
     files/etc/passwd.${hostclass}
site/files/etc/passwd.${distro}
     files/etc/passwd.${distro}
site/files/etc/passwd.${os}
     files/etc/passwd.${os}
site/files/etc/passwd.common
     files/etc/passwd.common

If you use the install_template function, then the same file matching logic applies. However, the content of the matched file will be treated like a heredoc, allowing you to do things like interpolate ${shell_variables} and perform $(process_substitution) within the file content. Note that if you do this, you must esacape any shell characters (like $) as needed.

Copying TLS certificates

The install_certificate and install_certificate_key functions can be used to copy certificates from the site/ca directory to the remote host. The certificates should be created and managed using the included pki script.

Note that certificate keys are also encrypted with $BOXCONF_VAULT_PASSWORD. They are automatically decrypted when generating the configuration tarball.

vault

The vault script is used to manage encrypted files using OpenSSL's pbkdf2. The encryption password is read from the BOXCONF_VAULT_PASSWORD environment variable or the .vault_password file.

Create a new encrypted file

The following command will invoke $EDITOR to create a new encrypted file at the specified path.

./vault create passwords.txt

Decrypt file(s)

The plaintext content of the file(s) will be written to stdout.

./vault decrypt secrets.txt

Edit an encrypted file

The file will be decrypted to a temporary file before being opened with $EDITOR. When the editor is closed, the file is encrypted again.

./vault edit passwords.txt

Encrypt an existing file

Encrypt an existing file in place:

./vault encrypt plain.txt

Re-encrypt file(s) with a different password

The new password is read from the VAULT_NEW_PASSWORD environment variable. If this variable is unset, you will be prompted interactively.

./vault reencrypt secrets.txt

pki

The pki script is used to manage an internal certificate authority using OpenSSL.

Certificates and private keys are stored in the 'site/ca' directory with human-readable names. The certificatess are mapped to their OpenSSL serial number via symlinks.

The private keys are encrypted with the BOXCONF_VAULT_PASSWORD variable, as described previously. The private key of the CA itself is acquired from the CA_PASSWORD environment variable, or the .ca_password file.

Every certificate is associated with a single boxconf hostname, along with a unique certificate name. This allows you to store multiple certificates per host.

Initialize the CA

pki init will create the CA certificate and private key, along with an OpenSSL configuration file. Name constraints for the CA can be added with the -c option.

For example, this command creates a CA for the example.com domain. This CA can sign certificates for all subdomains of example.com and example.net, as well as plain IP addresses in the 192.168.0.0/24 subnet:

./pki init -c 192.168.0.0/255.255.255.0 -c example.net example.com

Create a server certificate

pki cert creates a server certificate keypair signed by the CA.

For example, this command creates a certificate pair for nginx for the host webserver1 with a 365 day expiration (-d). After the hostname and certificate name, each additional argument is added to the Subject Alternative Names field.

The Common Name is taken from the first specified SAN. If you don't specify a type for the SAN, DNS is assumed.

./pki cert -d 365 webserver1 nginx www.example.com DNS:example.com IP:192.168.0.5

Create a client certificate

pki client-cert creates a client certificate keypair signed by the CA.

After the hostname and certificate name, the first argument must be an LDAP-style DN for the certificate's Common Name value. SANs can be specified using additional arguments in same way as described previously.

./pki client-cert -d 3650 ldap1 replicator cn=replicator,dc=idm,dc=example,dc=com

Renew a certificate

pki renew is used to renew an existing certificate.

./pki renew -d 365 webserver1 nginx