Skip to content

Commit

Permalink
feat: Implement creation and deletion of analysis keycloak clients
Browse files Browse the repository at this point in the history
  • Loading branch information
antidodo committed Apr 23, 2024
1 parent e87c841 commit 6165eb7
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 27 deletions.
2 changes: 2 additions & 0 deletions src/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from src.resources.analysis.constants import AnalysisStatus
from src.resources.database.entity import Database
from src.utils.kubernetes import get_logs, delete_deployment
from src.utils.token import delete_keycloak_client
from src.utils.other import create_image_address

router = APIRouter()
Expand Down Expand Up @@ -67,6 +68,7 @@ def delete_analysis(analysis_id: str):
deployment.stop(database)
deployment.status = AnalysisStatus.STOPPED.value
database.delete_analysis(analysis_id)
delete_keycloak_client(analysis_id)
return {"status": {deployment.deployment_name: deployment.status for deployment in deployments}}


Expand Down
108 changes: 81 additions & 27 deletions src/utils/token.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import os
import requests

import requests
from kong_admin_client import Configuration, ApiClient, ConsumersApi, ACLsApi, KeyAuthsApi
from kong_admin_client.rest import ApiException
from kong_admin_client.models.create_consumer_request import CreateConsumerRequest
from kong_admin_client.models.create_acl_for_consumer_request import (
CreateAclForConsumerRequest,
)
from kong_admin_client.models.create_consumer_request import CreateConsumerRequest
from kong_admin_client.models.create_key_auth_for_consumer_request import (
CreateKeyAuthForConsumerRequest,
)
from kong_admin_client.rest import ApiException

_KEYCLOAK_URL = os.getenv('KEYCLOAK_URL')
_KEYCLOAK_REALM = os.getenv('KEYCLOAK_REALM')


def create_tokens(analysis_id: str, project_id: str) -> dict[str, str]:
Expand All @@ -22,7 +25,7 @@ def create_tokens(analysis_id: str, project_id: str) -> dict[str, str]:
def _get_keycloak_token(analysis_id: str) -> str:
# curl -q -X POST -d "grant_type=client_credentials&client_id=service1&client_secret=9dd01665c2f3f02f93c32d03bd854569f03cd62f439ccf9f0861c141b9d6330e" http://flame-node-keycloak-service:8080/realms/flame/protocol/openid-connect/token

client_secret = _create_keycloak_client(analysis_id)
client_secret = _get_keycloak_client_secret(analysis_id)

keycloak_url = os.getenv('KEYCLOAK_URL') + "/realms/flame/protocol/openid-connect/token"
data = {"grant_type": "client_credentials", "client_id": analysis_id, "client_secret": client_secret}
Expand All @@ -31,43 +34,94 @@ def _get_keycloak_token(analysis_id: str) -> str:
try:
response = requests.post(keycloak_url, data=data)
response.raise_for_status()
print('Client token:', response.json()['access_token'])

return response.json()['access_token']
except requests.exceptions.RequestException as e:
print(e)
return None


def _create_keycloak_client(analysis_id: str) -> str:
"""
Create a client in keycloak
:return:
"""
keycloak_admin_user = os.getenv('KEYCLOAK_ADMIN_USER')
keycloak_admin_password = os.getenv('KEYCLOAK_ADMIN_PASSWORD')
keycloak_realm = os.getenv('KEYCLOAK_REALM')
keycloak_url = os.getenv('KEYCLOAK_URL')
def _get_keycloak_client_secret(analysis_id: str) -> str:
admin_token = _get_keycloak_admin_token()

if not _keycloak_client_exists(analysis_id, admin_token):
# create client
_create_keycloak_client(admin_token, analysis_id)

# get client secret
# curl -X GET -H "Authorization: Bearer $token" "http://flame-node-keycloak-service:8080/admin/realms/flame/clients?clientId=service3"
url_get_client = f"{_KEYCLOAK_URL}/admin/realms/{_KEYCLOAK_REALM}/clients?clientId={analysis_id}"
headers = {"Authorization": f"Bearer {admin_token}"}

