<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://ebasso.net/wiki/index.php?action=history&amp;feed=atom&amp;title=IBM_CP4D%3A_Add_Service_Instance_User_Script</id>
	<title>IBM CP4D: Add Service Instance User Script - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://ebasso.net/wiki/index.php?action=history&amp;feed=atom&amp;title=IBM_CP4D%3A_Add_Service_Instance_User_Script"/>
	<link rel="alternate" type="text/html" href="https://ebasso.net/wiki/index.php?title=IBM_CP4D:_Add_Service_Instance_User_Script&amp;action=history"/>
	<updated>2026-09-16T20:31:18Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://ebasso.net/wiki/index.php?title=IBM_CP4D:_Add_Service_Instance_User_Script&amp;diff=10266&amp;oldid=prev</id>
		<title>Ebasso: Created page with &quot; == .env file ==  &lt;syntaxhighlight lang=&quot;properties&quot;&gt; # CPD cluster admin credentials # Copy this file to .env and fill in your values.  CPD_URL=cpd.apps.mycluster.example.com CPD_ADMIN_USERNAME=admin CPD_ADMIN_PASSWORD=your_admin_password_here  # Used by cpd_add_instance_user.py CPD_INSTANCE_ID=your_service_instance_id (17....) CPD_NEW_USERNAME=username_to_add CPD_NEW_UID=uid_of_user (10003...) CPD_NEW_ROLE=Admin &lt;/syntaxhighlight&gt;  == cpd_add_instance_user.py == &lt;synta...&quot;</title>
		<link rel="alternate" type="text/html" href="https://ebasso.net/wiki/index.php?title=IBM_CP4D:_Add_Service_Instance_User_Script&amp;diff=10266&amp;oldid=prev"/>
		<updated>2026-09-11T14:39:21Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot; == .env file ==  &amp;lt;syntaxhighlight lang=&amp;quot;properties&amp;quot;&amp;gt; # CPD cluster admin credentials # Copy this file to .env and fill in your values.  CPD_URL=cpd.apps.mycluster.example.com CPD_ADMIN_USERNAME=admin CPD_ADMIN_PASSWORD=your_admin_password_here  # Used by cpd_add_instance_user.py CPD_INSTANCE_ID=your_service_instance_id (17....) CPD_NEW_USERNAME=username_to_add CPD_NEW_UID=uid_of_user (10003...) CPD_NEW_ROLE=Admin &amp;lt;/syntaxhighlight&amp;gt;  == cpd_add_instance_user.py == &amp;lt;synta...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;
