Skip to content

Commit 670aa6c

Browse files
committed
feat: add profile update script and fix secret role
1 parent 7abefab commit 670aa6c

3 files changed

Lines changed: 87 additions & 3 deletions

File tree

chart/templates/role.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ metadata:
66
labels:
77
{{- include "pint.labels" . | nindent 4 }}
88
rules:
9+
- apiGroups: [""]
10+
resources: ["secrets"]
11+
verbs: ["create"]
912
- apiGroups: [""]
1013
resources: ["secrets"]
1114
resourceNames:
1215
- {{ .Values.secrets.radiusClients | quote }}
1316
- {{ .Values.secrets.radiusConfig | quote }}
1417
- {{ .Values.secrets.radSecCert | quote }}
15-
verbs: ["get", "create", "update"]
18+
verbs: ["get", "update"]
1619
- apiGroups: [""]
1720
resources: ["pods"]
1821
verbs: ["list"]

ipa/profiles/pint_radsec_server.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
desc=CSH RadSec Server Certificate for FreeRADIUS (2-year)
1+
desc=CSH RadSec Server Certificate for FreeRADIUS (90-day)
22
visible=false
33
enable=true
44
enableBy=admin
@@ -27,7 +27,7 @@ policyset.radSecServerSet.2.constraint.params.notBeforeCheck=false
2727
policyset.radSecServerSet.2.constraint.params.notAfterCheck=false
2828
policyset.radSecServerSet.2.default.class_id=validityDefaultImpl
2929
policyset.radSecServerSet.2.default.name=Validity Default
30-
policyset.radSecServerSet.2.default.params.range=730
30+
policyset.radSecServerSet.2.default.params.range=90
3131
policyset.radSecServerSet.2.default.params.startTime=0
3232
policyset.radSecServerSet.3.constraint.class_id=keyConstraintImpl
3333
policyset.radSecServerSet.3.constraint.name=Key Constraint

ipa/update_profile.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env python3
2+
"""Update a FreeIPA certificate profile via the JSON-RPC API."""
3+
4+
import getpass
5+
import json
6+
import sys
7+
import urllib.parse
8+
import urllib.request
9+
from pathlib import Path
10+
11+
IPA_HOST = "ipa10-nrh.csh.rit.edu"
12+
BASE_URL = f"https://{IPA_HOST}/ipa"
13+
14+
15+
def login(opener: urllib.request.OpenerDirector, username: str, password: str) -> None:
16+
body = urllib.parse.urlencode({"user": username, "password": password}).encode()
17+
req = urllib.request.Request(
18+
f"{BASE_URL}/session/login_password",
19+
data=body,
20+
headers={"Referer": BASE_URL, "Content-Type": "application/x-www-form-urlencoded"},
21+
)
22+
resp = opener.open(req)
23+
if resp.status != 200:
24+
print(f"Login failed: {resp.status}", file=sys.stderr)
25+
sys.exit(1)
26+
27+
28+
def update_profile(opener: urllib.request.OpenerDirector, profile_id: str, cfg_path: Path) -> None:
29+
payload = json.dumps({
30+
"method": "certprofile_mod",
31+
"params": [[profile_id], {"file": cfg_path.read_text(), "raw": True}],
32+
"id": 0,
33+
}).encode()
34+
req = urllib.request.Request(
35+
f"{BASE_URL}/json",
36+
data=payload,
37+
headers={"Referer": BASE_URL, "Content-Type": "application/json"},
38+
)
39+
resp = opener.open(req)
40+
result = json.loads(resp.read())
41+
if result.get("error"):
42+
print(f"Error updating {profile_id}: {result['error']}", file=sys.stderr)
43+
sys.exit(1)
44+
print(f"Updated {profile_id}: {result['result'].get('summary', 'ok')}")
45+
46+
47+
def main() -> None:
48+
profiles_dir = Path(__file__).parent / "profiles"
49+
profiles = sorted(profiles_dir.glob("*.cfg"))
50+
if not profiles:
51+
print("No .cfg files found in profiles/", file=sys.stderr)
52+
sys.exit(1)
53+
54+
print("Available profiles:")
55+
for i, p in enumerate(profiles):
56+
print(f" {i + 1}. {p.stem}")
57+
print(f" {len(profiles) + 1}. all")
58+
59+
choice = input("Update which profile? ").strip()
60+
if choice == str(len(profiles) + 1) or choice.lower() == "all":
61+
selected = profiles
62+
else:
63+
try:
64+
selected = [profiles[int(choice) - 1]]
65+
except (ValueError, IndexError):
66+
print("Invalid choice.", file=sys.stderr)
67+
sys.exit(1)
68+
69+
username = input("IPA username: ").strip()
70+
password = getpass.getpass("IPA password: ")
71+
72+
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor())
73+
login(opener, username, password)
74+
print("Authenticated.")
75+
76+
for cfg in selected:
77+
update_profile(opener, cfg.stem, cfg)
78+
79+
80+
if __name__ == "__main__":
81+
main()

0 commit comments

Comments
 (0)