From 5781727353121d112b6daa6776643d76af5169e4 Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 16:36:22 +0200 Subject: [PATCH 01/13] test(bridge): identify bounded late-enrollment annotation drift Retain enforcement and original failures; report only fixed annotation booleans and UID-fenced retirement phase comparisons. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- .../template_diagnostics.py | 69 +++++++++++++++++++ .../test_template_diagnostics.py | 58 ++++++++++++++-- 2 files changed, 123 insertions(+), 4 deletions(-) diff --git a/bridge/tests/native-credentials/template_diagnostics.py b/bridge/tests/native-credentials/template_diagnostics.py index 6142235c..a64fb3b1 100644 --- a/bridge/tests/native-credentials/template_diagnostics.py +++ b/bridge/tests/native-credentials/template_diagnostics.py @@ -12,6 +12,14 @@ ACTORS = ("runtime", "controller", "bff") LIMIT = 2 * 1024 * 1024 UNAVAILABLE = "Native template comparison unavailable" +ANNOTATION_GROUPS = { + "privateEpochChanged": "kars.azure.com/private-epoch", + "servicesCredentialVersionChanged": "kars.azure.com/services-credential-version", + "credentialProjectionVersionChanged": "kars.azure.com/credential-projection-version", + "inferenceProvidersVersionChanged": "kars.azure.com/inference-providers-version", +} +RETIREMENT = "kars.azure.com/private-root-retirement" +PHASES = ("Pausing", "Retired", "Rotating", "Restoring", "Qualified") HASH_SCRIPT = """ import {readFileSync} from 'node:fs'; import {pathToFileURL} from 'node:url'; @@ -104,6 +112,18 @@ def project(before, current, review, before_digest, current_digest): } for key in ("labels", "annotations"): result[key + "Changed"] = encoded(baseline["metadata"].get(key)) != encoded(actual["metadata"].get(key)) + before_annotations = baseline["metadata"].get("annotations") + current_annotations = actual["metadata"].get("annotations") + require(all(value is None or isinstance(value, dict) + for value in (before_annotations, current_annotations)), UNAVAILABLE) + before_annotations = before_annotations or {} + current_annotations = current_annotations or {} + for label, key in ANNOTATION_GROUPS.items(): + result[label] = encoded(before_annotations.get(key)) != encoded(current_annotations.get(key)) + known = set(ANNOTATION_GROUPS.values()) + result["otherAnnotationsChanged"] = encoded({ + key: value for key, value in before_annotations.items() if key not in known + }) != encoded({key: value for key, value in current_annotations.items() if key not in known}) sections = ("containers", "initContainers", "volumes", "securityContext", "serviceAccountName") for key in sections: result[key + "Changed"] = encoded(baseline["spec"].get(key)) != encoded(actual["spec"].get(key)) @@ -114,6 +134,50 @@ def project(before, current, review, before_digest, current_digest): return result +def late_retirement(setup, scopes, runtime, current_digest): + """Report a stable receipt's phase/comparison, never claim to verify authority.""" + result = {"available": False, "category": "provenance-or-receipt-unavailable"} + try: + namespace, _, deployment_uid = identity(runtime) + matches = [scope for scope in scopes if scope["namespace"].get("name") == namespace] + require(len(matches) == 1 and isinstance(matches[0]["namespace"].get("uid"), str) + and matches[0]["namespace"]["uid"], UNAVAILABLE) + value = setup.admin.get("/api/v1/namespaces/" + namespace) + require(isinstance(value, dict) and isinstance(value.get("metadata"), dict), UNAVAILABLE) + meta = value.get("metadata", {}) + require(meta.get("name") == namespace and meta.get("uid") == matches[0]["namespace"]["uid"] + and isinstance(meta.get("resourceVersion"), str) and meta["resourceVersion"], UNAVAILABLE) + fields = meta.get("annotations") + require(fields is None or isinstance(fields, dict), UNAVAILABLE) + raw = (fields or {}).get(RETIREMENT) + if raw is None: + result = {"available": False, "category": "absent"} + else: + require(isinstance(raw, str) and len(raw.encode()) <= 131_072, UNAVAILABLE) + state = json.loads(raw) + require(isinstance(state, dict) and type(state.get("version")) is int + and state["version"] == 4 and state.get("phase") in PHASES + and isinstance(state.get("deployment"), dict), UNAVAILABLE) + result = { + "available": True, "reportedPhase": state["phase"], + "recordedDeploymentMatches": state["deployment"].get("uid") == deployment_uid, + "qualifiedTemplateRecorded": state.get("qualified") is not None, + "authorityVerified": False, + } + if result["qualifiedTemplateRecorded"]: + require(isinstance(state["qualified"], dict), UNAVAILABLE) + expected = state["qualified"].get("template") + require(isinstance(expected, str) and re.fullmatch(r"[a-f0-9]{64}", expected), UNAVAILABLE) + result["currentMatchesRecordedTemplate"] = current_digest == expected + again = setup.admin.get("/api/v1/namespaces/" + namespace) + require(isinstance(again, dict) and isinstance(again.get("metadata"), dict), UNAVAILABLE) + require(again["metadata"].get("uid") == meta["uid"] + and again["metadata"].get("resourceVersion") == meta["resourceVersion"], UNAVAILABLE) + return result + except READ_ERRORS: + return {"available": False, "category": "provenance-or-receipt-unavailable"} + + def collect(setup, baselines, failure): result = {"diagnosticOnly": True, "available": False, "category": "not-eligible"} if not isinstance(failure, str) or not any(failure.startswith(f"Native operator apply failed: {category} ") @@ -144,6 +208,8 @@ def collect(setup, baselines, failure): for consumer in scope["consumers"]) for scope in scopes), UNAVAILABLE) selected = [scope for scope in scopes if scope["namespace"]["name"] in namespaces] comparisons = {} + current_runtime = None + runtime_digest = None for actor in ACTORS: before = baselines[actor] namespace, name, uid = identity(before) @@ -159,7 +225,10 @@ def collect(setup, baselines, failure): and rechecked["metadata"]["resourceVersion"] == current["metadata"]["resourceVersion"], UNAVAILABLE) comparisons[actor] = project(before, current, matches[0], before_hash, current_hash) + if actor == "runtime": + current_runtime, runtime_digest = current, current_hash result.update(available=True, category="compared", actors=comparisons) + result["lateRetirement"] = late_retirement(setup, selected, current_runtime, runtime_digest) except READ_ERRORS: result["category"] = "provenance-or-comparison-unavailable" return result diff --git a/bridge/tests/native-credentials/test_template_diagnostics.py b/bridge/tests/native-credentials/test_template_diagnostics.py index 064785f3..2f075eeb 100644 --- a/bridge/tests/native-credentials/test_template_diagnostics.py +++ b/bridge/tests/native-credentials/test_template_diagnostics.py @@ -88,6 +88,24 @@ def test_section_comparisons_preserve_types_and_cover_other_pod_fields(self): with self.assertRaises(Failure): diagnostics.project(value, current, review(before), "a" * 64, "b" * 64) + def test_annotation_groups_retain_only_fixed_booleans_including_unknown_changes(self): + before = deployment("runtime") + for label, key in diagnostics.ANNOTATION_GROUPS.items(): + current = copy.deepcopy(before) + current["spec"]["template"]["metadata"]["annotations"] = {key: PRIVATE} + facts = diagnostics.project(before, current, review(before), *fixture_hashes([before, current])) + self.assertTrue(facts[label]) + self.assertTrue(facts["annotationsChanged"]) + self.assertFalse(facts["otherAnnotationsChanged"]) + self.assertTrue(all(type(value) is bool for value in facts.values())) + self.assertNotIn(PRIVATE, json.dumps(facts)) + self.assertNotIn(key, json.dumps(facts)) + current["spec"]["template"]["metadata"]["annotations"] = {PRIVATE: PRIVATE} + facts = diagnostics.project(before, current, review(before), *fixture_hashes([before, current])) + self.assertTrue(facts["otherAnnotationsChanged"]) + self.assertTrue(all(not facts[key] for key in diagnostics.ANNOTATION_GROUPS)) + self.assertNotIn(PRIVATE, json.dumps(facts)) + def test_wrong_namespaces_owners_and_review_shapes_are_refused(self): before = deployment("runtime") for key in ("namespace", "name"): @@ -100,12 +118,14 @@ def test_wrong_namespaces_owners_and_review_shapes_are_refused(self): with self.assertRaises(Failure): diagnostics.project(before, before, invalid, "a" * 64, "b" * 64) - def collect(self, *, mutate_review=None, changed_on_recheck=False, unavailable_hashes=False, failure=FAILURE): + def collect(self, *, mutate_review=None, changed_on_recheck=False, unavailable_hashes=False, + failure=FAILURE, receipt=None, namespace_changed=False): baselines = {actor: deployment(actor) for actor in diagnostics.ACTORS} document = {"apiVersion": "kars.azure.com/v1alpha1", "kind": "KarsCredentialGrant", "metadata": {"name": "workspace", "namespace": "kars-system"}, "spec": {"privateActivation": {"phase": "reviewed", "namespaces": [ - {"namespace": {"name": "work"}, "consumers": [review(value) for value in baselines.values()]} + {"namespace": {"name": "work", "uid": "work-uid"}, + "consumers": [review(value) for value in baselines.values()]} ]}}} if mutate_review: mutate_review(document) @@ -113,6 +133,10 @@ def collect(self, *, mutate_review=None, changed_on_recheck=False, unavailable_h def get(path): reads.append(path) + if path == "/api/v1/namespaces/work": + return {"metadata": {"name": "work", "uid": "work-uid", + "resourceVersion": "2" if namespace_changed and reads.count(path) == 2 else "1", + "annotations": {} if receipt is None else {diagnostics.RETIREMENT: json.dumps(receipt)}}} value = copy.deepcopy(baselines[path.rsplit("/", 1)[-1]]) if changed_on_recheck and len(reads) % 2 == 0: value["metadata"]["resourceVersion"] = "2" @@ -138,13 +162,39 @@ def test_complete_collector_rechecks_all_three_exact_deployments(self): self.assertTrue(result["available"]) self.assertTrue(result["diagnosticOnly"]) self.assertEqual(set(result["actors"]), set(diagnostics.ACTORS)) - self.assertEqual(len(reads), 6) + self.assertEqual(len(reads), 8) self.assertTrue(all(value["currentMatchesReview"] for value in result["actors"].values())) + self.assertEqual(result["lateRetirement"], {"available": False, "category": "absent"}) def test_writer_restoration_refusal_also_gets_value_free_template_comparisons(self): result, reads = self.collect(failure="Native operator apply failed: writer-runtime-transition (source=unavailable)") self.assertTrue(result["available"]) - self.assertEqual(len(reads), 6) + self.assertEqual(len(reads), 8) + + def test_stable_late_receipt_reports_phase_and_comparison_without_publishing_hashes(self): + expected = fixture_hashes([deployment("runtime")])[0] + receipt = {"version": 4, "phase": "Restoring", "deployment": {"uid": "runtime-uid"}, + "qualified": {"template": expected}, "private": PRIVATE} + result, _ = self.collect(receipt=receipt) + facts = result["lateRetirement"] + self.assertEqual(facts, {"available": True, "reportedPhase": "Restoring", + "recordedDeploymentMatches": True, "qualifiedTemplateRecorded": True, + "authorityVerified": False, "currentMatchesRecordedTemplate": True}) + self.assertNotIn(expected, json.dumps(result)) + self.assertNotIn(PRIVATE, json.dumps(result)) + receipt["qualified"]["template"] = "f" * 64 + result, _ = self.collect(receipt=receipt) + self.assertFalse(result["lateRetirement"]["currentMatchesRecordedTemplate"]) + + def test_unstable_or_invalid_receipt_does_not_erase_valid_deployment_comparisons(self): + receipt = {"version": 4, "phase": "Pausing", "deployment": {"uid": "runtime-uid"}} + for options in ({"receipt": receipt, "namespace_changed": True}, + {"receipt": {**receipt, "phase": PRIVATE}}, + {"receipt": {**receipt, "qualified": {"template": PRIVATE}}}): + result, _ = self.collect(**options) + self.assertTrue(result["available"]) + self.assertFalse(result["lateRetirement"]["available"]) + self.assertNotIn(PRIVATE, json.dumps(result)) def test_changed_resource_or_failed_hashing_never_returns_partial_comparisons(self): for options in ({"changed_on_recheck": True}, {"unavailable_hashes": True}): From 6a6201d4cc4cb90c90c1c3c5a46c54aaf6511723 Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 17:26:24 +0200 Subject: [PATCH 02/13] test: require complete audit intervals and real budget admission denial Read retained audit rotations, fence request barriers by Audit-Id, preserve exact CREATE counts, and disallow RBAC or transport failures as private-audience denial proof. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- .../native-credentials/audit_evidence.py | 96 +++++++++++++++ .../native-credentials/credential_cases.py | 7 +- bridge/tests/native-credentials/native_api.py | 29 +++-- .../native-credentials/test_audit_evidence.py | 115 ++++++++++++++++++ tests/e2e/budget-api-kubectl.mjs | 16 ++- tests/e2e/budget-api-kubectl.test.mjs | 41 ++++++- tests/e2e/inference-budget-api.mjs | 20 ++- 7 files changed, 302 insertions(+), 22 deletions(-) create mode 100644 bridge/tests/native-credentials/audit_evidence.py create mode 100644 bridge/tests/native-credentials/test_audit_evidence.py diff --git a/bridge/tests/native-credentials/audit_evidence.py b/bridge/tests/native-credentials/audit_evidence.py new file mode 100644 index 00000000..a0141261 --- /dev/null +++ b/bridge/tests/native-credentials/audit_evidence.py @@ -0,0 +1,96 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +"""Bounded metadata-only audit snapshots, including retained rotated files.""" + +import json +import re + +from native_api import BRIDGE, WRITER, CommandFailure, Failure, command, require, resource, until + +DIRECTORY = "/var/log/kars-native-audit" +CONTROL_PLANE = "bridge-native-control-plane" +MAX_BYTES = 80 * 1024 * 1024 +AUDIT_ID = re.compile(r"[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}") +NAME = re.compile(r"audit(?:-[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}-[0-9]{2}-[0-9]{2}\.[0-9]{3})?\.log") + + +class AuditSnapshot(list): + def __init__(self, events, marker): + super().__init__(events) + self.marker = marker + + +def paths(): + names = command("docker", "exec", CONTROL_PLANE, "find", DIRECTORY, + "-maxdepth", "1", "-type", "f", "-name", "audit*.log", + timeout=30).splitlines() + require(1 <= len(names) <= 3 and len(set(names)) == len(names) + and DIRECTORY + "/audit.log" in names + and all(name.startswith(DIRECTORY + "/") and + NAME.fullmatch(name[len(DIRECTORY) + 1:]) for name in names), + "Native audit file inventory is unavailable or outside its bounded scope") + return sorted(names) + + +def parse_events(raw, namespace=None): + require(len(raw.encode()) <= MAX_BYTES, "Native audit snapshot exceeds its bounded size") + unique = {} + for line in raw.splitlines(): + if not line: + continue + event = json.loads(line) + require(isinstance(event, dict), "Native audit contains an invalid record") + if event.get("stage") != "ResponseComplete" or event.get("user", {}).get("username") != ( + f"system:serviceaccount:{BRIDGE}:{WRITER}"): + continue + if namespace is not None and event.get("objectRef", {}).get("namespace") != namespace: + continue + audit_id = event.get("auditID") + require(isinstance(audit_id, str) and AUDIT_ID.fullmatch(audit_id), + "Native audit record omitted a valid request identity") + if audit_id in unique: + require(unique[audit_id] == event, "Native audit contains conflicting records for one request") + unique[audit_id] = event + return list(unique.values()) + + +def read(namespace=None): + for _ in range(3): + try: + before = paths() + raw = command("docker", "exec", CONTROL_PLANE, "cat", *before, timeout=30) + if before != paths(): + continue + return parse_events(raw, namespace) + except (CommandFailure, json.JSONDecodeError): + # Rotation can retire a file between inventory and open. + continue + raise Failure("Native audit snapshot did not settle; no complete event proof is available") + + +def barrier(setup, actor, namespace): + marker = actor.audit_marker(resource(namespace, "karscredentialgrants", "workspace")) + + def observed(): + events = setup.audit(namespace) + matches = [event for event in events if event["auditID"] == marker] + if not matches: + return None + require(len(matches) == 1 and matches[0].get("verb") == "get" + and matches[0].get("objectRef", {}).get("resource") == "karscredentialgrants" + and matches[0]["objectRef"].get("name") == "workspace" + and matches[0].get("responseStatus", {}).get("code") == 200, + "Native audit barrier does not match its actual successful request") + return AuditSnapshot(events, marker) + + return until("actual metadata audit barrier", observed, 30) + + +def changes(before, after): + require(isinstance(before, AuditSnapshot) and isinstance(after, AuditSnapshot) + and before.marker != after.marker, "Native audit interval needs two distinct actual barriers") + ids = {event["auditID"] for event in before} + require(before.marker in ids and any(event["auditID"] == before.marker for event in after), + "Native audit interval lost its starting barrier; event coverage is incomplete") + return [event for event in after if event["auditID"] not in ids] diff --git a/bridge/tests/native-credentials/credential_cases.py b/bridge/tests/native-credentials/credential_cases.py index 57dfa89d..b32d3ac4 100644 --- a/bridge/tests/native-credentials/credential_cases.py +++ b/bridge/tests/native-credentials/credential_cases.py @@ -64,8 +64,8 @@ def paused_team(setup, namespace, name): def changes_since(setup, actor, namespace, before): - ids = {event["auditID"] for event in before} - return [event for event in setup.audit_barrier(actor, namespace) if event["auditID"] not in ids] + from audit_evidence import changes + return changes(before, setup.audit_barrier(actor, namespace)) class CredentialCases: @@ -122,7 +122,8 @@ def bootstrap(self): posts = [event for event in events if event["verb"] == "create" and event.get("objectRef", {}).get("resource") == "secrets" and event.get("responseStatus", {}).get("code") == 201] - require(len(posts) == 1, "Bootstrap did not use one exclusive native source CREATE") + require(len(posts) == 1, + f"Bootstrap requires exactly one native source CREATE; observed {len(posts)} in the complete audit interval") created_at = posts[0]["requestReceivedTimestamp"] gets = [event for event in events if event["verb"] == "get" and event.get("objectRef", {}).get("resource") == "secrets" diff --git a/bridge/tests/native-credentials/native_api.py b/bridge/tests/native-credentials/native_api.py index a2039537..c5281653 100644 --- a/bridge/tests/native-credentials/native_api.py +++ b/bridge/tests/native-credentials/native_api.py @@ -146,7 +146,7 @@ def __init__(self, server, context, token=None): self.server = server def request(self, method, path, body=None, expected=(200,), patch_type=None, *, - accept="application/json", timeout=15): + accept="application/json", timeout=15, audit_ids=None): headers = {"Accept": accept} if self.token: headers["Authorization"] = f"Bearer {self.token}" @@ -165,6 +165,12 @@ def request(self, method, path, body=None, expected=(200,), patch_type=None, *, if response.status not in expected: raise Failure( f"Kubernetes {method} {path.split('?')[0]} returned {response.status} ({status_detail(value)})") + if audit_ids is not None: + audit_id = response.getheader("Audit-Id") + require(isinstance(audit_id, str) and re.fullmatch( + r"[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}", audit_id), + "Actual Kubernetes response omitted a valid audit request identity") + audit_ids.append(audit_id) return response.status, value finally: connection.close() @@ -172,6 +178,11 @@ def request(self, method, path, body=None, expected=(200,), patch_type=None, *, def get(self, path): return self.request("GET", path)[1] + def audit_marker(self, path): + ids = [] + self.request("GET", path, audit_ids=ids) + return ids[0] + def optional(self, path): status, body = self.request("GET", path, expected=(200, 404)) return body if status == 200 else None @@ -246,17 +257,9 @@ def ready(): return until(f"current native grant and writer in {namespace}", ready) def audit(self, namespace=None): - raw = command("docker", "exec", "bridge-native-control-plane", - "cat", "/var/log/kars-native-audit/audit.log") - return [ - event for line in raw.splitlines() if line - for event in [json.loads(line)] - if event.get("stage") == "ResponseComplete" - and event.get("user", {}).get("username") == f"system:serviceaccount:{BRIDGE}:{WRITER}" - and (namespace is None or event.get("objectRef", {}).get("namespace") == namespace) - ] + from audit_evidence import read + return read(namespace) def audit_barrier(self, actor, namespace): - actor.get(resource(namespace, "karscredentialgrants", "workspace")) - time.sleep(1) - return self.audit(namespace) + from audit_evidence import barrier + return barrier(self, actor, namespace) diff --git a/bridge/tests/native-credentials/test_audit_evidence.py b/bridge/tests/native-credentials/test_audit_evidence.py new file mode 100644 index 00000000..a6c9618e --- /dev/null +++ b/bridge/tests/native-credentials/test_audit_evidence.py @@ -0,0 +1,115 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import copy +import json +import ssl +from types import SimpleNamespace +import unittest +from unittest.mock import Mock, patch + +import audit_evidence as audit +from native_api import Api, CommandFailure, Failure + + +def identifier(number): + return f"00000000-0000-4000-8000-{number:012d}" + + +def event(number, verb="get", resource="karscredentialgrants", code=200): + return {"auditID": identifier(number), "stage": "ResponseComplete", "verb": verb, + "user": {"username": f"system:serviceaccount:{audit.BRIDGE}:{audit.WRITER}"}, + "objectRef": {"namespace": "work", "resource": resource, "name": "workspace"}, + "responseStatus": {"code": code}} + + +class AuditEvidenceTests(unittest.TestCase): + def test_retained_rotation_file_is_read_and_duplicate_snapshot_records_are_not_double_counted(self): + old = audit.DIRECTORY + "/audit-2026-09-16T10-30-00.001.log" + active = audit.DIRECTORY + "/audit.log" + created = event(1, "create", "secrets", 201) + raw = "\n".join(json.dumps(value) for value in [created, created, event(2)]) + with patch.object(audit, "paths", return_value=[old, active]), \ + patch.object(audit, "command", return_value=raw) as command: + values = audit.read("work") + self.assertEqual(values, [created, event(2)]) + command.assert_called_once_with("docker", "exec", audit.CONTROL_PLANE, + "cat", old, active, timeout=30) + + def test_changed_rotation_inventory_retries_instead_of_returning_partial_coverage(self): + active = audit.DIRECTORY + "/audit.log" + first = [audit.DIRECTORY + "/audit-2026-09-16T10-30-00.001.log", active] + second = [audit.DIRECTORY + "/audit-2026-09-16T10-31-00.001.log", active] + with patch.object(audit, "paths", side_effect=[first, second, second, second]), \ + patch.object(audit, "command", side_effect=[json.dumps(event(1)), json.dumps(event(2))]): + self.assertEqual(audit.read("work"), [event(2)]) + + def test_distinct_creates_are_retained_and_conflicting_duplicate_ids_are_refused(self): + one, two = event(1, "create", "secrets", 201), event(2, "create", "secrets", 201) + self.assertEqual(len(audit.parse_events(json.dumps(one) + "\n" + json.dumps(two), "work")), 2) + bad = copy.deepcopy(one) + bad["responseStatus"]["code"] = 403 + with self.assertRaisesRegex(Failure, "conflicting"): + audit.parse_events(json.dumps(one) + "\n" + json.dumps(bad), "work") + + def test_scope_filtering_and_bounded_inventory_fail_closed(self): + other = event(1) + other["objectRef"]["namespace"] = "other" + self.assertEqual(audit.parse_events(json.dumps(other), "work"), []) + with patch.object(audit, "MAX_BYTES", 1), self.assertRaises(Failure): + audit.parse_events(json.dumps(event(1)), "work") + for paths in ("", audit.DIRECTORY + "/audit-private.log", "/elsewhere/audit.log"): + with patch.object(audit, "command", return_value=paths), self.assertRaises(Failure): + audit.paths() + with patch.object(audit, "command", side_effect=CommandFailure("docker", 1, "private")), \ + self.assertRaisesRegex(Failure, "did not settle"): + audit.read("work") + + def test_barrier_waits_for_its_exact_successful_response_complete_event(self): + marker = identifier(3) + actor = SimpleNamespace(audit_marker=Mock(return_value=marker)) + setup = SimpleNamespace(audit=Mock(side_effect=[[], [event(2), event(3)]])) + + def wait(description, check, timeout): + self.assertEqual(timeout, 30) + self.assertIsNone(check()) + return check() + + with patch.object(audit, "until", side_effect=wait): + result = audit.barrier(setup, actor, "work") + self.assertIsInstance(result, audit.AuditSnapshot) + self.assertEqual(result.marker, marker) + self.assertEqual(len(result), 2) + + def test_barrier_rejects_wrong_response_and_interval_requires_retained_start(self): + actor = SimpleNamespace(audit_marker=lambda path: identifier(1)) + setup = SimpleNamespace(audit=lambda namespace: [event(1, code=403)]) + with patch.object(audit, "until", side_effect=lambda description, check, timeout: check()), \ + self.assertRaisesRegex(Failure, "barrier"): + audit.barrier(setup, actor, "work") + before = audit.AuditSnapshot([event(1)], identifier(1)) + after = audit.AuditSnapshot([event(1), event(2), event(3)], identifier(3)) + self.assertEqual(audit.changes(before, after), [event(2), event(3)]) + with self.assertRaisesRegex(Failure, "starting barrier"): + audit.changes(before, audit.AuditSnapshot([event(3)], identifier(3))) + with self.assertRaisesRegex(Failure, "distinct"): + audit.changes(before, before) + + def test_actual_api_client_reads_the_server_audit_header_without_changing_its_return_contract(self): + response = Mock(status=200) + response.read.return_value = b'{"metadata":{"name":"workspace"}}' + response.getheader.return_value = identifier(7) + connection = Mock() + connection.getresponse.return_value = response + with patch("native_api.http.client.HTTPSConnection", return_value=connection): + api = Api("https://127.0.0.1:6443", ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)) + self.assertEqual(api.audit_marker("/fixture"), identifier(7)) + self.assertEqual(api.get("/fixture"), {"metadata": {"name": "workspace"}}) + response.getheader.return_value = "private-invalid-audit-header" + with self.assertRaisesRegex(Failure, "audit request identity") as failure: + api.audit_marker("/fixture") + self.assertNotIn("private-invalid", str(failure.exception)) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/e2e/budget-api-kubectl.mjs b/tests/e2e/budget-api-kubectl.mjs index 5efdb9e5..c607cef9 100644 --- a/tests/e2e/budget-api-kubectl.mjs +++ b/tests/e2e/budget-api-kubectl.mjs @@ -7,6 +7,20 @@ import { fileURLToPath } from "node:url"; const root = fileURLToPath(new URL("../../", import.meta.url)); export const context = "kind-kars-budget-api"; +class BudgetApiCommandFailure extends Error { + constructor(error) { + super("Disposable budget API assertion command failed", { cause: undefined }); + const message = String(error.stderr ?? ""); + this.budgetTokenPolicyDenied = error.status === 1 + && /Error from server \(Forbidden\):/.test(message) + && /ValidatingAdmissionPolicy ['"]kars-inference-budget-token['"] with binding ['"]kars-inference-budget-token['"] denied request:/.test(message); + } +} + +export function isBudgetTokenPolicyDenial(error) { + return error instanceof BudgetApiCommandFailure && error.budgetTokenPolicyDenied; +} + export function kubectl(args, input, publicSchema = false) { try { return execFileSync("kubectl", ["--context", context, "--request-timeout=20s", ...args], { @@ -18,6 +32,6 @@ export function kubectl(args, input, publicSchema = false) { // Only public CRD/VAP creation and CRD readiness opt in, never Secret/token commands. console.error(String(error.stderr ?? "").slice(0, 12_000)); } - throw new Error("Disposable budget API assertion command failed", { cause: undefined }); + throw new BudgetApiCommandFailure(error); } } diff --git a/tests/e2e/budget-api-kubectl.test.mjs b/tests/e2e/budget-api-kubectl.test.mjs index e8b762f2..c2cf8b75 100644 --- a/tests/e2e/budget-api-kubectl.test.mjs +++ b/tests/e2e/budget-api-kubectl.test.mjs @@ -6,7 +6,7 @@ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; -import { context, kubectl } from "./budget-api-kubectl.mjs"; +import { context, kubectl, isBudgetTokenPolicyDenial } from "./budget-api-kubectl.mjs"; function fixture(t, { stderr = "", stdout = "", status = 0 } = {}) { const directory = mkdtempSync(join(tmpdir(), "kars-budget-command-")); @@ -71,10 +71,47 @@ test("successful public and private commands preserve their output without diagn assert.deepEqual(state.errors, []); }); +test("private audience denial requires the exact policy and binding without exposing error contents", (t) => { + const marker = "do-not-publish-token-material"; + const stderr = "Error from server (Forbidden): serviceaccounts is forbidden: " + + "ValidatingAdmissionPolicy 'kars-inference-budget-token' with binding " + + `'kars-inference-budget-token' denied request: ${marker}`; + const state = fixture(t, { stderr, status: 1 }); + assert.throws(() => kubectl(["create", "--raw", "/fixture/token"], { private: marker }), (error) => { + commandFailed(error); + assert.equal(isBudgetTokenPolicyDenial(error), true); + assert(!JSON.stringify(error).includes(marker)); + assert(!error.stack.includes(marker)); + return true; + }); + assert.deepEqual(state.errors, []); +}); + +for (const stderr of [ + 'Error from server (Forbidden): User "untrusted" cannot create resource "serviceaccounts/token"', + "Error from server (Forbidden): ValidatingAdmissionPolicy 'another-policy' with binding 'kars-inference-budget-token' denied request:", + "Error from server (Forbidden): ValidatingAdmissionPolicy 'kars-inference-budget-token' with binding 'another-binding' denied request:", + "Error from server (Invalid): ValidatingAdmissionPolicy 'kars-inference-budget-token' with binding 'kars-inference-budget-token' denied request:", + "Unable to connect to the server: connection refused", +]) { + test(`non-policy failure never qualifies private-audience denial: ${stderr}`, (t) => { + const state = fixture(t, { stderr, status: 1 }); + assert.throws(() => kubectl(["create", "--raw", "/fixture/token"], {}), (error) => { + commandFailed(error); + assert.equal(isBudgetTokenPolicyDenial(error), false); + return true; + }); + assert.deepEqual(state.errors, []); + }); +} + test("the actual preflight opts only its public CRD wait into schema diagnostics", () => { const source = readFileSync(new URL("./inference-budget-api.mjs", import.meta.url), "utf8"); assert.equal(context, "kind-kars-budget-api"); - assert.ok(source.includes('import { context, kubectl } from "./budget-api-kubectl.mjs";')); + assert.ok(source.includes('import { context, kubectl, isBudgetTokenPolicyDenial } from "./budget-api-kubectl.mjs";')); assert.ok(source.includes("root, context, kubectl, until, namespace, controller, principal,")); assert.ok(source.includes('kubectl(["wait", "--for=condition=Established", `crd/${definition.metadata.name}`, "--timeout=60s"], undefined, true);')); + assert(source.indexOf("kind: \"SelfSubjectAccessReview\"") < source.indexOf("const ordinaryToken =")); + assert(source.indexOf("const ordinaryToken =") < source.indexOf("assert.throws(() => kubectl(tokenArgs, tokenRequest)")); + assert.ok(source.includes("isBudgetTokenPolicyDenial,")); }); diff --git a/tests/e2e/inference-budget-api.mjs b/tests/e2e/inference-budget-api.mjs index 31b36469..4c856fd2 100644 --- a/tests/e2e/inference-budget-api.mjs +++ b/tests/e2e/inference-budget-api.mjs @@ -9,7 +9,7 @@ import { readFileSync } from "node:fs"; import { createRequire } from "node:module"; import { fileURLToPath } from "node:url"; import { runWorkloadProof } from "./budget-workload-cases.mjs"; -import { context, kubectl } from "./budget-api-kubectl.mjs"; +import { context, kubectl, isBudgetTokenPolicyDenial } from "./budget-api-kubectl.mjs"; const require = createRequire(new URL("../../cli/package.json", import.meta.url)); const { parseAllDocuments } = require("yaml"); @@ -128,8 +128,22 @@ assert.throws(() => kubectl(["replace", "-f", "-"], changedScope)); const tokenRequest = { apiVersion: "authentication.k8s.io/v1", kind: "TokenRequest", spec: { audiences: [audience], expirationSeconds: 600 } }; -assert.throws(() => kubectl(["create", "--raw", - `/api/v1/namespaces/${namespace}/serviceaccounts/untrusted/token`, "-f", "-", "--as", principal], tokenRequest)); +await until(() => { + const review = create({ apiVersion: "authorization.k8s.io/v1", kind: "SelfSubjectAccessReview", + spec: { resourceAttributes: { namespace, verb: "create", group: "", version: "v1", + resource: "serviceaccounts", subresource: "token", name: "untrusted" } } }, principal); + assert(!review.status?.evaluationError, "Fixture TokenRequest authorization evaluator failed"); + return review.status?.allowed === true; +}, "fixture principal is actually authorized for TokenRequest"); +const tokenArgs = ["create", "--raw", + `/api/v1/namespaces/${namespace}/serviceaccounts/untrusted/token`, "-f", "-", "--as", principal]; +const ordinaryAudience = structuredClone(tokenRequest); +ordinaryAudience.spec.audiences = ["kars.azure.com/budget-fixture-public"]; +const ordinaryToken = JSON.parse(kubectl(tokenArgs, ordinaryAudience)); +assert(typeof ordinaryToken.status?.token === "string" && ordinaryToken.status.token.length > 0, + "Same principal must be able to request an ordinary audience before testing private admission"); +assert.throws(() => kubectl(tokenArgs, tokenRequest), isBudgetTokenPolicyDenial, + "The private audience must be rejected by its exact admission policy, not RBAC or a transport failure"); const projection = { apiVersion: "v1", kind: "ConfigMap", metadata: { name: "kars-inference-budget-ca", namespace }, data: { "ca.crt": "public-test-only" } }; From 8512b50b4d5b565673e8d7c64eebcc92cbbf93f7 Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 17:36:32 +0200 Subject: [PATCH 03/13] test: match native admission reasons and retry audit rotation gaps Preserve the production policy default and classify its exact Invalid response. Treat only a missing active audit file during rotation as a bounded retry. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- bridge/tests/native-credentials/audit_evidence.py | 11 ++++++++--- .../tests/native-credentials/test_audit_evidence.py | 12 ++++++++++++ tests/e2e/budget-api-kubectl.mjs | 4 ++-- tests/e2e/budget-api-kubectl.test.mjs | 12 +++++++----- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/bridge/tests/native-credentials/audit_evidence.py b/bridge/tests/native-credentials/audit_evidence.py index a0141261..5068bdd6 100644 --- a/bridge/tests/native-credentials/audit_evidence.py +++ b/bridge/tests/native-credentials/audit_evidence.py @@ -21,15 +21,20 @@ def __init__(self, events, marker): self.marker = marker +class UnsettledInventory(Failure): + """The active log is between its rotation rename and recreation.""" + + def paths(): names = command("docker", "exec", CONTROL_PLANE, "find", DIRECTORY, "-maxdepth", "1", "-type", "f", "-name", "audit*.log", timeout=30).splitlines() - require(1 <= len(names) <= 3 and len(set(names)) == len(names) - and DIRECTORY + "/audit.log" in names + require(len(names) <= 3 and len(set(names)) == len(names) and all(name.startswith(DIRECTORY + "/") and NAME.fullmatch(name[len(DIRECTORY) + 1:]) for name in names), "Native audit file inventory is unavailable or outside its bounded scope") + if DIRECTORY + "/audit.log" not in names: + raise UnsettledInventory("Native audit rotation has not published its active file") return sorted(names) @@ -63,7 +68,7 @@ def read(namespace=None): if before != paths(): continue return parse_events(raw, namespace) - except (CommandFailure, json.JSONDecodeError): + except (CommandFailure, json.JSONDecodeError, UnsettledInventory): # Rotation can retire a file between inventory and open. continue raise Failure("Native audit snapshot did not settle; no complete event proof is available") diff --git a/bridge/tests/native-credentials/test_audit_evidence.py b/bridge/tests/native-credentials/test_audit_evidence.py index a6c9618e..cda4918d 100644 --- a/bridge/tests/native-credentials/test_audit_evidence.py +++ b/bridge/tests/native-credentials/test_audit_evidence.py @@ -44,6 +44,18 @@ def test_changed_rotation_inventory_retries_instead_of_returning_partial_coverag patch.object(audit, "command", side_effect=[json.dumps(event(1)), json.dumps(event(2))]): self.assertEqual(audit.read("work"), [event(2)]) + def test_rename_recreate_gap_retries_without_relaxing_path_validation(self): + old = audit.DIRECTORY + "/audit-2026-09-16T10-30-00.001.log" + healthy = old + "\n" + audit.DIRECTORY + "/audit.log" + with patch.object(audit, "command", side_effect=[ + old, healthy, json.dumps(event(1)), healthy, + ]) as command: + self.assertEqual(audit.read("work"), [event(1)]) + self.assertEqual(command.call_count, 4) + with patch.object(audit, "command", return_value=old), \ + self.assertRaisesRegex(Failure, "did not settle"): + audit.read("work") + def test_distinct_creates_are_retained_and_conflicting_duplicate_ids_are_refused(self): one, two = event(1, "create", "secrets", 201), event(2, "create", "secrets", 201) self.assertEqual(len(audit.parse_events(json.dumps(one) + "\n" + json.dumps(two), "work")), 2) diff --git a/tests/e2e/budget-api-kubectl.mjs b/tests/e2e/budget-api-kubectl.mjs index c607cef9..6c36ab46 100644 --- a/tests/e2e/budget-api-kubectl.mjs +++ b/tests/e2e/budget-api-kubectl.mjs @@ -12,8 +12,8 @@ class BudgetApiCommandFailure extends Error { super("Disposable budget API assertion command failed", { cause: undefined }); const message = String(error.stderr ?? ""); this.budgetTokenPolicyDenied = error.status === 1 - && /Error from server \(Forbidden\):/.test(message) - && /ValidatingAdmissionPolicy ['"]kars-inference-budget-token['"] with binding ['"]kars-inference-budget-token['"] denied request:/.test(message); + && /(?:^|\n)The serviceaccounts ["']untrusted["'] is invalid:/.test(message) + && /ValidatingAdmissionPolicy ['"]kars-inference-budget-token['"] with binding ['"]kars-inference-budget-token['"] denied request: Only kubelet node identities may obtain a Pod-bound governed-inference audience token(?:$|[\s"])/.test(message); } } diff --git a/tests/e2e/budget-api-kubectl.test.mjs b/tests/e2e/budget-api-kubectl.test.mjs index c2cf8b75..ecf32358 100644 --- a/tests/e2e/budget-api-kubectl.test.mjs +++ b/tests/e2e/budget-api-kubectl.test.mjs @@ -73,9 +73,10 @@ test("successful public and private commands preserve their output without diagn test("private audience denial requires the exact policy and binding without exposing error contents", (t) => { const marker = "do-not-publish-token-material"; - const stderr = "Error from server (Forbidden): serviceaccounts is forbidden: " + const stderr = 'The serviceaccounts "untrusted" is invalid: : Invalid value: "": ' + "ValidatingAdmissionPolicy 'kars-inference-budget-token' with binding " - + `'kars-inference-budget-token' denied request: ${marker}`; + + "'kars-inference-budget-token' denied request: " + + `Only kubelet node identities may obtain a Pod-bound governed-inference audience token\n${marker}`; const state = fixture(t, { stderr, status: 1 }); assert.throws(() => kubectl(["create", "--raw", "/fixture/token"], { private: marker }), (error) => { commandFailed(error); @@ -89,9 +90,10 @@ test("private audience denial requires the exact policy and binding without expo for (const stderr of [ 'Error from server (Forbidden): User "untrusted" cannot create resource "serviceaccounts/token"', - "Error from server (Forbidden): ValidatingAdmissionPolicy 'another-policy' with binding 'kars-inference-budget-token' denied request:", - "Error from server (Forbidden): ValidatingAdmissionPolicy 'kars-inference-budget-token' with binding 'another-binding' denied request:", - "Error from server (Invalid): ValidatingAdmissionPolicy 'kars-inference-budget-token' with binding 'kars-inference-budget-token' denied request:", + 'The serviceaccounts "untrusted" is invalid: ValidatingAdmissionPolicy \'another-policy\' with binding \'kars-inference-budget-token\' denied request: Only kubelet node identities may obtain a Pod-bound governed-inference audience token', + 'The serviceaccounts "untrusted" is invalid: ValidatingAdmissionPolicy \'kars-inference-budget-token\' with binding \'another-binding\' denied request: Only kubelet node identities may obtain a Pod-bound governed-inference audience token', + 'The serviceaccounts "untrusted" is invalid: ValidatingAdmissionPolicy \'kars-inference-budget-token\' with binding \'kars-inference-budget-token\' denied request: expression resulted in an evaluation error', + "Error from server (Forbidden): ValidatingAdmissionPolicy 'kars-inference-budget-token' with binding 'kars-inference-budget-token' denied request: Only kubelet node identities may obtain a Pod-bound governed-inference audience token", "Unable to connect to the server: connection refused", ]) { test(`non-policy failure never qualifies private-audience denial: ${stderr}`, (t) => { From e868751bd38d22f50023aecee702cc262f2980ce Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 18:47:59 +0200 Subject: [PATCH 04/13] test: retain bounded synthetic authorization-review diagnostics Expose only the non-secret fixture review failure; preserve private TokenRequest and Secret redaction and all admission requirements. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- tests/e2e/budget-api-kubectl.mjs | 2 +- tests/e2e/budget-api-kubectl.test.mjs | 11 +++++++++++ tests/e2e/inference-budget-api.mjs | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/e2e/budget-api-kubectl.mjs b/tests/e2e/budget-api-kubectl.mjs index 6c36ab46..a5dd3643 100644 --- a/tests/e2e/budget-api-kubectl.mjs +++ b/tests/e2e/budget-api-kubectl.mjs @@ -29,7 +29,7 @@ export function kubectl(args, input, publicSchema = false) { }); } catch (error) { if (publicSchema) { - // Only public CRD/VAP creation and CRD readiness opt in, never Secret/token commands. + // Public schemas/readiness and synthetic authorization reviews only, never Secret/token commands. console.error(String(error.stderr ?? "").slice(0, 12_000)); } throw new BudgetApiCommandFailure(error); diff --git a/tests/e2e/budget-api-kubectl.test.mjs b/tests/e2e/budget-api-kubectl.test.mjs index ecf32358..6ff2462f 100644 --- a/tests/e2e/budget-api-kubectl.test.mjs +++ b/tests/e2e/budget-api-kubectl.test.mjs @@ -61,6 +61,17 @@ test("Secret and TokenRequest failures never expose input, stderr or an underlyi assert.deepEqual(state.errors, []); }); +test("synthetic authorization review can expose bounded public diagnostics without token bodies", (t) => { + const diagnostic = "Error from server (Forbidden): synthetic fixture permission review rejected"; + const state = fixture(t, { stderr: diagnostic, status: 1 }); + const review = { apiVersion: "authorization.k8s.io/v1", kind: "SelfSubjectAccessReview", + spec: { resourceAttributes: { namespace: "budget-api-fixture", verb: "create", + resource: "serviceaccounts", subresource: "token", name: "untrusted" } } }; + assert.throws(() => kubectl(["create", "-f", "-"], review, true), commandFailed); + assert.deepEqual(state.errors, [diagnostic]); + assert(!state.request().input.includes("audiences")); +}); + test("successful public and private commands preserve their output without diagnostic logging", (t) => { const output = '{"metadata":{"uid":"fixture-uid"}}\n'; const state = fixture(t, { stdout: output }); diff --git a/tests/e2e/inference-budget-api.mjs b/tests/e2e/inference-budget-api.mjs index 4c856fd2..ab08b341 100644 --- a/tests/e2e/inference-budget-api.mjs +++ b/tests/e2e/inference-budget-api.mjs @@ -131,7 +131,7 @@ const tokenRequest = { apiVersion: "authentication.k8s.io/v1", kind: "TokenReque await until(() => { const review = create({ apiVersion: "authorization.k8s.io/v1", kind: "SelfSubjectAccessReview", spec: { resourceAttributes: { namespace, verb: "create", group: "", version: "v1", - resource: "serviceaccounts", subresource: "token", name: "untrusted" } } }, principal); + resource: "serviceaccounts", subresource: "token", name: "untrusted" } } }, principal, true); assert(!review.status?.evaluationError, "Fixture TokenRequest authorization evaluator failed"); return review.status?.allowed === true; }, "fixture principal is actually authorized for TokenRequest"); From a2712056af3f8b402149466b60ee29a634aa20a1 Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 18:57:17 +0200 Subject: [PATCH 05/13] test: post built-in budget permission review directly to the API Avoid kubectl CRD discovery under the intentionally restricted fixture identity. Keep server validation, exact impersonation, and all private-audience denial checks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- tests/e2e/budget-api-kubectl.test.mjs | 44 +++++++++++++++++++++++++++ tests/e2e/inference-budget-api.mjs | 6 ++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/tests/e2e/budget-api-kubectl.test.mjs b/tests/e2e/budget-api-kubectl.test.mjs index 6ff2462f..eef00cc7 100644 --- a/tests/e2e/budget-api-kubectl.test.mjs +++ b/tests/e2e/budget-api-kubectl.test.mjs @@ -2,7 +2,9 @@ // Licensed under the MIT License. import assert from "node:assert/strict"; +import { execFile } from "node:child_process"; import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { createServer } from "node:http"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; @@ -82,6 +84,46 @@ test("successful public and private commands preserve their output without diagn assert.deepEqual(state.errors, []); }); +test("real kubectl sends the built-in permission review without CRD discovery or relaxed validation", { timeout: 20_000 }, async (t) => { + const directory = mkdtempSync(join(tmpdir(), "kars-budget-raw-review-")); + t.after(() => rmSync(directory, { recursive: true, force: true })); + const path = "/apis/authorization.k8s.io/v1/selfsubjectaccessreviews"; + const principal = "system:serviceaccount:budget-api-fixture:untrusted"; + const review = { apiVersion: "authorization.k8s.io/v1", kind: "SelfSubjectAccessReview", + spec: { resourceAttributes: { namespace: "budget-api-fixture", verb: "create", + group: "", version: "v1", resource: "serviceaccounts", subresource: "token", name: "untrusted" } } }; + const requests = []; + const server = createServer(async (req, res) => { + let body = ""; + for await (const chunk of req) body += chunk; + requests.push({ method: req.method, path: new URL(req.url, "http://localhost").pathname, + actor: req.headers["impersonate-user"], body }); + res.setHeader("Content-Type", "application/json"); + if (req.method !== "POST" || new URL(req.url, "http://localhost").pathname !== path) { + res.writeHead(403); + res.end(JSON.stringify({ kind: "Status", status: "Failure", reason: "Forbidden", code: 403 })); + return; + } + res.end(JSON.stringify({ ...review, status: { allowed: true } })); + }); + await new Promise(resolve => server.listen(0, "127.0.0.1", resolve)); + t.after(() => new Promise(resolve => server.close(resolve))); + const config = join(directory, "config.json"); + writeFileSync(config, JSON.stringify({ apiVersion: "v1", kind: "Config", + clusters: [{ name: "fixture", cluster: { server: `http://127.0.0.1:${server.address().port}` } }], + users: [{ name: "fixture", user: {} }], + contexts: [{ name: context, context: { cluster: "fixture", user: "fixture" } }], + "current-context": context }), { mode: 0o600 }); + const output = await new Promise((resolve, reject) => { + const child = execFile("kubectl", ["--kubeconfig", config, "--context", context, + "--request-timeout=5s", "create", "--raw", path, "-f", "-", "--as", principal], + { encoding: "utf8", timeout: 10_000 }, (error, stdout) => error ? reject(error) : resolve(stdout)); + child.stdin.end(JSON.stringify(review)); + }); + assert.equal(JSON.parse(output).status.allowed, true); + assert.deepEqual(requests, [{ method: "POST", path, actor: principal, body: JSON.stringify(review) }]); +}); + test("private audience denial requires the exact policy and binding without exposing error contents", (t) => { const marker = "do-not-publish-token-material"; const stderr = 'The serviceaccounts "untrusted" is invalid: : Invalid value: "": ' @@ -125,6 +167,8 @@ test("the actual preflight opts only its public CRD wait into schema diagnostics assert.ok(source.includes("root, context, kubectl, until, namespace, controller, principal,")); assert.ok(source.includes('kubectl(["wait", "--for=condition=Established", `crd/${definition.metadata.name}`, "--timeout=60s"], undefined, true);')); assert(source.indexOf("kind: \"SelfSubjectAccessReview\"") < source.indexOf("const ordinaryToken =")); + assert.ok(source.includes('"/apis/authorization.k8s.io/v1/selfsubjectaccessreviews", "-f", "-", "--as", principal]')); + assert(!source.includes("--validate=false")); assert(source.indexOf("const ordinaryToken =") < source.indexOf("assert.throws(() => kubectl(tokenArgs, tokenRequest)")); assert.ok(source.includes("isBudgetTokenPolicyDenial,")); }); diff --git a/tests/e2e/inference-budget-api.mjs b/tests/e2e/inference-budget-api.mjs index ab08b341..2c1b1f36 100644 --- a/tests/e2e/inference-budget-api.mjs +++ b/tests/e2e/inference-budget-api.mjs @@ -129,9 +129,11 @@ assert.throws(() => kubectl(["replace", "-f", "-"], changedScope)); const tokenRequest = { apiVersion: "authentication.k8s.io/v1", kind: "TokenRequest", spec: { audiences: [audience], expirationSeconds: 600 } }; await until(() => { - const review = create({ apiVersion: "authorization.k8s.io/v1", kind: "SelfSubjectAccessReview", + const review = JSON.parse(kubectl(["create", "--raw", + "/apis/authorization.k8s.io/v1/selfsubjectaccessreviews", "-f", "-", "--as", principal], + { apiVersion: "authorization.k8s.io/v1", kind: "SelfSubjectAccessReview", spec: { resourceAttributes: { namespace, verb: "create", group: "", version: "v1", - resource: "serviceaccounts", subresource: "token", name: "untrusted" } } }, principal, true); + resource: "serviceaccounts", subresource: "token", name: "untrusted" } } }, true)); assert(!review.status?.evaluationError, "Fixture TokenRequest authorization evaluator failed"); return review.status?.allowed === true; }, "fixture principal is actually authorized for TokenRequest"); From f7cc7df8ef1cdfce9d4d92159a4e0ade5153bc1f Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 19:42:33 +0200 Subject: [PATCH 06/13] build(bridge): add reproducible patched Dex distroless qualification Pin stable upstream source, verified Go-generated dependency locks and disclosed compatibility patches. Require real OIDC/SQLite, signing continuity, native linkage, preserved attribution and full final-image vulnerability checks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- .github/workflows/bridge-ci.yml | 175 +- NOTICE | 14 + bridge/idp/.dockerignore | 18 + bridge/idp/Dockerfile | 67 + bridge/idp/Dockerfile.locks | 29 + bridge/idp/LICENSE | 21 + bridge/idp/NOTICE | 40 + bridge/idp/README.md | 367 +++ bridge/idp/locks/generated/SHA256SUMS | 15 + bridge/idp/locks/generated/api-modules.json | 421 ++++ bridge/idp/locks/generated/api/v2/go.mod | 17 + bridge/idp/locks/generated/api/v2/go.sum | 64 + bridge/idp/locks/generated/dependencies.patch | 528 +++++ bridge/idp/locks/generated/go.mod | 131 ++ bridge/idp/locks/generated/go.sum | 390 ++++ bridge/idp/locks/generated/graph.txt | 840 +++++++ bridge/idp/locks/generated/inputs.lock | 6 + bridge/idp/locks/generated/modules.json | 2028 +++++++++++++++++ bridge/idp/locks/generated/requests.txt | 10 + bridge/idp/locks/generated/toolchain.txt | 1 + .../locks/generated/upstream/api/v2/go.mod | 15 + .../locks/generated/upstream/api/v2/go.sum | 38 + bridge/idp/locks/generated/upstream/go.mod | 129 ++ bridge/idp/locks/generated/upstream/go.sum | 339 +++ bridge/idp/locks/inputs.lock | 6 + bridge/idp/locks/requests.txt | 10 + ...001-literal-oauth-error-descriptions.patch | 26 + .../0002-saml-fixture-validation-clock.patch | 39 + bridge/idp/patches/SHA256SUMS | 7 + bridge/idp/patches/patched.sha256 | 4 + bridge/idp/patches/saml_compat_test.go | 50 + bridge/idp/patches/series | 2 + bridge/idp/patches/server_compat_test.go | 62 + bridge/idp/patches/upstream.sha256 | 2 + bridge/idp/scripts/apply-source-patches.sh | 32 + bridge/idp/scripts/build.sh | 32 + bridge/idp/scripts/fetch-source.sh | 17 + bridge/idp/scripts/generate-locks.sh | 59 + bridge/idp/scripts/import-locks.py | 85 + bridge/idp/scripts/notices.go | 123 + bridge/idp/scripts/source-inventory.sh | 9 + bridge/idp/scripts/upstream-tests.sh | 14 + bridge/idp/scripts/verify-locks.sh | 29 + bridge/idp/tests/contracts.py | 135 ++ bridge/idp/tests/probe.go | 532 +++++ bridge/idp/tests/probe_test.go | 256 +++ bridge/idp/tests/qualify.py | 173 ++ bridge/idp/tests/test_contracts.py | 149 ++ bridge/idp/tests/test_patches.py | 193 ++ ci/bridge_component_results.py | 2 +- ci/copyright-coverage.json | 130 ++ ci/copyright_headers.py | 2 +- ci/tests/bridge_contracts_test.py | 109 +- ci/tests/copyright_headers_test.py | 26 +- 54 files changed, 8011 insertions(+), 7 deletions(-) create mode 100644 bridge/idp/.dockerignore create mode 100644 bridge/idp/Dockerfile create mode 100644 bridge/idp/Dockerfile.locks create mode 100644 bridge/idp/LICENSE create mode 100644 bridge/idp/NOTICE create mode 100644 bridge/idp/README.md create mode 100644 bridge/idp/locks/generated/SHA256SUMS create mode 100644 bridge/idp/locks/generated/api-modules.json create mode 100644 bridge/idp/locks/generated/api/v2/go.mod create mode 100644 bridge/idp/locks/generated/api/v2/go.sum create mode 100644 bridge/idp/locks/generated/dependencies.patch create mode 100644 bridge/idp/locks/generated/go.mod create mode 100644 bridge/idp/locks/generated/go.sum create mode 100644 bridge/idp/locks/generated/graph.txt create mode 100644 bridge/idp/locks/generated/inputs.lock create mode 100644 bridge/idp/locks/generated/modules.json create mode 100644 bridge/idp/locks/generated/requests.txt create mode 100644 bridge/idp/locks/generated/toolchain.txt create mode 100644 bridge/idp/locks/generated/upstream/api/v2/go.mod create mode 100644 bridge/idp/locks/generated/upstream/api/v2/go.sum create mode 100644 bridge/idp/locks/generated/upstream/go.mod create mode 100644 bridge/idp/locks/generated/upstream/go.sum create mode 100644 bridge/idp/locks/inputs.lock create mode 100644 bridge/idp/locks/requests.txt create mode 100644 bridge/idp/patches/0001-literal-oauth-error-descriptions.patch create mode 100644 bridge/idp/patches/0002-saml-fixture-validation-clock.patch create mode 100644 bridge/idp/patches/SHA256SUMS create mode 100644 bridge/idp/patches/patched.sha256 create mode 100644 bridge/idp/patches/saml_compat_test.go create mode 100644 bridge/idp/patches/series create mode 100644 bridge/idp/patches/server_compat_test.go create mode 100644 bridge/idp/patches/upstream.sha256 create mode 100644 bridge/idp/scripts/apply-source-patches.sh create mode 100644 bridge/idp/scripts/build.sh create mode 100644 bridge/idp/scripts/fetch-source.sh create mode 100644 bridge/idp/scripts/generate-locks.sh create mode 100644 bridge/idp/scripts/import-locks.py create mode 100644 bridge/idp/scripts/notices.go create mode 100644 bridge/idp/scripts/source-inventory.sh create mode 100644 bridge/idp/scripts/upstream-tests.sh create mode 100644 bridge/idp/scripts/verify-locks.sh create mode 100644 bridge/idp/tests/contracts.py create mode 100644 bridge/idp/tests/probe.go create mode 100644 bridge/idp/tests/probe_test.go create mode 100644 bridge/idp/tests/qualify.py create mode 100644 bridge/idp/tests/test_contracts.py create mode 100644 bridge/idp/tests/test_patches.py diff --git a/.github/workflows/bridge-ci.yml b/.github/workflows/bridge-ci.yml index 36137e19..01990571 100644 --- a/.github/workflows/bridge-ci.yml +++ b/.github/workflows/bridge-ci.yml @@ -20,7 +20,7 @@ concurrency: jobs: bridge-required-gates: name: Bridge component acceptance - needs: [addon, bff, dependencies, lockfiles, rust-dependencies, secrets, security, web] + needs: [addon, bff, dependencies, idp, lockfiles, rust-dependencies, secrets, security, web] if: always() runs-on: ubuntu-22.04 env: @@ -222,6 +222,179 @@ jobs: docker rm --force "$WEB_CONTAINER_ID" fi + idp: + name: Dex IdP runtime qualification + runs-on: ubuntu-24.04 + timeout-minutes: 60 + permissions: + contents: read + env: + PYTHONDONTWRITEBYTECODE: '1' + IDP_EVIDENCE_DIR: ${{ runner.temp }}/bridge-idp-evidence + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Initialize native Dex qualification evidence + run: | + set -euo pipefail + mkdir -p "$IDP_EVIDENCE_DIR" + printf 'commit=%s\nrun_id=%s\nrun_attempt=%s\n' \ + "$GITHUB_SHA" "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" \ + > "$IDP_EVIDENCE_DIR/provenance.txt" + test "$(uname -m)" = x86_64 + docker info --format '{{.OSType}}/{{.Architecture}}' \ + | tee "$IDP_EVIDENCE_DIR/docker-platform.txt" + df -h "$RUNNER_TEMP" | tee "$IDP_EVIDENCE_DIR/disk-before.txt" + - name: Check Dex source contracts and actual reviewed module locks + id: idp_source + run: | + set -euo pipefail + KARS_DEX_PATCH_NETWORK=1 python3 -m unittest discover \ + -s bridge/idp/tests -p 'test_*.py' \ + 2>&1 | tee "$IDP_EVIDENCE_DIR/source-contracts.log" + PYTHONPATH=bridge/idp/tests python3 -c \ + 'from contracts import check_modules; check_modules("bridge/idp"); print("Reviewed Go module locks verified")' \ + 2>&1 | tee "$IDP_EVIDENCE_DIR/module-locks.log" + PYTHONPATH=ci/tests python3 -m unittest bridge_contracts_test.ContractAggregateTests \ + 2>&1 | tee "$IDP_EVIDENCE_DIR/component-aggregate-contracts.log" + git diff --exit-code -- bridge/idp/locks + - name: Build and run upstream Dex root and API race suites + id: idp_upstream + run: | + set -euo pipefail + docker build --platform linux/amd64 --progress=plain \ + --target upstream-tests --tag kars-bridge-idp-upstream-tests:latest \ + --file bridge/idp/Dockerfile bridge/idp \ + 2>&1 | tee "$IDP_EVIDENCE_DIR/upstream-build.log" + - name: Collect actual upstream JSON reports and disclose skips + id: idp_reports + run: | + set -euo pipefail + container=$(docker create kars-bridge-idp-upstream-tests:latest) + trap 'docker rm "$container"' EXIT + docker cp "$container:/out/doc/upstream-tests.json" "$IDP_EVIDENCE_DIR/upstream-tests.json" + docker cp "$container:/out/doc/api-tests.json" "$IDP_EVIDENCE_DIR/api-tests.json" + docker image inspect kars-bridge-idp-upstream-tests:latest \ + > "$IDP_EVIDENCE_DIR/upstream-image.json" + python3 - <<'PY' + import collections + import json + import os + from pathlib import Path + + evidence = Path(os.environ["IDP_EVIDENCE_DIR"]) + summary = {} + for label, filename in (("root", "upstream-tests.json"), ("api", "api-tests.json")): + tests = collections.Counter() + packages = collections.Counter() + started, finished = set(), set() + skips = [] + for number, line in enumerate((evidence / filename).read_text().splitlines(), 1): + event = json.loads(line) + if not isinstance(event, dict) or not isinstance(event.get("Action"), str): + raise SystemExit(f"Invalid Go event in {filename}:{number}") + action = event["Action"] + if action in ("fail", "build-fail"): + raise SystemExit(f"Upstream failure recorded in {filename}:{number}") + package = event.get("Package") + if package and not event.get("Test"): + if action == "start": + started.add(package) + elif action in ("pass", "skip"): + finished.add(package) + packages[action] += 1 + if event.get("Test") and action in ("pass", "skip"): + tests[action] += 1 + if action == "skip": + skips.append({"package": package, "test": event.get("Test")}) + if not started or started != finished: + raise SystemExit(f"Incomplete package results in {filename}") + if label == "root" and not tests["pass"]: + raise SystemExit("The root report contains no passing upstream tests") + summary[label] = { + "testActions": dict(tests), "packageActions": dict(packages), "skipped": skips, + } + summary["coverageLimit"] = ( + "Skipped service integrations and unconfigured LDAP/cloud connectors are not " + "runtime-qualified. Memory, SQLite and static OIDC require the separate runtime harness." + ) + (evidence / "upstream-summary.json").write_text(json.dumps(summary, indent=2) + "\n") + with Path(os.environ["GITHUB_STEP_SUMMARY"]).open("a") as output: + output.write("### Dex upstream reports (not final runtime qualification)\n") + for label in ("root", "api"): + counts = summary[label] + output.write(f"- {label}: test actions {counts['testActions']}; " + f"package actions {counts['packageActions']}. See retained JSON for every skip.\n") + output.write(summary["coverageLimit"] + "\n") + PY + - name: Build Dex tools and run signing-key continuity race regressions + id: idp_tools + run: | + set -euo pipefail + docker build --platform linux/amd64 --progress=plain \ + --target test-tools --tag kars-bridge-idp-tools:latest \ + --file bridge/idp/Dockerfile bridge/idp \ + 2>&1 | tee "$IDP_EVIDENCE_DIR/probe-build.log" + docker image inspect kars-bridge-idp-tools:latest > "$IDP_EVIDENCE_DIR/tools-image.json" + - name: Build the actual Azure Linux distroless Dex runtime without publishing + id: idp_runtime + run: | + set -euo pipefail + docker build --platform linux/amd64 --progress=plain \ + --target runtime --tag kars-bridge-idp-qualification:latest \ + --file bridge/idp/Dockerfile bridge/idp \ + 2>&1 | tee "$IDP_EVIDENCE_DIR/runtime-build.log" + - name: Install pinned Trivy and scan the actual Dex runtime + id: idp_scan + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 + with: + version: v0.70.0 + cache: 'false' + scan-type: image + image-ref: kars-bridge-idp-qualification:latest + scanners: vuln + severity: HIGH,CRITICAL + ignore-unfixed: false + list-all-pkgs: 'true' + exit-code: '1' + format: json + output: ${{ runner.temp }}/bridge-idp-evidence/initial-image-scan.json + - name: Require real memory SQLite OIDC linkage inventory and fresh-cache scans + id: idp_qualification + if: ${{ !cancelled() && steps.idp_runtime.outcome == 'success' }} + run: | + set -euo pipefail + { + trivy_path="$(command -v trivy)" + test -x "$trivy_path" + printf '%s\n' "$trivy_path" > "$IDP_EVIDENCE_DIR/trivy-cli-path.txt" + "$trivy_path" --version | tee "$IDP_EVIDENCE_DIR/trivy-cli-version.txt" + grep -Eq '^Version: 0[.]70[.]0([[:space:]]|$)' "$IDP_EVIDENCE_DIR/trivy-cli-version.txt" + python3 bridge/idp/tests/qualify.py \ + --image kars-bridge-idp-qualification:latest \ + --tools-image kars-bridge-idp-tools:latest \ + --trivy "$trivy_path" --evidence "$IDP_EVIDENCE_DIR/runtime" + } 2>&1 | tee "$IDP_EVIDENCE_DIR/runtime-qualification.log" + - name: Record Dex step outcomes without overriding failures + if: always() + env: + IDP_STEP_RESULTS: ${{ toJSON(steps) }} + run: | + set -euo pipefail + mkdir -p "$IDP_EVIDENCE_DIR" + printf '%s\n' "$IDP_STEP_RESULTS" > "$IDP_EVIDENCE_DIR/step-outcomes.json" + - name: Retain actual Dex qualification evidence including failures + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4 + with: + name: bridge-idp-qualification-${{ github.sha }}-${{ github.run_attempt }} + path: ${{ runner.temp }}/bridge-idp-evidence/ + if-no-files-found: error + addon: name: Add-on install and uninstall runs-on: ubuntu-latest diff --git a/NOTICE b/NOTICE index 8edfa1d0..1bd003a7 100644 --- a/NOTICE +++ b/NOTICE @@ -85,6 +85,20 @@ The separately built aggregator downloads the official, checksum-verified remain with redistributed images; other bundled components retain their respective licenses. +## Optional curated Dex identity provider + +`bridge/idp` builds Dex v2.45.1 from upstream commit +`11d2eeb52b42e1980e14cb91e69dd9e3faab2076` under Apache License 2.0. +It preserves upstream attribution and explicitly discloses Kars packaging, +dependency updates, two literal-format fixes and a test-only historical +certificate clock adjustment. It is not an unmodified upstream Dex image. + +The original upstream license, source/module snapshots, reviewed patches and +linked dependency notices accompany the built image. `bridge/idp/NOTICE` +describes their installed locations. Generated module/checksum files and +patch inputs retain their exact verified bytes; Kars headers must not rewrite +them or imply ownership of upstream source. New Kars wrapper code is MIT. + ## Vendored TypeScript SDK build `vendor/agt/microsoft-agent-governance-sdk-4.0.0-agt-bdea1097.tgz` diff --git a/bridge/idp/.dockerignore b/bridge/idp/.dockerignore new file mode 100644 index 00000000..9e2e3154 --- /dev/null +++ b/bridge/idp/.dockerignore @@ -0,0 +1,18 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +* +!Dockerfile +!Dockerfile.locks +!locks +!locks/** +!patches +!patches/** +!scripts +!scripts/** +!tests +!tests/probe.go +!tests/probe_test.go +!NOTICE +!LICENSE +!README.md diff --git a/bridge/idp/Dockerfile b/bridge/idp/Dockerfile new file mode 100644 index 00000000..140fd60d --- /dev/null +++ b/bridge/idp/Dockerfile @@ -0,0 +1,67 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +# Context: bridge/idp. Native builds only: build each architecture on its own +# hosted worker. Bookworm's glibc baseline is older than Azure Linux 3's. +FROM golang:1.26.8-bookworm@sha256:9fdc884aacc3bec89b20ffc69f4bb369c78210e3e4f600387b5128b12c199f81 AS source +ENV GOTOOLCHAIN=local GOWORK=off GOPROXY=https://proxy.golang.org \ + GOSUMDB=sum.golang.org GOMODCACHE=/work/mod GOCACHE=/work/cache \ + GOFLAGS=-mod=readonly CGO_ENABLED=1 +WORKDIR /src/dex +COPY locks/inputs.lock /packaging/locks/inputs.lock +COPY scripts/fetch-source.sh scripts/source-inventory.sh scripts/apply-source-patches.sh /packaging/scripts/ +COPY patches/ /packaging/patches/ +RUN sh /packaging/scripts/fetch-source.sh + +FROM source AS dependencies +# Deliberately absent until a hosted Go resolver's output has been reviewed. +# A runtime build MUST fail rather than resolve new versions implicitly. +COPY locks/generated/ /locks/ +COPY locks/requests.txt /packaging/locks/requests.txt +COPY scripts/verify-locks.sh /packaging/scripts/verify-locks.sh +RUN sh /packaging/scripts/verify-locks.sh \ + && go mod download && go mod verify \ + && cmp go.mod /locks/go.mod && cmp go.sum /locks/go.sum \ + && cd api/v2 && go mod download && go mod verify \ + && cmp go.mod /locks/api/v2/go.mod && cmp go.sum /locks/api/v2/go.sum + +FROM dependencies AS build +COPY scripts/build.sh /packaging/scripts/build.sh +COPY scripts/notices.go /packaging/scripts/notices.go +COPY NOTICE LICENSE README.md /packaging/ +RUN sh /packaging/scripts/build.sh + +FROM build AS compatibility-tests +RUN go test -race -count=1 -v \ + -run '^(TestKarsAuthorizationErrorDescriptionsLiteral|TestVerifyUnsignedMessageAndSignedAssertionWithRootXmlNs|TestKarsSAMLFixtureCertificateValidity)$' \ + ./server ./connector/saml + +# Kept separate from shipping layers. Full upstream package suites; external +# service integration tests still require the upstream documented services. +FROM compatibility-tests AS upstream-tests +COPY scripts/upstream-tests.sh /packaging/scripts/upstream-tests.sh +RUN sh /packaging/scripts/upstream-tests.sh + +FROM build AS test-tools +COPY tests/probe.go tests/probe_test.go /packaging/tests/ +# Only the external HTTP probe is pure Go. Dex itself always uses real CGO. +RUN go test -race -count=1 -v /packaging/tests/probe.go /packaging/tests/probe_test.go \ + && CGO_ENABLED=0 go build -trimpath -buildvcs=false -o /out/probe /packaging/tests/probe.go +ENTRYPOINT ["/out/probe"] + +FROM mcr.microsoft.com/azurelinux/distroless/base:3.0@sha256:4377af4aa7a810b7d59f691eae5066895a71aa3eee4cfb4eba527bbebff16479 AS runtime +LABEL org.opencontainers.image.title="Kars Dex security rebuild" \ + org.opencontainers.image.description="Dex v2.45.1 with disclosed Kars source, dependency and packaging patches; not an unmodified upstream image" \ + org.opencontainers.image.version="v2.45.1-kars.1" \ + org.opencontainers.image.source="https://github.com/Azure/kars" \ + org.opencontainers.image.licenses="Apache-2.0 AND MIT" \ + io.kars.dex.upstream.revision="11d2eeb52b42e1980e14cb91e69dd9e3faab2076" +COPY --from=build /out/dex /usr/local/bin/dex +COPY --from=build /src/dex/web /srv/dex/web +COPY --from=build /out/doc/ /usr/share/doc/dex/ +COPY --from=build --chown=1001:1001 /out/etc/ /etc/dex/ +COPY --from=build --chown=1001:1001 /out/data/ /var/dex/ +USER 1001:1001 +EXPOSE 5556 5557 5558 +ENTRYPOINT ["/usr/local/bin/dex"] +CMD ["serve", "/etc/dex/config.yaml"] diff --git a/bridge/idp/Dockerfile.locks b/bridge/idp/Dockerfile.locks new file mode 100644 index 00000000..890c6252 --- /dev/null +++ b/bridge/idp/Dockerfile.locks @@ -0,0 +1,29 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +# Separate from the image recipe: even legacy builders must never resolve +# dependency versions as an incidental step in a normal runtime image build. +FROM golang:1.26.8-bookworm@sha256:9fdc884aacc3bec89b20ffc69f4bb369c78210e3e4f600387b5128b12c199f81 AS source +ENV GOTOOLCHAIN=local GOWORK=off GOPROXY=https://proxy.golang.org \ + GOSUMDB=sum.golang.org GOMODCACHE=/work/mod GOCACHE=/work/cache \ + GOFLAGS=-mod=readonly CGO_ENABLED=1 +WORKDIR /src/dex +COPY locks/inputs.lock /packaging/locks/inputs.lock +COPY scripts/fetch-source.sh scripts/source-inventory.sh scripts/apply-source-patches.sh /packaging/scripts/ +COPY patches/ /packaging/patches/ +RUN sh /packaging/scripts/fetch-source.sh + +FROM source AS lock-generation +COPY locks/requests.txt /packaging/locks/requests.txt +COPY scripts/generate-locks.sh /packaging/scripts/generate-locks.sh +RUN sh /packaging/scripts/generate-locks.sh + +FROM scratch AS lock-artifact +COPY --from=lock-generation /out/ / + +FROM lock-generation AS lock-replay +COPY locks/generated/ /reviewed/ +RUN cd /reviewed && sha256sum --check --strict SHA256SUMS \ + && cmp SHA256SUMS /out/SHA256SUMS \ + && cd /out && sha256sum --check --strict /reviewed/SHA256SUMS \ + && printf 'KARS_DEX_LOCK_REPLAY_PASSED\n' diff --git a/bridge/idp/LICENSE b/bridge/idp/LICENSE new file mode 100644 index 00000000..22aed37e --- /dev/null +++ b/bridge/idp/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/bridge/idp/NOTICE b/bridge/idp/NOTICE new file mode 100644 index 00000000..e1909281 --- /dev/null +++ b/bridge/idp/NOTICE @@ -0,0 +1,40 @@ +Kars Dex security rebuild + +Dex is an OpenID Connect identity provider originally developed by CoreOS, +maintained by the Dex project and its contributors: +https://github.com/dexidp/dex + +This package uses Dex v2.45.1 application source at commit +11d2eeb52b42e1980e14cb91e69dd9e3faab2076 under the Apache License, Version 2.0. +The unchanged upstream LICENSE is fetched from the verified source archive +and installed as /usr/share/doc/dex/DEX-LICENSE. + +This is NOT the official or unmodified upstream Dex image. Kars changes the +Go toolchain, module dependency manifests and container packaging, and marks +the binary version v2.45.1-kars.1. Two production calls in server/oauth2.go +now use a constant "%s" format to preserve preformatted error descriptions +literally and satisfy Go vet. These are the only production-source changes. +Production certificate validation, connectors, embedded web assets and real +CGO SQLite storage remain unchanged upstream implementations. + +A test-only patch validates the historical OAM SAML signature fixture at its +signed IssueInstant, using goxmldsig's supported test clock. Other signature +tests retain their real-clock default. The certificate and signed XML are not +changed. Added Go regressions exercise literal OAuth errors and enforce +certificate validity before/after the fixture certificate's lifetime. +The reviewed patches, regression sources and pinned before/after file hashes +are distributed in /usr/share/doc/dex/source-patches. Complete original and +expected patched source inventories are distributed as source.upstream.sha256 +and source.sha256 in /usr/share/doc/dex. + +The generated dependency diff and original and patched module files are +distributed in /usr/share/doc/dex/locks. Linked dependency license and notice +files are distributed in /usr/share/doc/dex/third-party. + +The official image's gomplate and docker-entrypoint programs are intentionally +not distributed. The supported invocation is /usr/local/bin/dex serve with an +explicit configuration file, not upstream entrypoint template expansion. + +Kars packaging code: Copyright (c) Microsoft Corporation. +Licensed under the MIT License in the Kars repository root. +Azure Linux base contents and attribution remain unchanged. diff --git a/bridge/idp/README.md b/bridge/idp/README.md new file mode 100644 index 00000000..8b49e5da --- /dev/null +++ b/bridge/idp/README.md @@ -0,0 +1,367 @@ + + +# Kars Dex security rebuild + +**Status: hosted build/test stages passed; final runtime qualification pending.** +Real Go-generated `locks/generated/` files are present and remain unchanged. +The successful hosted attempt on September 16, 2026 compiled Dex with CGO, +completed license collection, passed the compatibility cases, completed the +upstream root/API race-suite commands with exit code zero, passed all nine +signing-key-continuity regression subcases under the race detector, and compiled +the probe. Environment-dependent suite skips do not establish external +connector runtime coverage. + +The required `idp` job in public Bridge CI now builds these checked-in inputs +and executes the actual final distroless memory/SQLite/OIDC, linkage, inventory +and scan gates. That CI execution is still required; the earlier build/test +success is **not** final-image qualification or permission to deploy. This +wiring does not enable the optional IdP or change chart/default/installation +behavior. + +This is a packaging/dependency correction for the existing optional Dex IdP, +not another IdP or authentication framework. It starts from **Dex v2.45.1** +application source at +[`11d2eeb52b42e1980e14cb91e69dd9e3faab2076`](https://github.com/dexidp/dex/tree/11d2eeb52b42e1980e14cb91e69dd9e3faab2076). +The [stable release](https://github.com/dexidp/dex/releases/tag/v2.45.1) was +published March 3, 2026. The binary identifies itself as **v2.45.1-kars.1**, +and image labels and installed notices disclose both the dependency rebuild +and the bounded source changes. + +## Pinned inputs and security changes + +Public metadata was checked September 16, 2026. Pins are not a substitute for +a fresh final-image scan; a new advisory can block acceptance. + +| Input | Selected pin / reason | +| --- | --- | +| Dex source | `https://codeload.github.com/dexidp/dex/tar.gz/11d2eeb52b42e1980e14cb91e69dd9e3faab2076`, SHA-256 `18bf92e8ccbf53e86814c2beb39b7d59f28fb07c84639e9f47a9bb5ea764e0b9` (863,553 bytes when checked) | +| Compiler/builder | `golang:1.26.8-bookworm@sha256:9fdc884aacc3bec89b20ffc69f4bb369c78210e3e4f600387b5128b12c199f81` | +| Builder amd64 manifest | `sha256:bc6beb46032d45f421cf400036bf031cdc64f683ba9cdc124e31d063e71670bd` | +| Runtime | `mcr.microsoft.com/azurelinux/distroless/base:3.0@sha256:4377af4aa7a810b7d59f691eae5066895a71aa3eee4cfb4eba527bbebff16479` | +| Runtime amd64 manifest | `sha256:0198b6345e0aeffd6c2e455ebc4c74b1d644ac1dfcb5aa5236972f17fd281f27` | + +[Official Go download metadata](https://go.dev/dl/?mode=json&include=all) +selects **go1.26.8**, the latest stable 1.26 patch when checked. +[Release notes](https://go.dev/doc/devel/release#go1.26.8) date it September 1. +The official linux-amd64 Go archive SHA-256 is +`d0f743b33e8d8945e6b1f432edd15785c70507121d6e2a723b21285eddf8b57b`; +the Docker build uses the pinned official builder, not an unchecked download. +`GOTOOLCHAIN=local` forbids automatic replacement of the selected compiler. + +`locks/requests.txt` is a **resolution request, not a fake go.sum**: + +| Module | Upstream | Requested selection | Authoritative fix / dependency reason | +| --- | --- | --- | --- | +| `github.com/go-jose/go-jose/v4` | 4.1.3 | 4.1.4 | [GO-2026-4945](https://vuln.go.dev/ID/GO-2026-4945.json) | +| `github.com/russellhaering/goxmldsig` | 1.5.0 | 1.6.0 | [GO-2026-4753](https://vuln.go.dev/ID/GO-2026-4753.json) | +| `go.opentelemetry.io/otel`, `/metric`, `/trace` | 1.39.0 | 1.44.0 | [GO-2026-5506](https://vuln.go.dev/ID/GO-2026-5506.json) fixes 1.41; [GO-2026-5158](https://vuln.go.dev/ID/GO-2026-5158.json) and gRPC require 1.44 | +| `golang.org/x/crypto` | 0.48.0 | 0.56.0 | 0.55 fixes [GO-2026-6303](https://vuln.go.dev/ID/GO-2026-6303.json), but September advisories [GO-2026-6354](https://vuln.go.dev/ID/GO-2026-6354.json) / [6355](https://vuln.go.dev/ID/GO-2026-6355.json) require 0.56 | +| `golang.org/x/mod` | 0.32.0 | 0.40.0 | [GO-2026-6179](https://vuln.go.dev/ID/GO-2026-6179.json), [6180](https://vuln.go.dev/ID/GO-2026-6180.json) | +| `golang.org/x/net` | 0.50.0 | 0.58.0 | 0.56 fixes [GO-2026-5942](https://vuln.go.dev/ID/GO-2026-5942.json); gRPC requires 0.58 | +| `golang.org/x/text` | 0.34.0 | 0.41.0 | 0.39 fixes [GO-2026-5970](https://vuln.go.dev/ID/GO-2026-5970.json); gRPC/crypto require 0.41 | +| `google.golang.org/grpc` | 1.79.1 | 1.83.2 | [Stable security release](https://github.com/grpc/grpc-go/releases/tag/v1.83.2), [GO-2026-6443](https://vuln.go.dev/ID/GO-2026-6443.json) explicitly fixes the 1.83 branch in 1.83.2 | + +The exact module manifests are public at +`https://proxy.golang.org//@v/.mod`; their `.info` siblings +record upstream commit and publication metadata. +[gRPC 1.83.2](https://proxy.golang.org/google.golang.org/grpc/@v/v1.83.2.mod) +requires Go 1.25 and raises OTel/net/text. +[crypto 0.56.0](https://proxy.golang.org/golang.org/x/crypto/@v/v0.56.0.mod) +requires **Go 1.26.0**, so both root and nested API module directives are +deliberately raised from upstream's 1.25.0 / 1.24.0 to 1.26.0. The root's +`replace github.com/dexidp/dex/api/v2 => ./api/v2` is retained. +`x/mod` also requires `x/tools` 0.49.0; let Go resolve the full graph rather +than hand-editing transitive versions or checksums. + +Only the separate **`Dockerfile.locks`** maintenance recipe runs `go get` with exact +versions, followed by real `go mod tidy`, `download`, `verify` and `list`. +It uses the public checksum database and proxy without private configuration. +The image build only consumes the reviewed artifact with `-mod=readonly`; +it never runs `go get latest`, `tidy`, version selection or source generation. +The recipes are separate files, not just unrelated stages: legacy Docker +builders execute preceding stages even when the selected target does not +depend on them. Their pinned source/compiler stage is checked for consistency. +An unexpectedly higher MVS selection fails validation and needs review, not +a forced downgrade or a scanner waiver. + +## Disclosed source compatibility patches + +The original upstream commit and archive SHA-256 have **not** changed. +No new dependency versions, module locks, compiler pins or base images are +introduced by these compatibility corrections. + +| Reviewed input | Scope and reason | +| --- | --- | +| `patches/0001-literal-oauth-error-descriptions.patch` | Exactly two production calls in `server/oauth2.go`, originally lines 477 and 561, pass already-built descriptions as `"%s", description` / `"%s", err`. This satisfies Go vet and preserves literal percent characters instead of formatting the text twice. Error type, state, redirect URI and authorization decisions are unchanged. | +| `patches/0002-saml-fixture-validation-clock.patch` | Test-only change to `connector/saml/saml_test.go`. Only `TestVerifyUnsignedMessageAndSignedAssertionWithRootXmlNs` opts into a validation clock at the signed XML's `2016-12-12T16:54:35Z` IssueInstant. Existing helper callers keep a nil clock, which means the real clock. | +| `patches/server_compat_test.go` | Installed into the fetched source as `server/kars_compat_test.go`; exercises the real authorization parser, including literal `%s%[1]s%%` input and the out-of-band redirect error. | +| `patches/saml_compat_test.go` | Installed as `connector/saml/kars_compat_test.go`; the real signature verifier must accept the unchanged signed assertion at fixture time and reject it before certificate validity and after expiry. | + +The OAM fixture certificate is valid from **2016-06-30T04:54:16Z** through +**2026-06-28T04:54:16Z**. Its signed XML's IssueInstant is inside that interval. +This is an XML namespace/signature fixture, not a wall-clock expiry test. +The supported test-clock API is +[`NewFakeClockAt`](https://github.com/russellhaering/goxmldsig/blob/878c8c615feb628064040115d00e105a137fcfa7/clock.go); +[production validation](https://github.com/russellhaering/goxmldsig/blob/878c8c615feb628064040115d00e105a137fcfa7/validate.go) +still enforces the trusted certificate's `NotBefore` and `NotAfter`. +No certificate, signed XML, production SAML code, trust setting or vet setting +is weakened or replaced. + +`patches/SHA256SUMS` pins the patch order, both patches, regression sources and +the before/after file-hash manifests. The source stage first verifies the +original archive, inventories and verifies the **original** source, then +applies the reviewed patches with `git apply`. It verifies the reviewed post-patch hashes and +derives the expected `source.sha256` from the original inventory plus only +the four declared changed/added files. It compares that expected inventory +against the entire actual source inventory, rejecting additional files, +missing files, tampered patches, drift and double application. +Only the four dependency manifests are excluded from source inventory, as +before; they are independently checked against the generated Go locks. +The changed source files are **not** excluded or accepted by recomputing +their expected hashes from whatever a patch happens to produce. + +Original and patched source inventories and the complete disclosed patch +bundle are included in `/usr/share/doc/dex/`. The British-spelled `LICENCE` +handling in the dependency-notice collector is preserved. + +Source-only integrity checks (no Go compilation, bounded public download): + +```sh +PYTHONDONTWRITEBYTECODE=1 KARS_DEX_PATCH_NETWORK=1 \ + python3 -m unittest discover -s bridge/idp/tests -p 'test_*.py' +``` + +Without that opt-in, offline source contracts still run; actual patch-application +tests are reported as skipped. Neither mode is a replacement for the hosted +Go behavior regressions or runtime qualification. + +## Compatibility and shipping boundary + +The entrypoint is `/usr/local/bin/dex`; default arguments are +`serve /etc/dex/config.yaml`, matching the existing chart's direct command. +No config, client secret, test password, unsafe issuer or auth defaults ship. +The operator must mount an explicit configuration. `secretEnv`, bcrypt +`staticPasswords`, memory storage, Authorization Code + PKCE, nonce and JWKS +are unchanged upstream implementations. + +**CGO remains enabled for Dex.** No SQLite stub, `CGO_ENABLED=0`, custom +exclusion tags, static-glibc shortcut or connector removal is used to make a +scan pass. The Bookworm builder has an older glibc baseline than Azure Linux 3; +this is a compatibility premise, not proof of the actual native closure. +The shipping image copies **no Debian shared libraries**, compiler, shell, +package manager or build cache. Its loader and libraries must come from the +pinned Azure Linux base; hosted tests verify this and run real SQLite. +Build each platform on a native worker. Initial qualification is linux/amd64; +the multi-arch input indexes do not imply an arm64 qualification. + +The complete upstream `web/` tree remains at `/srv/dex/web`, in addition to +the normal compiled web assets. Upstream connectors and storage source remain +unchanged. Only the official image's unused `docker-entrypoint` and `gomplate` +programs are omitted: template expansion through that wrapper is **not** +supported by this package. Direct Dex features are not replaced or removed. + +Azure Linux's **14 RPM inventory records**, base files and CA trust are +retained rather than reconstructed. The final image installs the upstream +Apache-2.0 license, this package's MIT license, attribution, original/patched +module files, dependency diff, Go build metadata and ELF metadata under +`/usr/share/doc/dex/`. A build-time collector retains license/notice files +from linked modules (including bundled notices), and fails for missing root +licenses rather than silently shipping incomplete attribution. License review +of the generated graph and bundled native code is still an acceptance gate. + +## Hosted lock generation + +Local Docker and Go were unavailable and disk was below the 8.5 GiB floor. +Do not install Go, compile, populate a global cache or run these builds locally. +The following task uses an operator-approved ACR's compute but **does not push +an image**, deploy, or touch cluster state. +The context is this public-only directory, not private repository config. + +From the public Kars worktree root, set `SUBSCRIPTION_ID`, `ACR_NAME` and +`ARTIFACT_DIR` to approved operator values. Keep the artifact directory private. + +```sh +( + cd bridge/idp + az acr build \ + --subscription "$SUBSCRIPTION_ID" --registry "$ACR_NAME" \ + --platform linux/amd64 --no-push --timeout 3600 \ + --target lock-generation --file Dockerfile.locks . +) > "$ARTIFACT_DIR/dex-lock-generation.log" 2>&1 +``` + +`Dockerfile.locks` pins all public execution/source inputs above. This target +does **module metadata/source resolution only**, not Dex compilation or tests. +It uses only worker-owned `/work/mod` and `/work/cache`. Do not add registry +push credentials, Azure credentials, build secrets or private Go settings. +The log contains one public tar.gz artifact between +`KARS_DEX_LOCKS_BASE64_BEGIN` / `KARS_DEX_LOCKS_BASE64_END`, followed by its +transport SHA-256. Retain the ACR run ID and original log as provenance. + +```sh +python3 bridge/idp/scripts/import-locks.py "$ARTIFACT_DIR/dex-lock-generation.log" +PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s bridge/idp/tests -p 'test_*.py' +``` + +The importer checks the logged transport SHA-256 as well as the member +checksums. It rejects unsafe members, duplicate/incomplete files, oversized +archives, checksum/input drift, module resolver errors, duplicate module records, +unexpected toolchains and unreviewed module selections; it does not +overwrite existing locks. If ACR log delivery prefixes/truncates the artifact, +retrieve the **raw run log** rather than repairing checksums or guessing files. +Alternatively, on an approved hosted BuildKit worker: + +```sh +docker buildx build --platform linux/amd64 --target lock-artifact \ + --output "type=local,dest=$ARTIFACT_DIR/dex-locks" \ + --file bridge/idp/Dockerfile.locks bridge/idp +``` + +Artifact contents are the generated root/API `go.mod` and `go.sum`, +`modules.json`, `api-modules.json`, `graph.txt`, `toolchain.txt`, +`inputs.lock`, `requests.txt`, `dependencies.patch`, the four unchanged +`upstream/` module files, and `SHA256SUMS`. Review and persist these under +`bridge/idp/locks/generated/` before any runtime build. Generated module +checksums are Go's, not fabricated or transcribed from vulnerability reports. +On a second clean **native worker of the same architecture**, replay the +resolver without its cache and compare the entire reviewed artifact: + +```sh +docker build --no-cache --target lock-replay \ + --file bridge/idp/Dockerfile.locks bridge/idp +``` + +The replay target verifies both checksum inventories and requires exact +agreement for the root/API locks, selected module graphs, source snapshots, +dependency diff, inputs and toolchain record. Retain the build log with +`KARS_DEX_LOCK_REPLAY_PASSED`. A replay failure is a real reproducibility +blocker, not permission to overwrite the reviewed locks. Use a native Docker worker or an ACR task exposing Docker's `--no-cache` +option for this independent replay; do not assume the quick-build CLI exposes +that option. Neither replay nor generation is reachable from the normal +`Dockerfile`. + +## Required Bridge CI qualification + +[Bridge CI](../../.github/workflows/bridge-ci.yml) adds **Dex IdP runtime +qualification** (`idp`) to the existing **Bridge component acceptance** +aggregate. Missing, failed, cancelled or skipped IdP results fail that +aggregate; existing component checks remain required. The job has only +`contents: read`, builds on native amd64 Ubuntu Docker compute, and does not +log in to a registry, push an image or deploy cloud/cluster resources. + +The job runs source contracts with the verified-archive checks enabled and +explicitly validates the actual generated module locks. It builds +`upstream-tests`, `test-tools` and `runtime` from this directory. An owned +temporary container supplies the upstream root/API JSON reports; each report +must be complete and contain no failures. The summary records actual passing +test counts, package results and every skip, including packages with no test +files, without claiming that unconfigured LDAP/cloud integrations ran. + +The existing SHA-pinned Trivy action installs **0.70.0** and performs an initial +actual-image scan. The job discovers its executable using `command -v trivy`, +checks its version, and passes that path to `tests/qualify.py`. The harness +executes the real memory/SQLite/static-OIDC and key-continuity checks plus +native linkage, all base inventory/CA checks, and a separate strict scan with +a fresh cache and current DB. It still runs after an initial scan finding to +retain useful diagnostics; **both scan failures remain fatal**, with no +`continue-on-error` or alternate success path. + +The always-uploaded `bridge-idp-qualification--` artifact +contains source/build/probe/harness logs, upstream/API JSON and skip summary, +image provenance, discovered Trivy version/path, per-step outcomes, initial +scan JSON and all runtime evidence produced before success or failure. A failed +build retains its failure log instead of fabricating a completed test report. +Partial artifacts and upstream test success are not runtime qualification; +the harness's `runtime/runtime-passed.json` covers only its named gates, and +the overall job and aggregate must also succeed. + +## Hosted acceptance gates + +First run the focused compatibility target on approved hosted compute. The +subscription/registry/artifact values remain operator parameters; this example +does not push an image: + +```sh +( + cd bridge/idp + az acr build \ + --subscription "$SUBSCRIPTION_ID" --registry "$ACR_NAME" \ + --platform linux/amd64 --no-push --timeout 3600 \ + --target compatibility-tests --file Dockerfile . +) > "$ARTIFACT_DIR/dex-compatibility.log" 2>&1 +``` + +That target runs the real server/SAML regressions with race detection and vet +enabled. The earlier hosted attempt already passed those build/test stages; +the commands remain available to reproduce them before running the actual +runtime harness. The narrower target alone is not acceptance. Legacy ACR builders execute +preceding stages on the way to `test-tools`; the compatibility/upstream stages +are intentionally retained rather than reordered to conceal failures. + +On a **native Linux Docker worker with sufficient disk**, build the reviewed +context; examples below are local worker tags, never a publication: + +```sh +docker build --target compatibility-tests -t kars-dex-compat:latest bridge/idp +docker build --target upstream-tests -t kars-dex-tests:latest bridge/idp +docker build --target test-tools -t kars-dex-tools:latest bridge/idp +docker build --target runtime -t kars-dex:latest bridge/idp +trivy_path="$(command -v trivy)" +test -x "$trivy_path" +"$trivy_path" --version +python3 bridge/idp/tests/qualify.py \ + --image kars-dex:latest --tools-image kars-dex-tools:latest \ + --trivy "$trivy_path" \ + --evidence "$ARTIFACT_DIR/dex-runtime" +``` + +The runtime harness uses image IDs after resolving tags, private ephemeral +Docker networks/volumes, randomly generated test-only credentials, nonroot +read-only Dex containers, no capabilities and no-new-privileges. It cleans up +only its own uniquely named containers, networks, volumes and temporary files. +Test config and the external probe **never** enter the shipping image. + +Required evidence before parent acceptance: + +1. **Full upstream root/API suites** with race detection, retained JSON reports + (`/out/doc/upstream-tests.json`, `/out/doc/api-tests.json` in the test image). + Review and report every skip and remaining integration limit. Execute the + configured memory/SQLite/OIDC paths and relevant configured connector + integrations. Unconfigured external services do not become additional beta + prerequisites, but a skipped integration is not evidence of runtime + compatibility. Real code and compile/unit coverage remain; no production + service implementation is stubbed by this packaging. +2. **Real final-image runtime checks:** discovery, HTML password login, bcrypt, + `secretEnv` client authentication, S256 PKCE, JWKS RSA signature and + issuer/audience/nonce/expiry claims, userinfo, incorrect password/client + secret/verifier rejection, authorization-code replay rejection. Run all + against memory and SQLite. After SQLite restart, verify the old unexpired + ID token against restarted JWKS and the saved verified signing-key identity + before using the earlier refresh token. Retained old keys across legitimate + rotation must pass; missing/replaced keys must fail even if refresh works. +3. **Native closure and runtime contents:** ELF interpreter from the Azure Linux + base, its real `--list` output, successful native execution, unchanged base + file hashes/links and CA trust, all 14 RPM records, and no copied library + closure or extra tools. Docker's injected hosts/hostname/resolv.conf are the + only per-container export exclusions. +4. **Trivy 0.70.0, latest DB, zero HIGH/CRITICAL** across the final OS and Dex + binary. The harness uses a fresh cache, empty ignore/config files, explicit + vulnerability scanning, no ignored/unfixed exemptions, and requires + recognized Azure Linux inventory plus Go binary inventory. Persist JSON, + scanner/DB metadata, immutable image ID and ELF reports. Unknown/unscanned + payload is failure, not a clean report. +5. **Independent reproducibility and licenses:** rebuild without cache on a + second clean native worker and compare `/usr/local/bin/dex` SHA-256 plus + web/license/dependency payloads. Container export timestamps/image IDs alone + are not the reproducibility criterion. Review all dependency changes, + licenses and bundled SQLite attribution. +6. **Configured connector and beta integration checks** belong to the parent, + including genuine auth/native enrollment. Packaging probes do not diagnose + that flow and do not authorize shared chart/default/workflow changes. + +`runtime-passed.json` covers only the runtime harness's named gates, not full +qualification. No acceptance/publication/deployment status is implied by +source contracts, a generated lockfile, a successful compiler exit or a +scanner version floor. Any new vulnerability or compatibility failure blocks +acceptance and needs a real, disclosed correction. diff --git a/bridge/idp/locks/generated/SHA256SUMS b/bridge/idp/locks/generated/SHA256SUMS new file mode 100644 index 00000000..07c2eb38 --- /dev/null +++ b/bridge/idp/locks/generated/SHA256SUMS @@ -0,0 +1,15 @@ +4a7bed6907c8f8918791e69539597405d6ad18f3f386788a81ed28f024113ac8 ./api-modules.json +e304bf72c1bf687cf777af1ca1c70d96e928a86bfb40bc6d5aeb8239baac24f6 ./api/v2/go.mod +3410f76108a083dc3a603327c354639a078ee8d917146aa7bf769e37cce0f208 ./api/v2/go.sum +7aab541b65a7246f95a919912582d909a8cfc09e9348a10e34afac1773c29644 ./dependencies.patch +34b7b1e48a6020a855741fc497f0782f226fa75a701cf925c52ccdd322d38046 ./go.mod +6e47d5b5c5cd6ff030ffe276d8707e41c67e88321a6bc81248f61c58271ec59b ./go.sum +e65265ab047188c71f6c5369a5be77d8cbbbefe26e307eb505775050ebece449 ./graph.txt +d5a430f8c8fea443ebc134cff29ddc0914bdc7acc1220fce9073c439e1a780d6 ./inputs.lock +2381158f636af5715561fca4208f4d89ca22a0e9c393bd53daa984a644ce5b72 ./modules.json +23d3448085a87cb3d242e196bb8ad7b571b63392c90871c2f5b26b1c5f0b6575 ./requests.txt +7e35a947feee25f89c2649aa041942db786be35c3d6c484ab2ba2da849e3dc00 ./toolchain.txt +181fc42a509297fe685e3470388d378a229e6efd36dd874eef809b6e06fe41e8 ./upstream/api/v2/go.mod +ccf35830330ac8058a4f009babbb417039aec728cf92625572abc53474c5dfca ./upstream/api/v2/go.sum +3390a3a2aa213fa80b7cb857ae52eb031e0f1941292f3536951092acb1db1501 ./upstream/go.mod +09fab6a9bedf5e220ee82f75f8fc7db4f52854012875082f24ba629020980d13 ./upstream/go.sum diff --git a/bridge/idp/locks/generated/api-modules.json b/bridge/idp/locks/generated/api-modules.json new file mode 100644 index 00000000..f72cc83a --- /dev/null +++ b/bridge/idp/locks/generated/api-modules.json @@ -0,0 +1,421 @@ +{ + "Path": "github.com/dexidp/dex/api/v2", + "Main": true, + "Dir": "/src/dex/api/v2", + "GoMod": "/src/dex/api/v2/go.mod", + "GoVersion": "1.26.0" +} +{ + "Path": "cel.dev/expr", + "Version": "v0.25.2", + "Time": "2026-03-12T16:46:44Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/cel.dev/expr/@v/v0.25.2.mod", + "GoVersion": "1.23.0" +} +{ + "Path": "cloud.google.com/go/auth", + "Version": "v0.18.2", + "Time": "2026-02-13T17:14:27Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/cloud.google.com/go/auth/@v/v0.18.2.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "cloud.google.com/go/compute/metadata", + "Version": "v0.9.0", + "Time": "2025-09-24T19:41:55Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/cloud.google.com/go/compute/metadata/@v/v0.9.0.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp", + "Version": "v1.33.0", + "Time": "2026-06-04T20:21:43Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/!google!cloud!platform/opentelemetry-operations-go/detectors/gcp/@v/v1.33.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "github.com/cespare/xxhash/v2", + "Version": "v2.3.0", + "Time": "2024-04-04T20:00:10Z", + "Indirect": true, + "Dir": "/work/mod/github.com/cespare/xxhash/v2@v2.3.0", + "GoMod": "/work/mod/cache/download/github.com/cespare/xxhash/v2/@v/v2.3.0.mod", + "GoVersion": "1.11", + "Sum": "h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=", + "GoModSum": "h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=" +} +{ + "Path": "github.com/cncf/xds/go", + "Version": "v0.0.0-20260202195803-dba9d589def2", + "Time": "2026-02-02T19:58:03Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/cncf/xds/go/@v/v0.0.0-20260202195803-dba9d589def2.mod", + "GoVersion": "1.24.6" +} +{ + "Path": "github.com/envoyproxy/go-control-plane", + "Version": "v0.14.0", + "Time": "2025-11-04T22:01:44Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/envoyproxy/go-control-plane/@v/v0.14.0.mod", + "GoVersion": "1.23.0" +} +{ + "Path": "github.com/envoyproxy/go-control-plane/envoy", + "Version": "v1.37.0", + "Time": "2026-01-13T06:26:49Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/envoyproxy/go-control-plane/envoy/@v/v1.37.0.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "github.com/envoyproxy/go-control-plane/ratelimit", + "Version": "v0.1.0", + "Time": "2024-12-23T15:25:59Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/envoyproxy/go-control-plane/ratelimit/@v/v0.1.0.mod", + "GoVersion": "1.21" +} +{ + "Path": "github.com/envoyproxy/protoc-gen-validate", + "Version": "v1.3.3", + "Time": "2026-02-18T16:13:16Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/envoyproxy/protoc-gen-validate/@v/v1.3.3.mod", + "GoVersion": "1.24.1" +} +{ + "Path": "github.com/felixge/httpsnoop", + "Version": "v1.0.4", + "Time": "2023-03-12T10:31:09Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/felixge/httpsnoop/@v/v1.0.4.mod", + "GoVersion": "1.13" +} +{ + "Path": "github.com/go-jose/go-jose/v4", + "Version": "v4.1.4", + "Time": "2026-03-31T23:33:50Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/go-jose/go-jose/v4/@v/v4.1.4.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "github.com/go-logr/logr", + "Version": "v1.4.3", + "Time": "2025-05-19T04:56:57Z", + "Indirect": true, + "Dir": "/work/mod/github.com/go-logr/logr@v1.4.3", + "GoMod": "/work/mod/cache/download/github.com/go-logr/logr/@v/v1.4.3.mod", + "GoVersion": "1.18", + "Sum": "h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=", + "GoModSum": "h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=" +} +{ + "Path": "github.com/go-logr/stdr", + "Version": "v1.2.2", + "Time": "2021-12-14T08:00:35Z", + "Indirect": true, + "Dir": "/work/mod/github.com/go-logr/stdr@v1.2.2", + "GoMod": "/work/mod/cache/download/github.com/go-logr/stdr/@v/v1.2.2.mod", + "GoVersion": "1.16", + "Sum": "h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=", + "GoModSum": "h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=" +} +{ + "Path": "github.com/golang/glog", + "Version": "v1.2.5", + "Time": "2025-04-29T08:43:26Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/golang/glog/@v/v1.2.5.mod", + "GoVersion": "1.19" +} +{ + "Path": "github.com/golang/protobuf", + "Version": "v1.5.4", + "Time": "2024-03-06T06:45:40Z", + "Indirect": true, + "Dir": "/work/mod/github.com/golang/protobuf@v1.5.4", + "GoMod": "/work/mod/cache/download/github.com/golang/protobuf/@v/v1.5.4.mod", + "GoVersion": "1.17", + "Sum": "h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=", + "GoModSum": "h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=" +} +{ + "Path": "github.com/google/go-cmp", + "Version": "v0.7.0", + "Time": "2025-01-14T18:15:44Z", + "Indirect": true, + "Dir": "/work/mod/github.com/google/go-cmp@v0.7.0", + "GoMod": "/work/mod/cache/download/github.com/google/go-cmp/@v/v0.7.0.mod", + "GoVersion": "1.21", + "Sum": "h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=", + "GoModSum": "h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=" +} +{ + "Path": "github.com/google/s2a-go", + "Version": "v0.1.9", + "Time": "2025-01-06T17:53:46Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/google/s2a-go/@v/v0.1.9.mod", + "GoVersion": "1.20" +} +{ + "Path": "github.com/google/uuid", + "Version": "v1.6.0", + "Time": "2024-01-23T18:54:04Z", + "Indirect": true, + "Dir": "/work/mod/github.com/google/uuid@v1.6.0", + "GoMod": "/work/mod/cache/download/github.com/google/uuid/@v/v1.6.0.mod", + "Sum": "h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=", + "GoModSum": "h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=" +} +{ + "Path": "github.com/googleapis/enterprise-certificate-proxy", + "Version": "v0.3.11", + "Time": "2026-01-13T07:11:36Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/googleapis/enterprise-certificate-proxy/@v/v0.3.11.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "github.com/googleapis/gax-go/v2", + "Version": "v2.17.0", + "Time": "2026-02-03T18:41:38Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/googleapis/gax-go/v2/@v/v2.17.0.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "github.com/planetscale/vtprotobuf", + "Version": "v0.6.1-0.20240319094008-0393e58bdf10", + "Time": "2024-03-19T09:40:08Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/planetscale/vtprotobuf/@v/v0.6.1-0.20240319094008-0393e58bdf10.mod", + "GoVersion": "1.20" +} +{ + "Path": "github.com/spiffe/go-spiffe/v2", + "Version": "v2.7.0", + "Time": "2026-06-03T20:07:47Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/spiffe/go-spiffe/v2/@v/v2.7.0.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "go.opentelemetry.io/auto/sdk", + "Version": "v1.2.1", + "Time": "2025-09-15T16:53:44Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/auto/sdk@v1.2.1", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/auto/sdk/@v/v1.2.1.mod", + "GoVersion": "1.24.0", + "Sum": "h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=", + "GoModSum": "h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=" +} +{ + "Path": "go.opentelemetry.io/contrib/detectors/gcp", + "Version": "v1.44.0", + "Time": "2026-05-28T05:28:14Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/contrib/detectors/gcp/@v/v1.44.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", + "Version": "v0.61.0", + "Time": "2025-05-22T14:29:43Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/@v/v0.61.0.mod", + "GoVersion": "1.23.0" +} +{ + "Path": "go.opentelemetry.io/otel", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=", + "GoModSum": "h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=" +} +{ + "Path": "go.opentelemetry.io/otel/metric", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel/metric@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/metric/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=", + "GoModSum": "h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=" +} +{ + "Path": "go.opentelemetry.io/otel/sdk", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel/sdk@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/sdk/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=", + "GoModSum": "h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=" +} +{ + "Path": "go.opentelemetry.io/otel/sdk/metric", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel/sdk/metric@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/sdk/metric/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=", + "GoModSum": "h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=" +} +{ + "Path": "go.opentelemetry.io/otel/trace", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel/trace@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/trace/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=", + "GoModSum": "h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=" +} +{ + "Path": "golang.org/x/crypto", + "Version": "v0.55.0", + "Time": "2026-08-11T17:56:31Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/golang.org/x/crypto/@v/v0.55.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "golang.org/x/mod", + "Version": "v0.38.0", + "Time": "2026-07-08T15:41:22Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/golang.org/x/mod/@v/v0.38.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "golang.org/x/net", + "Version": "v0.58.0", + "Time": "2026-08-12T17:41:32Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/net@v0.58.0", + "GoMod": "/work/mod/cache/download/golang.org/x/net/@v/v0.58.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=", + "GoModSum": "h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=" +} +{ + "Path": "golang.org/x/oauth2", + "Version": "v0.36.0", + "Time": "2026-02-11T19:14:10Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/golang.org/x/oauth2/@v/v0.36.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "golang.org/x/sync", + "Version": "v0.22.0", + "Time": "2026-07-01T17:29:34Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/golang.org/x/sync/@v/v0.22.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "golang.org/x/sys", + "Version": "v0.47.0", + "Time": "2026-06-30T17:07:31Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/sys@v0.47.0", + "GoMod": "/work/mod/cache/download/golang.org/x/sys/@v/v0.47.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=", + "GoModSum": "h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=" +} +{ + "Path": "golang.org/x/term", + "Version": "v0.45.0", + "Time": "2026-07-08T15:40:56Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/golang.org/x/term/@v/v0.45.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "golang.org/x/text", + "Version": "v0.41.0", + "Time": "2026-08-11T15:22:47Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/text@v0.41.0", + "GoMod": "/work/mod/cache/download/golang.org/x/text/@v/v0.41.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=", + "GoModSum": "h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=" +} +{ + "Path": "golang.org/x/tools", + "Version": "v0.48.0", + "Time": "2026-07-09T02:42:41Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/golang.org/x/tools/@v/v0.48.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "gonum.org/v1/gonum", + "Version": "v0.17.0", + "Time": "2025-12-29T19:16:44Z", + "Indirect": true, + "Dir": "/work/mod/gonum.org/v1/gonum@v0.17.0", + "GoMod": "/work/mod/cache/download/gonum.org/v1/gonum/@v/v0.17.0.mod", + "GoVersion": "1.24.0", + "Sum": "h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=", + "GoModSum": "h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=" +} +{ + "Path": "google.golang.org/genproto/googleapis/api", + "Version": "v0.0.0-20260526163538-3dc84a4a5aaa", + "Time": "2026-05-26T16:35:38Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/google.golang.org/genproto/googleapis/api/@v/v0.0.0-20260526163538-3dc84a4a5aaa.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "google.golang.org/genproto/googleapis/rpc", + "Version": "v0.0.0-20260526163538-3dc84a4a5aaa", + "Time": "2026-05-26T16:35:38Z", + "Indirect": true, + "Dir": "/work/mod/google.golang.org/genproto/googleapis/rpc@v0.0.0-20260526163538-3dc84a4a5aaa", + "GoMod": "/work/mod/cache/download/google.golang.org/genproto/googleapis/rpc/@v/v0.0.0-20260526163538-3dc84a4a5aaa.mod", + "GoVersion": "1.25.0", + "Sum": "h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=", + "GoModSum": "h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=" +} +{ + "Path": "google.golang.org/grpc", + "Version": "v1.83.2", + "Time": "2026-08-25T15:47:16Z", + "Dir": "/work/mod/google.golang.org/grpc@v1.83.2", + "GoMod": "/work/mod/cache/download/google.golang.org/grpc/@v/v1.83.2.mod", + "GoVersion": "1.25.0", + "Sum": "h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU=", + "GoModSum": "h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8=" +} +{ + "Path": "google.golang.org/protobuf", + "Version": "v1.36.11", + "Time": "2025-12-12T08:48:31Z", + "Dir": "/work/mod/google.golang.org/protobuf@v1.36.11", + "GoMod": "/work/mod/cache/download/google.golang.org/protobuf/@v/v1.36.11.mod", + "GoVersion": "1.23", + "Sum": "h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=", + "GoModSum": "h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=" +} diff --git a/bridge/idp/locks/generated/api/v2/go.mod b/bridge/idp/locks/generated/api/v2/go.mod new file mode 100644 index 00000000..a48b6ec0 --- /dev/null +++ b/bridge/idp/locks/generated/api/v2/go.mod @@ -0,0 +1,17 @@ +module github.com/dexidp/dex/api/v2 + +go 1.26.0 + +toolchain go1.26.8 + +require ( + google.golang.org/grpc v1.83.2 + google.golang.org/protobuf v1.36.11 +) + +require ( + golang.org/x/net v0.58.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.41.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect +) diff --git a/bridge/idp/locks/generated/api/v2/go.sum b/bridge/idp/locks/generated/api/v2/go.sum new file mode 100644 index 00000000..c8fe8eee --- /dev/null +++ b/bridge/idp/locks/generated/api/v2/go.sum @@ -0,0 +1,64 @@ +cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8= +github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= +golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40= +golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= +golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= +google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/bridge/idp/locks/generated/dependencies.patch b/bridge/idp/locks/generated/dependencies.patch new file mode 100644 index 00000000..dd999d1e --- /dev/null +++ b/bridge/idp/locks/generated/dependencies.patch @@ -0,0 +1,528 @@ +--- upstream/go.mod ++++ kars/go.mod +@@ -1,6 +1,8 @@ + module github.com/dexidp/dex + +-go 1.25.0 ++go 1.26.0 ++ ++toolchain go1.26.8 + + require ( + cloud.google.com/go/compute/metadata v0.9.0 +@@ -13,7 +15,7 @@ + github.com/dexidp/dex/api/v2 v2.4.0 + github.com/fsnotify/fsnotify v1.9.0 + github.com/ghodss/yaml v1.0.0 +- github.com/go-jose/go-jose/v4 v4.1.3 ++ github.com/go-jose/go-jose/v4 v4.1.4 + github.com/go-ldap/ldap/v3 v3.4.12 + github.com/go-sql-driver/mysql v1.9.3 + github.com/google/uuid v1.6.0 +@@ -28,23 +30,23 @@ + github.com/openbao/openbao/api/v2 v2.5.1 + github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.23.2 +- github.com/russellhaering/goxmldsig v1.5.0 ++ github.com/russellhaering/goxmldsig v1.6.0 + github.com/spf13/cobra v1.10.2 + github.com/stretchr/testify v1.11.1 + go.etcd.io/etcd/client/pkg/v3 v3.6.8 + go.etcd.io/etcd/client/v3 v3.6.8 +- golang.org/x/crypto v0.48.0 ++ golang.org/x/crypto v0.56.0 + golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741 +- golang.org/x/net v0.50.0 +- golang.org/x/oauth2 v0.35.0 ++ golang.org/x/net v0.58.0 ++ golang.org/x/oauth2 v0.36.0 + google.golang.org/api v0.267.0 +- google.golang.org/grpc v1.79.1 ++ google.golang.org/grpc v1.83.2 + google.golang.org/protobuf v1.36.11 + ) + + require ( + ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect +- cloud.google.com/go/auth v0.18.1 // indirect ++ cloud.google.com/go/auth v0.18.2 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + dario.cat/mergo v1.0.1 // indirect + filippo.io/edwards25519 v1.1.1 // indirect +@@ -105,21 +107,21 @@ + go.etcd.io/etcd/api/v3 v3.6.8 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect +- go.opentelemetry.io/otel v1.39.0 // indirect +- go.opentelemetry.io/otel/metric v1.39.0 // indirect +- go.opentelemetry.io/otel/trace v1.39.0 // indirect ++ go.opentelemetry.io/otel v1.44.0 // indirect ++ go.opentelemetry.io/otel/metric v1.44.0 // indirect ++ go.opentelemetry.io/otel/trace v1.44.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect +- golang.org/x/mod v0.32.0 // indirect +- golang.org/x/sync v0.19.0 // indirect +- golang.org/x/sys v0.41.0 // indirect +- golang.org/x/text v0.34.0 // indirect ++ golang.org/x/mod v0.40.0 // indirect ++ golang.org/x/sync v0.22.0 // indirect ++ golang.org/x/sys v0.47.0 // indirect ++ golang.org/x/text v0.41.0 // indirect + golang.org/x/time v0.14.0 // indirect +- golang.org/x/tools v0.41.0 // indirect ++ golang.org/x/tools v0.49.0 // indirect + golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect +- google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect +- google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect ++ google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect ++ google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + ) +--- upstream/go.sum ++++ kars/go.sum +@@ -1,11 +1,15 @@ + ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 h1:E0wvcUXTkgyN4wy4LGtNzMNGMytJN8afmIWXJVMi4cc= + ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w= +-cloud.google.com/go/auth v0.18.1 h1:IwTEx92GFUo2pJ6Qea0EU3zYvKnTAeRCODxfA/G5UWs= +-cloud.google.com/go/auth v0.18.1/go.mod h1:GfTYoS9G3CWpRA3Va9doKN9mjPGRS+v41jmZAhBzbrA= ++cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= ++cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= ++cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM= ++cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= + cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= + cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= + cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= + cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= ++cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= ++cloud.google.com/go/translate v1.10.3/go.mod h1:GW0vC1qvPtd3pgtypCv4k4U8B7EdgK9/QEF2aJEUovs= + dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= + dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= + entgo.io/ent v0.14.5 h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4= +@@ -18,6 +22,7 @@ + github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= + github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= + github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= ++github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM= + github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= + github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= + github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +@@ -28,20 +33,28 @@ + github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= + github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= + github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= ++github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= ++github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= + github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e h1:4dAU9FXIyQktpoUAgOJK3OTFc/xug0PCXYCqU0FgDKI= + github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= ++github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= ++github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= ++github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= + github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= + github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= ++github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= + github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= + github.com/beevik/etree v1.6.0/go.mod h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc= + github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= + github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= ++github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= + github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= + github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= + github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= + github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= + github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= + github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= ++github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= + github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc= + github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8= + github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +@@ -53,6 +66,11 @@ + github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= ++github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= ++github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= ++github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= ++github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= ++github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= + github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= + github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= + github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +@@ -67,8 +85,8 @@ + github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= + github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= + github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +-github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +-github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= ++github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= ++github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= + github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4= + github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo= + github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +@@ -87,10 +105,13 @@ + github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= + github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= + github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= ++github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= ++github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= + github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= + github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= + github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= + github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= ++github.com/google/go-pkcs11 v0.3.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= + github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= + github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= + github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +@@ -103,6 +124,9 @@ + github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= + github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= + github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= ++github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= ++github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= ++github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +@@ -132,6 +156,7 @@ + github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= + github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= + github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= ++github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= + github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= + github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= + github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +@@ -146,8 +171,12 @@ + github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= + github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= + github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= ++github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= + github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= + github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= ++github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= ++github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= ++github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= + github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= + github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= + github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +@@ -173,6 +202,7 @@ + github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= + github.com/mattn/go-sqlite3 v1.14.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk= + github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= ++github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= + github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= + github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= + github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +@@ -181,8 +211,12 @@ + github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= + github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= + github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= ++github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= ++github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= ++github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= ++github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= + github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= + github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= + github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +@@ -192,9 +226,11 @@ + github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= + github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= + github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= ++github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= + github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= ++github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= + github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= + github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= + github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +@@ -203,11 +239,13 @@ + github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= + github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= + github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= ++github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= + github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= + github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +-github.com/russellhaering/goxmldsig v1.5.0 h1:AU2UkkYIUOTyZRbe08XMThaOCelArgvNfYapcmSjBNw= +-github.com/russellhaering/goxmldsig v1.5.0/go.mod h1:x98CjQNFJcWfMxeOrMnMKg70lvDP6tE0nTaeUnjXDmk= ++github.com/russellhaering/goxmldsig v1.6.0 h1:8fdWXEPh2k/NZNQBPFNoVfS3JmzS4ZprY/sAOpKQLks= ++github.com/russellhaering/goxmldsig v1.6.0/go.mod h1:TrnaquDcYxWXfJrOjeMBTX4mLBeYAqaHEyUeWPxZlBM= + github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= ++github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= + github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= + github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= + github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +@@ -220,6 +258,7 @@ + github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= + github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= + github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= ++github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= + github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= + github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= + github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +@@ -228,10 +267,15 @@ + github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= + github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= + github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= ++github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= ++github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= ++github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= + github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= + github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= ++github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= + github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= + github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= ++github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= + github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0= + github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= + go.etcd.io/etcd/api/v3 v3.6.8 h1:gqb1VN92TAI6G2FiBvWcqKtHiIjr4SU2GdXxTwyexbM= +@@ -240,22 +284,24 @@ + go.etcd.io/etcd/client/pkg/v3 v3.6.8/go.mod h1:GsiTRUZE2318PggZkAo6sWb6l8JLVrnckTNfbG8PWtw= + go.etcd.io/etcd/client/v3 v3.6.8 h1:B3G76t1UykqAOrbio7s/EPatixQDkQBevN8/mwiplrY= + go.etcd.io/etcd/client/v3 v3.6.8/go.mod h1:MVG4BpSIuumPi+ELF7wYtySETmoTWBHVcDoHdVupwt8= ++go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= + go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= + go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= ++go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s= + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +-go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +-go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +-go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +-go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +-go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +-go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +-go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +-go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +-go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +-go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= ++go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= ++go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= ++go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= ++go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= ++go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= ++go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= ++go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= ++go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= ++go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= ++go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= + go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= + go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= + go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +@@ -268,44 +314,46 @@ + golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= + golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +-golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +-golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= ++golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= ++golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= + golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741 h1:fGZugkZk2UgYBxtpKmvub51Yno1LJDeEsRp2xGD+0gY= + golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= + golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= + golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +-golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +-golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= ++golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= ++golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE= + golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= + golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= + golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= + golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +-golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +-golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +-golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= +-golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= ++golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= ++golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= ++golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= ++golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= + golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= + golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= + golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +-golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +-golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= ++golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= ++golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= + golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= + golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +-golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +-golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= ++golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= ++golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= ++golang.org/x/telemetry v0.0.0-20260811182544-a038080d80e5/go.mod h1:LVehoXe41cL5SCVQilsV7Gg6BNG+Js6P9PhSbYTIUkQ= ++golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= + golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= + golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +-golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +-golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= ++golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= ++golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= + golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= + golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= + golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= + golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= + golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= + golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +-golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +-golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= ++golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= ++golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= + golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY= + golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= + golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +@@ -314,18 +362,20 @@ + golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= + golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +-gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +-gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= ++gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= ++gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= + google.golang.org/api v0.267.0 h1:w+vfWPMPYeRs8qH1aYYsFX68jMls5acWl/jocfLomwE= + google.golang.org/api v0.267.0/go.mod h1:Jzc0+ZfLnyvXma3UtaTl023TdhZu6OMBP9tJ+0EmFD0= ++google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= + google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= + google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= +-google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M= +-google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I= +-google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac= +-google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +-google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= +-google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= ++google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= ++google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= ++google.golang.org/genproto/googleapis/bytestream v0.0.0-20260203192932-546029d2fa20/go.mod h1:Tej9lWiwVvQJP+b43pjJIsr/3mZycXWCIyoiXmbFf40= ++google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= ++google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= ++google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= ++google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= + google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= + google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= + gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +@@ -337,3 +387,4 @@ + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= + gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= + gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= ++sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +--- upstream/api/v2/go.mod ++++ kars/api/v2/go.mod +@@ -1,15 +1,17 @@ + module github.com/dexidp/dex/api/v2 + +-go 1.24.0 ++go 1.26.0 ++ ++toolchain go1.26.8 + + require ( +- google.golang.org/grpc v1.79.1 ++ google.golang.org/grpc v1.83.2 + google.golang.org/protobuf v1.36.11 + ) + + require ( +- golang.org/x/net v0.50.0 // indirect +- golang.org/x/sys v0.41.0 // indirect +- golang.org/x/text v0.34.0 // indirect +- google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect ++ golang.org/x/net v0.58.0 // indirect ++ golang.org/x/sys v0.47.0 // indirect ++ golang.org/x/text v0.41.0 // indirect ++ google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect + ) +--- upstream/api/v2/go.sum ++++ kars/api/v2/go.sum +@@ -1,38 +1,64 @@ ++cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= ++cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= ++cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= ++github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM= + github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= + github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= ++github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= ++github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= ++github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= ++github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= ++github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= ++github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= ++github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= + github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= + github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= + github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= + github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= ++github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= + github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= + github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= + github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= + github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= ++github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= + github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= + github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= ++github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8= ++github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= ++github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= ++github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= + go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= + go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +-go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +-go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +-go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +-go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +-go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +-go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +-go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +-go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +-go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +-go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +-golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +-golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +-golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +-golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +-golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +-golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +-gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +-gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +-google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac= +-google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +-google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= +-google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= ++go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s= ++go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= ++go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= ++go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= ++go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= ++go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= ++go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= ++go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= ++go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= ++go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= ++go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= ++go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= ++golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= ++golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40= ++golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= ++golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= ++golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= ++golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= ++golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= ++golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= ++golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= ++golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= ++golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= ++golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk= ++gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= ++gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= ++google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= ++google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= ++google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= ++google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= ++google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= + google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= + google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/bridge/idp/locks/generated/go.mod b/bridge/idp/locks/generated/go.mod new file mode 100644 index 00000000..b4b1cfa8 --- /dev/null +++ b/bridge/idp/locks/generated/go.mod @@ -0,0 +1,131 @@ +module github.com/dexidp/dex + +go 1.26.0 + +toolchain go1.26.8 + +require ( + cloud.google.com/go/compute/metadata v0.9.0 + entgo.io/ent v0.14.5 + github.com/AppsFlyer/go-sundheit v0.6.0 + github.com/Masterminds/semver v1.5.0 + github.com/Masterminds/sprig/v3 v3.3.0 + github.com/beevik/etree v1.6.0 + github.com/coreos/go-oidc/v3 v3.17.0 + github.com/dexidp/dex/api/v2 v2.4.0 + github.com/fsnotify/fsnotify v1.9.0 + github.com/ghodss/yaml v1.0.0 + github.com/go-jose/go-jose/v4 v4.1.4 + github.com/go-ldap/ldap/v3 v3.4.12 + github.com/go-sql-driver/mysql v1.9.3 + github.com/google/uuid v1.6.0 + github.com/gorilla/handlers v1.5.2 + github.com/gorilla/mux v1.8.1 + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 + github.com/kylelemons/godebug v1.1.0 + github.com/lib/pq v1.11.2 + github.com/mattermost/xml-roundtrip-validator v0.1.0 + github.com/mattn/go-sqlite3 v1.14.34 + github.com/oklog/run v1.2.0 + github.com/openbao/openbao/api/v2 v2.5.1 + github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.23.2 + github.com/russellhaering/goxmldsig v1.6.0 + github.com/spf13/cobra v1.10.2 + github.com/stretchr/testify v1.11.1 + go.etcd.io/etcd/client/pkg/v3 v3.6.8 + go.etcd.io/etcd/client/v3 v3.6.8 + golang.org/x/crypto v0.56.0 + golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741 + golang.org/x/net v0.58.0 + golang.org/x/oauth2 v0.36.0 + google.golang.org/api v0.267.0 + google.golang.org/grpc v1.83.2 + google.golang.org/protobuf v1.36.11 +) + +require ( + ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect + cloud.google.com/go/auth v0.18.2 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + dario.cat/mergo v1.0.1 // indirect + filippo.io/edwards25519 v1.1.1 // indirect + github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/agext/levenshtein v1.2.3 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bmatcuk/doublestar v1.3.4 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/inflect v0.19.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.11 // indirect + github.com/googleapis/gax-go/v2 v2.17.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-retryablehttp v0.7.8 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect + github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.7 // indirect + github.com/hashicorp/hcl v1.0.1-vault-7 // indirect + github.com/hashicorp/hcl/v2 v2.18.1 // indirect + github.com/huandu/xstrings v1.5.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jonboulle/clockwork v0.5.0 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/pflag v1.0.9 // indirect + github.com/zclconf/go-cty v1.14.4 // indirect + github.com/zclconf/go-cty-yaml v1.1.0 // indirect + go.etcd.io/etcd/api/v3 v3.6.8 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.44.0 // indirect + go.opentelemetry.io/otel/metric v1.44.0 // indirect + go.opentelemetry.io/otel/trace v1.44.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/mod v0.40.0 // indirect + golang.org/x/sync v0.22.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.41.0 // indirect + golang.org/x/time v0.14.0 // indirect + golang.org/x/tools v0.49.0 // indirect + golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/dexidp/dex/api/v2 => ./api/v2 + +tool entgo.io/ent/cmd/ent diff --git a/bridge/idp/locks/generated/go.sum b/bridge/idp/locks/generated/go.sum new file mode 100644 index 00000000..2235eedb --- /dev/null +++ b/bridge/idp/locks/generated/go.sum @@ -0,0 +1,390 @@ +ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 h1:E0wvcUXTkgyN4wy4LGtNzMNGMytJN8afmIWXJVMi4cc= +ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w= +cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= +cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= +cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM= +cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= +cloud.google.com/go/translate v1.10.3/go.mod h1:GW0vC1qvPtd3pgtypCv4k4U8B7EdgK9/QEF2aJEUovs= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +entgo.io/ent v0.14.5 h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4= +entgo.io/ent v0.14.5/go.mod h1:zTzLmWtPvGpmSwtkaayM2cm5m819NdM7z7tYPq3vN0U= +filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw= +filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/AppsFlyer/go-sundheit v0.6.0 h1:d2hBvCjBSb2lUsEWGfPigr4MCOt04sxB+Rppl0yUMSk= +github.com/AppsFlyer/go-sundheit v0.6.0/go.mod h1:LDdBHD6tQBtmHsdW+i1GwdTt6Wqc0qazf5ZEJVTbTME= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e h1:4dAU9FXIyQktpoUAgOJK3OTFc/xug0PCXYCqU0FgDKI= +github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= +github.com/beevik/etree v1.6.0/go.mod h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= +github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4= +github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc= +github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= +github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= +github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= +github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4= +github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= +github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-pkcs11 v0.3.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.11 h1:vAe81Msw+8tKUxi2Dqh/NZMz7475yUvmRIkXr4oN2ao= +github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8= +github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= +github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= +github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= +github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= +github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo= +github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= +github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= +github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs= +github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU= +github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.14.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk= +github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= +github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/openbao/openbao/api/v2 v2.5.1 h1:Br79D6L20SbAa5P7xqENxmvv8LyI4HoKosPy7klhn4o= +github.com/openbao/openbao/api/v2 v2.5.1/go.mod h1:Dh5un77tqGgMbmlVEqjqN+8/dMyUohnkaQVg/wXW0Ig= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russellhaering/goxmldsig v1.6.0 h1:8fdWXEPh2k/NZNQBPFNoVfS3JmzS4ZprY/sAOpKQLks= +github.com/russellhaering/goxmldsig v1.6.0/go.mod h1:TrnaquDcYxWXfJrOjeMBTX4mLBeYAqaHEyUeWPxZlBM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= +github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= +github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0= +github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= +go.etcd.io/etcd/api/v3 v3.6.8 h1:gqb1VN92TAI6G2FiBvWcqKtHiIjr4SU2GdXxTwyexbM= +go.etcd.io/etcd/api/v3 v3.6.8/go.mod h1:qyQj1HZPUV3B5cbAL8scG62+fyz5dSxxu0w8pn28N6Q= +go.etcd.io/etcd/client/pkg/v3 v3.6.8 h1:Qs/5C0LNFiqXxYf2GU8MVjYUEXJ6sZaYOz0zEqQgy50= +go.etcd.io/etcd/client/pkg/v3 v3.6.8/go.mod h1:GsiTRUZE2318PggZkAo6sWb6l8JLVrnckTNfbG8PWtw= +go.etcd.io/etcd/client/v3 v3.6.8 h1:B3G76t1UykqAOrbio7s/EPatixQDkQBevN8/mwiplrY= +go.etcd.io/etcd/client/v3 v3.6.8/go.mod h1:MVG4BpSIuumPi+ELF7wYtySETmoTWBHVcDoHdVupwt8= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/detectors/gcp v1.44.0/go.mod h1:tNAsgd8avTGke1+MndXlU5Cru4PQ9Ai/cCNWQv/ZJ/s= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= +golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= +golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741 h1:fGZugkZk2UgYBxtpKmvub51Yno1LJDeEsRp2xGD+0gY= +golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= +golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= +golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/telemetry v0.0.0-20260811182544-a038080d80e5/go.mod h1:LVehoXe41cL5SCVQilsV7Gg6BNG+Js6P9PhSbYTIUkQ= +golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= +golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= +golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY= +golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/api v0.267.0 h1:w+vfWPMPYeRs8qH1aYYsFX68jMls5acWl/jocfLomwE= +google.golang.org/api v0.267.0/go.mod h1:Jzc0+ZfLnyvXma3UtaTl023TdhZu6OMBP9tJ+0EmFD0= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= +google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20260203192932-546029d2fa20/go.mod h1:Tej9lWiwVvQJP+b43pjJIsr/3mZycXWCIyoiXmbFf40= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= +google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/bridge/idp/locks/generated/graph.txt b/bridge/idp/locks/generated/graph.txt new file mode 100644 index 00000000..ab0e13ba --- /dev/null +++ b/bridge/idp/locks/generated/graph.txt @@ -0,0 +1,840 @@ +github.com/dexidp/dex ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 +github.com/dexidp/dex cloud.google.com/go/auth@v0.18.2 +github.com/dexidp/dex cloud.google.com/go/auth/oauth2adapt@v0.2.8 +github.com/dexidp/dex cloud.google.com/go/compute/metadata@v0.9.0 +github.com/dexidp/dex dario.cat/mergo@v1.0.1 +github.com/dexidp/dex entgo.io/ent@v0.14.5 +github.com/dexidp/dex filippo.io/edwards25519@v1.1.1 +github.com/dexidp/dex github.com/AppsFlyer/go-sundheit@v0.6.0 +github.com/dexidp/dex github.com/Azure/go-ntlmssp@v0.0.0-20221128193559-754e69321358 +github.com/dexidp/dex github.com/Masterminds/goutils@v1.1.1 +github.com/dexidp/dex github.com/Masterminds/semver@v1.5.0 +github.com/dexidp/dex github.com/Masterminds/semver/v3@v3.3.0 +github.com/dexidp/dex github.com/Masterminds/sprig/v3@v3.3.0 +github.com/dexidp/dex github.com/agext/levenshtein@v1.2.3 +github.com/dexidp/dex github.com/apparentlymart/go-textseg/v15@v15.0.0 +github.com/dexidp/dex github.com/beevik/etree@v1.6.0 +github.com/dexidp/dex github.com/beorn7/perks@v1.0.1 +github.com/dexidp/dex github.com/bmatcuk/doublestar@v1.3.4 +github.com/dexidp/dex github.com/cenkalti/backoff/v4@v4.3.0 +github.com/dexidp/dex github.com/cespare/xxhash/v2@v2.3.0 +github.com/dexidp/dex github.com/coreos/go-oidc/v3@v3.17.0 +github.com/dexidp/dex github.com/coreos/go-semver@v0.3.1 +github.com/dexidp/dex github.com/coreos/go-systemd/v22@v22.5.0 +github.com/dexidp/dex github.com/davecgh/go-spew@v1.1.2-0.20180830191138-d8f796af33cc +github.com/dexidp/dex github.com/dexidp/dex/api/v2@v2.4.0 +github.com/dexidp/dex github.com/felixge/httpsnoop@v1.0.4 +github.com/dexidp/dex github.com/fsnotify/fsnotify@v1.9.0 +github.com/dexidp/dex github.com/ghodss/yaml@v1.0.0 +github.com/dexidp/dex github.com/go-asn1-ber/asn1-ber@v1.5.8-0.20250403174932-29230038a667 +github.com/dexidp/dex github.com/go-jose/go-jose/v4@v4.1.4 +github.com/dexidp/dex github.com/go-ldap/ldap/v3@v3.4.12 +github.com/dexidp/dex github.com/go-logr/logr@v1.4.3 +github.com/dexidp/dex github.com/go-logr/stdr@v1.2.2 +github.com/dexidp/dex github.com/go-openapi/inflect@v0.19.0 +github.com/dexidp/dex github.com/go-sql-driver/mysql@v1.9.3 +github.com/dexidp/dex github.com/go-viper/mapstructure/v2@v2.4.0 +github.com/dexidp/dex github.com/gogo/protobuf@v1.3.2 +github.com/dexidp/dex github.com/golang/protobuf@v1.5.4 +github.com/dexidp/dex github.com/google/go-cmp@v0.7.0 +github.com/dexidp/dex github.com/google/s2a-go@v0.1.9 +github.com/dexidp/dex github.com/google/uuid@v1.6.0 +github.com/dexidp/dex github.com/googleapis/enterprise-certificate-proxy@v0.3.11 +github.com/dexidp/dex github.com/googleapis/gax-go/v2@v2.17.0 +github.com/dexidp/dex github.com/gorilla/handlers@v1.5.2 +github.com/dexidp/dex github.com/gorilla/mux@v1.8.1 +github.com/dexidp/dex github.com/grpc-ecosystem/go-grpc-prometheus@v1.2.0 +github.com/dexidp/dex github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 +github.com/dexidp/dex github.com/hashicorp/errwrap@v1.1.0 +github.com/dexidp/dex github.com/hashicorp/go-cleanhttp@v0.5.2 +github.com/dexidp/dex github.com/hashicorp/go-multierror@v1.1.1 +github.com/dexidp/dex github.com/hashicorp/go-retryablehttp@v0.7.8 +github.com/dexidp/dex github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 +github.com/dexidp/dex github.com/hashicorp/go-secure-stdlib/strutil@v0.1.2 +github.com/dexidp/dex github.com/hashicorp/go-sockaddr@v1.0.7 +github.com/dexidp/dex github.com/hashicorp/hcl@v1.0.1-vault-7 +github.com/dexidp/dex github.com/hashicorp/hcl/v2@v2.18.1 +github.com/dexidp/dex github.com/huandu/xstrings@v1.5.0 +github.com/dexidp/dex github.com/inconshreveable/mousetrap@v1.1.0 +github.com/dexidp/dex github.com/jonboulle/clockwork@v0.5.0 +github.com/dexidp/dex github.com/kylelemons/godebug@v1.1.0 +github.com/dexidp/dex github.com/lib/pq@v1.11.2 +github.com/dexidp/dex github.com/mattermost/xml-roundtrip-validator@v0.1.0 +github.com/dexidp/dex github.com/mattn/go-runewidth@v0.0.9 +github.com/dexidp/dex github.com/mattn/go-sqlite3@v1.14.34 +github.com/dexidp/dex github.com/mitchellh/copystructure@v1.2.0 +github.com/dexidp/dex github.com/mitchellh/go-wordwrap@v1.0.1 +github.com/dexidp/dex github.com/mitchellh/mapstructure@v1.5.0 +github.com/dexidp/dex github.com/mitchellh/reflectwalk@v1.0.2 +github.com/dexidp/dex github.com/munnerz/goautoneg@v0.0.0-20191010083416-a7dc8b61c822 +github.com/dexidp/dex github.com/oklog/run@v1.2.0 +github.com/dexidp/dex github.com/olekukonko/tablewriter@v0.0.5 +github.com/dexidp/dex github.com/openbao/openbao/api/v2@v2.5.1 +github.com/dexidp/dex github.com/pkg/errors@v0.9.1 +github.com/dexidp/dex github.com/pmezard/go-difflib@v1.0.1-0.20181226105442-5d4384ee4fb2 +github.com/dexidp/dex github.com/prometheus/client_golang@v1.23.2 +github.com/dexidp/dex github.com/prometheus/client_model@v0.6.2 +github.com/dexidp/dex github.com/prometheus/common@v0.66.1 +github.com/dexidp/dex github.com/prometheus/procfs@v0.16.1 +github.com/dexidp/dex github.com/russellhaering/goxmldsig@v1.6.0 +github.com/dexidp/dex github.com/ryanuber/go-glob@v1.0.0 +github.com/dexidp/dex github.com/shopspring/decimal@v1.4.0 +github.com/dexidp/dex github.com/spf13/cast@v1.7.0 +github.com/dexidp/dex github.com/spf13/cobra@v1.10.2 +github.com/dexidp/dex github.com/spf13/pflag@v1.0.9 +github.com/dexidp/dex github.com/stretchr/testify@v1.11.1 +github.com/dexidp/dex github.com/zclconf/go-cty@v1.14.4 +github.com/dexidp/dex github.com/zclconf/go-cty-yaml@v1.1.0 +github.com/dexidp/dex go@1.26.0 +github.com/dexidp/dex go.etcd.io/etcd/api/v3@v3.6.8 +github.com/dexidp/dex go.etcd.io/etcd/client/pkg/v3@v3.6.8 +github.com/dexidp/dex go.etcd.io/etcd/client/v3@v3.6.8 +github.com/dexidp/dex go.opentelemetry.io/auto/sdk@v1.2.1 +github.com/dexidp/dex go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 +github.com/dexidp/dex go.opentelemetry.io/otel@v1.44.0 +github.com/dexidp/dex go.opentelemetry.io/otel/metric@v1.44.0 +github.com/dexidp/dex go.opentelemetry.io/otel/trace@v1.44.0 +github.com/dexidp/dex go.uber.org/multierr@v1.11.0 +github.com/dexidp/dex go.uber.org/zap@v1.27.0 +github.com/dexidp/dex go.yaml.in/yaml/v2@v2.4.2 +github.com/dexidp/dex golang.org/x/crypto@v0.56.0 +github.com/dexidp/dex golang.org/x/exp@v0.0.0-20221004215720-b9f4876ce741 +github.com/dexidp/dex golang.org/x/mod@v0.40.0 +github.com/dexidp/dex golang.org/x/net@v0.58.0 +github.com/dexidp/dex golang.org/x/oauth2@v0.36.0 +github.com/dexidp/dex golang.org/x/sync@v0.22.0 +github.com/dexidp/dex golang.org/x/sys@v0.47.0 +github.com/dexidp/dex golang.org/x/text@v0.41.0 +github.com/dexidp/dex golang.org/x/time@v0.14.0 +github.com/dexidp/dex golang.org/x/tools@v0.49.0 +github.com/dexidp/dex golang.org/x/tools/go/packages/packagestest@v0.1.1-deprecated +github.com/dexidp/dex google.golang.org/api@v0.267.0 +github.com/dexidp/dex google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa +github.com/dexidp/dex google.golang.org/genproto/googleapis/rpc@v0.0.0-20260526163538-3dc84a4a5aaa +github.com/dexidp/dex google.golang.org/grpc@v1.83.2 +github.com/dexidp/dex google.golang.org/protobuf@v1.36.11 +github.com/dexidp/dex gopkg.in/yaml.v2@v2.4.0 +github.com/dexidp/dex gopkg.in/yaml.v3@v3.0.1 +github.com/dexidp/dex toolchain@go1.26.8 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/DATA-DOG/go-sqlmock@v1.5.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/bmatcuk/doublestar@v1.3.4 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/go-openapi/inflect@v0.19.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/hashicorp/hcl/v2@v2.13.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/stretchr/testify@v1.8.2 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/zclconf/go-cty@v1.14.4 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/zclconf/go-cty-yaml@v1.1.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 golang.org/x/mod@v0.17.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/agext/levenshtein@v1.2.1 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/apparentlymart/go-textseg/v13@v13.0.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/apparentlymart/go-textseg/v15@v15.0.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/davecgh/go-spew@v1.1.1 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/google/go-cmp@v0.6.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/kr/text@v0.2.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/kylelemons/godebug@v1.1.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/mitchellh/go-wordwrap@v0.0.0-20150314170334-ad45545899c7 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 github.com/pmezard/go-difflib@v1.0.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 golang.org/x/text@v0.21.0 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 gopkg.in/yaml.v3@v3.0.1 +ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 go@1.22.12 +cloud.google.com/go/auth@v0.18.2 cloud.google.com/go/compute/metadata@v0.9.0 +cloud.google.com/go/auth@v0.18.2 github.com/google/go-cmp@v0.7.0 +cloud.google.com/go/auth@v0.18.2 github.com/google/s2a-go@v0.1.9 +cloud.google.com/go/auth@v0.18.2 github.com/googleapis/enterprise-certificate-proxy@v0.3.11 +cloud.google.com/go/auth@v0.18.2 github.com/googleapis/gax-go/v2@v2.17.0 +cloud.google.com/go/auth@v0.18.2 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc@v0.61.0 +cloud.google.com/go/auth@v0.18.2 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 +cloud.google.com/go/auth@v0.18.2 go.opentelemetry.io/otel@v1.39.0 +cloud.google.com/go/auth@v0.18.2 go.opentelemetry.io/otel/sdk@v1.39.0 +cloud.google.com/go/auth@v0.18.2 go.opentelemetry.io/otel/trace@v1.39.0 +cloud.google.com/go/auth@v0.18.2 golang.org/x/net@v0.49.0 +cloud.google.com/go/auth@v0.18.2 golang.org/x/time@v0.14.0 +cloud.google.com/go/auth@v0.18.2 google.golang.org/grpc@v1.78.0 +cloud.google.com/go/auth@v0.18.2 google.golang.org/protobuf@v1.36.11 +cloud.google.com/go/auth@v0.18.2 github.com/cespare/xxhash/v2@v2.3.0 +cloud.google.com/go/auth@v0.18.2 github.com/felixge/httpsnoop@v1.0.4 +cloud.google.com/go/auth@v0.18.2 github.com/go-logr/logr@v1.4.3 +cloud.google.com/go/auth@v0.18.2 github.com/go-logr/stdr@v1.2.2 +cloud.google.com/go/auth@v0.18.2 github.com/google/uuid@v1.6.0 +cloud.google.com/go/auth@v0.18.2 go.opentelemetry.io/auto/sdk@v1.2.1 +cloud.google.com/go/auth@v0.18.2 go.opentelemetry.io/otel/metric@v1.39.0 +cloud.google.com/go/auth@v0.18.2 golang.org/x/crypto@v0.47.0 +cloud.google.com/go/auth@v0.18.2 golang.org/x/oauth2@v0.32.0 +cloud.google.com/go/auth@v0.18.2 golang.org/x/sync@v0.19.0 +cloud.google.com/go/auth@v0.18.2 golang.org/x/sys@v0.40.0 +cloud.google.com/go/auth@v0.18.2 golang.org/x/text@v0.33.0 +cloud.google.com/go/auth@v0.18.2 google.golang.org/genproto/googleapis/rpc@v0.0.0-20260128011058-8636f8732409 +cloud.google.com/go/auth@v0.18.2 go@1.24.0 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 cloud.google.com/go/auth@v0.15.0 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 github.com/google/go-cmp@v0.7.0 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 golang.org/x/oauth2@v0.28.0 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 cloud.google.com/go/compute/metadata@v0.6.0 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 github.com/googleapis/enterprise-certificate-proxy@v0.3.5 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 github.com/googleapis/gax-go/v2@v2.14.1 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 golang.org/x/net@v0.37.0 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 golang.org/x/sys@v0.31.0 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 google.golang.org/genproto/googleapis/rpc@v0.0.0-20250227231956-55c901821b1e +cloud.google.com/go/auth/oauth2adapt@v0.2.8 google.golang.org/grpc@v1.71.0 +cloud.google.com/go/auth/oauth2adapt@v0.2.8 go@1.23.0 +cloud.google.com/go/compute/metadata@v0.9.0 github.com/google/go-cmp@v0.7.0 +cloud.google.com/go/compute/metadata@v0.9.0 golang.org/x/sys@v0.35.0 +cloud.google.com/go/compute/metadata@v0.9.0 go@1.24.0 +dario.cat/mergo@v1.0.1 gopkg.in/yaml.v3@v3.0.1 +entgo.io/ent@v0.14.5 ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9 +entgo.io/ent@v0.14.5 github.com/DATA-DOG/go-sqlmock@v1.5.0 +entgo.io/ent@v0.14.5 github.com/go-openapi/inflect@v0.19.0 +entgo.io/ent@v0.14.5 github.com/google/uuid@v1.3.0 +entgo.io/ent@v0.14.5 github.com/gorilla/websocket@v1.5.0 +entgo.io/ent@v0.14.5 github.com/jessevdk/go-flags@v1.5.0 +entgo.io/ent@v0.14.5 github.com/json-iterator/go@v1.1.12 +entgo.io/ent@v0.14.5 github.com/mattn/go-sqlite3@v1.14.17 +entgo.io/ent@v0.14.5 github.com/mitchellh/mapstructure@v1.5.0 +entgo.io/ent@v0.14.5 github.com/modern-go/reflect2@v1.0.2 +entgo.io/ent@v0.14.5 github.com/olekukonko/tablewriter@v0.0.5 +entgo.io/ent@v0.14.5 github.com/spf13/cobra@v1.7.0 +entgo.io/ent@v0.14.5 github.com/stretchr/testify@v1.8.4 +entgo.io/ent@v0.14.5 go.opencensus.io@v0.24.0 +entgo.io/ent@v0.14.5 golang.org/x/sync@v0.11.0 +entgo.io/ent@v0.14.5 golang.org/x/tools@v0.30.0 +entgo.io/ent@v0.14.5 github.com/agext/levenshtein@v1.2.3 +entgo.io/ent@v0.14.5 github.com/apparentlymart/go-textseg/v15@v15.0.0 +entgo.io/ent@v0.14.5 github.com/bmatcuk/doublestar@v1.3.4 +entgo.io/ent@v0.14.5 github.com/davecgh/go-spew@v1.1.1 +entgo.io/ent@v0.14.5 github.com/golang/groupcache@v0.0.0-20210331224755-41bb18bfe9da +entgo.io/ent@v0.14.5 github.com/google/go-cmp@v0.6.0 +entgo.io/ent@v0.14.5 github.com/hashicorp/hcl/v2@v2.18.1 +entgo.io/ent@v0.14.5 github.com/inconshreveable/mousetrap@v1.1.0 +entgo.io/ent@v0.14.5 github.com/kr/pretty@v0.3.0 +entgo.io/ent@v0.14.5 github.com/mattn/go-runewidth@v0.0.9 +entgo.io/ent@v0.14.5 github.com/mitchellh/go-wordwrap@v1.0.1 +entgo.io/ent@v0.14.5 github.com/modern-go/concurrent@v0.0.0-20180306012644-bacd9c7ef1dd +entgo.io/ent@v0.14.5 github.com/niemeyer/pretty@v0.0.0-20200227124842-a10e7caefd8e +entgo.io/ent@v0.14.5 github.com/pmezard/go-difflib@v1.0.0 +entgo.io/ent@v0.14.5 github.com/sergi/go-diff@v1.3.1 +entgo.io/ent@v0.14.5 github.com/spf13/pflag@v1.0.5 +entgo.io/ent@v0.14.5 github.com/stretchr/objx@v0.5.0 +entgo.io/ent@v0.14.5 github.com/zclconf/go-cty@v1.14.4 +entgo.io/ent@v0.14.5 github.com/zclconf/go-cty-yaml@v1.1.0 +entgo.io/ent@v0.14.5 golang.org/x/mod@v0.23.0 +entgo.io/ent@v0.14.5 golang.org/x/sys@v0.30.0 +entgo.io/ent@v0.14.5 golang.org/x/text@v0.21.0 +entgo.io/ent@v0.14.5 gopkg.in/check.v1@v1.0.0-20200227125254-8fa46927fb4f +entgo.io/ent@v0.14.5 gopkg.in/yaml.v3@v3.0.1 +entgo.io/ent@v0.14.5 go@1.23 +github.com/AppsFlyer/go-sundheit@v0.6.0 github.com/fortytw2/leaktest@v1.3.0 +github.com/AppsFlyer/go-sundheit@v0.6.0 github.com/kr/pretty@v0.1.0 +github.com/AppsFlyer/go-sundheit@v0.6.0 github.com/pkg/errors@v0.8.1 +github.com/AppsFlyer/go-sundheit@v0.6.0 github.com/stretchr/objx@v0.2.0 +github.com/AppsFlyer/go-sundheit@v0.6.0 github.com/stretchr/testify@v1.6.1 +github.com/AppsFlyer/go-sundheit@v0.6.0 gopkg.in/check.v1@v1.0.0-20190902080502-41f04d3bba15 +github.com/Masterminds/semver/v3@v3.3.0 go@1.21 +github.com/Masterminds/sprig/v3@v3.3.0 dario.cat/mergo@v1.0.1 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/Masterminds/goutils@v1.1.1 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/Masterminds/semver/v3@v3.3.0 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/google/uuid@v1.6.0 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/huandu/xstrings@v1.5.0 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/mitchellh/copystructure@v1.2.0 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/shopspring/decimal@v1.4.0 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/spf13/cast@v1.7.0 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/stretchr/testify@v1.5.1 +github.com/Masterminds/sprig/v3@v3.3.0 golang.org/x/crypto@v0.26.0 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/davecgh/go-spew@v1.1.1 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/google/go-cmp@v0.6.0 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/mitchellh/reflectwalk@v1.0.2 +github.com/Masterminds/sprig/v3@v3.3.0 github.com/pmezard/go-difflib@v1.0.0 +github.com/Masterminds/sprig/v3@v3.3.0 gopkg.in/yaml.v2@v2.3.0 +github.com/Masterminds/sprig/v3@v3.3.0 go@1.21 +github.com/beevik/etree@v1.6.0 go@1.23.0 +github.com/coreos/go-oidc/v3@v3.17.0 github.com/go-jose/go-jose/v4@v4.1.3 +github.com/coreos/go-oidc/v3@v3.17.0 golang.org/x/oauth2@v0.28.0 +github.com/coreos/go-oidc/v3@v3.17.0 go@1.24.0 +github.com/coreos/go-semver@v0.3.1 gopkg.in/yaml.v3@v3.0.1 +github.com/coreos/go-systemd/v22@v22.5.0 github.com/godbus/dbus/v5@v5.0.4 +github.com/dexidp/dex/api/v2@v2.4.0 google.golang.org/grpc@v1.83.2 +github.com/dexidp/dex/api/v2@v2.4.0 google.golang.org/protobuf@v1.36.11 +github.com/dexidp/dex/api/v2@v2.4.0 golang.org/x/net@v0.58.0 +github.com/dexidp/dex/api/v2@v2.4.0 golang.org/x/sys@v0.47.0 +github.com/dexidp/dex/api/v2@v2.4.0 golang.org/x/text@v0.41.0 +github.com/dexidp/dex/api/v2@v2.4.0 google.golang.org/genproto/googleapis/rpc@v0.0.0-20260526163538-3dc84a4a5aaa +github.com/dexidp/dex/api/v2@v2.4.0 go@1.26.0 +github.com/fsnotify/fsnotify@v1.9.0 golang.org/x/sys@v0.13.0 +github.com/go-jose/go-jose/v4@v4.1.4 go@1.24.0 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/Azure/go-ntlmssp@v0.0.0-20221128193559-754e69321358 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/alexbrainman/sspi@v0.0.0-20250919150558-7d374ff0d59e +github.com/go-ldap/ldap/v3@v3.4.12 github.com/go-asn1-ber/asn1-ber@v1.5.8-0.20250403174932-29230038a667 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/google/uuid@v1.6.0 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/jcmturner/gokrb5/v8@v8.4.4 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/stretchr/testify@v1.8.1 +github.com/go-ldap/ldap/v3@v3.4.12 golang.org/x/crypto@v0.36.0 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/davecgh/go-spew@v1.1.1 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/hashicorp/go-uuid@v1.0.3 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/jcmturner/aescts/v2@v2.0.0 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/jcmturner/dnsutils/v2@v2.0.0 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/jcmturner/gofork@v1.7.6 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/jcmturner/goidentity/v6@v6.0.1 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/jcmturner/rpc/v2@v2.0.3 +github.com/go-ldap/ldap/v3@v3.4.12 github.com/pmezard/go-difflib@v1.0.0 +github.com/go-ldap/ldap/v3@v3.4.12 golang.org/x/net@v0.38.0 +github.com/go-ldap/ldap/v3@v3.4.12 gopkg.in/yaml.v3@v3.0.1 +github.com/go-ldap/ldap/v3@v3.4.12 go@1.23.0 +github.com/go-logr/stdr@v1.2.2 github.com/go-logr/logr@v1.2.2 +github.com/go-sql-driver/mysql@v1.9.3 filippo.io/edwards25519@v1.1.0 +github.com/go-sql-driver/mysql@v1.9.3 go@1.21.0 +github.com/gogo/protobuf@v1.3.2 github.com/kisielk/errcheck@v1.5.0 +github.com/gogo/protobuf@v1.3.2 github.com/kisielk/gotool@v1.0.0 +github.com/gogo/protobuf@v1.3.2 golang.org/x/tools@v0.0.0-20210106214847-113979e3529a +github.com/golang/protobuf@v1.5.4 github.com/google/go-cmp@v0.5.5 +github.com/golang/protobuf@v1.5.4 google.golang.org/protobuf@v1.33.0 +github.com/google/go-cmp@v0.7.0 go@1.21 +github.com/google/s2a-go@v0.1.9 cloud.google.com/go/translate@v1.10.3 +github.com/google/s2a-go@v0.1.9 github.com/google/go-cmp@v0.6.0 +github.com/google/s2a-go@v0.1.9 golang.org/x/crypto@v0.31.0 +github.com/google/s2a-go@v0.1.9 golang.org/x/sync@v0.10.0 +github.com/google/s2a-go@v0.1.9 google.golang.org/api@v0.177.0 +github.com/google/s2a-go@v0.1.9 google.golang.org/appengine@v1.6.8 +github.com/google/s2a-go@v0.1.9 google.golang.org/grpc@v1.63.2 +github.com/google/s2a-go@v0.1.9 google.golang.org/protobuf@v1.34.2 +github.com/google/s2a-go@v0.1.9 cloud.google.com/go@v0.112.2 +github.com/google/s2a-go@v0.1.9 cloud.google.com/go/auth@v0.3.0 +github.com/google/s2a-go@v0.1.9 cloud.google.com/go/auth/oauth2adapt@v0.2.2 +github.com/google/s2a-go@v0.1.9 cloud.google.com/go/compute/metadata@v0.3.0 +github.com/google/s2a-go@v0.1.9 cloud.google.com/go/longrunning@v0.5.6 +github.com/google/s2a-go@v0.1.9 github.com/felixge/httpsnoop@v1.0.4 +github.com/google/s2a-go@v0.1.9 github.com/go-logr/logr@v1.4.1 +github.com/google/s2a-go@v0.1.9 github.com/go-logr/stdr@v1.2.2 +github.com/google/s2a-go@v0.1.9 github.com/golang/groupcache@v0.0.0-20210331224755-41bb18bfe9da +github.com/google/s2a-go@v0.1.9 github.com/golang/protobuf@v1.5.4 +github.com/google/s2a-go@v0.1.9 github.com/googleapis/enterprise-certificate-proxy@v0.3.2 +github.com/google/s2a-go@v0.1.9 github.com/googleapis/gax-go/v2@v2.12.3 +github.com/google/s2a-go@v0.1.9 go.opencensus.io@v0.24.0 +github.com/google/s2a-go@v0.1.9 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc@v0.49.0 +github.com/google/s2a-go@v0.1.9 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.49.0 +github.com/google/s2a-go@v0.1.9 go.opentelemetry.io/otel@v1.24.0 +github.com/google/s2a-go@v0.1.9 go.opentelemetry.io/otel/metric@v1.24.0 +github.com/google/s2a-go@v0.1.9 go.opentelemetry.io/otel/trace@v1.24.0 +github.com/google/s2a-go@v0.1.9 golang.org/x/net@v0.33.0 +github.com/google/s2a-go@v0.1.9 golang.org/x/oauth2@v0.19.0 +github.com/google/s2a-go@v0.1.9 golang.org/x/sys@v0.28.0 +github.com/google/s2a-go@v0.1.9 golang.org/x/text@v0.21.0 +github.com/google/s2a-go@v0.1.9 golang.org/x/time@v0.5.0 +github.com/google/s2a-go@v0.1.9 google.golang.org/genproto/googleapis/api@v0.0.0-20240429193739-8cf5692501f6 +github.com/google/s2a-go@v0.1.9 google.golang.org/genproto/googleapis/rpc@v0.0.0-20240429193739-8cf5692501f6 +github.com/googleapis/enterprise-certificate-proxy@v0.3.11 github.com/google/go-pkcs11@v0.3.0 +github.com/googleapis/enterprise-certificate-proxy@v0.3.11 golang.org/x/crypto@v0.47.0 +github.com/googleapis/enterprise-certificate-proxy@v0.3.11 golang.org/x/sys@v0.40.0 +github.com/googleapis/enterprise-certificate-proxy@v0.3.11 go@1.24.0 +github.com/googleapis/gax-go/v2@v2.17.0 github.com/google/go-cmp@v0.7.0 +github.com/googleapis/gax-go/v2@v2.17.0 google.golang.org/api@v0.264.0 +github.com/googleapis/gax-go/v2@v2.17.0 google.golang.org/genproto@v0.0.0-20260128011058-8636f8732409 +github.com/googleapis/gax-go/v2@v2.17.0 google.golang.org/genproto/googleapis/api@v0.0.0-20260128011058-8636f8732409 +github.com/googleapis/gax-go/v2@v2.17.0 google.golang.org/genproto/googleapis/rpc@v0.0.0-20260128011058-8636f8732409 +github.com/googleapis/gax-go/v2@v2.17.0 google.golang.org/grpc@v1.78.0 +github.com/googleapis/gax-go/v2@v2.17.0 google.golang.org/protobuf@v1.36.11 +github.com/googleapis/gax-go/v2@v2.17.0 golang.org/x/net@v0.49.0 +github.com/googleapis/gax-go/v2@v2.17.0 golang.org/x/sys@v0.40.0 +github.com/googleapis/gax-go/v2@v2.17.0 golang.org/x/text@v0.33.0 +github.com/googleapis/gax-go/v2@v2.17.0 go@1.24.0 +github.com/gorilla/handlers@v1.5.2 github.com/felixge/httpsnoop@v1.0.3 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 github.com/antihax/optional@v1.0.0 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 github.com/google/go-cmp@v0.7.0 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 github.com/rogpeppe/fastuuid@v1.2.0 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 golang.org/x/oauth2@v0.27.0 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 golang.org/x/text@v0.22.0 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 google.golang.org/genproto/googleapis/api@v0.0.0-20250303144028-a0af3efb3deb +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 google.golang.org/genproto/googleapis/rpc@v0.0.0-20250303144028-a0af3efb3deb +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 google.golang.org/grpc@v1.70.0 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 google.golang.org/protobuf@v1.36.5 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 gopkg.in/yaml.v3@v3.0.1 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 github.com/kr/pretty@v0.3.1 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 golang.org/x/net@v0.35.0 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 golang.org/x/sys@v0.30.0 +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c +github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 go@1.23.0 +github.com/hashicorp/go-multierror@v1.1.1 github.com/hashicorp/errwrap@v1.0.0 +github.com/hashicorp/go-retryablehttp@v0.7.8 github.com/hashicorp/go-cleanhttp@v0.5.2 +github.com/hashicorp/go-retryablehttp@v0.7.8 github.com/hashicorp/go-hclog@v1.6.3 +github.com/hashicorp/go-retryablehttp@v0.7.8 github.com/fatih/color@v1.16.0 +github.com/hashicorp/go-retryablehttp@v0.7.8 github.com/mattn/go-colorable@v0.1.13 +github.com/hashicorp/go-retryablehttp@v0.7.8 github.com/mattn/go-isatty@v0.0.20 +github.com/hashicorp/go-retryablehttp@v0.7.8 golang.org/x/sys@v0.20.0 +github.com/hashicorp/go-retryablehttp@v0.7.8 go@1.23 +github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 github.com/hashicorp/go-secure-stdlib/strutil@v0.1.2 +github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 github.com/hashicorp/go-sockaddr@v1.0.6 +github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 github.com/mitchellh/mapstructure@v1.5.0 +github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 github.com/stretchr/testify@v1.8.4 +github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 github.com/davecgh/go-spew@v1.1.1 +github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 github.com/pmezard/go-difflib@v1.0.0 +github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 github.com/ryanuber/go-glob@v1.0.0 +github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 gopkg.in/yaml.v3@v3.0.1 +github.com/hashicorp/go-secure-stdlib/strutil@v0.1.2 github.com/ryanuber/go-glob@v1.0.0 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/hashicorp/errwrap@v1.1.0 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/mitchellh/cli@v1.1.5 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/mitchellh/go-wordwrap@v1.0.1 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/ryanuber/columnize@v2.1.2+incompatible +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/Masterminds/goutils@v1.1.1 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/Masterminds/semver/v3@v3.1.1 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/Masterminds/sprig/v3@v3.2.1 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/armon/go-radix@v0.0.0-20180808171621-7fddfc383310 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/bgentry/speakeasy@v0.1.0 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/fatih/color@v1.7.0 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/google/uuid@v1.1.2 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/hashicorp/go-multierror@v1.0.0 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/huandu/xstrings@v1.3.2 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/imdario/mergo@v0.3.11 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/mattn/go-colorable@v0.0.9 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/mattn/go-isatty@v0.0.3 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/mitchellh/copystructure@v1.0.0 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/mitchellh/reflectwalk@v1.0.0 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/posener/complete@v1.1.1 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/shopspring/decimal@v1.2.0 +github.com/hashicorp/go-sockaddr@v1.0.7 github.com/spf13/cast@v1.3.1 +github.com/hashicorp/go-sockaddr@v1.0.7 golang.org/x/crypto@v0.17.0 +github.com/hashicorp/go-sockaddr@v1.0.7 golang.org/x/sys@v0.15.0 +github.com/hashicorp/hcl@v1.0.1-vault-7 github.com/davecgh/go-spew@v1.1.1 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/agext/levenshtein@v1.2.1 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/apparentlymart/go-dump@v0.0.0-20180507223929-23540a00eaa3 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/apparentlymart/go-textseg/v15@v15.0.0 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/davecgh/go-spew@v1.1.1 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/go-test/deep@v1.0.3 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/google/go-cmp@v0.3.1 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/kr/pretty@v0.1.0 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/kylelemons/godebug@v0.0.0-20170820004349-d65d576e9348 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/mitchellh/go-wordwrap@v0.0.0-20150314170334-ad45545899c7 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/sergi/go-diff@v1.0.0 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/spf13/pflag@v1.0.2 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/zclconf/go-cty@v1.13.0 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/zclconf/go-cty-debug@v0.0.0-20191215020915-b22d67c1ba0b +github.com/hashicorp/hcl/v2@v2.18.1 golang.org/x/crypto@v0.0.0-20220517005047-85d78b3ac167 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/apparentlymart/go-textseg/v13@v13.0.0 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/kr/text@v0.1.0 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/pmezard/go-difflib@v1.0.0 +github.com/hashicorp/hcl/v2@v2.18.1 github.com/stretchr/testify@v1.2.2 +github.com/hashicorp/hcl/v2@v2.18.1 golang.org/x/sys@v0.5.0 +github.com/hashicorp/hcl/v2@v2.18.1 golang.org/x/term@v0.0.0-20201126162022-7de9c90e9dd1 +github.com/hashicorp/hcl/v2@v2.18.1 golang.org/x/text@v0.11.0 +github.com/jonboulle/clockwork@v0.5.0 go@1.21 +github.com/lib/pq@v1.11.2 go@1.21 +github.com/mattermost/xml-roundtrip-validator@v0.1.0 github.com/stretchr/testify@v1.6.1 +github.com/mitchellh/copystructure@v1.2.0 github.com/mitchellh/reflectwalk@v1.0.2 +github.com/olekukonko/tablewriter@v0.0.5 github.com/mattn/go-runewidth@v0.0.9 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/cenkalti/backoff/v4@v4.3.0 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/go-jose/go-jose/v4@v4.1.3 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/go-test/deep@v1.1.1 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/go-viper/mapstructure/v2@v2.4.0 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/hashicorp/go-cleanhttp@v0.5.2 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/hashicorp/go-hclog@v1.6.3 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/hashicorp/go-multierror@v1.1.1 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/hashicorp/go-retryablehttp@v0.7.8 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/hashicorp/hcl@v1.0.1-vault-7 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/stretchr/testify@v1.11.1 +github.com/openbao/openbao/api/v2@v2.5.1 golang.org/x/net@v0.49.0 +github.com/openbao/openbao/api/v2@v2.5.1 golang.org/x/time@v0.14.0 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/davecgh/go-spew@v1.1.2-0.20180830191138-d8f796af33cc +github.com/openbao/openbao/api/v2@v2.5.1 github.com/fatih/color@v1.18.0 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/hashicorp/errwrap@v1.1.0 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/hashicorp/go-secure-stdlib/strutil@v0.1.2 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/hashicorp/go-sockaddr@v1.0.7 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/mattn/go-colorable@v0.1.14 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/mattn/go-isatty@v0.0.20 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/mitchellh/mapstructure@v1.5.0 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/pmezard/go-difflib@v1.0.1-0.20181226105442-5d4384ee4fb2 +github.com/openbao/openbao/api/v2@v2.5.1 github.com/ryanuber/go-glob@v1.0.0 +github.com/openbao/openbao/api/v2@v2.5.1 golang.org/x/sys@v0.40.0 +github.com/openbao/openbao/api/v2@v2.5.1 golang.org/x/text@v0.33.0 +github.com/openbao/openbao/api/v2@v2.5.1 gopkg.in/yaml.v3@v3.0.1 +github.com/openbao/openbao/api/v2@v2.5.1 go@1.24.0 +github.com/prometheus/client_golang@v1.23.2 github.com/beorn7/perks@v1.0.1 +github.com/prometheus/client_golang@v1.23.2 github.com/cespare/xxhash/v2@v2.3.0 +github.com/prometheus/client_golang@v1.23.2 github.com/google/go-cmp@v0.7.0 +github.com/prometheus/client_golang@v1.23.2 github.com/json-iterator/go@v1.1.12 +github.com/prometheus/client_golang@v1.23.2 github.com/klauspost/compress@v1.18.0 +github.com/prometheus/client_golang@v1.23.2 github.com/kylelemons/godebug@v1.1.0 +github.com/prometheus/client_golang@v1.23.2 github.com/prometheus/client_model@v0.6.2 +github.com/prometheus/client_golang@v1.23.2 github.com/prometheus/common@v0.66.1 +github.com/prometheus/client_golang@v1.23.2 github.com/prometheus/procfs@v0.16.1 +github.com/prometheus/client_golang@v1.23.2 go.uber.org/goleak@v1.3.0 +github.com/prometheus/client_golang@v1.23.2 golang.org/x/sys@v0.35.0 +github.com/prometheus/client_golang@v1.23.2 google.golang.org/protobuf@v1.36.8 +github.com/prometheus/client_golang@v1.23.2 github.com/jpillora/backoff@v1.0.0 +github.com/prometheus/client_golang@v1.23.2 github.com/kr/pretty@v0.3.1 +github.com/prometheus/client_golang@v1.23.2 github.com/modern-go/concurrent@v0.0.0-20180306012644-bacd9c7ef1dd +github.com/prometheus/client_golang@v1.23.2 github.com/modern-go/reflect2@v1.0.2 +github.com/prometheus/client_golang@v1.23.2 github.com/munnerz/goautoneg@v0.0.0-20191010083416-a7dc8b61c822 +github.com/prometheus/client_golang@v1.23.2 github.com/mwitkow/go-conntrack@v0.0.0-20190716064945-2f068394615f +github.com/prometheus/client_golang@v1.23.2 go.yaml.in/yaml/v2@v2.4.2 +github.com/prometheus/client_golang@v1.23.2 golang.org/x/net@v0.43.0 +github.com/prometheus/client_golang@v1.23.2 golang.org/x/oauth2@v0.30.0 +github.com/prometheus/client_golang@v1.23.2 golang.org/x/text@v0.28.0 +github.com/prometheus/client_golang@v1.23.2 go@1.23.0 +github.com/prometheus/client_model@v0.6.2 google.golang.org/protobuf@v1.36.6 +github.com/prometheus/client_model@v0.6.2 go@1.22.0 +github.com/prometheus/common@v0.66.1 github.com/alecthomas/kingpin/v2@v2.4.0 +github.com/prometheus/common@v0.66.1 github.com/google/go-cmp@v0.7.0 +github.com/prometheus/common@v0.66.1 github.com/julienschmidt/httprouter@v1.3.0 +github.com/prometheus/common@v0.66.1 github.com/munnerz/goautoneg@v0.0.0-20191010083416-a7dc8b61c822 +github.com/prometheus/common@v0.66.1 github.com/mwitkow/go-conntrack@v0.0.0-20190716064945-2f068394615f +github.com/prometheus/common@v0.66.1 github.com/prometheus/client_model@v0.6.2 +github.com/prometheus/common@v0.66.1 github.com/stretchr/testify@v1.11.1 +github.com/prometheus/common@v0.66.1 go.yaml.in/yaml/v2@v2.4.2 +github.com/prometheus/common@v0.66.1 golang.org/x/net@v0.43.0 +github.com/prometheus/common@v0.66.1 golang.org/x/oauth2@v0.30.0 +github.com/prometheus/common@v0.66.1 google.golang.org/protobuf@v1.36.8 +github.com/prometheus/common@v0.66.1 github.com/alecthomas/units@v0.0.0-20211218093645-b94a6e3cc137 +github.com/prometheus/common@v0.66.1 github.com/beorn7/perks@v1.0.1 +github.com/prometheus/common@v0.66.1 github.com/cespare/xxhash/v2@v2.3.0 +github.com/prometheus/common@v0.66.1 github.com/davecgh/go-spew@v1.1.1 +github.com/prometheus/common@v0.66.1 github.com/jpillora/backoff@v1.0.0 +github.com/prometheus/common@v0.66.1 github.com/pmezard/go-difflib@v1.0.0 +github.com/prometheus/common@v0.66.1 github.com/prometheus/client_golang@v1.20.4 +github.com/prometheus/common@v0.66.1 github.com/prometheus/procfs@v0.15.1 +github.com/prometheus/common@v0.66.1 github.com/rogpeppe/go-internal@v1.10.0 +github.com/prometheus/common@v0.66.1 github.com/xhit/go-str2duration/v2@v2.1.0 +github.com/prometheus/common@v0.66.1 golang.org/x/sys@v0.35.0 +github.com/prometheus/common@v0.66.1 golang.org/x/text@v0.28.0 +github.com/prometheus/common@v0.66.1 gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c +github.com/prometheus/common@v0.66.1 gopkg.in/yaml.v3@v3.0.1 +github.com/prometheus/common@v0.66.1 go@1.23.0 +github.com/prometheus/procfs@v0.16.1 github.com/google/go-cmp@v0.7.0 +github.com/prometheus/procfs@v0.16.1 golang.org/x/sync@v0.13.0 +github.com/prometheus/procfs@v0.16.1 golang.org/x/sys@v0.32.0 +github.com/prometheus/procfs@v0.16.1 go@1.23.0 +github.com/russellhaering/goxmldsig@v1.6.0 github.com/beevik/etree@v1.6.0 +github.com/russellhaering/goxmldsig@v1.6.0 github.com/jonboulle/clockwork@v0.5.0 +github.com/russellhaering/goxmldsig@v1.6.0 github.com/stretchr/testify@v1.8.4 +github.com/russellhaering/goxmldsig@v1.6.0 github.com/davecgh/go-spew@v1.1.1 +github.com/russellhaering/goxmldsig@v1.6.0 github.com/kr/pretty@v0.3.0 +github.com/russellhaering/goxmldsig@v1.6.0 github.com/pmezard/go-difflib@v1.0.0 +github.com/russellhaering/goxmldsig@v1.6.0 github.com/rogpeppe/go-internal@v1.8.0 +github.com/russellhaering/goxmldsig@v1.6.0 gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c +github.com/russellhaering/goxmldsig@v1.6.0 gopkg.in/yaml.v3@v3.0.1 +github.com/russellhaering/goxmldsig@v1.6.0 go@1.23.0 +github.com/spf13/cast@v1.7.0 github.com/frankban/quicktest@v1.14.6 +github.com/spf13/cast@v1.7.0 github.com/google/go-cmp@v0.5.9 +github.com/spf13/cast@v1.7.0 github.com/kr/pretty@v0.3.1 +github.com/spf13/cast@v1.7.0 github.com/kr/text@v0.2.0 +github.com/spf13/cast@v1.7.0 github.com/rogpeppe/go-internal@v1.9.0 +github.com/spf13/cobra@v1.10.2 github.com/cpuguy83/go-md2man/v2@v2.0.6 +github.com/spf13/cobra@v1.10.2 github.com/inconshreveable/mousetrap@v1.1.0 +github.com/spf13/cobra@v1.10.2 github.com/spf13/pflag@v1.0.9 +github.com/spf13/cobra@v1.10.2 go.yaml.in/yaml/v3@v3.0.4 +github.com/stretchr/testify@v1.11.1 github.com/davecgh/go-spew@v1.1.1 +github.com/stretchr/testify@v1.11.1 github.com/pmezard/go-difflib@v1.0.0 +github.com/stretchr/testify@v1.11.1 github.com/stretchr/objx@v0.5.2 +github.com/stretchr/testify@v1.11.1 gopkg.in/yaml.v3@v3.0.1 +github.com/zclconf/go-cty@v1.14.4 github.com/apparentlymart/go-textseg/v15@v15.0.0 +github.com/zclconf/go-cty@v1.14.4 github.com/google/go-cmp@v0.3.1 +github.com/zclconf/go-cty@v1.14.4 github.com/vmihailenco/msgpack/v5@v5.3.5 +github.com/zclconf/go-cty@v1.14.4 golang.org/x/text@v0.11.0 +github.com/zclconf/go-cty@v1.14.4 github.com/davecgh/go-spew@v1.1.1 +github.com/zclconf/go-cty@v1.14.4 github.com/vmihailenco/tagparser/v2@v2.0.0 +github.com/zclconf/go-cty-yaml@v1.1.0 github.com/zclconf/go-cty@v1.0.0 +github.com/zclconf/go-cty-yaml@v1.1.0 golang.org/x/text@v0.3.0 +go@1.26.0 toolchain@go1.26.0 +go.etcd.io/etcd/api/v3@v3.6.8 github.com/coreos/go-semver@v0.3.1 +go.etcd.io/etcd/api/v3@v3.6.8 github.com/gogo/protobuf@v1.3.2 +go.etcd.io/etcd/api/v3@v3.6.8 github.com/golang/protobuf@v1.5.4 +go.etcd.io/etcd/api/v3@v3.6.8 github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 +go.etcd.io/etcd/api/v3@v3.6.8 github.com/stretchr/testify@v1.10.0 +go.etcd.io/etcd/api/v3@v3.6.8 google.golang.org/genproto/googleapis/api@v0.0.0-20250303144028-a0af3efb3deb +go.etcd.io/etcd/api/v3@v3.6.8 google.golang.org/grpc@v1.71.1 +go.etcd.io/etcd/api/v3@v3.6.8 google.golang.org/protobuf@v1.36.5 +go.etcd.io/etcd/api/v3@v3.6.8 github.com/davecgh/go-spew@v1.1.1 +go.etcd.io/etcd/api/v3@v3.6.8 github.com/kr/text@v0.2.0 +go.etcd.io/etcd/api/v3@v3.6.8 github.com/pmezard/go-difflib@v1.0.0 +go.etcd.io/etcd/api/v3@v3.6.8 github.com/rogpeppe/go-internal@v1.14.1 +go.etcd.io/etcd/api/v3@v3.6.8 golang.org/x/net@v0.47.0 +go.etcd.io/etcd/api/v3@v3.6.8 golang.org/x/sys@v0.38.0 +go.etcd.io/etcd/api/v3@v3.6.8 golang.org/x/text@v0.31.0 +go.etcd.io/etcd/api/v3@v3.6.8 google.golang.org/genproto/googleapis/rpc@v0.0.0-20250303144028-a0af3efb3deb +go.etcd.io/etcd/api/v3@v3.6.8 gopkg.in/yaml.v3@v3.0.1 +go.etcd.io/etcd/api/v3@v3.6.8 go@1.24.0 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 github.com/coreos/go-systemd/v22@v22.5.0 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 github.com/stretchr/testify@v1.10.0 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 go.uber.org/zap@v1.27.0 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 golang.org/x/sys@v0.38.0 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 github.com/davecgh/go-spew@v1.1.1 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 github.com/kr/pretty@v0.3.1 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 github.com/pmezard/go-difflib@v1.0.0 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 github.com/rogpeppe/go-internal@v1.14.1 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 go.uber.org/multierr@v1.11.0 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c +go.etcd.io/etcd/client/pkg/v3@v3.6.8 gopkg.in/yaml.v3@v3.0.1 +go.etcd.io/etcd/client/pkg/v3@v3.6.8 go@1.24.0 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/coreos/go-semver@v0.3.1 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/dustin/go-humanize@v1.0.1 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus@v1.0.1 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/prometheus/client_golang@v1.20.5 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/stretchr/testify@v1.10.0 +go.etcd.io/etcd/client/v3@v3.6.8 go.etcd.io/etcd/api/v3@v3.6.8 +go.etcd.io/etcd/client/v3@v3.6.8 go.etcd.io/etcd/client/pkg/v3@v3.6.8 +go.etcd.io/etcd/client/v3@v3.6.8 go.uber.org/zap@v1.27.0 +go.etcd.io/etcd/client/v3@v3.6.8 google.golang.org/grpc@v1.71.1 +go.etcd.io/etcd/client/v3@v3.6.8 sigs.k8s.io/yaml@v1.4.0 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/beorn7/perks@v1.0.1 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/cespare/xxhash/v2@v2.3.0 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/coreos/go-systemd/v22@v22.5.0 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/davecgh/go-spew@v1.1.1 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/gogo/protobuf@v1.3.2 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/golang/protobuf@v1.5.4 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/grpc-ecosystem/go-grpc-middleware/v2@v2.1.0 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/klauspost/compress@v1.17.9 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/munnerz/goautoneg@v0.0.0-20191010083416-a7dc8b61c822 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/pmezard/go-difflib@v1.0.0 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/prometheus/client_model@v0.6.1 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/prometheus/common@v0.62.0 +go.etcd.io/etcd/client/v3@v3.6.8 github.com/prometheus/procfs@v0.15.1 +go.etcd.io/etcd/client/v3@v3.6.8 go.uber.org/multierr@v1.11.0 +go.etcd.io/etcd/client/v3@v3.6.8 golang.org/x/net@v0.47.0 +go.etcd.io/etcd/client/v3@v3.6.8 golang.org/x/sys@v0.38.0 +go.etcd.io/etcd/client/v3@v3.6.8 golang.org/x/text@v0.31.0 +go.etcd.io/etcd/client/v3@v3.6.8 google.golang.org/genproto/googleapis/api@v0.0.0-20250303144028-a0af3efb3deb +go.etcd.io/etcd/client/v3@v3.6.8 google.golang.org/genproto/googleapis/rpc@v0.0.0-20250303144028-a0af3efb3deb +go.etcd.io/etcd/client/v3@v3.6.8 google.golang.org/protobuf@v1.36.5 +go.etcd.io/etcd/client/v3@v3.6.8 gopkg.in/yaml.v3@v3.0.1 +go.etcd.io/etcd/client/v3@v3.6.8 go@1.24.0 +go.opentelemetry.io/auto/sdk@v1.2.1 github.com/stretchr/testify@v1.11.1 +go.opentelemetry.io/auto/sdk@v1.2.1 go.opentelemetry.io/otel@v1.38.0 +go.opentelemetry.io/auto/sdk@v1.2.1 go.opentelemetry.io/otel/trace@v1.38.0 +go.opentelemetry.io/auto/sdk@v1.2.1 github.com/davecgh/go-spew@v1.1.1 +go.opentelemetry.io/auto/sdk@v1.2.1 github.com/kr/pretty@v0.3.1 +go.opentelemetry.io/auto/sdk@v1.2.1 github.com/pmezard/go-difflib@v1.0.0 +go.opentelemetry.io/auto/sdk@v1.2.1 github.com/rogpeppe/go-internal@v1.14.1 +go.opentelemetry.io/auto/sdk@v1.2.1 gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c +go.opentelemetry.io/auto/sdk@v1.2.1 gopkg.in/yaml.v3@v3.0.1 +go.opentelemetry.io/auto/sdk@v1.2.1 go@1.24.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 github.com/felixge/httpsnoop@v1.0.4 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 github.com/stretchr/testify@v1.10.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 go.opentelemetry.io/otel@v1.36.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 go.opentelemetry.io/otel/metric@v1.36.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 go.opentelemetry.io/otel/sdk@v1.36.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 go.opentelemetry.io/otel/sdk/metric@v1.36.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 go.opentelemetry.io/otel/trace@v1.36.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 github.com/davecgh/go-spew@v1.1.1 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 github.com/go-logr/logr@v1.4.2 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 github.com/go-logr/stdr@v1.2.2 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 github.com/google/uuid@v1.6.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 github.com/pmezard/go-difflib@v1.0.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 go.opentelemetry.io/auto/sdk@v1.1.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 golang.org/x/sys@v0.33.0 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 gopkg.in/yaml.v3@v3.0.1 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 go@1.23.0 +go.opentelemetry.io/otel@v1.44.0 github.com/cespare/xxhash/v2@v2.3.0 +go.opentelemetry.io/otel@v1.44.0 github.com/go-logr/logr@v1.4.3 +go.opentelemetry.io/otel@v1.44.0 github.com/go-logr/stdr@v1.2.2 +go.opentelemetry.io/otel@v1.44.0 github.com/google/go-cmp@v0.7.0 +go.opentelemetry.io/otel@v1.44.0 github.com/stretchr/testify@v1.11.1 +go.opentelemetry.io/otel@v1.44.0 go.opentelemetry.io/auto/sdk@v1.2.1 +go.opentelemetry.io/otel@v1.44.0 go.opentelemetry.io/otel/metric@v1.44.0 +go.opentelemetry.io/otel@v1.44.0 go.opentelemetry.io/otel/trace@v1.44.0 +go.opentelemetry.io/otel@v1.44.0 github.com/davecgh/go-spew@v1.1.1 +go.opentelemetry.io/otel@v1.44.0 github.com/kr/text@v0.2.0 +go.opentelemetry.io/otel@v1.44.0 github.com/pmezard/go-difflib@v1.0.0 +go.opentelemetry.io/otel@v1.44.0 gopkg.in/yaml.v3@v3.0.1 +go.opentelemetry.io/otel@v1.44.0 go@1.25.0 +go.opentelemetry.io/otel/metric@v1.44.0 github.com/stretchr/testify@v1.11.1 +go.opentelemetry.io/otel/metric@v1.44.0 go.opentelemetry.io/otel@v1.44.0 +go.opentelemetry.io/otel/metric@v1.44.0 github.com/cespare/xxhash/v2@v2.3.0 +go.opentelemetry.io/otel/metric@v1.44.0 github.com/davecgh/go-spew@v1.1.1 +go.opentelemetry.io/otel/metric@v1.44.0 github.com/go-logr/logr@v1.4.3 +go.opentelemetry.io/otel/metric@v1.44.0 github.com/go-logr/stdr@v1.2.2 +go.opentelemetry.io/otel/metric@v1.44.0 github.com/pmezard/go-difflib@v1.0.0 +go.opentelemetry.io/otel/metric@v1.44.0 go.opentelemetry.io/auto/sdk@v1.2.1 +go.opentelemetry.io/otel/metric@v1.44.0 go.opentelemetry.io/otel/trace@v1.44.0 +go.opentelemetry.io/otel/metric@v1.44.0 gopkg.in/yaml.v3@v3.0.1 +go.opentelemetry.io/otel/metric@v1.44.0 go@1.25.0 +go.opentelemetry.io/otel/trace@v1.44.0 github.com/google/go-cmp@v0.7.0 +go.opentelemetry.io/otel/trace@v1.44.0 github.com/stretchr/testify@v1.11.1 +go.opentelemetry.io/otel/trace@v1.44.0 go.opentelemetry.io/otel@v1.44.0 +go.opentelemetry.io/otel/trace@v1.44.0 github.com/cespare/xxhash/v2@v2.3.0 +go.opentelemetry.io/otel/trace@v1.44.0 github.com/davecgh/go-spew@v1.1.1 +go.opentelemetry.io/otel/trace@v1.44.0 github.com/pmezard/go-difflib@v1.0.0 +go.opentelemetry.io/otel/trace@v1.44.0 gopkg.in/yaml.v3@v3.0.1 +go.opentelemetry.io/otel/trace@v1.44.0 go@1.25.0 +go.uber.org/multierr@v1.11.0 github.com/stretchr/testify@v1.7.0 +go.uber.org/multierr@v1.11.0 github.com/davecgh/go-spew@v1.1.1 +go.uber.org/multierr@v1.11.0 github.com/pmezard/go-difflib@v1.0.0 +go.uber.org/multierr@v1.11.0 gopkg.in/yaml.v3@v3.0.1 +go.uber.org/zap@v1.27.0 github.com/stretchr/testify@v1.8.1 +go.uber.org/zap@v1.27.0 go.uber.org/goleak@v1.3.0 +go.uber.org/zap@v1.27.0 go.uber.org/multierr@v1.10.0 +go.uber.org/zap@v1.27.0 gopkg.in/yaml.v3@v3.0.1 +go.uber.org/zap@v1.27.0 github.com/davecgh/go-spew@v1.1.1 +go.uber.org/zap@v1.27.0 github.com/kr/text@v0.2.0 +go.uber.org/zap@v1.27.0 github.com/pmezard/go-difflib@v1.0.0 +go.yaml.in/yaml/v2@v2.4.2 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 +golang.org/x/crypto@v0.56.0 golang.org/x/net@v0.57.0 +golang.org/x/crypto@v0.56.0 golang.org/x/sys@v0.47.0 +golang.org/x/crypto@v0.56.0 golang.org/x/term@v0.45.0 +golang.org/x/crypto@v0.56.0 golang.org/x/text@v0.41.0 +golang.org/x/crypto@v0.56.0 go@1.26.0 +golang.org/x/exp@v0.0.0-20221004215720-b9f4876ce741 github.com/google/go-cmp@v0.5.8 +golang.org/x/exp@v0.0.0-20221004215720-b9f4876ce741 golang.org/x/mod@v0.6.0-dev.0.20220419223038-86c51ed26bb4 +golang.org/x/exp@v0.0.0-20221004215720-b9f4876ce741 golang.org/x/tools@v0.1.12 +golang.org/x/exp@v0.0.0-20221004215720-b9f4876ce741 golang.org/x/sys@v0.0.0-20220722155257-8c9f86f7a55f +golang.org/x/mod@v0.40.0 golang.org/x/tools@v0.49.0 +golang.org/x/mod@v0.40.0 go@1.25.0 +golang.org/x/net@v0.58.0 golang.org/x/crypto@v0.55.0 +golang.org/x/net@v0.58.0 golang.org/x/sys@v0.47.0 +golang.org/x/net@v0.58.0 golang.org/x/term@v0.45.0 +golang.org/x/net@v0.58.0 golang.org/x/text@v0.41.0 +golang.org/x/net@v0.58.0 go@1.25.0 +golang.org/x/oauth2@v0.36.0 cloud.google.com/go/compute/metadata@v0.3.0 +golang.org/x/oauth2@v0.36.0 go@1.25.0 +golang.org/x/sync@v0.22.0 go@1.25.0 +golang.org/x/sys@v0.47.0 go@1.25.0 +golang.org/x/text@v0.41.0 golang.org/x/tools@v0.48.0 +golang.org/x/text@v0.41.0 golang.org/x/mod@v0.38.0 +golang.org/x/text@v0.41.0 golang.org/x/sync@v0.22.0 +golang.org/x/text@v0.41.0 go@1.25.0 +golang.org/x/time@v0.14.0 go@1.24.0 +golang.org/x/tools@v0.49.0 github.com/google/go-cmp@v0.6.0 +golang.org/x/tools@v0.49.0 github.com/yuin/goldmark@v1.4.13 +golang.org/x/tools@v0.49.0 golang.org/x/mod@v0.39.0 +golang.org/x/tools@v0.49.0 golang.org/x/net@v0.58.0 +golang.org/x/tools@v0.49.0 golang.org/x/sync@v0.22.0 +golang.org/x/tools@v0.49.0 golang.org/x/telemetry@v0.0.0-20260811182544-a038080d80e5 +golang.org/x/tools@v0.49.0 golang.org/x/sys@v0.47.0 +golang.org/x/tools@v0.49.0 go@1.25.0 +golang.org/x/tools/go/packages/packagestest@v0.1.1-deprecated golang.org/x/tools@v0.34.1-0.20250613162507-3f93fece84c7 +golang.org/x/tools/go/packages/packagestest@v0.1.1-deprecated golang.org/x/tools/go/expect@v0.1.0-deprecated +golang.org/x/tools/go/packages/packagestest@v0.1.1-deprecated golang.org/x/mod@v0.25.0 +golang.org/x/tools/go/packages/packagestest@v0.1.1-deprecated golang.org/x/sync@v0.15.0 +golang.org/x/tools/go/packages/packagestest@v0.1.1-deprecated go@1.23.0 +google.golang.org/api@v0.267.0 cloud.google.com/go/auth@v0.18.1 +google.golang.org/api@v0.267.0 cloud.google.com/go/auth/oauth2adapt@v0.2.8 +google.golang.org/api@v0.267.0 cloud.google.com/go/compute/metadata@v0.9.0 +google.golang.org/api@v0.267.0 github.com/google/go-cmp@v0.7.0 +google.golang.org/api@v0.267.0 github.com/google/s2a-go@v0.1.9 +google.golang.org/api@v0.267.0 github.com/google/uuid@v1.6.0 +google.golang.org/api@v0.267.0 github.com/googleapis/enterprise-certificate-proxy@v0.3.11 +google.golang.org/api@v0.267.0 github.com/googleapis/gax-go/v2@v2.17.0 +google.golang.org/api@v0.267.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc@v0.61.0 +google.golang.org/api@v0.267.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 +google.golang.org/api@v0.267.0 golang.org/x/net@v0.49.0 +google.golang.org/api@v0.267.0 golang.org/x/oauth2@v0.35.0 +google.golang.org/api@v0.267.0 golang.org/x/sync@v0.19.0 +google.golang.org/api@v0.267.0 golang.org/x/time@v0.14.0 +google.golang.org/api@v0.267.0 google.golang.org/genproto/googleapis/bytestream@v0.0.0-20260203192932-546029d2fa20 +google.golang.org/api@v0.267.0 google.golang.org/genproto/googleapis/rpc@v0.0.0-20260203192932-546029d2fa20 +google.golang.org/api@v0.267.0 google.golang.org/grpc@v1.78.0 +google.golang.org/api@v0.267.0 google.golang.org/protobuf@v1.36.11 +google.golang.org/api@v0.267.0 github.com/cespare/xxhash/v2@v2.3.0 +google.golang.org/api@v0.267.0 github.com/felixge/httpsnoop@v1.0.4 +google.golang.org/api@v0.267.0 github.com/go-logr/logr@v1.4.3 +google.golang.org/api@v0.267.0 github.com/go-logr/stdr@v1.2.2 +google.golang.org/api@v0.267.0 go.opentelemetry.io/auto/sdk@v1.2.1 +google.golang.org/api@v0.267.0 go.opentelemetry.io/otel@v1.39.0 +google.golang.org/api@v0.267.0 go.opentelemetry.io/otel/metric@v1.39.0 +google.golang.org/api@v0.267.0 go.opentelemetry.io/otel/trace@v1.39.0 +google.golang.org/api@v0.267.0 golang.org/x/crypto@v0.47.0 +google.golang.org/api@v0.267.0 golang.org/x/sys@v0.40.0 +google.golang.org/api@v0.267.0 golang.org/x/text@v0.33.0 +google.golang.org/api@v0.267.0 go@1.24.0 +google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa google.golang.org/genproto/googleapis/rpc@v0.0.0-20260523011958-0a33c5d7ca68 +google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa google.golang.org/grpc@v1.79.3 +google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa google.golang.org/protobuf@v1.36.11 +google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa golang.org/x/net@v0.48.0 +google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa golang.org/x/sys@v0.39.0 +google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa golang.org/x/text@v0.32.0 +google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa go@1.25.0 +google.golang.org/genproto/googleapis/rpc@v0.0.0-20260526163538-3dc84a4a5aaa google.golang.org/protobuf@v1.36.11 +google.golang.org/genproto/googleapis/rpc@v0.0.0-20260526163538-3dc84a4a5aaa go@1.25.0 +google.golang.org/grpc@v1.83.2 cloud.google.com/go/auth@v0.18.2 +google.golang.org/grpc@v1.83.2 cloud.google.com/go/compute/metadata@v0.9.0 +google.golang.org/grpc@v1.83.2 github.com/cespare/xxhash/v2@v2.3.0 +google.golang.org/grpc@v1.83.2 github.com/cncf/xds/go@v0.0.0-20260202195803-dba9d589def2 +google.golang.org/grpc@v1.83.2 github.com/envoyproxy/go-control-plane@v0.14.0 +google.golang.org/grpc@v1.83.2 github.com/envoyproxy/go-control-plane/envoy@v1.37.0 +google.golang.org/grpc@v1.83.2 github.com/golang/glog@v1.2.5 +google.golang.org/grpc@v1.83.2 github.com/golang/protobuf@v1.5.4 +google.golang.org/grpc@v1.83.2 github.com/google/go-cmp@v0.7.0 +google.golang.org/grpc@v1.83.2 github.com/google/uuid@v1.6.0 +google.golang.org/grpc@v1.83.2 github.com/spiffe/go-spiffe/v2@v2.7.0 +google.golang.org/grpc@v1.83.2 go.opentelemetry.io/contrib/detectors/gcp@v1.44.0 +google.golang.org/grpc@v1.83.2 go.opentelemetry.io/otel@v1.44.0 +google.golang.org/grpc@v1.83.2 go.opentelemetry.io/otel/metric@v1.44.0 +google.golang.org/grpc@v1.83.2 go.opentelemetry.io/otel/sdk@v1.44.0 +google.golang.org/grpc@v1.83.2 go.opentelemetry.io/otel/sdk/metric@v1.44.0 +google.golang.org/grpc@v1.83.2 go.opentelemetry.io/otel/trace@v1.44.0 +google.golang.org/grpc@v1.83.2 golang.org/x/net@v0.58.0 +google.golang.org/grpc@v1.83.2 golang.org/x/oauth2@v0.36.0 +google.golang.org/grpc@v1.83.2 golang.org/x/sync@v0.22.0 +google.golang.org/grpc@v1.83.2 golang.org/x/sys@v0.47.0 +google.golang.org/grpc@v1.83.2 gonum.org/v1/gonum@v0.17.0 +google.golang.org/grpc@v1.83.2 google.golang.org/genproto/googleapis/rpc@v0.0.0-20260526163538-3dc84a4a5aaa +google.golang.org/grpc@v1.83.2 google.golang.org/protobuf@v1.36.11 +google.golang.org/grpc@v1.83.2 cel.dev/expr@v0.25.2 +google.golang.org/grpc@v1.83.2 github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp@v1.33.0 +google.golang.org/grpc@v1.83.2 github.com/envoyproxy/go-control-plane/ratelimit@v0.1.0 +google.golang.org/grpc@v1.83.2 github.com/envoyproxy/protoc-gen-validate@v1.3.3 +google.golang.org/grpc@v1.83.2 github.com/felixge/httpsnoop@v1.0.4 +google.golang.org/grpc@v1.83.2 github.com/go-jose/go-jose/v4@v4.1.4 +google.golang.org/grpc@v1.83.2 github.com/go-logr/logr@v1.4.3 +google.golang.org/grpc@v1.83.2 github.com/go-logr/stdr@v1.2.2 +google.golang.org/grpc@v1.83.2 github.com/google/s2a-go@v0.1.9 +google.golang.org/grpc@v1.83.2 github.com/googleapis/enterprise-certificate-proxy@v0.3.11 +google.golang.org/grpc@v1.83.2 github.com/googleapis/gax-go/v2@v2.17.0 +google.golang.org/grpc@v1.83.2 github.com/planetscale/vtprotobuf@v0.6.1-0.20240319094008-0393e58bdf10 +google.golang.org/grpc@v1.83.2 go.opentelemetry.io/auto/sdk@v1.2.1 +google.golang.org/grpc@v1.83.2 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0 +google.golang.org/grpc@v1.83.2 golang.org/x/crypto@v0.55.0 +google.golang.org/grpc@v1.83.2 golang.org/x/text@v0.41.0 +google.golang.org/grpc@v1.83.2 google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa +google.golang.org/grpc@v1.83.2 go@1.25.0 +google.golang.org/protobuf@v1.36.11 github.com/golang/protobuf@v1.5.0 +google.golang.org/protobuf@v1.36.11 github.com/google/go-cmp@v0.7.0 +google.golang.org/protobuf@v1.36.11 go@1.23 +gopkg.in/yaml.v2@v2.4.0 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 +gopkg.in/yaml.v3@v3.0.1 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 +github.com/kr/pretty@v0.1.0 github.com/kr/text@v0.1.0 +github.com/stretchr/objx@v0.2.0 github.com/davecgh/go-spew@v1.1.1 +github.com/stretchr/objx@v0.2.0 github.com/stretchr/testify@v1.3.0 +github.com/stretchr/testify@v1.6.1 github.com/davecgh/go-spew@v1.1.0 +github.com/stretchr/testify@v1.6.1 github.com/pmezard/go-difflib@v1.0.0 +github.com/stretchr/testify@v1.6.1 github.com/stretchr/objx@v0.1.0 +github.com/stretchr/testify@v1.6.1 gopkg.in/yaml.v3@v3.0.0-20200313102051-9f266ea9e77c +github.com/kisielk/errcheck@v1.5.0 golang.org/x/tools@v0.0.0-20200619180055-7c47624df98f +golang.org/x/tools@v0.0.0-20210106214847-113979e3529a github.com/yuin/goldmark@v1.2.1 +golang.org/x/tools@v0.0.0-20210106214847-113979e3529a golang.org/x/mod@v0.3.0 +golang.org/x/tools@v0.0.0-20210106214847-113979e3529a golang.org/x/net@v0.0.0-20201021035429-f5854403a974 +golang.org/x/tools@v0.0.0-20210106214847-113979e3529a golang.org/x/sync@v0.0.0-20201020160332-67f06af15bc9 +golang.org/x/tools@v0.0.0-20210106214847-113979e3529a golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1 +github.com/kr/text@v0.1.0 github.com/kr/pty@v1.1.1 +github.com/cpuguy83/go-md2man/v2@v2.0.6 github.com/russross/blackfriday/v2@v2.1.0 +go.yaml.in/yaml/v3@v3.0.4 gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 +github.com/stretchr/testify@v1.3.0 github.com/davecgh/go-spew@v1.1.0 +github.com/stretchr/testify@v1.3.0 github.com/pmezard/go-difflib@v1.0.0 +github.com/stretchr/testify@v1.3.0 github.com/stretchr/objx@v0.1.0 +gopkg.in/yaml.v3@v3.0.0-20200313102051-9f266ea9e77c gopkg.in/check.v1@v0.0.0-20161208181325-20d25e280405 +golang.org/x/tools@v0.0.0-20200619180055-7c47624df98f github.com/yuin/goldmark@v1.1.27 +golang.org/x/tools@v0.0.0-20200619180055-7c47624df98f golang.org/x/mod@v0.2.0 +golang.org/x/tools@v0.0.0-20200619180055-7c47624df98f golang.org/x/net@v0.0.0-20200226121028-0de0cce0169b +golang.org/x/tools@v0.0.0-20200619180055-7c47624df98f golang.org/x/sync@v0.0.0-20190911185100-cd5d95a43a6e +golang.org/x/tools@v0.0.0-20200619180055-7c47624df98f golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 +golang.org/x/mod@v0.3.0 golang.org/x/crypto@v0.0.0-20191011191535-87dc89f01550 +golang.org/x/mod@v0.3.0 golang.org/x/tools@v0.0.0-20191119224855-298f0cb1881e +golang.org/x/mod@v0.3.0 golang.org/x/xerrors@v0.0.0-20191011141410-1b5146add898 +golang.org/x/net@v0.0.0-20201021035429-f5854403a974 golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9 +golang.org/x/net@v0.0.0-20201021035429-f5854403a974 golang.org/x/sys@v0.0.0-20200930185726-fdedc70b468f +golang.org/x/net@v0.0.0-20201021035429-f5854403a974 golang.org/x/text@v0.3.3 +golang.org/x/mod@v0.2.0 golang.org/x/crypto@v0.0.0-20191011191535-87dc89f01550 +golang.org/x/mod@v0.2.0 golang.org/x/tools@v0.0.0-20191119224855-298f0cb1881e +golang.org/x/mod@v0.2.0 golang.org/x/xerrors@v0.0.0-20191011141410-1b5146add898 +golang.org/x/net@v0.0.0-20200226121028-0de0cce0169b golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 +golang.org/x/net@v0.0.0-20200226121028-0de0cce0169b golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a +golang.org/x/net@v0.0.0-20200226121028-0de0cce0169b golang.org/x/text@v0.3.0 +golang.org/x/crypto@v0.0.0-20191011191535-87dc89f01550 golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 +golang.org/x/crypto@v0.0.0-20191011191535-87dc89f01550 golang.org/x/sys@v0.0.0-20190412213103-97732733099d +golang.org/x/tools@v0.0.0-20191119224855-298f0cb1881e golang.org/x/net@v0.0.0-20190620200207-3b0461eec859 +golang.org/x/tools@v0.0.0-20191119224855-298f0cb1881e golang.org/x/sync@v0.0.0-20190423024810-112230192c58 +golang.org/x/tools@v0.0.0-20191119224855-298f0cb1881e golang.org/x/xerrors@v0.0.0-20190717185122-a985d3407aa7 +golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9 golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 +golang.org/x/crypto@v0.0.0-20200622213623-75b288015ac9 golang.org/x/sys@v0.0.0-20190412213103-97732733099d +golang.org/x/text@v0.3.3 golang.org/x/tools@v0.0.0-20180917221912-90fa682c2a6e +golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a +golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 +golang.org/x/net@v0.0.0-20190404232315-eb5bcb51f2a3 golang.org/x/text@v0.3.0 +golang.org/x/net@v0.0.0-20190620200207-3b0461eec859 golang.org/x/crypto@v0.0.0-20190308221718-c2843e01d9a2 +golang.org/x/net@v0.0.0-20190620200207-3b0461eec859 golang.org/x/sys@v0.0.0-20190215142949-d0b11bdaac8a +golang.org/x/net@v0.0.0-20190620200207-3b0461eec859 golang.org/x/text@v0.3.0 diff --git a/bridge/idp/locks/generated/inputs.lock b/bridge/idp/locks/generated/inputs.lock new file mode 100644 index 00000000..8f0a8db2 --- /dev/null +++ b/bridge/idp/locks/generated/inputs.lock @@ -0,0 +1,6 @@ +# Public, immutable shell assignments; never source an unreviewed generated file. +DEX_COMMIT=11d2eeb52b42e1980e14cb91e69dd9e3faab2076 +DEX_ARCHIVE_SHA256=18bf92e8ccbf53e86814c2beb39b7d59f28fb07c84639e9f47a9bb5ea764e0b9 +DEX_VERSION=v2.45.1-kars.1 +GO_VERSION=go1.26.8 +SOURCE_DATE_EPOCH=0 diff --git a/bridge/idp/locks/generated/modules.json b/bridge/idp/locks/generated/modules.json new file mode 100644 index 00000000..b6c5638f --- /dev/null +++ b/bridge/idp/locks/generated/modules.json @@ -0,0 +1,2028 @@ +{ + "Path": "github.com/dexidp/dex", + "Main": true, + "Dir": "/src/dex", + "GoMod": "/src/dex/go.mod", + "GoVersion": "1.26.0" +} +{ + "Path": "ariga.io/atlas", + "Version": "v0.32.1-0.20250325101103-175b25e1c1b9", + "Time": "2025-03-25T10:11:03Z", + "Indirect": true, + "Dir": "/work/mod/ariga.io/atlas@v0.32.1-0.20250325101103-175b25e1c1b9", + "GoMod": "/work/mod/cache/download/ariga.io/atlas/@v/v0.32.1-0.20250325101103-175b25e1c1b9.mod", + "GoVersion": "1.22.12", + "Sum": "h1:E0wvcUXTkgyN4wy4LGtNzMNGMytJN8afmIWXJVMi4cc=", + "GoModSum": "h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w=" +} +{ + "Path": "cel.dev/expr", + "Version": "v0.25.2", + "Time": "2026-03-12T16:46:44Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/cel.dev/expr/@v/v0.25.2.mod", + "GoVersion": "1.23.0" +} +{ + "Path": "cloud.google.com/go", + "Version": "v0.112.2", + "Time": "2024-03-27T20:20:16Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/cloud.google.com/go/@v/v0.112.2.mod", + "GoVersion": "1.19" +} +{ + "Path": "cloud.google.com/go/auth", + "Version": "v0.18.2", + "Time": "2026-02-13T17:14:27Z", + "Indirect": true, + "Dir": "/work/mod/cloud.google.com/go/auth@v0.18.2", + "GoMod": "/work/mod/cache/download/cloud.google.com/go/auth/@v/v0.18.2.mod", + "GoVersion": "1.24.0", + "Sum": "h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=", + "GoModSum": "h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M=" +} +{ + "Path": "cloud.google.com/go/auth/oauth2adapt", + "Version": "v0.2.8", + "Time": "2025-03-20T15:18:21Z", + "Indirect": true, + "Dir": "/work/mod/cloud.google.com/go/auth/oauth2adapt@v0.2.8", + "GoMod": "/work/mod/cache/download/cloud.google.com/go/auth/oauth2adapt/@v/v0.2.8.mod", + "GoVersion": "1.23.0", + "Sum": "h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=", + "GoModSum": "h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=" +} +{ + "Path": "cloud.google.com/go/compute/metadata", + "Version": "v0.9.0", + "Time": "2025-09-24T19:41:55Z", + "Dir": "/work/mod/cloud.google.com/go/compute/metadata@v0.9.0", + "GoMod": "/work/mod/cache/download/cloud.google.com/go/compute/metadata/@v/v0.9.0.mod", + "GoVersion": "1.24.0", + "Sum": "h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=", + "GoModSum": "h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=" +} +{ + "Path": "cloud.google.com/go/longrunning", + "Version": "v0.5.6", + "Time": "2024-03-14T21:02:19Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/cloud.google.com/go/longrunning/@v/v0.5.6.mod", + "GoVersion": "1.19" +} +{ + "Path": "cloud.google.com/go/translate", + "Version": "v1.10.3", + "Time": "2024-05-01T18:24:19Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/cloud.google.com/go/translate/@v/v1.10.3.mod", + "GoVersion": "1.19" +} +{ + "Path": "dario.cat/mergo", + "Version": "v1.0.1", + "Time": "2024-08-17T20:16:10Z", + "Indirect": true, + "Dir": "/work/mod/dario.cat/mergo@v1.0.1", + "GoMod": "/work/mod/cache/download/dario.cat/mergo/@v/v1.0.1.mod", + "GoVersion": "1.13", + "Sum": "h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=", + "GoModSum": "h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=" +} +{ + "Path": "entgo.io/ent", + "Version": "v0.14.5", + "Time": "2025-07-21T09:33:06Z", + "Dir": "/work/mod/entgo.io/ent@v0.14.5", + "GoMod": "/work/mod/cache/download/entgo.io/ent/@v/v0.14.5.mod", + "GoVersion": "1.23", + "Sum": "h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4=", + "GoModSum": "h1:zTzLmWtPvGpmSwtkaayM2cm5m819NdM7z7tYPq3vN0U=" +} +{ + "Path": "filippo.io/edwards25519", + "Version": "v1.1.1", + "Time": "2026-02-17T16:50:01Z", + "Indirect": true, + "Dir": "/work/mod/filippo.io/edwards25519@v1.1.1", + "GoMod": "/work/mod/cache/download/filippo.io/edwards25519/@v/v1.1.1.mod", + "GoVersion": "1.20", + "Sum": "h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=", + "GoModSum": "h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=" +} +{ + "Path": "github.com/AppsFlyer/go-sundheit", + "Version": "v0.6.0", + "Time": "2024-07-25T06:35:08Z", + "Dir": "/work/mod/github.com/!apps!flyer/go-sundheit@v0.6.0", + "GoMod": "/work/mod/cache/download/github.com/!apps!flyer/go-sundheit/@v/v0.6.0.mod", + "GoVersion": "1.15", + "Sum": "h1:d2hBvCjBSb2lUsEWGfPigr4MCOt04sxB+Rppl0yUMSk=", + "GoModSum": "h1:LDdBHD6tQBtmHsdW+i1GwdTt6Wqc0qazf5ZEJVTbTME=" +} +{ + "Path": "github.com/Azure/go-ntlmssp", + "Version": "v0.0.0-20221128193559-754e69321358", + "Time": "2022-11-28T19:35:59Z", + "Indirect": true, + "Dir": "/work/mod/github.com/!azure/go-ntlmssp@v0.0.0-20221128193559-754e69321358", + "GoMod": "/work/mod/cache/download/github.com/!azure/go-ntlmssp/@v/v0.0.0-20221128193559-754e69321358.mod", + "Sum": "h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=", + "GoModSum": "h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=" +} +{ + "Path": "github.com/DATA-DOG/go-sqlmock", + "Version": "v1.5.0", + "Time": "2020-06-28T15:11:42Z", + "Indirect": true, + "Dir": "/work/mod/github.com/!d!a!t!a-!d!o!g/go-sqlmock@v1.5.0", + "GoMod": "/work/mod/cache/download/github.com/!d!a!t!a-!d!o!g/go-sqlmock/@v/v1.5.0.mod", + "Sum": "h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=", + "GoModSum": "h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=" +} +{ + "Path": "github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp", + "Version": "v1.33.0", + "Time": "2026-06-04T20:21:43Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/!google!cloud!platform/opentelemetry-operations-go/detectors/gcp/@v/v1.33.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "github.com/Masterminds/goutils", + "Version": "v1.1.1", + "Time": "2021-02-04T20:06:53Z", + "Indirect": true, + "Dir": "/work/mod/github.com/!masterminds/goutils@v1.1.1", + "GoMod": "/work/mod/cache/download/github.com/!masterminds/goutils/@v/v1.1.1.mod", + "Sum": "h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=", + "GoModSum": "h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=" +} +{ + "Path": "github.com/Masterminds/semver", + "Version": "v1.5.0", + "Time": "2019-09-11T18:23:18Z", + "Dir": "/work/mod/github.com/!masterminds/semver@v1.5.0", + "GoMod": "/work/mod/cache/download/github.com/!masterminds/semver/@v/v1.5.0.mod", + "Sum": "h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=", + "GoModSum": "h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=" +} +{ + "Path": "github.com/Masterminds/semver/v3", + "Version": "v3.3.0", + "Time": "2024-08-27T21:33:28Z", + "Indirect": true, + "Dir": "/work/mod/github.com/!masterminds/semver/v3@v3.3.0", + "GoMod": "/work/mod/cache/download/github.com/!masterminds/semver/v3/@v/v3.3.0.mod", + "GoVersion": "1.21", + "Sum": "h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=", + "GoModSum": "h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=" +} +{ + "Path": "github.com/Masterminds/sprig/v3", + "Version": "v3.3.0", + "Time": "2024-08-29T20:12:44Z", + "Dir": "/work/mod/github.com/!masterminds/sprig/v3@v3.3.0", + "GoMod": "/work/mod/cache/download/github.com/!masterminds/sprig/v3/@v/v3.3.0.mod", + "GoVersion": "1.21", + "Sum": "h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=", + "GoModSum": "h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=" +} +{ + "Path": "github.com/agext/levenshtein", + "Version": "v1.2.3", + "Time": "2020-03-12T21:09:59Z", + "Indirect": true, + "Dir": "/work/mod/github.com/agext/levenshtein@v1.2.3", + "GoMod": "/work/mod/cache/download/github.com/agext/levenshtein/@v/v1.2.3.mod", + "Sum": "h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=", + "GoModSum": "h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=" +} +{ + "Path": "github.com/alecthomas/kingpin/v2", + "Version": "v2.4.0", + "Time": "2023-09-30T22:59:49Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/alecthomas/kingpin/v2/@v/v2.4.0.mod", + "GoVersion": "1.17" +} +{ + "Path": "github.com/alecthomas/units", + "Version": "v0.0.0-20211218093645-b94a6e3cc137", + "Time": "2021-12-18T09:36:45Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/alecthomas/units/@v/v0.0.0-20211218093645-b94a6e3cc137.mod", + "GoVersion": "1.15" +} +{ + "Path": "github.com/alexbrainman/sspi", + "Version": "v0.0.0-20250919150558-7d374ff0d59e", + "Time": "2025-09-19T15:05:58Z", + "Indirect": true, + "Dir": "/work/mod/github.com/alexbrainman/sspi@v0.0.0-20250919150558-7d374ff0d59e", + "GoMod": "/work/mod/cache/download/github.com/alexbrainman/sspi/@v/v0.0.0-20250919150558-7d374ff0d59e.mod", + "GoVersion": "1.13", + "Sum": "h1:4dAU9FXIyQktpoUAgOJK3OTFc/xug0PCXYCqU0FgDKI=", + "GoModSum": "h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=" +} +{ + "Path": "github.com/antihax/optional", + "Version": "v1.0.0", + "Time": "2019-10-10T23:37:20Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/antihax/optional/@v/v1.0.0.mod", + "GoVersion": "1.13" +} +{ + "Path": "github.com/apparentlymart/go-dump", + "Version": "v0.0.0-20180507223929-23540a00eaa3", + "Time": "2018-05-07T22:39:29Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/apparentlymart/go-dump/@v/v0.0.0-20180507223929-23540a00eaa3.mod" +} +{ + "Path": "github.com/apparentlymart/go-textseg/v13", + "Version": "v13.0.0", + "Time": "2021-02-22T23:45:06Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/apparentlymart/go-textseg/v13/@v/v13.0.0.mod", + "GoVersion": "1.16" +} +{ + "Path": "github.com/apparentlymart/go-textseg/v15", + "Version": "v15.0.0", + "Time": "2023-08-29T15:35:34Z", + "Indirect": true, + "Dir": "/work/mod/github.com/apparentlymart/go-textseg/v15@v15.0.0", + "GoMod": "/work/mod/cache/download/github.com/apparentlymart/go-textseg/v15/@v/v15.0.0.mod", + "GoVersion": "1.16", + "Sum": "h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=", + "GoModSum": "h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=" +} +{ + "Path": "github.com/armon/go-radix", + "Version": "v0.0.0-20180808171621-7fddfc383310", + "Time": "2018-08-08T17:16:21Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/armon/go-radix/@v/v0.0.0-20180808171621-7fddfc383310.mod" +} +{ + "Path": "github.com/beevik/etree", + "Version": "v1.6.0", + "Time": "2025-08-22T22:58:11Z", + "Dir": "/work/mod/github.com/beevik/etree@v1.6.0", + "GoMod": "/work/mod/cache/download/github.com/beevik/etree/@v/v1.6.0.mod", + "GoVersion": "1.23.0", + "Sum": "h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE=", + "GoModSum": "h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc=" +} +{ + "Path": "github.com/beorn7/perks", + "Version": "v1.0.1", + "Time": "2019-07-31T12:00:54Z", + "Indirect": true, + "Dir": "/work/mod/github.com/beorn7/perks@v1.0.1", + "GoMod": "/work/mod/cache/download/github.com/beorn7/perks/@v/v1.0.1.mod", + "GoVersion": "1.11", + "Sum": "h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=", + "GoModSum": "h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=" +} +{ + "Path": "github.com/bgentry/speakeasy", + "Version": "v0.1.0", + "Time": "2017-04-17T20:07:03Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/bgentry/speakeasy/@v/v0.1.0.mod" +} +{ + "Path": "github.com/bmatcuk/doublestar", + "Version": "v1.3.4", + "Time": "2020-11-19T00:35:16Z", + "Indirect": true, + "Dir": "/work/mod/github.com/bmatcuk/doublestar@v1.3.4", + "GoMod": "/work/mod/cache/download/github.com/bmatcuk/doublestar/@v/v1.3.4.mod", + "GoVersion": "1.12", + "Sum": "h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=", + "GoModSum": "h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=" +} +{ + "Path": "github.com/cenkalti/backoff/v4", + "Version": "v4.3.0", + "Time": "2024-01-02T22:56:19Z", + "Indirect": true, + "Dir": "/work/mod/github.com/cenkalti/backoff/v4@v4.3.0", + "GoMod": "/work/mod/cache/download/github.com/cenkalti/backoff/v4/@v/v4.3.0.mod", + "GoVersion": "1.18", + "Sum": "h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=", + "GoModSum": "h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=" +} +{ + "Path": "github.com/cespare/xxhash/v2", + "Version": "v2.3.0", + "Time": "2024-04-04T20:00:10Z", + "Indirect": true, + "Dir": "/work/mod/github.com/cespare/xxhash/v2@v2.3.0", + "GoMod": "/work/mod/cache/download/github.com/cespare/xxhash/v2/@v/v2.3.0.mod", + "GoVersion": "1.11", + "Sum": "h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=", + "GoModSum": "h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=" +} +{ + "Path": "github.com/cncf/xds/go", + "Version": "v0.0.0-20260202195803-dba9d589def2", + "Time": "2026-02-02T19:58:03Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/cncf/xds/go/@v/v0.0.0-20260202195803-dba9d589def2.mod", + "GoVersion": "1.24.6" +} +{ + "Path": "github.com/coreos/go-oidc/v3", + "Version": "v3.17.0", + "Time": "2025-11-21T03:32:42Z", + "Dir": "/work/mod/github.com/coreos/go-oidc/v3@v3.17.0", + "GoMod": "/work/mod/cache/download/github.com/coreos/go-oidc/v3/@v/v3.17.0.mod", + "GoVersion": "1.24.0", + "Sum": "h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=", + "GoModSum": "h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=" +} +{ + "Path": "github.com/coreos/go-semver", + "Version": "v0.3.1", + "Time": "2023-01-16T22:04:39Z", + "Indirect": true, + "Dir": "/work/mod/github.com/coreos/go-semver@v0.3.1", + "GoMod": "/work/mod/cache/download/github.com/coreos/go-semver/@v/v0.3.1.mod", + "GoVersion": "1.8", + "Sum": "h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=", + "GoModSum": "h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=" +} +{ + "Path": "github.com/coreos/go-systemd/v22", + "Version": "v22.5.0", + "Time": "2022-11-07T13:52:27Z", + "Indirect": true, + "Dir": "/work/mod/github.com/coreos/go-systemd/v22@v22.5.0", + "GoMod": "/work/mod/cache/download/github.com/coreos/go-systemd/v22/@v/v22.5.0.mod", + "GoVersion": "1.12", + "Sum": "h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=", + "GoModSum": "h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=" +} +{ + "Path": "github.com/cpuguy83/go-md2man/v2", + "Version": "v2.0.6", + "Time": "2024-12-16T17:50:50Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/cpuguy83/go-md2man/v2/@v/v2.0.6.mod", + "GoVersion": "1.12", + "GoModSum": "h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=" +} +{ + "Path": "github.com/davecgh/go-spew", + "Version": "v1.1.2-0.20180830191138-d8f796af33cc", + "Time": "2018-08-30T19:11:38Z", + "Indirect": true, + "Dir": "/work/mod/github.com/davecgh/go-spew@v1.1.2-0.20180830191138-d8f796af33cc", + "GoMod": "/work/mod/cache/download/github.com/davecgh/go-spew/@v/v1.1.2-0.20180830191138-d8f796af33cc.mod", + "Sum": "h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=", + "GoModSum": "h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=" +} +{ + "Path": "github.com/dexidp/dex/api/v2", + "Version": "v2.4.0", + "Replace": { + "Path": "./api/v2", + "Dir": "/src/dex/api/v2", + "GoMod": "/src/dex/api/v2/go.mod", + "GoVersion": "1.26.0" + }, + "Dir": "/src/dex/api/v2", + "GoMod": "/src/dex/api/v2/go.mod", + "GoVersion": "1.26.0" +} +{ + "Path": "github.com/dustin/go-humanize", + "Version": "v1.0.1", + "Time": "2023-01-10T06:44:38Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/dustin/go-humanize/@v/v1.0.1.mod", + "GoVersion": "1.16" +} +{ + "Path": "github.com/envoyproxy/go-control-plane", + "Version": "v0.14.0", + "Time": "2025-11-04T22:01:44Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/envoyproxy/go-control-plane/@v/v0.14.0.mod", + "GoVersion": "1.23.0" +} +{ + "Path": "github.com/envoyproxy/go-control-plane/envoy", + "Version": "v1.37.0", + "Time": "2026-01-13T06:26:49Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/envoyproxy/go-control-plane/envoy/@v/v1.37.0.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "github.com/envoyproxy/go-control-plane/ratelimit", + "Version": "v0.1.0", + "Time": "2024-12-23T15:25:59Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/envoyproxy/go-control-plane/ratelimit/@v/v0.1.0.mod", + "GoVersion": "1.21" +} +{ + "Path": "github.com/envoyproxy/protoc-gen-validate", + "Version": "v1.3.3", + "Time": "2026-02-18T16:13:16Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/envoyproxy/protoc-gen-validate/@v/v1.3.3.mod", + "GoVersion": "1.24.1" +} +{ + "Path": "github.com/fatih/color", + "Version": "v1.18.0", + "Time": "2024-10-03T07:06:28Z", + "Indirect": true, + "Dir": "/work/mod/github.com/fatih/color@v1.18.0", + "GoMod": "/work/mod/cache/download/github.com/fatih/color/@v/v1.18.0.mod", + "GoVersion": "1.17", + "Sum": "h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=", + "GoModSum": "h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=" +} +{ + "Path": "github.com/felixge/httpsnoop", + "Version": "v1.0.4", + "Time": "2023-03-12T10:31:09Z", + "Indirect": true, + "Dir": "/work/mod/github.com/felixge/httpsnoop@v1.0.4", + "GoMod": "/work/mod/cache/download/github.com/felixge/httpsnoop/@v/v1.0.4.mod", + "GoVersion": "1.13", + "Sum": "h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=", + "GoModSum": "h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=" +} +{ + "Path": "github.com/fortytw2/leaktest", + "Version": "v1.3.0", + "Time": "2018-11-09T15:15:30Z", + "Indirect": true, + "Dir": "/work/mod/github.com/fortytw2/leaktest@v1.3.0", + "GoMod": "/work/mod/cache/download/github.com/fortytw2/leaktest/@v/v1.3.0.mod", + "Sum": "h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=", + "GoModSum": "h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=" +} +{ + "Path": "github.com/frankban/quicktest", + "Version": "v1.14.6", + "Time": "2023-08-01T06:27:26Z", + "Indirect": true, + "Dir": "/work/mod/github.com/frankban/quicktest@v1.14.6", + "GoMod": "/work/mod/cache/download/github.com/frankban/quicktest/@v/v1.14.6.mod", + "GoVersion": "1.13", + "Sum": "h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=", + "GoModSum": "h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=" +} +{ + "Path": "github.com/fsnotify/fsnotify", + "Version": "v1.9.0", + "Time": "2025-04-04T15:13:49Z", + "Dir": "/work/mod/github.com/fsnotify/fsnotify@v1.9.0", + "GoMod": "/work/mod/cache/download/github.com/fsnotify/fsnotify/@v/v1.9.0.mod", + "GoVersion": "1.17", + "Sum": "h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=", + "GoModSum": "h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=" +} +{ + "Path": "github.com/ghodss/yaml", + "Version": "v1.0.0", + "Time": "2017-03-27T23:54:44Z", + "Dir": "/work/mod/github.com/ghodss/yaml@v1.0.0", + "GoMod": "/work/mod/cache/download/github.com/ghodss/yaml/@v/v1.0.0.mod", + "Sum": "h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=", + "GoModSum": "h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=" +} +{ + "Path": "github.com/go-asn1-ber/asn1-ber", + "Version": "v1.5.8-0.20250403174932-29230038a667", + "Time": "2025-04-03T17:49:32Z", + "Indirect": true, + "Dir": "/work/mod/github.com/go-asn1-ber/asn1-ber@v1.5.8-0.20250403174932-29230038a667", + "GoMod": "/work/mod/cache/download/github.com/go-asn1-ber/asn1-ber/@v/v1.5.8-0.20250403174932-29230038a667.mod", + "GoVersion": "1.13", + "Sum": "h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=", + "GoModSum": "h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=" +} +{ + "Path": "github.com/go-jose/go-jose/v4", + "Version": "v4.1.4", + "Time": "2026-03-31T23:33:50Z", + "Dir": "/work/mod/github.com/go-jose/go-jose/v4@v4.1.4", + "GoMod": "/work/mod/cache/download/github.com/go-jose/go-jose/v4/@v/v4.1.4.mod", + "GoVersion": "1.24.0", + "Sum": "h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=", + "GoModSum": "h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=" +} +{ + "Path": "github.com/go-ldap/ldap/v3", + "Version": "v3.4.12", + "Time": "2025-10-01T13:57:01Z", + "Dir": "/work/mod/github.com/go-ldap/ldap/v3@v3.4.12", + "GoMod": "/work/mod/cache/download/github.com/go-ldap/ldap/v3/@v/v3.4.12.mod", + "GoVersion": "1.23.0", + "Sum": "h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4=", + "GoModSum": "h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo=" +} +{ + "Path": "github.com/go-logr/logr", + "Version": "v1.4.3", + "Time": "2025-05-19T04:56:57Z", + "Indirect": true, + "Dir": "/work/mod/github.com/go-logr/logr@v1.4.3", + "GoMod": "/work/mod/cache/download/github.com/go-logr/logr/@v/v1.4.3.mod", + "GoVersion": "1.18", + "Sum": "h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=", + "GoModSum": "h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=" +} +{ + "Path": "github.com/go-logr/stdr", + "Version": "v1.2.2", + "Time": "2021-12-14T08:00:35Z", + "Indirect": true, + "Dir": "/work/mod/github.com/go-logr/stdr@v1.2.2", + "GoMod": "/work/mod/cache/download/github.com/go-logr/stdr/@v/v1.2.2.mod", + "GoVersion": "1.16", + "Sum": "h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=", + "GoModSum": "h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=" +} +{ + "Path": "github.com/go-openapi/inflect", + "Version": "v0.19.0", + "Time": "2018-10-07T00:18:42Z", + "Indirect": true, + "Dir": "/work/mod/github.com/go-openapi/inflect@v0.19.0", + "GoMod": "/work/mod/cache/download/github.com/go-openapi/inflect/@v/v0.19.0.mod", + "Sum": "h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=", + "GoModSum": "h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=" +} +{ + "Path": "github.com/go-sql-driver/mysql", + "Version": "v1.9.3", + "Time": "2025-06-13T06:20:32Z", + "Dir": "/work/mod/github.com/go-sql-driver/mysql@v1.9.3", + "GoMod": "/work/mod/cache/download/github.com/go-sql-driver/mysql/@v/v1.9.3.mod", + "GoVersion": "1.21.0", + "Sum": "h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=", + "GoModSum": "h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=" +} +{ + "Path": "github.com/go-test/deep", + "Version": "v1.1.1", + "Time": "2024-06-23T16:27:23Z", + "Indirect": true, + "Dir": "/work/mod/github.com/go-test/deep@v1.1.1", + "GoMod": "/work/mod/cache/download/github.com/go-test/deep/@v/v1.1.1.mod", + "GoVersion": "1.16", + "Sum": "h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=", + "GoModSum": "h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=" +} +{ + "Path": "github.com/go-viper/mapstructure/v2", + "Version": "v2.4.0", + "Time": "2025-07-15T08:59:08Z", + "Indirect": true, + "Dir": "/work/mod/github.com/go-viper/mapstructure/v2@v2.4.0", + "GoMod": "/work/mod/cache/download/github.com/go-viper/mapstructure/v2/@v/v2.4.0.mod", + "GoVersion": "1.18", + "Sum": "h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=", + "GoModSum": "h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=" +} +{ + "Path": "github.com/godbus/dbus/v5", + "Version": "v5.0.4", + "Time": "2021-03-23T03:10:11Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/godbus/dbus/v5/@v/v5.0.4.mod", + "GoVersion": "1.12", + "GoModSum": "h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=" +} +{ + "Path": "github.com/gogo/protobuf", + "Version": "v1.3.2", + "Time": "2021-01-10T08:01:47Z", + "Indirect": true, + "Dir": "/work/mod/github.com/gogo/protobuf@v1.3.2", + "GoMod": "/work/mod/cache/download/github.com/gogo/protobuf/@v/v1.3.2.mod", + "GoVersion": "1.15", + "Sum": "h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=", + "GoModSum": "h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=" +} +{ + "Path": "github.com/golang/glog", + "Version": "v1.2.5", + "Time": "2025-04-29T08:43:26Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/golang/glog/@v/v1.2.5.mod", + "GoVersion": "1.19" +} +{ + "Path": "github.com/golang/groupcache", + "Version": "v0.0.0-20210331224755-41bb18bfe9da", + "Time": "2021-03-31T22:47:55Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/golang/groupcache/@v/v0.0.0-20210331224755-41bb18bfe9da.mod" +} +{ + "Path": "github.com/golang/protobuf", + "Version": "v1.5.4", + "Time": "2024-03-06T06:45:40Z", + "Indirect": true, + "Dir": "/work/mod/github.com/golang/protobuf@v1.5.4", + "GoMod": "/work/mod/cache/download/github.com/golang/protobuf/@v/v1.5.4.mod", + "GoVersion": "1.17", + "Sum": "h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=", + "GoModSum": "h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=" +} +{ + "Path": "github.com/google/go-cmp", + "Version": "v0.7.0", + "Time": "2025-01-14T18:15:44Z", + "Indirect": true, + "Dir": "/work/mod/github.com/google/go-cmp@v0.7.0", + "GoMod": "/work/mod/cache/download/github.com/google/go-cmp/@v/v0.7.0.mod", + "GoVersion": "1.21", + "Sum": "h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=", + "GoModSum": "h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=" +} +{ + "Path": "github.com/google/go-pkcs11", + "Version": "v0.3.0", + "Time": "2023-09-07T21:50:43Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/google/go-pkcs11/@v/v0.3.0.mod", + "GoVersion": "1.17" +} +{ + "Path": "github.com/google/s2a-go", + "Version": "v0.1.9", + "Time": "2025-01-06T17:53:46Z", + "Indirect": true, + "Dir": "/work/mod/github.com/google/s2a-go@v0.1.9", + "GoMod": "/work/mod/cache/download/github.com/google/s2a-go/@v/v0.1.9.mod", + "GoVersion": "1.20", + "Sum": "h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=", + "GoModSum": "h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=" +} +{ + "Path": "github.com/google/uuid", + "Version": "v1.6.0", + "Time": "2024-01-23T18:54:04Z", + "Dir": "/work/mod/github.com/google/uuid@v1.6.0", + "GoMod": "/work/mod/cache/download/github.com/google/uuid/@v/v1.6.0.mod", + "Sum": "h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=", + "GoModSum": "h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=" +} +{ + "Path": "github.com/googleapis/enterprise-certificate-proxy", + "Version": "v0.3.11", + "Time": "2026-01-13T07:11:36Z", + "Indirect": true, + "Dir": "/work/mod/github.com/googleapis/enterprise-certificate-proxy@v0.3.11", + "GoMod": "/work/mod/cache/download/github.com/googleapis/enterprise-certificate-proxy/@v/v0.3.11.mod", + "GoVersion": "1.24.0", + "Sum": "h1:vAe81Msw+8tKUxi2Dqh/NZMz7475yUvmRIkXr4oN2ao=", + "GoModSum": "h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8=" +} +{ + "Path": "github.com/googleapis/gax-go/v2", + "Version": "v2.17.0", + "Time": "2026-02-03T18:41:38Z", + "Indirect": true, + "Dir": "/work/mod/github.com/googleapis/gax-go/v2@v2.17.0", + "GoMod": "/work/mod/cache/download/github.com/googleapis/gax-go/v2/@v/v2.17.0.mod", + "GoVersion": "1.24.0", + "Sum": "h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc=", + "GoModSum": "h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY=" +} +{ + "Path": "github.com/gorilla/handlers", + "Version": "v1.5.2", + "Time": "2023-10-18T11:25:31Z", + "Dir": "/work/mod/github.com/gorilla/handlers@v1.5.2", + "GoMod": "/work/mod/cache/download/github.com/gorilla/handlers/@v/v1.5.2.mod", + "GoVersion": "1.20", + "Sum": "h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=", + "GoModSum": "h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=" +} +{ + "Path": "github.com/gorilla/mux", + "Version": "v1.8.1", + "Time": "2023-10-18T11:23:00Z", + "Dir": "/work/mod/github.com/gorilla/mux@v1.8.1", + "GoMod": "/work/mod/cache/download/github.com/gorilla/mux/@v/v1.8.1.mod", + "GoVersion": "1.20", + "Sum": "h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=", + "GoModSum": "h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=" +} +{ + "Path": "github.com/gorilla/websocket", + "Version": "v1.5.0", + "Time": "2022-01-04T01:59:52Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/gorilla/websocket/@v/v1.5.0.mod", + "GoVersion": "1.12" +} +{ + "Path": "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus", + "Version": "v1.0.1", + "Time": "2024-04-25T04:50:13Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/@v/v1.0.1.mod", + "GoVersion": "1.19" +} +{ + "Path": "github.com/grpc-ecosystem/go-grpc-middleware/v2", + "Version": "v2.1.0", + "Time": "2024-02-22T15:43:25Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/grpc-ecosystem/go-grpc-middleware/v2/@v/v2.1.0.mod", + "GoVersion": "1.19" +} +{ + "Path": "github.com/grpc-ecosystem/go-grpc-prometheus", + "Version": "v1.2.0", + "Time": "2018-06-04T12:28:56Z", + "Dir": "/work/mod/github.com/grpc-ecosystem/go-grpc-prometheus@v1.2.0", + "GoMod": "/work/mod/cache/download/github.com/grpc-ecosystem/go-grpc-prometheus/@v/v1.2.0.mod", + "Sum": "h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=", + "GoModSum": "h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=" +} +{ + "Path": "github.com/grpc-ecosystem/grpc-gateway/v2", + "Version": "v2.26.3", + "Time": "2025-03-04T17:40:45Z", + "Indirect": true, + "Dir": "/work/mod/github.com/grpc-ecosystem/grpc-gateway/v2@v2.26.3", + "GoMod": "/work/mod/cache/download/github.com/grpc-ecosystem/grpc-gateway/v2/@v/v2.26.3.mod", + "GoVersion": "1.23.0", + "Sum": "h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=", + "GoModSum": "h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=" +} +{ + "Path": "github.com/hashicorp/errwrap", + "Version": "v1.1.0", + "Time": "2020-07-14T15:51:01Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/errwrap@v1.1.0", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/errwrap/@v/v1.1.0.mod", + "Sum": "h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=", + "GoModSum": "h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=" +} +{ + "Path": "github.com/hashicorp/go-cleanhttp", + "Version": "v0.5.2", + "Time": "2021-02-03T18:51:13Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/go-cleanhttp@v0.5.2", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/go-cleanhttp/@v/v0.5.2.mod", + "GoVersion": "1.13", + "Sum": "h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=", + "GoModSum": "h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=" +} +{ + "Path": "github.com/hashicorp/go-hclog", + "Version": "v1.6.3", + "Time": "2024-04-01T20:03:54Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/go-hclog@v1.6.3", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/go-hclog/@v/v1.6.3.mod", + "GoVersion": "1.13", + "Sum": "h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=", + "GoModSum": "h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=" +} +{ + "Path": "github.com/hashicorp/go-multierror", + "Version": "v1.1.1", + "Time": "2021-03-11T20:17:12Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/go-multierror@v1.1.1", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/go-multierror/@v/v1.1.1.mod", + "GoVersion": "1.13", + "Sum": "h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=", + "GoModSum": "h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=" +} +{ + "Path": "github.com/hashicorp/go-retryablehttp", + "Version": "v0.7.8", + "Time": "2025-06-18T14:25:10Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/go-retryablehttp@v0.7.8", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/go-retryablehttp/@v/v0.7.8.mod", + "GoVersion": "1.23", + "Sum": "h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=", + "GoModSum": "h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=" +} +{ + "Path": "github.com/hashicorp/go-secure-stdlib/parseutil", + "Version": "v0.2.0", + "Time": "2025-03-06T22:34:24Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/go-secure-stdlib/parseutil@v0.2.0", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/go-secure-stdlib/parseutil/@v/v0.2.0.mod", + "GoVersion": "1.20", + "Sum": "h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM=", + "GoModSum": "h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0=" +} +{ + "Path": "github.com/hashicorp/go-secure-stdlib/strutil", + "Version": "v0.1.2", + "Time": "2021-11-22T19:44:14Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/go-secure-stdlib/strutil@v0.1.2", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/go-secure-stdlib/strutil/@v/v0.1.2.mod", + "GoVersion": "1.16", + "Sum": "h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=", + "GoModSum": "h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=" +} +{ + "Path": "github.com/hashicorp/go-sockaddr", + "Version": "v1.0.7", + "Time": "2024-09-19T09:47:04Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/go-sockaddr@v1.0.7", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/go-sockaddr/@v/v1.0.7.mod", + "GoVersion": "1.19", + "Sum": "h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw=", + "GoModSum": "h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw=" +} +{ + "Path": "github.com/hashicorp/go-uuid", + "Version": "v1.0.3", + "Time": "2022-04-08T14:59:45Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/go-uuid@v1.0.3", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/go-uuid/@v/v1.0.3.mod", + "Sum": "h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=", + "GoModSum": "h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=" +} +{ + "Path": "github.com/hashicorp/hcl", + "Version": "v1.0.1-vault-7", + "Time": "2024-11-07T22:23:56Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/hcl@v1.0.1-vault-7", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/hcl/@v/v1.0.1-vault-7.mod", + "GoVersion": "1.15", + "Sum": "h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I=", + "GoModSum": "h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=" +} +{ + "Path": "github.com/hashicorp/hcl/v2", + "Version": "v2.18.1", + "Time": "2023-10-06T01:44:43Z", + "Indirect": true, + "Dir": "/work/mod/github.com/hashicorp/hcl/v2@v2.18.1", + "GoMod": "/work/mod/cache/download/github.com/hashicorp/hcl/v2/@v/v2.18.1.mod", + "GoVersion": "1.18", + "Sum": "h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo=", + "GoModSum": "h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=" +} +{ + "Path": "github.com/huandu/xstrings", + "Version": "v1.5.0", + "Time": "2024-06-06T08:07:36Z", + "Indirect": true, + "Dir": "/work/mod/github.com/huandu/xstrings@v1.5.0", + "GoMod": "/work/mod/cache/download/github.com/huandu/xstrings/@v/v1.5.0.mod", + "GoVersion": "1.12", + "Sum": "h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=", + "GoModSum": "h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=" +} +{ + "Path": "github.com/imdario/mergo", + "Version": "v0.3.11", + "Time": "2020-08-11T19:49:30Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/imdario/mergo/@v/v0.3.11.mod", + "GoVersion": "1.13" +} +{ + "Path": "github.com/inconshreveable/mousetrap", + "Version": "v1.1.0", + "Time": "2022-11-27T22:01:53Z", + "Indirect": true, + "Dir": "/work/mod/github.com/inconshreveable/mousetrap@v1.1.0", + "GoMod": "/work/mod/cache/download/github.com/inconshreveable/mousetrap/@v/v1.1.0.mod", + "GoVersion": "1.18", + "Sum": "h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=", + "GoModSum": "h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=" +} +{ + "Path": "github.com/jcmturner/aescts/v2", + "Version": "v2.0.0", + "Time": "2020-02-04T21:18:11Z", + "Indirect": true, + "Dir": "/work/mod/github.com/jcmturner/aescts/v2@v2.0.0", + "GoMod": "/work/mod/cache/download/github.com/jcmturner/aescts/v2/@v/v2.0.0.mod", + "GoVersion": "1.13", + "Sum": "h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=", + "GoModSum": "h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=" +} +{ + "Path": "github.com/jcmturner/dnsutils/v2", + "Version": "v2.0.0", + "Time": "2020-02-04T20:52:29Z", + "Indirect": true, + "Dir": "/work/mod/github.com/jcmturner/dnsutils/v2@v2.0.0", + "GoMod": "/work/mod/cache/download/github.com/jcmturner/dnsutils/v2/@v/v2.0.0.mod", + "GoVersion": "1.13", + "Sum": "h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=", + "GoModSum": "h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=" +} +{ + "Path": "github.com/jcmturner/gofork", + "Version": "v1.7.6", + "Time": "2022-07-26T06:17:42Z", + "Indirect": true, + "Dir": "/work/mod/github.com/jcmturner/gofork@v1.7.6", + "GoMod": "/work/mod/cache/download/github.com/jcmturner/gofork/@v/v1.7.6.mod", + "GoVersion": "1.7", + "Sum": "h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=", + "GoModSum": "h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=" +} +{ + "Path": "github.com/jcmturner/goidentity/v6", + "Version": "v6.0.1", + "Time": "2020-01-19T21:33:46Z", + "Indirect": true, + "Dir": "/work/mod/github.com/jcmturner/goidentity/v6@v6.0.1", + "GoMod": "/work/mod/cache/download/github.com/jcmturner/goidentity/v6/@v/v6.0.1.mod", + "GoVersion": "1.13", + "Sum": "h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=", + "GoModSum": "h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=" +} +{ + "Path": "github.com/jcmturner/gokrb5/v8", + "Version": "v8.4.4", + "Time": "2023-02-25T07:18:19Z", + "Indirect": true, + "Dir": "/work/mod/github.com/jcmturner/gokrb5/v8@v8.4.4", + "GoMod": "/work/mod/cache/download/github.com/jcmturner/gokrb5/v8/@v/v8.4.4.mod", + "GoVersion": "1.16", + "Sum": "h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=", + "GoModSum": "h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=" +} +{ + "Path": "github.com/jcmturner/rpc/v2", + "Version": "v2.0.3", + "Time": "2020-11-12T14:32:19Z", + "Indirect": true, + "Dir": "/work/mod/github.com/jcmturner/rpc/v2@v2.0.3", + "GoMod": "/work/mod/cache/download/github.com/jcmturner/rpc/v2/@v/v2.0.3.mod", + "GoVersion": "1.13", + "Sum": "h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=", + "GoModSum": "h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=" +} +{ + "Path": "github.com/jessevdk/go-flags", + "Version": "v1.5.0", + "Time": "2021-03-21T10:32:44Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/jessevdk/go-flags/@v/v1.5.0.mod", + "GoVersion": "1.15" +} +{ + "Path": "github.com/jonboulle/clockwork", + "Version": "v0.5.0", + "Time": "2024-11-29T18:02:53Z", + "Indirect": true, + "Dir": "/work/mod/github.com/jonboulle/clockwork@v0.5.0", + "GoMod": "/work/mod/cache/download/github.com/jonboulle/clockwork/@v/v0.5.0.mod", + "GoVersion": "1.21", + "Sum": "h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=", + "GoModSum": "h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=" +} +{ + "Path": "github.com/jpillora/backoff", + "Version": "v1.0.0", + "Time": "2019-10-03T12:57:08Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/jpillora/backoff/@v/v1.0.0.mod", + "GoVersion": "1.13" +} +{ + "Path": "github.com/json-iterator/go", + "Version": "v1.1.12", + "Time": "2021-09-11T02:17:26Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/json-iterator/go/@v/v1.1.12.mod", + "GoVersion": "1.12" +} +{ + "Path": "github.com/julienschmidt/httprouter", + "Version": "v1.3.0", + "Time": "2019-09-29T23:21:22Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/julienschmidt/httprouter/@v/v1.3.0.mod", + "GoVersion": "1.7" +} +{ + "Path": "github.com/kisielk/errcheck", + "Version": "v1.5.0", + "Time": "2021-01-05T19:12:31Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/kisielk/errcheck/@v/v1.5.0.mod", + "GoVersion": "1.14", + "GoModSum": "h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=" +} +{ + "Path": "github.com/kisielk/gotool", + "Version": "v1.0.0", + "Time": "2018-02-21T18:54:26Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/kisielk/gotool/@v/v1.0.0.mod", + "GoModSum": "h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=" +} +{ + "Path": "github.com/klauspost/compress", + "Version": "v1.18.0", + "Time": "2025-02-19T09:26:03Z", + "Indirect": true, + "Dir": "/work/mod/github.com/klauspost/compress@v1.18.0", + "GoMod": "/work/mod/cache/download/github.com/klauspost/compress/@v/v1.18.0.mod", + "GoVersion": "1.22", + "Sum": "h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=", + "GoModSum": "h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=" +} +{ + "Path": "github.com/kr/pretty", + "Version": "v0.3.1", + "Time": "2022-08-29T23:03:05Z", + "Indirect": true, + "Dir": "/work/mod/github.com/kr/pretty@v0.3.1", + "GoMod": "/work/mod/cache/download/github.com/kr/pretty/@v/v0.3.1.mod", + "GoVersion": "1.12", + "Sum": "h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=", + "GoModSum": "h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=" +} +{ + "Path": "github.com/kr/pty", + "Version": "v1.1.1", + "Time": "2018-01-13T18:08:13Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/kr/pty/@v/v1.1.1.mod", + "GoModSum": "h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=" +} +{ + "Path": "github.com/kr/text", + "Version": "v0.2.0", + "Time": "2020-02-14T20:31:06Z", + "Indirect": true, + "Dir": "/work/mod/github.com/kr/text@v0.2.0", + "GoMod": "/work/mod/cache/download/github.com/kr/text/@v/v0.2.0.mod", + "Sum": "h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=", + "GoModSum": "h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=" +} +{ + "Path": "github.com/kylelemons/godebug", + "Version": "v1.1.0", + "Time": "2019-05-05T01:16:37Z", + "Dir": "/work/mod/github.com/kylelemons/godebug@v1.1.0", + "GoMod": "/work/mod/cache/download/github.com/kylelemons/godebug/@v/v1.1.0.mod", + "GoVersion": "1.11", + "Sum": "h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=", + "GoModSum": "h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=" +} +{ + "Path": "github.com/lib/pq", + "Version": "v1.11.2", + "Time": "2026-02-10T12:12:42Z", + "Dir": "/work/mod/github.com/lib/pq@v1.11.2", + "GoMod": "/work/mod/cache/download/github.com/lib/pq/@v/v1.11.2.mod", + "GoVersion": "1.21", + "Sum": "h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs=", + "GoModSum": "h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=" +} +{ + "Path": "github.com/mattermost/xml-roundtrip-validator", + "Version": "v0.1.0", + "Time": "2020-12-19T04:09:09Z", + "Dir": "/work/mod/github.com/mattermost/xml-roundtrip-validator@v0.1.0", + "GoMod": "/work/mod/cache/download/github.com/mattermost/xml-roundtrip-validator/@v/v0.1.0.mod", + "GoVersion": "1.14", + "Sum": "h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=", + "GoModSum": "h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=" +} +{ + "Path": "github.com/mattn/go-colorable", + "Version": "v0.1.14", + "Time": "2025-01-10T08:29:27Z", + "Indirect": true, + "Dir": "/work/mod/github.com/mattn/go-colorable@v0.1.14", + "GoMod": "/work/mod/cache/download/github.com/mattn/go-colorable/@v/v0.1.14.mod", + "GoVersion": "1.18", + "Sum": "h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=", + "GoModSum": "h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=" +} +{ + "Path": "github.com/mattn/go-isatty", + "Version": "v0.0.20", + "Time": "2023-10-17T07:28:21Z", + "Indirect": true, + "Dir": "/work/mod/github.com/mattn/go-isatty@v0.0.20", + "GoMod": "/work/mod/cache/download/github.com/mattn/go-isatty/@v/v0.0.20.mod", + "GoVersion": "1.15", + "Sum": "h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=", + "GoModSum": "h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=" +} +{ + "Path": "github.com/mattn/go-runewidth", + "Version": "v0.0.9", + "Time": "2020-03-20T06:32:21Z", + "Indirect": true, + "Dir": "/work/mod/github.com/mattn/go-runewidth@v0.0.9", + "GoMod": "/work/mod/cache/download/github.com/mattn/go-runewidth/@v/v0.0.9.mod", + "GoVersion": "1.9", + "Sum": "h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=", + "GoModSum": "h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=" +} +{ + "Path": "github.com/mattn/go-sqlite3", + "Version": "v1.14.34", + "Time": "2026-01-16T08:19:36Z", + "Dir": "/work/mod/github.com/mattn/go-sqlite3@v1.14.34", + "GoMod": "/work/mod/cache/download/github.com/mattn/go-sqlite3/@v/v1.14.34.mod", + "GoVersion": "1.19", + "Sum": "h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk=", + "GoModSum": "h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=" +} +{ + "Path": "github.com/mitchellh/cli", + "Version": "v1.1.5", + "Time": "2022-09-30T19:19:43Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/mitchellh/cli/@v/v1.1.5.mod", + "GoVersion": "1.11" +} +{ + "Path": "github.com/mitchellh/copystructure", + "Version": "v1.2.0", + "Time": "2021-05-05T17:08:07Z", + "Indirect": true, + "Dir": "/work/mod/github.com/mitchellh/copystructure@v1.2.0", + "GoMod": "/work/mod/cache/download/github.com/mitchellh/copystructure/@v/v1.2.0.mod", + "GoVersion": "1.15", + "Sum": "h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=", + "GoModSum": "h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=" +} +{ + "Path": "github.com/mitchellh/go-wordwrap", + "Version": "v1.0.1", + "Time": "2020-09-25T18:08:01Z", + "Indirect": true, + "Dir": "/work/mod/github.com/mitchellh/go-wordwrap@v1.0.1", + "GoMod": "/work/mod/cache/download/github.com/mitchellh/go-wordwrap/@v/v1.0.1.mod", + "GoVersion": "1.14", + "Sum": "h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=", + "GoModSum": "h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=" +} +{ + "Path": "github.com/mitchellh/mapstructure", + "Version": "v1.5.0", + "Time": "2022-04-20T22:31:31Z", + "Indirect": true, + "Dir": "/work/mod/github.com/mitchellh/mapstructure@v1.5.0", + "GoMod": "/work/mod/cache/download/github.com/mitchellh/mapstructure/@v/v1.5.0.mod", + "GoVersion": "1.14", + "Sum": "h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=", + "GoModSum": "h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=" +} +{ + "Path": "github.com/mitchellh/reflectwalk", + "Version": "v1.0.2", + "Time": "2021-05-03T23:34:11Z", + "Indirect": true, + "Dir": "/work/mod/github.com/mitchellh/reflectwalk@v1.0.2", + "GoMod": "/work/mod/cache/download/github.com/mitchellh/reflectwalk/@v/v1.0.2.mod", + "Sum": "h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=", + "GoModSum": "h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=" +} +{ + "Path": "github.com/modern-go/concurrent", + "Version": "v0.0.0-20180306012644-bacd9c7ef1dd", + "Time": "2018-03-06T01:26:44Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/modern-go/concurrent/@v/v0.0.0-20180306012644-bacd9c7ef1dd.mod" +} +{ + "Path": "github.com/modern-go/reflect2", + "Version": "v1.0.2", + "Time": "2021-09-11T02:10:30Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/modern-go/reflect2/@v/v1.0.2.mod", + "GoVersion": "1.12" +} +{ + "Path": "github.com/munnerz/goautoneg", + "Version": "v0.0.0-20191010083416-a7dc8b61c822", + "Time": "2019-10-10T08:34:16Z", + "Indirect": true, + "Dir": "/work/mod/github.com/munnerz/goautoneg@v0.0.0-20191010083416-a7dc8b61c822", + "GoMod": "/work/mod/cache/download/github.com/munnerz/goautoneg/@v/v0.0.0-20191010083416-a7dc8b61c822.mod", + "Sum": "h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=", + "GoModSum": "h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=" +} +{ + "Path": "github.com/mwitkow/go-conntrack", + "Version": "v0.0.0-20190716064945-2f068394615f", + "Time": "2019-07-16T06:49:45Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/mwitkow/go-conntrack/@v/v0.0.0-20190716064945-2f068394615f.mod" +} +{ + "Path": "github.com/niemeyer/pretty", + "Version": "v0.0.0-20200227124842-a10e7caefd8e", + "Time": "2020-02-27T12:48:42Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/niemeyer/pretty/@v/v0.0.0-20200227124842-a10e7caefd8e.mod", + "GoVersion": "1.12" +} +{ + "Path": "github.com/oklog/run", + "Version": "v1.2.0", + "Time": "2025-06-27T13:52:26Z", + "Dir": "/work/mod/github.com/oklog/run@v1.2.0", + "GoMod": "/work/mod/cache/download/github.com/oklog/run/@v/v1.2.0.mod", + "GoVersion": "1.20", + "Sum": "h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E=", + "GoModSum": "h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk=" +} +{ + "Path": "github.com/olekukonko/tablewriter", + "Version": "v0.0.5", + "Time": "2021-02-10T15:55:18Z", + "Indirect": true, + "Dir": "/work/mod/github.com/olekukonko/tablewriter@v0.0.5", + "GoMod": "/work/mod/cache/download/github.com/olekukonko/tablewriter/@v/v0.0.5.mod", + "GoVersion": "1.12", + "Sum": "h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=", + "GoModSum": "h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=" +} +{ + "Path": "github.com/openbao/openbao/api/v2", + "Version": "v2.5.1", + "Time": "2026-02-04T13:41:17Z", + "Dir": "/work/mod/github.com/openbao/openbao/api/v2@v2.5.1", + "GoMod": "/work/mod/cache/download/github.com/openbao/openbao/api/v2/@v/v2.5.1.mod", + "GoVersion": "1.24.0", + "Sum": "h1:Br79D6L20SbAa5P7xqENxmvv8LyI4HoKosPy7klhn4o=", + "GoModSum": "h1:Dh5un77tqGgMbmlVEqjqN+8/dMyUohnkaQVg/wXW0Ig=" +} +{ + "Path": "github.com/pkg/errors", + "Version": "v0.9.1", + "Time": "2020-01-14T19:47:44Z", + "Dir": "/work/mod/github.com/pkg/errors@v0.9.1", + "GoMod": "/work/mod/cache/download/github.com/pkg/errors/@v/v0.9.1.mod", + "Sum": "h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=", + "GoModSum": "h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=" +} +{ + "Path": "github.com/planetscale/vtprotobuf", + "Version": "v0.6.1-0.20240319094008-0393e58bdf10", + "Time": "2024-03-19T09:40:08Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/planetscale/vtprotobuf/@v/v0.6.1-0.20240319094008-0393e58bdf10.mod", + "GoVersion": "1.20" +} +{ + "Path": "github.com/pmezard/go-difflib", + "Version": "v1.0.1-0.20181226105442-5d4384ee4fb2", + "Time": "2018-12-26T10:54:42Z", + "Indirect": true, + "Dir": "/work/mod/github.com/pmezard/go-difflib@v1.0.1-0.20181226105442-5d4384ee4fb2", + "GoMod": "/work/mod/cache/download/github.com/pmezard/go-difflib/@v/v1.0.1-0.20181226105442-5d4384ee4fb2.mod", + "Sum": "h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=", + "GoModSum": "h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=" +} +{ + "Path": "github.com/posener/complete", + "Version": "v1.1.1", + "Time": "2018-03-09T06:24:32Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/posener/complete/@v/v1.1.1.mod" +} +{ + "Path": "github.com/prometheus/client_golang", + "Version": "v1.23.2", + "Time": "2025-09-05T14:03:59Z", + "Dir": "/work/mod/github.com/prometheus/client_golang@v1.23.2", + "GoMod": "/work/mod/cache/download/github.com/prometheus/client_golang/@v/v1.23.2.mod", + "GoVersion": "1.23.0", + "Sum": "h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=", + "GoModSum": "h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=" +} +{ + "Path": "github.com/prometheus/client_model", + "Version": "v0.6.2", + "Time": "2025-04-11T05:38:16Z", + "Indirect": true, + "Dir": "/work/mod/github.com/prometheus/client_model@v0.6.2", + "GoMod": "/work/mod/cache/download/github.com/prometheus/client_model/@v/v0.6.2.mod", + "GoVersion": "1.22.0", + "Sum": "h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=", + "GoModSum": "h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=" +} +{ + "Path": "github.com/prometheus/common", + "Version": "v0.66.1", + "Time": "2025-09-05T07:53:47Z", + "Indirect": true, + "Dir": "/work/mod/github.com/prometheus/common@v0.66.1", + "GoMod": "/work/mod/cache/download/github.com/prometheus/common/@v/v0.66.1.mod", + "GoVersion": "1.23.0", + "Sum": "h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=", + "GoModSum": "h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=" +} +{ + "Path": "github.com/prometheus/procfs", + "Version": "v0.16.1", + "Time": "2025-04-19T15:43:08Z", + "Indirect": true, + "Dir": "/work/mod/github.com/prometheus/procfs@v0.16.1", + "GoMod": "/work/mod/cache/download/github.com/prometheus/procfs/@v/v0.16.1.mod", + "GoVersion": "1.23.0", + "Sum": "h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=", + "GoModSum": "h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=" +} +{ + "Path": "github.com/rogpeppe/fastuuid", + "Version": "v1.2.0", + "Time": "2019-07-08T15:05:45Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/rogpeppe/fastuuid/@v/v1.2.0.mod", + "GoVersion": "1.12" +} +{ + "Path": "github.com/rogpeppe/go-internal", + "Version": "v1.14.1", + "Time": "2025-02-25T12:37:03Z", + "Indirect": true, + "Dir": "/work/mod/github.com/rogpeppe/go-internal@v1.14.1", + "GoMod": "/work/mod/cache/download/github.com/rogpeppe/go-internal/@v/v1.14.1.mod", + "GoVersion": "1.23", + "Sum": "h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=", + "GoModSum": "h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=" +} +{ + "Path": "github.com/russellhaering/goxmldsig", + "Version": "v1.6.0", + "Time": "2026-03-18T05:07:36Z", + "Dir": "/work/mod/github.com/russellhaering/goxmldsig@v1.6.0", + "GoMod": "/work/mod/cache/download/github.com/russellhaering/goxmldsig/@v/v1.6.0.mod", + "GoVersion": "1.23.0", + "Sum": "h1:8fdWXEPh2k/NZNQBPFNoVfS3JmzS4ZprY/sAOpKQLks=", + "GoModSum": "h1:TrnaquDcYxWXfJrOjeMBTX4mLBeYAqaHEyUeWPxZlBM=" +} +{ + "Path": "github.com/russross/blackfriday/v2", + "Version": "v2.1.0", + "Time": "2020-10-27T03:47:54Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/russross/blackfriday/v2/@v/v2.1.0.mod", + "GoModSum": "h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=" +} +{ + "Path": "github.com/ryanuber/columnize", + "Version": "v2.1.2+incompatible", + "Time": "2020-08-19T15:58:40Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/ryanuber/columnize/@v/v2.1.2+incompatible.mod" +} +{ + "Path": "github.com/ryanuber/go-glob", + "Version": "v1.0.0", + "Time": "2019-01-24T19:22:32Z", + "Indirect": true, + "Dir": "/work/mod/github.com/ryanuber/go-glob@v1.0.0", + "GoMod": "/work/mod/cache/download/github.com/ryanuber/go-glob/@v/v1.0.0.mod", + "Sum": "h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=", + "GoModSum": "h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=" +} +{ + "Path": "github.com/sergi/go-diff", + "Version": "v1.3.1", + "Time": "2023-01-13T08:54:48Z", + "Indirect": true, + "Dir": "/work/mod/github.com/sergi/go-diff@v1.3.1", + "GoMod": "/work/mod/cache/download/github.com/sergi/go-diff/@v/v1.3.1.mod", + "GoVersion": "1.12", + "Sum": "h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=", + "GoModSum": "h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=" +} +{ + "Path": "github.com/shopspring/decimal", + "Version": "v1.4.0", + "Time": "2024-04-12T14:15:38Z", + "Indirect": true, + "Dir": "/work/mod/github.com/shopspring/decimal@v1.4.0", + "GoMod": "/work/mod/cache/download/github.com/shopspring/decimal/@v/v1.4.0.mod", + "GoVersion": "1.10", + "Sum": "h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=", + "GoModSum": "h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=" +} +{ + "Path": "github.com/spf13/cast", + "Version": "v1.7.0", + "Time": "2024-08-06T19:08:19Z", + "Indirect": true, + "Dir": "/work/mod/github.com/spf13/cast@v1.7.0", + "GoMod": "/work/mod/cache/download/github.com/spf13/cast/@v/v1.7.0.mod", + "GoVersion": "1.19", + "Sum": "h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=", + "GoModSum": "h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=" +} +{ + "Path": "github.com/spf13/cobra", + "Version": "v1.10.2", + "Time": "2025-12-03T23:51:15Z", + "Dir": "/work/mod/github.com/spf13/cobra@v1.10.2", + "GoMod": "/work/mod/cache/download/github.com/spf13/cobra/@v/v1.10.2.mod", + "GoVersion": "1.15", + "Sum": "h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=", + "GoModSum": "h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=" +} +{ + "Path": "github.com/spf13/pflag", + "Version": "v1.0.9", + "Time": "2025-09-01T07:27:15Z", + "Indirect": true, + "Dir": "/work/mod/github.com/spf13/pflag@v1.0.9", + "GoMod": "/work/mod/cache/download/github.com/spf13/pflag/@v/v1.0.9.mod", + "GoVersion": "1.12", + "Sum": "h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=", + "GoModSum": "h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=" +} +{ + "Path": "github.com/spiffe/go-spiffe/v2", + "Version": "v2.7.0", + "Time": "2026-06-03T20:07:47Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/spiffe/go-spiffe/v2/@v/v2.7.0.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "github.com/stretchr/objx", + "Version": "v0.5.2", + "Time": "2024-02-29T09:57:51Z", + "Indirect": true, + "Dir": "/work/mod/github.com/stretchr/objx@v0.5.2", + "GoMod": "/work/mod/cache/download/github.com/stretchr/objx/@v/v0.5.2.mod", + "GoVersion": "1.20", + "Sum": "h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=", + "GoModSum": "h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=" +} +{ + "Path": "github.com/stretchr/testify", + "Version": "v1.11.1", + "Time": "2025-08-27T10:46:31Z", + "Dir": "/work/mod/github.com/stretchr/testify@v1.11.1", + "GoMod": "/work/mod/cache/download/github.com/stretchr/testify/@v/v1.11.1.mod", + "GoVersion": "1.17", + "Sum": "h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=", + "GoModSum": "h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=" +} +{ + "Path": "github.com/vmihailenco/msgpack/v5", + "Version": "v5.3.5", + "Time": "2021-10-22T10:21:31Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/vmihailenco/msgpack/v5/@v/v5.3.5.mod", + "GoVersion": "1.11" +} +{ + "Path": "github.com/vmihailenco/tagparser/v2", + "Version": "v2.0.0", + "Time": "2021-02-03T10:04:46Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/vmihailenco/tagparser/v2/@v/v2.0.0.mod", + "GoVersion": "1.15" +} +{ + "Path": "github.com/xhit/go-str2duration/v2", + "Version": "v2.1.0", + "Time": "2022-12-07T00:32:32Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/xhit/go-str2duration/v2/@v/v2.1.0.mod", + "GoVersion": "1.13" +} +{ + "Path": "github.com/yuin/goldmark", + "Version": "v1.4.13", + "Time": "2022-07-09T07:22:17Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/yuin/goldmark/@v/v1.4.13.mod", + "GoVersion": "1.18" +} +{ + "Path": "github.com/zclconf/go-cty", + "Version": "v1.14.4", + "Time": "2024-03-20T23:15:14Z", + "Indirect": true, + "Dir": "/work/mod/github.com/zclconf/go-cty@v1.14.4", + "GoMod": "/work/mod/cache/download/github.com/zclconf/go-cty/@v/v1.14.4.mod", + "GoVersion": "1.18", + "Sum": "h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8=", + "GoModSum": "h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=" +} +{ + "Path": "github.com/zclconf/go-cty-debug", + "Version": "v0.0.0-20191215020915-b22d67c1ba0b", + "Time": "2019-12-15T02:09:15Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/github.com/zclconf/go-cty-debug/@v/v0.0.0-20191215020915-b22d67c1ba0b.mod", + "GoVersion": "1.12" +} +{ + "Path": "github.com/zclconf/go-cty-yaml", + "Version": "v1.1.0", + "Time": "2024-10-02T16:59:11Z", + "Indirect": true, + "Dir": "/work/mod/github.com/zclconf/go-cty-yaml@v1.1.0", + "GoMod": "/work/mod/cache/download/github.com/zclconf/go-cty-yaml/@v/v1.1.0.mod", + "GoVersion": "1.17", + "Sum": "h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0=", + "GoModSum": "h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs=" +} +{ + "Path": "go.etcd.io/etcd/api/v3", + "Version": "v3.6.8", + "Time": "2026-02-13T18:39:11Z", + "Indirect": true, + "Dir": "/work/mod/go.etcd.io/etcd/api/v3@v3.6.8", + "GoMod": "/work/mod/cache/download/go.etcd.io/etcd/api/v3/@v/v3.6.8.mod", + "GoVersion": "1.24.0", + "Sum": "h1:gqb1VN92TAI6G2FiBvWcqKtHiIjr4SU2GdXxTwyexbM=", + "GoModSum": "h1:qyQj1HZPUV3B5cbAL8scG62+fyz5dSxxu0w8pn28N6Q=" +} +{ + "Path": "go.etcd.io/etcd/client/pkg/v3", + "Version": "v3.6.8", + "Time": "2026-02-13T18:39:11Z", + "Dir": "/work/mod/go.etcd.io/etcd/client/pkg/v3@v3.6.8", + "GoMod": "/work/mod/cache/download/go.etcd.io/etcd/client/pkg/v3/@v/v3.6.8.mod", + "GoVersion": "1.24.0", + "Sum": "h1:Qs/5C0LNFiqXxYf2GU8MVjYUEXJ6sZaYOz0zEqQgy50=", + "GoModSum": "h1:GsiTRUZE2318PggZkAo6sWb6l8JLVrnckTNfbG8PWtw=" +} +{ + "Path": "go.etcd.io/etcd/client/v3", + "Version": "v3.6.8", + "Time": "2026-02-13T18:39:11Z", + "Dir": "/work/mod/go.etcd.io/etcd/client/v3@v3.6.8", + "GoMod": "/work/mod/cache/download/go.etcd.io/etcd/client/v3/@v/v3.6.8.mod", + "GoVersion": "1.24.0", + "Sum": "h1:B3G76t1UykqAOrbio7s/EPatixQDkQBevN8/mwiplrY=", + "GoModSum": "h1:MVG4BpSIuumPi+ELF7wYtySETmoTWBHVcDoHdVupwt8=" +} +{ + "Path": "go.opencensus.io", + "Version": "v0.24.0", + "Time": "2022-11-03T20:13:50Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/go.opencensus.io/@v/v0.24.0.mod", + "GoVersion": "1.13" +} +{ + "Path": "go.opentelemetry.io/auto/sdk", + "Version": "v1.2.1", + "Time": "2025-09-15T16:53:44Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/auto/sdk@v1.2.1", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/auto/sdk/@v/v1.2.1.mod", + "GoVersion": "1.24.0", + "Sum": "h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=", + "GoModSum": "h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=" +} +{ + "Path": "go.opentelemetry.io/contrib/detectors/gcp", + "Version": "v1.44.0", + "Time": "2026-05-28T05:28:14Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/contrib/detectors/gcp/@v/v1.44.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc", + "Version": "v0.61.0", + "Time": "2025-05-22T14:29:43Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc@v0.61.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/@v/v0.61.0.mod", + "GoVersion": "1.23.0", + "Sum": "h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=", + "GoModSum": "h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=" +} +{ + "Path": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", + "Version": "v0.61.0", + "Time": "2025-05-22T14:29:43Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.61.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/@v/v0.61.0.mod", + "GoVersion": "1.23.0", + "Sum": "h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=", + "GoModSum": "h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=" +} +{ + "Path": "go.opentelemetry.io/otel", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=", + "GoModSum": "h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=" +} +{ + "Path": "go.opentelemetry.io/otel/metric", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel/metric@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/metric/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=", + "GoModSum": "h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=" +} +{ + "Path": "go.opentelemetry.io/otel/sdk", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel/sdk@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/sdk/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=", + "GoModSum": "h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=" +} +{ + "Path": "go.opentelemetry.io/otel/sdk/metric", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel/sdk/metric@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/sdk/metric/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=", + "GoModSum": "h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=" +} +{ + "Path": "go.opentelemetry.io/otel/trace", + "Version": "v1.44.0", + "Time": "2026-05-27T16:42:37Z", + "Indirect": true, + "Dir": "/work/mod/go.opentelemetry.io/otel/trace@v1.44.0", + "GoMod": "/work/mod/cache/download/go.opentelemetry.io/otel/trace/@v/v1.44.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=", + "GoModSum": "h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=" +} +{ + "Path": "go.uber.org/goleak", + "Version": "v1.3.0", + "Time": "2023-10-24T16:28:03Z", + "Indirect": true, + "Dir": "/work/mod/go.uber.org/goleak@v1.3.0", + "GoMod": "/work/mod/cache/download/go.uber.org/goleak/@v/v1.3.0.mod", + "GoVersion": "1.20", + "Sum": "h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=", + "GoModSum": "h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=" +} +{ + "Path": "go.uber.org/multierr", + "Version": "v1.11.0", + "Time": "2023-03-29T23:00:37Z", + "Indirect": true, + "Dir": "/work/mod/go.uber.org/multierr@v1.11.0", + "GoMod": "/work/mod/cache/download/go.uber.org/multierr/@v/v1.11.0.mod", + "GoVersion": "1.19", + "Sum": "h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=", + "GoModSum": "h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=" +} +{ + "Path": "go.uber.org/zap", + "Version": "v1.27.0", + "Time": "2024-02-20T20:55:06Z", + "Indirect": true, + "Dir": "/work/mod/go.uber.org/zap@v1.27.0", + "GoMod": "/work/mod/cache/download/go.uber.org/zap/@v/v1.27.0.mod", + "GoVersion": "1.19", + "Sum": "h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=", + "GoModSum": "h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=" +} +{ + "Path": "go.yaml.in/yaml/v2", + "Version": "v2.4.2", + "Time": "2025-06-02T16:37:17Z", + "Indirect": true, + "Dir": "/work/mod/go.yaml.in/yaml/v2@v2.4.2", + "GoMod": "/work/mod/cache/download/go.yaml.in/yaml/v2/@v/v2.4.2.mod", + "GoVersion": "1.15", + "Sum": "h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=", + "GoModSum": "h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=" +} +{ + "Path": "go.yaml.in/yaml/v3", + "Version": "v3.0.4", + "Time": "2025-06-29T14:09:51Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/go.yaml.in/yaml/v3/@v/v3.0.4.mod", + "GoVersion": "1.16", + "GoModSum": "h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=" +} +{ + "Path": "golang.org/x/crypto", + "Version": "v0.56.0", + "Time": "2026-09-02T18:02:47Z", + "Dir": "/work/mod/golang.org/x/crypto@v0.56.0", + "GoMod": "/work/mod/cache/download/golang.org/x/crypto/@v/v0.56.0.mod", + "GoVersion": "1.26.0", + "Sum": "h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y=", + "GoModSum": "h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I=" +} +{ + "Path": "golang.org/x/exp", + "Version": "v0.0.0-20221004215720-b9f4876ce741", + "Time": "2022-10-04T21:57:20Z", + "Dir": "/work/mod/golang.org/x/exp@v0.0.0-20221004215720-b9f4876ce741", + "GoMod": "/work/mod/cache/download/golang.org/x/exp/@v/v0.0.0-20221004215720-b9f4876ce741.mod", + "GoVersion": "1.18", + "Sum": "h1:fGZugkZk2UgYBxtpKmvub51Yno1LJDeEsRp2xGD+0gY=", + "GoModSum": "h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=" +} +{ + "Path": "golang.org/x/mod", + "Version": "v0.40.0", + "Time": "2026-08-13T19:09:22Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/mod@v0.40.0", + "GoMod": "/work/mod/cache/download/golang.org/x/mod/@v/v0.40.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs=", + "GoModSum": "h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE=" +} +{ + "Path": "golang.org/x/net", + "Version": "v0.58.0", + "Time": "2026-08-12T17:41:32Z", + "Dir": "/work/mod/golang.org/x/net@v0.58.0", + "GoMod": "/work/mod/cache/download/golang.org/x/net/@v/v0.58.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=", + "GoModSum": "h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=" +} +{ + "Path": "golang.org/x/oauth2", + "Version": "v0.36.0", + "Time": "2026-02-11T19:14:10Z", + "Dir": "/work/mod/golang.org/x/oauth2@v0.36.0", + "GoMod": "/work/mod/cache/download/golang.org/x/oauth2/@v/v0.36.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=", + "GoModSum": "h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=" +} +{ + "Path": "golang.org/x/sync", + "Version": "v0.22.0", + "Time": "2026-07-01T17:29:34Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/sync@v0.22.0", + "GoMod": "/work/mod/cache/download/golang.org/x/sync/@v/v0.22.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=", + "GoModSum": "h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=" +} +{ + "Path": "golang.org/x/sys", + "Version": "v0.47.0", + "Time": "2026-06-30T17:07:31Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/sys@v0.47.0", + "GoMod": "/work/mod/cache/download/golang.org/x/sys/@v/v0.47.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=", + "GoModSum": "h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=" +} +{ + "Path": "golang.org/x/telemetry", + "Version": "v0.0.0-20260811182544-a038080d80e5", + "Time": "2026-08-11T18:25:44Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/golang.org/x/telemetry/@v/v0.0.0-20260811182544-a038080d80e5.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "golang.org/x/term", + "Version": "v0.45.0", + "Time": "2026-07-08T15:40:56Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/golang.org/x/term/@v/v0.45.0.mod", + "GoVersion": "1.25.0" +} +{ + "Path": "golang.org/x/text", + "Version": "v0.41.0", + "Time": "2026-08-11T15:22:47Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/text@v0.41.0", + "GoMod": "/work/mod/cache/download/golang.org/x/text/@v/v0.41.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=", + "GoModSum": "h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=" +} +{ + "Path": "golang.org/x/time", + "Version": "v0.14.0", + "Time": "2025-09-16T23:29:52Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/time@v0.14.0", + "GoMod": "/work/mod/cache/download/golang.org/x/time/@v/v0.14.0.mod", + "GoVersion": "1.24.0", + "Sum": "h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=", + "GoModSum": "h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=" +} +{ + "Path": "golang.org/x/tools", + "Version": "v0.49.0", + "Time": "2026-08-13T14:53:26Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/tools@v0.49.0", + "GoMod": "/work/mod/cache/download/golang.org/x/tools/@v/v0.49.0.mod", + "GoVersion": "1.25.0", + "Sum": "h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=", + "GoModSum": "h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=" +} +{ + "Path": "golang.org/x/tools/go/expect", + "Version": "v0.1.0-deprecated", + "Time": "2025-06-12T15:17:39Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/tools/go/expect@v0.1.0-deprecated", + "GoMod": "/work/mod/cache/download/golang.org/x/tools/go/expect/@v/v0.1.0-deprecated.mod", + "GoVersion": "1.23.0", + "Sum": "h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY=", + "GoModSum": "h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=" +} +{ + "Path": "golang.org/x/tools/go/packages/packagestest", + "Version": "v0.1.1-deprecated", + "Time": "2025-06-13T18:44:18Z", + "Indirect": true, + "Dir": "/work/mod/golang.org/x/tools/go/packages/packagestest@v0.1.1-deprecated", + "GoMod": "/work/mod/cache/download/golang.org/x/tools/go/packages/packagestest/@v/v0.1.1-deprecated.mod", + "GoVersion": "1.23.0", + "Sum": "h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=", + "GoModSum": "h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=" +} +{ + "Path": "golang.org/x/xerrors", + "Version": "v0.0.0-20200804184101-5ec99f83aff1", + "Time": "2020-08-04T18:41:01Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/golang.org/x/xerrors/@v/v0.0.0-20200804184101-5ec99f83aff1.mod", + "GoVersion": "1.11", + "GoModSum": "h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=" +} +{ + "Path": "gonum.org/v1/gonum", + "Version": "v0.17.0", + "Time": "2025-12-29T19:16:44Z", + "Indirect": true, + "Dir": "/work/mod/gonum.org/v1/gonum@v0.17.0", + "GoMod": "/work/mod/cache/download/gonum.org/v1/gonum/@v/v0.17.0.mod", + "GoVersion": "1.24.0", + "Sum": "h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=", + "GoModSum": "h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=" +} +{ + "Path": "google.golang.org/api", + "Version": "v0.267.0", + "Time": "2026-02-17T16:52:11Z", + "Dir": "/work/mod/google.golang.org/api@v0.267.0", + "GoMod": "/work/mod/cache/download/google.golang.org/api/@v/v0.267.0.mod", + "GoVersion": "1.24.0", + "Sum": "h1:w+vfWPMPYeRs8qH1aYYsFX68jMls5acWl/jocfLomwE=", + "GoModSum": "h1:Jzc0+ZfLnyvXma3UtaTl023TdhZu6OMBP9tJ+0EmFD0=" +} +{ + "Path": "google.golang.org/appengine", + "Version": "v1.6.8", + "Time": "2023-08-30T01:12:52Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/google.golang.org/appengine/@v/v1.6.8.mod", + "GoVersion": "1.11" +} +{ + "Path": "google.golang.org/genproto", + "Version": "v0.0.0-20260128011058-8636f8732409", + "Time": "2026-01-28T01:10:58Z", + "Indirect": true, + "Dir": "/work/mod/google.golang.org/genproto@v0.0.0-20260128011058-8636f8732409", + "GoMod": "/work/mod/cache/download/google.golang.org/genproto/@v/v0.0.0-20260128011058-8636f8732409.mod", + "GoVersion": "1.24.0", + "Sum": "h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM=", + "GoModSum": "h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM=" +} +{ + "Path": "google.golang.org/genproto/googleapis/api", + "Version": "v0.0.0-20260526163538-3dc84a4a5aaa", + "Time": "2026-05-26T16:35:38Z", + "Indirect": true, + "Dir": "/work/mod/google.golang.org/genproto/googleapis/api@v0.0.0-20260526163538-3dc84a4a5aaa", + "GoMod": "/work/mod/cache/download/google.golang.org/genproto/googleapis/api/@v/v0.0.0-20260526163538-3dc84a4a5aaa.mod", + "GoVersion": "1.25.0", + "Sum": "h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8=", + "GoModSum": "h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=" +} +{ + "Path": "google.golang.org/genproto/googleapis/bytestream", + "Version": "v0.0.0-20260203192932-546029d2fa20", + "Time": "2026-02-03T19:29:32Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/google.golang.org/genproto/googleapis/bytestream/@v/v0.0.0-20260203192932-546029d2fa20.mod", + "GoVersion": "1.24.0" +} +{ + "Path": "google.golang.org/genproto/googleapis/rpc", + "Version": "v0.0.0-20260526163538-3dc84a4a5aaa", + "Time": "2026-05-26T16:35:38Z", + "Indirect": true, + "Dir": "/work/mod/google.golang.org/genproto/googleapis/rpc@v0.0.0-20260526163538-3dc84a4a5aaa", + "GoMod": "/work/mod/cache/download/google.golang.org/genproto/googleapis/rpc/@v/v0.0.0-20260526163538-3dc84a4a5aaa.mod", + "GoVersion": "1.25.0", + "Sum": "h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=", + "GoModSum": "h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=" +} +{ + "Path": "google.golang.org/grpc", + "Version": "v1.83.2", + "Time": "2026-08-25T15:47:16Z", + "Dir": "/work/mod/google.golang.org/grpc@v1.83.2", + "GoMod": "/work/mod/cache/download/google.golang.org/grpc/@v/v1.83.2.mod", + "GoVersion": "1.25.0", + "Sum": "h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU=", + "GoModSum": "h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8=" +} +{ + "Path": "google.golang.org/protobuf", + "Version": "v1.36.11", + "Time": "2025-12-12T08:48:31Z", + "Dir": "/work/mod/google.golang.org/protobuf@v1.36.11", + "GoMod": "/work/mod/cache/download/google.golang.org/protobuf/@v/v1.36.11.mod", + "GoVersion": "1.23", + "Sum": "h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=", + "GoModSum": "h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=" +} +{ + "Path": "gopkg.in/check.v1", + "Version": "v1.0.0-20201130134442-10cb98267c6c", + "Time": "2020-11-30T13:44:42Z", + "Indirect": true, + "Dir": "/work/mod/gopkg.in/check.v1@v1.0.0-20201130134442-10cb98267c6c", + "GoMod": "/work/mod/cache/download/gopkg.in/check.v1/@v/v1.0.0-20201130134442-10cb98267c6c.mod", + "GoVersion": "1.11", + "Sum": "h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=", + "GoModSum": "h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=" +} +{ + "Path": "gopkg.in/yaml.v2", + "Version": "v2.4.0", + "Time": "2020-11-17T15:46:20Z", + "Indirect": true, + "Dir": "/work/mod/gopkg.in/yaml.v2@v2.4.0", + "GoMod": "/work/mod/cache/download/gopkg.in/yaml.v2/@v/v2.4.0.mod", + "GoVersion": "1.15", + "Sum": "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=", + "GoModSum": "h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=" +} +{ + "Path": "gopkg.in/yaml.v3", + "Version": "v3.0.1", + "Time": "2022-05-27T08:35:30Z", + "Indirect": true, + "Dir": "/work/mod/gopkg.in/yaml.v3@v3.0.1", + "GoMod": "/work/mod/cache/download/gopkg.in/yaml.v3/@v/v3.0.1.mod", + "Sum": "h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=", + "GoModSum": "h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=" +} +{ + "Path": "sigs.k8s.io/yaml", + "Version": "v1.4.0", + "Time": "2023-10-24T17:13:34Z", + "Indirect": true, + "GoMod": "/work/mod/cache/download/sigs.k8s.io/yaml/@v/v1.4.0.mod", + "GoVersion": "1.12" +} diff --git a/bridge/idp/locks/generated/requests.txt b/bridge/idp/locks/generated/requests.txt new file mode 100644 index 00000000..6fc4313b --- /dev/null +++ b/bridge/idp/locks/generated/requests.txt @@ -0,0 +1,10 @@ +github.com/go-jose/go-jose/v4@v4.1.4 +github.com/russellhaering/goxmldsig@v1.6.0 +go.opentelemetry.io/otel@v1.44.0 +go.opentelemetry.io/otel/metric@v1.44.0 +go.opentelemetry.io/otel/trace@v1.44.0 +golang.org/x/crypto@v0.56.0 +golang.org/x/mod@v0.40.0 +golang.org/x/net@v0.58.0 +golang.org/x/text@v0.41.0 +google.golang.org/grpc@v1.83.2 diff --git a/bridge/idp/locks/generated/toolchain.txt b/bridge/idp/locks/generated/toolchain.txt new file mode 100644 index 00000000..b0b893ce --- /dev/null +++ b/bridge/idp/locks/generated/toolchain.txt @@ -0,0 +1 @@ +go version go1.26.8 linux/amd64 diff --git a/bridge/idp/locks/generated/upstream/api/v2/go.mod b/bridge/idp/locks/generated/upstream/api/v2/go.mod new file mode 100644 index 00000000..6c14b7e4 --- /dev/null +++ b/bridge/idp/locks/generated/upstream/api/v2/go.mod @@ -0,0 +1,15 @@ +module github.com/dexidp/dex/api/v2 + +go 1.24.0 + +require ( + google.golang.org/grpc v1.79.1 + google.golang.org/protobuf v1.36.11 +) + +require ( + golang.org/x/net v0.50.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect +) diff --git a/bridge/idp/locks/generated/upstream/api/v2/go.sum b/bridge/idp/locks/generated/upstream/api/v2/go.sum new file mode 100644 index 00000000..727897fb --- /dev/null +++ b/bridge/idp/locks/generated/upstream/api/v2/go.sum @@ -0,0 +1,38 @@ +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= +google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/bridge/idp/locks/generated/upstream/go.mod b/bridge/idp/locks/generated/upstream/go.mod new file mode 100644 index 00000000..ee55dd4e --- /dev/null +++ b/bridge/idp/locks/generated/upstream/go.mod @@ -0,0 +1,129 @@ +module github.com/dexidp/dex + +go 1.25.0 + +require ( + cloud.google.com/go/compute/metadata v0.9.0 + entgo.io/ent v0.14.5 + github.com/AppsFlyer/go-sundheit v0.6.0 + github.com/Masterminds/semver v1.5.0 + github.com/Masterminds/sprig/v3 v3.3.0 + github.com/beevik/etree v1.6.0 + github.com/coreos/go-oidc/v3 v3.17.0 + github.com/dexidp/dex/api/v2 v2.4.0 + github.com/fsnotify/fsnotify v1.9.0 + github.com/ghodss/yaml v1.0.0 + github.com/go-jose/go-jose/v4 v4.1.3 + github.com/go-ldap/ldap/v3 v3.4.12 + github.com/go-sql-driver/mysql v1.9.3 + github.com/google/uuid v1.6.0 + github.com/gorilla/handlers v1.5.2 + github.com/gorilla/mux v1.8.1 + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 + github.com/kylelemons/godebug v1.1.0 + github.com/lib/pq v1.11.2 + github.com/mattermost/xml-roundtrip-validator v0.1.0 + github.com/mattn/go-sqlite3 v1.14.34 + github.com/oklog/run v1.2.0 + github.com/openbao/openbao/api/v2 v2.5.1 + github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.23.2 + github.com/russellhaering/goxmldsig v1.5.0 + github.com/spf13/cobra v1.10.2 + github.com/stretchr/testify v1.11.1 + go.etcd.io/etcd/client/pkg/v3 v3.6.8 + go.etcd.io/etcd/client/v3 v3.6.8 + golang.org/x/crypto v0.48.0 + golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741 + golang.org/x/net v0.50.0 + golang.org/x/oauth2 v0.35.0 + google.golang.org/api v0.267.0 + google.golang.org/grpc v1.79.1 + google.golang.org/protobuf v1.36.11 +) + +require ( + ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 // indirect + cloud.google.com/go/auth v0.18.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect + dario.cat/mergo v1.0.1 // indirect + filippo.io/edwards25519 v1.1.1 // indirect + github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/agext/levenshtein v1.2.3 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bmatcuk/doublestar v1.3.4 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/inflect v0.19.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.11 // indirect + github.com/googleapis/gax-go/v2 v2.17.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-retryablehttp v0.7.8 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect + github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.7 // indirect + github.com/hashicorp/hcl v1.0.1-vault-7 // indirect + github.com/hashicorp/hcl/v2 v2.18.1 // indirect + github.com/huandu/xstrings v1.5.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jonboulle/clockwork v0.5.0 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect + github.com/shopspring/decimal v1.4.0 // indirect + github.com/spf13/cast v1.7.0 // indirect + github.com/spf13/pflag v1.0.9 // indirect + github.com/zclconf/go-cty v1.14.4 // indirect + github.com/zclconf/go-cty-yaml v1.1.0 // indirect + go.etcd.io/etcd/api/v3 v3.6.8 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.39.0 // indirect + go.opentelemetry.io/otel/metric v1.39.0 // indirect + go.opentelemetry.io/otel/trace v1.39.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/mod v0.32.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 // indirect + golang.org/x/time v0.14.0 // indirect + golang.org/x/tools v0.41.0 // indirect + golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/dexidp/dex/api/v2 => ./api/v2 + +tool entgo.io/ent/cmd/ent diff --git a/bridge/idp/locks/generated/upstream/go.sum b/bridge/idp/locks/generated/upstream/go.sum new file mode 100644 index 00000000..ac41652e --- /dev/null +++ b/bridge/idp/locks/generated/upstream/go.sum @@ -0,0 +1,339 @@ +ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9 h1:E0wvcUXTkgyN4wy4LGtNzMNGMytJN8afmIWXJVMi4cc= +ariga.io/atlas v0.32.1-0.20250325101103-175b25e1c1b9/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w= +cloud.google.com/go/auth v0.18.1 h1:IwTEx92GFUo2pJ6Qea0EU3zYvKnTAeRCODxfA/G5UWs= +cloud.google.com/go/auth v0.18.1/go.mod h1:GfTYoS9G3CWpRA3Va9doKN9mjPGRS+v41jmZAhBzbrA= +cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= +cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +entgo.io/ent v0.14.5 h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4= +entgo.io/ent v0.14.5/go.mod h1:zTzLmWtPvGpmSwtkaayM2cm5m819NdM7z7tYPq3vN0U= +filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw= +filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/AppsFlyer/go-sundheit v0.6.0 h1:d2hBvCjBSb2lUsEWGfPigr4MCOt04sxB+Rppl0yUMSk= +github.com/AppsFlyer/go-sundheit v0.6.0/go.mod h1:LDdBHD6tQBtmHsdW+i1GwdTt6Wqc0qazf5ZEJVTbTME= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= +github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e h1:4dAU9FXIyQktpoUAgOJK3OTFc/xug0PCXYCqU0FgDKI= +github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= +github.com/beevik/etree v1.6.0/go.mod h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= +github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc= +github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= +github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= +github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= +github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4= +github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= +github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= +github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.11 h1:vAe81Msw+8tKUxi2Dqh/NZMz7475yUvmRIkXr4oN2ao= +github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8= +github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= +github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= +github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= +github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= +github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= +github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= +github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZYSo= +github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= +github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= +github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= +github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= +github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs= +github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU= +github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.14.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk= +github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= +github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/openbao/openbao/api/v2 v2.5.1 h1:Br79D6L20SbAa5P7xqENxmvv8LyI4HoKosPy7klhn4o= +github.com/openbao/openbao/api/v2 v2.5.1/go.mod h1:Dh5un77tqGgMbmlVEqjqN+8/dMyUohnkaQVg/wXW0Ig= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russellhaering/goxmldsig v1.5.0 h1:AU2UkkYIUOTyZRbe08XMThaOCelArgvNfYapcmSjBNw= +github.com/russellhaering/goxmldsig v1.5.0/go.mod h1:x98CjQNFJcWfMxeOrMnMKg70lvDP6tE0nTaeUnjXDmk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= +github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= +github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0= +github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= +go.etcd.io/etcd/api/v3 v3.6.8 h1:gqb1VN92TAI6G2FiBvWcqKtHiIjr4SU2GdXxTwyexbM= +go.etcd.io/etcd/api/v3 v3.6.8/go.mod h1:qyQj1HZPUV3B5cbAL8scG62+fyz5dSxxu0w8pn28N6Q= +go.etcd.io/etcd/client/pkg/v3 v3.6.8 h1:Qs/5C0LNFiqXxYf2GU8MVjYUEXJ6sZaYOz0zEqQgy50= +go.etcd.io/etcd/client/pkg/v3 v3.6.8/go.mod h1:GsiTRUZE2318PggZkAo6sWb6l8JLVrnckTNfbG8PWtw= +go.etcd.io/etcd/client/v3 v3.6.8 h1:B3G76t1UykqAOrbio7s/EPatixQDkQBevN8/mwiplrY= +go.etcd.io/etcd/client/v3 v3.6.8/go.mod h1:MVG4BpSIuumPi+ELF7wYtySETmoTWBHVcDoHdVupwt8= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741 h1:fGZugkZk2UgYBxtpKmvub51Yno1LJDeEsRp2xGD+0gY= +golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= +golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= +golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= +golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY= +golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/api v0.267.0 h1:w+vfWPMPYeRs8qH1aYYsFX68jMls5acWl/jocfLomwE= +google.golang.org/api v0.267.0/go.mod h1:Jzc0+ZfLnyvXma3UtaTl023TdhZu6OMBP9tJ+0EmFD0= +google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= +google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M= +google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= +google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/bridge/idp/locks/inputs.lock b/bridge/idp/locks/inputs.lock new file mode 100644 index 00000000..8f0a8db2 --- /dev/null +++ b/bridge/idp/locks/inputs.lock @@ -0,0 +1,6 @@ +# Public, immutable shell assignments; never source an unreviewed generated file. +DEX_COMMIT=11d2eeb52b42e1980e14cb91e69dd9e3faab2076 +DEX_ARCHIVE_SHA256=18bf92e8ccbf53e86814c2beb39b7d59f28fb07c84639e9f47a9bb5ea764e0b9 +DEX_VERSION=v2.45.1-kars.1 +GO_VERSION=go1.26.8 +SOURCE_DATE_EPOCH=0 diff --git a/bridge/idp/locks/requests.txt b/bridge/idp/locks/requests.txt new file mode 100644 index 00000000..6fc4313b --- /dev/null +++ b/bridge/idp/locks/requests.txt @@ -0,0 +1,10 @@ +github.com/go-jose/go-jose/v4@v4.1.4 +github.com/russellhaering/goxmldsig@v1.6.0 +go.opentelemetry.io/otel@v1.44.0 +go.opentelemetry.io/otel/metric@v1.44.0 +go.opentelemetry.io/otel/trace@v1.44.0 +golang.org/x/crypto@v0.56.0 +golang.org/x/mod@v0.40.0 +golang.org/x/net@v0.58.0 +golang.org/x/text@v0.41.0 +google.golang.org/grpc@v1.83.2 diff --git a/bridge/idp/patches/0001-literal-oauth-error-descriptions.patch b/bridge/idp/patches/0001-literal-oauth-error-descriptions.patch new file mode 100644 index 00000000..5e2c56aa --- /dev/null +++ b/bridge/idp/patches/0001-literal-oauth-error-descriptions.patch @@ -0,0 +1,26 @@ +Subject: [Kars compatibility] Preserve literal preformatted OAuth error descriptions +Upstream: dexidp/dex v2.45.1, 11d2eeb52b42e1980e14cb91e69dd9e3faab2076 +Reason: Go 1.26 vet rejects two nonconstant format arguments. A constant %s +also prevents percent text in an unsupported PKCE method from being formatted +twice. No error type, redirect destination, or validation decision changes. + +--- a/server/oauth2.go ++++ b/server/oauth2.go +@@ -474,7 +474,7 @@ + + if codeChallengeMethod != codeChallengeMethodS256 && codeChallengeMethod != codeChallengeMethodPlain { + description := fmt.Sprintf("Unsupported PKCE challenge method (%q).", codeChallengeMethod) +- return nil, newRedirectedErr(errInvalidRequest, description) ++ return nil, newRedirectedErr(errInvalidRequest, "%s", description) + } + + var ( +@@ -558,7 +558,7 @@ + if rt.token { + if redirectURI == redirectURIOOB { + err := fmt.Sprintf("Cannot use response type 'token' with redirect_uri '%s'.", redirectURIOOB) +- return nil, newRedirectedErr(errInvalidRequest, err) ++ return nil, newRedirectedErr(errInvalidRequest, "%s", err) + } + } + diff --git a/bridge/idp/patches/0002-saml-fixture-validation-clock.patch b/bridge/idp/patches/0002-saml-fixture-validation-clock.patch new file mode 100644 index 00000000..9c6073c8 --- /dev/null +++ b/bridge/idp/patches/0002-saml-fixture-validation-clock.patch @@ -0,0 +1,39 @@ +Subject: [Kars test-only compatibility] Validate the historical OAM signature at fixture time +Upstream: dexidp/dex v2.45.1, 11d2eeb52b42e1980e14cb91e69dd9e3faab2076 +Fixture: connector/saml/testdata/oam-resp.xml IssueInstant 2016-12-12T16:54:35Z +Certificate: oam-ca.pem valid 2016-06-30T04:54:16Z through 2026-06-28T04:54:16Z +Reason: This XML namespace/signature test is not a wall-clock expiry test. +Only this historical fixture selects goxmldsig's supported fake test clock. +All other runVerify callers retain the real clock. Production validation, +the signed XML, and the certificate remain unchanged. + +--- a/connector/saml/saml_test.go ++++ b/connector/saml/saml_test.go +@@ -544,11 +544,16 @@ + func runVerify(t *testing.T, ca string, resp string, shouldSucceed bool) { ++ runVerifyWithClock(t, ca, resp, shouldSucceed, nil) ++} ++ ++func runVerifyWithClock(t *testing.T, ca string, resp string, shouldSucceed bool, clock *dsig.Clock) { + cert, err := loadCert(ca) + if err != nil { + t.Fatal(err) + } + s := certStore{[]*x509.Certificate{cert}} + + validator := dsig.NewDefaultValidationContext(s) ++ validator.Clock = clock + + data, err := os.ReadFile(resp) + if err != nil { +@@ -573,7 +578,9 @@ + func TestVerifyUnsignedMessageAndSignedAssertionWithRootXmlNs(t *testing.T) { +- runVerify(t, "testdata/oam-ca.pem", "testdata/oam-resp.xml", true) ++ // Match the signed fixture's IssueInstant, not the wall clock. ++ clock := dsig.NewFakeClockAt(time.Date(2016, time.December, 12, 16, 54, 35, 0, time.UTC)) ++ runVerifyWithClock(t, "testdata/oam-ca.pem", "testdata/oam-resp.xml", true, clock) + } + + func TestVerifySignedMessageAndUnsignedAssertion(t *testing.T) { + runVerify(t, "testdata/idp-cert.pem", "testdata/idp-resp-signed-message.xml", true) + } diff --git a/bridge/idp/patches/SHA256SUMS b/bridge/idp/patches/SHA256SUMS new file mode 100644 index 00000000..32b5d80b --- /dev/null +++ b/bridge/idp/patches/SHA256SUMS @@ -0,0 +1,7 @@ +8755f6149041ae291a8850de1e6b3012ffcbbaf01a4f259705dcab64645b373f 0001-literal-oauth-error-descriptions.patch +31d1e5b8438325374d2ab973c02eeed1539e4452b57d299ed747feac6c50bda6 0002-saml-fixture-validation-clock.patch +f936045965a7d837c1b5b59b6ea66b4e206b04e8e5c84272036e57e985a1b0d3 patched.sha256 +63da3c3b7a5739568f4e8601daaadd2b5e85e3b4776414d6ed0046c7fb876eff saml_compat_test.go +12b20222b552ad8d21cc5b98cf0abb8685c926c380909e851af75e8b76f30fc0 series +e310d58df8845a7fd8e839a5428880358789bff128b561558dfddd61b7a2853d server_compat_test.go +012b8266acefcfe80fbf0683ed69c4b44c00251d49d25f949f3f4c338deb723b upstream.sha256 diff --git a/bridge/idp/patches/patched.sha256 b/bridge/idp/patches/patched.sha256 new file mode 100644 index 00000000..6a1d541a --- /dev/null +++ b/bridge/idp/patches/patched.sha256 @@ -0,0 +1,4 @@ +c8b250efd8e8d41f88fb21968847e4d82f6eb3738f9815de662b6a7854cddeeb ./server/oauth2.go +de88d7c7361b41e306001280ef2b5f6e01827eff572a0404a047194e660bde31 ./connector/saml/saml_test.go +e310d58df8845a7fd8e839a5428880358789bff128b561558dfddd61b7a2853d ./server/kars_compat_test.go +63da3c3b7a5739568f4e8601daaadd2b5e85e3b4776414d6ed0046c7fb876eff ./connector/saml/kars_compat_test.go diff --git a/bridge/idp/patches/saml_compat_test.go b/bridge/idp/patches/saml_compat_test.go new file mode 100644 index 00000000..9fc1da04 --- /dev/null +++ b/bridge/idp/patches/saml_compat_test.go @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package saml + +import ( + "crypto/x509" + "os" + "strings" + "testing" + "time" + + dsig "github.com/russellhaering/goxmldsig" +) + +func TestKarsSAMLFixtureCertificateValidity(t *testing.T) { + cert, err := loadCert("testdata/oam-ca.pem") + if err != nil { + t.Fatal(err) + } + data, err := os.ReadFile("testdata/oam-resp.xml") + if err != nil { + t.Fatal(err) + } + for _, tc := range []struct { + name string + now time.Time + valid bool + }{ + {"at signed fixture time", time.Date(2016, time.December, 12, 16, 54, 35, 0, time.UTC), true}, + {"before certificate validity", cert.NotBefore.Add(-time.Second), false}, + {"after certificate expiry", cert.NotAfter.Add(time.Second), false}, + } { + t.Run(tc.name, func(t *testing.T) { + validator := dsig.NewDefaultValidationContext(certStore{[]*x509.Certificate{cert}}) + if validator.Clock != nil { + t.Fatal("production validation context must default to the real clock") + } + validator.Clock = dsig.NewFakeClockAt(tc.now) + _, rootVerified, err := verifyResponseSig(validator, data) + if tc.valid { + if err != nil || rootVerified { + t.Fatalf("expected verified assertion with unsigned root: rootVerified=%v, error=%v", rootVerified, err) + } + } else if err == nil || !strings.Contains(err.Error(), "Cert is not valid at this time") { + t.Fatalf("certificate validity must remain enforced, got %v", err) + } + }) + } +} diff --git a/bridge/idp/patches/series b/bridge/idp/patches/series new file mode 100644 index 00000000..3f779661 --- /dev/null +++ b/bridge/idp/patches/series @@ -0,0 +1,2 @@ +0001-literal-oauth-error-descriptions.patch +0002-saml-fixture-validation-clock.patch diff --git a/bridge/idp/patches/server_compat_test.go b/bridge/idp/patches/server_compat_test.go new file mode 100644 index 00000000..26f5f42c --- /dev/null +++ b/bridge/idp/patches/server_compat_test.go @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package server + +import ( + "fmt" + "net/http/httptest" + "net/url" + "testing" + + "github.com/dexidp/dex/storage" +) + +func TestKarsAuthorizationErrorDescriptionsLiteral(t *testing.T) { + for _, tc := range []struct { + name, method, redirectURI, responseType, description string + }{ + { + name: "percent verbs in PKCE method", method: "%s%[1]s%%", + redirectURI: "https://example.invalid/callback", responseType: "code", + description: `Unsupported PKCE challenge method ("%s%[1]s%%").`, + }, + { + name: "ordinary unsupported PKCE method", method: "unsupported", + redirectURI: "https://example.invalid/callback", responseType: "code", + description: `Unsupported PKCE challenge method ("unsupported").`, + }, + { + name: "token with out-of-band redirect", method: codeChallengeMethodS256, + redirectURI: redirectURIOOB, responseType: "code token", + description: fmt.Sprintf("Cannot use response type 'token' with redirect_uri '%s'.", redirectURIOOB), + }, + } { + t.Run(tc.name, func(t *testing.T) { + httpServer, server := newTestServerMultipleConnectors(t, func(c *Config) { + c.SupportedResponseTypes = []string{"code", "token"} + c.Storage = storage.WithStaticClients(c.Storage, []storage.Client{{ + ID: "compat-client", RedirectURIs: []string{tc.redirectURI}, + }}) + }) + defer httpServer.Close() + params := url.Values{ + "client_id": {"compat-client"}, "redirect_uri": {tc.redirectURI}, + "response_type": {tc.responseType}, "scope": {"openid"}, + "state": {"literal-state%25"}, "code_challenge_method": {tc.method}, + "code_challenge": {"challenge"}, + } + req := httptest.NewRequest("GET", httpServer.URL+"/auth?"+params.Encode(), nil) + _, err := server.parseAuthorizationRequest(req) + redirected, ok := err.(*redirectedAuthErr) + if !ok { + t.Fatalf("expected redirectedAuthErr, got %T: %v", err, err) + } + if redirected.Type != errInvalidRequest || redirected.RedirectURI != tc.redirectURI || + redirected.State != params.Get("state") || redirected.Description != tc.description { + t.Fatalf("redirected error = %+v; expected unchanged type/state/URI and literal description %q", + redirected, tc.description) + } + }) + } +} diff --git a/bridge/idp/patches/upstream.sha256 b/bridge/idp/patches/upstream.sha256 new file mode 100644 index 00000000..ba5588c8 --- /dev/null +++ b/bridge/idp/patches/upstream.sha256 @@ -0,0 +1,2 @@ +4dbc9a51b9b65b2295aaff258a36eced579c6b9b0b42816eacd179cd15f33cc7 ./server/oauth2.go +88e5ed609e7cf652d7ffb404ad15fab322f88d24627bfac9df453f1656a56395 ./connector/saml/saml_test.go diff --git a/bridge/idp/scripts/apply-source-patches.sh b/bridge/idp/scripts/apply-source-patches.sh new file mode 100644 index 00000000..cf90dc3e --- /dev/null +++ b/bridge/idp/scripts/apply-source-patches.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +set -eu +packaging="${1:-/packaging}" +patches="$packaging/patches" +(cd "$patches" && sha256sum --check --strict SHA256SUMS) +sha256sum --check --strict --quiet "$packaging/source.upstream.sha256" +sha256sum --check --strict "$patches/upstream.sha256" +while IFS= read -r name; do + git apply --no-index --check --whitespace=error-all "$patches/$name" + git apply --no-index --whitespace=error-all "$patches/$name" +done < "$patches/series" +test ! -e server/kars_compat_test.go +test ! -e connector/saml/kars_compat_test.go +cp "$patches/server_compat_test.go" server/kars_compat_test.go +cp "$patches/saml_compat_test.go" connector/saml/kars_compat_test.go +sha256sum --check --strict "$patches/patched.sha256" + +# Build the EXPECTED inventory from the verified original plus only the +# reviewed replacement/addition hashes, never from whatever patch produced. +awk 'NR == FNR { replacement[$2] = $1; next } + { if ($2 in replacement) { + print replacement[$2] " " $2; delete replacement[$2] + } else { print } } + END { for (name in replacement) print replacement[name] " " name }' \ + "$patches/patched.sha256" "$packaging/source.upstream.sha256" \ + | LC_ALL=C sort -k2 > "$packaging/source.sha256" +sha256sum --check --strict --quiet "$packaging/source.sha256" +sh "$packaging/scripts/source-inventory.sh" > "$packaging/source.actual.sha256" +cmp "$packaging/source.sha256" "$packaging/source.actual.sha256" diff --git a/bridge/idp/scripts/build.sh b/bridge/idp/scripts/build.sh new file mode 100644 index 00000000..8fd87185 --- /dev/null +++ b/bridge/idp/scripts/build.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +set -eu +. /packaging/locks/inputs.lock +export SOURCE_DATE_EPOCH +mkdir -p /out/doc /out/etc /out/data +sha256sum --check --strict /packaging/source.sha256 > /dev/null +# No CGO disablement, custom build tags, static libc or copied library closure. +go build -trimpath -buildvcs=false -ldflags="-w -buildid= -X main.version=$DEX_VERSION" \ + -o /out/dex ./cmd/dex +go version -m /out/dex > /out/doc/build-info.txt +readelf --wide --dynamic /out/dex > /out/doc/elf-dynamic.txt +readelf --wide --program-headers /out/dex > /out/doc/elf-program-headers.txt +readelf --wide --version-info /out/dex > /out/doc/elf-versions.txt +grep -q 'CGO_ENABLED=1' /out/doc/build-info.txt +cp LICENSE /out/doc/DEX-LICENSE +if test -f NOTICE; then cp NOTICE /out/doc/DEX-NOTICE; fi +cp /packaging/NOTICE /out/doc/KARS-NOTICE +cp /packaging/LICENSE /out/doc/KARS-LICENSE +cp /packaging/README.md /out/doc/PACKAGING-README.md +cp -R /locks /out/doc/locks +cp -R /packaging/patches /out/doc/source-patches +cp /packaging/source.upstream.sha256 /packaging/source.sha256 /out/doc/ +go list -deps -json ./cmd/dex > /tmp/dex-packages.json +go run /packaging/scripts/notices.go /tmp/dex-packages.json /out/doc/third-party +sha256sum --check --strict /packaging/source.sha256 > /dev/null +cmp go.mod /locks/go.mod +cmp go.sum /locks/go.sum +cmp api/v2/go.mod /locks/api/v2/go.mod +cmp api/v2/go.sum /locks/api/v2/go.sum diff --git a/bridge/idp/scripts/fetch-source.sh b/bridge/idp/scripts/fetch-source.sh new file mode 100644 index 00000000..133f9d10 --- /dev/null +++ b/bridge/idp/scripts/fetch-source.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +set -eu +. /packaging/locks/inputs.lock +test "$(go env GOVERSION)" = "$GO_VERSION" +curl --fail --silent --show-error --location --proto '=https' --tlsv1.2 \ + "https://codeload.github.com/dexidp/dex/tar.gz/$DEX_COMMIT" -o /tmp/dex.tar.gz +printf '%s %s\n' "$DEX_ARCHIVE_SHA256" /tmp/dex.tar.gz | sha256sum --check --strict +tar -xzf /tmp/dex.tar.gz --strip-components=1 -C /src/dex +rm /tmp/dex.tar.gz +sh /packaging/scripts/source-inventory.sh > /packaging/source.upstream.sha256 +mkdir -p /packaging/upstream/api/v2 +cp go.mod go.sum /packaging/upstream/ +cp api/v2/go.mod api/v2/go.sum /packaging/upstream/api/v2/ +sh /packaging/scripts/apply-source-patches.sh diff --git a/bridge/idp/scripts/generate-locks.sh b/bridge/idp/scripts/generate-locks.sh new file mode 100644 index 00000000..2aee2c21 --- /dev/null +++ b/bridge/idp/scripts/generate-locks.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +set -eu +. /packaging/locks/inputs.lock +export GOFLAGS=-mod=mod +mkdir -p /out/api/v2 + +# Update the nested API as well as the application; the local replace is retained. +( + cd api/v2 + go mod edit -go=1.26.0 -toolchain="$GO_VERSION" + go get google.golang.org/grpc@v1.83.2 golang.org/x/crypto@v0.56.0 + go mod tidy + go mod download + go mod verify + go list -m -json all > /out/api-modules.json +) +go mod edit -go=1.26.0 -toolchain="$GO_VERSION" +set -- +while IFS= read -r request; do + test -n "$request" + set -- "$@" "$request" +done < /packaging/locks/requests.txt +go get "$@" +go mod tidy +go mod download +go mod verify +sha256sum --check --strict /packaging/source.sha256 > /dev/null +go list -m -json all > /out/modules.json +go mod graph > /out/graph.txt +go version > /out/toolchain.txt +cp go.mod go.sum /out/ +cp api/v2/go.mod api/v2/go.sum /out/api/v2/ +cp /packaging/locks/inputs.lock /packaging/locks/requests.txt /out/ +cp -R /packaging/upstream /out/upstream +: > /out/dependencies.patch +for file in go.mod go.sum api/v2/go.mod api/v2/go.sum; do + set +e + diff -u --label "upstream/$file" --label "kars/$file" \ + "/packaging/upstream/$file" "/out/$file" >> /out/dependencies.patch + status=$? + set -e + test "$status" -le 1 +done +( + cd /out + find . -type f ! -name SHA256SUMS -print0 | LC_ALL=C sort -z \ + | xargs -0 sha256sum > SHA256SUMS +) +# ACR --no-push runs can return this public artifact via their build log. +tar --sort=name --mtime="@$SOURCE_DATE_EPOCH" --owner=0 --group=0 \ + -C /out -cf /tmp/dex-locks.tar . +gzip -n /tmp/dex-locks.tar +printf '\nKARS_DEX_LOCKS_BASE64_BEGIN\n' +base64 -w 0 /tmp/dex-locks.tar.gz +printf '\nKARS_DEX_LOCKS_BASE64_END\n' +sha256sum /tmp/dex-locks.tar.gz diff --git a/bridge/idp/scripts/import-locks.py b/bridge/idp/scripts/import-locks.py new file mode 100644 index 00000000..107e0188 --- /dev/null +++ b/bridge/idp/scripts/import-locks.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +"""Import public Go-generated artifacts from an ACR --no-push build log.""" + +import base64 +import gzip +import hashlib +import io +from pathlib import Path +import re +import shutil +import sys +import tarfile +import tempfile +import zlib + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT / "tests")) +from contracts import LOCK_FILES, check_modules, require + +MAX_ARCHIVE_BYTES = 16 * 1024 * 1024 + + +def decode_artifact(log): + blocks = re.findall( + r"(?m)^KARS_DEX_LOCKS_BASE64_BEGIN\r?\n([A-Za-z0-9+/=]+)\r?\nKARS_DEX_LOCKS_BASE64_END\r?$", + log, + ) + require(len(blocks) == 1, "expected exactly one unprefixed lock artifact in the raw ACR log") + require(len(blocks[0]) < 8 * 1024 * 1024, "unexpectedly large lock artifact") + payload = base64.b64decode(blocks[0], validate=True) + digests = re.findall(r"(?m)^([0-9a-f]{64}) /tmp/dex-locks\.tar\.gz\r?$", log) + require(len(digests) == 1 and hashlib.sha256(payload).hexdigest() == digests[0], + "missing or mismatched transport SHA-256") + # Bound the entire tar, including headers and directory entries, before + # tarfile can allocate an unbounded member index for a compressed archive. + with gzip.GzipFile(fileobj=io.BytesIO(payload)) as compressed: + expanded = compressed.read(MAX_ARCHIVE_BYTES + 1) + require(len(expanded) <= MAX_ARCHIVE_BYTES, "expanded artifact exceeds bounded lock size") + result = {} + size = 0 + with tarfile.open(fileobj=io.BytesIO(expanded), mode="r:") as archive: + for member in archive: + path = Path(member.name) + require(not path.is_absolute() and ".." not in path.parts, "unsafe archive path") + if member.isdir(): + continue + name = str(path) + require(member.isfile() and name in LOCK_FILES and name not in result, + f"unexpected or duplicate lock member: {name}") + size += member.size + require(size <= MAX_ARCHIVE_BYTES, "expanded artifact exceeds bounded lock size") + with archive.extractfile(member) as stream: + result[name] = stream.read() + require(set(result) == LOCK_FILES, "incomplete Go resolver artifact") + return result + + +def main(): + require(len(sys.argv) == 2, "usage: import-locks.py raw-acr-build.log") + target = ROOT / "locks/generated" + require(not target.exists(), "generated locks already exist; review them rather than overwriting") + files = decode_artifact(Path(sys.argv[1]).read_text()) + with tempfile.TemporaryDirectory(prefix=".dex-lock-import-", dir=ROOT / "locks") as temporary: + stage = Path(temporary) + generated = stage / "locks/generated" + generated.mkdir(parents=True) + for name, data in files.items(): + path = generated / name + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(data) + for name in ("inputs.lock", "requests.txt"): + shutil.copyfile(ROOT / "locks" / name, stage / "locks" / name) + check_modules(stage) + generated.rename(target) + print("Imported Go-generated locks. Review dependencies.patch and all selected modules before building.") + + +if __name__ == "__main__": + try: + main() + except (ValueError, OSError, EOFError, tarfile.TarError, zlib.error) as error: + raise SystemExit(str(error)) from None diff --git a/bridge/idp/scripts/notices.go b/bridge/idp/scripts/notices.go new file mode 100644 index 00000000..b3ff23f5 --- /dev/null +++ b/bridge/idp/scripts/notices.go @@ -0,0 +1,123 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Collect notices from actual linked modules, not from the entire module cache. +package main + +import ( + "encoding/json" + "fmt" + "io" + "io/fs" + "os" + "path/filepath" + "runtime" + "sort" + "strings" +) + +type module struct { + Path, Version, Dir string + Main bool + Replace *module +} + +func run() error { + if len(os.Args) != 3 { + return fmt.Errorf("usage: notices packages.json output-directory") + } + f, err := os.Open(os.Args[1]) + if err != nil { + return err + } + defer f.Close() + decoder := json.NewDecoder(f) + modules := map[string]module{ + "golang.org/toolchain@" + runtime.Version(): {Dir: runtime.GOROOT()}, + } + for { + var pkg struct{ Module *module } + if err := decoder.Decode(&pkg); err != nil { + if err == io.EOF { + break + } + return err + } + if pkg.Module == nil || pkg.Module.Main { + continue + } + m := *pkg.Module + if m.Replace != nil { + m.Dir = m.Replace.Dir + } + modules[m.Path+"@"+m.Version] = m + } + keys := make([]string, 0, len(modules)) + for key := range modules { + keys = append(keys, key) + } + sort.Strings(keys) + for _, key := range keys { + m := modules[key] + rootLicense := false + err := filepath.WalkDir(m.Dir, func(path string, entry fs.DirEntry, err error) error { + if err != nil { + return err + } + name := strings.ToUpper(entry.Name()) + if entry.IsDir() { + return nil + } + if !strings.HasPrefix(name, "LICENSE") && !strings.HasPrefix(name, "LICENCE") && !strings.HasPrefix(name, "COPYING") && + !strings.HasPrefix(name, "NOTICE") && !strings.HasPrefix(name, "COPYRIGHT") && + name != "AUTHORS" && name != "PATENTS" { + return nil + } + rel, err := filepath.Rel(m.Dir, path) + if err != nil { + return err + } + if filepath.Dir(rel) == "." && (strings.HasPrefix(name, "LICENSE") || strings.HasPrefix(name, "LICENCE") || strings.HasPrefix(name, "COPYING")) { + rootLicense = true + } + dest := filepath.Join(os.Args[2], key, rel) + if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { + return err + } + data, err := os.ReadFile(path) + if err != nil { + return err + } + return os.WriteFile(dest, data, 0644) + }) + if err != nil { + return fmt.Errorf("%s: %w", key, err) + } + // Dex's nested API is licensed by the upstream repository root. + if !rootLicense && m.Path == "github.com/dexidp/dex/api/v2" { + data, err := os.ReadFile("/src/dex/LICENSE") + if err != nil { + return err + } + dest := filepath.Join(os.Args[2], key) + if err := os.MkdirAll(dest, 0755); err != nil { + return err + } + if err := os.WriteFile(filepath.Join(dest, "LICENSE"), data, 0644); err != nil { + return err + } + rootLicense = true + } + if !rootLicense { + return fmt.Errorf("%s: missing root license; review upstream attribution before shipping", key) + } + } + return os.WriteFile(filepath.Join(os.Args[2], "MODULES"), []byte(strings.Join(keys, "\n")+"\n"), 0644) +} + +func main() { + if err := run(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/bridge/idp/scripts/source-inventory.sh b/bridge/idp/scripts/source-inventory.sh new file mode 100644 index 00000000..ef624b91 --- /dev/null +++ b/bridge/idp/scripts/source-inventory.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +set -eu +# Dependency manifests are verified separately against the generated Go locks. +find . -type f ! -path './go.mod' ! -path './go.sum' \ + ! -path './api/v2/go.mod' ! -path './api/v2/go.sum' \ + -print0 | LC_ALL=C sort -z | xargs -0 sha256sum diff --git a/bridge/idp/scripts/upstream-tests.sh b/bridge/idp/scripts/upstream-tests.sh new file mode 100644 index 00000000..e2e6f4ee --- /dev/null +++ b/bridge/idp/scripts/upstream-tests.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +set -eu +if ! go test -json -count=1 -race ./... > /out/doc/upstream-tests.json; then + cat /out/doc/upstream-tests.json + exit 1 +fi +cd api/v2 +if ! go test -json -count=1 -race ./... > /out/doc/api-tests.json; then + cat /out/doc/api-tests.json + exit 1 +fi diff --git a/bridge/idp/scripts/verify-locks.sh b/bridge/idp/scripts/verify-locks.sh new file mode 100644 index 00000000..1e7858c3 --- /dev/null +++ b/bridge/idp/scripts/verify-locks.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +set -eu +. /packaging/locks/inputs.lock +(cd /locks && sha256sum --check --strict SHA256SUMS) +cmp /packaging/locks/inputs.lock /locks/inputs.lock +cmp /packaging/locks/requests.txt /locks/requests.txt +test "$(cat /locks/toolchain.txt)" = "go version $GO_VERSION linux/$(go env GOARCH)" +for file in go.mod go.sum api/v2/go.mod api/v2/go.sum; do + cmp "/packaging/upstream/$file" "/locks/upstream/$file" + cp "/locks/$file" "$file" +done +test "$(go list -m -f '{{.GoVersion}}')" = 1.26.0 +replacements="$(go list -m -f '{{if .Replace}}{{.Path}} => {{.Replace.Path}}{{end}}' all)" +test "$(printf '%s\n' "$replacements" | sed '/^$/d')" = 'github.com/dexidp/dex/api/v2 => ./api/v2' +while IFS=@ read -r module version; do + # Exact requests are the approved selection, not merely scanner floors. + test "$(go list -m -f '{{.Version}}' "$module")" = "$version" +done < /packaging/locks/requests.txt +( + cd api/v2 + test "$(go list -m -f '{{.GoVersion}}')" = 1.26.0 + test "$(go list -m -f '{{.Version}}' google.golang.org/grpc)" = v1.83.2 + replacements="$(go list -m -f '{{if .Replace}}{{.Path}}{{end}}' all)" + test -z "$(printf '%s\n' "$replacements" | sed '/^$/d')" +) +sha256sum --check --strict /packaging/source.sha256 > /dev/null diff --git a/bridge/idp/tests/contracts.py b/bridge/idp/tests/contracts.py new file mode 100644 index 00000000..4847b2d0 --- /dev/null +++ b/bridge/idp/tests/contracts.py @@ -0,0 +1,135 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import hashlib +import json +from pathlib import Path +import re + +BASE = ( + "mcr.microsoft.com/azurelinux/distroless/base:3.0@sha256:" + "4377af4aa7a810b7d59f691eae5066895a71aa3eee4cfb4eba527bbebff16479" +) +RPM_MANIFEST = "var/lib/rpmmanifest/container-manifest-2" +LOCK_FILES = { + "go.mod", "go.sum", "api/v2/go.mod", "api/v2/go.sum", + "upstream/go.mod", "upstream/go.sum", "upstream/api/v2/go.mod", "upstream/api/v2/go.sum", + "modules.json", "api-modules.json", "graph.txt", "toolchain.txt", + "inputs.lock", "requests.txt", "dependencies.patch", "SHA256SUMS", +} + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def json_stream(text): + decoder = json.JSONDecoder() + while text.strip(): + text = text.lstrip() + value, end = decoder.raw_decode(text) + yield value + text = text[end:] + + +def module_inventory(text): + modules = {} + for module in json_stream(text): + require(isinstance(module, dict) and isinstance(module.get("Path"), str), + "invalid module inventory record") + require(not module.get("Error"), f"module resolver error: {module['Path']}") + require(module["Path"] not in modules, f"duplicate module inventory: {module['Path']}") + modules[module["Path"]] = module + return modules + + +def check_modules(root): + """Validate the reviewed resolver artifact, without inventing Go checksums.""" + root = Path(root) + generated = root / "locks/generated" + require(generated.is_dir(), "hosted generated locks are missing; runtime build is blocked") + require(not generated.is_symlink(), "lock artifact cannot be a symlink") + entries = list(generated.rglob("*")) + require(not any(path.is_symlink() for path in entries), "lock artifact cannot contain symlinks") + actual = {str(path.relative_to(generated)) for path in entries if path.is_file()} + require(actual == LOCK_FILES, "unexpected or missing lock artifact files") + for name in ("inputs.lock", "requests.txt"): + require((generated / name).read_bytes() == (root / "locks" / name).read_bytes(), + f"resolver input drift: {name}") + records = {} + for line in (generated / "SHA256SUMS").read_text().splitlines(): + digest, name = line.split(" ", 1) + require(re.fullmatch(r"[0-9a-f]{64}", digest), "invalid artifact SHA-256") + path = Path(name) + require(not path.is_absolute() and ".." not in path.parts, "unsafe checksum path") + require(name not in records, "duplicate checksum path") + records[name] = digest + require(hashlib.sha256((generated / path).read_bytes()).hexdigest() == digest, + f"artifact digest mismatch: {name}") + require({"./" + name for name in actual - {"SHA256SUMS"}} == set(records), + "artifact checksum coverage is incomplete") + require(re.fullmatch(r"go version go1\.26\.8 linux/(amd64|arm64)\n", + (generated / "toolchain.txt").read_text()), + "unexpected resolver toolchain") + inventories = {name: module_inventory((generated / name).read_text()) + for name in ("modules.json", "api-modules.json")} + selected = inventories["modules.json"] + for line in (root / "locks/requests.txt").read_text().splitlines(): + name, version = line.split("@") + require(selected.get(name, {}).get("Version") == version, f"unreviewed selection: {name}") + require("Replace" not in selected[name], f"unexpected replacement: {name}") + for name, modules in inventories.items(): + expected_main = "github.com/dexidp/dex" + ("/api/v2" if name == "api-modules.json" else "") + require([m["Path"] for m in modules.values() if m.get("Main")] == [expected_main], + f"unexpected main module in {name}") + for module in modules.values(): + if "Replace" in module: + require(name == "modules.json" and module["Path"] == "github.com/dexidp/dex/api/v2" and + module["Replace"]["Path"] == "./api/v2", + f"unexpected module replacement in {name}") + require(selected.get("github.com/dexidp/dex/api/v2", {}).get("Replace", {}).get("Path") == "./api/v2", + "upstream local API replacement is missing") + api = inventories["api-modules.json"] + require(api.get("google.golang.org/grpc", {}).get("Version") == "v1.83.2", "nested API gRPC is unpatched") + for name in ("go.mod", "api/v2/go.mod"): + manifest = (generated / name).read_text() + require("\ngo 1.26.0\n" in manifest, f"unexpected Go requirement: {name}") + # Go may omit a redundant toolchain directive; the pinned builder and + # GOTOOLCHAIN=local remain authoritative in that case. + directives = [line for line in manifest.splitlines() if line.startswith("toolchain ")] + require(not directives or directives == ["toolchain go1.26.8"], + f"unexpected automatic toolchain: {name}") + + +def check_rootfs(base, runtime, manifest): + # Docker injects these three per-container files during export. + injected = {"etc/hosts", "etc/hostname", "etc/resolv.conf"} + for name, record in base.items(): + if name not in injected: + require(runtime.get(name) == record, f"base file modified/removed: {name}") + require(len(manifest.strip().splitlines()) == 14, "expected 14 Azure Linux RPM inventory records") + require(RPM_MANIFEST in runtime, "RPM inventory missing") + require(any("ca-trust" in name or name.endswith("ca-certificates.crt") for name in base), + "base CA trust inventory missing") + for name in runtime.keys() - base.keys() - injected: + require(name == "usr/local/bin/dex" or + name.startswith(("srv/dex/web/", "usr/share/doc/dex/")), + f"unexpected runtime payload: {name}") + for name in ("usr/local/bin/docker-entrypoint", "usr/local/bin/gomplate", + "bin/sh", "bin/bash", "usr/bin/sh", "usr/bin/bash", + "usr/bin/tdnf", "usr/bin/npm", "usr/local/go/bin/go", "usr/bin/gcc"): + require(name not in runtime, f"shipping tool/unused entrypoint: {name}") + + +def check_scan(report): + require(report.get("Metadata", {}).get("OS", {}).get("Family") == "azurelinux", + "scanner failed to identify Azure Linux") + results = report.get("Results", []) + require(any(r.get("Type") == "gobinary" and r["Target"].lstrip("/") == "usr/local/bin/dex" + for r in results), "scanner failed to inventory the Dex Go binary") + for result in results: + require(not result.get("Vulnerabilities"), "HIGH/CRITICAL scan findings remain") + os_results = [r for r in results if r.get("Class") == "os-pkgs"] + packages = {p["Name"] for r in os_results for p in r.get("Packages", [])} + require(len(packages) == 14, "scanner did not inventory all 14 base RPM packages") diff --git a/bridge/idp/tests/probe.go b/bridge/idp/tests/probe.go new file mode 100644 index 00000000..f23316bb --- /dev/null +++ b/bridge/idp/tests/probe.go @@ -0,0 +1,532 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Hosted-only black-box checks against the actual distroless Dex container. +package main + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "math/big" + "net/http" + "net/http/cookiejar" + "net/url" + "os" + "path/filepath" + "strings" + "time" + + "golang.org/x/crypto/bcrypt" + "golang.org/x/net/html" +) + +const ( + clientID = "kars-packaging-probe" + email = "packaging-test@example.invalid" + callback = "http://127.0.0.1:18999/callback" +) + +type credentials struct { + Password string + Refresh string + Nonce string + IDToken string + SigningKey signingKeyIdentity +} + +type signingKeyIdentity struct { + Kid string + Modulus string + Exponent int +} + +type verifiedIDToken struct { + Subject string + SigningKey signingKeyIdentity +} + +type tokenSet struct { + Access string `json:"access_token"` + ID string `json:"id_token"` + Refresh string `json:"refresh_token"` + Type string `json:"token_type"` +} + +func randomToken() (string, error) { + b := make([]byte, 32) + if _, err := rand.Read(b); err != nil { + return "", err + } + return base64.RawURLEncoding.EncodeToString(b), nil +} + +func writeJSON(path string, value any, mode os.FileMode) error { + b, err := json.MarshalIndent(value, "", " ") + if err != nil { + return err + } + return os.WriteFile(path, b, mode) +} + +func configure(issuer, dir, storage string) error { + if storage != "memory" && storage != "sqlite3" { + return fmt.Errorf("unsupported test storage %q", storage) + } + password, err := randomToken() + if err != nil { + return err + } + hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return err + } + store := map[string]any{"type": storage} + if storage == "sqlite3" { + store["config"] = map[string]any{"file": "/var/dex/dex.db"} + if err := os.Chown("/var/dex", 1001, 1001); err != nil { + return err + } + } + config := map[string]any{ + "issuer": issuer, "storage": store, + "web": map[string]any{"http": "0.0.0.0:5556"}, + "frontend": map[string]any{"dir": "/srv/dex/web"}, + "oauth2": map[string]any{"skipApprovalScreen": true}, + "staticClients": []any{map[string]any{ + "id": clientID, "name": "Ephemeral packaging test", + "secretEnv": "DEX_TEST_CLIENT_SECRET", "redirectURIs": []string{callback}, + }}, + "enablePasswordDB": true, + "staticPasswords": []any{map[string]any{ + "email": email, "hash": string(hash), "username": "packaging-test", + "userID": "286e3ba6-cfb5-47e1-a5ae-66b290626b66", + }}, + } + if err := writeJSON(filepath.Join(dir, "config.yaml"), config, 0644); err != nil { + return err + } + return writeJSON(filepath.Join(dir, "credentials.json"), credentials{Password: password}, 0600) +} + +func client() (*http.Client, error) { + jar, err := cookiejar.New(nil) + if err != nil { + return nil, err + } + return &http.Client{ + Jar: jar, Timeout: 10 * time.Second, + CheckRedirect: func(req *http.Request, via []*http.Request) error { + if strings.HasPrefix(req.URL.String(), callback+"?") { + return http.ErrUseLastResponse + } + if len(via) >= 10 { + return fmt.Errorf("too many redirects") + } + return nil + }, + }, nil +} + +func getJSON(c *http.Client, endpoint string, result any) error { + resp, err := c.Get(endpoint) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("GET %s returned %d", endpoint, resp.StatusCode) + } + return json.NewDecoder(io.LimitReader(resp.Body, 1<<20)).Decode(result) +} + +func login(issuer, password, verifier, nonce string, shouldSucceed bool) (string, error) { + c, err := client() + if err != nil { + return "", err + } + state, err := randomToken() + if err != nil { + return "", err + } + challenge := sha256.Sum256([]byte(verifier)) + query := url.Values{ + "client_id": {clientID}, "redirect_uri": {callback}, "response_type": {"code"}, + "scope": {"openid profile email offline_access"}, "state": {state}, "nonce": {nonce}, + "code_challenge": {base64.RawURLEncoding.EncodeToString(challenge[:])}, + "code_challenge_method": {"S256"}, "connector_id": {"local"}, + } + resp, err := c.Get(issuer + "/auth?" + query.Encode()) + if err != nil { + return "", err + } + doc, parseErr := html.Parse(io.LimitReader(resp.Body, 1<<20)) + resp.Body.Close() + if parseErr != nil { + return "", parseErr + } + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("login page returned %d", resp.StatusCode) + } + action := "" + foundForm, foundPassword := false, false + fields := url.Values{} + var visit func(*html.Node) + visit = func(n *html.Node) { + attrs := map[string]string{} + for _, a := range n.Attr { + attrs[a.Key] = a.Val + } + if n.Type == html.ElementNode && n.Data == "form" { + action, foundForm = attrs["action"], true + } + if n.Type == html.ElementNode && n.Data == "input" { + if attrs["type"] == "hidden" { + fields.Set(attrs["name"], attrs["value"]) + } + if attrs["name"] == "password" { + foundPassword = true + } + } + for child := n.FirstChild; child != nil; child = child.NextSibling { + visit(child) + } + } + visit(doc) + if !foundForm || !foundPassword { + return "", fmt.Errorf("real password login form missing") + } + target, err := resp.Request.URL.Parse(action) + if err != nil { + return "", err + } + if target.Host != resp.Request.URL.Host || target.Scheme != resp.Request.URL.Scheme { + return "", fmt.Errorf("login form leaves issuer origin") + } + fields.Set("login", email) + fields.Set("password", password) + resp, err = c.PostForm(target.String(), fields) + if err != nil { + return "", err + } + defer resp.Body.Close() + location := resp.Header.Get("Location") + if !shouldSucceed { + if resp.StatusCode != http.StatusOK || strings.HasPrefix(location, callback) { + return "", fmt.Errorf("invalid password did not remain on login form") + } + body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) + if err != nil { + return "", err + } + if !strings.Contains(string(body), `id="login-error"`) { + return "", fmt.Errorf("invalid password rejection missing") + } + return "", nil + } + if (resp.StatusCode != 302 && resp.StatusCode != 303) || !strings.HasPrefix(location, callback+"?") { + return "", fmt.Errorf("authorization did not redirect to registered callback: status %d", resp.StatusCode) + } + redirect, err := url.Parse(location) + if err != nil { + return "", err + } + if redirect.Query().Get("state") != state || redirect.Query().Get("code") == "" || redirect.Query().Get("error") != "" { + return "", fmt.Errorf("authorization code/state response invalid") + } + return redirect.Query().Get("code"), nil +} + +func exchange(issuer, secret string, form url.Values, shouldSucceed bool) (tokenSet, error) { + c, err := client() + if err != nil { + return tokenSet{}, err + } + req, err := http.NewRequest(http.MethodPost, issuer+"/token", strings.NewReader(form.Encode())) + if err != nil { + return tokenSet{}, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.SetBasicAuth(clientID, secret) + resp, err := c.Do(req) + if err != nil { + return tokenSet{}, err + } + defer resp.Body.Close() + if !shouldSucceed { + var rejection struct{ Error string } + if err := json.NewDecoder(resp.Body).Decode(&rejection); err != nil { + return tokenSet{}, err + } + if resp.StatusCode < 400 || resp.StatusCode >= 500 || rejection.Error == "" { + return tokenSet{}, fmt.Errorf("invalid token request was not rejected") + } + return tokenSet{}, nil + } + if resp.StatusCode != http.StatusOK { + return tokenSet{}, fmt.Errorf("token endpoint returned %d", resp.StatusCode) + } + var tokens tokenSet + if err := json.NewDecoder(resp.Body).Decode(&tokens); err != nil { + return tokens, err + } + if tokens.Access == "" || tokens.ID == "" || tokens.Refresh == "" || !strings.EqualFold(tokens.Type, "bearer") { + return tokens, fmt.Errorf("incomplete token response") + } + return tokens, nil +} + +func verifyIDToken(c *http.Client, issuer, nonce, idToken string) (verifiedIDToken, error) { + parts := strings.Split(idToken, ".") + if len(parts) != 3 { + return verifiedIDToken{}, fmt.Errorf("invalid ID token shape") + } + decode := base64.RawURLEncoding.DecodeString + headerBytes, err := decode(parts[0]) + if err != nil { + return verifiedIDToken{}, err + } + var header struct{ Alg, Kid string } + if err := json.Unmarshal(headerBytes, &header); err != nil { + return verifiedIDToken{}, err + } + if header.Alg != "RS256" || header.Kid == "" { + return verifiedIDToken{}, fmt.Errorf("unexpected JWT algorithm or missing kid") + } + var jwks struct{ Keys []struct{ Kty, Kid, N, E string } } + if err := getJSON(c, issuer+"/keys", &jwks); err != nil { + return verifiedIDToken{}, err + } + var key *rsa.PublicKey + for _, jwk := range jwks.Keys { + if jwk.Kid != header.Kid || jwk.Kty != "RSA" { + continue + } + n, err := decode(jwk.N) + if err != nil { + return verifiedIDToken{}, err + } + e, err := decode(jwk.E) + if err != nil { + return verifiedIDToken{}, err + } + exponent := new(big.Int).SetBytes(e) + if exponent.BitLen() > 31 || exponent.Int64() < 3 { + return verifiedIDToken{}, fmt.Errorf("invalid RSA exponent") + } + key = &rsa.PublicKey{N: new(big.Int).SetBytes(n), E: int(exponent.Int64())} + } + if key == nil || key.N.BitLen() < 2048 { + return verifiedIDToken{}, fmt.Errorf("matching strong JWKS signing key missing") + } + signature, err := decode(parts[2]) + if err != nil { + return verifiedIDToken{}, err + } + digest := sha256.Sum256([]byte(parts[0] + "." + parts[1])) + if err := rsa.VerifyPKCS1v15(key, crypto.SHA256, digest[:], signature); err != nil { + return verifiedIDToken{}, err + } + payload, err := decode(parts[1]) + if err != nil { + return verifiedIDToken{}, err + } + var claims struct { + Iss, Sub, Nonce, Email string + Aud json.RawMessage + Exp int64 + EmailVerified bool `json:"email_verified"` + } + if err := json.Unmarshal(payload, &claims); err != nil { + return verifiedIDToken{}, err + } + var audience string + var audiences []string + if err := json.Unmarshal(claims.Aud, &audience); err != nil { + if err := json.Unmarshal(claims.Aud, &audiences); err != nil { + return verifiedIDToken{}, err + } + if len(audiences) == 1 { + audience = audiences[0] + } + } + if claims.Iss != issuer || audience != clientID || claims.Nonce != nonce || + claims.Exp <= time.Now().Unix() || claims.Sub == "" || claims.Email != email || !claims.EmailVerified { + return verifiedIDToken{}, fmt.Errorf("signed ID token claims mismatch") + } + return verifiedIDToken{ + Subject: claims.Sub, + SigningKey: signingKeyIdentity{ + Kid: header.Kid, Modulus: base64.RawURLEncoding.EncodeToString(key.N.Bytes()), Exponent: key.E, + }, + }, nil +} + +func verify(issuer, nonce string, tokens tokenSet) (signingKeyIdentity, error) { + c, err := client() + if err != nil { + return signingKeyIdentity{}, err + } + verified, err := verifyIDToken(c, issuer, nonce, tokens.ID) + if err != nil { + return signingKeyIdentity{}, err + } + req, err := http.NewRequest(http.MethodGet, issuer+"/userinfo", nil) + if err != nil { + return signingKeyIdentity{}, err + } + req.Header.Set("Authorization", "Bearer "+tokens.Access) + resp, err := c.Do(req) + if err != nil { + return signingKeyIdentity{}, err + } + defer resp.Body.Close() + var user struct{ Sub, Email string } + if resp.StatusCode != 200 { + return signingKeyIdentity{}, fmt.Errorf("userinfo returned %d", resp.StatusCode) + } + if err := json.NewDecoder(resp.Body).Decode(&user); err != nil { + return signingKeyIdentity{}, err + } + if user.Sub != verified.Subject || user.Email != email { + return signingKeyIdentity{}, fmt.Errorf("userinfo identity mismatch") + } + return verified.SigningKey, nil +} + +func check(issuer, dir, mode string) error { + c, err := client() + if err != nil { + return err + } + var discovery struct { + Issuer string + Auth string `json:"authorization_endpoint"` + Token string `json:"token_endpoint"` + JWKS string `json:"jwks_uri"` + PKCE []string `json:"code_challenge_methods_supported"` + } + var readyErr error + for attempt := 0; attempt < 60; attempt++ { + readyErr = getJSON(c, issuer+"/.well-known/openid-configuration", &discovery) + if readyErr == nil { + break + } + time.Sleep(time.Second) + } + if readyErr != nil { + return fmt.Errorf("discovery never became ready: %w", readyErr) + } + if discovery.Issuer != issuer || discovery.Auth != issuer+"/auth" || + discovery.Token != issuer+"/token" || discovery.JWKS != issuer+"/keys" || + !strings.Contains(strings.Join(discovery.PKCE, ","), "S256") { + return fmt.Errorf("OIDC discovery contract mismatch") + } + var creds credentials + data, err := os.ReadFile(filepath.Join(dir, "credentials.json")) + if err != nil { + return err + } + if err := json.Unmarshal(data, &creds); err != nil { + return err + } + secret := os.Getenv("DEX_TEST_CLIENT_SECRET") + if secret == "" { + return fmt.Errorf("ephemeral client secret missing") + } + if mode == "resume" { + if creds.IDToken == "" || creds.SigningKey.Kid == "" || creds.SigningKey.Modulus == "" || creds.SigningKey.Exponent == 0 { + return fmt.Errorf("pre-restart signing-key continuity evidence missing") + } + previous, err := verifyIDToken(c, issuer, creds.Nonce, creds.IDToken) + if err != nil { + return fmt.Errorf("pre-restart ID token verification failed: %w", err) + } + if previous.SigningKey != creds.SigningKey { + return fmt.Errorf("pre-restart signing-key identity changed") + } + tokens, err := exchange(issuer, secret, url.Values{ + "grant_type": {"refresh_token"}, "refresh_token": {creds.Refresh}, + }, true) + if err != nil { + return err + } + _, err = verify(issuer, creds.Nonce, tokens) + return err + } + verifier, err := randomToken() + if err != nil { + return err + } + creds.Nonce, err = randomToken() + if err != nil { + return err + } + if _, err := login(issuer, "deliberately-wrong", verifier, creds.Nonce, false); err != nil { + return err + } + for _, scenario := range []string{"wrong-pkce", "wrong-secret", "valid"} { + code, err := login(issuer, creds.Password, verifier, creds.Nonce, true) + if err != nil { + return err + } + form := url.Values{ + "grant_type": {"authorization_code"}, "redirect_uri": {callback}, + "code": {code}, "code_verifier": {verifier}, + } + useSecret := secret + if scenario == "wrong-pkce" { + form.Set("code_verifier", strings.Repeat("x", 43)) + } + if scenario == "wrong-secret" { + useSecret = "deliberately-wrong" + } + tokens, err := exchange(issuer, useSecret, form, scenario == "valid") + if err != nil { + return fmt.Errorf("%s: %w", scenario, err) + } + if scenario == "valid" { + signingKey, err := verify(issuer, creds.Nonce, tokens) + if err != nil { + return err + } + if _, err := exchange(issuer, secret, form, false); err != nil { + return fmt.Errorf("authorization code replay: %w", err) + } + creds.Refresh = tokens.Refresh + creds.IDToken = tokens.ID + creds.SigningKey = signingKey + } + } + return writeJSON(filepath.Join(dir, "credentials.json"), creds, 0600) +} + +func run() error { + if len(os.Args) < 4 { + return fmt.Errorf("usage: probe config|check|resume issuer config-directory [memory|sqlite3]") + } + switch os.Args[1] { + case "config": + if len(os.Args) != 5 { + return fmt.Errorf("config requires storage") + } + return configure(os.Args[2], os.Args[3], os.Args[4]) + case "check", "resume": + return check(os.Args[2], os.Args[3], os.Args[1]) + default: + return fmt.Errorf("unknown probe command") + } +} + +func main() { + if err := run(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + fmt.Println("Dex packaging probe passed") +} diff --git a/bridge/idp/tests/probe_test.go b/bridge/idp/tests/probe_test.go new file mode 100644 index 00000000..06781ba4 --- /dev/null +++ b/bridge/idp/tests/probe_test.go @@ -0,0 +1,256 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package main + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "math/big" + "net/http" + "net/http/httptest" + "net/url" + "os" + "path/filepath" + "slices" + "strings" + "sync" + "testing" + "time" +) + +type continuityJWK struct { + Kty string `json:"kty"` + Kid string `json:"kid"` + N string `json:"n"` + E string `json:"e"` +} + +func continuityKey(kid string, key *rsa.PrivateKey) continuityJWK { + return continuityJWK{ + Kty: "RSA", Kid: kid, + N: base64.RawURLEncoding.EncodeToString(key.N.Bytes()), + E: base64.RawURLEncoding.EncodeToString(big.NewInt(int64(key.E)).Bytes()), + } +} + +func continuityToken(t *testing.T, key *rsa.PrivateKey, issuer, kid, nonce string, expires time.Time) string { + t.Helper() + header, err := json.Marshal(map[string]string{"alg": "RS256", "kid": kid}) + if err != nil { + t.Fatal(err) + } + claims, err := json.Marshal(map[string]any{ + "iss": issuer, "aud": clientID, "sub": "continuity-subject", "nonce": nonce, + "exp": expires.Unix(), "email": email, "email_verified": true, + }) + if err != nil { + t.Fatal(err) + } + unsigned := base64.RawURLEncoding.EncodeToString(header) + "." + base64.RawURLEncoding.EncodeToString(claims) + digest := sha256.Sum256([]byte(unsigned)) + signature, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, digest[:]) + if err != nil { + t.Fatal(err) + } + return unsigned + "." + base64.RawURLEncoding.EncodeToString(signature) +} + +func continuityJSON(t *testing.T, w http.ResponseWriter, value any) { + t.Helper() + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(value); err != nil { + t.Errorf("fixture JSON response: %v", err) + } +} + +func TestSigningKeyContinuity(t *testing.T) { + oldKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatal(err) + } + newKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatal(err) + } + const secret = "ephemeral-unit-test-client-secret" + const nonce = "pre-restart-nonce" + t.Setenv("DEX_TEST_CLIENT_SECRET", secret) + + for _, tc := range []struct { + name string + retainOldKey bool + sameKid bool + unchanged bool + changedIdentity bool + missingToken bool + missingIdentity bool + expiredToken bool + wrongUserinfo bool + wantError string + }{ + {name: "lost signing keys despite working refresh", wantError: "pre-restart ID token verification failed"}, + {name: "replacement key reuses old kid", sameKid: true, wantError: "pre-restart ID token verification failed"}, + {name: "rotation retains old verification key", retainOldKey: true}, + {name: "unchanged signing key", unchanged: true}, + {name: "saved key identity differs", retainOldKey: true, changedIdentity: true, wantError: "pre-restart signing-key identity changed"}, + {name: "missing old token", retainOldKey: true, missingToken: true, wantError: "continuity evidence missing"}, + {name: "missing verified key identity", retainOldKey: true, missingIdentity: true, wantError: "continuity evidence missing"}, + {name: "expired old token", retainOldKey: true, expiredToken: true, wantError: "signed ID token claims mismatch"}, + {name: "refresh still requires matching userinfo", retainOldKey: true, wrongUserinfo: true, wantError: "userinfo identity mismatch"}, + } { + t.Run(tc.name, func(t *testing.T) { + var mu sync.Mutex + var issuer string + var requests []string + keys := []continuityJWK{continuityKey("old-key", oldKey)} + var refreshed tokenSet + userSubject := "continuity-subject" + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + mu.Lock() + defer mu.Unlock() + requests = append(requests, r.URL.Path) + switch r.URL.Path { + case "/dex/.well-known/openid-configuration": + continuityJSON(t, w, map[string]any{ + "issuer": issuer, "authorization_endpoint": issuer + "/auth", + "token_endpoint": issuer + "/token", "jwks_uri": issuer + "/keys", + "code_challenge_methods_supported": []string{"S256"}, + }) + case "/dex/keys": + continuityJSON(t, w, map[string]any{"keys": keys}) + case "/dex/token": + id, password, ok := r.BasicAuth() + if r.Method != http.MethodPost || !ok || id != clientID || password != secret { + http.Error(w, "fixture client authentication failed", http.StatusUnauthorized) + return + } + if err := r.ParseForm(); err != nil || r.Form.Get("grant_type") != "refresh_token" || + r.Form.Get("refresh_token") != "persisted-refresh" { + http.Error(w, "fixture refresh request invalid", http.StatusBadRequest) + return + } + continuityJSON(t, w, refreshed) + case "/dex/userinfo": + if auth := r.Header.Get("Authorization"); auth != "Bearer old-access" && auth != "Bearer new-access" { + http.Error(w, "fixture access token invalid", http.StatusUnauthorized) + return + } + continuityJSON(t, w, map[string]string{"sub": userSubject, "email": email}) + default: + http.NotFound(w, r) + } + })) + defer server.Close() + mu.Lock() + issuer = server.URL + "/dex" + mu.Unlock() + + oldTokens := tokenSet{ + Access: "old-access", Refresh: "persisted-refresh", Type: "Bearer", + ID: continuityToken(t, oldKey, issuer, "old-key", nonce, time.Now().Add(time.Hour)), + } + identity, err := verify(issuer, nonce, oldTokens) + if err != nil { + t.Fatalf("pre-restart token verification: %v", err) + } + expectedIdentity := signingKeyIdentity{ + Kid: "old-key", Modulus: continuityKey("old-key", oldKey).N, Exponent: oldKey.E, + } + if identity != expectedIdentity { + t.Fatalf("verified signing-key identity = %+v, want %+v", identity, expectedIdentity) + } + creds := credentials{ + Password: "unused-by-resume", Refresh: oldTokens.Refresh, Nonce: nonce, + IDToken: oldTokens.ID, SigningKey: identity, + } + if tc.changedIdentity { + creds.SigningKey.Modulus = continuityKey("new-key", newKey).N + } + if tc.missingToken { + creds.IDToken = "" + } + if tc.missingIdentity { + creds.SigningKey = signingKeyIdentity{} + } + if tc.expiredToken { + creds.IDToken = continuityToken(t, oldKey, issuer, "old-key", nonce, time.Now().Add(-time.Hour)) + } + dir := t.TempDir() + path := filepath.Join(dir, "credentials.json") + if err := writeJSON(path, creds, 0600); err != nil { + t.Fatal(err) + } + info, err := os.Stat(path) + if err != nil { + t.Fatal(err) + } + if info.Mode().Perm() != 0600 { + t.Fatalf("private continuity credentials mode = %o, want 600", info.Mode().Perm()) + } + + activeKey, activeKid := newKey, "new-key" + if tc.sameKid { + activeKid = "old-key" + } + if tc.unchanged { + activeKey, activeKid = oldKey, "old-key" + } + newTokens := tokenSet{ + Access: "new-access", Refresh: "renewed-refresh", Type: "Bearer", + ID: continuityToken(t, activeKey, issuer, activeKid, nonce, time.Now().Add(time.Hour)), + } + mu.Lock() + keys = []continuityJWK{continuityKey(activeKid, activeKey)} + if tc.retainOldKey { + keys = append(keys, continuityKey("old-key", oldKey)) + } + refreshed = newTokens + mu.Unlock() + + // Prove the previous refresh-only check would pass, including when + // the old signing key has been lost or replaced under the same kid. + control, err := exchange(issuer, secret, url.Values{ + "grant_type": {"refresh_token"}, "refresh_token": {creds.Refresh}, + }, true) + if err != nil { + t.Fatalf("persisted refresh control: %v", err) + } + if _, err := verify(issuer, nonce, control); err != nil { + t.Fatalf("new-token/current-JWKS control: %v", err) + } + mu.Lock() + requests = nil + if tc.wrongUserinfo { + userSubject = "different-user" + } + mu.Unlock() + + err = check(issuer, dir, "resume") + if tc.wantError == "" { + if err != nil { + t.Fatalf("retained signing key must survive resume: %v", err) + } + } else if err == nil || !strings.Contains(err.Error(), tc.wantError) { + t.Fatalf("resume error = %v, want %q", err, tc.wantError) + } + mu.Lock() + gotRequests := append([]string(nil), requests...) + mu.Unlock() + wantRequests := []string{"/dex/.well-known/openid-configuration"} + if !tc.missingToken && !tc.missingIdentity { + wantRequests = append(wantRequests, "/dex/keys") + } + if tc.wantError == "" || tc.wrongUserinfo { + wantRequests = append(wantRequests, "/dex/token", "/dex/keys", "/dex/userinfo") + } + if !slices.Equal(gotRequests, wantRequests) { + t.Fatalf("request order = %v, want %v; old-token verification must precede refresh", gotRequests, wantRequests) + } + }) + } +} diff --git a/bridge/idp/tests/qualify.py b/bridge/idp/tests/qualify.py new file mode 100644 index 00000000..6121e821 --- /dev/null +++ b/bridge/idp/tests/qualify.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python3 +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +"""Run only on a hosted native Linux Docker worker; no registry/cluster writes.""" + +import argparse +import hashlib +import json +import os +from pathlib import Path +import re +import secrets +import subprocess +import tarfile +import tempfile +import uuid + +from contracts import BASE, RPM_MANIFEST, check_modules, check_rootfs, check_scan, require + + +def run(*args, **kwargs): + return subprocess.run(args, check=True, text=True, capture_output=True, **kwargs).stdout + + +def export(image, directory, prefix): + container = run("docker", "create", "--entrypoint", "/usr/local/bin/dex", image).strip() + path = directory / (prefix + ".tar") + try: + run("docker", "export", "--output", str(path), container) + entries = {} + documents = {} + with tarfile.open(path) as archive: + for member in archive: + name = member.name.removeprefix("./") + if member.isfile(): + with archive.extractfile(member) as stream: + data = stream.read() + entries[name] = ("file", member.mode, hashlib.sha256(data).hexdigest()) + if name == RPM_MANIFEST or name.startswith("usr/share/doc/dex/elf-"): + documents[name] = data.decode() + elif member.issym() or member.islnk(): + entries[name] = ("link", member.mode, member.linkname) + return entries, documents + finally: + run("docker", "rm", container) + path.unlink(missing_ok=True) + + +def oidc(image, tools, storage, evidence): + suffix = uuid.uuid4().hex + network, config, data, name = (f"dex-test-{kind}-{suffix}" for kind in ("net", "config", "data", "server")) + created = [] + secret = "DEX_TEST_CLIENT_SECRET=" + secrets.token_urlsafe(32) + issuer = "http://dex:5556/dex" + try: + run("docker", "network", "create", "--internal", network) + created.append(("network", network)) + for volume in (config, data): + run("docker", "volume", "create", volume) + created.append(("volume", volume)) + probe = ["docker", "run", "--rm", "--network", network, "--env", secret, + "--mount", f"type=volume,src={config},dst=/config", + "--mount", f"type=volume,src={data},dst=/var/dex", tools] + run(*probe, "config", issuer, "/config", storage) + # This is the chart's direct invocation; no template-expanding wrapper. + run("docker", "create", "--name", name, "--network", network, + "--network-alias", "dex", "--read-only", "--cap-drop", "ALL", + "--security-opt", "no-new-privileges", "--user", "1001:1001", + "--tmpfs", "/tmp:rw,noexec,nosuid,size=16m", "--env", secret, + "--mount", f"type=volume,src={config},dst=/etc/dex,readonly", + "--mount", f"type=volume,src={data},dst=/var/dex", + "--entrypoint", "/usr/local/bin/dex", image, "serve", "/etc/dex/config.yaml") + created.append(("container", name)) + run("docker", "start", name) + output = run(*probe, "check", issuer, "/config") + if storage == "sqlite3": + run("docker", "restart", name) + output += run(*probe, "resume", issuer, "/config") + (evidence / f"{storage}-oidc.txt").write_text(output) + finally: + for kind, identifier in reversed(created): + if kind == "container": + run("docker", "rm", "--force", identifier) + else: + run("docker", kind, "rm", identifier) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--image", required=True) + parser.add_argument("--tools-image", required=True) + parser.add_argument("--evidence", required=True, type=Path) + parser.add_argument("--trivy", default="trivy") + args = parser.parse_args() + root = Path(__file__).resolve().parents[1] + check_modules(root) + args.evidence.mkdir(parents=True, exist_ok=False) + image = json.loads(run("docker", "image", "inspect", args.image))[0] + tools = json.loads(run("docker", "image", "inspect", args.tools_image))[0] + daemon_os, daemon_arch = run("docker", "info", "--format", "{{.OSType}}/{{.Architecture}}").strip().split("/") + daemon_arch = {"x86_64": "amd64", "aarch64": "arm64"}.get(daemon_arch, daemon_arch) + require(daemon_os == "linux" and daemon_arch == image["Architecture"], "native Linux worker required") + require(image["Os"] == "linux" and image["Architecture"] == tools["Architecture"], + "runtime/tools architecture mismatch") + # Resolve mutable local tags once. All subsequent checks address image IDs. + image_id, tools_id = image["Id"], tools["Id"] + (args.evidence / "image.json").write_text(json.dumps(image, indent=2)) + require(image["Config"]["User"] == "1001:1001", "unexpected runtime user") + require(image["Config"]["Entrypoint"] == ["/usr/local/bin/dex"], "unexpected entrypoint") + require(image["Config"]["Cmd"] == ["serve", "/etc/dex/config.yaml"], "unexpected command") + run("docker", "pull", "--platform", "linux/" + image["Architecture"], BASE) + with tempfile.TemporaryDirectory(prefix="dex-qualification-") as temporary: + scratch = Path(temporary) + base, _ = export(BASE, scratch, "base") + runtime, documents = export(image_id, scratch, "runtime") + check_rootfs(base, runtime, documents[RPM_MANIFEST]) + (args.evidence / "runtime-inventory.json").write_text(json.dumps(runtime, indent=2)) + for name, contents in documents.items(): + (args.evidence / Path(name).name).write_text(contents) + headers = documents["usr/share/doc/dex/elf-program-headers.txt"] + match = re.search(r"Requesting program interpreter: ([^\]]+)", headers) + require(match is not None, "CGO Dex must have a real runtime ELF interpreter") + loader = match.group(1) + require(loader.lstrip("/") in base, "ELF interpreter is not provided by pinned runtime") + linked = run("docker", "run", "--rm", "--network", "none", "--read-only", + "--cap-drop", "ALL", "--security-opt", "no-new-privileges", + "--entrypoint", loader, image_id, "--list", "/usr/local/bin/dex") + require("not found" not in linked and "libc.so.6" in linked, "native library closure failed") + (args.evidence / "runtime-linkage.txt").write_text(linked) + for storage in ("memory", "sqlite3"): + oidc(image_id, tools_id, storage, args.evidence) + environment = {k: v for k, v in os.environ.items() if not k.startswith("TRIVY_")} + version = run(args.trivy, "--version", env=environment) + require(re.search(r"Version: 0\.70\.0\b", version), "qualification requires Trivy 0.70.0") + empty_ignore = scratch / "empty.trivyignore" + empty_config = scratch / "empty.yaml" + empty_ignore.write_text("") + empty_config.write_text("{}\n") + cache = scratch / "trivy-cache" + common = [args.trivy, "--config", str(empty_config), "--cache-dir", str(cache), "image"] + run(*common, "--download-db-only", env=environment) + scan_path = args.evidence / "trivy-high-critical.json" + scan = subprocess.run( + [*common, "--image-src", "docker", "--scanners", "vuln", + "--ignorefile", str(empty_ignore), "--severity", "HIGH,CRITICAL", + "--list-all-pkgs", "--skip-db-update", "--exit-code", "1", + "--format", "json", "--output", str(scan_path), image_id], + text=True, capture_output=True, env=environment, + ) + (args.evidence / "trivy-stderr.txt").write_text(scan.stderr) + require(scan.returncode == 0, "final Trivy scan failed; see trivy-high-critical.json/stderr") + check_scan(json.loads(scan_path.read_text())) + (args.evidence / "trivy-version.txt").write_text(run(args.trivy, "--cache-dir", str(cache), + "--version", env=environment)) + (args.evidence / "runtime-passed.json").write_text(json.dumps({ + "image": image_id, "tools": tools_id, "base": BASE, + "checks": ["base-inventory-and-trust", "native-linkage", "memory-oidc", + "sqlite-oidc-and-refresh-after-restart", "latest-db-high-critical"], + "notCovered": ["upstream-service-integration-tests", "external-connector-enrollment", + "independent-rebuild-comparison", "deployment"], + }, indent=2)) + print("Runtime gates passed. Upstream suites, rebuild comparison and configured connector tests remain separate gates.") + + +if __name__ == "__main__": + try: + main() + except subprocess.CalledProcessError as error: + # Do not echo Docker command arguments containing ephemeral credentials. + raise SystemExit(f"Hosted command failed ({error.returncode}): {error.stderr or error.stdout}") from None + except (ValueError, OSError, KeyError) as error: + raise SystemExit(str(error)) from None diff --git a/bridge/idp/tests/test_contracts.py b/bridge/idp/tests/test_contracts.py new file mode 100644 index 00000000..688213f4 --- /dev/null +++ b/bridge/idp/tests/test_contracts.py @@ -0,0 +1,149 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import ast +import base64 +import gzip +import hashlib +import importlib.util +import io +from pathlib import Path +import tarfile +import unittest + +from contracts import BASE, LOCK_FILES, RPM_MANIFEST, check_modules, check_rootfs, check_scan, json_stream, module_inventory + +ROOT = Path(__file__).resolve().parents[1] +spec = importlib.util.spec_from_file_location("import_locks", ROOT / "scripts/import-locks.py") +import_locks = importlib.util.module_from_spec(spec) +spec.loader.exec_module(import_locks) + + +class SourceContracts(unittest.TestCase): + def test_json_stream(self): + self.assertEqual(list(json_stream('{"Path":"a"}\n{"Path":"b"}\n')), + [{"Path": "a"}, {"Path": "b"}]) + + def test_module_inventory_rejects_resolver_errors_and_duplicates(self): + self.assertEqual(module_inventory('{"Path":"module-a","Version":"v1.0.0"}'), + {"module-a": {"Path": "module-a", "Version": "v1.0.0"}}) + for bad in ('{"Path":"a"}\n{"Path":"a"}', '{"Path":"a","Error":{"Err":"unresolved"}}', + '{"Version":"v1.0.0"}', '[]'): + with self.assertRaises(ValueError): + module_inventory(bad) + + def test_runtime_recipe(self): + dockerfile = (ROOT / "Dockerfile").read_text() + runtime = dockerfile.split(f"FROM {BASE} AS runtime\n")[1] + self.assertNotIn("\nRUN ", runtime) + self.assertNotIn("--from=dependencies", runtime) + self.assertNotIn("COPY .", runtime) + self.assertIn('ENTRYPOINT ["/usr/local/bin/dex"]', runtime) + self.assertIn('CMD ["serve", "/etc/dex/config.yaml"]', runtime) + self.assertIn("COPY locks/generated/ /locks/", dockerfile) + self.assertIn("CGO_ENABLED=1", dockerfile) + self.assertIn("GOTOOLCHAIN=local", dockerfile) + self.assertNotIn("go get", (ROOT / "scripts/build.sh").read_text()) + + def test_resolver_is_separate_from_runtime_build(self): + runtime = (ROOT / "Dockerfile").read_text() + maintenance = (ROOT / "Dockerfile.locks").read_text() + self.assertNotIn("generate-locks", runtime) + self.assertNotIn("FROM lock-generation", runtime) + self.assertNotIn("lock-replay", runtime) + self.assertIn("FROM lock-generation AS lock-replay", maintenance) + self.assertIn("cmp SHA256SUMS /out/SHA256SUMS", maintenance) + def source(text): + return text[text.index("FROM golang:"):text.index("\nFROM source AS ")] + + self.assertEqual(source(runtime), source(maintenance)) + self.assertIn("!Dockerfile.locks", (ROOT / ".dockerignore").read_text()) + + def test_missing_locks_block_acceptance(self): + if (ROOT / "locks/generated").is_dir(): + check_modules(ROOT) + else: + with self.assertRaisesRegex(ValueError, "runtime build is blocked"): + check_modules(ROOT) + + def test_notice_collector_preserves_british_spelled_upstream_licences(self): + source = (ROOT / "scripts/notices.go").read_text() + self.assertEqual(source.count('strings.HasPrefix(name, "LICENCE")'), 2) + self.assertIn('strings.ToUpper(entry.Name())', source) + self.assertIn('missing root license; review upstream attribution before shipping', source) + self.assertIn('os.WriteFile(dest, data, 0644)', source) + + def test_base_inventory_must_survive(self): + base = {RPM_MANIFEST: ("file", 420, "manifest"), + "etc/pki/ca-trust/bundle.pem": ("file", 420, "trust")} + runtime = {**base, "usr/local/bin/dex": ("file", 493, "dex")} + manifest = "\n".join(f"rpm-{i}" for i in range(14)) + check_rootfs(base, runtime, manifest) + for name in base: + altered = dict(runtime) + altered[name] = ("file", 420, "changed") + with self.assertRaisesRegex(ValueError, "base file modified"): + check_rootfs(base, altered, manifest) + with self.assertRaisesRegex(ValueError, "14 Azure Linux RPM"): + check_rootfs(base, runtime, manifest + "\nunreviewed-rpm") + with self.assertRaisesRegex(ValueError, "unexpected runtime payload"): + check_rootfs(base, {**runtime, "usr/lib/libc.so": ("file", 493, "debian")}, manifest) + + def test_scanner_must_see_both_os_and_go(self): + report = { + "Metadata": {"OS": {"Family": "azurelinux"}}, + "Results": [ + {"Class": "os-pkgs", "Packages": [{"Name": f"rpm-{i}"} for i in range(14)]}, + {"Type": "gobinary", "Target": "/usr/local/bin/dex"}, + ], + } + check_scan(report) + report["Results"][1]["Vulnerabilities"] = [{"Severity": "HIGH"}] + with self.assertRaisesRegex(ValueError, "findings remain"): + check_scan(report) + report["Results"].pop() + with self.assertRaisesRegex(ValueError, "Dex Go binary"): + check_scan(report) + + def test_python_syntax(self): + for file in ROOT.rglob("*.py"): + ast.parse(file.read_text(), filename=str(file)) + + def test_lock_archive_boundaries(self): + def log_for(names, checksum=None): + stream = io.BytesIO() + with tarfile.open(fileobj=stream, mode="w:gz") as archive: + for name in names: + member = tarfile.TarInfo("./" + name) + member.size = 4 + archive.addfile(member, io.BytesIO(b"test")) + payload = stream.getvalue() + checksum = checksum or hashlib.sha256(payload).hexdigest() + return ("KARS_DEX_LOCKS_BASE64_BEGIN\n" + + base64.b64encode(payload).decode() + + "\nKARS_DEX_LOCKS_BASE64_END\n" + + checksum + " /tmp/dex-locks.tar.gz\n") + + names = sorted(LOCK_FILES) + self.assertEqual(set(import_locks.decode_artifact(log_for(names))), set(names)) + for invalid in (names + ["go.mod"], names + ["../escape"], names[:-1]): + with self.assertRaises(ValueError): + import_locks.decode_artifact(log_for(invalid)) + with self.assertRaisesRegex(ValueError, "exactly one"): + import_locks.decode_artifact(log_for(names) + log_for(names)) + with self.assertRaisesRegex(ValueError, "transport SHA-256"): + import_locks.decode_artifact(log_for(names, "0" * 64)) + with self.assertRaisesRegex(ValueError, "transport SHA-256"): + import_locks.decode_artifact(log_for(names).replace("/tmp/dex-locks.tar.gz", "/tmp/wrong.tar.gz")) + + def test_archive_limit_includes_headers_and_padding(self): + payload = gzip.compress(b"\0" * (import_locks.MAX_ARCHIVE_BYTES + 1)) + log = ("KARS_DEX_LOCKS_BASE64_BEGIN\n" + base64.b64encode(payload).decode() + + "\nKARS_DEX_LOCKS_BASE64_END\n" + hashlib.sha256(payload).hexdigest() + + " /tmp/dex-locks.tar.gz\n") + with self.assertRaisesRegex(ValueError, "expanded artifact exceeds"): + import_locks.decode_artifact(log) + + +if __name__ == "__main__": + unittest.main() diff --git a/bridge/idp/tests/test_patches.py b/bridge/idp/tests/test_patches.py new file mode 100644 index 00000000..7c36783b --- /dev/null +++ b/bridge/idp/tests/test_patches.py @@ -0,0 +1,193 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import hashlib +import io +import os +from pathlib import Path +import shutil +import subprocess +import tarfile +import tempfile +import unittest +import urllib.request +import xml.etree.ElementTree as ET + +ROOT = Path(__file__).resolve().parents[1] +MODIFIED = {"./server/oauth2.go", "./connector/saml/saml_test.go"} +ADDED = {"./server/kars_compat_test.go", "./connector/saml/kars_compat_test.go"} + + +def checksums(path): + result = {} + for line in path.read_text().splitlines(): + digest, name = line.split(" ", 1) + if name in result: + raise ValueError("duplicate checksum path") + result[name] = digest + return result + + +class PatchContracts(unittest.TestCase): + def test_all_reviewed_inputs_are_pinned(self): + patches = ROOT / "patches" + manifest = checksums(patches / "SHA256SUMS") + self.assertEqual(set(manifest), {p.name for p in patches.iterdir() if p.name != "SHA256SUMS"}) + for name, digest in manifest.items(): + self.assertEqual(hashlib.sha256((patches / name).read_bytes()).hexdigest(), digest, name) + self.assertEqual(set(checksums(patches / "upstream.sha256")), MODIFIED) + self.assertEqual(set(checksums(patches / "patched.sha256")), MODIFIED | ADDED) + self.assertEqual((patches / "series").read_text().splitlines(), [ + "0001-literal-oauth-error-descriptions.patch", + "0002-saml-fixture-validation-clock.patch", + ]) + + def test_production_delta_is_exactly_two_literal_format_callers(self): + lines = (ROOT / "patches/0001-literal-oauth-error-descriptions.patch").read_text().splitlines() + removed = [line[1:].strip() for line in lines if line.startswith("-") and not line.startswith("---")] + added = [line[1:].strip() for line in lines if line.startswith("+") and not line.startswith("+++")] + self.assertEqual(removed, [ + "return nil, newRedirectedErr(errInvalidRequest, description)", + "return nil, newRedirectedErr(errInvalidRequest, err)", + ]) + self.assertEqual(added, [ + 'return nil, newRedirectedErr(errInvalidRequest, "%s", description)', + 'return nil, newRedirectedErr(errInvalidRequest, "%s", err)', + ]) + + def test_fixture_clock_and_behavior_contracts_remain_test_only(self): + patch = (ROOT / "patches/0002-saml-fixture-validation-clock.patch").read_text() + self.assertEqual([line for line in patch.splitlines() if line.startswith("+++ ")], + ["+++ b/connector/saml/saml_test.go"]) + self.assertIn("runVerifyWithClock(t, ca, resp, shouldSucceed, nil)", patch) + self.assertIn("time.Date(2016, time.December, 12, 16, 54, 35, 0, time.UTC)", patch) + saml = (ROOT / "patches/saml_compat_test.go").read_text() + self.assertIn("cert.NotBefore.Add(-time.Second)", saml) + self.assertIn("cert.NotAfter.Add(time.Second)", saml) + self.assertIn("verifyResponseSig(validator, data)", saml) + self.assertIn("Cert is not valid at this time", saml) + oauth = (ROOT / "patches/server_compat_test.go").read_text() + self.assertIn('method: "%s%[1]s%%"', oauth) + self.assertIn("server.parseAuthorizationRequest(req)", oauth) + self.assertIn("redirected.Description != tc.description", oauth) + + def test_integrity_and_hosted_behavior_gates_are_wired(self): + script = (ROOT / "scripts/apply-source-patches.sh").read_text() + self.assertLess(script.index('source.upstream.sha256'), script.index("git apply --no-index --check")) + self.assertIn('git apply --no-index --whitespace=error-all "$patches/$name"', script) + self.assertNotIn("--unsafe-paths", script) + self.assertIn('"$patches/patched.sha256" "$packaging/source.upstream.sha256"', script) + self.assertIn('cmp "$packaging/source.sha256" "$packaging/source.actual.sha256"', script) + exclusions = (ROOT / "scripts/source-inventory.sh").read_text() + self.assertEqual(exclusions.count("! -path"), 4) + self.assertNotIn("oauth2.go", exclusions) + self.assertNotIn("saml_test.go", exclusions) + dockerfile = (ROOT / "Dockerfile").read_text() + self.assertIn("FROM build AS compatibility-tests", dockerfile) + self.assertIn("FROM compatibility-tests AS upstream-tests", dockerfile) + self.assertIn("TestKarsAuthorizationErrorDescriptionsLiteral", dockerfile) + self.assertIn("TestKarsSAMLFixtureCertificateValidity", dockerfile) + self.assertNotIn("-vet=off", dockerfile) + self.assertNotIn("-vet=off", (ROOT / "scripts/upstream-tests.sh").read_text()) + + +@unittest.skipUnless(os.environ.get("KARS_DEX_PATCH_NETWORK") == "1", + "opt in to bounded verified upstream download; no Go compilation") +class AppliedPatchContracts(unittest.TestCase): + @classmethod + def setUpClass(cls): + inputs = dict(line.split("=", 1) for line in (ROOT / "locks/inputs.lock").read_text().splitlines() + if line and not line.startswith("#")) + cls.commit = inputs["DEX_COMMIT"] + with urllib.request.urlopen(f"https://codeload.github.com/dexidp/dex/tar.gz/{cls.commit}", timeout=30) as response: + cls.archive = response.read(2 * 1024 * 1024 + 1) + if len(cls.archive) > 2 * 1024 * 1024: + raise ValueError("upstream archive exceeds bounded download size") + if hashlib.sha256(cls.archive).hexdigest() != inputs["DEX_ARCHIVE_SHA256"]: + raise ValueError("immutable upstream archive hash mismatch") + + def setUp(self): + temporary = tempfile.TemporaryDirectory(prefix=".patch-contract-", dir=ROOT) + self.addCleanup(temporary.cleanup) + self.directory = Path(temporary.name) + with tarfile.open(fileobj=io.BytesIO(self.archive), mode="r:gz") as archive: + self.assertLess(sum(member.size for member in archive), 16 * 1024 * 1024) + archive.extractall(self.directory, filter="data") + self.source = self.directory / ("dex-" + self.commit) + self.packaging = self.directory / "packaging" + shutil.copytree(ROOT / "patches", self.packaging / "patches") + (self.packaging / "scripts").mkdir() + for name in ("source-inventory.sh", "apply-source-patches.sh"): + shutil.copyfile(ROOT / "scripts" / name, self.packaging / "scripts" / name) + inventory = subprocess.run(["sh", str(self.packaging / "scripts/source-inventory.sh")], + cwd=self.source, check=True, capture_output=True, text=True) + (self.packaging / "source.upstream.sha256").write_text(inventory.stdout) + self.original = checksums(self.packaging / "source.upstream.sha256") + + def apply(self): + return subprocess.run(["sh", str(self.packaging / "scripts/apply-source-patches.sh"), str(self.packaging)], + cwd=self.source, capture_output=True, text=True) + + def test_exact_patch_application_and_complete_inventory(self): + original_oauth = (self.source / "server/oauth2.go").read_text() + self.assertIn("Description string", original_oauth) + module_paths = ["go.mod", "go.sum", "api/v2/go.mod", "api/v2/go.sum"] + modules = {name: (self.source / name).read_bytes() for name in module_paths} + result = self.apply() + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + expected = checksums(self.packaging / "source.sha256") + actual = checksums(self.packaging / "source.actual.sha256") + self.assertEqual(expected, actual) + self.assertEqual(set(expected) - set(self.original), ADDED) + self.assertEqual(set(self.original) - set(expected), set()) + self.assertEqual({name for name in self.original if self.original[name] != expected[name]}, MODIFIED) + self.assertEqual((self.source / "server/oauth2.go").read_text(), + original_oauth.replace("newRedirectedErr(errInvalidRequest, description)", + 'newRedirectedErr(errInvalidRequest, "%s", description)') + .replace("newRedirectedErr(errInvalidRequest, err)", + 'newRedirectedErr(errInvalidRequest, "%s", err)')) + for name, data in modules.items(): + self.assertEqual((self.source / name).read_bytes(), data) + fixture = ET.parse(self.source / "connector/saml/testdata/oam-resp.xml") + self.assertEqual(fixture.getroot().attrib["IssueInstant"], "2016-12-12T16:54:35Z") + self.assertEqual(self.original["./connector/saml/saml.go"], expected["./connector/saml/saml.go"]) + replay = self.apply() + self.assertNotEqual(replay.returncode, 0, "original-source verification must reject double application") + + def test_patch_tampering_fails_before_source_changes(self): + patch = self.packaging / "patches/0001-literal-oauth-error-descriptions.patch" + patch.write_text(patch.read_text() + "\n") + result = self.apply() + self.assertNotEqual(result.returncode, 0) + self.assertEqual(hashlib.sha256((self.source / "server/oauth2.go").read_bytes()).hexdigest(), + self.original["./server/oauth2.go"]) + + def test_original_source_drift_fails_before_patching(self): + source = self.source / "server/oauth2.go" + source.write_text(source.read_text() + "\n") + result = self.apply() + self.assertNotEqual(result.returncode, 0) + self.assertFalse((self.packaging / "source.sha256").exists()) + + def test_wrong_reviewed_post_hash_is_not_recomputed_from_output(self): + post = self.packaging / "patches/patched.sha256" + original_hash = checksums(post)["./server/oauth2.go"] + post.write_text(post.read_text().replace(original_hash, "0" * 64)) + manifest = self.packaging / "patches/SHA256SUMS" + old_pin = checksums(manifest)["patched.sha256"] + manifest.write_text(manifest.read_text().replace(old_pin, hashlib.sha256(post.read_bytes()).hexdigest())) + result = self.apply() + self.assertNotEqual(result.returncode, 0) + self.assertFalse((self.packaging / "source.sha256").exists()) + + def test_unreviewed_extra_source_is_rejected(self): + (self.source / "server/unreviewed.go").write_text("package server\n") + result = self.apply() + self.assertNotEqual(result.returncode, 0) + self.assertTrue((self.packaging / "source.actual.sha256").exists()) + self.assertNotEqual((self.packaging / "source.actual.sha256").read_bytes(), + (self.packaging / "source.sha256").read_bytes()) + + +if __name__ == "__main__": + unittest.main() diff --git a/ci/bridge_component_results.py b/ci/bridge_component_results.py index 6ebdab41..bcb85342 100644 --- a/ci/bridge_component_results.py +++ b/ci/bridge_component_results.py @@ -8,7 +8,7 @@ REQUIRED_JOBS = frozenset({ - "addon", "bff", "dependencies", "lockfiles", + "addon", "bff", "dependencies", "idp", "lockfiles", "rust-dependencies", "secrets", "security", "web", }) diff --git a/ci/copyright-coverage.json b/ci/copyright-coverage.json index a855aa91..cc0356d1 100644 --- a/ci/copyright-coverage.json +++ b/ci/copyright-coverage.json @@ -93,6 +93,136 @@ "reason": "Generated dependency lockfile; no dependency/checksum changes for copyright policy.", "notice": "LICENSE" }, + "bridge/idp/LICENSE": { + "category": "legal", + "reason": "Kars packaging license document; preserve the legal text rather than prepending a source header.", + "notice": "NOTICE" + }, + "bridge/idp/NOTICE": { + "category": "legal", + "reason": "Scoped Dex upstream and Kars patch attribution; preserve original ownership and license distinctions.", + "notice": "NOTICE" + }, + "bridge/idp/locks/inputs.lock": { + "category": "repository-license", + "reason": "Reviewed immutable resolver inputs are copied and checksum-bound in the generated artifact; preserve exact bytes.", + "notice": "NOTICE" + }, + "bridge/idp/locks/requests.txt": { + "category": "repository-license", + "reason": "Machine-read exact Go module resolution requests; comments would become module arguments and change the verified artifact.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/go.mod": { + "category": "generated", + "reason": "Actual hosted Go resolver output with disclosed Dex dependency patches; preserve the checksum-bound module file.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/go.sum": { + "category": "generated", + "reason": "Actual Go module checksums; do not rewrite generated integrity data for source-header policy.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/api/v2/go.mod": { + "category": "generated", + "reason": "Actual hosted nested API module resolver output; preserve the checksum-bound dependency contract.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/api/v2/go.sum": { + "category": "generated", + "reason": "Actual nested API Go module checksums; preserve original generated bytes.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/upstream/go.mod": { + "category": "third-party", + "reason": "Exact pinned upstream Dex module snapshot under Apache-2.0, not Microsoft-authored source.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/upstream/go.sum": { + "category": "third-party", + "reason": "Exact pinned upstream Dex dependency checksums retained for comparison and attribution.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/upstream/api/v2/go.mod": { + "category": "third-party", + "reason": "Exact pinned upstream Dex API module snapshot; preserve upstream ownership and bytes.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/upstream/api/v2/go.sum": { + "category": "third-party", + "reason": "Exact pinned upstream Dex API dependency checksum snapshot; preserve upstream data.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/modules.json": { + "category": "generated", + "reason": "Go-generated selected-module inventory verified against requests and checksums; preserve its machine-readable bytes.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/api-modules.json": { + "category": "generated", + "reason": "Go-generated nested API module inventory; preserve its machine-readable, checksum-bound bytes.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/graph.txt": { + "category": "generated", + "reason": "Actual go mod graph output retained for reproducibility and dependency review.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/toolchain.txt": { + "category": "generated", + "reason": "Actual hosted compiler identity output; comments would invalidate its exact verification contract.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/inputs.lock": { + "category": "generated", + "reason": "Resolver-emitted exact input snapshot, compared byte-for-byte with reviewed inputs.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/requests.txt": { + "category": "generated", + "reason": "Resolver-emitted exact module request snapshot; preserve checksummed data.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/dependencies.patch": { + "category": "generated", + "reason": "Actual resolver diff against pinned Apache-2.0 upstream module files; preserve patch and attribution bytes.", + "notice": "NOTICE" + }, + "bridge/idp/locks/generated/SHA256SUMS": { + "category": "generated", + "reason": "Complete generated artifact integrity inventory; headers must not alter digest verification.", + "notice": "NOTICE" + }, + "bridge/idp/patches/0001-literal-oauth-error-descriptions.patch": { + "category": "third-party", + "reason": "Reviewed narrow diff against pinned Apache-2.0 Dex source with disclosed Kars changes; preserve exact patch bytes and upstream attribution.", + "notice": "NOTICE" + }, + "bridge/idp/patches/0002-saml-fixture-validation-clock.patch": { + "category": "third-party", + "reason": "Reviewed test-only diff against pinned Apache-2.0 Dex fixtures; preserve exact signed-source patch inputs.", + "notice": "NOTICE" + }, + "bridge/idp/patches/SHA256SUMS": { + "category": "repository-license", + "reason": "Reviewed patch integrity inventory, not commentable source; exact bytes bind patch application.", + "notice": "NOTICE" + }, + "bridge/idp/patches/upstream.sha256": { + "category": "repository-license", + "reason": "Pinned pre-patch upstream source identities; preserve exact integrity metadata.", + "notice": "NOTICE" + }, + "bridge/idp/patches/patched.sha256": { + "category": "repository-license", + "reason": "Reviewed post-patch source identities; preserve exact integrity metadata rather than recomputing or rewriting it.", + "notice": "NOTICE" + }, + "bridge/idp/patches/series": { + "category": "repository-license", + "reason": "Ordered machine-read patch names; comments would change the checked patch application sequence.", + "notice": "NOTICE" + }, ".agt-sdk/.keep": { "category": "repository-license", "reason": "Empty directory marker; preserve emptiness.", diff --git a/ci/copyright_headers.py b/ci/copyright_headers.py index a330758e..7c193436 100644 --- a/ci/copyright_headers.py +++ b/ci/copyright_headers.py @@ -31,7 +31,7 @@ "handlebars": f"{{{{!-- {COPYRIGHT}\n{LICENSE} --}}}}", } SUFFIX_STYLES = { - **dict.fromkeys((".rs", ".ts", ".tsx", ".js", ".mjs", ".bicep"), "slash"), + **dict.fromkeys((".rs", ".go", ".ts", ".tsx", ".js", ".mjs", ".bicep"), "slash"), **dict.fromkeys((".sh", ".py", ".toml", ".yaml", ".yml"), "hash"), ".md": "html", ".css": "css", diff --git a/ci/tests/bridge_contracts_test.py b/ci/tests/bridge_contracts_test.py index 74aa7bf7..aeacc8c1 100644 --- a/ci/tests/bridge_contracts_test.py +++ b/ci/tests/bridge_contracts_test.py @@ -5,8 +5,11 @@ import json import os from pathlib import Path +import re import runpy import subprocess +import tempfile +import textwrap import unittest from git_fixture import GitFixture @@ -92,13 +95,113 @@ def test_sparse_core_checkout_really_removes_only_bridge(self): class ContractAggregateTests(unittest.TestCase): components = ( - "addon", "bff", "dependencies", "lockfiles", + "addon", "bff", "dependencies", "idp", "lockfiles", "rust-dependencies", "secrets", "security", "web", ) def component_success(self): return {name: {"result": "success"} for name in self.components} + def workflow_job(self, name): + workflow = (CI.parent / ".github/workflows/bridge-ci.yml").read_text() + match = re.search(rf"(?ms)^ {re.escape(name)}:\n(.*?)(?=^ \S|\Z)", workflow) + self.assertIsNotNone(match, name) + return match.group(1) + + def test_idp_is_required_by_the_exact_component_graph(self): + aggregate = self.workflow_job("bridge-required-gates") + needs = re.search(r"(?m)^ needs: \[([^\]]+)\]$", aggregate) + self.assertIsNotNone(needs) + self.assertEqual({name.strip() for name in needs.group(1).split(",")}, set(self.components)) + self.assertIn("idp", self.components) + self.assertIn(" if: always()", aggregate) + self.assertEqual(runpy.run_path(str(CI / "bridge_component_results.py"))["REQUIRED_JOBS"], + frozenset(self.components)) + + def test_idp_job_requires_real_hosted_images_reports_runtime_and_scans(self): + job = self.workflow_job("idp") + for required in ( + "runs-on: ubuntu-24.04", "permissions:\n contents: read", + 'test "$(uname -m)" = x86_64', "persist-credentials: false", + "KARS_DEX_PATCH_NETWORK=1", 'check_modules("bridge/idp")', + "--target upstream-tests", "--target test-tools", "--target runtime", + "--platform linux/amd64", "--file bridge/idp/Dockerfile bridge/idp", + "docker create kars-bridge-idp-upstream-tests:latest", + 'trap \'docker rm "$container"\' EXIT', + "$container:/out/doc/upstream-tests.json", "$container:/out/doc/api-tests.json", + "aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25", + "version: v0.70.0", "ignore-unfixed: false", "exit-code: '1'", + 'trivy_path="$(command -v trivy)"', 'test -x "$trivy_path"', + "python3 bridge/idp/tests/qualify.py", '--trivy "$trivy_path"', + '--evidence "$IDP_EVIDENCE_DIR/runtime"', + "if: ${{ !cancelled() && steps.idp_runtime.outcome == 'success' }}", + "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a", + "if-no-files-found: error", "runtime-qualification.log", "step-outcomes.json", + ): + self.assertIn(required, job, required) + self.assertNotIn("continue-on-error", job) + self.assertNotIn("|| true", job) + self.assertNotIn(": write", job) + self.assertNotRegex(job, r"\b(docker push|docker login|az acr|kubectl)\b") + self.assertNotIn("secrets.", job) + self.assertGreaterEqual(job.count("if: always()"), 2) + self.assertIn("set -euo pipefail", job) + + def report_summary(self, root_events, api_events): + block = self.workflow_job("idp").split("python3 - <<'PY'\n", 1)[1] + script = textwrap.dedent(block.split("\n PY", 1)[0]) + with tempfile.TemporaryDirectory(prefix="idp-report-contract-") as temporary: + evidence = Path(temporary) + for name, events in (("upstream-tests.json", root_events), ("api-tests.json", api_events)): + (evidence / name).write_text("".join(json.dumps(event) + "\n" for event in events)) + result = subprocess.run( + ["python3", "-c", script], text=True, capture_output=True, timeout=10, + env={**os.environ, "IDP_EVIDENCE_DIR": temporary, + "GITHUB_STEP_SUMMARY": str(evidence / "step-summary.md")}, + ) + summary_file = evidence / "upstream-summary.json" + summary = json.loads(summary_file.read_text()) if summary_file.exists() else None + return result, summary + + def upstream_report_fixtures(self): + root = [ + {"Action": "start", "Package": "example/root"}, + {"Action": "pass", "Package": "example/root", "Test": "TestUnit"}, + {"Action": "skip", "Package": "example/root", "Test": "TestUnconfiguredLDAP"}, + {"Action": "pass", "Package": "example/root"}, + ] + api = [ + {"Action": "start", "Package": "example/api"}, + {"Action": "output", "Package": "example/api", "Output": "[no test files]\n"}, + {"Action": "skip", "Package": "example/api"}, + ] + return root, api + + def test_upstream_summary_discloses_skips_without_inventing_api_tests(self): + result, summary = self.report_summary(*self.upstream_report_fixtures()) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(summary["root"]["testActions"], {"pass": 1, "skip": 1}) + self.assertEqual(summary["root"]["skipped"], + [{"package": "example/root", "test": "TestUnconfiguredLDAP"}]) + self.assertEqual(summary["api"]["testActions"], {}) + self.assertEqual(summary["api"]["packageActions"], {"skip": 1}) + self.assertIn("not runtime-qualified", summary["coverageLimit"]) + + def test_upstream_summary_rejects_failure_or_incomplete_proof(self): + root, api = self.upstream_report_fixtures() + for root_events, api_events in ( + (root[:-1], api), (root, []), + (root + [{"Action": "fail", "Package": "example/root", "Test": "TestFailure"}], api), + (root, api + [{"Action": "build-fail", "ImportPath": "example/api"}]), + ([{"Action": "start", "Package": "example/root"}, + {"Action": "skip", "Package": "example/root"}], api), + (root + [None], api), + ): + with self.subTest(root=root_events, api=api_events): + result, summary = self.report_summary(root_events, api_events) + self.assertNotEqual(result.returncode, 0) + self.assertIsNone(summary) + def test_component_aggregate_rejects_missing_failed_or_skipped_jobs(self): check = runpy.run_path(str(CI / "bridge_component_results.py"))["require_success"] check(self.component_success()) @@ -125,10 +228,12 @@ def test_component_aggregate_rejects_missing_failed_or_skipped_jobs(self): def test_component_workflow_entrypoint_requires_complete_results(self): partial = self.component_success() del partial["security"] + without_idp = self.component_success() + del without_idp["idp"] environment = {key: value for key, value in os.environ.items() if key != "COMPONENT_RESULTS"} for payload, expected in ((json.dumps(self.component_success()), 0), - (json.dumps(partial), 1), ("not-json", 1), + (json.dumps(partial), 1), (json.dumps(without_idp), 1), ("not-json", 1), ("null", 1), (None, 1)): with self.subTest(payload=payload): result = subprocess.run( diff --git a/ci/tests/copyright_headers_test.py b/ci/tests/copyright_headers_test.py index 8e09b4d2..62870f80 100644 --- a/ci/tests/copyright_headers_test.py +++ b/ci/tests/copyright_headers_test.py @@ -53,6 +53,7 @@ def apply(self, name, data, expected_offset=None): def test_all_commentable_formats(self): fixtures = { "a.rs": b"//! Crate docs\nfn main() {}\n", + "a.go": b"package fixture\n\nfunc Value() int { return 1 }\n", "a.ts": b"/// \nexport {};\n", "a.tsx": b"'use client';\nexport const A = () =>

;\n", "a.js": b'"use strict";\nconst x = 1;', @@ -101,6 +102,20 @@ def test_shebangs_and_encoding_cookies(self): # declaration; the header must still precede the executable statement. self.apply("a.py", b"x = 1\n# coding: utf-8\n", 0) + def test_dex_integrity_data_has_exact_coverage_without_exempting_source_directories(self): + for name in ("bridge/idp/locks/generated/go.sum", + "bridge/idp/locks/generated/upstream/api/v2/go.mod", + "bridge/idp/patches/0001-literal-oauth-error-descriptions.patch", + "bridge/idp/patches/SHA256SUMS"): + rule = headers.classification(name, self.policy) + self.assertNotEqual(rule["category"], "header") + self.assertEqual(rule["notice"], "NOTICE") + for name in ("bridge/idp/scripts/new.go", "bridge/idp/patches/new.go"): + self.assertEqual(headers.classification(name, self.policy), + {"category": "header", "style": "slash"}) + with self.assertRaises(headers.CoverageError): + headers.classification("bridge/idp/locks/generated/unreviewed.lock", self.policy) + def test_bom_crlf_and_no_final_newline(self): for body in ( codecs.BOM_UTF8 + b'"use client";\r\nexport {};', @@ -440,13 +455,20 @@ def test_output_directory_names_never_imply_generated_coverage(self): self.apply(nested, b"export const value = 1;\n", 0) def test_generated_coverage_requires_exact_reviewed_paths(self): - expected = {"tools/headlamp-plugin/dist/main.js", "tools/headlamp-plugin/dist/package.json"} + headlamp = {"tools/headlamp-plugin/dist/main.js", "tools/headlamp-plugin/dist/package.json"} + dex = {"bridge/idp/locks/generated/" + name for name in ( + "go.mod", "go.sum", "api/v2/go.mod", "api/v2/go.sum", "modules.json", + "api-modules.json", "graph.txt", "toolchain.txt", "inputs.lock", "requests.txt", + "dependencies.patch", "SHA256SUMS", + )} + expected = headlamp | dex generated = {p for p, r in self.policy["files"].items() if r["category"] == "generated"} self.assertEqual(generated, expected) for name in expected: rule = headers.classification(name, self.policy) self.assertEqual(rule["notice"], "NOTICE") - self.assertIn("tools/headlamp-plugin/package.json", rule["reason"]) + if name in headlamp: + self.assertIn("tools/headlamp-plugin/package.json", rule["reason"]) for name in ( "tools/headlamp-plugin/dist/authored.ts", "tools/headlamp-plugin/dist/authored.d.ts", From d3778aa2b75d836bfc7fdaf1e5c4a3e41e25684c Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 19:44:55 +0200 Subject: [PATCH 07/13] docs(security): record curated Dex review and required runtime qualification Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- bridge/docs/public-beta-helm.md | 9 ++ .../2026-09-16-curated-dex-runtime.md | 108 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 docs/security-audits/2026-09-16-curated-dex-runtime.md diff --git a/bridge/docs/public-beta-helm.md b/bridge/docs/public-beta-helm.md index 230bfe24..f021f103 100644 --- a/bridge/docs/public-beta-helm.md +++ b/bridge/docs/public-beta-helm.md @@ -44,6 +44,15 @@ its label is not a rebuild. Do not overwrite normal release repositories with beta images or assume historical chart image defaults are publicly available. See [Bridge image builds and deployment](deployment.md#install). +If enabling bundled Dex, separately build and qualify the +[curated IdP runtime](../idp/README.md), then set `idp.dex.image` to its approved +immutable registry reference. The historical upstream chart default is not +an approved image merely because it is a default: the September 16 scan of +upstream v2.45.1 found High/Critical issues and blocked its use. Do not deploy +it, suppress those findings, or use the dev-role preview as authentication. +The curated source recipe is not itself a published or runtime-qualified image. +External OIDC remains an alternative when genuinely configured by the operator. + Before changing an existing installation, inventory Helm ownership, CRD/schema compatibility, workload placement and external credentials. Back up sensitive configuration privately with restricted file permissions, outside the checkout. diff --git a/docs/security-audits/2026-09-16-curated-dex-runtime.md b/docs/security-audits/2026-09-16-curated-dex-runtime.md new file mode 100644 index 00000000..14d8a7e1 --- /dev/null +++ b/docs/security-audits/2026-09-16-curated-dex-runtime.md @@ -0,0 +1,108 @@ + + +# Curated Dex runtime: bounded delegated source review + +Base: `b413f340d8d41aa3227538deee13569ca62d3981`. +Reviewed source: `f7cc7df8ef1cdfce9d4d92159a4e0ade5153bc1f`. + +Status: **Source-approved for hosted qualification, not runtime publication or +deployment approval.** The final distroless runtime, OIDC/SQLite, linkage and +image-scan job must actually pass before acceptance. + +## T1: New surface and reason for the change + +This is a security rebuild of the existing optional Dex IdP, not a second +authentication framework or a new credential authority. The latest official +stable v2.45.1 image was scanned before use and rejected with 128 High and five +Critical findings. It was not mirrored or deployed. Moving its registry +reference alone would not repair its contents. + +The recipe pins upstream application source at +`11d2eeb52b42e1980e14cb91e69dd9e3faab2076`, its archive hash, the Go 1.26.8 +builder and Microsoft Azure Linux 3 distroless base. Real Go-generated root +and nested API module locks are committed with their source/input, checksum +and module inventories. The normal build uses those locks read-only; it +cannot run the separate dependency-resolution recipe implicitly. + +No configuration, credentials, default issuer or user account ships in the +runtime. The existing chart's direct `dex serve` invocation remains supported. +Unused upstream template-expansion wrappers are not included. CGO and real +SQLite remain enabled; other upstream connector/storage code is retained, +not replaced by stubs. Unconfigured backend integrations remain unqualified. + +## T2: Security-control and compatibility changes + +The dependency selections close the recorded Go/library advisories. A new +advisory can still reject the final image; selection alone is not a clean scan. +Two disclosed production call-site patches use constant `"%s"` formats for +already-formatted OAuth errors rather than disabling vet. A historical SAML +test fixture uses its signed time through the library's test clock. Production +certificate validation and signed fixture bytes remain unchanged. + +Patch application verifies original source, reviewed patch bytes, expected +post-patch files and the complete final source inventory. It does not ignore +changed application files or regenerate expected hashes from arbitrary output. +Git check/apply uses the existing builder toolchain with strict whitespace +checking and no unsafe-path option. + +The shipping filesystem preserves the pinned Microsoft base, its CA trust +and RPM inventory. It adds the application, web assets and explicit source, +dependency and legal notices, not Debian libraries or build tools. Authentic +upstream `LICENCE` files are collected alongside `LICENSE`; missing licenses +still fail rather than being relabeled or skipped. + +The runtime probe verifies the saved, unexpired ID token and its original +key identity against the restarted SQLite-backed server **before** refresh. +It rejects lost/replaced keys, including reuse of a key ID, while permitting +rotation that retains the previous verification key. Existing refresh, +userinfo, nonce, issuer, audience and negative authentication checks remain. +Test credentials stay in private ephemeral fixtures, not shipping layers. + +## T3: Qualification and retained limits + +Actual no-push hosted generation produced the committed Go lock artifact. +Its transport/member hashes, source inputs, toolchain and selected graph were +verified on import. Actual hosted execution subsequently passed the focused +compatibility tests, upstream root/API race-suite commands, nine signing-key +continuity scenarios and probe compilation. The upstream reports were retained +in the test image; successful command exit is not an invented test count or +proof of skipped external-service integrations. + +Earlier failures remain recorded: a license filename was not recognized; +newer vet checks rejected two call sites; a historical signed fixture expired; +and the builder lacked the first selected patch utility. Each was corrected +without changing an enforcement expectation or disabling security checks. + +Twenty pinned-source application/integrity regressions passed with zero skips. +The parent also checked CI aggregate/report contracts and precise licensing +classification. Go wrappers use normal source headers; only enumerated legal, +generated integrity and upstream snapshot files have non-header coverage. +Unknown source files in those directories remain checked. Literal unified-diff +context whitespace is preserved and validated by patch/integrity tests rather +than corrupting the checksum-bound patch data. + +The mandatory new IdP component job builds the actual runtime and tools, +collects upstream reports, invokes the memory/SQLite/old-key/linkage/inventory +harness and scans the final OS and Go binary with pinned Trivy and a fresh DB. +High/Critical findings, including unfixed findings, remain fatal. Evidence is +retained even on failure. Existing component jobs, cancellation policy, native +requirements and read-only workflow permissions remain unchanged. + +Independent contexts reviewed the packaging/dependency/source boundary, +closed the old-key-continuity finding and compatibility patches, and reviewed +the CI execution path. No residual source finding remains within those scopes. +This does not establish final-image qualification, independent rebuild +reproducibility, enterprise connector compatibility or live beta acceptance. +No cluster or main-branch mutation is authorized by this record. + +## Delegation and verdict + +This uses the maintainer's explicit +[publication-review delegation](https://github.com/Azure/kars/pull/551#issuecomment-5615522306). +The implementation, independent AI review and parent composition are disclosed +as such, not two human reviews. Accept this bounded source for qualification; +all current-head technical/security and deployment gates remain required. + +Signed-off-by: pallakatos (author source attestation through explicit maintainer-delegated AI review, not a claim of personal code review) <191481949+pallakatos@users.noreply.github.com> +Signed-off-by: GitHub Copilot (independent-context delegated AI source review, not a second human) <223556219+Copilot@users.noreply.github.com> From 157e0d431f83c209ef74e1375241853eb028f5f8 Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 19:53:51 +0200 Subject: [PATCH 08/13] ci: initialize Dex evidence paths in runner step context Keep all final-image gates mandatory while using RUNNER_TEMP only after a runner exists. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- .github/workflows/bridge-ci.yml | 3 ++- ci/tests/bridge_contracts_test.py | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/bridge-ci.yml b/.github/workflows/bridge-ci.yml index 01990571..4f3aaa5c 100644 --- a/.github/workflows/bridge-ci.yml +++ b/.github/workflows/bridge-ci.yml @@ -230,7 +230,6 @@ jobs: contents: read env: PYTHONDONTWRITEBYTECODE: '1' - IDP_EVIDENCE_DIR: ${{ runner.temp }}/bridge-idp-evidence defaults: run: shell: bash @@ -241,6 +240,8 @@ jobs: - name: Initialize native Dex qualification evidence run: | set -euo pipefail + export IDP_EVIDENCE_DIR="$RUNNER_TEMP/bridge-idp-evidence" + printf 'IDP_EVIDENCE_DIR=%s\n' "$IDP_EVIDENCE_DIR" >> "$GITHUB_ENV" mkdir -p "$IDP_EVIDENCE_DIR" printf 'commit=%s\nrun_id=%s\nrun_attempt=%s\n' \ "$GITHUB_SHA" "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" \ diff --git a/ci/tests/bridge_contracts_test.py b/ci/tests/bridge_contracts_test.py index aeacc8c1..b6bcad22 100644 --- a/ci/tests/bridge_contracts_test.py +++ b/ci/tests/bridge_contracts_test.py @@ -120,6 +120,9 @@ def test_idp_is_required_by_the_exact_component_graph(self): def test_idp_job_requires_real_hosted_images_reports_runtime_and_scans(self): job = self.workflow_job("idp") + self.assertNotIn("runner.", job.split(" steps:", 1)[0]) + self.assertIn('export IDP_EVIDENCE_DIR="$RUNNER_TEMP/bridge-idp-evidence"', job) + self.assertIn('printf \'IDP_EVIDENCE_DIR=%s\\n\' "$IDP_EVIDENCE_DIR" >> "$GITHUB_ENV"', job) for required in ( "runs-on: ubuntu-24.04", "permissions:\n contents: read", 'test "$(uname -m)" = x86_64', "persist-credentials: false", From 9c5ed9a3badcb820b7fbc3ec171c1fb6dde65a81 Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 20:18:50 +0200 Subject: [PATCH 09/13] test(idp): preserve baseline data roles and resolve verified runtime links Keep active dependency manifests scanned, preserve archived baseline bytes and checksums, require nonroot replay, and resolve the real base-provided ELF interpreter before executing it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- bridge/idp/Dockerfile.locks | 12 +- bridge/idp/NOTICE | 12 +- bridge/idp/README.md | 65 ++++++++++- bridge/idp/locks/generated/SHA256SUMS | 8 +- .../api/v2/{go.mod => go.mod.snapshot} | 0 .../api/v2/{go.sum => go.sum.snapshot} | 0 .../upstream/{go.mod => go.mod.snapshot} | 0 .../upstream/{go.sum => go.sum.snapshot} | 0 bridge/idp/scripts/fetch-source.sh | 5 +- bridge/idp/scripts/generate-locks.sh | 2 +- bridge/idp/scripts/import-locks.py | 4 +- bridge/idp/scripts/verify-locks.sh | 2 +- bridge/idp/tests/contracts.py | 37 +++++- bridge/idp/tests/qualify.py | 13 ++- bridge/idp/tests/test_baselines.py | 109 ++++++++++++++++++ bridge/idp/tests/test_contracts.py | 49 +++++++- bridge/idp/tests/test_patches.py | 1 + ci/copyright-coverage.json | 8 +- ci/tests/copyright_headers_test.py | 2 +- 19 files changed, 293 insertions(+), 36 deletions(-) rename bridge/idp/locks/generated/upstream/api/v2/{go.mod => go.mod.snapshot} (100%) rename bridge/idp/locks/generated/upstream/api/v2/{go.sum => go.sum.snapshot} (100%) rename bridge/idp/locks/generated/upstream/{go.mod => go.mod.snapshot} (100%) rename bridge/idp/locks/generated/upstream/{go.sum => go.sum.snapshot} (100%) create mode 100644 bridge/idp/tests/test_baselines.py diff --git a/bridge/idp/Dockerfile.locks b/bridge/idp/Dockerfile.locks index 890c6252..7b38db38 100644 --- a/bridge/idp/Dockerfile.locks +++ b/bridge/idp/Dockerfile.locks @@ -19,11 +19,15 @@ COPY scripts/generate-locks.sh /packaging/scripts/generate-locks.sh RUN sh /packaging/scripts/generate-locks.sh FROM scratch AS lock-artifact -COPY --from=lock-generation /out/ / +COPY --from=lock-generation --chown=1001:1001 /out/ / +USER 1001:1001 -FROM lock-generation AS lock-replay -COPY locks/generated/ /reviewed/ -RUN cd /reviewed && sha256sum --check --strict SHA256SUMS \ +FROM source AS lock-replay +COPY --from=lock-generation --chown=1001:1001 /out/ /out/ +COPY --chown=1001:1001 locks/generated/ /reviewed/ +USER 1001:1001 +RUN test "$(id -u)" = 1001 && test "$(id -g)" = 1001 \ + && cd /reviewed && sha256sum --check --strict SHA256SUMS \ && cmp SHA256SUMS /out/SHA256SUMS \ && cd /out && sha256sum --check --strict /reviewed/SHA256SUMS \ && printf 'KARS_DEX_LOCK_REPLAY_PASSED\n' diff --git a/bridge/idp/NOTICE b/bridge/idp/NOTICE index e1909281..692d598e 100644 --- a/bridge/idp/NOTICE +++ b/bridge/idp/NOTICE @@ -27,9 +27,15 @@ are distributed in /usr/share/doc/dex/source-patches. Complete original and expected patched source inventories are distributed as source.upstream.sha256 and source.sha256 in /usr/share/doc/dex. -The generated dependency diff and original and patched module files are -distributed in /usr/share/doc/dex/locks. Linked dependency license and notice -files are distributed in /usr/share/doc/dex/third-party. +The generated dependency diff, active patched module files, and byte-for-byte +original module baselines are distributed in /usr/share/doc/dex/locks. +The four archival baselines under locks/upstream use go.mod.snapshot and +go.sum.snapshot filenames, including the api/v2 subdirectory. They are +comparison/attribution data, never compiler inputs. This path-only distinction +preserves every original byte and SHA-256 while the active patched go.mod and +go.sum retain their normal filenames and full dependency/security scanning. +Linked dependency license and notice files are distributed in +/usr/share/doc/dex/third-party. The official image's gomplate and docker-entrypoint programs are intentionally not distributed. The supported invocation is /usr/local/bin/dex serve with an diff --git a/bridge/idp/README.md b/bridge/idp/README.md index 8b49e5da..bc600210 100644 --- a/bridge/idp/README.md +++ b/bridge/idp/README.md @@ -4,7 +4,8 @@ Licensed under the MIT License. --> # Kars Dex security rebuild **Status: hosted build/test stages passed; final runtime qualification pending.** -Real Go-generated `locks/generated/` files are present and remain unchanged. +Real Go-generated active locks under `locks/generated/` remain byte-for-byte +unchanged; historical baselines use the path-only snapshot layout described below. The successful hosted attempt on September 16, 2026 compiled Dex with CGO, completed license collection, passed the compatibility cases, completed the upstream root/API race-suite commands with exit code zero, passed all nine @@ -163,13 +164,60 @@ supported by this package. Direct Dex features are not replaced or removed. Azure Linux's **14 RPM inventory records**, base files and CA trust are retained rather than reconstructed. The final image installs the upstream -Apache-2.0 license, this package's MIT license, attribution, original/patched -module files, dependency diff, Go build metadata and ELF metadata under +Apache-2.0 license, this package's MIT license, attribution, original module +snapshots, active patched module files, dependency diff, Go build metadata and ELF metadata under `/usr/share/doc/dex/`. A build-time collector retains license/notice files from linked modules (including bundled notices), and fails for missing root licenses rather than silently shipping incomplete attribution. License review of the generated graph and bundled native code is still an acceptance gate. +## Active locks versus archival baseline data + +The verified hosted artifact's four historical module baselines are now +explicit **data snapshots**, not active Go manifests. The change is a +deterministic path-only migration of the already-verified artifact: all four +file contents and SHA-256 values are unchanged, and only their four paths +change in `locks/generated/SHA256SUMS`. No Go resolution, dependency update, +compiler/base change, exclusion, waiver or vulnerability suppression is involved. + +Under `bridge/idp/locks/generated/upstream/`: + +| Original archival path | Current data path | +| --- | --- | +| `go.mod` | `go.mod.snapshot` | +| `go.sum` | `go.sum.snapshot` | +| `api/v2/go.mod` | `api/v2/go.mod.snapshot` | +| `api/v2/go.sum` | `api/v2/go.sum.snapshot` | + +The active patched `locks/generated/go.mod`, `go.sum`, `api/v2/go.mod` and +`api/v2/go.sum` retain their normal filenames, original patched bytes and full +dependency/security scanning. Module inventories, graph, dependency diff, +inputs, toolchain record and all other generated artifact contents are +unchanged. The saved historical baselines are used only for byte comparison, +diffing and attribution; the build still copies **only active locks** into +the Go source tree. + +This distinction prevents dependency discovery from mistaking archived +upstream dependencies for new active dependencies. Actual runtime dependencies +and their final-image vulnerability scans remain fully enforced. The runtime +metadata copy preserves the same data suffixes under +`/usr/share/doc/dex/locks/upstream/`. + +The original raw hosted-generation log remains unchanged outside the repository +as provenance, with its original transport hash and original archive member +names. `dependencies.patch` also keeps its logical `upstream/go.mod` and +`upstream/api/v2/go.mod` source labels; those labels are not stored manifest +files or compile inputs. Future generation emits the new snapshot layout +directly. The importer and validator require that layout and reject legacy or +mixed active-looking baseline names; do not overwrite the migrated files by +reimporting an old-layout log or re-resolving dependencies. + +Representation contracts compare every generated file digest with the +pre-migration verified artifact, require exactly four normally named active +Go locks, and exercise archive import/rejection. With the verified-archive +source tests enabled, each baseline snapshot is also compared byte-for-byte +with its original file from the pinned upstream tarball. + ## Hosted lock generation Local Docker and Go were unavailable and disk was below the 8.5 GiB floor. @@ -220,8 +268,9 @@ docker buildx build --platform linux/amd64 --target lock-artifact \ Artifact contents are the generated root/API `go.mod` and `go.sum`, `modules.json`, `api-modules.json`, `graph.txt`, `toolchain.txt`, -`inputs.lock`, `requests.txt`, `dependencies.patch`, the four unchanged -`upstream/` module files, and `SHA256SUMS`. Review and persist these under +`inputs.lock`, `requests.txt`, `dependencies.patch`, the four byte-unchanged +`upstream/` baseline data files (`go.mod.snapshot` / `go.sum.snapshot` at the +root and under `api/v2`), and `SHA256SUMS`. Review and persist these under `bridge/idp/locks/generated/` before any runtime build. Generated module checksums are Go's, not fabricated or transcribed from vulnerability reports. On a second clean **native worker of the same architecture**, replay the @@ -232,6 +281,12 @@ docker build --no-cache --target lock-replay \ --file bridge/idp/Dockerfile.locks bridge/idp ``` +The non-shipping artifact and replay stages default to `1001:1001`. Both sets +of replay inputs are copied with that ownership, without changing lock bytes +or applying `chmod` to upstream data. Replay asserts its actual UID/GID before +running the read-only checksum comparisons. In `Dockerfile.locks`, root is +retained only in the source/resolution stages that need build-directory writes. + The replay target verifies both checksum inventories and requires exact agreement for the root/API locks, selected module graphs, source snapshots, dependency diff, inputs and toolchain record. Retain the build log with diff --git a/bridge/idp/locks/generated/SHA256SUMS b/bridge/idp/locks/generated/SHA256SUMS index 07c2eb38..52a96419 100644 --- a/bridge/idp/locks/generated/SHA256SUMS +++ b/bridge/idp/locks/generated/SHA256SUMS @@ -9,7 +9,7 @@ d5a430f8c8fea443ebc134cff29ddc0914bdc7acc1220fce9073c439e1a780d6 ./inputs.lock 2381158f636af5715561fca4208f4d89ca22a0e9c393bd53daa984a644ce5b72 ./modules.json 23d3448085a87cb3d242e196bb8ad7b571b63392c90871c2f5b26b1c5f0b6575 ./requests.txt 7e35a947feee25f89c2649aa041942db786be35c3d6c484ab2ba2da849e3dc00 ./toolchain.txt -181fc42a509297fe685e3470388d378a229e6efd36dd874eef809b6e06fe41e8 ./upstream/api/v2/go.mod -ccf35830330ac8058a4f009babbb417039aec728cf92625572abc53474c5dfca ./upstream/api/v2/go.sum -3390a3a2aa213fa80b7cb857ae52eb031e0f1941292f3536951092acb1db1501 ./upstream/go.mod -09fab6a9bedf5e220ee82f75f8fc7db4f52854012875082f24ba629020980d13 ./upstream/go.sum +181fc42a509297fe685e3470388d378a229e6efd36dd874eef809b6e06fe41e8 ./upstream/api/v2/go.mod.snapshot +ccf35830330ac8058a4f009babbb417039aec728cf92625572abc53474c5dfca ./upstream/api/v2/go.sum.snapshot +3390a3a2aa213fa80b7cb857ae52eb031e0f1941292f3536951092acb1db1501 ./upstream/go.mod.snapshot +09fab6a9bedf5e220ee82f75f8fc7db4f52854012875082f24ba629020980d13 ./upstream/go.sum.snapshot diff --git a/bridge/idp/locks/generated/upstream/api/v2/go.mod b/bridge/idp/locks/generated/upstream/api/v2/go.mod.snapshot similarity index 100% rename from bridge/idp/locks/generated/upstream/api/v2/go.mod rename to bridge/idp/locks/generated/upstream/api/v2/go.mod.snapshot diff --git a/bridge/idp/locks/generated/upstream/api/v2/go.sum b/bridge/idp/locks/generated/upstream/api/v2/go.sum.snapshot similarity index 100% rename from bridge/idp/locks/generated/upstream/api/v2/go.sum rename to bridge/idp/locks/generated/upstream/api/v2/go.sum.snapshot diff --git a/bridge/idp/locks/generated/upstream/go.mod b/bridge/idp/locks/generated/upstream/go.mod.snapshot similarity index 100% rename from bridge/idp/locks/generated/upstream/go.mod rename to bridge/idp/locks/generated/upstream/go.mod.snapshot diff --git a/bridge/idp/locks/generated/upstream/go.sum b/bridge/idp/locks/generated/upstream/go.sum.snapshot similarity index 100% rename from bridge/idp/locks/generated/upstream/go.sum rename to bridge/idp/locks/generated/upstream/go.sum.snapshot diff --git a/bridge/idp/scripts/fetch-source.sh b/bridge/idp/scripts/fetch-source.sh index 133f9d10..c0b90a81 100644 --- a/bridge/idp/scripts/fetch-source.sh +++ b/bridge/idp/scripts/fetch-source.sh @@ -12,6 +12,7 @@ tar -xzf /tmp/dex.tar.gz --strip-components=1 -C /src/dex rm /tmp/dex.tar.gz sh /packaging/scripts/source-inventory.sh > /packaging/source.upstream.sha256 mkdir -p /packaging/upstream/api/v2 -cp go.mod go.sum /packaging/upstream/ -cp api/v2/go.mod api/v2/go.sum /packaging/upstream/api/v2/ +for file in go.mod go.sum api/v2/go.mod api/v2/go.sum; do + cp "$file" "/packaging/upstream/$file.snapshot" +done sh /packaging/scripts/apply-source-patches.sh diff --git a/bridge/idp/scripts/generate-locks.sh b/bridge/idp/scripts/generate-locks.sh index 2aee2c21..8162297e 100644 --- a/bridge/idp/scripts/generate-locks.sh +++ b/bridge/idp/scripts/generate-locks.sh @@ -39,7 +39,7 @@ cp -R /packaging/upstream /out/upstream for file in go.mod go.sum api/v2/go.mod api/v2/go.sum; do set +e diff -u --label "upstream/$file" --label "kars/$file" \ - "/packaging/upstream/$file" "/out/$file" >> /out/dependencies.patch + "/packaging/upstream/$file.snapshot" "/out/$file" >> /out/dependencies.patch status=$? set -e test "$status" -le 1 diff --git a/bridge/idp/scripts/import-locks.py b/bridge/idp/scripts/import-locks.py index 107e0188..bd4848af 100644 --- a/bridge/idp/scripts/import-locks.py +++ b/bridge/idp/scripts/import-locks.py @@ -2,7 +2,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -"""Import public Go-generated artifacts from an ACR --no-push build log.""" +"""Import active Go locks and archival .snapshot baselines from a no-push build log.""" import base64 import gzip @@ -75,7 +75,7 @@ def main(): shutil.copyfile(ROOT / "locks" / name, stage / "locks" / name) check_modules(stage) generated.rename(target) - print("Imported Go-generated locks. Review dependencies.patch and all selected modules before building.") + print("Imported active Go locks and archival .snapshot baselines. Review dependencies.patch and all selected modules before building.") if __name__ == "__main__": diff --git a/bridge/idp/scripts/verify-locks.sh b/bridge/idp/scripts/verify-locks.sh index 1e7858c3..78ecb0a5 100644 --- a/bridge/idp/scripts/verify-locks.sh +++ b/bridge/idp/scripts/verify-locks.sh @@ -9,7 +9,7 @@ cmp /packaging/locks/inputs.lock /locks/inputs.lock cmp /packaging/locks/requests.txt /locks/requests.txt test "$(cat /locks/toolchain.txt)" = "go version $GO_VERSION linux/$(go env GOARCH)" for file in go.mod go.sum api/v2/go.mod api/v2/go.sum; do - cmp "/packaging/upstream/$file" "/locks/upstream/$file" + cmp "/packaging/upstream/$file.snapshot" "/locks/upstream/$file.snapshot" cp "/locks/$file" "$file" done test "$(go list -m -f '{{.GoVersion}}')" = 1.26.0 diff --git a/bridge/idp/tests/contracts.py b/bridge/idp/tests/contracts.py index 4847b2d0..ded87254 100644 --- a/bridge/idp/tests/contracts.py +++ b/bridge/idp/tests/contracts.py @@ -11,9 +11,9 @@ "4377af4aa7a810b7d59f691eae5066895a71aa3eee4cfb4eba527bbebff16479" ) RPM_MANIFEST = "var/lib/rpmmanifest/container-manifest-2" -LOCK_FILES = { - "go.mod", "go.sum", "api/v2/go.mod", "api/v2/go.sum", - "upstream/go.mod", "upstream/go.sum", "upstream/api/v2/go.mod", "upstream/api/v2/go.sum", +ACTIVE_LOCK_FILES = {"go.mod", "go.sum", "api/v2/go.mod", "api/v2/go.sum"} +BASELINE_SNAPSHOTS = {f"upstream/{name}.snapshot" for name in ACTIVE_LOCK_FILES} +LOCK_FILES = ACTIVE_LOCK_FILES | BASELINE_SNAPSHOTS | { "modules.json", "api-modules.json", "graph.txt", "toolchain.txt", "inputs.lock", "requests.txt", "dependencies.patch", "SHA256SUMS", } @@ -121,6 +121,37 @@ def check_rootfs(base, runtime, manifest): "usr/bin/tdnf", "usr/bin/npm", "usr/local/go/bin/go", "usr/bin/gcc"): require(name not in runtime, f"shipping tool/unused entrypoint: {name}") +def resolve_base_file(inventory, requested): + require(isinstance(requested, str) and requested.startswith("/") + and len(requested) <= 4096 and "\0" not in requested, "invalid ELF interpreter path") + pending = requested.split("/") + resolved = [] + links = 0 + while pending: + part = pending.pop(0) + if part in ("", "."): + continue + if part == "..": + require(resolved, "base link escapes image root") + resolved.pop() + continue + name = "/".join([*resolved, part]) + entry = inventory.get(name) + if entry is not None and entry[0] in ("symlink", "hardlink"): + links += 1 + require(links <= 32, "base link resolution exceeds its bound") + target = entry[2] + require(isinstance(target, str) and target and len(target) <= 4096 + and "\0" not in target, "invalid base link target") + if entry[0] == "hardlink" or target.startswith("/"): + resolved = [] + pending = target.split("/") + pending + else: + resolved.append(part) + name = "/".join(resolved) + require(inventory.get(name, (None,))[0] == "file", "ELF interpreter is not provided by pinned runtime") + return name + def check_scan(report): require(report.get("Metadata", {}).get("OS", {}).get("Family") == "azurelinux", diff --git a/bridge/idp/tests/qualify.py b/bridge/idp/tests/qualify.py index 6121e821..2c531d32 100644 --- a/bridge/idp/tests/qualify.py +++ b/bridge/idp/tests/qualify.py @@ -16,7 +16,7 @@ import tempfile import uuid -from contracts import BASE, RPM_MANIFEST, check_modules, check_rootfs, check_scan, require +from contracts import BASE, RPM_MANIFEST, check_modules, check_rootfs, check_scan, require, resolve_base_file def run(*args, **kwargs): @@ -39,8 +39,10 @@ def export(image, directory, prefix): entries[name] = ("file", member.mode, hashlib.sha256(data).hexdigest()) if name == RPM_MANIFEST or name.startswith("usr/share/doc/dex/elf-"): documents[name] = data.decode() - elif member.issym() or member.islnk(): - entries[name] = ("link", member.mode, member.linkname) + elif member.issym(): + entries[name] = ("symlink", member.mode, member.linkname) + elif member.islnk(): + entries[name] = ("hardlink", member.mode, member.linkname) return entries, documents finally: run("docker", "rm", container) @@ -122,7 +124,10 @@ def main(): match = re.search(r"Requesting program interpreter: ([^\]]+)", headers) require(match is not None, "CGO Dex must have a real runtime ELF interpreter") loader = match.group(1) - require(loader.lstrip("/") in base, "ELF interpreter is not provided by pinned runtime") + provided = resolve_base_file(base, loader) + (args.evidence / "interpreter-origin.json").write_text(json.dumps({ + "requested": loader, "resolvedBaseFile": provided, "baseEntry": base[provided], + }, indent=2)) linked = run("docker", "run", "--rm", "--network", "none", "--read-only", "--cap-drop", "ALL", "--security-opt", "no-new-privileges", "--entrypoint", loader, image_id, "--list", "/usr/local/bin/dex") diff --git a/bridge/idp/tests/test_baselines.py b/bridge/idp/tests/test_baselines.py new file mode 100644 index 00000000..da48fbfd --- /dev/null +++ b/bridge/idp/tests/test_baselines.py @@ -0,0 +1,109 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import base64 +import hashlib +import importlib.util +import io +from pathlib import Path +import tarfile +import unittest + +from contracts import ACTIVE_LOCK_FILES, BASELINE_SNAPSHOTS, LOCK_FILES, check_modules + +ROOT = Path(__file__).resolve().parents[1] +GENERATED = ROOT / "locks/generated" +spec = importlib.util.spec_from_file_location("baseline_import_locks", ROOT / "scripts/import-locks.py") +import_locks = importlib.util.module_from_spec(spec) +spec.loader.exec_module(import_locks) + +# Captured from the verified chhp artifact before the path-only migration. +# A future dependency update requires a newly reviewed artifact, not rewriting +# these historical digests as part of a representation-only change. +CHHP_MANIFEST = """4a7bed6907c8f8918791e69539597405d6ad18f3f386788a81ed28f024113ac8 ./api-modules.json +e304bf72c1bf687cf777af1ca1c70d96e928a86bfb40bc6d5aeb8239baac24f6 ./api/v2/go.mod +3410f76108a083dc3a603327c354639a078ee8d917146aa7bf769e37cce0f208 ./api/v2/go.sum +7aab541b65a7246f95a919912582d909a8cfc09e9348a10e34afac1773c29644 ./dependencies.patch +34b7b1e48a6020a855741fc497f0782f226fa75a701cf925c52ccdd322d38046 ./go.mod +6e47d5b5c5cd6ff030ffe276d8707e41c67e88321a6bc81248f61c58271ec59b ./go.sum +e65265ab047188c71f6c5369a5be77d8cbbbefe26e307eb505775050ebece449 ./graph.txt +d5a430f8c8fea443ebc134cff29ddc0914bdc7acc1220fce9073c439e1a780d6 ./inputs.lock +2381158f636af5715561fca4208f4d89ca22a0e9c393bd53daa984a644ce5b72 ./modules.json +23d3448085a87cb3d242e196bb8ad7b571b63392c90871c2f5b26b1c5f0b6575 ./requests.txt +7e35a947feee25f89c2649aa041942db786be35c3d6c484ab2ba2da849e3dc00 ./toolchain.txt +181fc42a509297fe685e3470388d378a229e6efd36dd874eef809b6e06fe41e8 ./upstream/api/v2/go.mod +ccf35830330ac8058a4f009babbb417039aec728cf92625572abc53474c5dfca ./upstream/api/v2/go.sum +3390a3a2aa213fa80b7cb857ae52eb031e0f1941292f3536951092acb1db1501 ./upstream/go.mod +09fab6a9bedf5e220ee82f75f8fc7db4f52854012875082f24ba629020980d13 ./upstream/go.sum +""" + + +def artifact_log(files): + stream = io.BytesIO() + with tarfile.open(fileobj=stream, mode="w:gz") as archive: + for name, data in sorted(files.items()): + member = tarfile.TarInfo("./" + name) + member.size = len(data) + archive.addfile(member, io.BytesIO(data)) + payload = stream.getvalue() + return ("KARS_DEX_LOCKS_BASE64_BEGIN\n" + base64.b64encode(payload).decode() + + "\nKARS_DEX_LOCKS_BASE64_END\n" + hashlib.sha256(payload).hexdigest() + + " /tmp/dex-locks.tar.gz\n") + + +class BaselineRepresentationContracts(unittest.TestCase): + def test_migration_preserves_every_artifact_digest_and_only_changes_manifest_paths(self): + expected_manifest = [] + for line in CHHP_MANIFEST.splitlines(): + digest, original = line.split(" ", 1) + renamed = original + ".snapshot" if original.startswith("./upstream/") else original + self.assertEqual(hashlib.sha256((GENERATED / renamed).read_bytes()).hexdigest(), digest, renamed) + expected_manifest.append(f"{digest} {renamed}\n") + self.assertEqual((GENERATED / "SHA256SUMS").read_bytes(), "".join(expected_manifest).encode()) + check_modules(ROOT) + + def test_only_active_go_locks_keep_recognized_manifest_filenames(self): + expected_active = {"go.mod", "go.sum", "api/v2/go.mod", "api/v2/go.sum"} + self.assertEqual(ACTIVE_LOCK_FILES, expected_active) + recognized = {str(path.relative_to(GENERATED)) for path in GENERATED.rglob("*") + if path.is_file() and path.name in ("go.mod", "go.sum")} + self.assertEqual(recognized, expected_active) + self.assertEqual(BASELINE_SNAPSHOTS, {f"upstream/{name}.snapshot" for name in expected_active}) + for name in expected_active: + self.assertFalse((GENERATED / "upstream" / name).exists()) + self.assertTrue((GENERATED / "upstream" / (name + ".snapshot")).is_file()) + + def test_new_artifacts_import_without_altering_active_or_archival_bytes(self): + files = {name: (GENERATED / name).read_bytes() for name in LOCK_FILES} + imported = import_locks.decode_artifact(artifact_log(files)) + self.assertEqual(set(imported), LOCK_FILES) + for name, data in files.items(): + self.assertEqual(imported[name], data, name) + + def test_import_rejects_legacy_or_duplicate_active_looking_baselines(self): + files = {name: (GENERATED / name).read_bytes() for name in LOCK_FILES} + legacy = {name.removesuffix(".snapshot") if name in BASELINE_SNAPSHOTS else name: data + for name, data in files.items()} + legacy["SHA256SUMS"] = CHHP_MANIFEST.encode() + mixed = {**files, "upstream/go.mod": files["upstream/go.mod.snapshot"]} + for invalid in (legacy, mixed): + with self.assertRaisesRegex(ValueError, "unexpected or duplicate lock member"): + import_locks.decode_artifact(artifact_log(invalid)) + + def test_generator_validator_and_runtime_metadata_use_the_data_layout(self): + fetch = (ROOT / "scripts/fetch-source.sh").read_text() + self.assertIn('cp "$file" "/packaging/upstream/$file.snapshot"', fetch) + generator = (ROOT / "scripts/generate-locks.sh").read_text() + self.assertIn('cp -R /packaging/upstream /out/upstream', generator) + self.assertIn('"/packaging/upstream/$file.snapshot" "/out/$file"', generator) + self.assertIn('--label "upstream/$file" --label "kars/$file"', generator) + verifier = (ROOT / "scripts/verify-locks.sh").read_text() + self.assertIn('cmp "/packaging/upstream/$file.snapshot" "/locks/upstream/$file.snapshot"', verifier) + self.assertIn('cp "/locks/$file" "$file"', verifier) + self.assertNotIn('cp "/locks/upstream/', verifier) + self.assertIn('cp -R /locks /out/doc/locks', (ROOT / "scripts/build.sh").read_text()) + self.assertIn('COPY --from=build /out/doc/ /usr/share/doc/dex/', (ROOT / "Dockerfile").read_text()) + + +if __name__ == "__main__": + unittest.main() diff --git a/bridge/idp/tests/test_contracts.py b/bridge/idp/tests/test_contracts.py index 688213f4..f50ba601 100644 --- a/bridge/idp/tests/test_contracts.py +++ b/bridge/idp/tests/test_contracts.py @@ -11,7 +11,7 @@ import tarfile import unittest -from contracts import BASE, LOCK_FILES, RPM_MANIFEST, check_modules, check_rootfs, check_scan, json_stream, module_inventory +from contracts import BASE, LOCK_FILES, RPM_MANIFEST, check_modules, check_rootfs, check_scan, json_stream, module_inventory, resolve_base_file ROOT = Path(__file__).resolve().parents[1] spec = importlib.util.spec_from_file_location("import_locks", ROOT / "scripts/import-locks.py") @@ -51,7 +51,7 @@ def test_resolver_is_separate_from_runtime_build(self): self.assertNotIn("generate-locks", runtime) self.assertNotIn("FROM lock-generation", runtime) self.assertNotIn("lock-replay", runtime) - self.assertIn("FROM lock-generation AS lock-replay", maintenance) + self.assertIn("FROM source AS lock-replay", maintenance) self.assertIn("cmp SHA256SUMS /out/SHA256SUMS", maintenance) def source(text): return text[text.index("FROM golang:"):text.index("\nFROM source AS ")] @@ -59,6 +59,31 @@ def source(text): self.assertEqual(source(runtime), source(maintenance)) self.assertIn("!Dockerfile.locks", (ROOT / ".dockerignore").read_text()) + def test_lock_artifact_and_readonly_replay_default_to_nonroot(self): + maintenance = (ROOT / "Dockerfile.locks").read_text() + artifact = maintenance.split("FROM scratch AS lock-artifact\n", 1)[1].split("\nFROM ", 1)[0] + replay = maintenance.split("FROM source AS lock-replay\n", 1)[1] + self.assertIn("COPY --from=lock-generation --chown=1001:1001 /out/ /", artifact) + self.assertEqual([line for line in artifact.splitlines() if line.startswith("USER ")], + ["USER 1001:1001"]) + self.assertNotIn("RUN ", artifact) + self.assertIn("COPY --from=lock-generation --chown=1001:1001 /out/ /out/", replay) + self.assertIn("COPY --chown=1001:1001 locks/generated/ /reviewed/", replay) + self.assertEqual([line for line in replay.splitlines() if line.startswith("USER ")], + ["USER 1001:1001"]) + self.assertLess(replay.index("USER 1001:1001"), replay.index("RUN ")) + self.assertIn('test "$(id -u)" = 1001 && test "$(id -g)" = 1001', replay) + self.assertIn("sha256sum --check --strict /reviewed/SHA256SUMS", replay) + self.assertNotIn("chmod", maintenance) + self.assertNotIn("go get", replay) + self.assertNotIn("go mod", replay) + self.assertNotIn("USER root", replay) + for path in (ROOT / "locks/generated").rglob("*"): + if path.is_file(): + self.assertTrue(path.stat().st_mode & 0o400, f"COPY owner cannot read {path}") + elif path.is_dir(): + self.assertTrue(path.stat().st_mode & 0o100, f"COPY owner cannot traverse {path}") + def test_missing_locks_block_acceptance(self): if (ROOT / "locks/generated").is_dir(): check_modules(ROOT) @@ -105,6 +130,26 @@ def test_scanner_must_see_both_os_and_go(self): with self.assertRaisesRegex(ValueError, "Dex Go binary"): check_scan(report) + def test_real_azure_linux_interpreter_links_resolve_only_to_base_files(self): + inventory = { + "lib64": ("symlink", 0o777, "usr/lib"), + "usr/lib64": ("symlink", 0o777, "lib"), + "usr/lib/ld-linux-x86-64.so.2": ("file", 0o755, "original-base-bytes"), + "usr/lib/absolute-loader": ("symlink", 0o777, "/lib64/ld-linux-x86-64.so.2"), + "usr/lib/hard-loader": ("hardlink", 0o755, "usr/lib/ld-linux-x86-64.so.2"), + } + for path in ("/lib64/ld-linux-x86-64.so.2", "/usr/lib64/ld-linux-x86-64.so.2", + "/usr/lib/absolute-loader", "/usr/lib/hard-loader"): + self.assertEqual(resolve_base_file(inventory, path), "usr/lib/ld-linux-x86-64.so.2") + self.assertEqual(inventory["lib64"][2], "usr/lib") + for path in ("/usr/share/doc/dex/not-in-base", "/lib64/missing", "relative/path"): + with self.assertRaises(ValueError): + resolve_base_file(inventory, path) + with self.assertRaisesRegex(ValueError, "bound"): + resolve_base_file({"cycle": ("symlink", 0o777, "cycle")}, "/cycle") + with self.assertRaisesRegex(ValueError, "escapes"): + resolve_base_file({"escape": ("symlink", 0o777, "../../host")}, "/escape") + def test_python_syntax(self): for file in ROOT.rglob("*.py"): ast.parse(file.read_text(), filename=str(file)) diff --git a/bridge/idp/tests/test_patches.py b/bridge/idp/tests/test_patches.py index 7c36783b..c998052a 100644 --- a/bridge/idp/tests/test_patches.py +++ b/bridge/idp/tests/test_patches.py @@ -148,6 +148,7 @@ def test_exact_patch_application_and_complete_inventory(self): 'newRedirectedErr(errInvalidRequest, "%s", err)')) for name, data in modules.items(): self.assertEqual((self.source / name).read_bytes(), data) + self.assertEqual((ROOT / "locks/generated/upstream" / (name + ".snapshot")).read_bytes(), data) fixture = ET.parse(self.source / "connector/saml/testdata/oam-resp.xml") self.assertEqual(fixture.getroot().attrib["IssueInstant"], "2016-12-12T16:54:35Z") self.assertEqual(self.original["./connector/saml/saml.go"], expected["./connector/saml/saml.go"]) diff --git a/ci/copyright-coverage.json b/ci/copyright-coverage.json index cc0356d1..0c93e7a2 100644 --- a/ci/copyright-coverage.json +++ b/ci/copyright-coverage.json @@ -133,22 +133,22 @@ "reason": "Actual nested API Go module checksums; preserve original generated bytes.", "notice": "NOTICE" }, - "bridge/idp/locks/generated/upstream/go.mod": { + "bridge/idp/locks/generated/upstream/go.mod.snapshot": { "category": "third-party", "reason": "Exact pinned upstream Dex module snapshot under Apache-2.0, not Microsoft-authored source.", "notice": "NOTICE" }, - "bridge/idp/locks/generated/upstream/go.sum": { + "bridge/idp/locks/generated/upstream/go.sum.snapshot": { "category": "third-party", "reason": "Exact pinned upstream Dex dependency checksums retained for comparison and attribution.", "notice": "NOTICE" }, - "bridge/idp/locks/generated/upstream/api/v2/go.mod": { + "bridge/idp/locks/generated/upstream/api/v2/go.mod.snapshot": { "category": "third-party", "reason": "Exact pinned upstream Dex API module snapshot; preserve upstream ownership and bytes.", "notice": "NOTICE" }, - "bridge/idp/locks/generated/upstream/api/v2/go.sum": { + "bridge/idp/locks/generated/upstream/api/v2/go.sum.snapshot": { "category": "third-party", "reason": "Exact pinned upstream Dex API dependency checksum snapshot; preserve upstream data.", "notice": "NOTICE" diff --git a/ci/tests/copyright_headers_test.py b/ci/tests/copyright_headers_test.py index 62870f80..ea2a3c9c 100644 --- a/ci/tests/copyright_headers_test.py +++ b/ci/tests/copyright_headers_test.py @@ -104,7 +104,7 @@ def test_shebangs_and_encoding_cookies(self): def test_dex_integrity_data_has_exact_coverage_without_exempting_source_directories(self): for name in ("bridge/idp/locks/generated/go.sum", - "bridge/idp/locks/generated/upstream/api/v2/go.mod", + "bridge/idp/locks/generated/upstream/api/v2/go.mod.snapshot", "bridge/idp/patches/0001-literal-oauth-error-descriptions.patch", "bridge/idp/patches/SHA256SUMS"): rule = headers.classification(name, self.policy) From 369aa8616a239cfab7b4612f99188e99441596d2 Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 20:31:14 +0200 Subject: [PATCH 10/13] test(idp): require Dex unauthorized response for invalid passwords Match the pinned upstream login contract exactly, retain error-form and no-callback requirements, and reject misleading successful or unrelated error responses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- bridge/idp/tests/probe.go | 4 +-- bridge/idp/tests/probe_test.go | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/bridge/idp/tests/probe.go b/bridge/idp/tests/probe.go index f23316bb..a5ea32c5 100644 --- a/bridge/idp/tests/probe.go +++ b/bridge/idp/tests/probe.go @@ -217,8 +217,8 @@ func login(issuer, password, verifier, nonce string, shouldSucceed bool) (string defer resp.Body.Close() location := resp.Header.Get("Location") if !shouldSucceed { - if resp.StatusCode != http.StatusOK || strings.HasPrefix(location, callback) { - return "", fmt.Errorf("invalid password did not remain on login form") + if resp.StatusCode != http.StatusUnauthorized || strings.HasPrefix(location, callback) { + return "", fmt.Errorf("invalid password did not return its unauthorized login form (status %d)", resp.StatusCode) } body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) if err != nil { diff --git a/bridge/idp/tests/probe_test.go b/bridge/idp/tests/probe_test.go index 06781ba4..9406e3e3 100644 --- a/bridge/idp/tests/probe_test.go +++ b/bridge/idp/tests/probe_test.go @@ -38,6 +38,55 @@ func continuityKey(kid string, key *rsa.PrivateKey) continuityJWK { } } +func TestInvalidPasswordResponse(t *testing.T) { + for _, tc := range []struct { + name string + status int + errorBox bool + redirect bool + wantOK bool + }{ + {name: "upstream unauthorized form", status: http.StatusUnauthorized, errorBox: true, wantOK: true}, + {name: "successful status is not rejection", status: http.StatusOK, errorBox: true}, + {name: "unrelated unauthorized response", status: http.StatusUnauthorized}, + {name: "bad request is not authentication rejection", status: http.StatusBadRequest, errorBox: true}, + {name: "callback redirect is not rejection", status: http.StatusFound, redirect: true}, + } { + t.Run(tc.name, func(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html") + switch { + case r.Method == http.MethodGet && r.URL.Path == "/dex/auth": + _, _ = w.Write([]byte(`

`)) + case r.Method == http.MethodPost && r.URL.Path == "/dex/login": + if err := r.ParseForm(); err != nil { + t.Error(err) + w.WriteHeader(http.StatusBadRequest) + return + } + if r.Form.Get("login") != email || r.Form.Get("password") != "wrong-password" { + t.Error("probe did not submit the intended invalid credentials") + } + if tc.redirect { + w.Header().Set("Location", callback+"?code=unexpected-code") + } + w.WriteHeader(tc.status) + if tc.errorBox { + _, _ = w.Write([]byte(`
Invalid credentials.
`)) + } + default: + w.WriteHeader(http.StatusNotFound) + } + })) + defer server.Close() + code, err := login(server.URL+"/dex", "wrong-password", strings.Repeat("v", 43), "nonce", false) + if code != "" || (err == nil) != tc.wantOK { + t.Fatalf("invalid-password result: code present=%v, error=%v, want success=%v", code != "", err, tc.wantOK) + } + }) + } +} + func continuityToken(t *testing.T, key *rsa.PrivateKey, issuer, kid, nonce string, expires time.Time) string { t.Helper() header, err := json.Marshal(map[string]string{"alg": "RS256", "kid": kid}) From 0f47f368e2b436263d419a51187bffeceb560742 Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 22:12:20 +0200 Subject: [PATCH 11/13] fix(idp): patch NTLM dependency and prove runtime package scope Promote the verified single-module Go resolver update to go-ntlmssp v0.1.1, require its overflow regression, and retain the actual compiled package inventory with a fatal OpenPGP import guard. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- bridge/idp/Dockerfile | 5 +- bridge/idp/NOTICE | 8 ++ bridge/idp/README.md | 97 ++++++++++++++++++- bridge/idp/locks/generated/SHA256SUMS | 12 +-- bridge/idp/locks/generated/dependencies.patch | 17 +++- bridge/idp/locks/generated/go.mod | 2 +- bridge/idp/locks/generated/go.sum | 4 +- bridge/idp/locks/generated/graph.txt | 3 +- bridge/idp/locks/generated/modules.json | 15 +-- bridge/idp/locks/generated/requests.txt | 1 + bridge/idp/locks/requests.txt | 1 + bridge/idp/scripts/build.sh | 4 +- bridge/idp/scripts/import-locks.py | 26 +++-- bridge/idp/scripts/notices.go | 49 +++++++--- bridge/idp/scripts/notices_test.go | 55 +++++++++++ bridge/idp/scripts/upstream-tests.sh | 8 ++ bridge/idp/tests/test_baselines.py | 15 +-- bridge/idp/tests/test_ntlm_update.py | 83 ++++++++++++++++ .../2026-09-16-curated-dex-runtime.md | 26 +++++ 19 files changed, 378 insertions(+), 53 deletions(-) create mode 100644 bridge/idp/scripts/notices_test.go create mode 100644 bridge/idp/tests/test_ntlm_update.py diff --git a/bridge/idp/Dockerfile b/bridge/idp/Dockerfile index 140fd60d..c6a91f0c 100644 --- a/bridge/idp/Dockerfile +++ b/bridge/idp/Dockerfile @@ -27,9 +27,10 @@ RUN sh /packaging/scripts/verify-locks.sh \ FROM dependencies AS build COPY scripts/build.sh /packaging/scripts/build.sh -COPY scripts/notices.go /packaging/scripts/notices.go +COPY scripts/notices.go scripts/notices_test.go /packaging/scripts/ COPY NOTICE LICENSE README.md /packaging/ -RUN sh /packaging/scripts/build.sh +RUN go test -count=1 /packaging/scripts/notices.go /packaging/scripts/notices_test.go \ + && sh /packaging/scripts/build.sh FROM build AS compatibility-tests RUN go test -race -count=1 -v \ diff --git a/bridge/idp/NOTICE b/bridge/idp/NOTICE index 692d598e..412b6090 100644 --- a/bridge/idp/NOTICE +++ b/bridge/idp/NOTICE @@ -37,6 +37,14 @@ go.sum retain their normal filenames and full dependency/security scanning. Linked dependency license and notice files are distributed in /usr/share/doc/dex/third-party. +The requested dependency graph now includes github.com/Azure/go-ntlmssp +v0.1.1 for CVE-2026-32952; the updated graph must be generated and verified +before a new image can be accepted. No other toolchain/base/crypto pin is +changed for this correction. The build retains the actual compiled-package +inventory as /usr/share/doc/dex/runtime-packages.json and fails if +golang.org/x/crypto/openpgp or a subpackage is linked (GO-2026-5932). +This does not suppress scanning of golang.org/x/crypto or any runtime module. + The official image's gomplate and docker-entrypoint programs are intentionally not distributed. The supported invocation is /usr/local/bin/dex serve with an explicit configuration file, not upstream entrypoint template expansion. diff --git a/bridge/idp/README.md b/bridge/idp/README.md index bc600210..e34109d3 100644 --- a/bridge/idp/README.md +++ b/bridge/idp/README.md @@ -3,9 +3,13 @@ Licensed under the MIT License. --> # Kars Dex security rebuild -**Status: hosted build/test stages passed; final runtime qualification pending.** -Real Go-generated active locks under `locks/generated/` remain byte-for-byte -unchanged; historical baselines use the path-only snapshot layout described below. +**Status: NTLM security update pending hosted Go locks and full requalification.** +The exact request now includes `github.com/Azure/go-ntlmssp@v0.1.1` for +CVE-2026-32952. Existing previously qualified files under `locks/generated/` +remain byte-for-byte unchanged until a new hosted artifact is verified. +Consequently, their old request stamp does not satisfy the new request: +normal image/qualification builds must fail closed until reviewed new locks +are installed. No module checksums were edited by hand. The successful hosted attempt on September 16, 2026 compiled Dex with CGO, completed license collection, passed the compatibility cases, completed the upstream root/API race-suite commands with exit code zero, passed all nine @@ -13,7 +17,13 @@ signing-key-continuity regression subcases under the race detector, and compiled the probe. Environment-dependent suite skips do not establish external connector runtime coverage. -The required `idp` job in public Bridge CI now builds these checked-in inputs +That earlier result applies only to the old dependency graph. Its binary +digest `c4b5f8017cffb5e9853788a66cc1a1ce21104b9e4b4ba04901947d7510d5e4f9` +and publication payload expectations must **not** be reused for a rebuilt +NTLM-fixed image. Frozen operations artifacts remain unsubmitted and require +a new approved reference after fresh qualification. + +The required `idp` job in public Bridge CI builds the checked-in inputs and executes the actual final distroless memory/SQLite/OIDC, linkage, inventory and scan gates. That CI execution is still required; the earlier build/test success is **not** final-image qualification or permission to deploy. This @@ -54,6 +64,7 @@ the Docker build uses the pinned official builder, not an unchecked download. | Module | Upstream | Requested selection | Authoritative fix / dependency reason | | --- | --- | --- | --- | +| `github.com/Azure/go-ntlmssp` | `v0.0.0-20221128193559-754e69321358` | 0.1.1 | [CVE-2026-32952 / GHSA-pjcq-xvwq-hhpj](https://github.com/advisories/GHSA-pjcq-xvwq-hhpj): malformed NTLM challenges can panic before 0.1.1 | | `github.com/go-jose/go-jose/v4` | 4.1.3 | 4.1.4 | [GO-2026-4945](https://vuln.go.dev/ID/GO-2026-4945.json) | | `github.com/russellhaering/goxmldsig` | 1.5.0 | 1.6.0 | [GO-2026-4753](https://vuln.go.dev/ID/GO-2026-4753.json) | | `go.opentelemetry.io/otel`, `/metric`, `/trace` | 1.39.0 | 1.44.0 | [GO-2026-5506](https://vuln.go.dev/ID/GO-2026-5506.json) fixes 1.41; [GO-2026-5158](https://vuln.go.dev/ID/GO-2026-5158.json) and gRPC require 1.44 | @@ -86,6 +97,38 @@ depend on them. Their pinned source/compiler stage is checked for consistency. An unexpectedly higher MVS selection fails validation and needs review, not a forced downgrade or a scanner waiver. +### NTLM update and package-scoped OpenPGP evidence + +The exact NTLM release is +[`bd8579c18d41bf5d91a5f74b1117c958f635b866`](https://github.com/Azure/go-ntlmssp/tree/bd8579c18d41bf5d91a5f74b1117c958f635b866). +Its [module metadata](https://proxy.golang.org/github.com/!azure/go-ntlmssp/@v/v0.1.1.mod) +requires Go 1.24 and declares no module dependencies, compatible with the +unchanged Go 1.26.8 builder. The hosted upstream-tests stage requires the +actual `TestNewAuthenticateMessage_ChallengeTargetInfoOffsetOverflowNoPanics` +regression to be registered, then runs `go test -json -count=1 -race +github.com/Azure/go-ntlmssp/...`. The actual JSON is retained as +`/out/doc/ntlm-tests.json` in the test image and printed into the existing +upstream build log. Standard IIS E2E cases retain their upstream +environment-dependent skips; no IIS credentials or new provider prerequisite +is introduced. + +[GO-2026-5932](https://vuln.go.dev/ID/GO-2026-5932.json) concerns +`golang.org/x/crypto/openpgp` and its subpackages, not every package in +`golang.org/x/crypto`. The crypto pin remains **v0.56.0**, with no module +suppression, exclusion or waiver. + +Each build now retains the actual +`go list -deps -json=ImportPath,Module ./cmd/dex` result as +`/usr/share/doc/dex/runtime-packages.json`. It records runtime package paths +and their selected modules without test-only or tool-only packages. The +build-time notice collector rejects an empty/wrong-target inventory and +fatally rejects `golang.org/x/crypto/openpgp` or any descendant import path +before completing the image. Other crypto packages remain allowed and +scanned. The same inventory supplies license collection; existing `LICENCE` +handling is preserved. This is package-inclusion evidence and a future +introduction guard, **not** a scanner filter or proof that a pending build +has already passed. + ## Disclosed source compatibility patches The original upstream commit and archive SHA-256 have **not** changed. @@ -226,6 +269,10 @@ The following task uses an operator-approved ACR's compute but **does not push an image**, deploy, or touch cluster state. The context is this public-only directory, not private repository config. +For the current NTLM change, use the concrete staged-review procedure below; +do not remove or overwrite the currently qualified generated locks merely +to make the default importer run. + From the public Kars worktree root, set `SUBSCRIPTION_ID`, `ACR_NAME` and `ARTIFACT_DIR` to approved operator values. Keep the artifact directory private. @@ -296,6 +343,48 @@ option for this independent replay; do not assume the quick-build CLI exposes that option. Neither replay nor generation is reachable from the normal `Dockerfile`. +### Parent-only no-push NTLM lock-generation and review + +Set `SUBSCRIPTION_ID`, `ACR_NAME` and an existing `ARTIFACT_DIR` **outside the +source checkout** to approved operator values. The task below only resolves +the exact requested Go graph on the pinned worker image; it does not build or +push a Dex image. Only the parent submits it. + +```sh +( + cd bridge/idp + az acr build \ + --subscription "$SUBSCRIPTION_ID" --registry "$ACR_NAME" \ + --platform linux/amd64 --no-push --timeout 3600 \ + --target lock-generation --file Dockerfile.locks . +) > "$ARTIFACT_DIR/ntlm-lock-generation.log" 2>&1 + +PYTHONDONTWRITEBYTECODE=1 python3 bridge/idp/scripts/import-locks.py \ + "$ARTIFACT_DIR/ntlm-lock-generation.log" \ + --output "$ARTIFACT_DIR/ntlm-reviewed-locks" +``` + +`--output` validates the complete archive, current request stamp and exact +selected versions in a temporary sibling, then creates a new review +directory. It refuses any existing output and any alternate location inside +the source checkout. Failed/stale artifacts leave both the proposed output +and existing qualified locks untouched. + +Before promotion, review the generated root/API manifests, sums, module +inventories, graph and `dependencies.patch`. Confirm NTLM is exactly v0.1.1, +the crypto/toolchain/base/source pins are unchanged, and original `.snapshot` +baselines still match their pinned upstream bytes. Keep the old artifact and +raw generation logs outside the repository as historical provenance. Only +after that review may the parent replace `locks/generated/` with the verified +new artifact; this source change does not perform that replacement. + +Then rerun source contracts, the hosted notice-guard Go tests, NTLM package +regressions, compatibility/root/API/probe race suites, the full actual +distroless runtime qualifier and fresh scans. Require zero HIGH/CRITICAL +findings **and** confirmed resolution of the current NTLM advisory. Retain +the new package inventory and establish a new binary/payload reference. +The prior green checks and old binary hash do not qualify this update. + ## Required Bridge CI qualification [Bridge CI](../../.github/workflows/bridge-ci.yml) adds **Dex IdP runtime diff --git a/bridge/idp/locks/generated/SHA256SUMS b/bridge/idp/locks/generated/SHA256SUMS index 52a96419..5efc481b 100644 --- a/bridge/idp/locks/generated/SHA256SUMS +++ b/bridge/idp/locks/generated/SHA256SUMS @@ -1,13 +1,13 @@ 4a7bed6907c8f8918791e69539597405d6ad18f3f386788a81ed28f024113ac8 ./api-modules.json e304bf72c1bf687cf777af1ca1c70d96e928a86bfb40bc6d5aeb8239baac24f6 ./api/v2/go.mod 3410f76108a083dc3a603327c354639a078ee8d917146aa7bf769e37cce0f208 ./api/v2/go.sum -7aab541b65a7246f95a919912582d909a8cfc09e9348a10e34afac1773c29644 ./dependencies.patch -34b7b1e48a6020a855741fc497f0782f226fa75a701cf925c52ccdd322d38046 ./go.mod -6e47d5b5c5cd6ff030ffe276d8707e41c67e88321a6bc81248f61c58271ec59b ./go.sum -e65265ab047188c71f6c5369a5be77d8cbbbefe26e307eb505775050ebece449 ./graph.txt +dd23e549cea30d69b362925e0253d6da392ba9cc0eb507816885c431aa7fb307 ./dependencies.patch +62b200f67cd9692cdd5bb7f568adeb5a3c8997bd004f835df519eeb466cb2b07 ./go.mod +c7ff038490b371cae3f016e749214f05366638234e705c7e13f527cb25710f64 ./go.sum +c0f24094a89a13e270701ce531bf3b4d4225d70da78243915a2c772fcb470c25 ./graph.txt d5a430f8c8fea443ebc134cff29ddc0914bdc7acc1220fce9073c439e1a780d6 ./inputs.lock -2381158f636af5715561fca4208f4d89ca22a0e9c393bd53daa984a644ce5b72 ./modules.json -23d3448085a87cb3d242e196bb8ad7b571b63392c90871c2f5b26b1c5f0b6575 ./requests.txt +db04d9e4cbbd669a29040abfe5f04e9f8c3b08bc6e9e68e6c2cbc473ca632216 ./modules.json +e5fe468d767406cd3cfcbd6f3063240e1e51bba644f3c0ae75f657a319083008 ./requests.txt 7e35a947feee25f89c2649aa041942db786be35c3d6c484ab2ba2da849e3dc00 ./toolchain.txt 181fc42a509297fe685e3470388d378a229e6efd36dd874eef809b6e06fe41e8 ./upstream/api/v2/go.mod.snapshot ccf35830330ac8058a4f009babbb417039aec728cf92625572abc53474c5dfca ./upstream/api/v2/go.sum.snapshot diff --git a/bridge/idp/locks/generated/dependencies.patch b/bridge/idp/locks/generated/dependencies.patch index dd999d1e..477605ce 100644 --- a/bridge/idp/locks/generated/dependencies.patch +++ b/bridge/idp/locks/generated/dependencies.patch @@ -19,7 +19,7 @@ github.com/go-ldap/ldap/v3 v3.4.12 github.com/go-sql-driver/mysql v1.9.3 github.com/google/uuid v1.6.0 -@@ -28,23 +30,23 @@ +@@ -28,27 +30,27 @@ github.com/openbao/openbao/api/v2 v2.5.1 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.23.2 @@ -49,6 +49,11 @@ cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect dario.cat/mergo v1.0.1 // indirect filippo.io/edwards25519 v1.1.1 // indirect +- github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect ++ github.com/Azure/go-ntlmssp v0.1.1 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/agext/levenshtein v1.2.3 // indirect @@ -105,21 +107,21 @@ go.etcd.io/etcd/api/v3 v3.6.8 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect @@ -101,8 +106,14 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= entgo.io/ent v0.14.5 h1:Rj2WOYJtCkWyFo6a+5wB3EfBRP0rnx1fMk6gGA0UUe4= -@@ -18,6 +22,7 @@ - github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +@@ -14,10 +18,11 @@ + filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= + github.com/AppsFlyer/go-sundheit v0.6.0 h1:d2hBvCjBSb2lUsEWGfPigr4MCOt04sxB+Rppl0yUMSk= + github.com/AppsFlyer/go-sundheit v0.6.0/go.mod h1:LDdBHD6tQBtmHsdW+i1GwdTt6Wqc0qazf5ZEJVTbTME= +-github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= +-github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= ++github.com/Azure/go-ntlmssp v0.1.1 h1:l+FM/EEMb0U9QZE7mKNEDw5Mu3mFiaa2GKOoTSsNDPw= ++github.com/Azure/go-ntlmssp v0.1.1/go.mod h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM= diff --git a/bridge/idp/locks/generated/go.mod b/bridge/idp/locks/generated/go.mod index b4b1cfa8..6de46909 100644 --- a/bridge/idp/locks/generated/go.mod +++ b/bridge/idp/locks/generated/go.mod @@ -50,7 +50,7 @@ require ( cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect dario.cat/mergo v1.0.1 // indirect filippo.io/edwards25519 v1.1.1 // indirect - github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect + github.com/Azure/go-ntlmssp v0.1.1 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.3.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect diff --git a/bridge/idp/locks/generated/go.sum b/bridge/idp/locks/generated/go.sum index 2235eedb..cd39f32d 100644 --- a/bridge/idp/locks/generated/go.sum +++ b/bridge/idp/locks/generated/go.sum @@ -18,8 +18,8 @@ filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw= filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AppsFlyer/go-sundheit v0.6.0 h1:d2hBvCjBSb2lUsEWGfPigr4MCOt04sxB+Rppl0yUMSk= github.com/AppsFlyer/go-sundheit v0.6.0/go.mod h1:LDdBHD6tQBtmHsdW+i1GwdTt6Wqc0qazf5ZEJVTbTME= -github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= -github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/Azure/go-ntlmssp v0.1.1 h1:l+FM/EEMb0U9QZE7mKNEDw5Mu3mFiaa2GKOoTSsNDPw= +github.com/Azure/go-ntlmssp v0.1.1/go.mod h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.33.0/go.mod h1:pJTkW8hEUIIi3Pf65lPZOnn4Y81yCllX6IWk2jNXdkM= diff --git a/bridge/idp/locks/generated/graph.txt b/bridge/idp/locks/generated/graph.txt index ab0e13ba..21affc67 100644 --- a/bridge/idp/locks/generated/graph.txt +++ b/bridge/idp/locks/generated/graph.txt @@ -6,7 +6,7 @@ github.com/dexidp/dex dario.cat/mergo@v1.0.1 github.com/dexidp/dex entgo.io/ent@v0.14.5 github.com/dexidp/dex filippo.io/edwards25519@v1.1.1 github.com/dexidp/dex github.com/AppsFlyer/go-sundheit@v0.6.0 -github.com/dexidp/dex github.com/Azure/go-ntlmssp@v0.0.0-20221128193559-754e69321358 +github.com/dexidp/dex github.com/Azure/go-ntlmssp@v0.1.1 github.com/dexidp/dex github.com/Masterminds/goutils@v1.1.1 github.com/dexidp/dex github.com/Masterminds/semver@v1.5.0 github.com/dexidp/dex github.com/Masterminds/semver/v3@v3.3.0 @@ -226,6 +226,7 @@ github.com/AppsFlyer/go-sundheit@v0.6.0 github.com/pkg/errors@v0.8.1 github.com/AppsFlyer/go-sundheit@v0.6.0 github.com/stretchr/objx@v0.2.0 github.com/AppsFlyer/go-sundheit@v0.6.0 github.com/stretchr/testify@v1.6.1 github.com/AppsFlyer/go-sundheit@v0.6.0 gopkg.in/check.v1@v1.0.0-20190902080502-41f04d3bba15 +github.com/Azure/go-ntlmssp@v0.1.1 go@1.24 github.com/Masterminds/semver/v3@v3.3.0 go@1.21 github.com/Masterminds/sprig/v3@v3.3.0 dario.cat/mergo@v1.0.1 github.com/Masterminds/sprig/v3@v3.3.0 github.com/Masterminds/goutils@v1.1.1 diff --git a/bridge/idp/locks/generated/modules.json b/bridge/idp/locks/generated/modules.json index b6c5638f..07dbc55e 100644 --- a/bridge/idp/locks/generated/modules.json +++ b/bridge/idp/locks/generated/modules.json @@ -124,13 +124,14 @@ } { "Path": "github.com/Azure/go-ntlmssp", - "Version": "v0.0.0-20221128193559-754e69321358", - "Time": "2022-11-28T19:35:59Z", - "Indirect": true, - "Dir": "/work/mod/github.com/!azure/go-ntlmssp@v0.0.0-20221128193559-754e69321358", - "GoMod": "/work/mod/cache/download/github.com/!azure/go-ntlmssp/@v/v0.0.0-20221128193559-754e69321358.mod", - "Sum": "h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=", - "GoModSum": "h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=" + "Version": "v0.1.1", + "Time": "2026-04-23T07:51:54Z", + "Indirect": true, + "Dir": "/work/mod/github.com/!azure/go-ntlmssp@v0.1.1", + "GoMod": "/work/mod/cache/download/github.com/!azure/go-ntlmssp/@v/v0.1.1.mod", + "GoVersion": "1.24", + "Sum": "h1:l+FM/EEMb0U9QZE7mKNEDw5Mu3mFiaa2GKOoTSsNDPw=", + "GoModSum": "h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk=" } { "Path": "github.com/DATA-DOG/go-sqlmock", diff --git a/bridge/idp/locks/generated/requests.txt b/bridge/idp/locks/generated/requests.txt index 6fc4313b..923f3afd 100644 --- a/bridge/idp/locks/generated/requests.txt +++ b/bridge/idp/locks/generated/requests.txt @@ -1,3 +1,4 @@ +github.com/Azure/go-ntlmssp@v0.1.1 github.com/go-jose/go-jose/v4@v4.1.4 github.com/russellhaering/goxmldsig@v1.6.0 go.opentelemetry.io/otel@v1.44.0 diff --git a/bridge/idp/locks/requests.txt b/bridge/idp/locks/requests.txt index 6fc4313b..923f3afd 100644 --- a/bridge/idp/locks/requests.txt +++ b/bridge/idp/locks/requests.txt @@ -1,3 +1,4 @@ +github.com/Azure/go-ntlmssp@v0.1.1 github.com/go-jose/go-jose/v4@v4.1.4 github.com/russellhaering/goxmldsig@v1.6.0 go.opentelemetry.io/otel@v1.44.0 diff --git a/bridge/idp/scripts/build.sh b/bridge/idp/scripts/build.sh index 8fd87185..74454555 100644 --- a/bridge/idp/scripts/build.sh +++ b/bridge/idp/scripts/build.sh @@ -23,8 +23,8 @@ cp /packaging/README.md /out/doc/PACKAGING-README.md cp -R /locks /out/doc/locks cp -R /packaging/patches /out/doc/source-patches cp /packaging/source.upstream.sha256 /packaging/source.sha256 /out/doc/ -go list -deps -json ./cmd/dex > /tmp/dex-packages.json -go run /packaging/scripts/notices.go /tmp/dex-packages.json /out/doc/third-party +go list -deps -json=ImportPath,Module ./cmd/dex > /out/doc/runtime-packages.json +go run /packaging/scripts/notices.go /out/doc/runtime-packages.json /out/doc/third-party sha256sum --check --strict /packaging/source.sha256 > /dev/null cmp go.mod /locks/go.mod cmp go.sum /locks/go.sum diff --git a/bridge/idp/scripts/import-locks.py b/bridge/idp/scripts/import-locks.py index bd4848af..ef054255 100644 --- a/bridge/idp/scripts/import-locks.py +++ b/bridge/idp/scripts/import-locks.py @@ -4,6 +4,7 @@ """Import active Go locks and archival .snapshot baselines from a no-push build log.""" +import argparse import base64 import gzip import hashlib @@ -58,12 +59,16 @@ def decode_artifact(log): return result -def main(): - require(len(sys.argv) == 2, "usage: import-locks.py raw-acr-build.log") - target = ROOT / "locks/generated" - require(not target.exists(), "generated locks already exist; review them rather than overwriting") - files = decode_artifact(Path(sys.argv[1]).read_text()) - with tempfile.TemporaryDirectory(prefix=".dex-lock-import-", dir=ROOT / "locks") as temporary: +def import_artifact(log, target): + target = Path(target).resolve() + default = ROOT / "locks/generated" + checkout = next((path for path in (ROOT, *ROOT.parents) if (path / ".git").exists()), ROOT) + require(target == default or not target.is_relative_to(checkout), + "alternate lock-review output must be outside the source checkout") + require(not target.exists(), "lock output already exists; review it rather than overwriting") + require(target.parent.is_dir(), "lock-review output parent directory must already exist") + files = decode_artifact(Path(log).read_text()) + with tempfile.TemporaryDirectory(prefix=".dex-lock-import-", dir=target.parent) as temporary: stage = Path(temporary) generated = stage / "locks/generated" generated.mkdir(parents=True) @@ -75,6 +80,15 @@ def main(): shutil.copyfile(ROOT / "locks" / name, stage / "locks" / name) check_modules(stage) generated.rename(target) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("log", type=Path) + parser.add_argument("--output", type=Path, default=ROOT / "locks/generated", + help="New review directory outside the checkout; existing qualified locks are never overwritten") + args = parser.parse_args() + import_artifact(args.log, args.output) print("Imported active Go locks and archival .snapshot baselines. Review dependencies.patch and all selected modules before building.") diff --git a/bridge/idp/scripts/notices.go b/bridge/idp/scripts/notices.go index b3ff23f5..b1337b8a 100644 --- a/bridge/idp/scripts/notices.go +++ b/bridge/idp/scripts/notices.go @@ -22,26 +22,32 @@ type module struct { Replace *module } -func run() error { - if len(os.Args) != 3 { - return fmt.Errorf("usage: notices packages.json output-directory") - } - f, err := os.Open(os.Args[1]) - if err != nil { - return err - } - defer f.Close() - decoder := json.NewDecoder(f) +func runtimeModules(input io.Reader) (map[string]module, error) { + decoder := json.NewDecoder(input) modules := map[string]module{ "golang.org/toolchain@" + runtime.Version(): {Dir: runtime.GOROOT()}, } + foundDex := false for { - var pkg struct{ Module *module } + var pkg struct { + ImportPath string + Module *module + } if err := decoder.Decode(&pkg); err != nil { if err == io.EOF { break } - return err + return nil, err + } + if pkg.ImportPath == "" { + return nil, fmt.Errorf("runtime package inventory contains a missing import path") + } + if pkg.ImportPath == "golang.org/x/crypto/openpgp" || + strings.HasPrefix(pkg.ImportPath, "golang.org/x/crypto/openpgp/") { + return nil, fmt.Errorf("forbidden compiled runtime package: %s (GO-2026-5932)", pkg.ImportPath) + } + if pkg.ImportPath == "github.com/dexidp/dex/cmd/dex" { + foundDex = true } if pkg.Module == nil || pkg.Module.Main { continue @@ -52,6 +58,25 @@ func run() error { } modules[m.Path+"@"+m.Version] = m } + if !foundDex { + return nil, fmt.Errorf("runtime package inventory does not include the Dex command") + } + return modules, nil +} + +func run() error { + if len(os.Args) != 3 { + return fmt.Errorf("usage: notices packages.json output-directory") + } + f, err := os.Open(os.Args[1]) + if err != nil { + return err + } + defer f.Close() + modules, err := runtimeModules(f) + if err != nil { + return err + } keys := make([]string, 0, len(modules)) for key := range modules { keys = append(keys, key) diff --git a/bridge/idp/scripts/notices_test.go b/bridge/idp/scripts/notices_test.go new file mode 100644 index 00000000..2f83351b --- /dev/null +++ b/bridge/idp/scripts/notices_test.go @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package main + +import ( + "encoding/json" + "strings" + "testing" +) + +func packageInventory(paths ...string) string { + var inventory strings.Builder + encoder := json.NewEncoder(&inventory) + for _, path := range paths { + if err := encoder.Encode(map[string]string{"ImportPath": path}); err != nil { + panic(err) + } + } + return inventory.String() +} + +func TestRuntimeModulesRejectsOpenPGPAndEverySubpackage(t *testing.T) { + for _, suffix := range []string{"", "/packet", "/armor", "/clearsign", "/errors", "/elgamal", "/s2k", "/future/nested"} { + t.Run(suffix, func(t *testing.T) { + path := "golang.org/x/crypto/openpgp" + suffix + _, err := runtimeModules(strings.NewReader(packageInventory("github.com/dexidp/dex/cmd/dex", path))) + if err == nil || !strings.Contains(err.Error(), "forbidden compiled runtime package: "+path) { + t.Fatalf("expected fatal OpenPGP package rejection, got %v", err) + } + }) + } +} + +func TestRuntimeModulesKeepsOtherCryptoAndModuleEvidence(t *testing.T) { + inventory := packageInventory( + "crypto/rsa", "github.com/dexidp/dex/cmd/dex", "golang.org/x/crypto/bcrypt", + "golang.org/x/crypto/openpgpcompat", "github.com/ProtonMail/go-crypto/openpgp", + ) + `{"ImportPath":"github.com/Azure/go-ntlmssp","Module":{"Path":"github.com/Azure/go-ntlmssp","Version":"v0.1.1","Dir":"/verified/module"}}` + modules, err := runtimeModules(strings.NewReader(inventory)) + if err != nil { + t.Fatal(err) + } + if modules["github.com/Azure/go-ntlmssp@v0.1.1"].Dir != "/verified/module" { + t.Fatal("actual selected module evidence was not retained") + } +} + +func TestRuntimeModulesRejectsEmptyMalformedOrWrongTargetInventory(t *testing.T) { + for _, input := range []string{"", "{", "{}", "null", packageInventory("golang.org/x/crypto/bcrypt")} { + if _, err := runtimeModules(strings.NewReader(input)); err == nil { + t.Fatalf("invalid runtime inventory accepted: %q", input) + } + } +} diff --git a/bridge/idp/scripts/upstream-tests.sh b/bridge/idp/scripts/upstream-tests.sh index e2e6f4ee..500234af 100644 --- a/bridge/idp/scripts/upstream-tests.sh +++ b/bridge/idp/scripts/upstream-tests.sh @@ -3,6 +3,14 @@ # Licensed under the MIT License. set -eu +go test -list '^TestNewAuthenticateMessage_ChallengeTargetInfoOffsetOverflowNoPanics$' \ + github.com/Azure/go-ntlmssp > /out/doc/ntlm-test-list.txt +grep -Fx 'TestNewAuthenticateMessage_ChallengeTargetInfoOffsetOverflowNoPanics' /out/doc/ntlm-test-list.txt +if ! go test -json -count=1 -race github.com/Azure/go-ntlmssp/... > /out/doc/ntlm-tests.json; then + cat /out/doc/ntlm-tests.json + exit 1 +fi +cat /out/doc/ntlm-tests.json if ! go test -json -count=1 -race ./... > /out/doc/upstream-tests.json; then cat /out/doc/upstream-tests.json exit 1 diff --git a/bridge/idp/tests/test_baselines.py b/bridge/idp/tests/test_baselines.py index da48fbfd..2e2a81a2 100644 --- a/bridge/idp/tests/test_baselines.py +++ b/bridge/idp/tests/test_baselines.py @@ -9,7 +9,7 @@ import tarfile import unittest -from contracts import ACTIVE_LOCK_FILES, BASELINE_SNAPSHOTS, LOCK_FILES, check_modules +from contracts import ACTIVE_LOCK_FILES, BASELINE_SNAPSHOTS, LOCK_FILES ROOT = Path(__file__).resolve().parents[1] GENERATED = ROOT / "locks/generated" @@ -52,15 +52,16 @@ def artifact_log(files): class BaselineRepresentationContracts(unittest.TestCase): - def test_migration_preserves_every_artifact_digest_and_only_changes_manifest_paths(self): - expected_manifest = [] + def test_archival_baselines_remain_immutable_across_reviewed_dependency_updates(self): + current_manifest = dict(line.split(" ", 1)[::-1] + for line in (GENERATED / "SHA256SUMS").read_text().splitlines()) for line in CHHP_MANIFEST.splitlines(): digest, original = line.split(" ", 1) - renamed = original + ".snapshot" if original.startswith("./upstream/") else original + if not original.startswith("./upstream/"): + continue + renamed = original + ".snapshot" self.assertEqual(hashlib.sha256((GENERATED / renamed).read_bytes()).hexdigest(), digest, renamed) - expected_manifest.append(f"{digest} {renamed}\n") - self.assertEqual((GENERATED / "SHA256SUMS").read_bytes(), "".join(expected_manifest).encode()) - check_modules(ROOT) + self.assertEqual(current_manifest[renamed], digest) def test_only_active_go_locks_keep_recognized_manifest_filenames(self): expected_active = {"go.mod", "go.sum", "api/v2/go.mod", "api/v2/go.sum"} diff --git a/bridge/idp/tests/test_ntlm_update.py b/bridge/idp/tests/test_ntlm_update.py new file mode 100644 index 00000000..c68a7cf4 --- /dev/null +++ b/bridge/idp/tests/test_ntlm_update.py @@ -0,0 +1,83 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import hashlib +from pathlib import Path +import tempfile +import unittest + +from contracts import LOCK_FILES +from test_baselines import artifact_log, import_locks + +ROOT = Path(__file__).resolve().parents[1] +NTLM_REQUEST = "github.com/Azure/go-ntlmssp@v0.1.1" + + +class NTLMSecurityUpdateContracts(unittest.TestCase): + def test_exact_ntlm_update_does_not_change_crypto_or_other_pins(self): + requested = (ROOT / "locks/requests.txt").read_text().splitlines() + self.assertEqual(requested.count(NTLM_REQUEST), 1) + self.assertIn("golang.org/x/crypto@v0.56.0", requested) + self.assertIn("GO_VERSION=go1.26.8", (ROOT / "locks/inputs.lock").read_text()) + self.assertEqual(len(requested), len(set(requested))) + + def test_runtime_inventory_is_retained_and_checked_without_filtering_packages(self): + build = (ROOT / "scripts/build.sh").read_text() + self.assertIn("go list -deps -json=ImportPath,Module ./cmd/dex > /out/doc/runtime-packages.json", build) + self.assertIn("go run /packaging/scripts/notices.go /out/doc/runtime-packages.json /out/doc/third-party", build) + notice = (ROOT / "scripts/notices.go").read_text() + self.assertIn('pkg.ImportPath == "golang.org/x/crypto/openpgp"', notice) + self.assertIn('strings.HasPrefix(pkg.ImportPath, "golang.org/x/crypto/openpgp/")', notice) + self.assertIn('forbidden compiled runtime package: %s (GO-2026-5932)', notice) + self.assertIn('runtime package inventory does not include the Dex command', notice) + self.assertEqual(notice.count('strings.HasPrefix(name, "LICENCE")'), 2) + dockerfile = (ROOT / "Dockerfile").read_text() + self.assertIn("go test -count=1 /packaging/scripts/notices.go /packaging/scripts/notices_test.go", dockerfile) + self.assertIn("COPY --from=build /out/doc/ /usr/share/doc/dex/", dockerfile) + + def test_real_upstream_ntlm_overflow_regression_and_package_suite_are_required(self): + script = (ROOT / "scripts/upstream-tests.sh").read_text() + test = "TestNewAuthenticateMessage_ChallengeTargetInfoOffsetOverflowNoPanics" + self.assertIn(f"go test -list '^{test}$'", script) + self.assertIn(f"grep -Fx '{test}' /out/doc/ntlm-test-list.txt", script) + self.assertIn("go test -json -count=1 -race github.com/Azure/go-ntlmssp/...", script) + self.assertIn("cat /out/doc/ntlm-tests.json", script) + self.assertIn("go test -json -count=1 -race ./...", script) + self.assertNotIn("-vet=off", script) + + def test_review_import_never_overwrites_an_existing_output(self): + with tempfile.TemporaryDirectory(prefix="kars-ntlm-review-contract-") as temporary: + target = Path(temporary) / "reviewed" + target.mkdir() + marker = target / "keep" + marker.write_bytes(b"existing reviewed evidence") + with self.assertRaisesRegex(ValueError, "already exists"): + import_locks.import_artifact(Path(temporary) / "unused.log", target) + self.assertEqual(marker.read_bytes(), b"existing reviewed evidence") + + def test_review_import_rejects_stale_artifacts_without_touching_qualified_locks(self): + generated = ROOT / "locks/generated" + before = {name: hashlib.sha256((generated / name).read_bytes()).hexdigest() for name in LOCK_FILES} + files = {name: (generated / name).read_bytes() for name in LOCK_FILES} + files["requests.txt"] = "\n".join( + line for line in files["requests.txt"].decode().splitlines() if line != NTLM_REQUEST + ).encode() + b"\n" + with tempfile.TemporaryDirectory(prefix="kars-ntlm-staging-contract-") as temporary: + directory = Path(temporary) + log = directory / "stale.log" + log.write_text(artifact_log(files)) + target = directory / "reviewed" + with self.assertRaisesRegex(ValueError, "resolver input drift: requests.txt"): + import_locks.import_artifact(log, target) + self.assertFalse(target.exists()) + self.assertEqual(sorted(path.name for path in directory.iterdir()), ["stale.log"]) + after = {name: hashlib.sha256((generated / name).read_bytes()).hexdigest() for name in LOCK_FILES} + self.assertEqual(after, before) + + def test_alternate_review_output_cannot_create_more_active_manifests_in_checkout(self): + with self.assertRaisesRegex(ValueError, "outside the source checkout"): + import_locks.import_artifact("unused.log", ROOT / "locks/proposed-ntlm") + + +if __name__ == "__main__": + unittest.main() diff --git a/docs/security-audits/2026-09-16-curated-dex-runtime.md b/docs/security-audits/2026-09-16-curated-dex-runtime.md index 14d8a7e1..2ec1dd00 100644 --- a/docs/security-audits/2026-09-16-curated-dex-runtime.md +++ b/docs/security-audits/2026-09-16-curated-dex-runtime.md @@ -98,6 +98,32 @@ No cluster or main-branch mutation is authorized by this record. ## Delegation and verdict +### Subsequent security discussion follow-up + +Candidate `369aa8616a239cfab7b4612f99188e99441596d2` passed the complete +technical checks, including actual final-image OIDC/SQLite, linkage and +High/Critical scans. Guarded merge nevertheless stopped before any write on +two unresolved GHAS conversations. These were not waived because the image +threshold passed. + +CVE-2026-32952 is a real Medium-severity issue in the selected +`github.com/Azure/go-ntlmssp` version. A new hosted Go resolver output selects +v0.1.1. The parent verified that this is the only changed module selection, +with the nested API and archived baseline bytes unchanged; the previous +qualified artifact remains retained separately. Checksums were generated by +Go, not transcribed. The upstream overflow regression and package race suite +must execute on the new candidate. + +GO-2026-5932 concerns the `golang.org/x/crypto/openpgp` package and its +subpackages, not every use of the crypto module. The build now retains its +actual `go list -deps` inventory and rejects those package paths. That guard +must execute and its evidence must be reviewed before resolving the note. +There is no module-wide scanner exception or unsupported fixed-version claim. + +The prior binary/runtime evidence does not qualify this changed dependency +selection. Fresh source review and all current-head build/runtime/security +requirements remain mandatory; this follow-up does not itself approve merge. + This uses the maintainer's explicit [publication-review delegation](https://github.com/Azure/kars/pull/551#issuecomment-5615522306). The implementation, independent AI review and parent composition are disclosed From fe15c098cac4fcdf86974f3f6c6a37065327934f Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 23:37:35 +0200 Subject: [PATCH 12/13] test(bridge): retain unready observer startup evidence Record bounded process state, fixed current/previous startup markers and exact-router kubelet probe categories after native observer failure. Preserve UID/RV provenance and keep readiness, network intervention and acceptance gates unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- bridge/docs/governed-credentials.md | 15 ++ .../native-credentials/rollout_diagnostics.py | 219 ++++++++++++++++++ bridge/tests/native-credentials/run.py | 6 +- .../test_rollout_diagnostics.py | 202 ++++++++++++++++ 4 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 bridge/tests/native-credentials/rollout_diagnostics.py create mode 100644 bridge/tests/native-credentials/test_rollout_diagnostics.py diff --git a/bridge/docs/governed-credentials.md b/bridge/docs/governed-credentials.md index 55bdc48c..bd8fd156 100644 --- a/bridge/docs/governed-credentials.md +++ b/bridge/docs/governed-credentials.md @@ -272,6 +272,21 @@ are never written to this evidence. Collection cannot qualify any assertion. TLS negatives, 9447/9448 paths, CNI peer denial, and credential rotation remain required unchanged. +`routerRollout` separately captures an unready router's bounded container state, +restart count, previous exit reason/code/signal, fixed startup-log markers and +classified kubelet probe events. It checks the target namespace/Deployment and +ReplicaSet/Pod UID chain, then rechecks all snapshot resource versions and Pod +process state. Old observer versions are reported as comparison booleans, not +accepted as current capability authority. This does not relax the existing +readiness collector or the network experiment's ready-process requirement. +Current and previous process log tails remain separate; failed log/event reads +are explicit without discarding otherwise stable process-state evidence. +Events must reference the exact Pod UID and `spec.containers{inference-router}`; +their coverage is the Pod lifetime, not proof of the current process's failure. +Unknown text, probe URLs/bodies, container IDs and raw errors are not retained. +A logged listener-start intention is not a successful bind or reachability +proof. The original failed result and three dependent blocked cases remain. + An operator template-drift or writer-restoration refusal also records `enrollmentTemplateDrift`. It compares the fixture's pre-preview runtime, controller and BFF Deployment snapshots with the existing CLI review and current objects, using the shipped diff --git a/bridge/tests/native-credentials/rollout_diagnostics.py b/bridge/tests/native-credentials/rollout_diagnostics.py new file mode 100644 index 00000000..e0e5944d --- /dev/null +++ b/bridge/tests/native-credentials/rollout_diagnostics.py @@ -0,0 +1,219 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +"""Read-only failure evidence, including unready routers; never authorizes a probe.""" + +import json +import re +from urllib.parse import urlencode + +from native_api import CORE, command, core, require, resource +from observation_diagnostics import READ_ERRORS, VERSION, identity, owner +from observer_network_diagnostics import complete_inventory + +UNAVAILABLE = "Native rollout diagnostic unavailable" +REASONS = frozenset(""" +Completed Error OOMKilled ContainerCannotRun StartError CrashLoopBackOff +ImagePullBackOff ErrImagePull CreateContainerConfigError CreateContainerError +RunContainerError ContainerCreating PodInitializing +""".split()) +STARTUP = { + ("kars_inference_router", "kars Inference Router starting"): "starting", + ("kars_inference_router", "Registry topology"): "configuration-loaded", + ("kars_inference_router", "Listening on 0.0.0.0:8443"): "listener-planned", + ("kars_inference_router::service_observation_tls", + "Private observation listener stopped"): "observation-listener-stopped", +} + + +def bounded_integer(value, maximum): + require(type(value) is int and 0 <= value <= maximum, UNAVAILABLE) + return value + + +def container_state(value): + require(isinstance(value, dict) and len(value) <= 1, UNAVAILABLE) + if not value: + return {"phase": "absent"} + phase = next(iter(value)) + require(phase in ("running", "waiting", "terminated") + and isinstance(value[phase], dict), UNAVAILABLE) + state = value[phase] + result = {"phase": phase} + if phase != "running": + result["reason"] = state.get("reason") if state.get("reason") in REASONS else "Other" + if phase == "terminated": + result["exitCode"] = bounded_integer(state.get("exitCode"), 255) + if "signal" in state: + result["signal"] = bounded_integer(state["signal"], 64) + return result + + +def startup_records(raw): + require(isinstance(raw, str) and len(raw.encode()) <= 131072, UNAVAILABLE) + records = [] + error_records = 0 + for line in raw.splitlines()[-512:]: + try: + value = json.loads(line) + except (ValueError, TypeError): + continue + if not isinstance(value, dict) or not isinstance(value.get("fields"), dict): + continue + target, message = value.get("target"), value["fields"].get("message") + if not isinstance(target, str) or not isinstance(message, str): + continue + stage = STARTUP.get((target, message)) + if stage and (not records or records[-1] != stage): + records.append(stage) + if (target == "kars_inference_router" or target.startswith("kars_inference_router::")) \ + and value.get("level") == "ERROR": + error_records += 1 + return {"stages": records[-16:], "errorRecords": error_records, + "coverage": "bounded-process-log-tail", + "listenerReachabilityProved": False} + + +def read_logs(namespace, name, previous=False): + try: + raw = command("kubectl", "logs", "-n", namespace, name, "-c", "inference-router", + "--tail=512", "--limit-bytes=131072", "--request-timeout=10s", + *(["--previous"] if previous else []), timeout=15) + return {"available": True, **startup_records(raw)} + except READ_ERRORS: + return {"available": False, "category": "log-read-unavailable"} + + +def event_records(events, namespace, name, pod_uid): + records = [] + for event in complete_inventory(events, 128): + require(isinstance(event, dict), UNAVAILABLE) + ref, source = event.get("involvedObject", {}), event.get("source", {}) + require(isinstance(ref, dict) and isinstance(source, dict), UNAVAILABLE) + if (ref.get("kind") != "Pod" or ref.get("apiVersion") != "v1" + or ref.get("namespace") != namespace or ref.get("name") != name + or ref.get("uid") != pod_uid + or ref.get("fieldPath") != "spec.containers{inference-router}" + or source.get("component") != "kubelet"): + continue + message = event.get("message") + if event.get("reason") != "Unhealthy" or not isinstance(message, str): + continue + match = re.fullmatch(r"(Readiness|Liveness|Startup) probe (failed|errored): ([\s\S]*)", message) + if match is None: + continue + probe, outcome, detail = match.groups() + category = "other" + code = re.fullmatch(r"HTTP probe failed with statuscode: ([1-5][0-9]{2})", detail) + if code: + category = "http-response" + elif "connection refused" in detail: + category = "connection-refused" + elif any(text in detail for text in ( + "context deadline exceeded", "Client.Timeout", "i/o timeout")): + category = "timeout" + record = {"probe": probe.lower(), "outcome": outcome, "category": category, + "httpStatus": int(code[1]) if code else 0} + if record not in records: + records.append(record) + return {"coverage": "pod-lifetime-events-not-current-process", + "records": records[:24]} + + +def collect(setup, target): + result = {"diagnosticOnly": True, "available": False, "category": "target-unavailable"} + anchors = {} + try: + require(isinstance(target, dict) and target.get("workspace") == CORE + and isinstance(target.get("uid"), str) and target["uid"] + and isinstance(target.get("sandbox"), str) + and re.fullmatch(r"[a-z0-9][-a-z0-9]{0,62}", target["sandbox"]), UNAVAILABLE) + name, namespace = target["sandbox"], "kars-" + target["sandbox"] + + def read(path): + value = setup.admin.get(path) + identity(value) + anchors[path] = value + return value + + result["category"] = "authority-unavailable" + sandbox = read(resource(CORE, "karssandboxes", name)) + observed = sandbox.get("status", {}).get("serviceObservation", {}) + require(identity(sandbox)[0] == target["uid"] and isinstance(observed, dict) + and sandbox["metadata"].get("name") == name + and sandbox["metadata"].get("namespace") == CORE + and observed.get("phase") in ("Prepared", "Ready") + and isinstance(observed.get("version"), str) and observed["version"], UNAVAILABLE) + ns = read("/api/v1/namespaces/" + namespace) + deployment = read(resource(namespace, "deployments", name, "/apis/apps/v1")) + require(ns["metadata"].get("name") == namespace + and identity(ns)[0] == observed.get("namespaceUid") + and deployment["metadata"].get("namespace") == namespace + and deployment["metadata"].get("name") == name + and identity(deployment)[0] == observed.get("deploymentUid"), UNAVAILABLE) + template = deployment["spec"]["template"] + require(template["spec"].get("serviceAccountName") == "sandbox" + and template["metadata"]["labels"].get("kars.azure.com/sandbox") == name, UNAVAILABLE) + result["category"] = "consumer-unavailable" + pods = [] + candidates = [pod for pod in complete_inventory(setup.admin.get(core(namespace, "pods")), 32) + if pod["metadata"].get("labels", {}).get("kars.azure.com/sandbox") == name + and pod["metadata"].get("namespace") == namespace] + require(0 < len(candidates) <= 8, UNAVAILABLE) + for candidate in candidates: + require(candidate.get("kind") == "Pod" and candidate["spec"].get("serviceAccountName") == "sandbox", + UNAVAILABLE) + ref = owner(candidate, "ReplicaSet") + require(ref is not None, UNAVAILABLE) + replica = read(resource(namespace, "replicasets", ref["name"], "/apis/apps/v1")) + lineage = owner(replica, "Deployment") + require(identity(replica)[0] == ref["uid"] and lineage is not None + and replica["metadata"].get("namespace") == namespace + and replica["metadata"].get("name") == ref["name"] + and lineage["name"] == name and lineage["uid"] == identity(deployment)[0], + UNAVAILABLE) + pod_name = candidate["metadata"]["name"] + require(re.fullmatch(r"[a-z0-9][-a-z0-9]{0,252}", pod_name) is not None, UNAVAILABLE) + pod = read(core(namespace, "pods", pod_name)) + require(identity(pod) == identity(candidate), UNAVAILABLE) + statuses = [item for item in pod.get("status", {}).get("containerStatuses", []) + if item.get("name") == "inference-router"] + require(len(statuses) == 1, UNAVAILABLE) + status = statuses[0] + require(type(status.get("ready")) is bool, UNAVAILABLE) + restarts = bounded_integer(status.get("restartCount"), 1000000) + state = container_state(status.get("state", {})) + entry = { + "routerReady": status["ready"], "restartCount": restarts, + "state": state, "lastState": container_state(status.get("lastState", {})), + "observerVersionMatchesStatus": + pod["metadata"].get("annotations", {}).get(VERSION) == observed["version"], + "observerVersionMatchesTemplate": + pod["metadata"].get("annotations", {}).get(VERSION) + == template["metadata"].get("annotations", {}).get(VERSION), + "logs": {"available": False, "category": "no-running-process"}, + "previousLogs": {"available": False, "category": "no-previous-process"}, + } + if state["phase"] == "running" and isinstance(status.get("containerID"), str) and status["containerID"]: + entry["logs"] = read_logs(namespace, pod_name) + if restarts > 0 and entry["lastState"]["phase"] == "terminated": + entry["previousLogs"] = read_logs(namespace, pod_name, previous=True) + try: + events = setup.admin.get(core(namespace, "events") + "?" + urlencode({ + "fieldSelector": "involvedObject.uid=" + identity(pod)[0]})) + entry["probeEvents"] = { + "available": True, **event_records(events, namespace, pod_name, identity(pod)[0])} + except READ_ERRORS: + entry["probeEvents"] = {"available": False, "category": "event-read-unavailable"} + pods.append(entry) + require(bool(pods), UNAVAILABLE) + result["category"] = "snapshot-changed" + for path, before in anchors.items(): + current = setup.admin.get(path) + require(identity(current) == identity(before), UNAVAILABLE) + if before.get("kind") == "Pod": + require(current.get("status") == before.get("status"), UNAVAILABLE) + result.update(available=True, category="captured", pods=pods) + except READ_ERRORS: + return result + return result diff --git a/bridge/tests/native-credentials/run.py b/bridge/tests/native-credentials/run.py index 6f71f7fc..3e8ab50c 100644 --- a/bridge/tests/native-credentials/run.py +++ b/bridge/tests/native-credentials/run.py @@ -20,6 +20,7 @@ from observation_diagnostics import collect as observation_diagnostics from observer_network_diagnostics import collect as observer_network_diagnostics from rotation_diagnostics import collect as rotation_diagnostics +from rollout_diagnostics import collect as rollout_diagnostics from template_diagnostics import collect as template_diagnostics @@ -126,6 +127,8 @@ def case(name, operation, allowed=True): setup, observations.observer_target, report["cases"][name], started_at) save() if name == "private-bff-observer-and-fresh-privacy-rpc": + report["cases"][name]["routerRollout"] = rollout_diagnostics( + setup, observations.observer_target) report["cases"][name]["enrollmentTemplateDrift"] = template_diagnostics( setup, observations.enrollment_templates, report["cases"][name]["failure"]) report["cases"][name]["observationReadiness"] = observation_diagnostics( @@ -148,7 +151,8 @@ def case(name, operation, allowed=True): print(json.dumps({"nativeCase": name, **{key: value for key, value in report["cases"][name].items() if key not in ("metadataAtFailure", "observationReadiness", "actorApiOutcomes", "observerApiReachability", - "enrollmentTemplateDrift", "rotationFailureSnapshot")}}), flush=True) + "enrollmentTemplateDrift", "rotationFailureSnapshot", + "routerRollout")}}), flush=True) def passed(name): return report["cases"].get(name, {}).get("result") == "passed" diff --git a/bridge/tests/native-credentials/test_rollout_diagnostics.py b/bridge/tests/native-credentials/test_rollout_diagnostics.py new file mode 100644 index 00000000..cbfbb2d6 --- /dev/null +++ b/bridge/tests/native-credentials/test_rollout_diagnostics.py @@ -0,0 +1,202 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +import copy +import json +from types import SimpleNamespace +import unittest +from unittest.mock import patch + +from native_api import Failure +from observation_diagnostics import VERSION +from rollout_diagnostics import collect, container_state, event_records, startup_records +from test_observation_diagnostics import DEPLOYMENT, POD, REPLICA_SET, RUNTIME, SANDBOX, TARGET, Fixture + + +def event(**changes): + value = { + "involvedObject": {"kind": "Pod", "apiVersion": "v1", "namespace": RUNTIME, + "name": "agent-pod", "uid": "agent-pod-uid", + "fieldPath": "spec.containers{inference-router}"}, + "source": {"component": "kubelet"}, "reason": "Unhealthy", + "message": 'Readiness probe failed: Get "http://private-canary": connection refused', + } + value.update(changes) + return value + + +class RolloutFixture(Fixture): + def __init__(self): + super().__init__() + self.events = [event()] + self.objects[POD]["status"] = {"containerStatuses": [{ + "name": "inference-router", "ready": False, "restartCount": 3, + "containerID": "containerd://private-canary", "state": {"running": {"startedAt": "private-canary"}}, + "lastState": {"terminated": {"reason": "OOMKilled", "exitCode": 137, "signal": 9, + "message": "private-canary"}}, + }]} + + def get(self, path): + if "/events?" in path: + return {"items": copy.deepcopy(self.events)} + return super().get(path) + + +def log(message="kars Inference Router starting", **changes): + return json.dumps({"target": "kars_inference_router", "level": "INFO", + "fields": {"message": message, "token": "private-canary"}, **changes}) + + +class RolloutDiagnosticsTests(unittest.TestCase): + def capture(self, fixture=None, side_effect=None): + fixture = fixture or RolloutFixture() + with patch("rollout_diagnostics.command", return_value=log(), side_effect=side_effect) as call: + value = collect(SimpleNamespace(admin=fixture), {**TARGET, "uid": "sandbox-uid"}) + return value, call + + def test_unready_router_has_bounded_process_and_probe_evidence(self): + value, call = self.capture() + self.assertTrue(value["available"]) + self.assertTrue(value["diagnosticOnly"]) + pod = value["pods"][0] + self.assertFalse(pod["routerReady"]) + self.assertEqual(pod["restartCount"], 3) + self.assertEqual(pod["lastState"], {"phase": "terminated", "reason": "OOMKilled", + "exitCode": 137, "signal": 9}) + self.assertEqual(pod["logs"]["stages"], ["starting"]) + self.assertFalse(pod["logs"]["listenerReachabilityProved"]) + self.assertEqual(pod["probeEvents"]["records"], + [{"probe": "readiness", "outcome": "failed", + "category": "connection-refused", "httpStatus": 0}]) + self.assertNotIn("private-canary", json.dumps(value)) + self.assertEqual(call.call_count, 2) + self.assertIn("--limit-bytes=131072", call.call_args.args) + self.assertIn("--previous", call.call_args.args) + + def test_stale_observer_version_is_reported_not_treated_as_current_authority(self): + fixture = RolloutFixture() + fixture.objects[POD]["metadata"]["annotations"][VERSION] = "old:1" + value, _ = self.capture(fixture) + self.assertTrue(value["available"]) + self.assertFalse(value["pods"][0]["observerVersionMatchesStatus"]) + self.assertFalse(value["pods"][0]["observerVersionMatchesTemplate"]) + self.assertTrue(value["diagnosticOnly"]) + + def test_waiting_container_reads_only_its_previous_process_logs(self): + fixture = RolloutFixture() + fixture.objects[POD]["status"]["containerStatuses"][0]["state"] = { + "waiting": {"reason": "CrashLoopBackOff", "message": "private-canary"}} + value, call = self.capture(fixture) + self.assertTrue(value["available"]) + self.assertEqual(value["pods"][0]["state"]["phase"], "waiting") + self.assertFalse(value["pods"][0]["logs"]["available"]) + self.assertTrue(value["pods"][0]["previousLogs"]["available"]) + self.assertEqual(call.call_count, 1) + self.assertIn("--previous", call.call_args.args) + + def test_fixed_startup_markers_do_not_claim_bound_listener(self): + raw = "\n".join([log(), log("Registry topology"), log("Listening on 0.0.0.0:8443"), + log("unknown-private-canary", level="ERROR"), "Error: private-canary", + log([], level="ERROR"), "[]"]) + value = startup_records(raw) + self.assertEqual(value["stages"], ["starting", "configuration-loaded", "listener-planned"]) + self.assertEqual(value["errorRecords"], 1) + self.assertFalse(value["listenerReachabilityProved"]) + self.assertNotIn("canary", json.dumps(value)) + with self.assertRaises(Failure): + startup_records("x" * 131073) + + def test_probe_events_remain_pod_lifetime_and_foreign_events_are_ignored(self): + records = [event(), event(message="Liveness probe failed: HTTP probe failed with statuscode: 503"), + event(message="Startup probe failed: private-canary context deadline exceeded"), + event(message="Readiness probe failed: private-canary"), + event(message="Readiness probe errored: private-canary"), + event(involvedObject={"uid": "foreign"}), + event(source={"component": "private-canary"}), + event(involvedObject={**event()["involvedObject"], + "fieldPath": "spec.containers{openclaw}"})] + value = event_records({"items": records}, RUNTIME, "agent-pod", "agent-pod-uid") + self.assertEqual(value["coverage"], "pod-lifetime-events-not-current-process") + self.assertEqual([item["category"] for item in value["records"]], + ["connection-refused", "http-response", "timeout", "other", "other"]) + self.assertEqual(value["records"][1]["httpStatus"], 503) + self.assertEqual(value["records"][-1]["outcome"], "errored") + self.assertNotIn("canary", json.dumps(value)) + for metadata in ({"continue": "more"}, {"remainingItemCount": 1}): + with self.assertRaises(Failure): + event_records({"metadata": metadata, "items": records}, RUNTIME, "agent-pod", "agent-pod-uid") + + def test_changed_identity_revision_or_process_discards_projection(self): + for path in (SANDBOX, DEPLOYMENT, REPLICA_SET, POD): + for field in ("uid", "resourceVersion"): + with self.subTest(path=path, field=field): + fixture = RolloutFixture() + + def changed(*args, **kwargs): + fixture.objects[path]["metadata"][field] = "changed" + return log() + + value, _ = self.capture(fixture, changed) + self.assertFalse(value["available"]) + self.assertNotIn("pods", value) + fixture = RolloutFixture() + + def restarted(*args, **kwargs): + fixture.objects[POD]["status"]["containerStatuses"][0]["restartCount"] += 1 + return log() + + value, _ = self.capture(fixture, restarted) + self.assertFalse(value["available"]) + self.assertNotIn("pods", value) + + def test_foreign_or_incomplete_authority_never_reads_logs(self): + for path, change in ( + (SANDBOX, lambda item: item["metadata"].update(uid="foreign")), + (DEPLOYMENT, lambda item: item["metadata"].update(uid="foreign")), + (REPLICA_SET, lambda item: item["metadata"]["ownerReferences"][0].update(uid="foreign")), + (POD, lambda item: item["metadata"].update(deletionTimestamp="terminating")), + ): + with self.subTest(path=path): + fixture = RolloutFixture() + change(fixture.objects[path]) + value, call = self.capture(fixture) + self.assertFalse(value["available"]) + call.assert_not_called() + + def test_errors_are_explicit_and_value_free(self): + value, _ = self.capture(side_effect=OSError("private-canary")) + self.assertTrue(value["available"]) + self.assertFalse(value["pods"][0]["logs"]["available"]) + self.assertFalse(value["pods"][0]["previousLogs"]["available"]) + self.assertEqual(value["pods"][0]["logs"]["category"], "log-read-unavailable") + self.assertNotIn("canary", json.dumps(value)) + + def test_event_read_error_preserves_stable_process_evidence(self): + fixture = RolloutFixture() + original = fixture.get + + def failing(path): + if "/events?" in path: + raise OSError("private-canary") + return original(path) + + fixture.get = failing + value, _ = self.capture(fixture) + self.assertTrue(value["available"]) + self.assertTrue(value["pods"][0]["logs"]["available"]) + self.assertEqual(value["pods"][0]["probeEvents"], + {"available": False, "category": "event-read-unavailable"}) + self.assertNotIn("canary", json.dumps(value)) + + def test_state_types_and_values_are_bounded(self): + for value in ({"terminated": {"exitCode": True}}, {"terminated": {"exitCode": 256}}, + {"running": {}, "waiting": {}}, {"private-canary": {}}, []): + with self.subTest(value=value): + with self.assertRaises(Failure): + container_state(value) + self.assertEqual(container_state({"waiting": {"reason": "private-canary"}}), + {"phase": "waiting", "reason": "Other"}) + + +if __name__ == "__main__": + unittest.main() From 7ae918cf16fbf021f96f99f531dd0b078eb00038 Mon Sep 17 00:00:00 2001 From: pallakatos Date: Wed, 16 Sep 2026 23:45:46 +0200 Subject: [PATCH 13/13] test(bridge): preserve first rollout diagnostic anchors Reject UID or resourceVersion drift when multiple Pods share one ReplicaSet. The two-Pod regression reproduces the previous revision false acceptance and verifies stable shared anchors remain supported. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: eb3654cd-f1e0-445a-8734-430800af1903 --- .../native-credentials/rollout_diagnostics.py | 5 +++- .../test_rollout_diagnostics.py | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/bridge/tests/native-credentials/rollout_diagnostics.py b/bridge/tests/native-credentials/rollout_diagnostics.py index e0e5944d..69e05754 100644 --- a/bridge/tests/native-credentials/rollout_diagnostics.py +++ b/bridge/tests/native-credentials/rollout_diagnostics.py @@ -133,7 +133,10 @@ def collect(setup, target): def read(path): value = setup.admin.get(path) identity(value) - anchors[path] = value + if path in anchors: + require(identity(value) == identity(anchors[path]), UNAVAILABLE) + else: + anchors[path] = value return value result["category"] = "authority-unavailable" diff --git a/bridge/tests/native-credentials/test_rollout_diagnostics.py b/bridge/tests/native-credentials/test_rollout_diagnostics.py index cbfbb2d6..f0715371 100644 --- a/bridge/tests/native-credentials/test_rollout_diagnostics.py +++ b/bridge/tests/native-credentials/test_rollout_diagnostics.py @@ -163,6 +163,35 @@ def test_foreign_or_incomplete_authority_never_reads_logs(self): self.assertFalse(value["available"]) call.assert_not_called() + def test_shared_replicaset_retains_its_first_snapshot_across_pods(self): + for changed_field in (None, "uid", "resourceVersion"): + with self.subTest(changed_field=changed_field): + fixture = RolloutFixture() + second = copy.deepcopy(fixture.objects[POD]) + second["metadata"].update(name="agent-pod-2", uid="agent-pod-2-uid") + fixture.objects[POD + "-2"] = second + original = fixture.get + replica_reads = 0 + + def changing(path): + nonlocal replica_reads + if path == REPLICA_SET: + replica_reads += 1 + if replica_reads == 2 and changed_field: + fixture.objects[path]["metadata"][changed_field] = "changed-private-canary" + return original(path) + + fixture.get = changing + value, _ = self.capture(fixture) + self.assertEqual(value["available"], changed_field is None) + if changed_field is None: + self.assertEqual(len(value["pods"]), 2) + self.assertEqual(replica_reads, 3) + else: + self.assertNotIn("pods", value) + self.assertEqual(replica_reads, 2) + self.assertNotIn("canary", json.dumps(value)) + def test_errors_are_explicit_and_value_free(self): value, _ = self.capture(side_effect=OSError("private-canary")) self.assertTrue(value["available"])