Skip to content

Commit d29757c

Browse files
authored
Merge pull request #619 from s-and-p-team/feat/github-issue-agent-rbac-scope-gating
Feat/GitHub issue agent rbac scope gating
2 parents 13eec8e + a20a645 commit d29757c

10 files changed

Lines changed: 1686 additions & 65 deletions

File tree

authbridge/demos/github-issue/aiac/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ aiac.env
55
aiac_agent/config/llm_conf.yaml
66

77
# Generated policy files — created at runtime by aiac_cli.py.
8-
generated_configs/
8+
config/
99

1010
# Python virtual environment
1111
venv/

authbridge/demos/github-issue/aiac/Makefile

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ help: ## Show this menu (default)
3131
$(MAKEFILE_LIST)
3232
@printf "\nVariables:\n"
3333
@printf " \033[36m%-20s\033[0m %s\n" "POLICY" "policy file to apply (default: policies/regular_policy.txt)"
34+
@printf " \033[36m%-20s\033[0m %s\n" "RBAC_CONFIG" "RBAC config file (default: rbac/config.yaml)"
3435
@printf " \033[36m%-20s\033[0m %s\n" "PYTHON" "Python interpreter (default: kagenti-extensions/.venv/bin/python)"
3536
@printf "\nPrerequisites: uv, Keycloak running, aiac.env and llm_conf.yaml configured.\n\n"
3637

3738
POLICY ?= policies/regular_policy.txt
39+
RBAC_CONFIG ?= rbac/config.yaml
3840

3941
# Resolve the venv relative to this Makefile, regardless of where make is invoked.
4042
MAKEFILE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
@@ -81,28 +83,28 @@ preflight: ## Verify prerequisites (uv, venv, aiac.env, llm_conf.yaml, Keycloak
8183

8284
setup: preflight ## Provision Keycloak realm with clients, roles, and users
8385
@echo "[*] Provisioning Keycloak realm ..."
84-
$(PYTHON) ../setup_keycloak.py -rbac config.yaml
86+
$(PYTHON) ../setup_keycloak.py -rbac $(RBAC_CONFIG)
8587
@echo "[✓] Keycloak realm provisioned."
8688

8789
# ---------- Apply policy ----------
8890

8991
apply-policy: preflight ## Generate + apply POLICY (default: policies/regular_policy.txt) to Keycloak
9092
@echo "[*] Running AIAC full pipeline: $(POLICY)"
91-
$(PYTHON) aiac_cli.py --yes $(POLICY)
93+
$(PYTHON) aiac_cli.py $(POLICY)
9294

9395
apply-permissive: POLICY = policies/permissive_policy.txt
9496
apply-permissive: apply-policy ## Generate + apply the permissive policy (grants Sales access)
9597

9698
# ---------- Show result ----------
9799

98100
show-result: preflight ## Show active composite-role mappings in Keycloak (verify applied policy)
99-
$(PYTHON) scripts/show-result.py
101+
$(PYTHON) scripts/show-result.py --config-path ../$(RBAC_CONFIG)
100102

101103
# ---------- Reset ----------
102104

