Skip to content

Commit d8a6e92

Browse files
authored
Merge pull request #135 from Lerentis/bugfix/tt/133
bugfixes and updates
2 parents 4e9fd81 + 4056b8b commit d8a6e92

6 files changed

Lines changed: 57 additions & 19 deletions

File tree

‎Dockerfile‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
FROM alpine:3.23.3
1+
FROM alpine:3.24.2
22

33
LABEL org.opencontainers.image.source=https://github.com/Lerentis/bitwarden-crd-operator
44
LABEL org.opencontainers.image.description="Kubernetes Operator to create k8s secrets from bitwarden"
55
LABEL org.opencontainers.image.licenses=MIT
66

7-
ARG PYTHON_VERSION=3.12.12-r0
8-
ARG PIP_VERSION=25.1.1-r1
7+
ARG PYTHON_VERSION=3.14.7-r1
8+
ARG PIP_VERSION=26.1.2-r0
99
ARG GCOMPAT_VERSION=1.1.0-r4
10-
ARG LIBCRYPTO_VERSION=3.5.5-r0
10+
ARG LIBCRYPTO_VERSION=3.5.8-r0
1111
ARG BW_VERSION=2025.5.0
12-
ARG NODE_VERSION=24.14.1-r0
12+
ARG NODE_VERSION=24.18.1-r0
1313

1414
COPY requirements.txt /requirements.txt
1515

‎charts/bitwarden-crd-operator/Chart.yaml‎

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ description: Deploy the Bitwarden CRD Operator
44

55
type: application
66

7-
version: "v0.18.0"
7+
version: "v0.18.1"
88

9-
appVersion: "0.17.0"
9+
appVersion: "0.18.0"
1010

1111
keywords:
1212
- operator
@@ -112,8 +112,24 @@ annotations:
112112
artifacthub.io/operator: "true"
113113
artifacthub.io/containsSecurityUpdates: "false"
114114
artifacthub.io/changes: |
115-
- kind: added
116-
description: "Added self heal mechanism on vault unlock issues"
115+
- kind: changed
116+
description: "updated alpine to 3.24.2"
117+
- kind: changed
118+
description: "updated python to 3.14.7"
119+
- kind: changed
120+
description: "updated pip to 26.1.2"
121+
- kind: changed
122+
description: "updated libcrypto3 to 3.5.8"
123+
- kind: changed
124+
description: "updated nodejs to 24.18.1"
125+
- kind: fixed
126+
description: "fixed auth recovery to reconfigure the bitwarden host instead of falling back to a default"
127+
- kind: changed
128+
description: "updated kopf to 1.44.6"
129+
- kind: changed
130+
description: "updated kubernetes to 36.0.3"
131+
- kind: fixed
132+
description: "fixed termination of operator process after failed authentication recovery"
117133
artifacthub.io/images: |
118134
- name: bitwarden-crd-operator
119-
image: ghcr.io/lerentis/bitwarden-crd-operator:0.17.0
135+
image: ghcr.io/lerentis/bitwarden-crd-operator:0.18.0

‎requirements.txt‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
kopf==1.44.4
2-
kubernetes==35.0.0
1+
kopf==1.44.6
2+
kubernetes==36.0.3
33
Jinja2==3.1.6
44
schedule==1.2.2

‎src/bitwardenCrdOperator.py‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,15 @@ def recover_auth_state(logger):
9292
command_wrapper(logger, "logout", use_success=False)
9393

9494
home_dir = os.path.expanduser("~")
95+
96+
bw_host_file = os.path.join(home_dir, ".bw_host")
97+
if os.path.isfile(bw_host_file):
98+
try:
99+
os.remove(bw_host_file)
100+
logger.warn("Removed Bitwarden CLI host marker to recover auth state")
101+
except OSError as exc:
102+
logger.warn(f"Could not remove Bitwarden CLI host marker: {exc}")
103+
95104
cli_data_file = os.path.join(home_dir, ".config", "Bitwarden CLI", "data.json")
96105
if os.path.isfile(cli_data_file):
97106
try:
@@ -126,6 +135,7 @@ def bitwarden_signin(logger, **kwargs):
126135
"Authentication failure threshold reached, recovering Bitwarden auth state"
127136
)
128137
recover_auth_state(logger)
138+
_configure_bw_host(logger)
129139

