key-rotation-manager 1.0.4 → 1.0.6
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 +22 -15
- package/package.json +2 -3
- package/dist/LICENSE +0 -21
- package/dist/README.md +0 -284
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ This library is designed for backend systems that need safe, extensible, and tra
|
|
|
22
22
|
## Installation
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npm install
|
|
25
|
+
npm install key-rotation-manager
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
---
|
|
@@ -30,19 +30,20 @@ npm install rotate-key
|
|
|
30
30
|
## Quick Start
|
|
31
31
|
|
|
32
32
|
```typescript
|
|
33
|
-
import { create } from '
|
|
33
|
+
import { create, km } from 'key-rotation-manager';
|
|
34
34
|
|
|
35
35
|
const keyManager = create({});
|
|
36
|
+
// or
|
|
37
|
+
const keyManager = km({});
|
|
36
38
|
|
|
37
39
|
const { key, path } = await keyManager.newKey({
|
|
38
40
|
type: 'api',
|
|
41
|
+
...options
|
|
39
42
|
});
|
|
40
|
-
|
|
41
|
-
console.log(key, path);
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
This will:
|
|
45
|
-
- Create a `keys/` directory
|
|
46
|
+
- Create a `keys/` directory base on {{path}}/{{filename}}.{{fileExt}}
|
|
46
47
|
- Generate a new key
|
|
47
48
|
- Save it using default storage rules
|
|
48
49
|
|
|
@@ -53,9 +54,11 @@ This will:
|
|
|
53
54
|
### Initialize KeyManager
|
|
54
55
|
|
|
55
56
|
```typescript
|
|
56
|
-
import { create } from '
|
|
57
|
+
import { create, km } from 'key-rotation-manager';
|
|
57
58
|
|
|
58
59
|
const keyManager = create({});
|
|
60
|
+
// or
|
|
61
|
+
const keyManager = km({});
|
|
59
62
|
```
|
|
60
63
|
|
|
61
64
|
On initialization:
|
|
@@ -71,7 +74,7 @@ On initialization:
|
|
|
71
74
|
file: ['{{type}}', 'v', '{{version}}'],
|
|
72
75
|
fileSplitor: '_',
|
|
73
76
|
fileExt: 'json',
|
|
74
|
-
gitIgnore: true,
|
|
77
|
+
gitIgnore: true, // add resolved path to .gitignore
|
|
75
78
|
|
|
76
79
|
crypto: {
|
|
77
80
|
algorithm: 'aes-256-gcm',
|
|
@@ -105,7 +108,7 @@ keys/
|
|
|
105
108
|
### 1. Non-expiring Key
|
|
106
109
|
|
|
107
110
|
```typescript
|
|
108
|
-
const { key } = await
|
|
111
|
+
const { key } = await km.newKey({
|
|
109
112
|
type: 'service',
|
|
110
113
|
});
|
|
111
114
|
```
|
|
@@ -113,7 +116,7 @@ const { key } = await keyManager.newKey({
|
|
|
113
116
|
### 2. Expiring / Rotating Key
|
|
114
117
|
|
|
115
118
|
```typescript
|
|
116
|
-
const { key } = await
|
|
119
|
+
const { key } = await km.newKey({
|
|
117
120
|
type: 'service',
|
|
118
121
|
duration: 30,
|
|
119
122
|
unit: 'seconds',
|
|
@@ -133,7 +136,7 @@ const { key } = await keyManager.newKey({
|
|
|
133
136
|
duration: 30,
|
|
134
137
|
unit: 'seconds',
|
|
135
138
|
rotate: true,
|
|
136
|
-
merge: true,
|
|
139
|
+
merge: true, // Merge into 1 file {{path}}/{filename}
|
|
137
140
|
});
|
|
138
141
|
```
|
|
139
142
|
|
|
@@ -142,12 +145,13 @@ const { key } = await keyManager.newKey({
|
|
|
142
145
|
## Custom Path & File Naming
|
|
143
146
|
|
|
144
147
|
```typescript
|
|
145
|
-
import { create } from '
|
|
148
|
+
import { create } from 'key-rotation-manager';
|
|
146
149
|
|
|
147
150
|
const keyManager = create({
|
|
148
151
|
path: ['keys', 'custom'],
|
|
149
152
|
file: '{{type}}',
|
|
150
153
|
fileExt: 'txt',
|
|
154
|
+
...options,
|
|
151
155
|
});
|
|
152
156
|
```
|
|
153
157
|
|
|
@@ -155,6 +159,9 @@ Resulting structure:
|
|
|
155
159
|
|
|
156
160
|
```
|
|
157
161
|
keys/custom/service.txt
|
|
162
|
+
|
|
163
|
+
>> .gitignore
|
|
164
|
+
keys/custom/*
|
|
158
165
|
```
|
|
159
166
|
|
|
160
167
|
---
|
|
@@ -195,7 +202,7 @@ Returned structure:
|
|
|
195
202
|
```typescript
|
|
196
203
|
{
|
|
197
204
|
ready: Key | null,
|
|
198
|
-
expired
|
|
205
|
+
expired: Key | null
|
|
199
206
|
}
|
|
200
207
|
```
|
|
201
208
|
|
|
@@ -221,8 +228,8 @@ Expired rotate options not provided
|
|
|
221
228
|
|
|
222
229
|
```typescript
|
|
223
230
|
const result = await keyManager.getKey({
|
|
224
|
-
path: '
|
|
225
|
-
version: '
|
|
231
|
+
path: 'path (full path return from km.newKey)',
|
|
232
|
+
version: 'version',
|
|
226
233
|
});
|
|
227
234
|
```
|
|
228
235
|
|
|
@@ -240,7 +247,7 @@ keyManager.useGetKey(async () => {
|
|
|
240
247
|
key: '...',
|
|
241
248
|
hashed: '...',
|
|
242
249
|
type: 'service',
|
|
243
|
-
version: '
|
|
250
|
+
version: 'version',
|
|
244
251
|
rotate: true,
|
|
245
252
|
};
|
|
246
253
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "key-rotation-manager",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Simple, secure key rotation for Node.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -19,8 +19,7 @@
|
|
|
19
19
|
"LICENSE"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
-
"build": "tsup
|
|
23
|
-
"copy-files": "node -e \"const fs=require('fs');['README.md','LICENSE'].forEach(f=>fs.copyFileSync(f,'dist/'+f))\"",
|
|
22
|
+
"build": "tsup",
|
|
24
23
|
"clean": "rimraf dist",
|
|
25
24
|
"lint": "eslint src --ext .ts",
|
|
26
25
|
"lint:fix": "eslint src --ext .ts --fix",
|
package/dist/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/dist/README.md
DELETED
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
# Rotate Key
|
|
2
|
-
|
|
3
|
-
Flexible, file-based key management for Node.js.
|
|
4
|
-
It helps you **generate, store, rotate, and retrieve cryptographic keys** with support for expiration, versioning, merge strategies, custom storage logic, and lifecycle events.
|
|
5
|
-
|
|
6
|
-
This library is designed for backend systems that need safe, extensible, and transparent key handling.
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## Features
|
|
11
|
-
|
|
12
|
-
- 🔐 Secure key generation (AES-256-GCM by default)
|
|
13
|
-
- 🔄 Key expiration & rotation
|
|
14
|
-
- 🗂 File-based storage with configurable structure
|
|
15
|
-
- 🧩 Merge & non-merge key strategies
|
|
16
|
-
- 🔧 Custom save & get hooks
|
|
17
|
-
- 📡 Event-driven lifecycle
|
|
18
|
-
- 📁 Automatic `.gitignore` integration
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Installation
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
npm install rotate-key
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Quick Start
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
import { create } from 'rotate-key';
|
|
34
|
-
|
|
35
|
-
const keyManager = create({});
|
|
36
|
-
|
|
37
|
-
const { key, path } = await keyManager.newKey({
|
|
38
|
-
type: 'api',
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
console.log(key, path);
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
This will:
|
|
45
|
-
- Create a `keys/` directory
|
|
46
|
-
- Generate a new key
|
|
47
|
-
- Save it using default storage rules
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## Basic Usage
|
|
52
|
-
|
|
53
|
-
### Initialize KeyManager
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import { create } from 'rotate-key';
|
|
57
|
-
|
|
58
|
-
const keyManager = create({});
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
On initialization:
|
|
62
|
-
- The key storage folder is created
|
|
63
|
-
- `.gitignore` is updated (if enabled)
|
|
64
|
-
- A store initialization event is emitted
|
|
65
|
-
|
|
66
|
-
### Default Configuration
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
{
|
|
70
|
-
path: ['keys'],
|
|
71
|
-
file: ['{{type}}', 'v', '{{version}}'],
|
|
72
|
-
fileSplitor: '_',
|
|
73
|
-
fileExt: 'json',
|
|
74
|
-
gitIgnore: true,
|
|
75
|
-
|
|
76
|
-
crypto: {
|
|
77
|
-
algorithm: 'aes-256-gcm',
|
|
78
|
-
kdf: 'scrypt',
|
|
79
|
-
hashAlgorithm: 'sha256',
|
|
80
|
-
keyLength: 32,
|
|
81
|
-
ivLength: 16,
|
|
82
|
-
saltLength: 32,
|
|
83
|
-
tagLength: 16,
|
|
84
|
-
iterations: 100000,
|
|
85
|
-
encoding: 'base64',
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
versionGenerator: () => Date.now().toString()
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### File Structure
|
|
93
|
-
|
|
94
|
-
With default settings, keys are stored as:
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
keys/
|
|
98
|
-
└── api_v_1700000000000.json
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## Creating Keys
|
|
104
|
-
|
|
105
|
-
### 1. Non-expiring Key
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
const { key } = await keyManager.newKey({
|
|
109
|
-
type: 'service',
|
|
110
|
-
});
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### 2. Expiring / Rotating Key
|
|
114
|
-
|
|
115
|
-
```typescript
|
|
116
|
-
const { key } = await keyManager.newKey({
|
|
117
|
-
type: 'service',
|
|
118
|
-
duration: 30,
|
|
119
|
-
unit: 'seconds',
|
|
120
|
-
rotate: true,
|
|
121
|
-
});
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
The key expires after 30 seconds and requires rotation.
|
|
125
|
-
|
|
126
|
-
### 3. Merge Strategy
|
|
127
|
-
|
|
128
|
-
Merge mode stores multiple key versions in a single file.
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
const { key } = await keyManager.newKey({
|
|
132
|
-
type: 'service',
|
|
133
|
-
duration: 30,
|
|
134
|
-
unit: 'seconds',
|
|
135
|
-
rotate: true,
|
|
136
|
-
merge: true,
|
|
137
|
-
});
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## Custom Path & File Naming
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
import { create } from 'rotate-key';
|
|
146
|
-
|
|
147
|
-
const keyManager = create({
|
|
148
|
-
path: ['keys', 'custom'],
|
|
149
|
-
file: '{{type}}',
|
|
150
|
-
fileExt: 'txt',
|
|
151
|
-
});
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
Resulting structure:
|
|
155
|
-
|
|
156
|
-
```
|
|
157
|
-
keys/custom/service.txt
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## Custom Save Logic
|
|
163
|
-
|
|
164
|
-
Override how and where keys are saved:
|
|
165
|
-
|
|
166
|
-
```typescript
|
|
167
|
-
keyManager.useSaveKey(async () => {
|
|
168
|
-
return '/absolute/custom/path/key.json';
|
|
169
|
-
});
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
The returned value becomes `key.path`.
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
|
|
176
|
-
## Retrieving Keys
|
|
177
|
-
|
|
178
|
-
### Rotate Key (Valid)
|
|
179
|
-
|
|
180
|
-
```typescript
|
|
181
|
-
const result = await keyManager.getKey({
|
|
182
|
-
path: 'keys/service_merge.json',
|
|
183
|
-
version: 'rotate',
|
|
184
|
-
onRotate: {
|
|
185
|
-
duration: 30,
|
|
186
|
-
unit: 'seconds',
|
|
187
|
-
rotate: true,
|
|
188
|
-
merge: true,
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
Returned structure:
|
|
194
|
-
|
|
195
|
-
```typescript
|
|
196
|
-
{
|
|
197
|
-
ready: Key | null,
|
|
198
|
-
expired?: Key
|
|
199
|
-
}
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
- `ready` → usable key
|
|
203
|
-
- `expired` → expired key (if rotation occurred)
|
|
204
|
-
|
|
205
|
-
### Rotate Key (Invalid – Missing Options)
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
await keyManager.getKey({
|
|
209
|
-
path: 'keys/service_merge.json',
|
|
210
|
-
version: 'rotate-invalid',
|
|
211
|
-
});
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
Throws:
|
|
215
|
-
|
|
216
|
-
```
|
|
217
|
-
Expired rotate options not provided
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### Non-Rotating Key
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
const result = await keyManager.getKey({
|
|
224
|
-
path: 'keys/service_merge.json',
|
|
225
|
-
version: 'non-rotate',
|
|
226
|
-
});
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
---
|
|
230
|
-
|
|
231
|
-
## Custom Get Logic
|
|
232
|
-
|
|
233
|
-
Override how keys are retrieved:
|
|
234
|
-
|
|
235
|
-
```typescript
|
|
236
|
-
keyManager.useGetKey(async () => {
|
|
237
|
-
return {
|
|
238
|
-
from: '2025-12-29T01:23:27.882Z',
|
|
239
|
-
to: '2099-12-29T01:23:57.882Z',
|
|
240
|
-
key: '...',
|
|
241
|
-
hashed: '...',
|
|
242
|
-
type: 'service',
|
|
243
|
-
version: 'rotate',
|
|
244
|
-
rotate: true,
|
|
245
|
-
};
|
|
246
|
-
});
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Return `null` to indicate an invalid or missing key.
|
|
250
|
-
|
|
251
|
-
---
|
|
252
|
-
|
|
253
|
-
## Events
|
|
254
|
-
|
|
255
|
-
KeyManager emits lifecycle events.
|
|
256
|
-
|
|
257
|
-
### Store Initialization Event
|
|
258
|
-
|
|
259
|
-
```typescript
|
|
260
|
-
import { create, types } from 'rotate-key';
|
|
261
|
-
const { EEvent } = types;
|
|
262
|
-
const keyManager = create({});
|
|
263
|
-
|
|
264
|
-
keyManager.once(EEvent.STORE_INIT_FOLDER, ({ storePath }) => {
|
|
265
|
-
console.log('Key store initialized at:', storePath);
|
|
266
|
-
});
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
---
|
|
270
|
-
|
|
271
|
-
## Use Cases
|
|
272
|
-
|
|
273
|
-
- API key management
|
|
274
|
-
- Token & credential rotation
|
|
275
|
-
- Secure file-based secrets
|
|
276
|
-
- Multi-version key handling
|
|
277
|
-
- Custom persistence strategies
|
|
278
|
-
- Backend Node.js services
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
## License
|
|
283
|
-
|
|
284
|
-
MIT
|