@lsmacedo/envres 0.0.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.
Files changed (3) hide show
  1. package/README.md +38 -0
  2. package/envres +173 -0
  3. package/package.json +8 -0
package/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # envres
2
+
3
+ Resolve environment variable references from the macOS keychain and run a command with the real secrets injected.
4
+
5
+ Set a variable's value to an `envres/<service>` reference instead of a plaintext secret. `envres` rewrites it to the keychain secret (`security find-generic-password -s <service> -w`) just before running your command. Variables without the prefix pass through untouched.
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ npm i -g envres
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```sh
16
+ envres run [--env-file <path>] -- <command> [args...]
17
+ ```
18
+
19
+ Reference secrets in your shell profile, then alias the command that needs them:
20
+
21
+ ```sh
22
+ export ARTIFACTORY_TOKEN="envres/artifactory-token"
23
+ alias npm='envres run -- npm'
24
+ ```
25
+
26
+ Now `npm install` runs with `ARTIFACTORY_TOKEN` resolved from the keychain.
27
+
28
+ Load references from a `.env` file too (the file is never modified; its values override the environment):
29
+
30
+ ```sh
31
+ envres run --env-file .env -- npm install
32
+ ```
33
+
34
+ ```sh
35
+ # .env
36
+ ARTIFACTORY_TOKEN=envres/artifactory-token
37
+ NPM_TOKEN=envres/npm-token
38
+ ```
package/envres ADDED
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # envres — resolve environment variable references from a secret backend
4
+ # (currently the macOS keychain) and run a command with them injected.
5
+ #
6
+ # Set an env var's value to a reference, e.g. in your shell profile:
7
+ #
8
+ # export ARTIFACTORY_TOKEN="envres/artifactory-token"
9
+ #
10
+ # Then wrap the command that needs the real secret:
11
+ #
12
+ # alias npm='envres run -- npm'
13
+ #
14
+ # When you run `npm install`, envres rewrites ARTIFACTORY_TOKEN to the output
15
+ # of `security find-generic-password -s artifactory-token -w` before exec'ing
16
+ # the wrapped command. Vars without the prefix pass through untouched.
17
+ #
18
+ # --env-file <path> additionally loads KEY=value lines from a .env file into the
19
+ # command's environment, resolving any `envres/`-prefixed values the same way.
20
+ # The file is read-only; its values override the existing environment.
21
+
22
+ set -euo pipefail
23
+
24
+ PREFIX="envres/"
25
+
26
+ usage() {
27
+ cat <<'EOF'
28
+ usage: envres run [--env-file <path>] -- <command> [args...]
29
+
30
+ Resolves environment variables whose value is "envres/<service>" by
31
+ replacing them with `security find-generic-password -s <service> -w`,
32
+ then executes <command>.
33
+
34
+ --env-file <path> Also load KEY=value lines from <path> into the command's
35
+ environment (resolving envres/ values). Values from the
36
+ file override the existing environment. The file is never
37
+ modified.
38
+
39
+ example:
40
+ alias npm='envres run -- npm'
41
+ envres run --env-file .env -- npm install
42
+ EOF
43
+ }
44
+
45
+ resolve_secret() {
46
+ local service="$1"
47
+ if ! security find-generic-password -s "$service" -w 2>/dev/null; then
48
+ echo "envres: no keychain entry for service '$service'" >&2
49
+ return 1
50
+ fi
51
+ }
52
+
53
+ # Load KEY=value lines from a .env file, exporting each into the environment.
54
+ # Values are exported verbatim (including any envres/ prefix); resolve_env
55
+ # performs keychain substitution afterward over the merged environment.
56
+ load_env_file() {
57
+ local file="$1" line key value
58
+ if [[ ! -r "$file" ]]; then
59
+ echo "envres: cannot read env file '$file'" >&2
60
+ return 1
61
+ fi
62
+
63
+ while IFS= read -r line || [[ -n "$line" ]]; do
64
+ line="${line#"${line%%[![:space:]]*}"}" # trim leading whitespace
65
+ [[ -z "$line" || "$line" == "#"* ]] && continue
66
+ [[ "$line" == "export "* ]] && line="${line#export }"
67
+ [[ "$line" == *=* ]] || continue
68
+
69
+ key="${line%%=*}"
70
+ value="${line#*=}"
71
+
72
+ if [[ ! "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then
73
+ echo "envres: skipping invalid key '$key' in '$file'" >&2
74
+ continue
75
+ fi
76
+
77
+ if [[ "$value" == \"*\" || "$value" == \'*\' ]]; then
78
+ value="${value:1:${#value}-2}" # strip one pair of surrounding quotes
79
+ else
80
+ value="${value%"${value##*[![:space:]]}"}" # trim trailing whitespace
81
+ fi
82
+
83
+ export "$key=$value"
84
+ done <"$file"
85
+ }
86
+
87
+ resolve_env() {
88
+ local name value service secret
89
+ while IFS= read -r name; do
90
+ value="${!name-}"
91
+ [[ "$value" == "$PREFIX"* ]] || continue
92
+
93
+ service="${value#"$PREFIX"}"
94
+ if [[ -z "$service" ]]; then
95
+ echo "envres: $name has empty service reference ('$value')" >&2
96
+ return 1
97
+ fi
98
+
99
+ if ! secret="$(resolve_secret "$service")"; then
100
+ echo "envres: failed to resolve $name from keychain" >&2
101
+ return 1
102
+ fi
103
+
104
+ export "$name=$secret"
105
+ done < <(compgen -e)
106
+ }
107
+
108
+ main() {
109
+ if [[ $# -eq 0 ]]; then
110
+ usage >&2
111
+ exit 2
112
+ fi
113
+
114
+ case "$1" in
115
+ -h | --help)
116
+ usage
117
+ exit 0
118
+ ;;
119
+ run)
120
+ shift
121
+ ;;
122
+ *)
123
+ echo "envres: unknown subcommand '$1'" >&2
124
+ usage >&2
125
+ exit 2
126
+ ;;
127
+ esac
128
+
129
+ local env_file=""
130
+ while [[ $# -gt 0 ]]; do
131
+ case "$1" in
132
+ --env-file)
133
+ env_file="${2-}"
134
+ if [[ -z "$env_file" ]]; then
135
+ echo "envres: --env-file requires a path" >&2
136
+ exit 2
137
+ fi
138
+ shift 2
139
+ ;;
140
+ --env-file=*)
141
+ env_file="${1#--env-file=}"
142
+ shift
143
+ ;;
144
+ --)
145
+ shift
146
+ break
147
+ ;;
148
+ -*)
149
+ echo "envres: unknown option '$1'" >&2
150
+ usage >&2
151
+ exit 2
152
+ ;;
153
+ *)
154
+ break
155
+ ;;
156
+ esac
157
+ done
158
+
159
+ if [[ $# -eq 0 ]]; then
160
+ echo "envres: no command given" >&2
161
+ usage >&2
162
+ exit 2
163
+ fi
164
+
165
+ if [[ -n "$env_file" ]]; then
166
+ load_env_file "$env_file" || exit 2
167
+ fi
168
+
169
+ resolve_env
170
+ exec "$@"
171
+ }
172
+
173
+ main "$@"
package/package.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "@lsmacedo/envres",
3
+ "bin": "./envres",
4
+ "version": "0.0.1",
5
+ "description": "Resolve environment variable references from the macOS keychain and run a command with them injected.",
6
+ "license": "ISC",
7
+ "author": "lsmacedo"
8
+ }