envrcctl 0.2.7__tar.gz → 0.2.8__tar.gz
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.
- {envrcctl-0.2.7 → envrcctl-0.2.8}/PKG-INFO +1 -1
- {envrcctl-0.2.7 → envrcctl-0.2.8}/pyproject.toml +1 -1
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/auth.py +6 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/keychain.py +16 -26
- {envrcctl-0.2.7 → envrcctl-0.2.8}/.gitignore +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/LICENSE +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/README.md +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/completions/envrcctl.bash +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/completions/envrcctl.fish +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/completions/envrcctl.zsh +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/scripts/build_macos_auth_helper.sh +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/scripts/generate_completions.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/scripts/macos/envrcctl-macos-auth.swift +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/scripts/package_for_ship.sh +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/scripts/release_artifacts.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/__init__.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/audit.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/cli.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/command_runner.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/envrc.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/envrcctl-macos-auth.bak +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/errors.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/main.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/managed_block.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/secrets.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/src/envrcctl/secretservice.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/__init__.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/conftest.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/helpers/__init__.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/helpers/cli_support.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_audit.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_audit_cli.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_auth.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_doctor.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_errors.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_eval.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_exec.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_helpers.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_inject.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_migrate.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_secret_get.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_secret_list.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_cli_secret_set_unset.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_command_runner.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_envrc.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_keychain.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_main.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_managed_block.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_secrets.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_secretservice.py +0 -0
- {envrcctl-0.2.7 → envrcctl-0.2.8}/tests/test_smoke.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: envrcctl
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: Manage .envrc with managed blocks and OS-backed secrets.
|
|
5
5
|
Project-URL: Homepage, https://github.com/rioriost/envrcctl
|
|
6
6
|
Project-URL: Issues, https://github.com/rioriost/envrcctl/issues
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
import shutil
|
|
4
5
|
import subprocess
|
|
5
6
|
import sys
|
|
6
7
|
from pathlib import Path
|
|
@@ -19,6 +20,11 @@ def _helper_path() -> Path:
|
|
|
19
20
|
configured = os.getenv(_HELPER_ENV_VAR)
|
|
20
21
|
if configured:
|
|
21
22
|
return Path(configured).expanduser()
|
|
23
|
+
|
|
24
|
+
helper_on_path = shutil.which(_DEFAULT_HELPER_BASENAME)
|
|
25
|
+
if helper_on_path:
|
|
26
|
+
return Path(helper_on_path)
|
|
27
|
+
|
|
22
28
|
return _default_helper_path()
|
|
23
29
|
|
|
24
30
|
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
|
+
import shutil
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import List
|
|
7
8
|
|
|
@@ -20,6 +21,11 @@ class KeychainBackend(SecretBackend):
|
|
|
20
21
|
configured = os.getenv(self.HELPER_ENV_VAR)
|
|
21
22
|
if configured:
|
|
22
23
|
return Path(configured).expanduser()
|
|
24
|
+
|
|
25
|
+
on_path = shutil.which(self.DEFAULT_HELPER_BASENAME)
|
|
26
|
+
if on_path:
|
|
27
|
+
return Path(on_path)
|
|
28
|
+
|
|
23
29
|
return Path(__file__).resolve().parent / self.DEFAULT_HELPER_BASENAME
|
|
24
30
|
|
|
25
31
|
def _ensure_helper_ready(self, helper_path: Path) -> None:
|
|
@@ -30,19 +36,16 @@ class KeychainBackend(SecretBackend):
|
|
|
30
36
|
)
|
|
31
37
|
if not helper_path.is_file():
|
|
32
38
|
raise EnvrcctlError(
|
|
33
|
-
"macOS authentication helper path is invalid. "
|
|
34
|
-
"Expected an executable file."
|
|
39
|
+
"macOS authentication helper path is invalid. Expected an executable file."
|
|
35
40
|
)
|
|
36
41
|
if not os.access(helper_path, os.X_OK):
|
|
37
42
|
raise EnvrcctlError(
|
|
38
|
-
"macOS authentication helper is not executable. "
|
|
39
|
-
"Fix permissions and retry."
|
|
43
|
+
"macOS authentication helper is not executable. Fix permissions and retry."
|
|
40
44
|
)
|
|
41
45
|
|
|
42
46
|
def _build_auth_reason(self, action: str, ref: SecretRef) -> str:
|
|
43
47
|
return (
|
|
44
|
-
f"envrcctl needs device owner authentication to {action} "
|
|
45
|
-
f"the secret for {ref.account}."
|
|
48
|
+
f"envrcctl needs device owner authentication to {action} the secret for {ref.account}."
|
|
46
49
|
)
|
|
47
50
|
|
|
48
51
|
def _run_auth_helper(self, args: list[str], input_text: str | None = None) -> str:
|
|
@@ -85,9 +88,7 @@ class KeychainBackend(SecretBackend):
|
|
|
85
88
|
seen_refs.add(key)
|
|
86
89
|
unique_refs.append(ref)
|
|
87
90
|
|
|
88
|
-
items = [
|
|
89
|
-
{"service": ref.service, "account": ref.account} for ref in unique_refs
|
|
90
|
-
]
|
|
91
|
+
items = [{"service": ref.service, "account": ref.account} for ref in unique_refs]
|
|
91
92
|
payload = json.dumps({"items": items})
|
|
92
93
|
|
|
93
94
|
output = self._run_auth_helper(
|
|
@@ -108,22 +109,16 @@ class KeychainBackend(SecretBackend):
|
|
|
108
109
|
try:
|
|
109
110
|
decoded = json.loads(output)
|
|
110
111
|
except json.JSONDecodeError as exc:
|
|
111
|
-
raise EnvrcctlError(
|
|
112
|
-
"Authenticated Keychain helper returned invalid JSON."
|
|
113
|
-
) from exc
|
|
112
|
+
raise EnvrcctlError("Authenticated Keychain helper returned invalid JSON.") from exc
|
|
114
113
|
|
|
115
114
|
raw_items = decoded.get("items")
|
|
116
115
|
if not isinstance(raw_items, list):
|
|
117
|
-
raise EnvrcctlError(
|
|
118
|
-
"Authenticated Keychain helper returned an invalid response."
|
|
119
|
-
)
|
|
116
|
+
raise EnvrcctlError("Authenticated Keychain helper returned an invalid response.")
|
|
120
117
|
|
|
121
118
|
values: dict[tuple[str, str], str] = {}
|
|
122
119
|
for item in raw_items:
|
|
123
120
|
if not isinstance(item, dict):
|
|
124
|
-
raise EnvrcctlError(
|
|
125
|
-
"Authenticated Keychain helper returned an invalid item."
|
|
126
|
-
)
|
|
121
|
+
raise EnvrcctlError("Authenticated Keychain helper returned an invalid item.")
|
|
127
122
|
service = item.get("service")
|
|
128
123
|
account = item.get("account")
|
|
129
124
|
value = item.get("value")
|
|
@@ -132,9 +127,7 @@ class KeychainBackend(SecretBackend):
|
|
|
132
127
|
"Authenticated Keychain helper returned an invalid item payload."
|
|
133
128
|
)
|
|
134
129
|
if not isinstance(value, str):
|
|
135
|
-
raise EnvrcctlError(
|
|
136
|
-
"Authenticated Keychain helper response is missing a value."
|
|
137
|
-
)
|
|
130
|
+
raise EnvrcctlError("Authenticated Keychain helper response is missing a value.")
|
|
138
131
|
key = (service, account)
|
|
139
132
|
if key in values:
|
|
140
133
|
raise EnvrcctlError(
|
|
@@ -145,12 +138,9 @@ class KeychainBackend(SecretBackend):
|
|
|
145
138
|
expected = {(ref.service, ref.account) for ref in unique_refs}
|
|
146
139
|
missing = expected - set(values.keys())
|
|
147
140
|
if missing:
|
|
148
|
-
missing_list = ", ".join(
|
|
149
|
-
f"{service}/{account}" for service, account in sorted(missing)
|
|
150
|
-
)
|
|
141
|
+
missing_list = ", ".join(f"{service}/{account}" for service, account in sorted(missing))
|
|
151
142
|
raise EnvrcctlError(
|
|
152
|
-
"Authenticated Keychain helper response is missing secrets: "
|
|
153
|
-
f"{missing_list}"
|
|
143
|
+
f"Authenticated Keychain helper response is missing secrets: {missing_list}"
|
|
154
144
|
)
|
|
155
145
|
|
|
156
146
|
return values
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|