103105
reset: preflight ## Wipe generated configs and re-provision the realm from scratch
104106
@echo "[*] Removing generated configs ..."
105-
@rm -f generated_configs/*.yaml
107+
@rm -f config/*.yaml
106108
@echo "[*] Re-provisioning Keycloak realm ..."
107-
$(PYTHON) ../setup_keycloak.py -rbac config.yaml
109+
$(PYTHON) ../setup_keycloak.py -rbac $(RBAC_CONFIG)
108110
@echo "[✓] Reset complete."

authbridge/demos/github-issue/aiac/aiac_cli.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,11 @@ def run_full_pipeline(policy_text_file: str, policy_name: str | None, yes: bool
149149
print_info(f"Policy name: {policy_name}")
150150
print()
151151

152-
generated_configs_dir = script_dir / "generated_configs"
152+
generated_configs_dir = script_dir / "config"
153153
generated_configs_dir.mkdir(exist_ok=True)
154154

155155
config_file = generated_configs_dir / f"{policy_name}_config.yaml"
156156
policy_file = generated_configs_dir / f"{policy_name}_policy.yaml"
157-
main_config = "config.yaml"
158157

159158
realm_name = os.getenv("REALM_NAME", "demo")
160159
keycloak_url = os.getenv("KEYCLOAK_URL")
@@ -212,7 +211,7 @@ def run_full_pipeline(policy_text_file: str, policy_name: str | None, yes: bool
212211
realm_name=realm_name,
213212
user_realm_name="master",
214213
)
215-
delete_access_control_policy(admin, realm_name, script_dir / main_config)
214+
delete_access_control_policy(admin, realm_name, config_file=config_file)
216215
print_success("Old rules removed successfully")
217216
print()
218217

@@ -226,8 +225,8 @@ def run_full_pipeline(policy_text_file: str, policy_name: str | None, yes: bool
226225
print_success(f"Policy '{policy_name}' has been successfully updated in Keycloak")
227226
print()
228227
print_info("Generated files:")
229-
print(f" - Configuration: generated_configs/{config_file.name}")
230-
print(f" - Rules: generated_configs/{policy_file.name}")
228+
print(f" - Configuration: {config_file}")
229+
print(f" - Rules: {policy_file}")
231230

232231
except Exception as e:
233232
print_error(f"An error occurred: {e}")

authbridge/demos/github-issue/aiac/scripts/show-result.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
Run via: make show-result
1010
"""
1111

12+
import argparse
1213
import os
1314
import sys
1415
from pathlib import Path
@@ -46,6 +47,15 @@ def section(title: str) -> None:
4647

4748

4849
def main() -> None:
50+
parser = argparse.ArgumentParser(description="Display composite-role mappings currently active in Keycloak")
51+
parser.add_argument(
52+
"--config-path",
53+
type=Path,
54+
required=True,
55+
help="Path to the RBAC configuration YAML file",
56+
)
57+
args = parser.parse_args()
58+
4959
try:
5060
admin = KeycloakAdmin(
5161
server_url=KEYCLOAK_URL,
@@ -58,7 +68,11 @@ def main() -> None:
5868
print(f"{RED}ERROR: Could not connect to Keycloak at {KEYCLOAK_URL}: {e}{RESET}")
5969
sys.exit(1)
6070

61-
config_path = AIAC_DIR / "config.yaml"
71+
config_path = args.config_path
72+
if not config_path.exists():
73+
print(f"{RED}ERROR: Config file not found: {config_path}{RESET}")
74+
sys.exit(1)
75+
6276
with open(config_path) as f:
6377
config = yaml.safe_load(f)
6478

@@ -85,7 +99,7 @@ def main() -> None:
8599
name = c.get("name", "?")
86100
print(f" {GREEN}{RESET} {container}.{name}")
87101

88-
gen_dir = AIAC_DIR / "generated_configs"
102+
gen_dir = AIAC_DIR / "config"
89103
policy_files = list(gen_dir.glob("*_policy.yaml")) if gen_dir.exists() else []
90104
if policy_files:
91105
latest = max(policy_files, key=lambda p: p.stat().st_mtime_ns)

authbridge/demos/github-issue/demo-aiac.md

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ REALM_NAME=kagenti
378378
Run the setup script to create the demo realm with clients, roles, and users:
379379

380380
```bash
381-
python setup_keycloak.py -rbac config.yaml
381+
python setup_keycloak.py -rbac rbac/config.yaml
382382
```
383383

384384
Open bash inside the test client pod
@@ -560,26 +560,26 @@ python aiac_cli.py policies/regular_policy.txt
560560
```
561561

562562
Review generated files:
563-
- Configuration: generated_configs/regular_policy_config.yaml
564-
- Rules: generated_configs/regular_policy_policy.yaml
563+
- Configuration: config/regular_policy_config.yaml
564+
- Rules: config/regular_policy_policy.yaml
565565

566566

567567
Verify results
568568
```bash
569569
echo "1. Developer has github-full-access:"
570-
yq '.policy.developer[] | select(.client == "github-tool" and .role == "github-full-access")' generated_configs/regular_policy_policy.yaml
570+
yq '.policy.developer[] | select(.client == "github-tool" and .role == "github-full-access")' config/regular_policy_policy.yaml
571571

572572
echo -e "\n2. Developer has github-tool-aud:"
573-
yq '.policy.developer[] | select(.client == "github-tool" and .role == "github-tool-aud")' generated_configs/regular_policy_policy.yaml
573+
yq '.policy.developer[] | select(.client == "github-tool" and .role == "github-tool-aud")' config/regular_policy_policy.yaml
574574

575575
echo -e "\n3. Tech-support has github-tool-aud:"
576-
yq '.policy.tech-support[] | select(.client == "github-tool" and .role == "github-tool-aud")' generated_configs/regular_policy_policy.yaml
576+
yq '.policy.tech-support[] | select(.client == "github-tool" and .role == "github-tool-aud")' config/regular_policy_policy.yaml
577577

578578
echo -e "\n4. Tech-support does NOT have github-full-access (should be empty):"
579-
yq '.policy.tech-support[] | select(.client == "github-tool" and .role == "github-full-access")' generated_configs/regular_policy_policy.yaml
579+
yq '.policy.tech-support[] | select(.client == "github-tool" and .role == "github-full-access")' config/regular_policy_policy.yaml
580580

581581
echo -e "\n5. Sales does NOT exist in policy (should be null):"
582-
yq '.policy.sales' generated_configs/regular_policy_policy.yaml
582+
yq '.policy.sales' config/regular_policy_policy.yaml
583583
```
584584
Expected output :
585585
```bash
@@ -641,7 +641,7 @@ echo "Client ID: $CLIENT_ID Secret length: ${#CLIENT_SECRET}"
641641

642642

643643
# step 2 - run AIAC using regualr policy
644-
# python AIAC.py policy/regular_policy.txt
644+
# python aiac_cli.py policies/regular_policy.txt
645645
# users will be configured acording to the 'regular' policy
646646
#ALICE (Developer) can list issues in kagenti/kagenti repo
647647
#ALICE can also list issues in omerboehm/intro2c repo (because she is a DEVELOPER and has full access)
@@ -791,26 +791,26 @@ Apply the updated policy
791791
python aiac_cli.py policies/permissive_policy.txt
792792
```
793793
Review generated files:
794-
- Configuration: generated_configs/permissive_policy_config.yaml
795-
- Rules: generated_configs/permissive_policy_policy.yaml
794+
- Configuration: config/permissive_policy_config.yaml
795+
- Rules: config/permissive_policy_policy.yaml
796796

797797

798798
Verify results
799799
```bash
800800
echo "1. Developer has github-full-access:"
801-
yq '.policy.developer[] | select(.client == "github-tool" and .role == "github-full-access")' generated_configs/permissive_policy_policy.yaml
801+
yq '.policy.developer[] | select(.client == "github-tool" and .role == "github-full-access")' config/permissive_policy_policy.yaml
802802

803803
echo -e "\n2. Developer has github-tool-aud:"
804-
yq '.policy.developer[] | select(.client == "github-tool" and .role == "github-tool-aud")' generated_configs/permissive_policy_policy.yaml
804+
yq '.policy.developer[] | select(.client == "github-tool" and .role == "github-tool-aud")' config/permissive_policy_policy.yaml
805805

806806
echo -e "\n3. Tech-support has github-tool-aud:"
807-
yq '.policy.tech-support[] | select(.client == "github-tool" and .role == "github-tool-aud")' generated_configs/permissive_policy_policy.yaml
807+
yq '.policy.tech-support[] | select(.client == "github-tool" and .role == "github-tool-aud")' config/permissive_policy_policy.yaml
808808

809809
echo -e "\n4. Tech-support does NOT have github-full-access (should be empty):"
810-
yq '.policy.tech-support[] | select(.client == "github-tool" and .role == "github-full-access")' generated_configs/permissive_policy_policy.yaml
810+
yq '.policy.tech-support[] | select(.client == "github-tool" and .role == "github-full-access")' config/permissive_policy_policy.yaml
811811

812812
echo -e "\n5. Sales is now just like Tech-support (\"Other personnel\"):"
813-
yq '.policy.sales[] | select(.client == "github-tool" and .role == "github-tool-aud")' generated_configs/permissive_policy_policy.yaml
813+
yq '.policy.sales[] | select(.client == "github-tool" and .role == "github-tool-aud")' config/permissive_policy_policy.yaml
814814
```
815815
Expected output :
816816
```txt
@@ -831,17 +831,18 @@ role: github-tool-aud
831831
5. Sales is now just like Tech-support ("Other personnel"):
832832
client: github-tool
833833
role: github-tool-aud
834-
834+
```
835835

836836

837837
### Step 17: Reset Realm (Optional)
838838

839839
To clean up and start fresh:
840840

841841
```bash
842+
cd demos/github-issue/
842843
# delete generated policies
843-
rm -f generated_configs/*.yaml
844+
rm -f aiac/config/*.yaml
844845

845846
# re-provision the realm
846-
python setup_keycloak.py -rbac config.yaml
847+
python setup_keycloak.py -rbac rbac/config.yaml
847848
```

0 commit comments

Comments
 (0)