response = requests.get(url_get_client, headers=headers)
response.raise_for_status()
print('Client secret:', response.json()['secret'])

return response.json()['secret']


def _get_keycloak_admin_token() -> str:
# curl -d "grant_type=client_credentials" -d "client_id=admin_script" -d "client_secret=RSDuBMhVIGnqEzOZjTLDjT0q5jpw5Igz" "http://flame-node-keycloak-service:8080/realms/flame/protocol/openid-connect/token"
keycloak_admin_client_id = os.getenv('KEYCLOAK_ADMIN_CLIENT_ID')
keycloak_admin_client_secret = os.getenv('KEYCLOAK_ADMIN_CLIENT_SECRET')

# get admin token
url_admin_access_token = f"{keycloak_url}/auth/realms/{keycloak_realm}/protocol/openid-connect/token"
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = {"grant_type": "password", "client_id": keycloak_admin_user, "client_secret": keycloak_admin_password}
response = requests.post(url_admin_access_token, headers=headers, data=data, verify=False)
url_admin_access_token = f"{_KEYCLOAK_URL}/realms/{_KEYCLOAK_REALM}/protocol/openid-connect/token"
data = {
"grant_type": "client_credentials",
"client_id": keycloak_admin_client_id,
"client_secret": keycloak_admin_client_secret
}
response = requests.get(url_admin_access_token, data=data)
response.raise_for_status()
admin_token = response.json()['access_token']
print('Admin token:', response.json()['access_token'])

return response.json()['access_token']

# create client
url_create_client = f"{keycloak_url}/auth/admin/realms/{keycloak_realm}/clients"

def _keycloak_client_exists(analysis_id: str, admin_token: str) -> bool:
url_get_client = f"{_KEYCLOAK_URL}/admin/realms/{_KEYCLOAK_REALM}/clients?clientId={analysis_id}"
headers = {"Authorization": f"Bearer {admin_token}"}

client_data = {
"clientId": analysis_id,
"publicClient": True, # Adjust based on your client type
}
response = requests.get(url_get_client, headers=headers)
response.raise_for_status()
print('Does client already exist:', bool(response))

return bool(response)


def _create_keycloak_client(admin_token: str, analysis_id: str) -> None:
# curl -X POST -d '{ "clientId": "service3" }' -H "Content-Type:application/json" -H "Authorization: Bearer $token" "http://flame-node-keycloak-service:8080/admin/realms/flame/clients"
url_create_client = f"{_KEYCLOAK_URL}/admin/realms/{_KEYCLOAK_REALM}/clients"
headers = {"Authorization": f"Bearer {admin_token}", "Content-Type": "application/json"}
client_data = {"clientId": analysis_id}

response = requests.post(url_create_client, headers=headers, data=client_data)
response.raise_for_status()


def delete_keycloak_client(analysis_id: str) -> None:
admin_token = _get_keycloak_admin_token()

# get client uuid
url_get_client = f"{_KEYCLOAK_URL}/admin/realms/{_KEYCLOAK_REALM}/clients?clientId={analysis_id}"
headers = {"Authorization": f"Bearer {admin_token}"}

response = requests.get(url_get_client, headers=headers)
response.raise_for_status()
try:
uuid = response.json()['id']
except KeyError:
print('Client not found')
return

# curl -X DELETE -H "Authorization: Bearer $token" "http://flame-node-keycloak-service:8080/admin/realms/flame/clients/6094fabe-823f-4cce-a251-0782be5611e3"
url_delete_client = f"{_KEYCLOAK_URL}/admin/realms/{_KEYCLOAK_REALM}/clients/{uuid}"
headers = {"Authorization": f"Bearer {admin_token}"}

response = requests.post(url_create_client, headers=headers, data=client_data , verify=False)
response = requests.delete(url_delete_client, headers=headers)
response.raise_for_status()
print(response.json())
return response.json()['client_secret']


def _get_kong_token(analysis_id: str, project_id: str) -> str:
Expand Down

0 comments on commit 6165eb7

Please sign in to comment.