Eric Radman : a Journal

Dynamic Credentials

The first step to using a relational database is to start a connection, which you do by supplying a connection string. But where do these credentials come from? The solution to this first step is not at obvious because for a database the connection string may, or I say should contain information about the client. For PostgresSQL this is accomplished by setting application_name,

This is most useful in the pg_stat_activity view

 SELECT usename,client_addr,state,application_name
 FROM pg_stat_activity
 WHERE usename='localharvest';

Execute-only Scripts

A seeminly unique feature of OpenBSD is the ability to run scripts that have execute, but not read permission. This allows one to run script while preventing applications from opening or reading it directly:

$ chmod 710 /etc/cred/localharvest
$ chown www:www /etc/cred/localharvest
$ psql $(/opt/cred/localharvest web_ui)

Where the contents of this script simply format a URL

#!/bin/sh
dbname=localharvest
host=db1
user=localharvest
pass=H55NrCz8U
application=$1
echo "postgresql://$user:$pass@$host/$dbname?application_name=$application:$(whoami):$(hostname -s)"

Establishing a Command Line API

For most platforms removing read access also prevents the execution of scripts. The dyncred(1) utility allows tight control over the way these scripts are used by switching to a credentials user before executing credentials scripts that are not group or world readable.

This establishes an interface for getting credentials that can ultimately be audited or extended if need be

Examples in C

Run dyncred as a subprocess:

FILE *fp;
char url[1024];

fp = popen("dyncred -s localharvest -n web_ui", "r");
fgets(url, 1024, fp);
pclose(fp);

Start an application with a wrapper script and then read from an environment variable

LOCALHARVEST_CREDENTIALS=$(dyncred -s localharvest -n web_ui)
char *url;
url = getenv("LOCALHARVEST_CREDENTIALS");

Last updated on May 15, 2018