dotsec 4.0.0-alpha.4 → 4.0.0-alpha.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 +105 -63
- package/dist/cli/index.js +17 -16
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +12 -11
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,45 +1,7 @@
|
|
|
1
1
|
# dotsec
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## Installation
|
|
7
|
-
|
|
8
|
-
With AWS support:
|
|
9
|
-
|
|
10
|
-
```sh
|
|
11
|
-
npm install --save dotsec @dotsec/plugin-aws
|
|
12
|
-
npx dotsec --plugin @dotsec/plugin-aws aws init
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
With PKE support:
|
|
16
|
-
|
|
17
|
-
```sh
|
|
18
|
-
npm install --save dotsec @dotsec/plugin-pke
|
|
19
|
-
npx dotsec --plugin @dotsec/plugin-pke pke init
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Usage
|
|
23
|
-
|
|
24
|
-
```sh
|
|
25
|
-
npx dotsec --help
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
<!--
|
|
29
|
-
`dotsec` is a tool for managing environment variables in a secure way. Encrypted environment variables are stored in a `.sec` file, and decrypted to a `.env` file. The `.sec` file can be committed to your repository. The `.env` file should not be committed to your repository.
|
|
30
|
-
|
|
31
|
-
Next to encrypting and decrypting environment variables, `dotsec` can also be used to run a command with the values of a `.env` file in its environment, or with the values of a `.sec` file in its environment.
|
|
32
|
-
|
|
33
|
-
As of writing this, `dotsec` supports the following encryption providers:
|
|
34
|
-
|
|
35
|
-
- [AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/)
|
|
36
|
-
- [Public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography)
|
|
37
|
-
|
|
38
|
-
When using the AWS plugin, dotsec can also push selected `.env`/`.sec` entries to AWS Systems Manager Parameter Store, and/or AWS Secrets Manager.
|
|
39
|
-
|
|
40
|
-
## Table of Contents
|
|
41
|
-
|
|
42
|
-
- [Installation](#installation)
|
|
3
|
+
The solution offers encryption and decryption of `.env` files to and from `.sec` files, the ability to run a command with the values of a `.env`/`.sec` file in its environment, and the ability to push selected `.env`/`.sec` entries to AWS Systems Manager Parameter Store and AWS Secrets Manager.
|
|
4
|
+
Encrypts your `.env` file with the AWS Encryption SDK so you can safely commit it to your repository.
|
|
43
5
|
|
|
44
6
|
## Features
|
|
45
7
|
|
|
@@ -67,7 +29,87 @@ When using the AWS plugin, dotsec can also push selected `.env`/`.sec` entries t
|
|
|
67
29
|
|
|
68
30
|
- For initialisation enough credentials for creating a KMS key, and alias.
|
|
69
31
|
- For usage enough credentials for using the KMS key to encrypt and/or decrypt.
|
|
70
|
-
- An AWS KMS key with an alias.
|
|
32
|
+
- An AWS KMS key with an alias.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
npm install --save-dev dotsec @dotsec/plugin-aws
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Add the folowing to dotsec.config.ts:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { DotsecPluginAws } from "@dotsec/plugin-aws";
|
|
44
|
+
import { DotsecConfig } from "dotsec";
|
|
45
|
+
|
|
46
|
+
export const dotsec: DotsecConfig<{ plugins: DotsecPluginAws }> = {
|
|
47
|
+
defaults: {
|
|
48
|
+
encryptionEngine: "aws",
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
If you don't have a .env file, create one:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
I_CAN_SEE="clearly now"
|
|
59
|
+
SINGING="in the rain"
|
|
60
|
+
I_BLESS_THE_RAINS="down in Africa"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Execute a command and use the values of a .env file in its environment
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
npx dotsec run --with-env node -e "console.log(process.env.I_BLESS_THE_RAINS)"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Encrypt a .env file to .sec
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
npx dotsec encrypt
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Execute a command and use the values of a .sec file in its environment
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
npx dotsec run --with-sec node -e "console.log(process.env.I_BLESS_THE_RAINS)"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Decrypt a .sec file to .env
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
npx dotsec decrypt
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Push selected .env entries to AWS Systems Manager Parameter Store
|
|
88
|
+
|
|
89
|
+
Edit the `dotsec.config.ts` file. Add the following to the `aws` object:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
{
|
|
93
|
+
...
|
|
94
|
+
variables: {
|
|
95
|
+
"I_BLESS_THE_RAINS": {
|
|
96
|
+
push: {
|
|
97
|
+
aws: {
|
|
98
|
+
ssm: true
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Run the following command:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
npx dotsec push
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
> You might want to set AWS_REGION before running the command. If you don't, the region will be set to `eu-west-1`.
|
|
71
113
|
<!--
|
|
72
114
|
## Usage
|
|
73
115
|
|
|
@@ -85,15 +127,15 @@ Take not of the `KeyMetadata.KeyId` value, and create an alias for it:
|
|
|
85
127
|
aws kms create-alias --alias-name alias/dotsec --target-key-id <key-id>
|
|
86
128
|
```
|
|
87
129
|
|
|
88
|
-
### Execute a command and use the values of a
|
|
130
|
+
### Execute a command and use the values of a .env file in its environment
|
|
89
131
|
|
|
90
|
-
Create a
|
|
132
|
+
Create a .env file if you don't have one already, and add some values:
|
|
91
133
|
|
|
92
134
|
```sh
|
|
93
|
-
echo "MY_FANCY_ENV_VAR='yes yes yallzies'\nHEY_HO='Let\'s go'" >
|
|
135
|
+
echo "MY_FANCY_ENV_VAR='yes yes yallzies'\nHEY_HO='Let\'s go'" > .env
|
|
94
136
|
```
|
|
95
137
|
|
|
96
|
-
The following command will create an encrypted version of the
|
|
138
|
+
The following command will create an encrypted version of the `.env` file, and store it in a file called `.sec`. It will also create a config file called `dotsec.config.ts` which contains the KMS key alias, and AWS region. (Note: you don't have to add the key alias and region to the config file, you can also pass them as options to the dotsec aws sub command. See `dotsec init aws --help` for more information.)
|
|
97
139
|
|
|
98
140
|
```sh
|
|
99
141
|
npx dotsec init --aws-region eu-west-1 [--aws-key-alias alias/dotsec]
|
|
@@ -101,28 +143,28 @@ npx dotsec init --aws-region eu-west-1 [--aws-key-alias alias/dotsec]
|
|
|
101
143
|
|
|
102
144
|
The following files will be created:
|
|
103
145
|
|
|
104
|
-
-
|
|
146
|
+
- `.sec` - The encrypted version of the `.env` file.
|
|
105
147
|
- `dotsec.config.ts` - The config file containing the KMS key alias and AWS region.
|
|
106
148
|
|
|
107
149
|
### Add files to Git
|
|
108
150
|
|
|
109
|
-
Add the
|
|
151
|
+
Add the `.sec` and `dotsec.config.ts` files to your repository, and commit these accordingly.
|
|
110
152
|
|
|
111
|
-
### Run a process with your
|
|
153
|
+
### Run a process with your .env file
|
|
112
154
|
|
|
113
155
|
```sh
|
|
114
|
-
npx dotsec run --env
|
|
156
|
+
npx dotsec run --env .env command env
|
|
115
157
|
```
|
|
116
158
|
|
|
117
|
-
### Run a process with your
|
|
159
|
+
### Run a process with your .sec file
|
|
118
160
|
|
|
119
161
|
```sh
|
|
120
|
-
npx dotsec run --sec
|
|
162
|
+
npx dotsec run --sec .sec command env
|
|
121
163
|
```
|
|
122
164
|
|
|
123
165
|
For more options see `dotsec run --help`.
|
|
124
166
|
|
|
125
|
-
### Decrypt a
|
|
167
|
+
### Decrypt a .sec file to .env
|
|
126
168
|
|
|
127
169
|
```sh
|
|
128
170
|
npx dotsec decrypt
|
|
@@ -130,7 +172,7 @@ npx dotsec decrypt
|
|
|
130
172
|
|
|
131
173
|
For more options see `dotsec decrypt --help`.
|
|
132
174
|
|
|
133
|
-
### Encrypt a
|
|
175
|
+
### Encrypt a .env file to .sec
|
|
134
176
|
|
|
135
177
|
```sh
|
|
136
178
|
npx dotsec encrypt
|
|
@@ -138,7 +180,7 @@ npx dotsec encrypt
|
|
|
138
180
|
|
|
139
181
|
For more options see `dotsec encrypt --help`.
|
|
140
182
|
|
|
141
|
-
### Push selected
|
|
183
|
+
### Push selected .env/.sec entries to AWS Systems Manager Parameter Store
|
|
142
184
|
|
|
143
185
|
Take your favorite editor, and edit the `dotsec.config.ts` file. Add the following to the `aws` object:
|
|
144
186
|
|
|
@@ -162,7 +204,7 @@ Take your favorite editor, and edit the `dotsec.config.ts` file. Add the followi
|
|
|
162
204
|
npx dotsec push --env --to-aws-ssm
|
|
163
205
|
```
|
|
164
206
|
|
|
165
|
-
### Push selected
|
|
207
|
+
### Push selected .env/.sec entries to AWS Secrets Manager
|
|
166
208
|
|
|
167
209
|
Take your favorite editor, and edit the `dotsec.config.ts` file. Add the following to the `aws` object:
|
|
168
210
|
|
|
@@ -185,12 +227,12 @@ Take your favorite editor, and edit the `dotsec.config.ts` file. Add the followi
|
|
|
185
227
|
```sh
|
|
186
228
|
npx dotsec push --env --to-aws-secrets-manager
|
|
187
229
|
``` -->
|
|
188
|
-
|
|
230
|
+
|
|
189
231
|
### FAQ
|
|
190
232
|
|
|
191
|
-
#### Is it safe to commit a
|
|
233
|
+
#### Is it safe to commit a `.sec` and `dotsec.config.ts` file alongside your code?
|
|
192
234
|
|
|
193
|
-
Yes it is. But it is up to you to make sure that access to the KMS key is restricted to the people who need to decrypt and/or encrypt the
|
|
235
|
+
Yes it is. But it is up to you to make sure that access to the KMS key is restricted to the people who need to decrypt and/or encrypt the `.sec` file.
|
|
194
236
|
|
|
195
237
|
#### Should I use this in production?
|
|
196
238
|
|
|
@@ -201,15 +243,15 @@ We do, however, since this package is relatively new, I don't think you should.
|
|
|
201
243
|
- Write some tests already.
|
|
202
244
|
- Add support in-code use like `dotsec.config()`
|
|
203
245
|
- Add support for Node preload modules like `node -r dotsec/register index.js`
|
|
204
|
-
- Add watcher for
|
|
246
|
+
- Add watcher for `.env` file changes and automatically encrypt
|
|
205
247
|
- Write guide on postinstall for npm/yarn/pnpm
|
|
206
|
-
- Add chunking for encoding larger files with assymetric keys. Current limit is 4kb
|
|
248
|
+
- ~~Add chunking for encoding larger files with assymetric keys. Current limit is 4kb.~~
|
|
207
249
|
- Add support for other encryption SDKs like GCP KMS, Azure Key Vault, etc.
|
|
208
|
-
- Split up dotsec package in multiple packages, one for each encryption SDK
|
|
250
|
+
- ~~Split up dotsec package in multiple packages, one for each encryption SDK.~~
|
|
209
251
|
- Add support for pulling entries to GitHub actions secrets.
|
|
210
252
|
|
|
211
253
|
## Limitations
|
|
212
254
|
|
|
213
255
|
- The only supported encryption SDK is the AWS Encryption SDK. For now.
|
|
214
|
-
- Assymetric keys are supported, but the encrypted file size is limited to the payload size of the key. Until chunking is implemented, that is
|
|
215
|
-
- AWS Secrets Manager secrets which are marked for deletion **cannot** be updated until the deletion is complete. As of writing, the minimum deletion time is 7 days. This means that if you want to update a deleted AWS Secrets Manager secret, you have to wait at least 7 days before you can update it again. This is a limitation of AWS Secrets Manager, not dotsec
|
|
256
|
+
- ~~Assymetric keys are supported, but the encrypted file size is limited to the payload size of the key. Until chunking is implemented, that is.~~
|
|
257
|
+
- AWS Secrets Manager secrets which are marked for deletion **cannot** be updated until the deletion is complete. As of writing, the minimum deletion time is 7 days. This means that if you want to update a deleted AWS Secrets Manager secret, you have to wait at least 7 days before you can update it again. This is a limitation of AWS Secrets Manager, not dotsec
|
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var je=Object.create;var J=Object.defineProperty;var Ve=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var ke=Object.getPrototypeOf,He=Object.prototype.hasOwnProperty;var Le=(n,o,
|
|
1
|
+
var je=Object.create;var J=Object.defineProperty;var Ve=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var ke=Object.getPrototypeOf,He=Object.prototype.hasOwnProperty;var Le=(n,o,s,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of Ae(o))!He.call(n,e)&&e!==s&&J(n,e,{get:()=>o[e],enumerable:!(t=Ve(o,e))||t.enumerable});return n};var w=(n,o,s)=>(s=n!=null?je(ke(n)):{},Le(o||!n||!n.__esModule?J(s,"default",{value:n,enumerable:!0}):s,n));var Te=require("commander");var Me="dotsec.config.ts",B=[Me],q=".sec",G=".env",_={defaults:{}};var Y=w(require("fs")),z=w(require("path"));function Re(n){try{return new Function(`return ${n.trim()}`)()}catch{return{}}}var Q=async n=>{try{return Re(await Y.default.promises.readFile(n,"utf8"))}catch(o){throw o instanceof Error?new Error(`Failed to parse ${z.default.relative(process.cwd(),n)}: ${o.message}`):o}};var X=require("bundle-require"),Z=w(require("joycon")),ee=w(require("path")),ne=async n=>{let o=process.cwd(),t=await new Z.default().resolve({files:n?[n]:[...B,"package.json"],cwd:o,stopDir:ee.default.parse(o).root,packageKey:"dotsec"});if(n&&t===null)throw new Error(`Could not find config file ${n}`);if(t){if(t.endsWith(".json")){let e=await Q(t),i;return t.endsWith("package.json")&&e.dotsec!==void 0?i=e.dotsec:i=e,{source:"json",contents:{..._,...i,defaults:{...i?.defaults,..._.defaults,plugins:{...i?.defaults?.plugins,..._.defaults?.plugins}},push:{...i?.push}}}}else if(t.endsWith(".ts")){let e=await(0,X.bundleRequire)({filepath:t}),i=e.mod.dotsec||e.mod.default||e.mod;return{source:"ts",contents:{..._,...i,defaults:{...i?.defaults,..._.defaults,plugins:{...i?.defaults?.plugins,..._.defaults?.plugins}},push:{...i?.push}}}}}return{source:"defaultConfig",contents:_}};var W=async n=>import(n.name).then(o=>o.default);var te=require("commander"),F=(n,o,s)=>{n&&Object.values(n).map(t=>{let e;if(Array.isArray(t)){let[i,c,l]=t;e={flags:i,description:c,defaultValue:l}}else{let{flags:i,description:c,defaultValue:l,choices:a,env:r,fn:f}=t;e={flags:i,description:c,defaultValue:l,choices:a,env:r,fn:f}}if(e){let i=new te.Option(e.flags,e.description);e.fn&&i.argParser(e.fn),e.defaultValue&&i.default(e.defaultValue),e.env&&i.env(e.env),s&&i.makeOptionMandatory(!0),e.choices&&i.choices(e.choices),o.addOption(i)}})};var k=w(require("fs/promises")),oe=w(require("path")),ie=w(require("prompts")),V=async n=>await k.default.readFile(n,"utf-8"),I=async(n,o)=>await k.default.writeFile(n,o,"utf-8"),qe=async n=>{try{return await(0,k.stat)(n),!0}catch{return!1}},A=async({filePath:n,skip:o})=>{let s;return await qe(n)&&o!==!0?s=await(0,ie.default)({type:"confirm",name:"overwrite",message:()=>`Overwrite './${oe.default.relative(process.cwd(),n)}' ?`}):s=void 0,s};var re=w(require("chalk")),Ge=w(require("cli-table"));var C=n=>re.default.yellow.bold(n);var ye=require("commander");var S={option:["--env-file <envFile>",`Path to .env file. If not provided, will look for value in 'ENV_FILE' environment variable. If not provided, will look for '${G}' file in current directory.`,G],env:"ENV_FILE"},N={option:["--sec-file, <secFile>",`Path to .sec file. If not provided, will look for value in 'SEC_FILE' environment variable. If not provided, will look for '${q}' file in current directory.`,q],env:"SEC_FILE"},L={flags:"--using <using>",description:"Wether to use a dot env file or a dot sec file",choices:["env","sec"],env:"DOTSEC_USING"},se={flags:"--using <using>",description:"Wether to use a dot env file or a dot sec file",choices:["env"],env:"DOTSEC_USING"},$={option:["--yes","Skip confirmation prompts"]};var x={option:["-c, --config-file, --configFile <configFile>","Config file"],env:"DOTSEC_CONFIG_FILE"},ae={option:["--plugin <plugin>","Comma-separated list of plugins to use"],env:"DOTSEC_PLUGIN"},ce={option:["--engine <engine>","Encryption engine to use"],env:"DOTSEC_ENGINE"},M={option:["--create-manifest","Create a markdown manifest file. See the --manifest-file option for more information."],env:"CREATE_MANIFEST"},R={option:["--manifest-file-prefix <manifestFilePrefix>","Mmanifest file prefix"],env:"ENCRYPTION_MANIFEST_FILE"};var We={decrypt:{options:{configFile:x,envFile:S,secFile:N,createManifest:M,manifestFilePrefix:R,yes:$},description:"Decrypt a sec file",helpText:`Examples:
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
Decrypt .sec file to .env file
|
|
@@ -16,7 +16,7 @@ Specify a different .env file
|
|
|
16
16
|
$ npx dotsec decrypt --env-file .env.dev
|
|
17
17
|
$ ENV_FILE=.env.dev npx dotsec decrypt
|
|
18
18
|
|
|
19
|
-
Write a manifest file
|
|
19
|
+
Write a manifest markdown file
|
|
20
20
|
|
|
21
21
|
$ npx dotsec decrypt --create-manifest
|
|
22
22
|
$ CREATE_MANIFEST=true npx dotsec decrypt
|
|
@@ -24,8 +24,8 @@ $ CREATE_MANIFEST=true npx dotsec decrypt
|
|
|
24
24
|
Specify a different manifest file
|
|
25
25
|
|
|
26
26
|
$ npx dotsec decrypt --manifest-file .manifest.dev
|
|
27
|
-
$ MANIFEST_FILE
|
|
28
|
-
`}},pe=We;var Ue={dotsec:{options:{configFile:
|
|
27
|
+
$ MANIFEST_FILE=decryption-manifest.md npx dotsec decrypt
|
|
28
|
+
`}},pe=We;var Ue={dotsec:{options:{configFile:x,plugin:ae}}},le=Ue;var Ke={encrypt:{options:{configFile:x,envFile:S,secFile:N,createManifest:M,manifestFile:R,yes:$},description:"Encrypt an env file",helpText:`Examples:
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
Encrypt .env file to .sec file
|
|
@@ -38,13 +38,14 @@ Specify a different .env file
|
|
|
38
38
|
$ npx dotsec encrypt --env-file .env.dev
|
|
39
39
|
$ ENV_FILE=.env.dev npx dotsec encrypt
|
|
40
40
|
|
|
41
|
+
|
|
41
42
|
Specify a different .sec file
|
|
42
43
|
|
|
43
44
|
$ npx dotsec encrypt --sec-file .sec.dev
|
|
44
45
|
$ SEC_FILE=.sec.dev npx dotsec encrypt
|
|
45
46
|
|
|
46
47
|
|
|
47
|
-
Write a manifest file
|
|
48
|
+
Write a manifest markdown file
|
|
48
49
|
|
|
49
50
|
$ npx dotsec encrypt --create-manifest
|
|
50
51
|
$ CREATE_MANIFEST=true npx dotsec encrypt
|
|
@@ -52,9 +53,9 @@ $ CREATE_MANIFEST=true npx dotsec encrypt
|
|
|
52
53
|
|
|
53
54
|
Specify a different manifest file
|
|
54
55
|
|
|
55
|
-
$ npx dotsec encrypt --manifest-file
|
|
56
|
-
$ MANIFEST_FILE
|
|
57
|
-
`}},de=Ke;var Je={init:{options:{configFile:
|
|
56
|
+
$ npx dotsec encrypt --manifest-file manifest.dev
|
|
57
|
+
$ MANIFEST_FILE=encryption-manifest.md npx dotsec encrypt
|
|
58
|
+
`}},de=Ke;var Je={init:{options:{configFile:x,yes:$},description:"Initialize a dotsec project by creating a dotsec.config.ts file.",helpText:`Examples:
|
|
58
59
|
|
|
59
60
|
Create a dotsec.config.ts file in the current directory
|
|
60
61
|
|
|
@@ -73,7 +74,7 @@ By specifying the --config-file option, you can create a dotsec config file with
|
|
|
73
74
|
$ npx dotsec init --config-file dotsec.config.ts
|
|
74
75
|
|
|
75
76
|
$ DOTSEC_CONFIG_FILE=my.config.ts npx dotsec init
|
|
76
|
-
`}},fe=Je;var Be={push:{options:{configFile:
|
|
77
|
+
`}},fe=Je;var Be={push:{options:{configFile:x,envFile:S,secFile:N,yes:$},requiredOptions:{using:L},description:"Push variables from env or sec file to a remote",helpText:`Examples:
|
|
77
78
|
|
|
78
79
|
Push variables from .env file to remote
|
|
79
80
|
|
|
@@ -85,7 +86,7 @@ Push variables from .sec file to remote
|
|
|
85
86
|
|
|
86
87
|
$ npx dotsec push --using sec
|
|
87
88
|
$ DOTSEC_USING=sec npx dotsec push
|
|
88
|
-
`}},me=Be;var Ye={runEnvOnly:{usage:"--using env [commandArgs...]",options:{configFile:
|
|
89
|
+
`}},me=Be;var Ye={runEnvOnly:{usage:"--using env [commandArgs...]",options:{configFile:x,envFile:S,yes:$,engine:ce},requiredOptions:{using:se},description:"Run a command in a separate process and populate env with contents of a dotenv file.",helpText:`Examples:
|
|
89
90
|
|
|
90
91
|
Run a command with a .env file
|
|
91
92
|
|
|
@@ -105,7 +106,7 @@ $ ENV_FILE=.env.dev npx dotsec run --using env node -e "console.log(process.env)
|
|
|
105
106
|
You can also specify 'using' as an environment variable
|
|
106
107
|
|
|
107
108
|
$ DOTSEC_USING=env npx dotsec run node -e "console.log(process.env)"
|
|
108
|
-
`},run:{options:{configFile:
|
|
109
|
+
`},run:{options:{configFile:x,envFile:S,secFile:N,yes:$},requiredOptions:{using:L},usage:"[--using env] [--using sec] [commandArgs...]",description:`Run a command in a separate process and populate env with either
|
|
109
110
|
- contents of a dotenv file
|
|
110
111
|
- decrypted values of a dotsec file.
|
|
111
112
|
|
|
@@ -129,11 +130,11 @@ $ dotsec run --with-sec echo "hello world"
|
|
|
129
130
|
Run a command with a specific .sec file
|
|
130
131
|
|
|
131
132
|
$ dotsec run --with-sec --sec-file .sec.dev echo "hello world"
|
|
132
|
-
`}},ge=Ye;var ze={...le,...fe,...de,...pe,...ge,...me},Qe=n=>{if(Array.isArray(n)){let[o,
|
|
133
|
+
`}},ge=Ye;var ze={...le,...fe,...de,...pe,...ge,...me},Qe=n=>{if(Array.isArray(n)){let[o,s,t]=n;return{flags:o,description:s,defaultValue:t}}else{if("option"in n){let[o,s,t]=n.option;return{flags:o,description:s,defaultValue:t,env:n.env}}return n}},ue=(n,o)=>{let s=o?.dotsecConfig?.defaults?.options?.[o?.optionKey],t=Qe(n),e=new ye.Option(t.flags,t.description);return t.fn&&e.argParser(t.fn),t.defaultValue&&e.default(s||t.defaultValue),t.env&&e.env(t.env),o.required&&e.makeOptionMandatory(!0),t.choices&&e.choices(t.choices),e},P=n=>{let{program:o,commandName:s,dotsecConfig:t}=n,e=ze[s||o.name()];if(e){let{options:i,requiredOptions:c,description:l,usage:a,helpText:r}=e;i&&Object.keys(i).forEach(f=>{let m=i[f],d=ue(m,{dotsecConfig:t,optionKey:f});o.addOption(d)}),c&&Object.keys(c).forEach(f=>{let m=c[f],d=ue(m,{required:!0,dotsecConfig:t,optionKey:f});o.addOption(d)}),l&&o.description(l),a&&o.usage(a),r&&o.description(r)}};var Oe=require("dotenv"),Xe=async(n,o)=>{let{dotsecConfig:s,decryptHandlers:t}=o,e=n.enablePositionalOptions().passThroughOptions().command("decrypt").action(async(c,l)=>{try{let{envFile:a,secFile:r,engine:f,createManifest:m,manifestFile:d,yes:p}=l.optsWithGlobals(),O=f||s?.defaults?.encryptionEngine,u=(t||[]).find(h=>h.triggerOptionValue===O);if(!u)throw new Error(`No decryption plugin found, available decryption engine(s): ${o.decryptHandlers.map(h=>`--${h.triggerOptionValue}`).join(", ")}`);console.log("Decrypting with",C(u.encryptionEngineName||u.triggerOptionValue),"engine");let g=[...Object.keys(u.options||{}),...Object.keys(u.requiredOptions||{})],D=Object.fromEntries(g.map(h=>[h,c[h]])),v=await V(r),E=await u.handler({ciphertext:v,...D}),j=await A({filePath:a,skip:p});if((j===void 0||j.overwrite===!0)&&(await I(a,E),console.log(`Wrote plaintext contents of ${C(r)} file to ${C(a)}`)),m||s?.defaults?.options?.createManifest){let h=(0,Oe.parse)(E),y=`# Dotsec decryption manifest
|
|
133
134
|
|
|
134
135
|
## Overview
|
|
135
136
|
|
|
136
|
-
- plaintext source: ${
|
|
137
|
+
- plaintext source: ${a}
|
|
137
138
|
- ciphertext target: ${r}
|
|
138
139
|
- created: ${new Date().toUTCString()}
|
|
139
140
|
- Decryption engine: ${u.encryptionEngineName||u.triggerOptionValue}
|
|
@@ -145,7 +146,7 @@ $ dotsec run --with-sec --sec-file .sec.dev echo "hello world"
|
|
|
145
146
|
| --- |
|
|
146
147
|
${Object.keys(h).map(H=>`| \`${H} \`| `).join(`
|
|
147
148
|
`)}
|
|
148
|
-
`,b=d||`${
|
|
149
|
+
`,b=d||`${a}.decryption-manifest.md`;await I(b,y),console.log(`Wrote manifest of ${C(a)} file to ${C(b)}`)}}catch(a){console.error(C(a.message)),l.help()}});o.decryptHandlers.map(c=>{let{options:l,requiredOptions:a}=c;F(l,e),F(a,e,!0)});let i=o.decryptHandlers.map(c=>c.triggerOptionValue);return e.option("--engine <engine>",`Encryption engine${i.length>0?"s":""} to use: ${i.length===1?i[0]:i.join(", ")}`,i.length===1?i[0]:void 0),P({program:e,dotsecConfig:s}),e},Ce=Xe;var he=require("dotenv"),Ze=async(n,o)=>{let{encryptHandlers:s,dotsecConfig:t}=o,e=n.enablePositionalOptions().passThroughOptions().command("encrypt").action(async(l,a)=>{try{let{envFile:r,secFile:f,engine:m,createManifest:d,manifestFile:p,yes:O}=a.optsWithGlobals(),u=m||t?.defaults?.encryptionEngine,g=(s||[]).find(y=>y.triggerOptionValue===u);if(!g)throw new Error(`No encryption plugin found, available encryption engine(s): ${o.encryptHandlers.map(y=>y.triggerOptionValue).join(", ")}`);let D=[...Object.keys(g.options||{}),...Object.keys(g.requiredOptions||{})],v=Object.fromEntries(D.map(y=>[y,l[y]])),E=await V(r),j=await g.handler({plaintext:E,...v}),h=await A({filePath:f,skip:O});if((h===void 0||h.overwrite===!0)&&(await I(f,j),console.log(`Wrote encrypted contents of ${C(r)} file to ${C(f)}`),d||t?.defaults?.options?.createManifest)){let y=(0,he.parse)(E),b=`# Dotsec encryption manifest
|
|
149
150
|
|
|
150
151
|
## Overview
|
|
151
152
|
|
|
@@ -161,7 +162,7 @@ ${Object.keys(h).map(H=>`| \`${H} \`| `).join(`
|
|
|
161
162
|
| --- |
|
|
162
163
|
${Object.keys(y).map(Ne=>`| \`${Ne} \`| `).join(`
|
|
163
164
|
`)}
|
|
164
|
-
`,H=p||`${f}.encryption-manifest.md`;await I(H,b),console.log(`Wrote manifest of ${C(r)} file to ${C(H)}`)}}catch(r){console.error(C(r.message)),
|
|
165
|
+
`,H=p||`${f}.encryption-manifest.md`;await I(H,b),console.log(`Wrote manifest of ${C(r)} file to ${C(H)}`)}}catch(r){console.error(C(r.message)),a.help()}});o.encryptHandlers.map(l=>{let{options:a,requiredOptions:r}=l;F(a,e),F(r,e,!0)});let i=o.encryptHandlers.map(l=>l.triggerOptionValue),c=o.encryptHandlers.map(l=>l.encryptionEngineName);return e.option("--engine <engine>",`Encryption engine${i.length>0?"s":""}: ${i.length===1?i[0]:i.join(", ")}`,i.length===1?i[0]:void 0),P({program:e,dotsecConfig:t}),e.description(`Encrypt .env file using ${c.join(", ")}`),e},ve=Ze;var Ee=w(require("path")),en=async(n,o)=>{let{dotsecConfig:s}=o,t=n.enablePositionalOptions().passThroughOptions().command("init").action(async(e,i)=>{let{configFile:c="dotsec.config.ts",yes:l}=i.optsWithGlobals();try{let a=await V(Ee.default.resolve(__dirname,"../../src/templates/dotsec.config.ts")),r=await A({filePath:c,skip:l});(r===void 0||r.overwrite===!0)&&(await I(c,a),console.log(`Wrote config file to ${C(c)}`))}catch(a){i.error(a)}});return P({program:t,dotsecConfig:s}),t},we=en;var De=require("dotenv"),xe=require("dotenv-expand"),U=w(require("fs")),nn=async(n,o)=>{let{dotsecConfig:s,handlers:t}=o,e=n.enablePositionalOptions().passThroughOptions().command("push").action(async(r,f)=>{try{let{using:m,envFile:d,secFile:p,engine:O,yes:u}=f.optsWithGlobals(),g=O||s?.defaults?.encryptionEngine,D=(t||[]).find(y=>y.decrypt?.triggerOptionValue===g)?.decrypt,v=(t||[]).find(y=>y.push?.triggerOptionValue===g)?.push;if(!v)throw new Error("No push plugin found!");let E=[...Object.keys(D?.options||{}),...Object.keys(D?.requiredOptions||{}),...Object.keys(v?.options||{}),...Object.keys(v?.requiredOptions||{})],j=Object.fromEntries(E.map(y=>[y,r[y]])),h;if(m==="env"){if(!d)throw new Error("No dotenv file specified in --env-file option");h=U.default.readFileSync(d,"utf8")}else{if(!p)throw new Error("No dotsec file specified in --sec-file option");if(!D)throw new Error(`No decryption plugin found, available decryption engine(s): ${t.map(b=>`--${b.decrypt?.triggerOptionValue}`).join(", ")}`);let y=U.default.readFileSync(p,"utf8");h=await D.handler({ciphertext:y,...j})}if(h){let y=(0,De.parse)(h),b=(0,xe.expand)({ignoreProcessEnv:!0,parsed:{...process.env,...y}});b.parsed&&await v.handler({push:b.parsed,yes:u,...j})}else throw new Error("No .env or .sec file provided")}catch(m){console.error(m),process.exit(1)}});P({program:e,dotsecConfig:s});let i=o.handlers.map(({decrypt:r})=>r.triggerOptionValue);e.option("--engine <engine>",`Encryption engine${i.length>0?"s":""} to use: ${i.length===1?i[0]:i.join(", ")}`,i.length===1?i[0]:void 0);let c={};o.handlers.forEach(r=>{Object.keys(r).map(f=>{let{options:m,requiredOptions:d}=r[f];Object.keys(m||{}).forEach(p=>{c[p]=Array.isArray(m[p])?m[p]:{...c[p],...m[p]}}),Object.keys(d||{}).forEach(p=>{c[p]=Array.isArray(d[p])?d[p]:{...c[p],...d[p],required:!0}})})});let l=[],a=[];return t.forEach(r=>{r.push?.description&&a.push(r.push.description),r.push?.usage&&l.push(r.push.usage)}),a.length>0&&e.description(a.join(`
|
|
165
166
|
`)),l.length>0&&e.usage(l.join(`
|
|
166
|
-
`)),
|
|
167
|
+
`)),F(Object.fromEntries(Object.entries(c).filter(([r,f])=>f.required!==!0)),e),F(Object.fromEntries(Object.entries(c).filter(([r,f])=>f.required===!0)),e,!0),e},Fe=nn;var K=w(require("fs")),Pe=require("dotenv"),$e=require("dotenv-expand");var be=require("child_process"),tn=(n,o)=>{let{dotsecConfig:s,decryptHandlers:t}=o||{},e=t!==void 0&&t.length>0,i=n.command("run <command...>").allowUnknownOption(!0).enablePositionalOptions().passThroughOptions().showHelpAfterError(!0).action(async(c,l,a)=>{try{let{envFile:r,using:f,secFile:m,engine:d}=a.optsWithGlobals(),p;if(f==="env"||e===!1){if(!r)throw new Error("No dotenv file specified in --env-file option");p=K.default.readFileSync(r,"utf8")}else if(f==="sec"){if(!m)throw new Error("No dotsec file specified in --sec-file option");let O=d||s?.defaults?.encryptionEngine,u=(t||[]).find(E=>E.triggerOptionValue===O);if(!u)throw new Error(`No decryption plugin found, available decryption engine(s): ${(t||[]).map(E=>`--${E.triggerOptionValue}`).join(", ")}`);let g=[...Object.keys(u.options||{}),...Object.keys(u.requiredOptions||{})],D=Object.fromEntries(g.map(E=>[E,l[E]])),v=K.default.readFileSync(m,"utf8");p=await u.handler({ciphertext:v,...D})}if(p){let O=(0,Pe.parse)(p),u=(0,$e.expand)({ignoreProcessEnv:!0,parsed:{...process.env,...O}}),[g,...D]=c,v=(0,be.spawnSync)(g,[...D],{stdio:"inherit",shell:!1,encoding:"utf-8",env:{...u.parsed,...process.env,__DOTSEC_ENV__:JSON.stringify(Object.keys(O))}});v.status!==0&&process.exit(v.status||1)}else throw new Error("No .env or .sec file provided")}catch(r){console.error(C(r.message)),a.help()}});if(P({program:i,commandName:e?"run":"runEnvOnly",dotsecConfig:s}),e){t?.map(l=>{let{options:a,requiredOptions:r}=l;F(a,i),F(r,i,!0)});let c=t?.map(l=>l.triggerOptionValue);i.option("--engine <engine>",`Encryption engine${c.length>0?"s":""}: ${c.join(", "),c.length===1?c[0]:void 0}`)}return i},Se=tn;var _e=w(require("ajv")),Ie=w(require("yargs-parser")),on={keyword:"separator",type:"string",metaSchema:{type:"string",description:"value separator"},modifying:!0,valid:!0,errors:!1,compile:n=>(o,s)=>{if(s){let{parentData:t,parentDataProperty:e}=s;return t[e]=o===""?[]:o.split(n),!0}else return!1}},T=new Te.Command;(async()=>{let n=(0,Ie.default)(process.argv),o=[];n.plugin&&(Array.isArray(n.plugin)?o.push(...n.plugin):o.push(n.plugin));let s=[...Array.isArray(n.configFile)?n.configFile:[n.configFile],...Array.isArray(n.c)?n.c:[n.c]][0]||process.env.DOTSEC_CONFIG_FILE,{contents:t={}}=await ne(s),{defaults:e={},push:i,plugins:c}=t;T.name("dotsec").description(".env, but secure").version("1.0.0").passThroughOptions().action((d,p)=>{p.help()}),P({program:T,dotsecConfig:t});let l=new _e.default({allErrors:!0,removeAdditional:!0,useDefaults:!0,coerceTypes:!0,allowUnionTypes:!0,addUsedSchema:!1,keywords:[on]}),a={};if(c)for(let d of c)e?.plugins?.[d]||(e.plugins={...e.plugins,[d]:{}});if(o.length>0)for(let d of o){let O=await(await W({name:d}))({dotsecConfig:t,ajv:l,configFile:s});a[O.name]=d,o.length===1&&(t.defaults={...t.defaults,encryptionEngine:String(O.name),plugins:{...t.defaults?.plugins,[O.name]:{...t.defaults?.plugins?.[O.name]}}})}e?.encryptionEngine&&(e?.plugins?.[e.encryptionEngine]||(e.plugins={...e.plugins,[e.encryptionEngine]:{}})),e?.plugins&&Object.entries(e?.plugins).forEach(([d,p])=>{p?.name?a[d]=p?.name:a[d]=`@dotsec/plugin-${d}`}),Object.values(i||{}).forEach(d=>{Object.keys(d).forEach(p=>{a[p]||(a[p]=`@dotsec/plugin-${p}`)})});let r=[],f=[],m=[];for(let d of Object.keys(a)){let p=a[d],O=await W({name:p}),{addCliCommand:u,cliHandlers:g}=await O({ajv:l,dotsecConfig:t,configFile:s});g?.encrypt&&r.push(g.encrypt),g?.decrypt&&(f.push(g.decrypt),g?.push&&m.push({push:g.push,decrypt:g.decrypt})),u&&u({program:T})}r.length&&await ve(T,{dotsecConfig:t,encryptHandlers:r}),f.length&&await Ce(T,{dotsecConfig:t,decryptHandlers:f}),m.length&&await Fe(T,{dotsecConfig:t,handlers:m}),await we(T,{dotsecConfig:t}),await Se(T,{dotsecConfig:t,decryptHandlers:f}),await T.parse()})();
|
|
167
168
|
//# sourceMappingURL=index.js.map
|