@pgpm/encrypted-secrets 0.15.2 → 0.15.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Makefile +1 -1
- package/README.md +17 -0
- package/package.json +5 -5
- package/pgpm-encrypted-secrets.control +1 -1
- package/__tests__/__snapshots__/secrets.test.ts.snap +0 -28
- package/__tests__/secrets.test.ts +0 -193
- /package/sql/{pgpm-encrypted-secrets--0.14.0.sql → pgpm-encrypted-secrets--0.15.3.sql} +0 -0
package/Makefile
CHANGED
package/README.md
CHANGED
|
@@ -446,6 +446,22 @@ SELECT encrypted_secrets.secrets_upsert('uuid', 'key', 'value');
|
|
|
446
446
|
SELECT * FROM secrets_schema.secrets_table WHERE secrets_owned_field = 'uuid';
|
|
447
447
|
```
|
|
448
448
|
|
|
449
|
+
### With PGPM roles
|
|
450
|
+
|
|
451
|
+
Ensure the standard roles exist before granting:
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
pgpm admin-users bootstrap
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
```sql
|
|
458
|
+
-- Only authenticated users can manage secrets
|
|
459
|
+
GRANT EXECUTE ON FUNCTION encrypted_secrets.secrets_upsert TO authenticated;
|
|
460
|
+
GRANT EXECUTE ON FUNCTION encrypted_secrets.secrets_getter TO authenticated;
|
|
461
|
+
GRANT EXECUTE ON FUNCTION encrypted_secrets.secrets_verify TO authenticated;
|
|
462
|
+
GRANT EXECUTE ON FUNCTION encrypted_secrets.secrets_delete TO authenticated;
|
|
463
|
+
```
|
|
464
|
+
|
|
449
465
|
### With @pgpm/jwt-claims
|
|
450
466
|
|
|
451
467
|
Use JWT claims for owner context:
|
|
@@ -468,6 +484,7 @@ SELECT encrypted_secrets.secrets_getter(
|
|
|
468
484
|
|
|
469
485
|
## Dependencies
|
|
470
486
|
|
|
487
|
+
- PGPM roles (anonymous, authenticated, administrator)
|
|
471
488
|
- `@pgpm/encrypted-secrets-table`: Storage layer
|
|
472
489
|
- `@pgpm/verify`: Verification utilities
|
|
473
490
|
- PostgreSQL pgcrypto extension (for encryption functions)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgpm/encrypted-secrets",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.4",
|
|
4
4
|
"description": "Encrypted secrets management for PostgreSQL",
|
|
5
5
|
"author": "Dan Lynch <pyramation@gmail.com>",
|
|
6
6
|
"contributors": [
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
"test:watch": "jest --watch"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@pgpm/encrypted-secrets-table": "0.15.
|
|
25
|
-
"@pgpm/verify": "0.15.
|
|
24
|
+
"@pgpm/encrypted-secrets-table": "0.15.4",
|
|
25
|
+
"@pgpm/verify": "0.15.4"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"pgpm": "^1.
|
|
28
|
+
"pgpm": "^1.2.2"
|
|
29
29
|
},
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"bugs": {
|
|
36
36
|
"url": "https://github.com/constructive-io/pgpm-modules/issues"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "aad0dbef0336d6c18d027120ef9addc418822edd"
|
|
39
39
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pgpm-encrypted-secrets extension
|
|
2
2
|
comment = 'pgpm-encrypted-secrets extension'
|
|
3
|
-
default_version = '0.
|
|
3
|
+
default_version = '0.15.3'
|
|
4
4
|
module_pathname = '$libdir/pgpm-encrypted-secrets'
|
|
5
5
|
requires = 'pgcrypto,plpgsql,uuid-ossp,pgpm-encrypted-secrets-table,pgpm-verify'
|
|
6
6
|
relocatable = false
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`encrypted secrets encrypt_field_bytea_to_text 1`] = `"value-there-and-back"`;
|
|
4
|
-
|
|
5
|
-
exports[`encrypted secrets encrypt_field_pgp_get 1`] = `"my-secret"`;
|
|
6
|
-
|
|
7
|
-
exports[`encrypted secrets encrypt_field_set 1`] = `
|
|
8
|
-
{
|
|
9
|
-
"data": [
|
|
10
|
-
109,
|
|
11
|
-
121,
|
|
12
|
-
118,
|
|
13
|
-
97,
|
|
14
|
-
108,
|
|
15
|
-
117,
|
|
16
|
-
101,
|
|
17
|
-
],
|
|
18
|
-
"type": "Buffer",
|
|
19
|
-
}
|
|
20
|
-
`;
|
|
21
|
-
|
|
22
|
-
exports[`encrypted secrets secrets_getter 1`] = `"my-secret"`;
|
|
23
|
-
|
|
24
|
-
exports[`encrypted secrets secrets_upsert 1`] = `true`;
|
|
25
|
-
|
|
26
|
-
exports[`encrypted secrets secrets_upsert 2`] = `true`;
|
|
27
|
-
|
|
28
|
-
exports[`encrypted secrets secrets_verify 1`] = `true`;
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import { getConnections, PgTestClient } from 'pgsql-test';
|
|
2
|
-
|
|
3
|
-
let pg: PgTestClient;
|
|
4
|
-
let teardown: () => Promise<void>;
|
|
5
|
-
|
|
6
|
-
const user_id = 'dc474833-318a-41f5-9239-ee563ab657a6';
|
|
7
|
-
|
|
8
|
-
describe('encrypted secrets', () => {
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
({ pg, teardown } = await getConnections());
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
afterAll(async () => {
|
|
14
|
-
await teardown();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
beforeEach(async () => {
|
|
18
|
-
await pg.beforeEach();
|
|
19
|
-
|
|
20
|
-
// Insert test data
|
|
21
|
-
await pg.any(`
|
|
22
|
-
INSERT INTO secrets_schema.secrets_table
|
|
23
|
-
( secrets_owned_field,
|
|
24
|
-
name,
|
|
25
|
-
secrets_value_field,
|
|
26
|
-
secrets_enc_field
|
|
27
|
-
) VALUES
|
|
28
|
-
(
|
|
29
|
-
$1::uuid,
|
|
30
|
-
'my-secret-name',
|
|
31
|
-
'my-secret'::bytea,
|
|
32
|
-
'pgp'
|
|
33
|
-
)
|
|
34
|
-
`, [user_id]);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
afterEach(async () => {
|
|
38
|
-
await pg.afterEach();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('encrypt_field_pgp_get', async () => {
|
|
42
|
-
const [{ encrypt_field_pgp_get }] = await pg.any(
|
|
43
|
-
`SELECT encrypted_secrets.encrypt_field_pgp_get(secrets_value_field, secrets_owned_field::text)
|
|
44
|
-
FROM secrets_schema.secrets_table
|
|
45
|
-
WHERE secrets_owned_field = $1`,
|
|
46
|
-
[user_id]
|
|
47
|
-
);
|
|
48
|
-
expect(encrypt_field_pgp_get).toMatchSnapshot();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('encrypt_field_set', async () => {
|
|
52
|
-
const [{ encrypt_field_set }] = await pg.any(
|
|
53
|
-
`SELECT encrypted_secrets.encrypt_field_set('myvalue')`
|
|
54
|
-
);
|
|
55
|
-
expect(encrypt_field_set).toMatchSnapshot();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('encrypt_field_bytea_to_text', async () => {
|
|
59
|
-
const [{ encrypt_field_bytea_to_text }] = await pg.any(
|
|
60
|
-
`SELECT encrypted_secrets.encrypt_field_bytea_to_text(
|
|
61
|
-
encrypted_secrets.encrypt_field_set('value-there-and-back')
|
|
62
|
-
)`
|
|
63
|
-
);
|
|
64
|
-
expect(encrypt_field_bytea_to_text).toMatchSnapshot();
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('secrets_getter', async () => {
|
|
68
|
-
const [{ secrets_getter }] = await pg.any(
|
|
69
|
-
`SELECT encrypted_secrets.secrets_getter(
|
|
70
|
-
$1::uuid,
|
|
71
|
-
'my-secret-name'
|
|
72
|
-
)`,
|
|
73
|
-
[user_id]
|
|
74
|
-
);
|
|
75
|
-
expect(secrets_getter).toMatchSnapshot();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('secrets_verify', async () => {
|
|
79
|
-
const [{ secrets_verify }] = await pg.any(
|
|
80
|
-
`SELECT encrypted_secrets.secrets_verify(
|
|
81
|
-
$1::uuid,
|
|
82
|
-
'my-secret-name',
|
|
83
|
-
'my-secret'
|
|
84
|
-
)`,
|
|
85
|
-
[user_id]
|
|
86
|
-
);
|
|
87
|
-
expect(secrets_verify).toMatchSnapshot();
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('secrets_upsert', async () => {
|
|
91
|
-
const [{ secrets_upsert }] = await pg.any(
|
|
92
|
-
`SELECT encrypted_secrets.secrets_upsert(
|
|
93
|
-
$1::uuid,
|
|
94
|
-
'my-secret-name',
|
|
95
|
-
'my-secret-other-value'
|
|
96
|
-
)`,
|
|
97
|
-
[user_id]
|
|
98
|
-
);
|
|
99
|
-
expect(secrets_upsert).toMatchSnapshot();
|
|
100
|
-
|
|
101
|
-
const [{ secrets_verify }] = await pg.any(
|
|
102
|
-
`SELECT encrypted_secrets.secrets_verify(
|
|
103
|
-
$1::uuid,
|
|
104
|
-
'my-secret-name',
|
|
105
|
-
'my-secret-other-value'
|
|
106
|
-
)`,
|
|
107
|
-
[user_id]
|
|
108
|
-
);
|
|
109
|
-
expect(secrets_verify).toMatchSnapshot();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('secrets_delete single', async () => {
|
|
113
|
-
// First verify the secret exists
|
|
114
|
-
const [beforeDelete] = await pg.any(
|
|
115
|
-
`SELECT encrypted_secrets.secrets_getter($1::uuid, 'my-secret-name')`,
|
|
116
|
-
[user_id]
|
|
117
|
-
);
|
|
118
|
-
expect(beforeDelete.secrets_getter).toBe('my-secret');
|
|
119
|
-
|
|
120
|
-
// Delete the secret
|
|
121
|
-
await pg.any(
|
|
122
|
-
`SELECT encrypted_secrets.secrets_delete($1::uuid, 'my-secret-name')`,
|
|
123
|
-
[user_id]
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
// Verify it's gone
|
|
127
|
-
const [afterDelete] = await pg.any(
|
|
128
|
-
`SELECT encrypted_secrets.secrets_getter($1::uuid, 'my-secret-name', 'default-value')`,
|
|
129
|
-
[user_id]
|
|
130
|
-
);
|
|
131
|
-
expect(afterDelete.secrets_getter).toBe('default-value');
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it('secrets_delete multiple', async () => {
|
|
135
|
-
// Add multiple secrets
|
|
136
|
-
await pg.any(
|
|
137
|
-
`SELECT encrypted_secrets.secrets_upsert($1::uuid, 'secret-1', 'value-1')`,
|
|
138
|
-
[user_id]
|
|
139
|
-
);
|
|
140
|
-
await pg.any(
|
|
141
|
-
`SELECT encrypted_secrets.secrets_upsert($1::uuid, 'secret-2', 'value-2')`,
|
|
142
|
-
[user_id]
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
// Delete multiple secrets
|
|
146
|
-
await pg.any(
|
|
147
|
-
`SELECT encrypted_secrets.secrets_delete($1::uuid, $2::text[])`,
|
|
148
|
-
[user_id, ['secret-1', 'secret-2']]
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
// Verify they're gone
|
|
152
|
-
const [result1] = await pg.any(
|
|
153
|
-
`SELECT encrypted_secrets.secrets_getter($1::uuid, 'secret-1', 'not-found')`,
|
|
154
|
-
[user_id]
|
|
155
|
-
);
|
|
156
|
-
const [result2] = await pg.any(
|
|
157
|
-
`SELECT encrypted_secrets.secrets_getter($1::uuid, 'secret-2', 'not-found')`,
|
|
158
|
-
[user_id]
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
expect(result1.secrets_getter).toBe('not-found');
|
|
162
|
-
expect(result2.secrets_getter).toBe('not-found');
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
xit('encrypt_field_pgp_getter', async () => {
|
|
166
|
-
const [{ encrypt_field_pgp_getter }] = await pg.any(
|
|
167
|
-
`SELECT encrypted_secrets.encrypt_field_pgp_getter(
|
|
168
|
-
$1::uuid,
|
|
169
|
-
'secrets_value_field',
|
|
170
|
-
'secrets_enc_field'
|
|
171
|
-
)`,
|
|
172
|
-
[user_id]
|
|
173
|
-
);
|
|
174
|
-
expect(encrypt_field_pgp_getter).toMatchSnapshot();
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
xit('secrets_table_upsert', async () => {
|
|
178
|
-
const [{ secrets_table_upsert }] = await pg.any(
|
|
179
|
-
`SELECT encrypted_secrets.secrets_table_upsert(
|
|
180
|
-
$1::uuid,
|
|
181
|
-
$2::json
|
|
182
|
-
)`,
|
|
183
|
-
[
|
|
184
|
-
user_id,
|
|
185
|
-
JSON.stringify({
|
|
186
|
-
myOther: 'secret',
|
|
187
|
-
hiOther: 'here'
|
|
188
|
-
})
|
|
189
|
-
]
|
|
190
|
-
);
|
|
191
|
-
expect(secrets_table_upsert).toMatchSnapshot();
|
|
192
|
-
});
|
|
193
|
-
});
|
|
File without changes
|