Skip to content

Instantly share code, notes, and snippets.

@mattupstate mattupstate/resources.tf
Last active Sep 29, 2019

Embed
What would you like to do?
Just a clever way to set an RDS master password with Terraform and Ansible to prevent the password from being stored in plain text
resource "aws_db_instance" "core" {
username = "postgres"
password = "changeme"
...
}
resource "null_resource" "master_password" {
triggers {
db_host = "${aws_db_instance.address}"
}
provisioner "local-exec" {
command = "ansible localhost -e @path/to/secrets.yml --vault-password-file path/to/vault.txt -a 'set-postgres-master-password --host ${aws_db_instance.address} --password changeme --new-password {{ my_new_master_password }}'"
}
}
#!/usr/bin/env python
import argparse
import psycopg2
def main(host, port, user, password, newpassword):
sql = "ALTER ROLE %s WITH PASSWORD '%s';" % (user, newpassword)
conn_str = 'host=%s user=%s password=%s' % (host, user, password)
connection = psycopg2.connect(conn_str)
cursor = connection.cursor()
cursor.execute(sql)
connection.commit()
cursor.close()
connection.close()
print('New password set successfully')
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Sets a PostgreSQL database master password')
parser.add_argument('--user', dest='user', default='postgres',
help='the master username')
parser.add_argument('--password', dest='password', required=True,
help='the current master username')
parser.add_argument('--new-password', dest='newpassword', required=True,
help='the new password')
parser.add_argument('--host', dest='host', required=True,
help='the host to connect to')
parser.add_argument('--port', dest='port', default=5432,
help='the port to connect to')
args = parser.parse_args()
main(args.host, args.port, args.user, args.password, args.newpassword)
@calve

This comment has been minimized.

Copy link

commented Sep 21, 2018

--new-password {{ my_new_master_password }} might leak in your local history or be logged by process watching execve() like snoopylogger

@calve

This comment has been minimized.

Copy link

commented Sep 21, 2018

Should be better to pass it as an environment variables or read it from a file 🙂

@junkert

This comment has been minimized.

Copy link

commented Oct 23, 2018

Or even better yet use -> https://docs.python.org/2/library/getpass.html and if you need to use an ENV variable or something else you just PIPE it into the script. This way .history does not contain the password.

echo -e "$PASSWORD_OLD\n$PASSWORD_NEW\n" | ./set-postgres-master-password.py --user=master_user
@rdonkin

This comment has been minimized.

Copy link

commented Feb 5, 2019

The Terraform part is useful but the Python script isn't necessary with RDS (though it might be useful with standard Postgres) - just use this AWS CLI command:

aws rds modify-db-instance --db-instance-identifier mydb --master-user-password mypassword

This requires an IAM user/role with the right permissions to modify the RDS DB instance.

@smiller171

This comment has been minimized.

Copy link

commented Mar 27, 2019

Note: It's been pointed out that my way keeps the password in the Terraform State. Use your best judgement about whether you can trust your Terraform statefile for this.

You can actually just generate the password on the fly https://gist.github.com/smiller171/6be734957e30c5d4e4b15422634f13f4

@tonglil

This comment has been minimized.

Copy link

commented Jun 10, 2019

@smiller171 in your gist the db password (random string) is still stored in tf state file. This solution actually changes the password to something else so even if the state file is breached, it is has a dummy password.

@smiller171

This comment has been minimized.

Copy link

commented Jun 11, 2019

@smiller171 in your gist the db password (random string) is still stored in tf state file. This solution actually changes the password to something else so even if the state file is breached, it is has a dummy password.

That's fair. In my case my statefile is encrypted in S3 so this is an acceptable risk to be able to manage it this way, but I definitely see the advantage to your way.

@tonglil

This comment has been minimized.

Copy link

commented Jun 12, 2019

Not a criticism just pointing it out in case anyone reads this and assumes the alternative does the same thing as this one.

If one is storing the state in s3 then it's fair enough to source the password from a file on disk through an env var.

@smiller171

This comment has been minimized.

Copy link

commented Jun 12, 2019

@tonglil I've updated my original comment to reflect the added risk in case anyone doesn't read this far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.