== .env file ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;properties&amp;quot;&amp;gt;&lt;br /&gt;
# CPD cluster admin credentials&lt;br /&gt;
# Copy this file to .env and fill in your values.&lt;br /&gt;
&lt;br /&gt;
CPD_URL=cpd.apps.mycluster.example.com&lt;br /&gt;
CPD_ADMIN_USERNAME=admin&lt;br /&gt;
CPD_ADMIN_PASSWORD=your_admin_password_here&lt;br /&gt;
&lt;br /&gt;
# Used by cpd_add_instance_user.py&lt;br /&gt;
CPD_INSTANCE_ID=your_service_instance_id (17....)&lt;br /&gt;
CPD_NEW_USERNAME=username_to_add&lt;br /&gt;
CPD_NEW_UID=uid_of_user (10003...)&lt;br /&gt;
CPD_NEW_ROLE=Admin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== cpd_add_instance_user.py ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
CPD Add Service Instance User Script&lt;br /&gt;
Authenticates against CPD, then adds a user to a service instance&lt;br /&gt;
via POST /zen-data/v2/serviceInstance/users using a ZenApiKey token.&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
import os&lt;br /&gt;
import sys&lt;br /&gt;
import urllib.request&lt;br /&gt;
import urllib.error&lt;br /&gt;
import ssl&lt;br /&gt;
import getpass&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# ---------------------------------------------------------------------------&lt;br /&gt;
# Shared helpers (same pattern as cpd_create_user.py)&lt;br /&gt;
# ---------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
def load_env(path: str = &amp;quot;.env&amp;quot;) -&amp;gt; None:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Parse a .env file and populate os.environ (no external dependencies).&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    try:&lt;br /&gt;
        with open(path) as fh:&lt;br /&gt;
            for line in fh:&lt;br /&gt;
                line = line.strip()&lt;br /&gt;
                if not line or line.startswith(&amp;quot;#&amp;quot;) or &amp;quot;=&amp;quot; not in line:&lt;br /&gt;
                    continue&lt;br /&gt;
                key, _, value = line.partition(&amp;quot;=&amp;quot;)&lt;br /&gt;
                value = value.strip().strip(&amp;quot;\&amp;quot;&amp;#039;&amp;quot;)&lt;br /&gt;
                os.environ.setdefault(key.strip(), value)&lt;br /&gt;
    except FileNotFoundError:&lt;br /&gt;
        pass  # .env is optional&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def _ssl_ctx() -&amp;gt; ssl.SSLContext:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Return an SSL context with certificate verification disabled (mirrors curl -k).&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ctx = ssl.create_default_context()&lt;br /&gt;
    ctx.check_hostname = False&lt;br /&gt;
    ctx.verify_mode = ssl.CERT_NONE&lt;br /&gt;
    return ctx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def prompt(label: str, secret: bool = False) -&amp;gt; str:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Prompt interactively; hide input when secret=True.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if secret:&lt;br /&gt;
        return getpass.getpass(f&amp;quot;{label}: &amp;quot;)&lt;br /&gt;
    value = input(f&amp;quot;{label}: &amp;quot;).strip()&lt;br /&gt;
    if not value:&lt;br /&gt;
        print(f&amp;quot;[ERROR] &amp;#039;{label}&amp;#039; cannot be empty.&amp;quot;, file=sys.stderr)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
    return value&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# ---------------------------------------------------------------------------&lt;br /&gt;
# API calls&lt;br /&gt;
# ---------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
def get_bearer_token(cpd_url: str, admin_user: str, admin_password: str) -&amp;gt; str:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Authenticate and return the Bearer token.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    url = f&amp;quot;https://{cpd_url}/icp4d-api/v1/authorize&amp;quot;&lt;br /&gt;
    payload = json.dumps({&amp;quot;username&amp;quot;: admin_user, &amp;quot;password&amp;quot;: admin_password}).encode()&lt;br /&gt;
&lt;br /&gt;
    req = urllib.request.Request(&lt;br /&gt;
        url,&lt;br /&gt;
        data=payload,&lt;br /&gt;
        headers={&amp;quot;Content-Type&amp;quot;: &amp;quot;application/json&amp;quot;},&lt;br /&gt;
        method=&amp;quot;POST&amp;quot;,&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        with urllib.request.urlopen(req, context=_ssl_ctx()) as resp:&lt;br /&gt;
            body = json.loads(resp.read().decode())&lt;br /&gt;
    except urllib.error.HTTPError as exc:&lt;br /&gt;
        print(f&amp;quot;[ERROR] Authentication failed ({exc.code}): {exc.read().decode()}&amp;quot;, file=sys.stderr)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    token = body.get(&amp;quot;token&amp;quot;)&lt;br /&gt;
    if not token:&lt;br /&gt;
        print(f&amp;quot;[ERROR] No token in response: {body}&amp;quot;, file=sys.stderr)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    return token&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def list_instance_users(cpd_url: str, zen_token: str, instance_id: str) -&amp;gt; list:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;List all users of a CPD service instance.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    url = f&amp;quot;https://{cpd_url}/zen-data/v2/serviceInstance/users?sID={instance_id}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    req = urllib.request.Request(&lt;br /&gt;
        url,&lt;br /&gt;
        headers={&lt;br /&gt;
            &amp;quot;Authorization&amp;quot;: f&amp;quot;Bearer {zen_token}&amp;quot;,&lt;br /&gt;
            &amp;quot;Accept&amp;quot;: &amp;quot;application/json&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        method=&amp;quot;GET&amp;quot;,&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        with urllib.request.urlopen(req, context=_ssl_ctx()) as resp:&lt;br /&gt;
            body = json.loads(resp.read().decode())&lt;br /&gt;
    except urllib.error.HTTPError as exc:&lt;br /&gt;
        print(f&amp;quot;[ERROR] List instance users failed ({exc.code}): {exc.read().decode()}&amp;quot;, file=sys.stderr)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    # The API may return {&amp;quot;users&amp;quot;: [...]} or a bare list or another structure.&lt;br /&gt;
    # Print raw response to help diagnose unexpected shapes.&lt;br /&gt;
    if &amp;quot;users&amp;quot; not in body:&lt;br /&gt;
        print(f&amp;quot;      [DEBUG] Raw response: {json.dumps(body, indent=2)}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
    users = body.get(&amp;quot;users&amp;quot;, [])&lt;br /&gt;
    # Guard: keep only dict entries so we never crash on unexpected types.&lt;br /&gt;
    return [u for u in users if isinstance(u, dict)]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def add_instance_user(&lt;br /&gt;
    cpd_url: str,&lt;br /&gt;
    zen_token: str,&lt;br /&gt;
    instance_id: str,&lt;br /&gt;
    username: str,&lt;br /&gt;
    uid: str,&lt;br /&gt;
    role: str,&lt;br /&gt;
) -&amp;gt; dict:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Add a user to a CPD service instance and return the API response.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    url = f&amp;quot;https://{cpd_url}/zen-data/v2/serviceInstance/users&amp;quot;&lt;br /&gt;
    payload = json.dumps(&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;serviceInstanceID&amp;quot;: instance_id,&lt;br /&gt;
            &amp;quot;users&amp;quot;: [&lt;br /&gt;
                {&lt;br /&gt;
                    &amp;quot;role&amp;quot;: role,&lt;br /&gt;
                    &amp;quot;uid&amp;quot;: uid,&lt;br /&gt;
                    &amp;quot;username&amp;quot;: username,&lt;br /&gt;
                }&lt;br /&gt;
            ],&lt;br /&gt;
        }&lt;br /&gt;
    ).encode()&lt;br /&gt;
&lt;br /&gt;
    req = urllib.request.Request(&lt;br /&gt;
        url,&lt;br /&gt;
        data=payload,&lt;br /&gt;
        headers={&lt;br /&gt;
            &amp;quot;Authorization&amp;quot;: f&amp;quot;Bearer {zen_token}&amp;quot;,&lt;br /&gt;
            &amp;quot;Content-Type&amp;quot;: &amp;quot;application/json&amp;quot;,&lt;br /&gt;
        },&lt;br /&gt;
        method=&amp;quot;POST&amp;quot;,&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        with urllib.request.urlopen(req, context=_ssl_ctx()) as resp:&lt;br /&gt;
            return json.loads(resp.read().decode())&lt;br /&gt;
    except urllib.error.HTTPError as exc:&lt;br /&gt;
        print(f&amp;quot;[ERROR] Add instance user failed ({exc.code}): {exc.read().decode()}&amp;quot;, file=sys.stderr)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# ---------------------------------------------------------------------------&lt;br /&gt;
# Entry point&lt;br /&gt;
# ---------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
def main() -&amp;gt; None:&lt;br /&gt;
    load_env()&lt;br /&gt;
    print(&amp;quot;=== IBM Cloud Pak for Data — Add Service Instance User ===\n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # --- Cluster / admin credentials (.env → interactive fallback) ---&lt;br /&gt;
    cpd_url    = os.environ.get(&amp;quot;CPD_URL&amp;quot;)            or prompt(&amp;quot;CPD Route URL (without https://)&amp;quot;)&lt;br /&gt;
    admin_user = os.environ.get(&amp;quot;CPD_ADMIN_USERNAME&amp;quot;) or (input(&amp;quot;CPD admin username [admin]: &amp;quot;).strip() or &amp;quot;admin&amp;quot;)&lt;br /&gt;
    admin_pass = os.environ.get(&amp;quot;CPD_ADMIN_PASSWORD&amp;quot;) or prompt(&amp;quot;CPD admin password&amp;quot;, secret=True)&lt;br /&gt;
&lt;br /&gt;
    # --- Step 1: fetch Bearer / ZenApiKey token ---&lt;br /&gt;
    print(&amp;quot;\n[1/2] Fetching Bearer token...&amp;quot;)&lt;br /&gt;
    token = get_bearer_token(cpd_url, admin_user, admin_pass)&lt;br /&gt;
    print(f&amp;quot;      Token obtained (first 40 chars): {token[:40]}...&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # --- Service instance user details (required from environment / .env) ---&lt;br /&gt;
    instance_id = os.environ.get(&amp;quot;CPD_INSTANCE_ID&amp;quot;) or prompt(&amp;quot;Service Instance ID&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def require_env(var: str) -&amp;gt; str:&lt;br /&gt;
        value = os.environ.get(var, &amp;quot;&amp;quot;).strip()&lt;br /&gt;
        if not value:&lt;br /&gt;
            print(f&amp;quot;[ERROR] Environment variable &amp;#039;{var}&amp;#039; is required but not set.&amp;quot;, file=sys.stderr)&lt;br /&gt;
            sys.exit(1)&lt;br /&gt;
        return value&lt;br /&gt;
&lt;br /&gt;
    # --- Step 2: list current users ---&lt;br /&gt;
    print(&amp;quot;\n[2/3] Current users in service instance...&amp;quot;)&lt;br /&gt;
    current_users = list_instance_users(cpd_url, token, instance_id)&lt;br /&gt;
    if current_users:&lt;br /&gt;
        print(f&amp;quot;      {&amp;#039;USERNAME&amp;#039;:&amp;lt;30} {&amp;#039;UID&amp;#039;:&amp;lt;20} ROLE&amp;quot;)&lt;br /&gt;
        print(f&amp;quot;      {&amp;#039;-&amp;#039;*30} {&amp;#039;-&amp;#039;*20} {&amp;#039;-&amp;#039;*20}&amp;quot;)&lt;br /&gt;
        for u in current_users:&lt;br /&gt;
            print(f&amp;quot;      {u.get(&amp;#039;username&amp;#039;, u):&amp;lt;30} {str(u.get(&amp;#039;uid&amp;#039;, &amp;#039;&amp;#039;)):&amp;lt;20} {u.get(&amp;#039;role&amp;#039;, &amp;#039;&amp;#039;)}&amp;quot;)&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;      (no users found)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    username = os.environ.get(&amp;quot;CPD_NEW_USERNAME&amp;quot;, &amp;quot;&amp;quot;).strip()&lt;br /&gt;
    uid      = require_env(&amp;quot;CPD_NEW_UID&amp;quot;)&lt;br /&gt;
    role     = require_env(&amp;quot;CPD_NEW_ROLE&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # --- Step 3: add user to instance (skip if CPD_NEW_USERNAME is empty) ---&lt;br /&gt;
    if not username:&lt;br /&gt;
        print(&amp;quot;\n[3/3] CPD_NEW_USERNAME not set — skipping add user step.&amp;quot;)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    print(&amp;quot;\n[3/3] Adding user to service instance...&amp;quot;)&lt;br /&gt;
    result = add_instance_user(&lt;br /&gt;
        cpd_url=cpd_url,&lt;br /&gt;
        zen_token=token,&lt;br /&gt;
        instance_id=instance_id,&lt;br /&gt;
        username=username,&lt;br /&gt;
        uid=uid,&lt;br /&gt;
        role=role,&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    print(&amp;quot;\n[OK] User added to service instance successfully.&amp;quot;)&lt;br /&gt;
    print(json.dumps(result, indent=2))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Ver também =&lt;br /&gt;
&lt;br /&gt;
[[Category:Cognos]]&lt;br /&gt;
[[Category:CP4D]]&lt;br /&gt;
[[Category:IBM Maximo]]&lt;br /&gt;
[[Category:IBM MAS]]&lt;/div&gt;</summary>
		<author><name>Ebasso</name></author>
	</entry>
</feed>