Open sebght opened 9 months ago
I've been struggling with this exat configuration. Thanks for the PR !
My tests have led me to think that the option is changed to false
until it's not explicitly given to the API... This means everytime you terraform apply
your client resource, it will set it back to false
...
Kind of a thorn in the side for ppl I guess (for me it is 😅). Should we consider a v4.4.1
@mrparkers ?
Nevermind, I did more precise tests and they prove that the option is not overwritten every apply
. Sorry for the spamming !
Hi @sebght ! Thanks for working on adding support for this option Any chance this could be merged soon? This would help a lot in my current project 🙂
Good job @sebght, can't wait to see that released! 🚀
Well the repository is quite on pause currently, but I hope that this will change and that this PR will move on ! Follow the news here : https://github.com/mrparkers/terraform-provider-keycloak/issues/964
Hello @sebght, Thank you for the merge request. We're currently encountering this issue after upgrading Keycloak to the latest version. Is there any chance this could be merged soon? In the meantime, we've created a script as a workaround until an official release is available.
import requests
import argparse
import logging
from typing import List, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
def get_token(idp_host: str, username: str, password: str) -> Optional[str]:
"""Get access token from the Identity Provider"""
url = f"{idp_host}/realms/master/protocol/openid-connect/token"
payload = {
"username": username,
"password": password,
"grant_type": "password",
"client_id": "admin-cli",
}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
response = requests.post(url, data=payload, headers=headers)
if response.status_code == 200:
logger.info("Successfully obtained token")
return response.json().get("access_token")
else:
logger.error(f"Failed to get token: {response.status_code}, {response.text}")
return None
def get_realms(idp_host: str, token: str) -> List[str]:
"""Fetch a list of realms"""
url = f"{idp_host}/admin/realms"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
logger.info("Successfully fetched realms")
realms = response.json()
return [realm["realm"] for realm in realms]
else:
logger.error(f"Failed to fetch realms: {response.status_code}, {response.text}")
return []
def get_client_ids(idp_host: str, realm: str, token: str) -> List[str]:
"""Fetch client IDs that contain 'ui' in their clientId"""
url = f"{idp_host}/admin/realms/{realm}/clients"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
logger.info(f"Successfully fetched clients for realm {realm}")
clients = response.json()
return [client["id"] for client in clients if "ui" in client["clientId"]]
else:
logger.error(f"Failed to fetch clients for realm {realm}: {response.status_code}, {response.text}")
return []
def update_client(idp_host: str, realm: str, client_id: str, token: str) -> None:
"""Update the client's attribute to exclude issuer from the URL"""
url = f"{idp_host}/admin/realms/{realm}/clients/{client_id}"
headers = {"Authorization": f"Bearer {token}"}
# Fetch client details
response = requests.get(url, headers=headers)
if response.status_code == 200:
client_details = response.json()
client_name = client_details["clientId"]
logger.info(f"Updating client {client_name} in realm {realm}...")
# Update client attribute
client_details["attributes"]["exclude.issuer.from.auth.response"] = "true"
# Send the updated client details
update_response = requests.put(
url, headers=headers, json=client_details
)
if update_response.status_code == 204:
logger.info(f"Client {client_name} updated successfully.")
else:
logger.error(
f"Failed to update client {client_name}: {update_response.status_code}, {update_response.text}")
else:
logger.error(f"Failed to fetch client details: {response.status_code}, {response.text}")
def main(idp_host: str, username: str, password: str) -> None:
"""Main function to handle the logic of fetching realms and updating clients"""
token = get_token(idp_host, username, password)
if not token:
logger.error("Failed to retrieve token. Exiting.")
return
realms = get_realms(idp_host, token)
if not realms:
logger.error("No realms found. Exiting.")
return
for realm in realms:
logger.info(f"Processing realm: {realm}")
client_ids = get_client_ids(idp_host, realm, token)
for client_id in client_ids:
update_client(idp_host, realm, client_id, token)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Keycloak Client Attribute Updater")
parser.add_argument("--host", required=True, help="Identity Provider host URL")
parser.add_argument("-u", "--username", required=True, help="Username for authentication")
parser.add_argument("-p", "--password", required=True, help="Password for authentication")
args = parser.parse_args()
main(args.host, args.username, args.password)
Solves https://github.com/mrparkers/terraform-provider-keycloak/issues/928
What has been changed :
ExcludeIssuerFromAuthResponse
attribute in the clientExcludeIssuerFromAuthResponse
attributeopenid_client
also returns this attribute