From c0e596dcc0e4df1e11349a77c0c3d080f509afa3 Mon Sep 17 00:00:00 2001 From: amitpandey Date: Fri, 6 Feb 2026 16:11:43 +0530 Subject: [PATCH 01/11] RDS post provisioning Testing --- .../120-ibm-dbs-rds-database/README.md | 229 ++++++++++- .../templates/00-configmap.yaml | 59 +++ .../templates/01-dbs-rds-postsync-setup.yaml | 18 + .../120-ibm-dbs-rds-database/values.yaml | 24 +- .../00-presync-create-db2-rds-user_Job.yaml | 356 ++++++++++++++++++ .../templates/120-db2-databases-app.yaml | 2 + .../templates/120-dbs-rds-databases-app.yaml | 52 ++- 7 files changed, 734 insertions(+), 6 deletions(-) create mode 100644 instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user_Job.yaml diff --git a/instance-applications/120-ibm-dbs-rds-database/README.md b/instance-applications/120-ibm-dbs-rds-database/README.md index db8bafb2e..efdda781b 100644 --- a/instance-applications/120-ibm-dbs-rds-database/README.md +++ b/instance-applications/120-ibm-dbs-rds-database/README.md @@ -1,3 +1,226 @@ -IBM DB2U Database -=============================================================================== -Create a Db2RDS database for a MAS app. \ No newline at end of file +# IBM DB2 RDS Database Configuration + +This Helm chart configures and initializes IBM DB2 RDS databases for MAS applications. + +## Overview + +The chart performs the following operations: +1. Creates bufferpools and tablespaces for MAS applications (Manage, Facilities, IoT) +2. Applies DB2 instance registry settings +3. Applies DB2 database configuration parameters +4. Applies DB2 instance DBM configuration +5. Configures DB2 audit settings (optional) + +## Configuration Values + +### Basic Connection Configuration + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `rds_admin_db_name` | RDS admin database name | `"rdsadmin"` | +| `host` | Database host endpoint | `"xyz.db"` | +| `port` | Database port | `50000` | +| `dbname` | Target database name | `"rds1"` | +| `user` | Database username | `"dummy"` | +| `password` | Database password | `"dummy"` | + +### Additional Configuration + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `db2_namespace` | DB2 namespace identifier | `""` | +| `mas_application_id` | MAS application ID (manage, facilities, iot) | `""` | +| `jdbc_connection_url` | JDBC connection URL | `""` | +| `replica_db` | Whether this is a replica database | `false` | + +### MAS Application-Specific Configuration + +The `mas_application_id` field determines which bufferpools, tablespaces, and configurations are created: + +#### Manage +- **Bufferpools**: MAXBUFPOOL, MAXBUFPOOLINDX, MAXTEMPBP +- **Tablespaces**: MAXDATA, MAXINDEX, MAXTEMP +- **Recommended Settings**: + - `DB2_WORKLOAD=MAXIMO` + - `AUTO_MAINT=OFF` + - `AUTO_TBL_MAINT=OFF` + - `LOCKTIMEOUT=300` + - `DATABASE_MEMORY=2199408 AUTOMATIC` + +#### Facilities (TRIRIGA) +- **Bufferpools**: TRIBUFPOOL, TRIBUFPOOLINDEX, TRITEMPBP, DEDICATEDBPDATA, DEDICATEDBPINDX, DEDICATEDBPLOB +- **Tablespaces**: TRIDATA_DATA, TRIDATA_INDX, TRITEMP (temp), DEDICATED_DATA, DEDICATED_INDEX, DEDICATED_LOBS +- **Recommended Settings**: + - `DB2_COMPATIBILITY_VECTOR=ORA` + - `DB2_PARALLEL_IO=*` + - `DB2_DEFERRED_PREPARE_SEMANTICS=YES` + - `CATALOGCACHE_SZ=2048` + - `LOCKTIMEOUT=30` + +#### IoT +- **Bufferpools**: Uses default bufferpools +- **Tablespaces**: Uses default tablespaces +- **Recommended Settings**: Default DB2 settings with auto-maintenance enabled + +### DB2 Instance Registry Configuration + +Configure DB2 instance registry variables. Example: + +```yaml +db2_instance_registry: + DB2_COMPATIBILITY_VECTOR: "ORA" + DB2_PARALLEL_IO: "*" + DB2_DEFERRED_PREPARE_SEMANTICS: "YES" + DB2_WORKLOAD: "MAXIMO" + DB2_SKIPINSERTED: "ON" + DB2AUTH: "OSAUTHDB,ALLOW_LOCAL_FALLBACK,PLUGIN_AUTO_RELOAD" +``` + +### DB2 Database Configuration + +Configure database-level parameters. Example: + +```yaml +db2_database_db_config: + AUTO_MAINT: "OFF" + AUTO_TBL_MAINT: "OFF" + CATALOGCACHE_SZ: "800" + LOCKTIMEOUT: "300" + LOGSECOND: "100" + STMTHEAP: "20000 AUTOMATIC" + DATABASE_MEMORY: "2199408 AUTOMATIC" +``` + +### DB2 Instance DBM Configuration + +Configure instance-level DBM parameters. Example: + +```yaml +db2_instance_dbm_config: + AGENT_STACK_SZ: "1024" + RQRIOBLK: "65535" + DFT_MON_STMT: "ON" + MON_HEAP_SZ: "AUTOMATIC" +``` + +### DB2 Audit Configuration + +Configure audit settings. Example: + +```yaml +db2_addons_audit_config: + enableAudit: true + applyDefaultPolicy: true +``` + +## Templates + +### 00-configmap.yaml +Creates a ConfigMap with Python script that performs all DB2 RDS initialization and configuration: +- Creates bufferpools and tablespaces based on MAS application type +- Applies DB2 instance registry settings using `CALL rdsadmin.update_db_param('database_name', 'key', 'value')` +- Applies DB2 database configuration using `CALL rdsadmin.update_db_param('database_name', 'key', 'value')` +- Applies DB2 instance DBM configuration using `CALL rdsadmin.update_db_param('database_name', 'key', 'value')` +- Configures DB2 audit settings using `CALL rdsadmin.update_db_param('database_name', 'AUDIT_BUF_SZ', '1000')` + +### 01-dbs-rds-postsync-setup.yaml +Job that runs the initialization script: +- **Sync Wave**: 136 +- Creates secret with database credentials +- Executes the Python script from ConfigMap +- Passes all configuration values as environment variables (JSON format) +- Downloads RDS SSL certificate for secure connections + +## Usage + +This chart is typically deployed via the root application at: +`root-applications/ibm-mas-instance-root/templates/120-dbs-rds-databases-app.yaml` + +The root application iterates over `ibm_dbs_rds_databases` configuration and creates a separate ArgoCD Application for each database instance, passing all configuration values to this chart. + +### Example Configurations + +#### Manage Database +```yaml +ibm_dbs_rds_databases: + - db2_namespace: rds-inst8 + db2_instance_name: rds-inst8-manage + mas_application_id: manage + host: "db2-rds-endpoint.us-east-1.rds.amazonaws.com" + port: 50000 + dbname: "MAXDB80" + rds_admin_db_name: "rdsadmin" + user: "db2inst1" + password: "" + replica_db: false + db2_instance_registry: + DB2_WORKLOAD: "MAXIMO" + DB2_SKIPINSERTED: "ON" + db2_database_db_config: + AUTO_MAINT: "OFF" + LOCKTIMEOUT: "300" + db2_addons_audit_config: + enableAudit: true + applyDefaultPolicy: true +``` + +#### Facilities Database +```yaml +ibm_dbs_rds_databases: + - db2_namespace: rds-inst8 + db2_instance_name: rds-inst8-facilities + mas_application_id: facilities + host: "db2-rds-endpoint.us-east-1.rds.amazonaws.com" + port: 50000 + dbname: "TRIDB80" + rds_admin_db_name: "rdsadmin" + user: "db2inst1" + password: "" + replica_db: true + db2_instance_registry: + DB2_COMPATIBILITY_VECTOR: "ORA" + DB2_PARALLEL_IO: "*" + db2_database_db_config: + CATALOGCACHE_SZ: "2048" + LOCKTIMEOUT: "30" + db2_addons_audit_config: + enableAudit: true + applyDefaultPolicy: true +``` + +#### IoT Database +```yaml +ibm_dbs_rds_databases: + - db2_namespace: rds-inst8 + db2_instance_name: rds-inst8-iot + mas_application_id: iot + host: "db2-rds-endpoint.us-east-1.rds.amazonaws.com" + port: 50000 + dbname: "IOTDB80" + rds_admin_db_name: "rdsadmin" + user: "db2inst1" + password: "" + replica_db: false + db2_addons_audit_config: + enableAudit: true + applyDefaultPolicy: true +``` + +## Sync Waves + +The chart uses ArgoCD sync waves to ensure proper ordering: + +1. **Wave 135**: ConfigMap with comprehensive initialization and configuration script +2. **Wave 136**: Secret and job that executes all DB2 setup: + - Creates bufferpools and tablespaces + - Applies DB2 instance registry settings + - Applies DB2 database configuration + - Applies DB2 instance DBM configuration + - Configures audit settings (if enabled) + +## Notes + +- All jobs are idempotent and can be safely re-run +- Jobs use the `mas.ibm.com/job-cleanup-group` label for automatic cleanup +- SSL/TLS is enforced for all database connections +- The RDS global certificate bundle is automatically downloaded \ No newline at end of file diff --git a/instance-applications/120-ibm-dbs-rds-database/templates/00-configmap.yaml b/instance-applications/120-ibm-dbs-rds-database/templates/00-configmap.yaml index 8bf9424b3..91de39b7b 100644 --- a/instance-applications/120-ibm-dbs-rds-database/templates/00-configmap.yaml +++ b/instance-applications/120-ibm-dbs-rds-database/templates/00-configmap.yaml @@ -189,5 +189,64 @@ data: else: print("āœ… All bufferpools and tablespaces already existed or not created — please check.") + # 3. Apply DB2 Instance Registry Configuration + db2_instance_registry = os.environ.get('DB2_INSTANCE_REGISTRY', '') + if db2_instance_registry: + print("\nšŸ“ Applying DB2 Instance Registry settings...") + import json + registry = json.loads(db2_instance_registry) + for key, value in registry.items(): + try: + sql = f"CALL rdsadmin.update_db_param('{database_name}', '{key}', '{value}')" + db2.exec_immediate(admin_conn, sql) + print(f" āœ… Set {key} = {value}") + except Exception as e: + print(f" āš ļø Failed to set {key}: {e}") + + # 4. Apply DB2 Database Configuration + db2_database_config = os.environ.get('DB2_DATABASE_CONFIG', '') + if db2_database_config: + print("\nšŸ“ Applying DB2 Database Configuration settings...") + import json + config = json.loads(db2_database_config) + for key, value in config.items(): + try: + sql = f"CALL rdsadmin.update_db_param('{database_name}', '{key}', '{value}')" + db2.exec_immediate(admin_conn, sql) + print(f" āœ… Set {key} = {value}") + except Exception as e: + print(f" āš ļø Failed to set {key}: {e}") + + # 5. Apply DB2 Instance DBM Configuration + db2_instance_dbm_config = os.environ.get('DB2_INSTANCE_DBM_CONFIG', '') + if db2_instance_dbm_config: + print("\nšŸ“ Applying DB2 Instance DBM Configuration settings...") + import json + config = json.loads(db2_instance_dbm_config) + for key, value in config.items(): + try: + sql = f"CALL rdsadmin.update_db_param('{database_name}', '{key}', '{value}')" + db2.exec_immediate(admin_conn, sql) + print(f" āœ… Set {key} = {value}") + except Exception as e: + print(f" āš ļø Failed to set {key}: {e}") + + # 6. Apply DB2 Audit Configuration + enable_audit = os.environ.get('ENABLE_AUDIT', 'false').lower() == 'true' + if enable_audit: + print("\nšŸ“ Configuring DB2 Audit...") + try: + sql = f"CALL rdsadmin.update_db_param('{database_name}', 'AUDIT_BUF_SZ', '1000')" + db2.exec_immediate(admin_conn, sql) + print(" āœ… Set AUDIT_BUF_SZ = 1000") + + apply_default_policy = os.environ.get('APPLY_DEFAULT_POLICY', 'false').lower() == 'true' + if apply_default_policy: + print(" ā„¹ļø Default audit policy would be applied here") + except Exception as e: + print(f" āš ļø Failed to configure audit: {e}") + + print("\nāœ… All DB2 configurations applied successfully") + db2.close(admin_conn) db2.close(db2_conn) diff --git a/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml b/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml index 16c007d46..15dc71749 100644 --- a/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml +++ b/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml @@ -126,6 +126,24 @@ spec: value: {{ .Values.dbname | quote }} - name: SSL_CERT_PATH value: "/etc/mas/rds-ssl/global-bundle.pem" + {{ - if .Values.db2_instance_registry }} + - name: DB2_INSTANCE_REGISTRY + value: {{ .Values.db2_instance_registry | toJson | quote }} + {{ - end }} + {{ - if .Values.db2_database_db_config }} + - name: DB2_DATABASE_CONFIG + value: {{ .Values.db2_database_db_config | toJson | quote }} + {{ - end }} + {{ - if .Values.db2_instance_dbm_config }} + - name: DB2_INSTANCE_DBM_CONFIG + value: {{ .Values.db2_instance_dbm_config | toJson | quote }} + {{ - end }} + {{ - if .Values.db2_addons_audit_config }} + - name: ENABLE_AUDIT + value: {{ .Values.db2_addons_audit_config.enableAudit | quote }} + - name: APPLY_DEFAULT_POLICY + value: {{ .Values.db2_addons_audit_config.applyDefaultPolicy | quote }} + {{ - end }} volumeMounts: - name: dbs-rds-secret-store mountPath: /etc/mas/dbs-rds-creds/ diff --git a/instance-applications/120-ibm-dbs-rds-database/values.yaml b/instance-applications/120-ibm-dbs-rds-database/values.yaml index 18be43a63..901c8b02c 100644 --- a/instance-applications/120-ibm-dbs-rds-database/values.yaml +++ b/instance-applications/120-ibm-dbs-rds-database/values.yaml @@ -1,3 +1,4 @@ +# Basic connection configuration rds_admin_db_name: "rdsadmin" host: "xyz.db" port: 50000 @@ -5,6 +6,27 @@ dbname: "rds1" user: "dummy" password: "dummy" +# Additional basic values +db2_namespace: "" +mas_application_id: "" # manage, facilities, or iot +jdbc_connection_url: "" +replica_db: false + +# DB2 Instance Registry Configuration +db2_instance_registry: {} + +# DB2 Database Configuration +db2_database_db_config: {} + +# DB2 Audit Configuration +db2_addons_audit_config: + enableAudit: false + applyDefaultPolicy: false + +# DB2 Instance DBM Configuration +db2_instance_dbm_config: {} + +# Script and application configuration db2_rds_instance_name: dbs-rds-inst1-manage scriptConfigMapName: dbs-rds-init-script -mas_application_id: \ No newline at end of file +mas_application_id: "" \ No newline at end of file diff --git a/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user_Job.yaml b/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user_Job.yaml new file mode 100644 index 000000000..d9f9e0c40 --- /dev/null +++ b/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user_Job.yaml @@ -0,0 +1,356 @@ +{{- if eq .Values.jdbc_type "rds-db2" }} + +{{- /* +Use the build/bin/set-cli-image-digest.sh script to update this value across all charts. +*/}} +{{- $_cli_image_digest := "sha256:d51f6123caf0d7bdb08b9337b63ced23c95beeccdc5225348e5890ec24e7e2ec" }} + +{{ $ns := printf "mas-%s-core" .Values.instance_id }} +{{ $prefix := printf "pre-jdbc-usr-%s" .Values.mas_config_name }} +{{ $secret := printf "%s-creds" $prefix }} +{{ $sa := printf "%s-sa" $prefix }} +{{ $crole := printf "%s-crole" $prefix }} +{{ $crb := printf "%s-crb" $prefix }} +{{ $np := printf "%s-np" $prefix }} +{{ $job := printf "%s-job" $prefix }} + +--- + +# We need to embed the supplied JDBC creds in a K8S secret so we can safely access them from +# the Job without exposing them via the ArgoCD resources +# NOTE: do not want to use the actual usersupplied jdbc creds secret as I'd have to annotate that +# to be a presync hook which will cause ArgoCD to delete it and could cause problems; safer just to create a dedicated secret for the presync hook. +# (alternatively could look up the secret via SM in the Job script but it's better this way as we use the actual credentials set in the chart values) +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ $secret }} + namespace: {{ $ns }} + annotations: + argocd.argoproj.io/hook: PreSync + argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation +{{- if .Values.custom_labels }} + labels: +{{ .Values.custom_labels | toYaml | indent 4 }} +{{- end }} +stringData: + username: "{{ .Values.jdbc_instance_username }}" + password: "{{ .Values.jdbc_instance_password }}" + +--- +kind: ServiceAccount +apiVersion: v1 +metadata: + name: {{ $sa }} + namespace: {{ $ns }} + annotations: + argocd.argoproj.io/hook: PreSync + argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation +{{- if .Values.custom_labels }} + labels: +{{ .Values.custom_labels | toYaml | indent 4 }} +{{- end }} + + + +--- +# Needed for "oc get crd db2uclusters.db2u.databases.ibm.com" command +# and for accessing resources in the db2u namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ $crole }} + annotations: + argocd.argoproj.io/hook: PreSync + argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation +{{- if .Values.custom_labels }} + labels: +{{ .Values.custom_labels | toYaml | indent 4 }} +{{- end }} +rules: +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get +- apiGroups: + - "" + resources: + - pods + verbs: + - list + - get +- apiGroups: + - "" + resources: + - pods/exec + verbs: + - create +- apiGroups: + - db2u.databases.ibm.com + resources: + - db2uengines + verbs: + - get + +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ $crb }} + annotations: + argocd.argoproj.io/hook: PreSync + argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation +{{- if .Values.custom_labels }} + labels: +{{ .Values.custom_labels | toYaml | indent 4 }} +{{- end }} +subjects: + - kind: ServiceAccount + name: {{ $sa }} + namespace: {{ $ns }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ $crole }} + + + +--- + +# Permit outbound communication by the Job pods +# (Needed to communicate with the K8S HTTP API and AWS SM) +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: {{ $np }} + namespace: {{ $ns }} + annotations: + argocd.argoproj.io/hook: PreSync + argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation +{{- if .Values.custom_labels }} + labels: +{{ .Values.custom_labels | toYaml | indent 4 }} +{{- end }} +spec: + podSelector: + matchLabels: + app: {{ $job }} + egress: + - {} + policyTypes: + - Egress + + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ $job }} + namespace: {{ $ns }} + annotations: + argocd.argoproj.io/hook: PreSync + argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation +{{- if .Values.custom_labels }} + labels: +{{ .Values.custom_labels | toYaml | indent 4 }} +{{- end }} +spec: + template: + metadata: + labels: + app: {{ $job }} +{{- if .Values.custom_labels }} +{{ .Values.custom_labels | toYaml | indent 8 }} +{{- end }} + spec: + containers: + - name: run + # TODO: use a dedicated image with a smaller footprint for this sort of thing? + # Just using cli for now since it has all the deps we need to talk with AWS SM + image: quay.io/ibmmas/cli@{{ $_cli_image_digest }} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 10m + memory: 64Mi + env: + - name: DB2_NAMESPACE + value: "{{ .Values.db2_namespace }}" + - name: DB2_INSTANCE_NAME + value: "{{ .Values.jdbc_instance_name }}" + - name: DB2_DBNAME + value: "{{ .Values.db2_dbname }}" + volumeMounts: + - name: db2-credentials + mountPath: /etc/mas/creds/db2-credentials + command: + - /bin/sh + - -c + - | + + set -e + + source /mascli/functions/gitops_utils + + export DB2_CREDENTIALS_SECRET_PATH="/etc/mas/creds/db2-credentials" + + echo "" + echo "================================================================================" + echo "Settings" + echo "================================================================================" + echo "DB2_NAMESPACE ....................... ${DB2_NAMESPACE}" + echo "DB2_INSTANCE_NAME ................... ${DB2_INSTANCE_NAME}" + echo "DB2_DBNAME .......................... ${DB2_DBNAME}" + echo "DB2_CREDENTIALS_SECRET_PATH ......... ${DB2_CREDENTIALS_SECRET_PATH}" + + echo "" + echo "================================================================================" + echo "Checking DB2 CRD db2uclusters.db2u.databases.ibm.com is ready (retries every ~10 seconds for ~5 minutes)" + echo "================================================================================" + + # wait till CRD db2uclusters.db2u.databases.ibm.com NamesAccepted=True STARTS + wait_period=0 + while true; do + export DB2_CRD_NAMES_ACCEPTED_STATUS=$(oc get crd db2uclusters.db2u.databases.ibm.com -o=jsonpath="{.status.conditions[?(@.type=='NamesAccepted')].status}") + echo "DB2_CRD_NAMES_ACCEPTED_STATUS .... ${DB2_CRD_NAMES_ACCEPTED_STATUS}" + if [[ "$DB2_CRD_NAMES_ACCEPTED_STATUS" == "True" ]]; then + break + fi + + wait_period=$(($wait_period+10)) + if [ $wait_period -gt 300 ];then + echo "CRD db2uclusters.db2u.databases.ibm.com is not ready with in 300 sec, exiting" + exit 1 + else + echo "CRD db2uclusters.db2u.databases.ibm.com is not ready, trying again in 10 seconds" + sleep 10 + fi + done + # wait till CRD db2uclusters.db2u.databases.ibm.com NamesAccepted=True DONE + + echo "" + echo "================================================================================" + echo "Reading LDAP credentials from ${DB2_CREDENTIALS_SECRET_PATH}" + echo "================================================================================" + export DB2_LDAP_USERNAME=$(cat /etc/mas/creds/db2-credentials/username) + export DB2_LDAP_PASSWORD=$(cat /etc/mas/creds/db2-credentials/password) + + echo "" + echo "================================================================================" + echo "Checking if ${DB2_LDAP_USERNAME} user exists already" + echo "================================================================================" + + echo "" + echo "Looking up name of DB2 db2u pod" + echo "--------------------------------------------------------------------------------" + export DB2_DB2U_POD_NAME=$(oc get pods -o custom-columns=POD:.metadata.name -l app=${DB2_INSTANCE_NAME},role=db -n ${DB2_NAMESPACE} --no-headers) + if [[ -z "${DB2_DB2U_POD_NAME}" ]]; then + echo "Failed to look up DB2 db2u pod name" + exit 1 + fi + echo "DB2_DB2U_POD_NAME .......................... ${DB2_DB2U_POD_NAME}" + + + echo "" + echo "Executing command on DB2 db2u pod; su -lc \"id ${DB2_LDAP_USERNAME}\"" + echo "--------------------------------------------------------------------------------" + # Using the || syntax to avoid surfacing a non 0 rc and exitting the job (without having to disable set -e) + DB2_USER_FOUND=true + oc exec -it -n ${DB2_NAMESPACE} ${DB2_DB2U_POD_NAME} -- su -lc "id ${DB2_LDAP_USERNAME}" || DB2_USER_FOUND=false + if [[ "${DB2_USER_FOUND}" == "true" ]]; then + echo "DB2 user exists already, exiting now" + exit 0 + fi + echo "DB2 user does not exist yet" + + echo "" + echo "================================================================================" + echo "Creating user ${DB2_LDAP_USERNAME}" + echo "================================================================================" + + echo "" + echo "Looking up name of DB2 LDAP pod" + echo "--------------------------------------------------------------------------------" + export DB2_LDAP_POD_NAME=$(oc get pods -o custom-columns=POD:.metadata.name -l app=${DB2_INSTANCE_NAME},role=ldap -n ${DB2_NAMESPACE} --no-headers) + if [[ -z "${DB2_LDAP_POD_NAME}" ]]; then + echo "Failed to look up DB2 LDAP pod name" + exit 1 + fi + echo "DB2_LDAP_POD_NAME .......................... ${DB2_LDAP_POD_NAME}" + + + echo "" + echo "Executing addLdapUser.py script in ${DB2_LDAP_POD_NAME} pod" + echo "--------------------------------------------------------------------------------" + oc exec -it -n ${DB2_NAMESPACE} ${DB2_LDAP_POD_NAME} -- /opt/ibm/ldap_scripts/addLdapUser.py -u ${DB2_LDAP_USERNAME} -r admin -p ${DB2_LDAP_PASSWORD} + echo "..... rc $?" + + echo "" + echo "Verifying that ${DB2_LDAP_USERNAME} can authenticate with ${DB2_DBNAME} database (retries every ~10 seconds for max ~5 minutes)" + echo "--------------------------------------------------------------------------------" + wait_period=0 + while true; do + + # Using the || syntax to avoid surfacing a non 0 rc and exitting the job (without having to disable set -e) + AUTH_SUCCESS=true + oc exec -it c-${DB2_INSTANCE_NAME}-db2u-0 -n ${DB2_NAMESPACE} -c db2u -- su -lc "db2 connect to ${DB2_DBNAME} user ${DB2_LDAP_USERNAME} using ${DB2_LDAP_PASSWORD}" db2inst1 || AUTH_SUCCESS=false + if [[ "${AUTH_SUCCESS}" == "true" ]]; then + echo "Authenticated successfully" + break + fi + echo "... failed to authenticate this time" + + wait_period=$(($wait_period+10)) + if [ $wait_period -gt 300 ]; then + echo "... >5 minutes have elapsed, failing job." + exit 1 + else + echo "... retrying in 10 seconds" + sleep 10 + fi + done + + echo "" + echo "================================================================================" + echo "Wait for c-${DB2_INSTANCE_NAME}-db2u Db2uEngine to report ready (retries every ~10 seconds for max ~5 minutes)" + echo "================================================================================" + wait_period=0 + while true; do + + export DB2U_ENGINE_STATE=$(oc get Db2uEngine c-${DB2_INSTANCE_NAME}-db2u -n ${DB2_NAMESPACE} -ojsonpath='{.status.state}') + + echo "... Db2uEngine state: ${DB2U_ENGINE_STATE}" + if [[ ${DB2U_ENGINE_STATE} == "Ready" ]]; then + echo "Db2uEngine c-${DB2_INSTANCE_NAME}-db2u is ready" + break + fi + + wait_period=$(($wait_period+10)) + if [ $wait_period -gt 300 ]; then + echo "... >5 minutes have elapsed, failing job." + exit 1 + else + echo "... retrying in 10 seconds" + sleep 10 + fi + done + + + restartPolicy: Never + + serviceAccountName: {{ $sa }} + volumes: + - name: db2-credentials + secret: + secretName: {{ $secret }} + defaultMode: 420 + optional: false + backoffLimit: 4 + +{{- end }} diff --git a/root-applications/ibm-mas-instance-root/templates/120-db2-databases-app.yaml b/root-applications/ibm-mas-instance-root/templates/120-db2-databases-app.yaml index 77e433dae..31e619167 100644 --- a/root-applications/ibm-mas-instance-root/templates/120-db2-databases-app.yaml +++ b/root-applications/ibm-mas-instance-root/templates/120-db2-databases-app.yaml @@ -4,6 +4,7 @@ For example: {{ $.Values.account.id }} (instead of {{ .Values.account.id }} ) */}} {{- range $i, $value := .Values.ibm_db2u_databases }} +{{- if not (contains "rds" $value.db2_instance_name) }} --- apiVersion: argoproj.io/v1alpha1 kind: Application @@ -85,4 +86,5 @@ spec: kind: Db2uInstance jsonPointers: - /spec/environment/ssl/secretName +{{- end }} {{- end }} \ No newline at end of file diff --git a/root-applications/ibm-mas-instance-root/templates/120-dbs-rds-databases-app.yaml b/root-applications/ibm-mas-instance-root/templates/120-dbs-rds-databases-app.yaml index 5a273ac52..166909161 100644 --- a/root-applications/ibm-mas-instance-root/templates/120-dbs-rds-databases-app.yaml +++ b/root-applications/ibm-mas-instance-root/templates/120-dbs-rds-databases-app.yaml @@ -3,7 +3,8 @@ For example: {{ $.Values.account.id }} (instead of {{ .Values.account.id }} ) */}} - {{- range $i, $value := .Values.ibm_dbs_rds_databases }} +{{- range $i, $value := .Values.ibm_dbs_rds_databases }} +{{- if contains "rds" $value.db2_instance_name }} --- apiVersion: argoproj.io/v1alpha1 kind: Application @@ -38,12 +39,58 @@ spec: env: - name: {{ $.Values.avp.values_varname }} value: | + # Basic connection configuration rds_admin_db_name: "{{ $value.rds_admin_db_name }}" host: "{{ $value.host }}" port: "{{ $value.port }}" dbname: "{{ $value.dbname }}" user: "{{ $value.user }}" password: "{{ $value.password }}" + + # Additional basic values + db2_namespace: "{{ $value.db2_namespace }}" + {{- if $value.mas_application_id }} + mas_application_id: "{{ $value.mas_application_id }}" + {{- end }} + {{- if $value.jdbc_connection_url }} + jdbc_connection_url: "{{ $value.jdbc_connection_url }}" + {{- end }} + {{- if hasKey $value "replica_db" }} + replica_db: {{ $value.replica_db }} + {{- end }} + + # DB2 Instance Registry Configuration + {{- if $value.db2_instance_registry }} + db2_instance_registry: + {{- range $key, $val := $value.db2_instance_registry }} + {{ $key }}: "{{ $val }}" + {{- end }} + {{- end }} + + # DB2 Database Configuration + {{- if $value.db2_database_db_config }} + db2_database_db_config: + {{- range $key, $val := $value.db2_database_db_config }} + {{ $key }}: "{{ $val }}" + {{- end }} + {{- end }} + + # DB2 Audit Configuration + {{- if $value.db2_addons_audit_config }} + db2_addons_audit_config: + enableAudit: {{ $value.db2_addons_audit_config.enableAudit }} + applyDefaultPolicy: {{ $value.db2_addons_audit_config.applyDefaultPolicy }} + {{- end }} + + # DB2 Instance DBM Configuration + {{- if $value.db2_instance_dbm_config }} + db2_instance_dbm_config: + {{- range $key, $val := $value.db2_instance_dbm_config }} + {{ $key }}: "{{ $val }}" + {{- end }} + {{- end }} + + # JUnit Reporter Configuration junitreporter: reporter_name: {{ $value.db2_instance_name }} cluster_id: "{{ $.Values.cluster.id }}" @@ -66,4 +113,5 @@ spec: syncOptions: - CreateNamespace=false - RespectIgnoreDifferences=true - {{- end }} \ No newline at end of file +{{- end }} +{{- end }} \ No newline at end of file From 98011f47298cc644a902446d701a953ad509a299 Mon Sep 17 00:00:00 2001 From: amitpandey Date: Tue, 10 Feb 2026 15:48:40 +0530 Subject: [PATCH 02/11] db2 name changes --- .../00-presync-create-db2-rds-user_Job.yaml | 356 ------------------ 1 file changed, 356 deletions(-) delete mode 100644 instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user_Job.yaml diff --git a/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user_Job.yaml b/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user_Job.yaml deleted file mode 100644 index d9f9e0c40..000000000 --- a/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user_Job.yaml +++ /dev/null @@ -1,356 +0,0 @@ -{{- if eq .Values.jdbc_type "rds-db2" }} - -{{- /* -Use the build/bin/set-cli-image-digest.sh script to update this value across all charts. -*/}} -{{- $_cli_image_digest := "sha256:d51f6123caf0d7bdb08b9337b63ced23c95beeccdc5225348e5890ec24e7e2ec" }} - -{{ $ns := printf "mas-%s-core" .Values.instance_id }} -{{ $prefix := printf "pre-jdbc-usr-%s" .Values.mas_config_name }} -{{ $secret := printf "%s-creds" $prefix }} -{{ $sa := printf "%s-sa" $prefix }} -{{ $crole := printf "%s-crole" $prefix }} -{{ $crb := printf "%s-crb" $prefix }} -{{ $np := printf "%s-np" $prefix }} -{{ $job := printf "%s-job" $prefix }} - ---- - -# We need to embed the supplied JDBC creds in a K8S secret so we can safely access them from -# the Job without exposing them via the ArgoCD resources -# NOTE: do not want to use the actual usersupplied jdbc creds secret as I'd have to annotate that -# to be a presync hook which will cause ArgoCD to delete it and could cause problems; safer just to create a dedicated secret for the presync hook. -# (alternatively could look up the secret via SM in the Job script but it's better this way as we use the actual credentials set in the chart values) -apiVersion: v1 -kind: Secret -type: Opaque -metadata: - name: {{ $secret }} - namespace: {{ $ns }} - annotations: - argocd.argoproj.io/hook: PreSync - argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation -{{- if .Values.custom_labels }} - labels: -{{ .Values.custom_labels | toYaml | indent 4 }} -{{- end }} -stringData: - username: "{{ .Values.jdbc_instance_username }}" - password: "{{ .Values.jdbc_instance_password }}" - ---- -kind: ServiceAccount -apiVersion: v1 -metadata: - name: {{ $sa }} - namespace: {{ $ns }} - annotations: - argocd.argoproj.io/hook: PreSync - argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation -{{- if .Values.custom_labels }} - labels: -{{ .Values.custom_labels | toYaml | indent 4 }} -{{- end }} - - - ---- -# Needed for "oc get crd db2uclusters.db2u.databases.ibm.com" command -# and for accessing resources in the db2u namespace -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ $crole }} - annotations: - argocd.argoproj.io/hook: PreSync - argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation -{{- if .Values.custom_labels }} - labels: -{{ .Values.custom_labels | toYaml | indent 4 }} -{{- end }} -rules: -- apiGroups: - - apiextensions.k8s.io - resources: - - customresourcedefinitions - verbs: - - get -- apiGroups: - - "" - resources: - - pods - verbs: - - list - - get -- apiGroups: - - "" - resources: - - pods/exec - verbs: - - create -- apiGroups: - - db2u.databases.ibm.com - resources: - - db2uengines - verbs: - - get - ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ $crb }} - annotations: - argocd.argoproj.io/hook: PreSync - argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation -{{- if .Values.custom_labels }} - labels: -{{ .Values.custom_labels | toYaml | indent 4 }} -{{- end }} -subjects: - - kind: ServiceAccount - name: {{ $sa }} - namespace: {{ $ns }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ $crole }} - - - ---- - -# Permit outbound communication by the Job pods -# (Needed to communicate with the K8S HTTP API and AWS SM) -kind: NetworkPolicy -apiVersion: networking.k8s.io/v1 -metadata: - name: {{ $np }} - namespace: {{ $ns }} - annotations: - argocd.argoproj.io/hook: PreSync - argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation -{{- if .Values.custom_labels }} - labels: -{{ .Values.custom_labels | toYaml | indent 4 }} -{{- end }} -spec: - podSelector: - matchLabels: - app: {{ $job }} - egress: - - {} - policyTypes: - - Egress - - ---- -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ $job }} - namespace: {{ $ns }} - annotations: - argocd.argoproj.io/hook: PreSync - argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation -{{- if .Values.custom_labels }} - labels: -{{ .Values.custom_labels | toYaml | indent 4 }} -{{- end }} -spec: - template: - metadata: - labels: - app: {{ $job }} -{{- if .Values.custom_labels }} -{{ .Values.custom_labels | toYaml | indent 8 }} -{{- end }} - spec: - containers: - - name: run - # TODO: use a dedicated image with a smaller footprint for this sort of thing? - # Just using cli for now since it has all the deps we need to talk with AWS SM - image: quay.io/ibmmas/cli@{{ $_cli_image_digest }} - imagePullPolicy: IfNotPresent - resources: - limits: - cpu: 200m - memory: 512Mi - requests: - cpu: 10m - memory: 64Mi - env: - - name: DB2_NAMESPACE - value: "{{ .Values.db2_namespace }}" - - name: DB2_INSTANCE_NAME - value: "{{ .Values.jdbc_instance_name }}" - - name: DB2_DBNAME - value: "{{ .Values.db2_dbname }}" - volumeMounts: - - name: db2-credentials - mountPath: /etc/mas/creds/db2-credentials - command: - - /bin/sh - - -c - - | - - set -e - - source /mascli/functions/gitops_utils - - export DB2_CREDENTIALS_SECRET_PATH="/etc/mas/creds/db2-credentials" - - echo "" - echo "================================================================================" - echo "Settings" - echo "================================================================================" - echo "DB2_NAMESPACE ....................... ${DB2_NAMESPACE}" - echo "DB2_INSTANCE_NAME ................... ${DB2_INSTANCE_NAME}" - echo "DB2_DBNAME .......................... ${DB2_DBNAME}" - echo "DB2_CREDENTIALS_SECRET_PATH ......... ${DB2_CREDENTIALS_SECRET_PATH}" - - echo "" - echo "================================================================================" - echo "Checking DB2 CRD db2uclusters.db2u.databases.ibm.com is ready (retries every ~10 seconds for ~5 minutes)" - echo "================================================================================" - - # wait till CRD db2uclusters.db2u.databases.ibm.com NamesAccepted=True STARTS - wait_period=0 - while true; do - export DB2_CRD_NAMES_ACCEPTED_STATUS=$(oc get crd db2uclusters.db2u.databases.ibm.com -o=jsonpath="{.status.conditions[?(@.type=='NamesAccepted')].status}") - echo "DB2_CRD_NAMES_ACCEPTED_STATUS .... ${DB2_CRD_NAMES_ACCEPTED_STATUS}" - if [[ "$DB2_CRD_NAMES_ACCEPTED_STATUS" == "True" ]]; then - break - fi - - wait_period=$(($wait_period+10)) - if [ $wait_period -gt 300 ];then - echo "CRD db2uclusters.db2u.databases.ibm.com is not ready with in 300 sec, exiting" - exit 1 - else - echo "CRD db2uclusters.db2u.databases.ibm.com is not ready, trying again in 10 seconds" - sleep 10 - fi - done - # wait till CRD db2uclusters.db2u.databases.ibm.com NamesAccepted=True DONE - - echo "" - echo "================================================================================" - echo "Reading LDAP credentials from ${DB2_CREDENTIALS_SECRET_PATH}" - echo "================================================================================" - export DB2_LDAP_USERNAME=$(cat /etc/mas/creds/db2-credentials/username) - export DB2_LDAP_PASSWORD=$(cat /etc/mas/creds/db2-credentials/password) - - echo "" - echo "================================================================================" - echo "Checking if ${DB2_LDAP_USERNAME} user exists already" - echo "================================================================================" - - echo "" - echo "Looking up name of DB2 db2u pod" - echo "--------------------------------------------------------------------------------" - export DB2_DB2U_POD_NAME=$(oc get pods -o custom-columns=POD:.metadata.name -l app=${DB2_INSTANCE_NAME},role=db -n ${DB2_NAMESPACE} --no-headers) - if [[ -z "${DB2_DB2U_POD_NAME}" ]]; then - echo "Failed to look up DB2 db2u pod name" - exit 1 - fi - echo "DB2_DB2U_POD_NAME .......................... ${DB2_DB2U_POD_NAME}" - - - echo "" - echo "Executing command on DB2 db2u pod; su -lc \"id ${DB2_LDAP_USERNAME}\"" - echo "--------------------------------------------------------------------------------" - # Using the || syntax to avoid surfacing a non 0 rc and exitting the job (without having to disable set -e) - DB2_USER_FOUND=true - oc exec -it -n ${DB2_NAMESPACE} ${DB2_DB2U_POD_NAME} -- su -lc "id ${DB2_LDAP_USERNAME}" || DB2_USER_FOUND=false - if [[ "${DB2_USER_FOUND}" == "true" ]]; then - echo "DB2 user exists already, exiting now" - exit 0 - fi - echo "DB2 user does not exist yet" - - echo "" - echo "================================================================================" - echo "Creating user ${DB2_LDAP_USERNAME}" - echo "================================================================================" - - echo "" - echo "Looking up name of DB2 LDAP pod" - echo "--------------------------------------------------------------------------------" - export DB2_LDAP_POD_NAME=$(oc get pods -o custom-columns=POD:.metadata.name -l app=${DB2_INSTANCE_NAME},role=ldap -n ${DB2_NAMESPACE} --no-headers) - if [[ -z "${DB2_LDAP_POD_NAME}" ]]; then - echo "Failed to look up DB2 LDAP pod name" - exit 1 - fi - echo "DB2_LDAP_POD_NAME .......................... ${DB2_LDAP_POD_NAME}" - - - echo "" - echo "Executing addLdapUser.py script in ${DB2_LDAP_POD_NAME} pod" - echo "--------------------------------------------------------------------------------" - oc exec -it -n ${DB2_NAMESPACE} ${DB2_LDAP_POD_NAME} -- /opt/ibm/ldap_scripts/addLdapUser.py -u ${DB2_LDAP_USERNAME} -r admin -p ${DB2_LDAP_PASSWORD} - echo "..... rc $?" - - echo "" - echo "Verifying that ${DB2_LDAP_USERNAME} can authenticate with ${DB2_DBNAME} database (retries every ~10 seconds for max ~5 minutes)" - echo "--------------------------------------------------------------------------------" - wait_period=0 - while true; do - - # Using the || syntax to avoid surfacing a non 0 rc and exitting the job (without having to disable set -e) - AUTH_SUCCESS=true - oc exec -it c-${DB2_INSTANCE_NAME}-db2u-0 -n ${DB2_NAMESPACE} -c db2u -- su -lc "db2 connect to ${DB2_DBNAME} user ${DB2_LDAP_USERNAME} using ${DB2_LDAP_PASSWORD}" db2inst1 || AUTH_SUCCESS=false - if [[ "${AUTH_SUCCESS}" == "true" ]]; then - echo "Authenticated successfully" - break - fi - echo "... failed to authenticate this time" - - wait_period=$(($wait_period+10)) - if [ $wait_period -gt 300 ]; then - echo "... >5 minutes have elapsed, failing job." - exit 1 - else - echo "... retrying in 10 seconds" - sleep 10 - fi - done - - echo "" - echo "================================================================================" - echo "Wait for c-${DB2_INSTANCE_NAME}-db2u Db2uEngine to report ready (retries every ~10 seconds for max ~5 minutes)" - echo "================================================================================" - wait_period=0 - while true; do - - export DB2U_ENGINE_STATE=$(oc get Db2uEngine c-${DB2_INSTANCE_NAME}-db2u -n ${DB2_NAMESPACE} -ojsonpath='{.status.state}') - - echo "... Db2uEngine state: ${DB2U_ENGINE_STATE}" - if [[ ${DB2U_ENGINE_STATE} == "Ready" ]]; then - echo "Db2uEngine c-${DB2_INSTANCE_NAME}-db2u is ready" - break - fi - - wait_period=$(($wait_period+10)) - if [ $wait_period -gt 300 ]; then - echo "... >5 minutes have elapsed, failing job." - exit 1 - else - echo "... retrying in 10 seconds" - sleep 10 - fi - done - - - restartPolicy: Never - - serviceAccountName: {{ $sa }} - volumes: - - name: db2-credentials - secret: - secretName: {{ $secret }} - defaultMode: 420 - optional: false - backoffLimit: 4 - -{{- end }} From f5c4cb12c4f2309a7de7e78a4ab06352842c6ebd Mon Sep 17 00:00:00 2001 From: amitpandey Date: Tue, 10 Feb 2026 18:33:52 +0530 Subject: [PATCH 03/11] Post sync job for users and role creation --- .../00-presync-create-db2-rds-user-Job.yaml | 278 +++++++++++ .../703-postsync-rds-manage-roles.yaml | 471 ++++++++++++++++++ .../510-550-ibm-mas-masapp-configs.yaml | 45 ++ 3 files changed, 794 insertions(+) create mode 100644 instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml create mode 100644 instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml diff --git a/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml b/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml new file mode 100644 index 000000000..873a7575b --- /dev/null +++ b/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml @@ -0,0 +1,278 @@ +{{- if eq .Values.jdbc_type "rds-db2" }} + + {{- /* + Use the build/bin/set-cli-image-digest.sh script to update this value across all charts. + */}} + {{- $_cli_image_digest := "sha256:55b5d6dd185503f14c112836a9a4899347d28e7b6545e0b9cf21d87f9526fb40" }} + + {{ $ns := printf "mas-%s-core" .Values.instance_id }} + {{ $prefix := printf "pre-jdbc-nonadmin-%s" .Values.mas_config_name }} + {{ $sa := printf "%s-sa" $prefix }} + {{ $np := printf "%s-np" $prefix }} + {{ $job := printf "%s-job" $prefix }} + +--- +kind: ServiceAccount +apiVersion: v1 +metadata: + name: {{ $sa }} + namespace: {{ $ns }} + annotations: + argocd.argoproj.io/hook: PreSync + argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation + {{- if .Values.custom_labels }} +labels: + {{ .Values.custom_labels | toYaml | indent 4 }} + {{- end }} + +--- +# Permit outbound communication by the Job pods +# (Needed to communicate with RDS) +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: {{ $np }} + namespace: {{ $ns }} + annotations: + argocd.argoproj.io/hook: PreSync + argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation + {{- if .Values.custom_labels }} +labels: + {{ .Values.custom_labels | toYaml | indent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app: {{ $job }} + egress: + - {} + policyTypes: + - Egress + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ $job }} + namespace: {{ $ns }} + annotations: + argocd.argoproj.io/hook: PreSync + argocd.argoproj.io/hook-delete-policy: HookSucceeded,BeforeHookCreation + {{- if .Values.custom_labels }} +labels: + {{ .Values.custom_labels | toYaml | indent 4 }} + {{- end }} +spec: + template: + metadata: + labels: + app: {{ $job }} + {{- if .Values.custom_labels }} + {{ .Values.custom_labels | toYaml | indent 8 }} + {{- end }} +spec: + containers: + - name: run + image: quay.io/ibmmas/cli@{{ $_cli_image_digest }} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 10m + memory: 64Mi + env: + - name: JDBC_CONNECTION_URL + value: "{{ .Values.jdbc_connection_url }}" + - name: JDBC_INSTANCE_USERNAME + value: "{{ .Values.jdbc_instance_username }}" + - name: JDBC_INSTANCE_PASSWORD + value: "{{ .Values.jdbc_instance_password }}" + - name: MAS_APP_ID + value: "{{ .Values.mas_application_id }}" + command: + - /bin/sh + - -c + - | + + set -e + + echo "" + echo "================================================================================" + echo "Settings" + echo "================================================================================" + echo "JDBC_CONNECTION_URL ................. ${JDBC_CONNECTION_URL}" + echo "JDBC_INSTANCE_USERNAME .............. ${JDBC_INSTANCE_USERNAME}" + echo "MAS_APP_ID .......................... ${MAS_APP_ID}" + + echo "" + echo "Installing required Python packages..." + echo "--------------------------------------------------------------------------------" + pip install ibm_db + + echo "" + echo "Downloading RDS SSL certificate..." + echo "--------------------------------------------------------------------------------" + mkdir -p /tmp/rds-ssl + curl -sSL https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem -o /tmp/rds-ssl/global-bundle.pem + echo "āœ… Certificate downloaded" + + # Path to the generated Python script + RDS_USER_SCRIPT="/tmp/create_rds_nonadmin_users.py" + + echo "" + echo "Create ${RDS_USER_SCRIPT}" + echo "--------------------------------------------------------------------------------" + + # Generate a Python script to create non-admin users and grant permissions + cat > ${RDS_USER_SCRIPT} << 'EOFPYTHON' + import ibm_db + import os + import sys + + import re + + # Get environment variables + jdbc_connection_url = os.getenv('JDBC_CONNECTION_URL') + jdbc_username = os.getenv('JDBC_INSTANCE_USERNAME') + jdbc_password = os.getenv('JDBC_INSTANCE_PASSWORD') + mas_app_id = os.getenv('MAS_APP_ID', 'manage') + ssl_cert_path = '/tmp/rds-ssl/global-bundle.pem' + + # Parse JDBC connection URL to extract host, port, and database + # Format: jdbc:db2://host:port/database + match = re.match(r'jdbc:db2://([^:]+):(\d+)/(.+)', jdbc_connection_url) + if not match: + print(f"āŒ Failed to parse JDBC connection URL: {jdbc_connection_url}") + sys.exit(1) + + rds_host = match.group(1) + rds_port = match.group(2) + rds_dbname = match.group(3).split(':')[0] # Remove any additional parameters + + # Build connection string with SSL + conn_str = ( + f"DATABASE={rds_dbname};" + f"HOSTNAME={rds_host};" + f"PORT={rds_port};" + f"PROTOCOL=TCPIP;" + f"UID={jdbc_username};" + f"PWD={jdbc_password};" + f"Security=SSL;" + f"SSLServerCertificate={ssl_cert_path};" + ) + + print(f"Connecting to RDS DB2 instance: {rds_host}:{rds_port}/{rds_dbname}") + print(f"MAS Application ID: {mas_app_id}") + print(f"JDBC Username: {jdbc_username}") + + # Define all app-specific admin users to create + # Create users for all three app types regardless of current MAS_APP_ID + users_to_create = [ + { + 'username': 'DB2_manage', + 'role': 'DBADM', + 'grants': ['MAXIMO_READ', 'MAXIMO_WRITE'], + 'description': 'Manage Admin User', + 'app_type': 'manage' + }, + { + 'username': 'DB2_facilities', + 'role': 'DBADM', + 'grants': ['TRIDATA_READ', 'TRIDATA_WRITE'], + 'description': 'Facilities Admin User', + 'app_type': 'facilities' + }, + { + 'username': 'DB2_iot', + 'role': 'DBADM', + 'grants': [], + 'description': 'IoT Admin User', + 'app_type': 'iot' + } + ] + + print(f"\nāœ… Creating users for all MAS applications (manage, facilities, iot)") + + try: + # Connect to the database + conn = ibm_db.connect(conn_str, "", "") + print("āœ… Successfully connected to RDS DB2") + + for user_info in users_to_create: + username = user_info['username'] + role_to_assign = user_info['role'] + grants = user_info['grants'] + description = user_info['description'] + + print(f"\n{'='*80}") + print(f"Processing: {description}") + print(f"Username: {username}") + print(f"{'='*80}") + + # Check if user exists + check_user_sql = f""" + SELECT COUNT(*) as user_count + FROM SYSIBM.SYSDBAUTH + WHERE GRANTEE = '{username}' + """ + + try: + stmt = ibm_db.exec_immediate(conn, check_user_sql) + result = ibm_db.fetch_assoc(stmt) + user_exists = result['USER_COUNT'] > 0 + + if user_exists: + print(f"ā„¹ļø User {username} already exists") + else: + # Create user - Note: In RDS DB2, users are typically created externally + # This grants database privileges to the user + print(f"āœ… Granting {role_to_assign} privileges to {username}") + grant_dbadm_sql = f"GRANT {role_to_assign} ON DATABASE TO USER {username}" + try: + ibm_db.exec_immediate(conn, grant_dbadm_sql) + print(f"āœ… Granted {role_to_assign} to {username}") + except Exception as e: + print(f"āš ļø Error granting {role_to_assign}: {str(e)}") + + except Exception as e: + print(f"āš ļø Error checking user {username}: {str(e)}") + + # Grant role permissions + if grants: + print(f"\nāœ… Granting role permissions to {username}...") + for grant_role in grants: + try: + grant_role_sql = f"GRANT ROLE {grant_role} TO USER {username}" + ibm_db.exec_immediate(conn, grant_role_sql) + print(f"āœ… Granted role {grant_role} to {username}") + except Exception as e: + print(f"āš ļø Error granting role {grant_role}: {str(e)}") + + print("\nāœ… App-specific admin user creation and permission grants completed successfully") + + # Close connection + ibm_db.close(conn) + + except Exception as e: + print(f"āŒ Error: {str(e)}") + sys.exit(1) + EOFPYTHON + # IMPORTANT: Do not make any changes to the "EOFPYTHON" line above (including its indentation) + + echo "" + echo "Executing ${RDS_USER_SCRIPT}" + echo "--------------------------------------------------------------------------------" + python ${RDS_USER_SCRIPT} || exit $? + + echo "" + echo "āœ… RDS app-specific admin user creation job completed successfully" + + restartPolicy: Never + serviceAccountName: {{ $sa }} + volumes: [] +backoffLimit: 4 + + {{- end }} + diff --git a/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml b/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml new file mode 100644 index 000000000..85bdd157f --- /dev/null +++ b/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml @@ -0,0 +1,471 @@ +{{- if not (empty .Values.manage_rds_databases) }} + +{{- /* +Use the build/bin/set-cli-image-digest.sh script to update this value across all charts. +*/}} +{{- $_cli_image_digest := "sha256:55b5d6dd185503f14c112836a9a4899347d28e7b6545e0b9cf21d87f9526fb40" }} + +{{ $manage_ns := .Values.mas_app_namespace }} +{{ $np_name := "postsync-manage-rds-roles-np" }} +{{ $sa_name := "postsync-manage-rds-roles-sa" }} +{{ $job_label := "postsync-manage-rds-roles-job" }} + +--- +{{- /* + Permit outbound communication by the Job pod (Needed to communicate with RDS) + This single policy is shared by all per-rds job instances +*/}} +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: {{ $np_name }} + namespace: {{ $manage_ns }} + annotations: + argocd.argoproj.io/sync-wave: "703" +{{- if .Values.custom_labels }} + labels: +{{ .Values.custom_labels | toYaml | indent 4 }} +{{- end }} +spec: + podSelector: + matchLabels: + app: {{ $job_label }} + egress: + - {} + policyTypes: + - Egress + +--- +{{- /* + Service account for the job + This single service account is shared by all per-rds job instances +*/}} +kind: ServiceAccount +apiVersion: v1 +metadata: + name: "{{ $sa_name }}" + namespace: "{{ $manage_ns }}" + annotations: + argocd.argoproj.io/sync-wave: "703" +{{- if .Values.custom_labels }} + labels: +{{ .Values.custom_labels | toYaml | indent 4 }} +{{- end }} + + +{{- /* + A separate CronJob is created in the app namespace per RDS instance reserved for use by MAS applications (Manage or Facilities). + This job runs periodically to check if application-specific tables exist and creates required roles. + + NOTE: When inside the range loop below, make sure you prefix any references to chart values NOT under .Values.manage_rds_databases with $. + For example: {{ $.Values.custom_labels }} (instead of {{ .Values.custom_labels }} ) +*/}} +{{- range $i, $db := .Values.manage_rds_databases }} + +{{- /* +Meaningful prefix for the job resource name. Must be under 52 chars in length to leave room for the 11 chars reserved for '-' and $_job_hash. +*/}} +{{- $_job_name_prefix := "postsync-rds-roles" }} + +{{- /* +A dict of values that influence the behaviour of the job in some way. +Any changes to values in this dict will trigger a rerun of the job. +Included in $_job_hash (see below). +*/}} +{{- $_job_config_values := $db }} + +{{- /* +Increment this value whenever you make a change to an immutable field of the Job resource. +E.g. passing in a new environment variable. +Included in $_job_hash (see below). +*/}} +{{- $_job_version := "v1" }} + +{{- /* +10 char hash appended to the job name taking into account $_job_config_values, $_job_version and $_cli_image_digest +This is to ensure ArgoCD will create a new job resource instead of attempting (and failing) to update an +immutable field of any existing Job resource. +*/}} +{{- $_job_hash := print ( $_job_config_values | toYaml ) $_cli_image_digest $_job_version | adler32sum }} + +{{- $_cronjob_name := join "-" (list $_job_name_prefix $_job_hash) }} + +{{- /* +Set as the value for the mas.ibm.com/job-cleanup-group label on the Job resource. + +When the auto_delete flag is not set on the root application, a CronJob in the cluster uses this label +to identify old Job resources that should be pruned on behalf of ArgoCD. + +Any Job resources in the same namespace that have the mas.ibm.com/job-cleanup-group with this value +will be considered to belong to the same cleanup group. All but the most recent (i.e. with the latest "creation_timestamp") +Jobs will be automatically deleted. + +$_job_cleanup_group can usually just be based on $_job_name_prefix. There are some special cases +where multiple Jobs are created in our templates using a Helm loop. In those cases, additional discriminators +must be added to $_job_cleanup_group. +NOTE: this is one of those cases; we need a separate cleanup group for each per-rds Job. + +By convention, we sha1sum this value to guarantee we never exceed the 63 char limit regardless of which discriminators +are required here. +*/}} +{{- $_job_cleanup_group := cat $_job_name_prefix $db.rds_instance_name | sha1sum }} + +{{ $rds_host := $db.rds_host }} +{{ $rds_port := $db.rds_port }} +{{ $rds_dbname := $db.rds_dbname }} +{{ $rds_instance_name := $db.rds_instance_name }} +{{ $rds_admin_user := $db.rds_admin_user }} +{{ $rds_admin_password := $db.rds_admin_password }} + +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: {{ $_cronjob_name }} + namespace: "{{ $manage_ns }}" + annotations: + argocd.argoproj.io/sync-wave: "704" + labels: + mas.ibm.com/job-cleanup-group: {{ $_job_cleanup_group }} +{{- if $.Values.custom_labels }} +{{ $.Values.custom_labels | toYaml | indent 4 }} +{{- end }} +spec: + schedule: "*/30 * * * *" # Run every 30 minutes + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 3 + failedJobsHistoryLimit: 1 + jobTemplate: + metadata: + labels: + app: {{ $job_label }} +{{- if $.Values.custom_labels }} +{{ $.Values.custom_labels | toYaml | indent 8 }} +{{- end }} + spec: + template: + metadata: + labels: + app: {{ $job_label }} +{{- if $.Values.custom_labels }} +{{ $.Values.custom_labels | toYaml | indent 12 }} +{{- end }} + spec: + containers: + - name: run + image: {{ $.Values.cli_image_repo | default "quay.io/ibmmas/cli" }}@{{ $_cli_image_digest }} + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 10m + memory: 64Mi + env: + - name: RDS_HOST + value: "{{ $rds_host }}" + - name: RDS_PORT + value: "{{ $rds_port }}" + - name: RDS_DBNAME + value: "{{ $rds_dbname }}" + - name: RDS_INSTANCE_NAME + value: "{{ $rds_instance_name }}" + - name: RDS_ADMIN_USER + value: "{{ $rds_admin_user }}" + - name: RDS_ADMIN_PASSWORD + value: "{{ $rds_admin_password }}" + - name: MAS_APP_ID + value: "{{ $.Values.mas_app_id }}" + - name: OPERATIONAL_MODE + value: "{{ $.Values.operational_mode }}" + + volumeMounts: [] + command: + - /bin/sh + - -c + - | + + set -e + source /mascli/functions/gitops_utils + + echo "" + echo "================================================================================" + echo "Settings" + echo "================================================================================" + echo "RDS_INSTANCE_NAME ................... ${RDS_INSTANCE_NAME}" + echo "RDS_DBNAME .......................... ${RDS_DBNAME}" + echo "RDS_HOST ............................ ${RDS_HOST}" + echo "RDS_PORT ............................ ${RDS_PORT}" + echo "OPERATIONAL_MODE .................... ${OPERATIONAL_MODE}" + + echo "" + echo "Installing required Python packages..." + echo "--------------------------------------------------------------------------------" + pip install ibm_db + + echo "" + echo "Downloading RDS SSL certificate..." + echo "--------------------------------------------------------------------------------" + mkdir -p /tmp/rds-ssl + curl -sSL https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem -o /tmp/rds-ssl/global-bundle.pem + echo "āœ… Certificate downloaded" + + # Path to the generated Python script + RDS_ROLES_SCRIPT="/tmp/create_rds_roles.py" + + echo "" + echo "Create ${RDS_ROLES_SCRIPT}" + echo "--------------------------------------------------------------------------------" + + # Generate a Python script to check table and create roles + cat > ${RDS_ROLES_SCRIPT} << 'EOFPYTHON' + import ibm_db + import os + import sys + + # Get environment variables + rds_host = os.getenv('RDS_HOST') + rds_port = os.getenv('RDS_PORT') + rds_dbname = os.getenv('RDS_DBNAME') + rds_admin_user = os.getenv('RDS_ADMIN_USER') + rds_admin_password = os.getenv('RDS_ADMIN_PASSWORD') + ssl_cert_path = '/tmp/rds-ssl/global-bundle.pem' + + # Build connection string with SSL + conn_str = ( + f"DATABASE={rds_dbname};" + f"HOSTNAME={rds_host};" + f"PORT={rds_port};" + f"PROTOCOL=TCPIP;" + f"UID={rds_admin_user};" + f"PWD={rds_admin_password};" + f"Security=SSL;" + f"SSLServerCertificate={ssl_cert_path};" + ) + + print(f"Connecting to RDS DB2 instance: {rds_host}:{rds_port}/{rds_dbname}") + print("Creating roles for all MAS applications: manage, facilities, iot") + + try: + # Connect to the database + conn = ibm_db.connect(conn_str, "", "") + print("āœ… Successfully connected to RDS DB2") + + # Define app configurations with table checks and roles + app_configs = [ + { + 'app_name': 'manage', + 'schema': 'MAXIMO', + 'check_table': 'MAXUSERS', + 'roles': ['MAXIMO_READ', 'MAXIMO_WRITE', 'MAXIMO_SEQ', 'EXPLAIN'] + }, + { + 'app_name': 'facilities', + 'schema': 'TRIDATA', + 'check_table': 'TRIDATA_DATA', + 'roles': ['TRIDATA_READ', 'TRIDATA_WRITE'] + }, + { + 'app_name': 'iot', + 'schema': 'IOT', + 'check_table': 'IOT_DATA', + 'roles': ['IOT_READ', 'IOT_WRITE'] + } + ] + + # Process each app configuration + for app_config in app_configs: + app_name = app_config['app_name'] + schema_name = app_config['schema'] + table_name = app_config['check_table'] + roles = app_config['roles'] + + print(f"\n{'='*60}") + print(f"Processing {app_name.upper()} application") + print(f"{'='*60}") + + # Check if the required table exists + check_table_sql = f""" + SELECT COUNT(*) as table_count + FROM SYSCAT.TABLES + WHERE TABSCHEMA = '{schema_name}' AND TABNAME = '{table_name}' + """ + + stmt = ibm_db.exec_immediate(conn, check_table_sql) + result = ibm_db.fetch_assoc(stmt) + table_exists = result['TABLE_COUNT'] > 0 + + if not table_exists: + print(f"āš ļø Table {schema_name}.{table_name} does not exist yet. Skipping {app_name} role creation.") + continue + + print(f"āœ… Table {schema_name}.{table_name} exists. Proceeding with role creation...") + + # Create roles if they don't exist + for role in roles: + try: + # Check if role exists + check_role_sql = f""" + SELECT COUNT(*) as role_count + FROM SYSCAT.ROLES + WHERE ROLENAME = '{role}' + """ + stmt = ibm_db.exec_immediate(conn, check_role_sql) + result = ibm_db.fetch_assoc(stmt) + role_exists = result['ROLE_COUNT'] > 0 + + if not role_exists: + create_role_sql = f"CREATE ROLE {role}" + ibm_db.exec_immediate(conn, create_role_sql) + print(f"āœ… Created role: {role}") + else: + print(f"ā„¹ļø Role {role} already exists") + + except Exception as e: + print(f"āš ļø Error creating role {role}: {str(e)}") + + # Grant permissions based on app type + if app_name == 'manage': + # Grant permissions to MAXIMO_READ role + print("\nāœ… Granting permissions to MAXIMO_READ role...") + read_grants = [ + "GRANT SELECT ON TABLE MAXIMO.MAXUSERS TO ROLE MAXIMO_READ", + "GRANT SELECT ON SCHEMA MAXIMO TO ROLE MAXIMO_READ", + ] + + for grant_sql in read_grants: + try: + ibm_db.exec_immediate(conn, grant_sql) + print(f"āœ… Executed: {grant_sql}") + except Exception as e: + print(f"āš ļø Error executing grant: {str(e)}") + + # Grant permissions to MAXIMO_WRITE role + print("\nāœ… Granting permissions to MAXIMO_WRITE role...") + write_grants = [ + "GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE MAXIMO.MAXUSERS TO ROLE MAXIMO_WRITE", + "GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA MAXIMO TO ROLE MAXIMO_WRITE", + ] + + for grant_sql in write_grants: + try: + ibm_db.exec_immediate(conn, grant_sql) + print(f"āœ… Executed: {grant_sql}") + except Exception as e: + print(f"āš ļø Error executing grant: {str(e)}") + + # Grant permissions to MAXIMO_SEQ role + print("\nāœ… Granting permissions to MAXIMO_SEQ role...") + seq_grants = [ + "GRANT USAGE ON SEQUENCE MAXIMO.MAXSEQ TO ROLE MAXIMO_SEQ", + "GRANT ALTER ON SEQUENCE MAXIMO.MAXSEQ TO ROLE MAXIMO_SEQ", + ] + + for grant_sql in seq_grants: + try: + ibm_db.exec_immediate(conn, grant_sql) + print(f"āœ… Executed: {grant_sql}") + except Exception as e: + print(f"āš ļø Error executing grant: {str(e)}") + + # Grant permissions to EXPLAIN role + print("\nāœ… Granting permissions to EXPLAIN role...") + explain_grants = [ + "GRANT EXECUTE ON PACKAGE NULLID.SYSSH200 TO ROLE EXPLAIN", + "GRANT SELECT ON TABLE SYSTOOLS.EXPLAIN_INSTANCE TO ROLE EXPLAIN", + ] + + for grant_sql in explain_grants: + try: + ibm_db.exec_immediate(conn, grant_sql) + print(f"āœ… Executed: {grant_sql}") + except Exception as e: + print(f"āš ļø Error executing grant: {str(e)}") + + elif app_name == 'facilities': + # Grant permissions to TRIDATA_READ role + print("\nāœ… Granting permissions to TRIDATA_READ role...") + read_grants = [ + "GRANT SELECT ON TABLE TRIDATA.TRIDATA_DATA TO ROLE TRIDATA_READ", + "GRANT SELECT ON SCHEMA TRIDATA TO ROLE TRIDATA_READ", + ] + + for grant_sql in read_grants: + try: + ibm_db.exec_immediate(conn, grant_sql) + print(f"āœ… Executed: {grant_sql}") + except Exception as e: + print(f"āš ļø Error executing grant: {str(e)}") + + # Grant permissions to TRIDATA_WRITE role + print("\nāœ… Granting permissions to TRIDATA_WRITE role...") + write_grants = [ + "GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE TRIDATA.TRIDATA_DATA TO ROLE TRIDATA_WRITE", + "GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA TRIDATA TO ROLE TRIDATA_WRITE", + ] + + for grant_sql in write_grants: + try: + ibm_db.exec_immediate(conn, grant_sql) + print(f"āœ… Executed: {grant_sql}") + except Exception as e: + print(f"āš ļø Error executing grant: {str(e)}") + + elif app_name == 'iot': + # Grant permissions to IOT_READ role + print("\nāœ… Granting permissions to IOT_READ role...") + read_grants = [ + "GRANT SELECT ON TABLE IOT.IOT_DATA TO ROLE IOT_READ", + "GRANT SELECT ON SCHEMA IOT TO ROLE IOT_READ", + ] + + for grant_sql in read_grants: + try: + ibm_db.exec_immediate(conn, grant_sql) + print(f"āœ… Executed: {grant_sql}") + except Exception as e: + print(f"āš ļø Error executing grant: {str(e)}") + + # Grant permissions to IOT_WRITE role + print("\nāœ… Granting permissions to IOT_WRITE role...") + write_grants = [ + "GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE IOT.IOT_DATA TO ROLE IOT_WRITE", + "GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA IOT TO ROLE IOT_WRITE", + ] + + for grant_sql in write_grants: + try: + ibm_db.exec_immediate(conn, grant_sql) + print(f"āœ… Executed: {grant_sql}") + except Exception as e: + print(f"āš ļø Error executing grant: {str(e)}") + + print("\n" + "="*60) + print("āœ… Role creation and permission grants completed for all applications") + print("="*60) + + # Close connection + ibm_db.close(conn) + + except Exception as e: + print(f"Error: {str(e)}") + sys.exit(1) + EOFPYTHON + # IMPORTANT: Do not make any changes to the "EOFPYTHON" line above (including its indentation) + + echo "" + echo "Executing ${RDS_ROLES_SCRIPT}" + echo "--------------------------------------------------------------------------------" + python ${RDS_ROLES_SCRIPT} || exit $? + + echo "" + echo "RDS role creation job completed successfully" + + restartPolicy: Never + serviceAccountName: "{{ $sa_name }}" + volumes: [] + backoffLimit: 4 +{{- end }} +{{- end }} +{{- end }} diff --git a/root-applications/ibm-mas-instance-root/templates/510-550-ibm-mas-masapp-configs.yaml b/root-applications/ibm-mas-instance-root/templates/510-550-ibm-mas-masapp-configs.yaml index 63c34977d..11fdde87d 100644 --- a/root-applications/ibm-mas-instance-root/templates/510-550-ibm-mas-masapp-configs.yaml +++ b/root-applications/ibm-mas-instance-root/templates/510-550-ibm-mas-masapp-configs.yaml @@ -135,6 +135,51 @@ spec: {{- end }} {{- end }} {{- end }} + {{- if not (empty $.Values.ibm_dbs_rds_databases) }} + manage_rds_databases: + {{- range $j, $db := $.Values.ibm_dbs_rds_databases }} + {{- if eq $db.mas_application_id "manage" }} + - rds_host: {{ $db.host }} + rds_port: {{ $db.port | quote }} + rds_dbname: {{ $db.dbname }} + rds_instance_name: {{ $db.db2_instance_name }} + rds_admin_user: {{ $db.user }} + rds_admin_password: {{ $db.password }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + {{- if (eq $value.mas_app_id "facilities") }} + {{- if not (empty $.Values.ibm_dbs_rds_databases) }} + manage_rds_databases: + {{- range $j, $db := $.Values.ibm_dbs_rds_databases }} + {{- if eq $db.mas_application_id "facilities" }} + - rds_host: {{ $db.host }} + rds_port: {{ $db.port | quote }} + rds_dbname: {{ $db.dbname }} + rds_instance_name: {{ $db.db2_instance_name }} + rds_admin_user: {{ $db.user }} + rds_admin_password: {{ $db.password }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + + {{- if (eq $value.mas_app_id "iot") }} + {{- if not (empty $.Values.ibm_dbs_rds_databases) }} + manage_rds_databases: + {{- range $j, $db := $.Values.ibm_dbs_rds_databases }} + {{- if eq $db.mas_application_id "iot" }} + - rds_host: {{ $db.host }} + rds_port: {{ $db.port | quote }} + rds_dbname: {{ $db.dbname }} + rds_instance_name: {{ $db.db2_instance_name }} + rds_admin_user: {{ $db.user }} + rds_admin_password: {{ $db.password }} + {{- end }} + {{- end }} + {{- end }} {{- end }} {{- if $value.storage_class_definitions }} From e086e1afcaed3154cdedbacd33bd1e5cd2932bba Mon Sep 17 00:00:00 2001 From: amitpandey Date: Tue, 10 Feb 2026 18:37:40 +0530 Subject: [PATCH 04/11] Post sync job for users and role creation --- .../templates/703-postsync-rds-manage-roles.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml b/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml index 85bdd157f..2a1fea010 100644 --- a/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml +++ b/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml @@ -468,4 +468,3 @@ spec: backoffLimit: 4 {{- end }} {{- end }} -{{- end }} From c73830676ebe96936a697c688242b11869ed73b6 Mon Sep 17 00:00:00 2001 From: amitpandey Date: Tue, 10 Feb 2026 18:42:19 +0530 Subject: [PATCH 05/11] Post sync job for users and role creation --- ...es.yaml => 703-postsync-rds-app-roles.yaml} | 18 +++++++++--------- .../510-550-ibm-mas-masapp-configs.yaml | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) rename instance-applications/510-550-ibm-mas-suite-app-config/templates/{703-postsync-rds-manage-roles.yaml => 703-postsync-rds-app-roles.yaml} (97%) diff --git a/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml b/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-app-roles.yaml similarity index 97% rename from instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml rename to instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-app-roles.yaml index 2a1fea010..fffe56b44 100644 --- a/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-manage-roles.yaml +++ b/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-app-roles.yaml @@ -1,14 +1,14 @@ -{{- if not (empty .Values.manage_rds_databases) }} +{{- if not (empty .Values.mas_rds_databases) }} {{- /* Use the build/bin/set-cli-image-digest.sh script to update this value across all charts. */}} {{- $_cli_image_digest := "sha256:55b5d6dd185503f14c112836a9a4899347d28e7b6545e0b9cf21d87f9526fb40" }} -{{ $manage_ns := .Values.mas_app_namespace }} -{{ $np_name := "postsync-manage-rds-roles-np" }} -{{ $sa_name := "postsync-manage-rds-roles-sa" }} -{{ $job_label := "postsync-manage-rds-roles-job" }} +{{ $app_ns := .Values.mas_app_namespace }} +{{ $np_name := "postsync-app-rds-roles-np" }} +{{ $sa_name := "postsync-app-rds-roles-sa" }} +{{ $job_label := "postsync-app-rds-roles-job" }} --- {{- /* @@ -19,7 +19,7 @@ kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: {{ $np_name }} - namespace: {{ $manage_ns }} + namespace: {{ $app_ns }} annotations: argocd.argoproj.io/sync-wave: "703" {{- if .Values.custom_labels }} @@ -44,7 +44,7 @@ kind: ServiceAccount apiVersion: v1 metadata: name: "{{ $sa_name }}" - namespace: "{{ $manage_ns }}" + namespace: "{{ $app_ns }}" annotations: argocd.argoproj.io/sync-wave: "703" {{- if .Values.custom_labels }} @@ -60,7 +60,7 @@ metadata: NOTE: When inside the range loop below, make sure you prefix any references to chart values NOT under .Values.manage_rds_databases with $. For example: {{ $.Values.custom_labels }} (instead of {{ .Values.custom_labels }} ) */}} -{{- range $i, $db := .Values.manage_rds_databases }} +{{- range $i, $db := .Values.mas_rds_databases }} {{- /* Meaningful prefix for the job resource name. Must be under 52 chars in length to leave room for the 11 chars reserved for '-' and $_job_hash. @@ -122,7 +122,7 @@ apiVersion: batch/v1 kind: CronJob metadata: name: {{ $_cronjob_name }} - namespace: "{{ $manage_ns }}" + namespace: "{{ $app_ns }}" annotations: argocd.argoproj.io/sync-wave: "704" labels: diff --git a/root-applications/ibm-mas-instance-root/templates/510-550-ibm-mas-masapp-configs.yaml b/root-applications/ibm-mas-instance-root/templates/510-550-ibm-mas-masapp-configs.yaml index 11fdde87d..00ac53fb3 100644 --- a/root-applications/ibm-mas-instance-root/templates/510-550-ibm-mas-masapp-configs.yaml +++ b/root-applications/ibm-mas-instance-root/templates/510-550-ibm-mas-masapp-configs.yaml @@ -136,7 +136,7 @@ spec: {{- end }} {{- end }} {{- if not (empty $.Values.ibm_dbs_rds_databases) }} - manage_rds_databases: + mas_rds_databases: {{- range $j, $db := $.Values.ibm_dbs_rds_databases }} {{- if eq $db.mas_application_id "manage" }} - rds_host: {{ $db.host }} @@ -152,7 +152,7 @@ spec: {{- if (eq $value.mas_app_id "facilities") }} {{- if not (empty $.Values.ibm_dbs_rds_databases) }} - manage_rds_databases: + mas_rds_databases: {{- range $j, $db := $.Values.ibm_dbs_rds_databases }} {{- if eq $db.mas_application_id "facilities" }} - rds_host: {{ $db.host }} @@ -168,7 +168,7 @@ spec: {{- if (eq $value.mas_app_id "iot") }} {{- if not (empty $.Values.ibm_dbs_rds_databases) }} - manage_rds_databases: + mas_rds_databases: {{- range $j, $db := $.Values.ibm_dbs_rds_databases }} {{- if eq $db.mas_application_id "iot" }} - rds_host: {{ $db.host }} From 32830c479b45be0060a0ddde3942d11ec377d5bd Mon Sep 17 00:00:00 2001 From: amitpandey Date: Tue, 10 Feb 2026 18:44:06 +0530 Subject: [PATCH 06/11] Post sync job for users and role creation --- .../templates/01-dbs-rds-postsync-setup.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml b/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml index 15dc71749..c3717e574 100644 --- a/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml +++ b/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml @@ -126,18 +126,18 @@ spec: value: {{ .Values.dbname | quote }} - name: SSL_CERT_PATH value: "/etc/mas/rds-ssl/global-bundle.pem" - {{ - if .Values.db2_instance_registry }} + {{- if .Values.db2_instance_registry }} - name: DB2_INSTANCE_REGISTRY value: {{ .Values.db2_instance_registry | toJson | quote }} - {{ - end }} - {{ - if .Values.db2_database_db_config }} + {{- end }} + {{- if .Values.db2_database_db_config }} - name: DB2_DATABASE_CONFIG value: {{ .Values.db2_database_db_config | toJson | quote }} - {{ - end }} - {{ - if .Values.db2_instance_dbm_config }} + {{- end }} + {{- if .Values.db2_instance_dbm_config }} - name: DB2_INSTANCE_DBM_CONFIG value: {{ .Values.db2_instance_dbm_config | toJson | quote }} - {{ - end }} + {{- end }} {{ - if .Values.db2_addons_audit_config }} - name: ENABLE_AUDIT value: {{ .Values.db2_addons_audit_config.enableAudit | quote }} From 3e4280407a748256a92ba7e55940f37676d819da Mon Sep 17 00:00:00 2001 From: amitpandey Date: Tue, 10 Feb 2026 18:47:46 +0530 Subject: [PATCH 07/11] Post sync job for users and role creation --- .../templates/01-dbs-rds-postsync-setup.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml b/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml index c3717e574..b693e48a3 100644 --- a/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml +++ b/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml @@ -138,12 +138,12 @@ spec: - name: DB2_INSTANCE_DBM_CONFIG value: {{ .Values.db2_instance_dbm_config | toJson | quote }} {{- end }} - {{ - if .Values.db2_addons_audit_config }} + {{ - if .Values.db2_addons_audit_config }} - name: ENABLE_AUDIT value: {{ .Values.db2_addons_audit_config.enableAudit | quote }} - name: APPLY_DEFAULT_POLICY value: {{ .Values.db2_addons_audit_config.applyDefaultPolicy | quote }} - {{ - end }} + {{ - end }} volumeMounts: - name: dbs-rds-secret-store mountPath: /etc/mas/dbs-rds-creds/ From 3a607398315f4f04ed7eb3b094c4e98dc042be81 Mon Sep 17 00:00:00 2001 From: amitpandey Date: Tue, 10 Feb 2026 18:49:22 +0530 Subject: [PATCH 08/11] Post sync job for users and role creation --- .../templates/01-dbs-rds-postsync-setup.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml b/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml index b693e48a3..65a323368 100644 --- a/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml +++ b/instance-applications/120-ibm-dbs-rds-database/templates/01-dbs-rds-postsync-setup.yaml @@ -138,12 +138,12 @@ spec: - name: DB2_INSTANCE_DBM_CONFIG value: {{ .Values.db2_instance_dbm_config | toJson | quote }} {{- end }} - {{ - if .Values.db2_addons_audit_config }} + {{- if .Values.db2_addons_audit_config }} - name: ENABLE_AUDIT value: {{ .Values.db2_addons_audit_config.enableAudit | quote }} - name: APPLY_DEFAULT_POLICY value: {{ .Values.db2_addons_audit_config.applyDefaultPolicy | quote }} - {{ - end }} + {{- end }} volumeMounts: - name: dbs-rds-secret-store mountPath: /etc/mas/dbs-rds-creds/ From 20e71c3617cf20d4732d7c708fe49c6da1ec49d2 Mon Sep 17 00:00:00 2001 From: amitpandey Date: Wed, 11 Feb 2026 15:49:06 +0530 Subject: [PATCH 09/11] Post sync job for users and role creation --- .../00-presync-create-db2-rds-user-Job.yaml | 140 +++++++++++++----- 1 file changed, 105 insertions(+), 35 deletions(-) diff --git a/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml b/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml index 873a7575b..0a09fd1b0 100644 --- a/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml +++ b/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml @@ -167,54 +167,81 @@ spec: print(f"MAS Application ID: {mas_app_id}") print(f"JDBC Username: {jdbc_username}") - # Define all app-specific admin users to create - # Create users for all three app types regardless of current MAS_APP_ID - users_to_create = [ + # Option 2: Create TWO types of users + # 1. Admin users: We CREATE these with DBADM (for schema management) + # 2. Non-admin user: We FETCH from AWS Secrets Manager and grant only app roles (for runtime) + + # Admin users to CREATE (with DBADM) + admin_users_to_create = [ { 'username': 'DB2_manage', 'role': 'DBADM', - 'grants': ['MAXIMO_READ', 'MAXIMO_WRITE'], - 'description': 'Manage Admin User', + 'description': 'Manage Admin User (DBADM for schema management)', 'app_type': 'manage' }, { 'username': 'DB2_facilities', 'role': 'DBADM', - 'grants': ['TRIDATA_READ', 'TRIDATA_WRITE'], - 'description': 'Facilities Admin User', + 'description': 'Facilities Admin User (DBADM for schema management)', 'app_type': 'facilities' }, { 'username': 'DB2_iot', 'role': 'DBADM', - 'grants': [], - 'description': 'IoT Admin User', + 'description': 'IoT Admin User (DBADM for schema management)', 'app_type': 'iot' } ] - print(f"\nāœ… Creating users for all MAS applications (manage, facilities, iot)") + # Non-admin user from AWS Secrets Manager (grant only app roles) + # Note: IoT does NOT get non-admin roles - only admin user with DBADM + nonadmin_user_roles = [ + { + 'username': jdbc_username, # From AWS Secrets Manager + 'grants': ['MAXIMO_READ', 'MAXIMO_WRITE', 'MAXIMO_SEQ', 'EXPLAIN'], + 'description': 'Manage Application User (from AWS Secrets Manager)', + 'app_type': 'manage' + }, + { + 'username': jdbc_username, + 'grants': ['TRIDATA_READ', 'TRIDATA_WRITE'], + 'description': 'Facilities Application User (from AWS Secrets Manager)', + 'app_type': 'facilities' + } + # IoT: No non-admin roles - uses admin user (DB2_iot) with DBADM only + ] + + print(f"\nāœ… Creating users:") + print(f" 1. Admin users: DB2_manage, DB2_facilities, DB2_iot (DBADM)") + print(f" 2. Non-admin user: {jdbc_username} (App roles for Manage & Facilities only)") + print(f" Note: IoT uses admin user (DB2_iot) with DBADM only") try: # Connect to the database conn = ibm_db.connect(conn_str, "", "") print("āœ… Successfully connected to RDS DB2") - for user_info in users_to_create: - username = user_info['username'] - role_to_assign = user_info['role'] - grants = user_info['grants'] - description = user_info['description'] + # ======================================================================== + # STEP 1: Create Admin Users with DBADM + # ======================================================================== + print(f"\n{'='*80}") + print("STEP 1: Creating Admin Users (DBADM)") + print(f"{'='*80}") + + for admin_user in admin_users_to_create: + username = admin_user['username'] + role_to_assign = admin_user['role'] + description = admin_user['description'] + app_type = admin_user['app_type'] - print(f"\n{'='*80}") - print(f"Processing: {description}") + print(f"\n--- Processing: {description} ---") print(f"Username: {username}") - print(f"{'='*80}") + print(f"App Type: {app_type}") # Check if user exists check_user_sql = f""" - SELECT COUNT(*) as user_count - FROM SYSIBM.SYSDBAUTH + SELECT COUNT(*) as user_count + FROM SYSIBM.SYSDBAUTH WHERE GRANTEE = '{username}' """ @@ -226,31 +253,74 @@ spec: if user_exists: print(f"ā„¹ļø User {username} already exists") else: - # Create user - Note: In RDS DB2, users are typically created externally - # This grants database privileges to the user - print(f"āœ… Granting {role_to_assign} privileges to {username}") - grant_dbadm_sql = f"GRANT {role_to_assign} ON DATABASE TO USER {username}" - try: - ibm_db.exec_immediate(conn, grant_dbadm_sql) - print(f"āœ… Granted {role_to_assign} to {username}") - except Exception as e: - print(f"āš ļø Error granting {role_to_assign}: {str(e)}") + print(f"āœ… Creating user {username} with {role_to_assign}") + + # Grant DBADM to user + grant_dbadm_sql = f"GRANT {role_to_assign} ON DATABASE TO USER {username}" + try: + ibm_db.exec_immediate(conn, grant_dbadm_sql) + print(f"āœ… Granted {role_to_assign} to {username}") + except Exception as e: + print(f"āš ļø Error granting {role_to_assign}: {str(e)}") except Exception as e: - print(f"āš ļø Error checking user {username}: {str(e)}") + print(f"āš ļø Error processing user {username}: {str(e)}") + + # ======================================================================== + # STEP 2: Grant Application Roles to Non-Admin User (from AWS Secrets) + # ======================================================================== + print(f"\n{'='*80}") + print("STEP 2: Granting Application Roles to Non-Admin User") + print(f"{'='*80}") + print(f"Non-admin user: {jdbc_username} (from AWS Secrets Manager)") + + # Check if non-admin user exists + check_user_sql = f""" + SELECT COUNT(*) as user_count + FROM SYSIBM.SYSDBAUTH + WHERE GRANTEE = '{jdbc_username}' + """ + + try: + stmt = ibm_db.exec_immediate(conn, check_user_sql) + result = ibm_db.fetch_assoc(stmt) + user_exists = result['USER_COUNT'] > 0 + + if user_exists: + print(f"āœ… User {jdbc_username} exists in database") + else: + print(f"āš ļø User {jdbc_username} not found in database") + print(f" Note: User should be created externally in AWS RDS") + + except Exception as e: + print(f"āš ļø Error checking user {jdbc_username}: {str(e)}") + + # Grant application-specific roles to non-admin user + for user_info in nonadmin_user_roles: + grants = user_info['grants'] + description = user_info['description'] + app_type = user_info['app_type'] + + print(f"\n--- Processing: {description} ---") + print(f"App Type: {app_type}") - # Grant role permissions + # Grant application role permissions if grants: - print(f"\nāœ… Granting role permissions to {username}...") + print(f"āœ… Granting {app_type} application roles to {jdbc_username}...") for grant_role in grants: try: - grant_role_sql = f"GRANT ROLE {grant_role} TO USER {username}" + grant_role_sql = f"GRANT ROLE {grant_role} TO USER {jdbc_username}" ibm_db.exec_immediate(conn, grant_role_sql) - print(f"āœ… Granted role {grant_role} to {username}") + print(f"āœ… Granted role {grant_role} to {jdbc_username}") except Exception as e: print(f"āš ļø Error granting role {grant_role}: {str(e)}") + print(f" Note: Role {grant_role} may not exist yet. It will be created by the role creation job.") - print("\nāœ… App-specific admin user creation and permission grants completed successfully") + print(f"\n{'='*80}") + print("āœ… User creation and role assignment completed successfully") + print(f"{'='*80}") + print(f"Admin users: DB2_manage, DB2_facilities, DB2_iot (DBADM)") + print(f"Non-admin user: {jdbc_username} (Application roles only)") # Close connection ibm_db.close(conn) From b73d3dde4d927838822da661ab92cbf8692e4e19 Mon Sep 17 00:00:00 2001 From: amitpandey Date: Wed, 11 Feb 2026 18:08:42 +0530 Subject: [PATCH 10/11] Post sync job for users and role creation --- .../00-presync-create-db2-rds-user-Job.yaml | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml b/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml index 0a09fd1b0..d7a3f6519 100644 --- a/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml +++ b/instance-applications/130-ibm-jdbc-config/templates/00-presync-create-db2-rds-user-Job.yaml @@ -253,15 +253,25 @@ spec: if user_exists: print(f"ā„¹ļø User {username} already exists") else: - print(f"āœ… Creating user {username} with {role_to_assign}") + print(f"āœ… Creating user {username} with comprehensive admin privileges") - # Grant DBADM to user - grant_dbadm_sql = f"GRANT {role_to_assign} ON DATABASE TO USER {username}" - try: - ibm_db.exec_immediate(conn, grant_dbadm_sql) - print(f"āœ… Granted {role_to_assign} to {username}") - except Exception as e: - print(f"āš ļø Error granting {role_to_assign}: {str(e)}") + # Grant comprehensive admin privileges to user + admin_grants = [ + f"GRANT DBADM, CREATETAB, BINDADD, CONNECT, CREATE_NOT_FENCED_ROUTINE, IMPLICIT_SCHEMA, LOAD, CREATE_EXTERNAL_ROUTINE, QUIESCE_CONNECT ON DATABASE TO USER {username}", + f"GRANT USE OF TABLESPACE MAXDATA TO USER {username}", + f"GRANT DBADM WITHOUT DATAACCESS WITHOUT ACCESSCTRL ON DATABASE TO USER {username}", + f"GRANT SECADM ON DATABASE TO USER {username}", + f"GRANT DATAACCESS ON DATABASE TO USER {username}", + f"GRANT ACCESSCTRL ON DATABASE TO USER {username}" + ] + + for grant_sql in admin_grants: + try: + ibm_db.exec_immediate(conn, grant_sql) + print(f"āœ… Executed: {grant_sql}") + except Exception as e: + print(f"āš ļø Error executing grant: {str(e)}") + print(f" SQL: {grant_sql}") except Exception as e: print(f"āš ļø Error processing user {username}: {str(e)}") From 25b5dd2b97f405c7c940c54a9de10a4b401ad143 Mon Sep 17 00:00:00 2001 From: amitpandey Date: Wed, 11 Feb 2026 21:26:52 +0530 Subject: [PATCH 11/11] Post sync job for users and role creation --- .../templates/703-postsync-rds-app-roles.yaml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-app-roles.yaml b/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-app-roles.yaml index fffe56b44..75fa7d90f 100644 --- a/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-app-roles.yaml +++ b/instance-applications/510-550-ibm-mas-suite-app-config/templates/703-postsync-rds-app-roles.yaml @@ -245,7 +245,8 @@ spec: ) print(f"Connecting to RDS DB2 instance: {rds_host}:{rds_port}/{rds_dbname}") - print("Creating roles for all MAS applications: manage, facilities, iot") + print("Creating roles for MAS applications: manage, facilities") + print("Note: IoT uses admin user (DB2_iot) with full admin privileges - no separate roles") try: # Connect to the database @@ -253,6 +254,7 @@ spec: print("āœ… Successfully connected to RDS DB2") # Define app configurations with table checks and roles + # Note: IoT is NOT included - it uses admin user (DB2_iot) with full privileges only app_configs = [ { 'app_name': 'manage', @@ -265,13 +267,8 @@ spec: 'schema': 'TRIDATA', 'check_table': 'TRIDATA_DATA', 'roles': ['TRIDATA_READ', 'TRIDATA_WRITE'] - }, - { - 'app_name': 'iot', - 'schema': 'IOT', - 'check_table': 'IOT_DATA', - 'roles': ['IOT_READ', 'IOT_WRITE'] } + # IoT: No roles created - uses DB2_iot admin user with full privileges ] # Process each app configuration