130140
recovery_ok, recovery_error = _login_and_unlock(logger)
131141
if recovery_ok:
@@ -135,7 +145,7 @@ def bitwarden_signin(logger, **kwargs):
135145

136146
logger.error(f"Authentication recovery failed: {recovery_error}")
137147
logger.error("Stopping operator process after failed authentication recovery")
138-
sys.exit(1)
148+
os._exit(1)
139149

140150

141151
def run_continuously(interval=30):

‎src/utils/utils.py‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
import os
22
import json
33
import subprocess
4-
import distutils
54
import kubernetes
65
import kopf
76

7+
8+
def _strtobool(value):
9+
normalized = str(value).strip().lower()
10+
if normalized in {"y", "yes", "1", "true", "on"}:
11+
return 1
12+
if normalized in {"n", "no", "0", "false", "off", ""}:
13+
return 0
14+
raise ValueError(f"invalid truth value {value!r}")
15+
816
bw_sync_interval = float(os.environ.get(
917
'BW_SYNC_INTERVAL', 900))
1018

@@ -30,7 +38,7 @@ def _sync(logger):
3038
logger.info("Running with regular force sync enabled")
3139
return
3240

33-
global_force_sync = bool(distutils.util.strtobool(
41+
global_force_sync = bool(_strtobool(
3442
os.environ.get('BW_FORCE_SYNC', "false")))
3543

3644
if global_force_sync:

‎tests/test_bitwarden_signin_recovery.py‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,19 @@ def test_recovery_runs_after_threshold_and_resets_counter(
8686
self.assertEqual(operator.auth_failures, 0)
8787
self.assertEqual(os.environ.get("BW_SESSION"), "new-session")
8888

89-
@patch("bitwardenCrdOperator.sys.exit")
89+
@patch("bitwardenCrdOperator.os._exit")
9090
@patch("bitwardenCrdOperator.recover_auth_state")
9191
@patch("bitwardenCrdOperator.command_wrapper")
9292
def test_recovery_failure_exits_process(
93-
self, command_wrapper_mock, recover_auth_state_mock, sys_exit_mock
93+
self, command_wrapper_mock, recover_auth_state_mock, os_exit_mock
9494
):
9595
os.environ["BW_AUTH_FAILURE_THRESHOLD"] = "1"
9696
command_wrapper_mock.side_effect = [None, None]
9797

9898
operator.bitwarden_signin(self.logger)
9999

100100
recover_auth_state_mock.assert_called_once_with(self.logger)
101-
sys_exit_mock.assert_called_once_with(1)
101+
os_exit_mock.assert_called_once_with(1)
102102

103103
def test_invalid_threshold_uses_default_without_exception_control_flow(self):
104104
os.environ["BW_AUTH_FAILURE_THRESHOLD"] = "invalid"
@@ -108,13 +108,16 @@ def test_invalid_threshold_uses_default_without_exception_control_flow(self):
108108
self.assertEqual(threshold, operator.AUTH_FAILURE_THRESHOLD)
109109

110110
@patch("bitwardenCrdOperator.command_wrapper")
111-
def test_recover_auth_state_clears_session_and_cache_file(
111+
def test_recover_auth_state_clears_session_cache_and_bw_host_marker(
112112
self, command_wrapper_mock
113113
):
114114
with tempfile.TemporaryDirectory() as temp_dir:
115115
data_file = Path(temp_dir) / ".config" / "Bitwarden CLI" / "data.json"
116116
data_file.parent.mkdir(parents=True, exist_ok=True)
117117
data_file.write_text("{ invalid", encoding="utf-8")
118+
119+
bw_host_file = Path(temp_dir) / ".bw_host"
120+
bw_host_file.write_text("https://vault.example.com", encoding="utf-8")
118121
os.environ["BW_SESSION"] = "stale-session"
119122

120123
with patch(
@@ -124,6 +127,7 @@ def test_recover_auth_state_clears_session_and_cache_file(
124127

125128
self.assertNotIn("BW_SESSION", os.environ)
126129
self.assertFalse(data_file.exists())
130+
self.assertFalse(bw_host_file.exists())
127131
command_wrapper_mock.assert_called_once_with(
128132
self.logger, "logout", use_success=False
129133
)

0 commit comments

Comments
 (0)