Skip to content

Commit

Permalink
Add initial version of pg-password-util with support for md5 and scra…
Browse files Browse the repository at this point in the history
…m-sha-256
  • Loading branch information
sehrope committed Jan 5, 2024
1 parent 666c039 commit b5cd4cc
Show file tree
Hide file tree
Showing 12 changed files with 6,424 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
"@typescript-eslint/no-explicit-any": "off"
},
};
60 changes: 60 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: CI

on:
pull_request:
branches:
- '*'
paths-ignore:
- 'docs/**'
- '**/*.md'

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Lint
run: make clean deps lint

test:
name: Test - Node v${{ matrix.node_version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node_version:
- '16'
- '18'
- '20'
- 'lts/-0'
- 'lts/-1'
- 'latest'
steps:
- uses: actions/checkout@v2
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node_version }}
cache: npm
- name: Compile
run: make clean deps compile
- name: Setup Postgres
env:
DOCKER_OPTS: '--detach'
run: |
bin/postgres-server
for i in {1..10}
do
if pg_isready -h 127.0.0.1
then
break
fi
sleep 1
done
- name: Test
run: make test-cov
- name: Upload Coverage
uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
coverage
.env
lib
node_modules
.nyc_output
scratch
# Dummy change goes here v2
13 changes: 13 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
bin
coverage
.env
.eslintrc.js
examples
.github/**
Makefile
.nyc_output
scratch
src
test
.travis.yml
tsconfig.json
40 changes: 40 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
default: deps compile

deps: node_modules

node_modules:
npm ci

clean:
rm -rf lib node_modules coverage

compile:
node_modules/.bin/tsc --declaration

watch:
node_modules/.bin/tsc --watch --declaration

test:
node_modules/.bin/ts-mocha test/suite.ts --exit $(TEST_ARGS)

clean-cov:
rm -rf coverage

test-cov:
node_modules/.bin/c8 \
--require source-map-support/register \
--require ts-node/register \
--reporter=html \
--reporter=lcov \
--extension .ts \
node_modules/.bin/ts-mocha --exit test/suite.ts

lint:
node_modules/.bin/eslint src

package: clean deps compile

publish: package test
npm publish

.PHONY: default deps clean compile test test-cov watch package publish
96 changes: 96 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# pg-password-util

[![NPM](https://nodei.co/npm/pg-query-exec.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/pg-query-exec/)

# Overview
Utility library for password encoding for PostgreSQL.

This solves the problem of plaintext passwords appearing in server logs by replacing:

```sql
ALTER USER app PASSWORD 'Super Duper Secret!'
```

With the password encoded client side:

```sql
ALTER USER app PASSWORD 'SCRAM-SHA-256$4096:M1A3zTFR9TzaX5NuvytilQ==$TZtMCtrZ8wkkZVkS7vursem77PsBqthl8GqkPohscJw=:POfEEJ9BOrm6upeAFKU3awWqMg+kKYXyPOG5E5tuhJc='
```

That hashed value does not contain the plaintext of the password and matches how the PostgreSQL stores the value in `pg_shadow`.

* [Install](#install)
* [Usage](#usage)
* [Features](#features)
* [Building and Testing](#building-and-testing)
* [License](#license)

# Install

$ npm install pg-password-util

# Dependencies

The only direct dependency is [`pg-format`](https://www.npmjs.com/package/pg-format) used to escape literals and identifiers.

The ALTER USER helpers accept a `client` argument that must provide the same signature as `pg.Client` (i.e. the client from the [`pg`](https://www.npmjs.com/package/pg) node-postgres driver). It's not a direct dependency of this module though.

# Features
* Encoding passwords using SCRAM-SHA-256 (recommended)
* Encoding passwords using md5 (for legacy systems)
* Generating SQL to change a user's password
* Inferring the password_encryption from the target database

# Usage
## Generate SQL for an ALTER USER to change a password

```typescript
import { genAlterUserPasswordSql } = require('pg-password-util');

const sql = genAlterUserPasswordSql({
username: 'app',
password: 'my-new-secret-password',
passwordEncryption: 'scram-sha-256',
});
```
## Generate encoded password for use in a custom CREATE USER statement
```typescript
import { encodeScramSha256 } = require('pg-password-util');
import * as pgFormat from 'pg-format';

const encodedPassword = encodeScramSha256({
password: 'my-new-secret-password',
iterations: 10000,
});
const sql = pgFormat('CREATE USER app PASSWORD %L LOGIN', encodedPassword);
```

## Change a user's password

```typescript
import { alterUserPassword } = require('pg-password-util');

// client is a pg.Client
await alterUserPassword(client, {
username: 'app',
password: 'my-new-secret-password',
});
```
# Building and Testing
To build the module run:
$ make
Testing requires a PostgreSQL database. You can start one in the foreground via:
$ bin/postgres-server
Then, to run the tests run:
$ make test
# License
ISC. See the file [LICENSE](LICENSE).
14 changes: 14 additions & 0 deletions bin/postgres-server
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail

main () {
exec docker run \
${DOCKER_OPTS:-} \
--rm \
--env POSTGRES_PASSWORD=dbpass \
--env POSTGRES_HOST_AUTH_METHOD=md5 \
--publish 5432:5432 \
postgres
}

main "$@"
Loading

0 comments on commit b5cd4cc

Please sign in to comment.