Skip to content

Add initial version of pg-password-util with support for md5 and scram-sha-256 #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
},
};
59 changes: 59 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
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/*'
- 'latest'
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
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