Skip to content

Commit

Permalink
Merge pull request #236 from dotenv-org/decrypt
Browse files Browse the repository at this point in the history
Decrypt command
  • Loading branch information
motdotla committed Jan 27, 2023
2 parents a4d5046 + 62f1abc commit 69bb993
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 2 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [Unreleased](https://github.com/dotenv-org/dotenv-vault/compare/v1.17.0...master)
## [Unreleased](https://github.com/dotenv-org/dotenv-vault/compare/v1.18.0...master)

## [1.17.0](https://github.com/dotenv-org/dotenv-vault/compare/v1.17.0...v1.18.0) (2023-01-27)

### Added

- Added `decrypt` command [#236](https://github.com/dotenv-org/dotenv-vault/pull/236)

## [1.17.0](https://github.com/dotenv-org/dotenv-vault/compare/v1.16.3...v1.17.0) (2022-12-13)

Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ Below are a list of dotenv-vault cli commands. You can also learn more on the [d
* [build](#build)
* [keys](#keys)
* [rotatekey](#rotatekey)
* [decrypt](#decrypt)
* [versions](#versions)

### `new`
Expand Down Expand Up @@ -739,6 +740,28 @@ $ npx dotenv-vault rotatekey -y

---

### `decrypt`

Decrypt .env.vault locally.

Example:

```bash
$ npx dotenv-vault decrypt dotenv://:[email protected]/vault/.env.vault?environment=development
```

##### ARGUMENTS

*[DOTENV_KEY]*

Set `DOTENV_KEY` to decrypt .env.vault. Development key will decrypt development, production will decrypt production, and so on.

```
$ npx dotenv-vault decrypt dotenv://:[email protected]/vault/.env.vault?environment=development
```

---

### `versions`

List version history.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"axios": "^0.27.2",
"chalk": "^4.1.2",
"dotenv": "16.0.3",
"dotenv-vault-core": "0.6.1"
"dotenv-vault-core": "0.7.0"
},
"devDependencies": {
"@oclif/test": "^2",
Expand Down
27 changes: 27 additions & 0 deletions src/commands/decrypt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {Command} from '@oclif/core'

import {DecryptService} from '../services/decrypt-service'

export default class Decrypt extends Command {
static description = 'Decrypt .env.vault locally'

static examples = [
'<%= config.bin %> <%= command.id %>',
]

static args = [
{
name: 'DOTENV_KEY',
required: true,
description: 'Set decryption key',
hidden: false,
},
]

public async run(): Promise<void> {
const {args} = await this.parse(Decrypt)
const dotenvKey = args.DOTENV_KEY

await new DecryptService({cmd: this, dotenvKey: dotenvKey}).run()
}
}
90 changes: 90 additions & 0 deletions src/services/decrypt-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {LogService} from '../services/log-service'

import {config} from 'dotenv'
import {decrypt} from 'dotenv-vault-core'

interface DecryptServiceAttrs {
cmd;
dotenvKey;
}

type InstructionsType = {
ciphertext: string;
key: string;
}

class DecryptService {
public cmd;
public dotenvKey;
public log;

constructor(attrs: DecryptServiceAttrs = {} as DecryptServiceAttrs) {
this.cmd = attrs.cmd
this.dotenvKey = attrs.dotenvKey

this.log = new LogService({cmd: attrs.cmd})
}

async run(): Promise<void> {
const result = config({path: this.vaultPath})
const keys = this.dotenvKey.split(',')
const length = keys.length

let decrypted
for (let i = 0; i < length; i++) {
try {
// Get full key
const key = keys[i].trim()

// Get instructions for decrypt
const attrs = this._instructions(result, key)

// Decrypt
decrypted = decrypt(attrs.ciphertext, attrs.key)

break
} catch (error) {
// last key
if (i + 1 >= length) {
throw error
}
// try next key
}
}

this.log.plain(decrypted)
}

_instructions(result: string, dotenvKey: string): InstructionsType {
// Parse DOTENV_KEY. Format is a URI
const uri = new URL(dotenvKey)

// Get decrypt key
const key = uri.password
if (!key) {
throw new Error('INVALID_DOTENV_KEY: Missing key part')
}

// Get environment
const environment = uri.searchParams.get('environment')
if (!environment) {
throw new Error('INVALID_DOTENV_KEY: Missing environment part')
}

// Get ciphertext payload
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`
const ciphertext = result.parsed[environmentKey] // DOTENV_VAULT_PRODUCTION
if (!ciphertext) {
throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file. Run 'npx dotenv-vault build' to include it.`)
}

return {ciphertext, key}
}

get vaultPath(): string {
return '.env.vault'
}
}

export {DecryptService}

0 comments on commit 69bb993

Please sign in to comment.