Skip to content

Commit f57b261

Browse files
committed
Adding an initial realm setup
Signed-off-by: Matthias Wessendorf <[email protected]>
1 parent a3c981f commit f57b261

File tree

1 file changed

+218
-0
lines changed

1 file changed

+218
-0
lines changed

build/keycloak.mk

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,221 @@ keycloak-status: ## Show Keycloak status and connection info
5454
.PHONY: keycloak-logs
5555
keycloak-logs: ## Tail Keycloak logs
5656
@kubectl logs -n $(KEYCLOAK_NAMESPACE) -l app=keycloak -f --tail=100
57+
58+
.PHONY: keycloak-setup-realm
59+
keycloak-setup-realm: ## Setup OpenShift realm with token exchange support
60+
@echo "========================================="
61+
@echo "Setting up OpenShift Realm for Token Exchange"
62+
@echo "========================================="
63+
@echo "Using Keycloak at http://localhost:8090"
64+
@echo "(Ensure 'make keycloak-forward' is running in another terminal)"
65+
@echo ""
66+
@echo "Getting admin access token..."
67+
@TOKEN=$$(curl -s -X POST "http://localhost:8090/realms/master/protocol/openid-connect/token" \
68+
-H "Content-Type: application/x-www-form-urlencoded" \
69+
-d "username=$(KEYCLOAK_ADMIN_USER)" \
70+
-d "password=$(KEYCLOAK_ADMIN_PASSWORD)" \
71+
-d "grant_type=password" \
72+
-d "client_id=admin-cli" \
73+
2>/dev/null | jq -r '.access_token // empty'); \
74+
if [ -z "$$TOKEN" ] || [ "$$TOKEN" = "null" ]; then \
75+
echo "❌ Failed to get access token. Check if:"; \
76+
echo " - Keycloak is running (make keycloak-install)"; \
77+
echo " - Port forwarding is active (make keycloak-forward)"; \
78+
echo " - Admin credentials are correct: $(KEYCLOAK_ADMIN_USER)/$(KEYCLOAK_ADMIN_PASSWORD)"; \
79+
exit 1; \
80+
fi; \
81+
echo "✅ Successfully obtained access token"; \
82+
echo ""; \
83+
echo "Creating OpenShift realm..."; \
84+
REALM_RESPONSE=$$(curl -s -w "%{http_code}" -X POST "http://localhost:8090/admin/realms" \
85+
-H "Authorization: Bearer $$TOKEN" \
86+
-H "Content-Type: application/json" \
87+
-d '{"realm":"openshift","enabled":true}'); \
88+
REALM_CODE=$$(echo "$$REALM_RESPONSE" | tail -c 4); \
89+
if [ "$$REALM_CODE" = "201" ] || [ "$$REALM_CODE" = "409" ]; then \
90+
if [ "$$REALM_CODE" = "201" ]; then echo "✅ OpenShift realm created"; \
91+
else echo "✅ OpenShift realm already exists"; fi; \
92+
else \
93+
echo "❌ Failed to create OpenShift realm (HTTP $$REALM_CODE)"; \
94+
exit 1; \
95+
fi; \
96+
echo ""; \
97+
echo "Creating mcp:openshift client scope..."; \
98+
SCOPE_RESPONSE=$$(curl -s -w "HTTPCODE:%{http_code}" -X POST "http://localhost:8090/admin/realms/openshift/client-scopes" \
99+
-H "Authorization: Bearer $$TOKEN" \
100+
-H "Content-Type: application/json" \
101+
-d '{"name":"mcp:openshift","protocol":"openid-connect","attributes":{"display.on.consent.screen":"false","include.in.token.scope":"true"}}'); \
102+
SCOPE_CODE=$$(echo "$$SCOPE_RESPONSE" | grep -o "HTTPCODE:[0-9]*" | cut -d: -f2); \
103+
if [ "$$SCOPE_CODE" = "201" ] || [ "$$SCOPE_CODE" = "409" ]; then \
104+
if [ "$$SCOPE_CODE" = "201" ]; then echo "✅ mcp:openshift client scope created"; \
105+
else echo "✅ mcp:openshift client scope already exists"; fi; \
106+
else \
107+
echo "❌ Failed to create mcp:openshift scope (HTTP $$SCOPE_CODE)"; \
108+
exit 1; \
109+
fi; \
110+
echo ""; \
111+
echo "Adding audience mapper to mcp:openshift scope..."; \
112+
SCOPES_LIST=$$(curl -s -X GET "http://localhost:8090/admin/realms/openshift/client-scopes" \
113+
-H "Authorization: Bearer $$TOKEN" \
114+
-H "Accept: application/json"); \
115+
SCOPE_ID=$$(echo "$$SCOPES_LIST" | jq -r '.[] | select(.name == "mcp:openshift") | .id // empty' 2>/dev/null); \
116+
if [ -z "$$SCOPE_ID" ]; then \
117+
echo "❌ Failed to find mcp:openshift scope"; \
118+
exit 1; \
119+
fi; \
120+
MAPPER_RESPONSE=$$(curl -s -w "HTTPCODE:%{http_code}" -X POST "http://localhost:8090/admin/realms/openshift/client-scopes/$$SCOPE_ID/protocol-mappers/models" \
121+
-H "Authorization: Bearer $$TOKEN" \
122+
-H "Content-Type: application/json" \
123+
-d '{"name":"openshift-audience","protocol":"openid-connect","protocolMapper":"oidc-audience-mapper","config":{"included.client.audience":"openshift","id.token.claim":"true","access.token.claim":"true"}}'); \
124+
MAPPER_CODE=$$(echo "$$MAPPER_RESPONSE" | grep -o "HTTPCODE:[0-9]*" | cut -d: -f2); \
125+
if [ "$$MAPPER_CODE" = "201" ] || [ "$$MAPPER_CODE" = "409" ]; then \
126+
if [ "$$MAPPER_CODE" = "201" ]; then echo "✅ Audience mapper added"; \
127+
else echo "✅ Audience mapper already exists"; fi; \
128+
else \
129+
echo "❌ Failed to create audience mapper (HTTP $$MAPPER_CODE)"; \
130+
exit 1; \
131+
fi; \
132+
echo ""; \
133+
echo "Creating groups client scope..."; \
134+
GROUPS_SCOPE_RESPONSE=$$(curl -s -w "HTTPCODE:%{http_code}" -X POST "http://localhost:8090/admin/realms/openshift/client-scopes" \
135+
-H "Authorization: Bearer $$TOKEN" \
136+
-H "Content-Type: application/json" \
137+
-d '{"name":"groups","protocol":"openid-connect","attributes":{"display.on.consent.screen":"false","include.in.token.scope":"true"}}'); \
138+
GROUPS_SCOPE_CODE=$$(echo "$$GROUPS_SCOPE_RESPONSE" | grep -o "HTTPCODE:[0-9]*" | cut -d: -f2); \
139+
if [ "$$GROUPS_SCOPE_CODE" = "201" ] || [ "$$GROUPS_SCOPE_CODE" = "409" ]; then \
140+
if [ "$$GROUPS_SCOPE_CODE" = "201" ]; then echo "✅ groups client scope created"; \
141+
else echo "✅ groups client scope already exists"; fi; \
142+
else \
143+
echo "❌ Failed to create groups scope (HTTP $$GROUPS_SCOPE_CODE)"; \
144+
exit 1; \
145+
fi; \
146+
echo ""; \
147+
echo "Adding group membership mapper to groups scope..."; \
148+
SCOPES_LIST=$$(curl -s -X GET "http://localhost:8090/admin/realms/openshift/client-scopes" \
149+
-H "Authorization: Bearer $$TOKEN" \
150+
-H "Accept: application/json"); \
151+
GROUPS_SCOPE_ID=$$(echo "$$SCOPES_LIST" | jq -r '.[] | select(.name == "groups") | .id // empty' 2>/dev/null); \
152+
if [ -z "$$GROUPS_SCOPE_ID" ]; then \
153+
echo "❌ Failed to find groups scope"; \
154+
exit 1; \
155+
fi; \
156+
GROUPS_MAPPER_RESPONSE=$$(curl -s -w "HTTPCODE:%{http_code}" -X POST "http://localhost:8090/admin/realms/openshift/client-scopes/$$GROUPS_SCOPE_ID/protocol-mappers/models" \
157+
-H "Authorization: Bearer $$TOKEN" \
158+
-H "Content-Type: application/json" \
159+
-d '{"name":"groups","protocol":"openid-connect","protocolMapper":"oidc-group-membership-mapper","config":{"claim.name":"groups","full.path":"false","id.token.claim":"true","access.token.claim":"true","userinfo.token.claim":"true"}}'); \
160+
GROUPS_MAPPER_CODE=$$(echo "$$GROUPS_MAPPER_RESPONSE" | grep -o "HTTPCODE:[0-9]*" | cut -d: -f2); \
161+
if [ "$$GROUPS_MAPPER_CODE" = "201" ] || [ "$$GROUPS_MAPPER_CODE" = "409" ]; then \
162+
if [ "$$GROUPS_MAPPER_CODE" = "201" ]; then echo "✅ Group membership mapper added"; \
163+
else echo "✅ Group membership mapper already exists"; fi; \
164+
else \
165+
echo "❌ Failed to create group mapper (HTTP $$GROUPS_MAPPER_CODE)"; \
166+
exit 1; \
167+
fi; \
168+
echo ""; \
169+
echo "Creating openshift service client..."; \
170+
OPENSHIFT_CLIENT_RESPONSE=$$(curl -s -w "HTTPCODE:%{http_code}" -X POST "http://localhost:8090/admin/realms/openshift/clients" \
171+
-H "Authorization: Bearer $$TOKEN" \
172+
-H "Content-Type: application/json" \
173+
-d '{"clientId":"openshift","enabled":true,"publicClient":false,"standardFlowEnabled":true,"directAccessGrantsEnabled":true,"serviceAccountsEnabled":true,"authorizationServicesEnabled":false,"redirectUris":["*"],"defaultClientScopes":["groups"],"optionalClientScopes":[]}'); \
174+
OPENSHIFT_CLIENT_CODE=$$(echo "$$OPENSHIFT_CLIENT_RESPONSE" | grep -o "HTTPCODE:[0-9]*" | cut -d: -f2); \
175+
if [ "$$OPENSHIFT_CLIENT_CODE" = "201" ] || [ "$$OPENSHIFT_CLIENT_CODE" = "409" ]; then \
176+
if [ "$$OPENSHIFT_CLIENT_CODE" = "201" ]; then echo "✅ openshift client created"; \
177+
else echo "✅ openshift client already exists"; fi; \
178+
else \
179+
echo "❌ Failed to create openshift client (HTTP $$OPENSHIFT_CLIENT_CODE)"; \
180+
exit 1; \
181+
fi; \
182+
echo ""; \
183+
echo "Creating mcp-server client with token exchange..."; \
184+
MCP_CLIENT_RESPONSE=$$(curl -s -w "HTTPCODE:%{http_code}" -X POST "http://localhost:8090/admin/realms/openshift/clients" \
185+
-H "Authorization: Bearer $$TOKEN" \
186+
-H "Content-Type: application/json" \
187+
-d '{"clientId":"mcp-server","enabled":true,"publicClient":false,"standardFlowEnabled":true,"directAccessGrantsEnabled":true,"serviceAccountsEnabled":true,"authorizationServicesEnabled":false,"redirectUris":["*"],"defaultClientScopes":["groups"],"optionalClientScopes":["mcp:openshift"],"attributes":{"oauth2.device.authorization.grant.enabled":"false","oidc.ciba.grant.enabled":"false","backchannel.logout.session.required":"true","backchannel.logout.revoke.offline.tokens":"false"}}'); \
188+
MCP_CLIENT_CODE=$$(echo "$$MCP_CLIENT_RESPONSE" | grep -o "HTTPCODE:[0-9]*" | cut -d: -f2); \
189+
if [ "$$MCP_CLIENT_CODE" = "201" ] || [ "$$MCP_CLIENT_CODE" = "409" ]; then \
190+
if [ "$$MCP_CLIENT_CODE" = "201" ]; then echo "✅ mcp-server client created"; \
191+
else echo "✅ mcp-server client already exists"; fi; \
192+
else \
193+
echo "❌ Failed to create mcp-server client (HTTP $$MCP_CLIENT_CODE)"; \
194+
exit 1; \
195+
fi; \
196+
echo ""; \
197+
echo "Enabling token exchange for mcp-server..."; \
198+
CLIENTS_LIST=$$(curl -s -X GET "http://localhost:8090/admin/realms/openshift/clients" \
199+
-H "Authorization: Bearer $$TOKEN" \
200+
-H "Accept: application/json"); \
201+
MCP_CLIENT_ID=$$(echo "$$CLIENTS_LIST" | jq -r '.[] | select(.clientId == "mcp-server") | .id // empty' 2>/dev/null); \
202+
if [ -z "$$MCP_CLIENT_ID" ]; then \
203+
echo "❌ Failed to find mcp-server client"; \
204+
exit 1; \
205+
fi; \
206+
PERMS_RESPONSE=$$(curl -s -w "HTTPCODE:%{http_code}" -X PUT "http://localhost:8090/admin/realms/openshift/clients/$$MCP_CLIENT_ID/management/permissions" \
207+
-H "Authorization: Bearer $$TOKEN" \
208+
-H "Content-Type: application/json" \
209+
-d '{"enabled":true}'); \
210+
PERMS_CODE=$$(echo "$$PERMS_RESPONSE" | grep -o "HTTPCODE:[0-9]*" | cut -d: -f2); \
211+
if [ "$$PERMS_CODE" = "200" ]; then \
212+
echo "✅ Token exchange permissions enabled"; \
213+
else \
214+
echo "⚠️ Could not enable permissions (HTTP $$PERMS_CODE) - may need manual configuration"; \
215+
fi; \
216+
echo ""; \
217+
echo "Getting mcp-server client secret..."; \
218+
SECRET_RESPONSE=$$(curl -s -X GET "http://localhost:8090/admin/realms/openshift/clients/$$MCP_CLIENT_ID/client-secret" \
219+
-H "Authorization: Bearer $$TOKEN" \
220+
-H "Accept: application/json"); \
221+
CLIENT_SECRET=$$(echo "$$SECRET_RESPONSE" | jq -r '.value // empty' 2>/dev/null); \
222+
if [ -z "$$CLIENT_SECRET" ]; then \
223+
echo "❌ Failed to get client secret"; \
224+
else \
225+
echo "✅ Client secret retrieved"; \
226+
fi; \
227+
echo ""; \
228+
echo "Creating test user developer/developer..."; \
229+
USER_RESPONSE=$$(curl -s -w "%{http_code}" -X POST "http://localhost:8090/admin/realms/openshift/users" \
230+
-H "Authorization: Bearer $$TOKEN" \
231+
-H "Content-Type: application/json" \
232+
-d '{"username":"developer","email":"[email protected]","firstName":"Developer","lastName":"User","enabled":true,"emailVerified":true,"credentials":[{"type":"password","value":"developer","temporary":false}]}'); \
233+
USER_CODE=$$(echo "$$USER_RESPONSE" | tail -c 4); \
234+
if [ "$$USER_CODE" = "201" ] || [ "$$USER_CODE" = "409" ]; then \
235+
if [ "$$USER_CODE" = "201" ]; then echo "✅ developer user created"; \
236+
else echo "✅ developer user already exists"; fi; \
237+
else \
238+
echo "❌ Failed to create developer user (HTTP $$USER_CODE)"; \
239+
exit 1; \
240+
fi; \
241+
echo ""; \
242+
echo "🎉 OpenShift realm setup complete!"; \
243+
echo ""; \
244+
echo "========================================"; \
245+
echo "Configuration Summary"; \
246+
echo "========================================"; \
247+
echo "Realm: openshift"; \
248+
echo "Authorization URL: http://localhost:8090/realms/openshift"; \
249+
echo ""; \
250+
echo "Test User:"; \
251+
echo " Username: developer"; \
252+
echo " Password: developer"; \
253+
echo " Email: [email protected]"; \
254+
echo ""; \
255+
echo "Clients:"; \
256+
echo " mcp-server (confidential, token exchange enabled)"; \
257+
echo " Client ID: mcp-server"; \
258+
echo " Client Secret: $$CLIENT_SECRET"; \
259+
echo " openshift (service account)"; \
260+
echo " Client ID: openshift"; \
261+
echo ""; \
262+
echo "Client Scopes:"; \
263+
echo " mcp:openshift (optional) - Audience: openshift"; \
264+
echo " groups (default) - Group membership mapper"; \
265+
echo ""; \
266+
echo "TOML Configuration:"; \
267+
echo " require_oauth = true"; \
268+
echo " oauth_audience = \"mcp-server\""; \
269+
echo " authorization_url = \"http://localhost:8090/realms/openshift\""; \
270+
echo " sts_client_id = \"mcp-server\""; \
271+
echo " sts_client_secret = \"$$CLIENT_SECRET\""; \
272+
echo " sts_audience = \"openshift\""; \
273+
echo " sts_scopes = [\"mcp:openshift\"]"; \
274+
echo "========================================"

0 commit comments

Comments
 (0)