IBM CP4D: Creating a Cognos Analytics administrator for publishing packages

From Wiki
Jump to navigation Jump to search

Has this https://www.ibm.com/docs/en/maximo-manage/cd?topic=server-creating-cognos-analytics-administrator-publishing-packages

But i prefer a python script:

.env file

# 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

cpd_create_user.py

#!/usr/bin/env python3
"""
CPD Create User Script
Automates Bearer Token retrieval and CPD user creation via the IBM Cloud Pak for Data API.
"""

import json
import os
import sys
import urllib.request
import urllib.error
import ssl
import getpass


def get_bearer_token(cpd_url: str, admin_user: str, admin_password: str) -> str:
    """Authenticate against CPD and return the Bearer token."""
    url = f"https://{cpd_url}/icp4d-api/v1/authorize"
    payload = json.dumps({"username": admin_user, "password": admin_password}).encode("utf-8")

    req = urllib.request.Request(
        url,
        data=payload,
        headers={"Content-Type": "application/json"},
        method="POST",
    )

    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE

    try:
        with urllib.request.urlopen(req, context=ctx) as resp:
            body = json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as exc:
        print(f"[ERROR] Authentication failed ({exc.code}): {exc.read().decode()}", file=sys.stderr)
        sys.exit(1)

    token = body.get("token")
    if not token:
        print(f"[ERROR] No token in response: {body}", file=sys.stderr)
        sys.exit(1)

    return token


def create_cpd_user(
    cpd_url: str,
    bearer_token: str,
    username: str,
    password: str,
    display_name: str,
    email: str,
    roles: list[str],
) -> dict:
    """Create a new CPD user and return the API response body."""
    url = f"https://{cpd_url}/usermgmt/v1/user"
    payload = json.dumps(
        {
            "username": username,
            "password": password,
            "displayName": display_name,
            "email": email,
            "user_roles": roles,
        }
    ).encode("utf-8")

    req = urllib.request.Request(
        url,
        data=payload,
        headers={
            "Authorization": f"Bearer {bearer_token}",
            "Content-Type": "application/json",
        },
        method="POST",
    )

    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE

    try:
        with urllib.request.urlopen(req, context=ctx) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as exc:
        print(f"[ERROR] User creation failed ({exc.code}): {exc.read().decode()}", file=sys.stderr)
        sys.exit(1)


def load_env(path: str = ".env") -> None:
    """Parse a .env file and populate os.environ (no external dependencies)."""
    try:
        with open(path) as fh:
            for line in fh:
                line = line.strip()
                if not line or line.startswith("#") or "=" not in line:
                    continue
                key, _, value = line.partition("=")
                # Strip optional surrounding quotes
                value = value.strip().strip("\"'")
                os.environ.setdefault(key.strip(), value)
    except FileNotFoundError:
        pass  # .env is optional


def prompt(label: str, secret: bool = False) -> str:
    """Prompt the user for input, hiding the value when secret=True."""
    if secret:
        return getpass.getpass(f"{label}: ")
    value = input(f"{label}: ").strip()
    if not value:
        print(f"[ERROR] '{label}' cannot be empty.", file=sys.stderr)
        sys.exit(1)
    return value


def main() -> None:
    load_env()
    print("=== IBM Cloud Pak for Data — Create CPD User ===\n")

    # --- CPD cluster details (prefer .env, fall back to interactive prompt) ---
    cpd_url    = os.environ.get("CPD_URL")    or prompt("CPD Route URL (without https://)")
    admin_user = os.environ.get("CPD_ADMIN_USERNAME") or (input("CPD admin username [admin]: ").strip() or "admin")
    admin_pass = os.environ.get("CPD_ADMIN_PASSWORD") or prompt("CPD admin password", secret=True)

    # --- Step 1: fetch Bearer token ---
    print("\n[1/2] Fetching Bearer token...")
    token = get_bearer_token(cpd_url, admin_user, admin_pass)
    print(f"      Token obtained (first 40 chars): {token[:40]}...")

    # --- New user details ---
    print("\nNew user details:")
    new_username     = prompt("Username")
    new_password     = prompt("Password", secret=True)
    new_display_name = prompt("Display name")
    new_email        = prompt("Email")

    roles_input = input("Roles (comma-separated) [User,Administrator]: ").strip()
    roles = [r.strip() for r in roles_input.split(",")] if roles_input else ["User", "Administrator"]

    # --- Step 2: create user ---
    print("\n[2/2] Creating CPD user...")
    result = create_cpd_user(
        cpd_url=cpd_url,
        bearer_token=token,
        username=new_username,
        password=new_password,
        display_name=new_display_name,
        email=new_email,
        roles=roles,
    )

    print("\n[OK] User created successfully.")
    print(json.dumps(result, indent=2))


if __name__ == "__main__":
    main()


Ver também