envhub-cli 0.1.1
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 +60 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +92 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/cat.d.ts +6 -0
- package/dist/commands/cat.d.ts.map +1 -0
- package/dist/commands/cat.js +55 -0
- package/dist/commands/cat.js.map +1 -0
- package/dist/commands/delete.d.ts +10 -0
- package/dist/commands/delete.d.ts.map +1 -0
- package/dist/commands/delete.js +46 -0
- package/dist/commands/delete.js.map +1 -0
- package/dist/commands/grant.d.ts +6 -0
- package/dist/commands/grant.d.ts.map +1 -0
- package/dist/commands/grant.js +25 -0
- package/dist/commands/grant.js.map +1 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +275 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +6 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +46 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/pull.d.ts +6 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +35 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +11 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +126 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/revoke.d.ts +6 -0
- package/dist/commands/revoke.d.ts.map +1 -0
- package/dist/commands/revoke.js +25 -0
- package/dist/commands/revoke.js.map +1 -0
- package/dist/config/config.d.ts +52 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +136 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/config.schema.d.ts +66 -0
- package/dist/config/config.schema.d.ts.map +1 -0
- package/dist/config/config.schema.js +33 -0
- package/dist/config/config.schema.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/aws/aws-secrets.provider.d.ts +44 -0
- package/dist/providers/aws/aws-secrets.provider.d.ts.map +1 -0
- package/dist/providers/aws/aws-secrets.provider.js +306 -0
- package/dist/providers/aws/aws-secrets.provider.js.map +1 -0
- package/dist/providers/provider.factory.d.ts +24 -0
- package/dist/providers/provider.factory.d.ts.map +1 -0
- package/dist/providers/provider.factory.js +40 -0
- package/dist/providers/provider.factory.js.map +1 -0
- package/dist/providers/provider.interface.d.ts +96 -0
- package/dist/providers/provider.interface.d.ts.map +1 -0
- package/dist/providers/provider.interface.js +2 -0
- package/dist/providers/provider.interface.js.map +1 -0
- package/dist/utils/diff.d.ts +27 -0
- package/dist/utils/diff.d.ts.map +1 -0
- package/dist/utils/diff.js +105 -0
- package/dist/utils/diff.js.map +1 -0
- package/dist/utils/env-parser.d.ts +48 -0
- package/dist/utils/env-parser.d.ts.map +1 -0
- package/dist/utils/env-parser.js +84 -0
- package/dist/utils/env-parser.js.map +1 -0
- package/dist/utils/logger.d.ts +57 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +82 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/versioning/version-control.d.ts +44 -0
- package/dist/versioning/version-control.d.ts.map +1 -0
- package/dist/versioning/version-control.js +81 -0
- package/dist/versioning/version-control.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createProgram } from "./cli.js";
|
|
3
|
+
import { logger } from "./utils/logger.js";
|
|
4
|
+
const program = createProgram();
|
|
5
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
6
|
+
if (error instanceof Error) {
|
|
7
|
+
logger.error(error.message);
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
logger.error("An unexpected error occurred.");
|
|
11
|
+
}
|
|
12
|
+
process.exit(1);
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAEhC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACxD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AWSConfig } from "../../config/config.schema.js";
|
|
2
|
+
import type { SecretProvider, PushOptions, PushResult, PullResult, SecretListItem, DeleteOptions } from "../provider.interface.js";
|
|
3
|
+
/**
|
|
4
|
+
* AWS Secrets Manager implementation of the SecretProvider interface.
|
|
5
|
+
*
|
|
6
|
+
* Stores .env file contents as JSON payloads in AWS Secrets Manager,
|
|
7
|
+
* prefixed with a configurable namespace (default: "envhub-").
|
|
8
|
+
*/
|
|
9
|
+
export declare class AWSSecretsProvider implements SecretProvider {
|
|
10
|
+
readonly name = "aws";
|
|
11
|
+
private client;
|
|
12
|
+
private iamClient;
|
|
13
|
+
private prefix;
|
|
14
|
+
constructor(config: AWSConfig, prefix?: string);
|
|
15
|
+
/**
|
|
16
|
+
* Get the full secret name with prefix.
|
|
17
|
+
*/
|
|
18
|
+
private fullName;
|
|
19
|
+
/**
|
|
20
|
+
* Strip the prefix from a full secret name.
|
|
21
|
+
*/
|
|
22
|
+
private stripPrefix;
|
|
23
|
+
/**
|
|
24
|
+
* Check if a secret exists.
|
|
25
|
+
*/
|
|
26
|
+
private secretExists;
|
|
27
|
+
/**
|
|
28
|
+
* Read the current payload from a secret.
|
|
29
|
+
*/
|
|
30
|
+
private getPayload;
|
|
31
|
+
push(secretName: string, content: string, options?: PushOptions): Promise<PushResult>;
|
|
32
|
+
pull(secretName: string): Promise<PullResult>;
|
|
33
|
+
cat(secretName: string): Promise<string>;
|
|
34
|
+
list(): Promise<SecretListItem[]>;
|
|
35
|
+
delete(secretName: string, options?: DeleteOptions): Promise<void>;
|
|
36
|
+
grant(secretName: string, userIdentifier: string): Promise<void>;
|
|
37
|
+
revoke(secretName: string, userIdentifier: string): Promise<void>;
|
|
38
|
+
getVersion(secretName: string): Promise<number>;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a user identifier (username or ARN) to a full ARN.
|
|
41
|
+
*/
|
|
42
|
+
private resolveUserArn;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=aws-secrets.provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-secrets.provider.d.ts","sourceRoot":"","sources":["../../../src/providers/aws/aws-secrets.provider.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,UAAU,EACV,UAAU,EACV,cAAc,EACd,aAAa,EACd,MAAM,0BAA0B,CAAC;AAqBlC;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,cAAc;IACvD,QAAQ,CAAC,IAAI,SAAS;IACtB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,SAAS,EAAE,MAAM,GAAE,MAAkB;IAgBzD;;OAEG;IACH,OAAO,CAAC,QAAQ;IAIhB;;OAEG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;YACW,YAAY;IAc1B;;OAEG;YACW,UAAU;IAclB,IAAI,CACR,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,UAAU,CAAC;IAmDhB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAU7C,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKxC,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAmDjC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2DhE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgEjE,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAcrD;;OAEG;YACW,cAAc;CAwB7B"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { SecretsManagerClient, CreateSecretCommand, GetSecretValueCommand, UpdateSecretCommand, ListSecretsCommand, DeleteSecretCommand, DescribeSecretCommand, GetResourcePolicyCommand, PutResourcePolicyCommand, DeleteResourcePolicyCommand, ResourceNotFoundException, } from "@aws-sdk/client-secrets-manager";
|
|
2
|
+
import { IAMClient, GetUserCommand, } from "@aws-sdk/client-iam";
|
|
3
|
+
import { fromIni } from "@aws-sdk/credential-providers";
|
|
4
|
+
import { parseEnvContent } from "../../utils/env-parser.js";
|
|
5
|
+
/**
|
|
6
|
+
* AWS Secrets Manager implementation of the SecretProvider interface.
|
|
7
|
+
*
|
|
8
|
+
* Stores .env file contents as JSON payloads in AWS Secrets Manager,
|
|
9
|
+
* prefixed with a configurable namespace (default: "envhub-").
|
|
10
|
+
*/
|
|
11
|
+
export class AWSSecretsProvider {
|
|
12
|
+
name = "aws";
|
|
13
|
+
client;
|
|
14
|
+
iamClient;
|
|
15
|
+
prefix;
|
|
16
|
+
constructor(config, prefix = "envhub-") {
|
|
17
|
+
const credentials = fromIni({ profile: config.profile });
|
|
18
|
+
this.client = new SecretsManagerClient({
|
|
19
|
+
region: config.region,
|
|
20
|
+
credentials,
|
|
21
|
+
});
|
|
22
|
+
this.iamClient = new IAMClient({
|
|
23
|
+
region: config.region,
|
|
24
|
+
credentials,
|
|
25
|
+
});
|
|
26
|
+
this.prefix = prefix;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the full secret name with prefix.
|
|
30
|
+
*/
|
|
31
|
+
fullName(secretName) {
|
|
32
|
+
return `${this.prefix}${secretName}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Strip the prefix from a full secret name.
|
|
36
|
+
*/
|
|
37
|
+
stripPrefix(fullName) {
|
|
38
|
+
if (fullName.startsWith(this.prefix)) {
|
|
39
|
+
return fullName.substring(this.prefix.length);
|
|
40
|
+
}
|
|
41
|
+
return fullName;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if a secret exists.
|
|
45
|
+
*/
|
|
46
|
+
async secretExists(secretName) {
|
|
47
|
+
try {
|
|
48
|
+
await this.client.send(new DescribeSecretCommand({ SecretId: this.fullName(secretName) }));
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (error instanceof ResourceNotFoundException) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Read the current payload from a secret.
|
|
60
|
+
*/
|
|
61
|
+
async getPayload(secretName) {
|
|
62
|
+
const result = await this.client.send(new GetSecretValueCommand({ SecretId: this.fullName(secretName) }));
|
|
63
|
+
if (!result.SecretString) {
|
|
64
|
+
throw new Error(`Secret '${secretName}' has no string content.`);
|
|
65
|
+
}
|
|
66
|
+
return JSON.parse(result.SecretString);
|
|
67
|
+
}
|
|
68
|
+
// ── Core Operations ──────────────────────────────────────────────
|
|
69
|
+
async push(secretName, content, options) {
|
|
70
|
+
const exists = await this.secretExists(secretName);
|
|
71
|
+
let newVersion;
|
|
72
|
+
if (exists) {
|
|
73
|
+
// Get current version
|
|
74
|
+
const currentPayload = await this.getPayload(secretName);
|
|
75
|
+
newVersion = currentPayload.metadata.version + 1;
|
|
76
|
+
const payload = {
|
|
77
|
+
content,
|
|
78
|
+
metadata: {
|
|
79
|
+
version: newVersion,
|
|
80
|
+
message: options?.message,
|
|
81
|
+
updatedAt: new Date().toISOString(),
|
|
82
|
+
managedBy: "envhub-cli",
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
await this.client.send(new UpdateSecretCommand({
|
|
86
|
+
SecretId: this.fullName(secretName),
|
|
87
|
+
SecretString: JSON.stringify(payload),
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Create new secret
|
|
92
|
+
newVersion = 1;
|
|
93
|
+
const payload = {
|
|
94
|
+
content,
|
|
95
|
+
metadata: {
|
|
96
|
+
version: newVersion,
|
|
97
|
+
message: options?.message,
|
|
98
|
+
updatedAt: new Date().toISOString(),
|
|
99
|
+
managedBy: "envhub-cli",
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
await this.client.send(new CreateSecretCommand({
|
|
103
|
+
Name: this.fullName(secretName),
|
|
104
|
+
SecretString: JSON.stringify(payload),
|
|
105
|
+
Description: `Managed by envhub-cli`,
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
return { version: newVersion, name: secretName };
|
|
109
|
+
}
|
|
110
|
+
async pull(secretName) {
|
|
111
|
+
const payload = await this.getPayload(secretName);
|
|
112
|
+
return {
|
|
113
|
+
content: payload.content,
|
|
114
|
+
version: payload.metadata.version,
|
|
115
|
+
name: secretName,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
async cat(secretName) {
|
|
119
|
+
const payload = await this.getPayload(secretName);
|
|
120
|
+
return payload.content;
|
|
121
|
+
}
|
|
122
|
+
async list() {
|
|
123
|
+
const items = [];
|
|
124
|
+
let nextToken;
|
|
125
|
+
do {
|
|
126
|
+
const result = await this.client.send(new ListSecretsCommand({
|
|
127
|
+
NextToken: nextToken,
|
|
128
|
+
Filters: [
|
|
129
|
+
{
|
|
130
|
+
Key: "name",
|
|
131
|
+
Values: [this.prefix],
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
}));
|
|
135
|
+
if (result.SecretList) {
|
|
136
|
+
for (const secret of result.SecretList) {
|
|
137
|
+
if (!secret.Name?.startsWith(this.prefix)) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
// Try to get the secret content for additional info
|
|
141
|
+
let secretsCount = 0;
|
|
142
|
+
let lastMessage = null;
|
|
143
|
+
try {
|
|
144
|
+
const payload = await this.getPayload(this.stripPrefix(secret.Name));
|
|
145
|
+
const entries = parseEnvContent(payload.content);
|
|
146
|
+
secretsCount = entries.size;
|
|
147
|
+
lastMessage = payload.metadata.message ?? null;
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// If we can't read the secret, just show basic info
|
|
151
|
+
}
|
|
152
|
+
items.push({
|
|
153
|
+
name: this.stripPrefix(secret.Name),
|
|
154
|
+
secretsCount,
|
|
155
|
+
updatedAt: secret.LastChangedDate ?? null,
|
|
156
|
+
lastMessage,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
nextToken = result.NextToken;
|
|
161
|
+
} while (nextToken);
|
|
162
|
+
return items;
|
|
163
|
+
}
|
|
164
|
+
async delete(secretName, options) {
|
|
165
|
+
await this.client.send(new DeleteSecretCommand({
|
|
166
|
+
SecretId: this.fullName(secretName),
|
|
167
|
+
ForceDeleteWithoutRecovery: options?.force ?? false,
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
// ── Access Control ───────────────────────────────────────────────
|
|
171
|
+
async grant(secretName, userIdentifier) {
|
|
172
|
+
const userArn = await this.resolveUserArn(userIdentifier);
|
|
173
|
+
const fullSecretName = this.fullName(secretName);
|
|
174
|
+
// Get the secret ARN
|
|
175
|
+
const describeResult = await this.client.send(new DescribeSecretCommand({ SecretId: fullSecretName }));
|
|
176
|
+
const secretArn = describeResult.ARN;
|
|
177
|
+
if (!secretArn) {
|
|
178
|
+
throw new Error(`Could not determine ARN for secret '${secretName}'.`);
|
|
179
|
+
}
|
|
180
|
+
// Get existing policy or create a new one
|
|
181
|
+
let policy;
|
|
182
|
+
try {
|
|
183
|
+
const policyResult = await this.client.send(new GetResourcePolicyCommand({ SecretId: fullSecretName }));
|
|
184
|
+
policy = policyResult.ResourcePolicy
|
|
185
|
+
? JSON.parse(policyResult.ResourcePolicy)
|
|
186
|
+
: createEmptyPolicy();
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
policy = createEmptyPolicy();
|
|
190
|
+
}
|
|
191
|
+
// Add the user to the policy
|
|
192
|
+
const existingStatement = policy.Statement.find((s) => s.Sid === "EnvhubAccess");
|
|
193
|
+
if (existingStatement) {
|
|
194
|
+
const principals = Array.isArray(existingStatement.Principal.AWS)
|
|
195
|
+
? existingStatement.Principal.AWS
|
|
196
|
+
: [existingStatement.Principal.AWS];
|
|
197
|
+
if (!principals.includes(userArn)) {
|
|
198
|
+
principals.push(userArn);
|
|
199
|
+
}
|
|
200
|
+
existingStatement.Principal.AWS = principals;
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
policy.Statement.push({
|
|
204
|
+
Sid: "EnvhubAccess",
|
|
205
|
+
Effect: "Allow",
|
|
206
|
+
Principal: { AWS: [userArn] },
|
|
207
|
+
Action: ["secretsmanager:GetSecretValue"],
|
|
208
|
+
Resource: secretArn,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
await this.client.send(new PutResourcePolicyCommand({
|
|
212
|
+
SecretId: fullSecretName,
|
|
213
|
+
ResourcePolicy: JSON.stringify(policy),
|
|
214
|
+
}));
|
|
215
|
+
}
|
|
216
|
+
async revoke(secretName, userIdentifier) {
|
|
217
|
+
const userArn = await this.resolveUserArn(userIdentifier);
|
|
218
|
+
const fullSecretName = this.fullName(secretName);
|
|
219
|
+
// Get existing policy
|
|
220
|
+
let policy;
|
|
221
|
+
try {
|
|
222
|
+
const policyResult = await this.client.send(new GetResourcePolicyCommand({ SecretId: fullSecretName }));
|
|
223
|
+
if (!policyResult.ResourcePolicy) {
|
|
224
|
+
throw new Error(`No access policy found for secret '${secretName}'.`);
|
|
225
|
+
}
|
|
226
|
+
policy = JSON.parse(policyResult.ResourcePolicy);
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
if (error instanceof Error && error.message.includes("No access policy")) {
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
throw new Error(`Failed to retrieve policy for secret '${secretName}'.`);
|
|
233
|
+
}
|
|
234
|
+
// Remove the user from the policy
|
|
235
|
+
const statement = policy.Statement.find((s) => s.Sid === "EnvhubAccess");
|
|
236
|
+
if (!statement) {
|
|
237
|
+
throw new Error(`No envhub access policy found for secret '${secretName}'.`);
|
|
238
|
+
}
|
|
239
|
+
const principals = Array.isArray(statement.Principal.AWS)
|
|
240
|
+
? statement.Principal.AWS
|
|
241
|
+
: [statement.Principal.AWS];
|
|
242
|
+
const filtered = principals.filter((arn) => arn !== userArn);
|
|
243
|
+
if (filtered.length === principals.length) {
|
|
244
|
+
throw new Error(`User '${userIdentifier}' does not have access to secret '${secretName}'.`);
|
|
245
|
+
}
|
|
246
|
+
if (filtered.length === 0) {
|
|
247
|
+
// Remove the entire statement
|
|
248
|
+
policy.Statement = policy.Statement.filter((s) => s.Sid !== "EnvhubAccess");
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
statement.Principal.AWS = filtered;
|
|
252
|
+
}
|
|
253
|
+
if (policy.Statement.length === 0) {
|
|
254
|
+
// No statements left — delete the entire policy
|
|
255
|
+
await this.client.send(new DeleteResourcePolicyCommand({ SecretId: fullSecretName }));
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
await this.client.send(new PutResourcePolicyCommand({
|
|
259
|
+
SecretId: fullSecretName,
|
|
260
|
+
ResourcePolicy: JSON.stringify(policy),
|
|
261
|
+
}));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// ── Versioning ───────────────────────────────────────────────────
|
|
265
|
+
async getVersion(secretName) {
|
|
266
|
+
try {
|
|
267
|
+
const payload = await this.getPayload(secretName);
|
|
268
|
+
return payload.metadata.version;
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
if (error instanceof ResourceNotFoundException) {
|
|
272
|
+
return 0;
|
|
273
|
+
}
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// ── Private Helpers ──────────────────────────────────────────────
|
|
278
|
+
/**
|
|
279
|
+
* Resolve a user identifier (username or ARN) to a full ARN.
|
|
280
|
+
*/
|
|
281
|
+
async resolveUserArn(userIdentifier) {
|
|
282
|
+
// If it's already an ARN, return it directly
|
|
283
|
+
if (userIdentifier.startsWith("arn:aws:")) {
|
|
284
|
+
return userIdentifier;
|
|
285
|
+
}
|
|
286
|
+
// Otherwise, look up the user by username
|
|
287
|
+
try {
|
|
288
|
+
const result = await this.iamClient.send(new GetUserCommand({ UserName: userIdentifier }));
|
|
289
|
+
if (!result.User?.Arn) {
|
|
290
|
+
throw new Error(`Could not resolve ARN for user '${userIdentifier}'.`);
|
|
291
|
+
}
|
|
292
|
+
return result.User.Arn;
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
throw new Error(`Failed to resolve user '${userIdentifier}'. ` +
|
|
296
|
+
`Provide either a valid IAM username or a full ARN.`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function createEmptyPolicy() {
|
|
301
|
+
return {
|
|
302
|
+
Version: "2012-10-17",
|
|
303
|
+
Statement: [],
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=aws-secrets.provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-secrets.provider.js","sourceRoot":"","sources":["../../../src/providers/aws/aws-secrets.provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SecretProvider } from "./provider.interface.js";
|
|
2
|
+
import { EnvhubConfig, ProviderType } from "../config/config.schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Factory for creating provider instances based on configuration.
|
|
5
|
+
*
|
|
6
|
+
* To register a new provider:
|
|
7
|
+
* 1. Create a class implementing SecretProvider
|
|
8
|
+
* 2. Add the instantiation logic in the createProvider method
|
|
9
|
+
*/
|
|
10
|
+
export declare class ProviderFactory {
|
|
11
|
+
/**
|
|
12
|
+
* Create a SecretProvider instance based on the current configuration.
|
|
13
|
+
*/
|
|
14
|
+
static createProvider(config: EnvhubConfig): SecretProvider;
|
|
15
|
+
/**
|
|
16
|
+
* Get a list of all available provider types.
|
|
17
|
+
*/
|
|
18
|
+
static getAvailableProviders(): {
|
|
19
|
+
type: ProviderType;
|
|
20
|
+
label: string;
|
|
21
|
+
available: boolean;
|
|
22
|
+
}[];
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=provider.factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.factory.d.ts","sourceRoot":"","sources":["../../src/providers/provider.factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAGxE;;;;;;GAMG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc;IA2B3D;;OAEG;IACH,MAAM,CAAC,qBAAqB,IAAI;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,EAAE;CAO5F"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AWSSecretsProvider } from "./aws/aws-secrets.provider.js";
|
|
2
|
+
/**
|
|
3
|
+
* Factory for creating provider instances based on configuration.
|
|
4
|
+
*
|
|
5
|
+
* To register a new provider:
|
|
6
|
+
* 1. Create a class implementing SecretProvider
|
|
7
|
+
* 2. Add the instantiation logic in the createProvider method
|
|
8
|
+
*/
|
|
9
|
+
export class ProviderFactory {
|
|
10
|
+
/**
|
|
11
|
+
* Create a SecretProvider instance based on the current configuration.
|
|
12
|
+
*/
|
|
13
|
+
static createProvider(config) {
|
|
14
|
+
const providerType = config.provider;
|
|
15
|
+
switch (providerType) {
|
|
16
|
+
case "aws":
|
|
17
|
+
if (!config.aws) {
|
|
18
|
+
throw new Error("AWS configuration is missing. Run 'envhub init' first.");
|
|
19
|
+
}
|
|
20
|
+
return new AWSSecretsProvider(config.aws, config.prefix);
|
|
21
|
+
case "azure":
|
|
22
|
+
throw new Error("Azure Key Vault provider is not yet implemented. Coming soon!");
|
|
23
|
+
case "gcp":
|
|
24
|
+
throw new Error("GCP Secret Manager provider is not yet implemented. Coming soon!");
|
|
25
|
+
default:
|
|
26
|
+
throw new Error(`Unknown provider '${providerType}'. Supported: aws, azure, gcp`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get a list of all available provider types.
|
|
31
|
+
*/
|
|
32
|
+
static getAvailableProviders() {
|
|
33
|
+
return [
|
|
34
|
+
{ type: "aws", label: "AWS Secrets Manager", available: true },
|
|
35
|
+
{ type: "azure", label: "Azure Key Vault", available: false },
|
|
36
|
+
{ type: "gcp", label: "GCP Secret Manager", available: false },
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=provider.factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.factory.js","sourceRoot":"","sources":["../../src/providers/provider.factory.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,OAAO,eAAe;IAC1B;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAoB;QACxC,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC;QAErC,QAAQ,YAAY,EAAE,CAAC;YACrB,KAAK,KAAK;gBACR,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;gBAC5E,CAAC;gBACD,OAAO,IAAI,kBAAkB,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAE3D,KAAK,OAAO;gBACV,MAAM,IAAI,KAAK,CACb,+DAA+D,CAChE,CAAC;YAEJ,KAAK,KAAK;gBACR,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;YAEJ;gBACE,MAAM,IAAI,KAAK,CACb,qBAAqB,YAA4B,+BAA+B,CACjF,CAAC;QACN,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,qBAAqB;QAC1B,OAAO;YACL,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,IAAI,EAAE;YAC9D,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,KAAK,EAAE;YAC7D,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,KAAK,EAAE;SAC/D,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for push operations.
|
|
3
|
+
*/
|
|
4
|
+
export interface PushOptions {
|
|
5
|
+
/** Optional commit-style message describing the change */
|
|
6
|
+
message?: string;
|
|
7
|
+
/** Bypass version conflict checking */
|
|
8
|
+
force?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Result of a push operation.
|
|
12
|
+
*/
|
|
13
|
+
export interface PushResult {
|
|
14
|
+
/** The new version number after the push */
|
|
15
|
+
version: number;
|
|
16
|
+
/** Name of the secret that was pushed */
|
|
17
|
+
name: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Result of a pull operation.
|
|
21
|
+
*/
|
|
22
|
+
export interface PullResult {
|
|
23
|
+
/** The raw content of the secret (the .env file content) */
|
|
24
|
+
content: string;
|
|
25
|
+
/** The version number of the pulled secret */
|
|
26
|
+
version: number;
|
|
27
|
+
/** Name of the secret that was pulled */
|
|
28
|
+
name: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Information about a secret in a list response.
|
|
32
|
+
*/
|
|
33
|
+
export interface SecretListItem {
|
|
34
|
+
/** The secret name (without provider prefix) */
|
|
35
|
+
name: string;
|
|
36
|
+
/** Number of key-value pairs in the secret */
|
|
37
|
+
secretsCount: number;
|
|
38
|
+
/** Last updated timestamp */
|
|
39
|
+
updatedAt: Date | null;
|
|
40
|
+
/** Last push message (if any) */
|
|
41
|
+
lastMessage: string | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Options for delete operations.
|
|
45
|
+
*/
|
|
46
|
+
export interface DeleteOptions {
|
|
47
|
+
/** Force immediate deletion without scheduling */
|
|
48
|
+
force?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The SecretProvider interface that every backend provider must implement.
|
|
52
|
+
*
|
|
53
|
+
* To add a new provider (e.g. Azure Key Vault, GCP Secret Manager),
|
|
54
|
+
* create a class that implements this interface and register it in
|
|
55
|
+
* the ProviderFactory.
|
|
56
|
+
*/
|
|
57
|
+
export interface SecretProvider {
|
|
58
|
+
/** Unique identifier for this provider (e.g. "aws", "azure", "gcp") */
|
|
59
|
+
readonly name: string;
|
|
60
|
+
/**
|
|
61
|
+
* Push a .env file's content to the cloud provider.
|
|
62
|
+
* Creates the secret if it doesn't exist, updates it otherwise.
|
|
63
|
+
*/
|
|
64
|
+
push(secretName: string, content: string, options?: PushOptions): Promise<PushResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Pull the latest version of a secret from the cloud provider.
|
|
67
|
+
*/
|
|
68
|
+
pull(secretName: string): Promise<PullResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Read and return the content of a secret without writing to disk.
|
|
71
|
+
*/
|
|
72
|
+
cat(secretName: string): Promise<string>;
|
|
73
|
+
/**
|
|
74
|
+
* List all secrets managed by envhub for this provider.
|
|
75
|
+
*/
|
|
76
|
+
list(): Promise<SecretListItem[]>;
|
|
77
|
+
/**
|
|
78
|
+
* Delete a secret from the cloud provider.
|
|
79
|
+
*/
|
|
80
|
+
delete(secretName: string, options?: DeleteOptions): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Grant another user access to a secret.
|
|
83
|
+
* @param userIdentifier - Provider-specific user identifier (e.g. AWS ARN or username)
|
|
84
|
+
*/
|
|
85
|
+
grant(secretName: string, userIdentifier: string): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Revoke a user's access to a secret.
|
|
88
|
+
* @param userIdentifier - Provider-specific user identifier (e.g. AWS ARN or username)
|
|
89
|
+
*/
|
|
90
|
+
revoke(secretName: string, userIdentifier: string): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Get the current remote version number of a secret.
|
|
93
|
+
*/
|
|
94
|
+
getVersion(secretName: string): Promise<number>;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=provider.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.interface.d.ts","sourceRoot":"","sources":["../../src/providers/provider.interface.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,iCAAiC;IACjC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAItB;;;OAGG;IACH,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAEtF;;OAEG;IACH,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAE9C;;OAEG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzC;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAElC;;OAEG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAInE;;;OAGG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjE;;;OAGG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAIlE;;OAEG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACjD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.interface.js","sourceRoot":"","sources":["../../src/providers/provider.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a single change between two .env versions.
|
|
3
|
+
*/
|
|
4
|
+
export interface EnvChange {
|
|
5
|
+
key: string;
|
|
6
|
+
type: "added" | "removed" | "changed";
|
|
7
|
+
oldValue?: string;
|
|
8
|
+
newValue?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Compare two .env contents and return the differences.
|
|
12
|
+
*
|
|
13
|
+
* @param localContent - The current local .env content
|
|
14
|
+
* @param remoteContent - The remote/new .env content
|
|
15
|
+
* @returns Array of changes detected
|
|
16
|
+
*/
|
|
17
|
+
export declare function diffEnvContents(localContent: string, remoteContent: string): EnvChange[];
|
|
18
|
+
/**
|
|
19
|
+
* Format changes into a human-readable string for terminal display.
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatChanges(changes: EnvChange[]): string;
|
|
22
|
+
/**
|
|
23
|
+
* Format changes into a compact one-line summary.
|
|
24
|
+
* Example: "3 added, 1 removed, 12 changed"
|
|
25
|
+
*/
|
|
26
|
+
export declare function summarizeChanges(changes: EnvChange[]): string;
|
|
27
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/utils/diff.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,SAAS,EAAE,CAqCb;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,CAiC1D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,CAe7D"}
|