132 lines
4.6 KiB
YAML
132 lines
4.6 KiB
YAML
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: zitadel-action-create-user
|
|
namespace: django
|
|
data:
|
|
createUser.js: |
|
|
function createUser(ctx, api) {
|
|
let http = require('zitadel/http');
|
|
let logger = require('zitadel/log');
|
|
|
|
const BACKEND_HOST = 'http://backend-svc.django.svc.cluster.local:80/api'
|
|
const USER_COMPANIES = [1]
|
|
|
|
const BASIC_AUTH = '__BASIC_AUTH__'
|
|
|
|
logger.log('Creating external user in backend');
|
|
logger.log('Context: ' + JSON.stringify(ctx));
|
|
|
|
const userData = {
|
|
first_name: ctx.v1.user.human.firstName,
|
|
last_name: ctx.v1.user.human.lastName,
|
|
email: ctx.v1.user.human.email,
|
|
username: ctx.v1.user.username,
|
|
companies: USER_COMPANIES,
|
|
departments: [],
|
|
user_permissions: []
|
|
};
|
|
|
|
logger.log('Sending user data: ' + JSON.stringify(userData));
|
|
|
|
const response = http.fetch(BACKEND_HOST + '/core/admin/users/external/', {
|
|
method: 'POST',
|
|
body: userData,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': BASIC_AUTH
|
|
}
|
|
});
|
|
|
|
if (response.status != 200 && response.status != 201) {
|
|
logger.log('Error response status: ' + response.status);
|
|
logger.log('Error response body: ' + response.text());
|
|
throw "Backend API error: " + response.status;
|
|
}
|
|
|
|
const metadata = response.json();
|
|
|
|
logger.log('Metadata received: ' + JSON.stringify(metadata));
|
|
|
|
Object.keys(metadata).forEach(function(key) {
|
|
var value = metadata[key];
|
|
logger.log('Setting metadata - Key: ' + key + ', Value: ' + value);
|
|
api.v1.user.appendMetadata(key, value);
|
|
});
|
|
|
|
logger.log('External user successfully created and metadata set');
|
|
}
|
|
apply.py: |
|
|
import os
|
|
import sys
|
|
|
|
import httpx
|
|
|
|
ZITADEL = os.environ["ZITADEL_URL"]
|
|
HEADERS = {
|
|
"Host": os.environ["ZITADEL_HOST"],
|
|
"X-Forwarded-Proto": "https",
|
|
"Authorization": "Bearer " + open("/vault/secrets/zitadel-token").read().strip(),
|
|
"Content-Type": "application/json",
|
|
}
|
|
ORG_NAME = os.environ["ZITADEL_ORG_NAME"]
|
|
ACTION_NAME = os.environ["ACTION_NAME"]
|
|
FLOW_TYPE = os.environ["FLOW_TYPE"]
|
|
TRIGGER_TYPE = os.environ["TRIGGER_TYPE"]
|
|
|
|
client = httpx.Client(base_url=ZITADEL, headers=HEADERS, timeout=30)
|
|
|
|
|
|
def call(method, path, body=None, org_id=None, allow=()):
|
|
headers = {"x-zitadel-orgid": org_id} if org_id else {}
|
|
r = client.request(method, path, json=body, headers=headers)
|
|
if r.status_code in allow:
|
|
return None
|
|
if r.status_code >= 300:
|
|
print(f"{method} {path} -> {r.status_code}: {r.text}")
|
|
sys.exit(1)
|
|
return r.json() if r.content else {}
|
|
|
|
|
|
me = call("GET", "/auth/v1/users/me")["user"]
|
|
print(f"token user {me.get('userName')} id={me.get('id')}")
|
|
|
|
org = None
|
|
found_orgs = call("POST", "/admin/v1/orgs/_search", {"queries": []}, allow=(403,))
|
|
if found_orgs is not None:
|
|
orgs = found_orgs.get("result", [])
|
|
org = next((o for o in orgs if o.get("name", "").lower() == ORG_NAME.lower()), None)
|
|
if org is None:
|
|
print(f"org '{ORG_NAME}' not found, available: {[o.get('name') for o in orgs]}")
|
|
sys.exit(1)
|
|
else:
|
|
org = call("GET", "/management/v1/orgs/me")["org"]
|
|
print(f"no instance permissions, using token org '{org.get('name')}'")
|
|
if org.get("name", "").lower() != ORG_NAME.lower():
|
|
print(f"token org is '{org.get('name')}', not '{ORG_NAME}'")
|
|
sys.exit(1)
|
|
org_id = org["id"]
|
|
print(f"org {org['name']} id={org_id}")
|
|
|
|
script = open("/opt/action/createUser.js").read().replace(
|
|
"__BASIC_AUTH__", "Basic " + open("/vault/secrets/backend-basic").read().strip()
|
|
)
|
|
body = {"name": ACTION_NAME, "script": script, "timeout": "10s", "allowedToFail": False}
|
|
|
|
found = call(
|
|
"POST",
|
|
"/management/v1/actions/_search",
|
|
{"queries": [{"actionNameQuery": {"name": ACTION_NAME, "method": "TEXT_QUERY_METHOD_EQUALS"}}]},
|
|
org_id,
|
|
).get("result", [])
|
|
if found:
|
|
action_id = found[0]["id"]
|
|
call("PUT", f"/management/v1/actions/{action_id}", body, org_id)
|
|
print(f"action {ACTION_NAME} updated id={action_id}")
|
|
else:
|
|
action_id = call("POST", "/management/v1/actions", body, org_id)["id"]
|
|
print(f"action {ACTION_NAME} created id={action_id}")
|
|
|
|
call("POST", f"/management/v1/flows/{FLOW_TYPE}/trigger/{TRIGGER_TYPE}", {"actionIds": [action_id]}, org_id)
|
|
print(f"flow {FLOW_TYPE} trigger {TRIGGER_TYPE} -> {ACTION_NAME}")
|