yamlock 0.3.0 → 1.0.0
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/README.md +223 -38
- package/bin/yamlock +8 -0
- package/dist/cli/cli.js +457 -74
- package/dist/crypto/decrypt.js +112 -13
- package/dist/crypto/encrypt.js +107 -18
- package/dist/crypto/payload-v2.js +371 -0
- package/dist/crypto/utils.js +65 -14
- package/dist/errors.js +59 -0
- package/dist/index.d.ts +123 -0
- package/dist/index.js +10 -0
- package/dist/utils/config.js +294 -54
- package/dist/utils/file.js +58 -0
- package/dist/utils/migrate.js +170 -0
- package/dist/utils/path.js +58 -9
- package/docs/api.md +56 -0
- package/docs/design/payload-v2.md +344 -0
- package/docs/errors.md +71 -0
- package/docs/yaml-behavior.md +51 -0
- package/examples/basic.js +31 -0
- package/examples/docs/ci-cd.md +58 -0
- package/examples/docs/key-rotation.md +65 -0
- package/package.json +19 -7
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# CI/CD Example: locking configs before deployment
|
|
2
|
+
|
|
3
|
+
This example shows how to decrypt configs for build-time use and re-encrypt
|
|
4
|
+
them with the default authenticated v2 format before artifacts are published.
|
|
5
|
+
It assumes `yamlock` is declared in the project's dependencies or
|
|
6
|
+
devDependencies.
|
|
7
|
+
|
|
8
|
+
```yaml
|
|
9
|
+
# .github/workflows/deploy.yml
|
|
10
|
+
name: deploy
|
|
11
|
+
|
|
12
|
+
on: [push]
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
env:
|
|
18
|
+
YARN_VERSION: 1.22.22
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
deploy:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
|
|
26
|
+
- name: Set up Node
|
|
27
|
+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
28
|
+
with:
|
|
29
|
+
node-version: '22'
|
|
30
|
+
cache: yarn
|
|
31
|
+
|
|
32
|
+
- name: Use Yarn Classic
|
|
33
|
+
run: npm install --global "yarn@$YARN_VERSION"
|
|
34
|
+
|
|
35
|
+
- name: Install deps
|
|
36
|
+
run: yarn install --frozen-lockfile
|
|
37
|
+
|
|
38
|
+
- name: Decrypt configs for build
|
|
39
|
+
run: |
|
|
40
|
+
yarn yamlock decrypt config.yaml --key "$YAMLOCK_KEY"
|
|
41
|
+
yarn yamlock decrypt secrets.json --key "$YAMLOCK_KEY" --paths "db.password,api.token"
|
|
42
|
+
env:
|
|
43
|
+
YAMLOCK_KEY: ${{ secrets.YAMLOCK_KEY }}
|
|
44
|
+
|
|
45
|
+
- name: Build
|
|
46
|
+
run: yarn build
|
|
47
|
+
|
|
48
|
+
- name: Re-encrypt before pushing artifacts
|
|
49
|
+
run: |
|
|
50
|
+
yarn yamlock encrypt config.yaml --key "$YAMLOCK_KEY"
|
|
51
|
+
yarn yamlock encrypt secrets.json --key "$YAMLOCK_KEY" --paths "db.password,api.token"
|
|
52
|
+
env:
|
|
53
|
+
YAMLOCK_KEY: ${{ secrets.YAMLOCK_KEY }}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Adjust the paths/filenames as needed. Keeping encryption in the pipeline helps
|
|
57
|
+
prevent accidental plaintext commits. Add `--legacy` only when a consumer has a
|
|
58
|
+
temporary, documented requirement for v1 payloads.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Key Rotation Guidance
|
|
2
|
+
|
|
3
|
+
This document explains how to rotate encryption keys without losing data or
|
|
4
|
+
leaving plaintext in the working tree longer than necessary. V2 authenticates
|
|
5
|
+
the field path and uses a separate random KDF salt for every value.
|
|
6
|
+
|
|
7
|
+
## Recommended approach
|
|
8
|
+
|
|
9
|
+
1. **Inventory encrypted files**
|
|
10
|
+
Maintain a manifest (for example, a simple `yamlock.files` text file at the repo root) listing every YAML/JSON file that contains encrypted values, one path per line. Example:
|
|
11
|
+
|
|
12
|
+
```txt
|
|
13
|
+
config.yaml
|
|
14
|
+
secrets.json
|
|
15
|
+
infra/prod/environment.yaml
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Reference this file in scripts so rotations stay consistent.
|
|
19
|
+
|
|
20
|
+
2. **Create recoverable backups**
|
|
21
|
+
- Copy encrypted inputs to a protected location before changing them.
|
|
22
|
+
- Keep backup permissions at least as restrictive as the source files.
|
|
23
|
+
- Do not commit decrypted files, keys, or backup archives.
|
|
24
|
+
|
|
25
|
+
3. **Export decrypted configs**
|
|
26
|
+
- Use `yamlock decrypt <file> --key <old-key>` for every file in the manifest.
|
|
27
|
+
- Work in a protected temporary directory outside the repository. Do not use `git stash`: it stores plaintext in Git objects.
|
|
28
|
+
|
|
29
|
+
4. **Set the new key**
|
|
30
|
+
- Generate a fresh key via `yamlock keygen` or your secret manager.
|
|
31
|
+
- Update `YAMLOCK_KEY` in CI secrets, `.env` files, and deployment platforms. Keep the old key accessible until rotation completes.
|
|
32
|
+
|
|
33
|
+
5. **Re-encrypt with the new key**
|
|
34
|
+
- Run `yamlock encrypt <file> --key <new-key>` for each file.
|
|
35
|
+
- The default writer produces authenticated v2 payloads; do not add `--legacy` unless an older consumer explicitly requires v1.
|
|
36
|
+
- Validate using `yamlock decrypt ... --key <new-key>` to confirm round-trips.
|
|
37
|
+
|
|
38
|
+
6. **Deploy carefully**
|
|
39
|
+
- Ship the updated configs only after all environments know about the new key.
|
|
40
|
+
- Monitor for authentication failures, unsupported payload versions, and missing-key errors.
|
|
41
|
+
|
|
42
|
+
7. **Retire the old key**
|
|
43
|
+
- Once every environment reads the re-encrypted configs, revoke the previous key from secret stores.
|
|
44
|
+
|
|
45
|
+
## Automation snippet
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
#!/usr/bin/env bash
|
|
49
|
+
set -euo pipefail
|
|
50
|
+
|
|
51
|
+
FILES=(config.yaml secrets.json infra/cluster.yaml)
|
|
52
|
+
|
|
53
|
+
for file in "${FILES[@]}"; do
|
|
54
|
+
yamlock decrypt "$file" --key "$OLD_KEY"
|
|
55
|
+
yamlock encrypt "$file" --key "$NEW_KEY"
|
|
56
|
+
done
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Run the script from CI to ensure consistency. Store `OLD_KEY` and `NEW_KEY` via environment secrets.
|
|
60
|
+
|
|
61
|
+
## Tips
|
|
62
|
+
|
|
63
|
+
- Keep encrypted backups in protected storage; never put plaintext backups in Git, including stashes.
|
|
64
|
+
- Keep temporary plaintext outside the repository and remove it after verified re-encryption.
|
|
65
|
+
- Audit diffs before committing: only encrypted blobs should change.
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yamlock",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"author": "PAVEL TKACHEV (phoenixweiss) <mail@phoenixweiss.me>",
|
|
5
5
|
"description": "Value-level encryption for YAML/JSON configuration files with CLI + Node.js APIs.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"packageManager": "yarn@1.22.22",
|
|
8
9
|
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
9
11
|
"exports": {
|
|
10
12
|
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
11
14
|
"import": "./dist/index.js"
|
|
12
15
|
},
|
|
13
16
|
"./package.json": "./package.json"
|
|
@@ -18,6 +21,8 @@
|
|
|
18
21
|
"files": [
|
|
19
22
|
"dist",
|
|
20
23
|
"bin",
|
|
24
|
+
"docs",
|
|
25
|
+
"examples",
|
|
21
26
|
"README.md",
|
|
22
27
|
"LICENSE"
|
|
23
28
|
],
|
|
@@ -33,10 +38,15 @@
|
|
|
33
38
|
"node": ">=22.0.0"
|
|
34
39
|
},
|
|
35
40
|
"scripts": {
|
|
36
|
-
"build": "rimraf dist && cp -R src dist",
|
|
41
|
+
"build": "rimraf dist && mkdir -p dist && cp -R src/* dist/",
|
|
42
|
+
"check:docs": "node scripts/check-docs.js",
|
|
43
|
+
"check:release": "node scripts/release-check.js",
|
|
37
44
|
"lint": "eslint .",
|
|
38
45
|
"prepare": "yarn run build",
|
|
39
|
-
"test": "node --test"
|
|
46
|
+
"test": "node --test",
|
|
47
|
+
"test:coverage": "node --test --experimental-test-coverage --test-coverage-include='src/**/*.js' --test-coverage-lines=90 --test-coverage-branches=80 --test-coverage-functions=95",
|
|
48
|
+
"test:types": "yarn run build && tsc --project test/types/tsconfig.json",
|
|
49
|
+
"test:package": "yarn run build && node scripts/package-smoke.js"
|
|
40
50
|
},
|
|
41
51
|
"repository": {
|
|
42
52
|
"type": "git",
|
|
@@ -47,12 +57,14 @@
|
|
|
47
57
|
},
|
|
48
58
|
"homepage": "https://github.com/phoenixweiss/yamlock#readme",
|
|
49
59
|
"dependencies": {
|
|
50
|
-
"js-yaml": "^4.1
|
|
60
|
+
"js-yaml": "^4.3.1"
|
|
51
61
|
},
|
|
52
62
|
"devDependencies": {
|
|
53
|
-
"@eslint/js": "^9.
|
|
54
|
-
"
|
|
63
|
+
"@eslint/js": "^9.39.5",
|
|
64
|
+
"@types/node": "^22.0.0",
|
|
65
|
+
"eslint": "^9.39.5",
|
|
55
66
|
"globals": "^15.0.0",
|
|
56
|
-
"rimraf": "^5.0.5"
|
|
67
|
+
"rimraf": "^5.0.5",
|
|
68
|
+
"typescript": "^5.9.2"
|
|
57
69
|
}
|
|
58
70
|
}
|