Update nexus: fix conflicts and sync local changes
This commit is contained in:
@@ -1,470 +1,470 @@
|
||||
# SaaS-Change-UPN-Script-Runbook_686074283
|
||||
## Introduction
|
||||
|
||||
There are many scenarios where customers may need to update UPNs, such as domain migrations or company mergers. This runbook will guide the Operations team to migrate customers' UPNs using a defined mapping table.
|
||||
|
||||
## Preparation
|
||||
|
||||
- Tenant admin should not be included
|
||||
- User migration mapping file (CSV), including old UPN, old Email, new UPN, below is the template:
|
||||
- Sample CSV format:
|
||||
| oldUpn | newUpn | oldEmail | newEmail |
|
||||
| --- | --- | --- | --- |
|
||||
| xiao1 | xiao1\_New | [xiao1\_New@microfocus.com](mailto:xiao1_New@opentext.com) | [xiao1\_New@opentext.com](mailto:xiao1_New@opentext.com) |
|
||||
| xiao2 | xiao2\_New | [xiao2\_New@](mailto:xiao2_New@opentext.com) [microfocus.com](mailto:xiao1_New@opentext.com) | [xiao2\_New@opentext.com](mailto:xiao2_New@opentext.com) |
|
||||
| userTKit05 | userTKit055 | [userTKit055@](mailto:userTKit055@opentext.com) [microfocus.com](mailto:xiao1_New@opentext.com) | [userTKit055@opentext.com](mailto:userTKit055@opentext.com) |
|
||||
- Make sure no duplicate users in mapping file
|
||||
- Make sure the migrated users should not exist in SMAX
|
||||
|
||||
## Check PAT accounts
|
||||
|
||||
Go into IdM's database.
|
||||
|
||||
1. Get the uuid for target tenant.
|
||||
|
||||
```
|
||||
select uuid,name from <idm_schema>.organizations where name =<tenant_id>
|
||||
```
|
||||
|
||||
2\. List PAT users by uuid
|
||||
|
||||
```
|
||||
select au.name, au.organization, at2.uuid from <idm_schema>.api_token at2, <idm_schema>.abstract_user au where at2.user_id=au.uuid and au.organization=<uuid>;
|
||||
```
|
||||
|
||||
3.Inform the above users that they need to use a new UPN to obtain token after migrate if they use the UPN to get the PAT token before.
|
||||
|
||||
The admin user may use an api call(api/scim/organizations/<org-id>/users/<user\_id>/access-tokens) to get other ordinary user's token. The <user\_id> may be uuid or UPN, if it's UPN, it needs to be switched to a new one.
|
||||
|
||||
### Find out the user set that user's OT UPN are already existed in SMAX
|
||||
|
||||
#### BO
|
||||
|
||||
Go to BO's DB
|
||||
|
||||
a. Create a temp mapping table
|
||||
|
||||
```
|
||||
create table <bo_user_schema>.mf_ot_user_mapping
|
||||
(
|
||||
old_upn varchar(512) not null
|
||||
constraint unique_old_upn
|
||||
unique,
|
||||
new_upn varchar(512) not null
|
||||
constraint unique_new_upn
|
||||
unique,
|
||||
old_email varchar(512) not null,
|
||||
new_email varchar(512) not null
|
||||
);
|
||||
```
|
||||
|
||||
b. Copy csv data
|
||||
|
||||
```
|
||||
\copy <bo_user_schema>.mf_ot_user_mapping(old_upn,new_upn,old_email,new_email) FROM '<csv_path>' DELIMITER ',' CSV HEADER;
|
||||
```
|
||||
|
||||
c. Find out users
|
||||
|
||||
```
|
||||
select distinct des.* from <bo_user_schema>.user_entity nu inner join
|
||||
(select mp.* from <bo_user_schema>.mf_ot_user_mapping mp inner join <bo_user_schema>.user_entity u on lower(mp.old_upn) = lower(u.name) and lower(mp.old_upn) !=lower(mp.new_upn) and u.is_deleted=false where u.idm_organization='<tenant_id>') des
|
||||
on lower(nu.name)=lower(des.new_upn) and nu.is_deleted=false and nu.idm_organization='<tenant_id>';
|
||||
```
|
||||
|
||||
Collect the results
|
||||
|
||||
d. drop the temp table
|
||||
|
||||
```
|
||||
drop table <bo_user_schema>.mf_ot_user_mapping
|
||||
```
|
||||
|
||||
#### IdM
|
||||
|
||||
Go to IdM's DB
|
||||
|
||||
a. Create a temp mapping table
|
||||
|
||||
```
|
||||
create table <idm_schema>.mf_ot_user_mapping
|
||||
(
|
||||
old_upn varchar(512) not null
|
||||
constraint unique_old_upn
|
||||
unique,
|
||||
new_upn varchar(512) not null
|
||||
constraint unique_new_upn
|
||||
unique,
|
||||
old_email varchar(512) not null,
|
||||
new_email varchar(512) not null
|
||||
);
|
||||
```
|
||||
|
||||
b. Copy csv data
|
||||
|
||||
```
|
||||
\copy <idm_schema>.mf_ot_user_mapping(old_upn,new_upn,old_email,new_email) FROM '<csv_path>' DELIMITER ',' CSV HEADER;
|
||||
```
|
||||
|
||||
c. Find out users
|
||||
|
||||
```
|
||||
select distinct des.* from <idm_schema>.abstract_user nu inner join
|
||||
(select mp.* from <idm_schema>.mf_ot_user_mapping mp inner join <idm_schema>.abstract_user u on lower(mp.old_upn)=lower(u.name) and lower(mp.old_upn) !=lower(mp.new_upn) where u.organization=(select uuid from <idm_schema>.organizations where name='<tenant_id>')) as des
|
||||
on lower(nu.name)=lower(des.new_upn) and nu.organization=(select uuid from <idm_schema>.organizations where name='<tenant_id>');
|
||||
```
|
||||
|
||||
Collect the resluts
|
||||
|
||||
d. drop the temp table
|
||||
|
||||
```
|
||||
drop table <idm_schema>.mf_ot_user_mapping
|
||||
```
|
||||
|
||||
#### EMS
|
||||
|
||||
Since we need to select Person's upn from entities\_<tenant\_id>, we need to get Tenant version from RMS's DB first.
|
||||
|
||||
Go to RMS's DB
|
||||
|
||||
- Get tenant version
|
||||
|
||||
```
|
||||
select body -> 'tenant' ->> 'version' from <rms_schema>."TenantData_857561481" where body -> 'tenant' ->> 'tenantId' = '<tenant_id>';
|
||||
```
|
||||
|
||||
Go to EMS's DB
|
||||
|
||||
a. Create a temp mapping table
|
||||
|
||||
```
|
||||
create table <ems_schema>.mf_ot_user_mapping
|
||||
(
|
||||
old_upn varchar(512) not null
|
||||
constraint unique_old_upn
|
||||
unique,
|
||||
new_upn varchar(512) not null
|
||||
constraint unique_new_upn
|
||||
unique,
|
||||
old_email varchar(512) not null,
|
||||
new_email varchar(512) not null
|
||||
);
|
||||
```
|
||||
|
||||
b. Copy csv data
|
||||
|
||||
```
|
||||
\copy <ems_schema>.mf_ot_user_mapping(old_upn,new_upn,old_email,new_email) FROM '<csv_path>' DELIMITER ',' CSV HEADER;
|
||||
```
|
||||
|
||||
c. Find out users for tenant
|
||||
|
||||
- Get physical\_type\_name(Replace <tenant\_version> with the tenant version that get from RMS)
|
||||
|
||||
```
|
||||
select physical_type_name from <ems_schema>.entityDescriptor_mapping where entity_type = 'Person' AND tenant_id = '<tenant_version>' AND logical_type_name = 'Upn';
|
||||
```
|
||||
|
||||
- Get entity\_type\_id(Replace <tenant\_version> with the tenant version that get from RMS)
|
||||
|
||||
```
|
||||
select id from "entity_descriptor" where tenant_id = '<tenant_version>' and name = 'Person';
|
||||
```
|
||||
|
||||
Find out users(Replace <physical\_type\_name>,<entity\_type\_id> with the physical\_type\_name, entity\_type\_id that get from above)
|
||||
|
||||
```
|
||||
select distinct des.* from <ems_schema>.entities_<tenant_id> nu inner join
|
||||
(select mp.* from <ems_schema>.mf_ot_user_mapping mp inner join <ems_schema>.entities_<tenant_id> u on lower(mp.old_upn) = lower(u.<physical_type_name>) and lower(mp.old_upn) !=lower(mp.new_upn) and u.is_deleted=false and u.entity_type_id=<entity_type_id> ) des
|
||||
on lower(nu.<physical_type_name>)=lower(des.new_upn) and nu.is_deleted=false and nu.entity_type_id=<entity_type_id>;
|
||||
```
|
||||
|
||||
Collect the results.
|
||||
|
||||
d. drop the temp table
|
||||
|
||||
```
|
||||
drop table <ems_schema>.mf_ot_user_mapping
|
||||
```
|
||||
|
||||
#### RMS
|
||||
|
||||
Go to RMS's DB
|
||||
|
||||
a. Create a temp mapping table
|
||||
|
||||
```
|
||||
create table <rms_schema>.mf_ot_user_mapping
|
||||
(
|
||||
old_upn varchar(512) not null
|
||||
constraint unique_old_upn
|
||||
unique,
|
||||
new_upn varchar(512) not null
|
||||
constraint unique_new_upn
|
||||
unique,
|
||||
old_email varchar(512) not null,
|
||||
new_email varchar(512) not null
|
||||
);
|
||||
```
|
||||
|
||||
b. Copy csv data
|
||||
|
||||
```
|
||||
\copy <rms_schema>.mf_ot_user_mapping(old_upn,new_upn,old_email,new_email) FROM '<csv_path>' DELIMITER ',' CSV HEADER;
|
||||
```
|
||||
|
||||
c. Find out users for tenant
|
||||
|
||||
```
|
||||
select distinct des.* from <rms_schema>."AuthorizationPrincipalResourceJSON_<tenant_id>" nu inner join
|
||||
(select mp.* from <rms_schema>.mf_ot_user_mapping mp inner join <rms_schema>."AuthorizationPrincipalResourceJSON_<tenant_id>" u on lower(mp.old_upn) = lower(u.body ->> 'UserId') and lower(mp.old_upn) !=lower(mp.new_upn)) des
|
||||
on lower(nu.body ->> 'UserId')=lower(des.new_upn);
|
||||
```
|
||||
|
||||
Collect the results.
|
||||
|
||||
d. drop the temp table
|
||||
|
||||
```
|
||||
drop table <rms_schema>.mf_ot_user_mapping
|
||||
```
|
||||
|
||||
**In summary, we need to get the union of all the records from BO, IdM, EMS and RMS, Then cut this part of the data from the csv file.**
|
||||
|
||||
### 1.Actions in Suite
|
||||
|
||||
- Disable User sync in the account
|
||||
|
||||
Login to Suite Administration:
|
||||
|
||||
ACCOUNTS>General>User auto-sync
|
||||
|
||||

|
||||
|
||||
- Change the tenant to Inactive
|
||||
|
||||
Login to Suite Administration:
|
||||
|
||||
TENANTS>General>Inactive
|
||||
|
||||

|
||||
|
||||
- Stop the external integration in the tenant
|
||||
- Do NOT do any write action(Create/Update/Delete) on Users
|
||||
- Delete the SAML authentication config in IdM
|
||||
|
||||
Login to Suite Administration:
|
||||
|
||||
TENANTS>IdM settings>Authentication
|
||||
|
||||

|
||||
|
||||
### 2.Backup Databases:
|
||||
|
||||
Ensure backups of the following databases are taken before initiating changes:
|
||||
|
||||
- **Suite Administration** service database:
|
||||
- `bo_user`
|
||||
- `user_entity`
|
||||
|
||||
```
|
||||
create table <schema>.user_entity_v0 as select * from <schema>.user_entity;
|
||||
```
|
||||
|
||||
- **IDM** service database:
|
||||
- `idm`
|
||||
- `abstract_user`
|
||||
- `abstract_user_metadata`
|
||||
- `abstract_user_profile`
|
||||
|
||||
```
|
||||
create table <schema>.abstract_user_v0 as select * from <schema>.abstract_user;
|
||||
create table <schema>.abstract_user_metadata_v0 as select * from <schema>.abstract_user_metadata;
|
||||
create table <schema>.abstract_user_profile_v0 as select * from <schema>.abstract_user_profile;
|
||||
```
|
||||
|
||||
- XServices databases:
|
||||
- `xservices_ems`
|
||||
- entities\_<Target\_tenant\_Id> `eg:entities_140038523`
|
||||
|
||||
```
|
||||
create table <schema>.entities_<tenant_id>_v0 as select * from <schema>.entities_<tenant_id>;
|
||||
```
|
||||
|
||||
- - `xservices_rms`
|
||||
- AuthorizationPrincipalResourceJSON\_<Target\_tenant\_Id> `eg:AuthorizationPrincipalResourceJSON_140038523`
|
||||
|
||||
```
|
||||
create table <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>_v0" as select * FROM <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>";
|
||||
```
|
||||
|
||||
Please note the single and double **quotes**
|
||||
|
||||
**Note: Please replace the value in <> according to the actual environment**
|
||||
|
||||
### 3.Prepare user Data
|
||||
|
||||
Provide a CSV file containing the new UPNs and corresponding old UPNs and new Emails.
|
||||
|
||||
Sample CSV format:
|
||||
|
||||
| oldUpn | newUpn | oldEmail | newEmail |
|
||||
| --- | --- | --- | --- |
|
||||
| xiao1 | xiao1\_New | [xiao1\_New@microfocus.com](mailto:xiao1_New@opentext.com) | [xiao1\_New@opentext.com](mailto:xiao1_New@opentext.com) |
|
||||
| xiao2 | xiao2\_New | [xiao2\_New@](mailto:xiao2_New@opentext.com) [microfocus.com](mailto:xiao1_New@opentext.com) | [xiao2\_New@opentext.com](mailto:xiao2_New@opentext.com) |
|
||||
| userTKit05 | userTKit055 | [userTKit055@](mailto:userTKit055@opentext.com) [microfocus.com](mailto:xiao1_New@opentext.com) | [userTKit055@opentext.com](mailto:userTKit055@opentext.com) |
|
||||
|
||||
**We can choose a small data set to test firstly, validate these users. If everything goes fine, we can do with the rest files.**
|
||||
|
||||
## Run Script
|
||||
|
||||
#### Notes:
|
||||
|
||||
1. This script needs to provide the old and new upn, as well as the email, the file format should be.csv.
|
||||
2. In addition, you need to specify the column number of the column corresponding to the new/old UPN and old/new Email of the corresponding file and the row number starting from the line.
|
||||
3. You must have the "root" privilege to execute the script.
|
||||
4. Script package should include two files: **changeUserUpn.sh** and **change**, and put these two files in the same level directory.
|
||||
5. The account for updating UPN should be of 3in1 type, which means that the account id and tenant id should be the same.
|
||||
6. In IdM, this script is only update for SAML users, which means that if you are using non-SAML integrated authentication, this script is not suitable
|
||||
7. Before the script runs, you need to back up the database
|
||||
8. Before the script runs, you need to turn off the user sync of the account, and you need to set the tenant to " **Inactive** ", and stop the external integration on the tenant
|
||||
|
||||
#### Follow these steps:
|
||||
|
||||
1. Upload the scripts file and User data csv file to the bastion/master node of the suite
|
||||
2. Log in to the bastion/master node as a root user, copy the scripts and data file to the toolkit pod, grant executable permissions to scripts and file.
|
||||
3. Go into the toolkit pod and run the following command in the directory where the script is located: `sh changeUserUpn.sh -a <account_id>` Where <account\_id> is the ID of the account which you want to change these users under the account. For example, `sh changeUserUpn.sh -a 123456789`
|
||||
4. Follow the prompts step by step to continue executing the script
|
||||
|
||||
**The script will be executed after you put the correct line number in mapping file.**And you can see following messages after the script is successful executed:
|
||||
|
||||

|
||||
|
||||
## Validation
|
||||
|
||||
Firstly, You can check whether the user's upn and email are updated correctly in IdM/BO and SAW. If it's OK, you need to
|
||||
|
||||
- configure OT's SAML in IdM
|
||||
- Active Tenant and turn on User auto-sync in BO.
|
||||
|
||||
Then you can do some regular validation such as:
|
||||
|
||||
- The user account's UPN doesn't change before/after migration
|
||||
To verify after SAML login the user can match to the original user account and role/permission settings aren’t changed
|
||||
- The user account's UPN has been changed after migration
|
||||
To verify after SAML login the user can match to the original user account and role/permission settings aren’t changed
|
||||
To verify after SAML login the user information can be updated to new IDP information, such as email can be updated to OT email
|
||||
- The user account never login SMAX tenant
|
||||
To verify the new SAML user account can be created properly with new UPN in both BO and Tenant
|
||||
|
||||
## Rollback
|
||||
|
||||
If you need to rollback, just rollback the database that has been backed up.
|
||||
|
||||
### Primary rollback:
|
||||
|
||||
You can re-run the change UPN script and specify the old UPN and new UPN with reversed column numbers.
|
||||
|
||||
### Secondary rollback:
|
||||
|
||||
- **Suite Administration** service database:
|
||||
- `bo_user`
|
||||
|
||||
```
|
||||
create table <schema>.user_entity_v1 as select * from <schema>.user_entity;
|
||||
|
||||
update <schema>.user_entity as S set name = B.name, email = B.email
|
||||
from <schema>.user_entity_v0 as B
|
||||
where S.id = B.id
|
||||
and S.account_id = '<tenant_id>';
|
||||
```
|
||||
|
||||
IDM:
|
||||
|
||||
- IDM service database:
|
||||
- `idm`
|
||||
|
||||
```
|
||||
create table <schema>.abstract_user_v1 as select * from <schema>.abstract_user;
|
||||
create table <schema>.abstract_user_metadata_v1 as select * from <schema>.abstract_user_metadata;
|
||||
create table <schema>.abstract_user_profile_v1 as select * from <schema>.abstract_user_profile;
|
||||
|
||||
update <schema>.abstract_user as au set name=bak.name, display_name=bak.display_name, name_lower=bak.name_lower from <schema>.abstract_user_v0 bak where au.uuid=bak.uuid and au.organization='<tenant_uuid>';
|
||||
|
||||
update <schema>.abstract_user_metadata as am set field_value=bak.field_value, field_value_lower=bak.field_value_lower from <schema>.abstract_user au, abstract_user_metadata_v0 bak where am.field_key='username' and am.uuid=bak.uuid and bak.uuid=au.uuid and au.organization='<tenant_uuid>';
|
||||
|
||||
update <schema>.abstract_user_metadata as am set field_value=bak.field_value, field_value_lower=bak.field_value_lower from <schema>.abstract_user au, abstract_user_metadata_v0 bak where am.field_key='email' and am.uuid=bak.uuid and bak.uuid=au.uuid and au.organization='<tenant_uuid>';
|
||||
|
||||
update <schema>.abstract_user_profile as ap set user_name=bak.user_name, email=bak.email from <schema>.abstract_user au, abstract_user_profile_v0 bak where ap.uuid=bak.uuid and ap.user_id=au.uuid and au.organization='<tenant_uuid>';
|
||||
```
|
||||
|
||||
- XServices databases:
|
||||
- `xservices_ems`
|
||||
|
||||
```
|
||||
create table <schema>.entities_<tenant_id>_v1 as select * from <schema>.entities_<tenant_id>;
|
||||
|
||||
-- get entity type id:
|
||||
SELECT DISTINCT id, name FROM <schema>.entity_descriptor WHERE name in ('Person');
|
||||
|
||||
-- get tenant_version such as v27.
|
||||
|
||||
-- get UPN field name: (such as schar1)
|
||||
select physical_type_name from <schema>.entityDescriptor_mapping where entity_type = 'Person' AND tenant_id = '<tenant_version>' AND logical_type_name = 'Upn';
|
||||
|
||||
-- get email field name: (such as schar2)
|
||||
select physical_type_name from <schema>.entityDescriptor_mapping where entity_type = 'Person' AND tenant_id = '<tenant_version>' AND logical_type_name = 'Email';
|
||||
|
||||
update <schema>.entities_<tenant_id> as S set <UPN_field_name> = B.<UPN_field_name>, <email_field_name> = B.<email_field_name>
|
||||
from <schema>.entities_<tenant_id>_v0 as B
|
||||
where S.entity_id = B.entity_id
|
||||
and S.entity_type_id = '<entity_type_id>';
|
||||
```
|
||||
|
||||
- - `xservices_rms`
|
||||
|
||||
```
|
||||
alter table <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>" rename to "AuthorizationPrincipalResourceJSON_<tenant_id>_v1";
|
||||
|
||||
create table <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>" as select * FROM <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>_v0";
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Empty mapping file
|
||||
|
||||
If you see this msg that means the.csv file is empty.
|
||||
|
||||
```
|
||||
Try to read the file that mappings of user UPN and Email.
|
||||
time="2024-03-11 16:21:54" level=error msg="The user mappings file is empty."
|
||||
The user mappings file is empty.
|
||||
```
|
||||
|
||||
### Empty parameter
|
||||
|
||||
```
|
||||
time="2024-03-11 17:50:02" level=error msg="Required param is EMPTY,OriginName:test1,NewName:,OriginEmail:test1,NewEmail:test1"
|
||||
Required param is EMPTY,OriginName:test1,NewName:,OriginEmail:test1,NewEmail:test1
|
||||
```
|
||||
|
||||
If you see this msg that means the NewName is empty.
|
||||
|
||||
### Duplicated user
|
||||
|
||||
If you get this error, go to the Preparation and follow actions to find out the duplicated users.
|
||||
|
||||

|
||||
|
||||
More information will be added during next testing.
|
||||
|
||||
## Script Files
|
||||
|
||||
change
|
||||
|
||||
[change](attachments/686074283/686074285)
|
||||
|
||||
changeUserUpn.sh
|
||||
|
||||
[changeUserUpn.sh](attachments/686074283/686074286.sh)
|
||||
# SaaS-Change-UPN-Script-Runbook_686074283
|
||||
## Introduction
|
||||
|
||||
There are many scenarios where customers may need to update UPNs, such as domain migrations or company mergers. This runbook will guide the Operations team to migrate customers' UPNs using a defined mapping table.
|
||||
|
||||
## Preparation
|
||||
|
||||
- Tenant admin should not be included
|
||||
- User migration mapping file (CSV), including old UPN, old Email, new UPN, below is the template:
|
||||
- Sample CSV format:
|
||||
| oldUpn | newUpn | oldEmail | newEmail |
|
||||
| --- | --- | --- | --- |
|
||||
| xiao1 | xiao1\_New | [xiao1\_New@microfocus.com](mailto:xiao1_New@opentext.com) | [xiao1\_New@opentext.com](mailto:xiao1_New@opentext.com) |
|
||||
| xiao2 | xiao2\_New | [xiao2\_New@](mailto:xiao2_New@opentext.com) [microfocus.com](mailto:xiao1_New@opentext.com) | [xiao2\_New@opentext.com](mailto:xiao2_New@opentext.com) |
|
||||
| userTKit05 | userTKit055 | [userTKit055@](mailto:userTKit055@opentext.com) [microfocus.com](mailto:xiao1_New@opentext.com) | [userTKit055@opentext.com](mailto:userTKit055@opentext.com) |
|
||||
- Make sure no duplicate users in mapping file
|
||||
- Make sure the migrated users should not exist in SMAX
|
||||
|
||||
## Check PAT accounts
|
||||
|
||||
Go into IdM's database.
|
||||
|
||||
1. Get the uuid for target tenant.
|
||||
|
||||
```
|
||||
select uuid,name from <idm_schema>.organizations where name =<tenant_id>
|
||||
```
|
||||
|
||||
2\. List PAT users by uuid
|
||||
|
||||
```
|
||||
select au.name, au.organization, at2.uuid from <idm_schema>.api_token at2, <idm_schema>.abstract_user au where at2.user_id=au.uuid and au.organization=<uuid>;
|
||||
```
|
||||
|
||||
3.Inform the above users that they need to use a new UPN to obtain token after migrate if they use the UPN to get the PAT token before.
|
||||
|
||||
The admin user may use an api call(api/scim/organizations/<org-id>/users/<user\_id>/access-tokens) to get other ordinary user's token. The <user\_id> may be uuid or UPN, if it's UPN, it needs to be switched to a new one.
|
||||
|
||||
### Find out the user set that user's OT UPN are already existed in SMAX
|
||||
|
||||
#### BO
|
||||
|
||||
Go to BO's DB
|
||||
|
||||
a. Create a temp mapping table
|
||||
|
||||
```
|
||||
create table <bo_user_schema>.mf_ot_user_mapping
|
||||
(
|
||||
old_upn varchar(512) not null
|
||||
constraint unique_old_upn
|
||||
unique,
|
||||
new_upn varchar(512) not null
|
||||
constraint unique_new_upn
|
||||
unique,
|
||||
old_email varchar(512) not null,
|
||||
new_email varchar(512) not null
|
||||
);
|
||||
```
|
||||
|
||||
b. Copy csv data
|
||||
|
||||
```
|
||||
\copy <bo_user_schema>.mf_ot_user_mapping(old_upn,new_upn,old_email,new_email) FROM '<csv_path>' DELIMITER ',' CSV HEADER;
|
||||
```
|
||||
|
||||
c. Find out users
|
||||
|
||||
```
|
||||
select distinct des.* from <bo_user_schema>.user_entity nu inner join
|
||||
(select mp.* from <bo_user_schema>.mf_ot_user_mapping mp inner join <bo_user_schema>.user_entity u on lower(mp.old_upn) = lower(u.name) and lower(mp.old_upn) !=lower(mp.new_upn) and u.is_deleted=false where u.idm_organization='<tenant_id>') des
|
||||
on lower(nu.name)=lower(des.new_upn) and nu.is_deleted=false and nu.idm_organization='<tenant_id>';
|
||||
```
|
||||
|
||||
Collect the results
|
||||
|
||||
d. drop the temp table
|
||||
|
||||
```
|
||||
drop table <bo_user_schema>.mf_ot_user_mapping
|
||||
```
|
||||
|
||||
#### IdM
|
||||
|
||||
Go to IdM's DB
|
||||
|
||||
a. Create a temp mapping table
|
||||
|
||||
```
|
||||
create table <idm_schema>.mf_ot_user_mapping
|
||||
(
|
||||
old_upn varchar(512) not null
|
||||
constraint unique_old_upn
|
||||
unique,
|
||||
new_upn varchar(512) not null
|
||||
constraint unique_new_upn
|
||||
unique,
|
||||
old_email varchar(512) not null,
|
||||
new_email varchar(512) not null
|
||||
);
|
||||
```
|
||||
|
||||
b. Copy csv data
|
||||
|
||||
```
|
||||
\copy <idm_schema>.mf_ot_user_mapping(old_upn,new_upn,old_email,new_email) FROM '<csv_path>' DELIMITER ',' CSV HEADER;
|
||||
```
|
||||
|
||||
c. Find out users
|
||||
|
||||
```
|
||||
select distinct des.* from <idm_schema>.abstract_user nu inner join
|
||||
(select mp.* from <idm_schema>.mf_ot_user_mapping mp inner join <idm_schema>.abstract_user u on lower(mp.old_upn)=lower(u.name) and lower(mp.old_upn) !=lower(mp.new_upn) where u.organization=(select uuid from <idm_schema>.organizations where name='<tenant_id>')) as des
|
||||
on lower(nu.name)=lower(des.new_upn) and nu.organization=(select uuid from <idm_schema>.organizations where name='<tenant_id>');
|
||||
```
|
||||
|
||||
Collect the resluts
|
||||
|
||||
d. drop the temp table
|
||||
|
||||
```
|
||||
drop table <idm_schema>.mf_ot_user_mapping
|
||||
```
|
||||
|
||||
#### EMS
|
||||
|
||||
Since we need to select Person's upn from entities\_<tenant\_id>, we need to get Tenant version from RMS's DB first.
|
||||
|
||||
Go to RMS's DB
|
||||
|
||||
- Get tenant version
|
||||
|
||||
```
|
||||
select body -> 'tenant' ->> 'version' from <rms_schema>."TenantData_857561481" where body -> 'tenant' ->> 'tenantId' = '<tenant_id>';
|
||||
```
|
||||
|
||||
Go to EMS's DB
|
||||
|
||||
a. Create a temp mapping table
|
||||
|
||||
```
|
||||
create table <ems_schema>.mf_ot_user_mapping
|
||||
(
|
||||
old_upn varchar(512) not null
|
||||
constraint unique_old_upn
|
||||
unique,
|
||||
new_upn varchar(512) not null
|
||||
constraint unique_new_upn
|
||||
unique,
|
||||
old_email varchar(512) not null,
|
||||
new_email varchar(512) not null
|
||||
);
|
||||
```
|
||||
|
||||
b. Copy csv data
|
||||
|
||||
```
|
||||
\copy <ems_schema>.mf_ot_user_mapping(old_upn,new_upn,old_email,new_email) FROM '<csv_path>' DELIMITER ',' CSV HEADER;
|
||||
```
|
||||
|
||||
c. Find out users for tenant
|
||||
|
||||
- Get physical\_type\_name(Replace <tenant\_version> with the tenant version that get from RMS)
|
||||
|
||||
```
|
||||
select physical_type_name from <ems_schema>.entityDescriptor_mapping where entity_type = 'Person' AND tenant_id = '<tenant_version>' AND logical_type_name = 'Upn';
|
||||
```
|
||||
|
||||
- Get entity\_type\_id(Replace <tenant\_version> with the tenant version that get from RMS)
|
||||
|
||||
```
|
||||
select id from "entity_descriptor" where tenant_id = '<tenant_version>' and name = 'Person';
|
||||
```
|
||||
|
||||
Find out users(Replace <physical\_type\_name>,<entity\_type\_id> with the physical\_type\_name, entity\_type\_id that get from above)
|
||||
|
||||
```
|
||||
select distinct des.* from <ems_schema>.entities_<tenant_id> nu inner join
|
||||
(select mp.* from <ems_schema>.mf_ot_user_mapping mp inner join <ems_schema>.entities_<tenant_id> u on lower(mp.old_upn) = lower(u.<physical_type_name>) and lower(mp.old_upn) !=lower(mp.new_upn) and u.is_deleted=false and u.entity_type_id=<entity_type_id> ) des
|
||||
on lower(nu.<physical_type_name>)=lower(des.new_upn) and nu.is_deleted=false and nu.entity_type_id=<entity_type_id>;
|
||||
```
|
||||
|
||||
Collect the results.
|
||||
|
||||
d. drop the temp table
|
||||
|
||||
```
|
||||
drop table <ems_schema>.mf_ot_user_mapping
|
||||
```
|
||||
|
||||
#### RMS
|
||||
|
||||
Go to RMS's DB
|
||||
|
||||
a. Create a temp mapping table
|
||||
|
||||
```
|
||||
create table <rms_schema>.mf_ot_user_mapping
|
||||
(
|
||||
old_upn varchar(512) not null
|
||||
constraint unique_old_upn
|
||||
unique,
|
||||
new_upn varchar(512) not null
|
||||
constraint unique_new_upn
|
||||
unique,
|
||||
old_email varchar(512) not null,
|
||||
new_email varchar(512) not null
|
||||
);
|
||||
```
|
||||
|
||||
b. Copy csv data
|
||||
|
||||
```
|
||||
\copy <rms_schema>.mf_ot_user_mapping(old_upn,new_upn,old_email,new_email) FROM '<csv_path>' DELIMITER ',' CSV HEADER;
|
||||
```
|
||||
|
||||
c. Find out users for tenant
|
||||
|
||||
```
|
||||
select distinct des.* from <rms_schema>."AuthorizationPrincipalResourceJSON_<tenant_id>" nu inner join
|
||||
(select mp.* from <rms_schema>.mf_ot_user_mapping mp inner join <rms_schema>."AuthorizationPrincipalResourceJSON_<tenant_id>" u on lower(mp.old_upn) = lower(u.body ->> 'UserId') and lower(mp.old_upn) !=lower(mp.new_upn)) des
|
||||
on lower(nu.body ->> 'UserId')=lower(des.new_upn);
|
||||
```
|
||||
|
||||
Collect the results.
|
||||
|
||||
d. drop the temp table
|
||||
|
||||
```
|
||||
drop table <rms_schema>.mf_ot_user_mapping
|
||||
```
|
||||
|
||||
**In summary, we need to get the union of all the records from BO, IdM, EMS and RMS, Then cut this part of the data from the csv file.**
|
||||
|
||||
### 1.Actions in Suite
|
||||
|
||||
- Disable User sync in the account
|
||||
|
||||
Login to Suite Administration:
|
||||
|
||||
ACCOUNTS>General>User auto-sync
|
||||
|
||||

|
||||
|
||||
- Change the tenant to Inactive
|
||||
|
||||
Login to Suite Administration:
|
||||
|
||||
TENANTS>General>Inactive
|
||||
|
||||

|
||||
|
||||
- Stop the external integration in the tenant
|
||||
- Do NOT do any write action(Create/Update/Delete) on Users
|
||||
- Delete the SAML authentication config in IdM
|
||||
|
||||
Login to Suite Administration:
|
||||
|
||||
TENANTS>IdM settings>Authentication
|
||||
|
||||

|
||||
|
||||
### 2.Backup Databases:
|
||||
|
||||
Ensure backups of the following databases are taken before initiating changes:
|
||||
|
||||
- **Suite Administration** service database:
|
||||
- `bo_user`
|
||||
- `user_entity`
|
||||
|
||||
```
|
||||
create table <schema>.user_entity_v0 as select * from <schema>.user_entity;
|
||||
```
|
||||
|
||||
- **IDM** service database:
|
||||
- `idm`
|
||||
- `abstract_user`
|
||||
- `abstract_user_metadata`
|
||||
- `abstract_user_profile`
|
||||
|
||||
```
|
||||
create table <schema>.abstract_user_v0 as select * from <schema>.abstract_user;
|
||||
create table <schema>.abstract_user_metadata_v0 as select * from <schema>.abstract_user_metadata;
|
||||
create table <schema>.abstract_user_profile_v0 as select * from <schema>.abstract_user_profile;
|
||||
```
|
||||
|
||||
- XServices databases:
|
||||
- `xservices_ems`
|
||||
- entities\_<Target\_tenant\_Id> `eg:entities_140038523`
|
||||
|
||||
```
|
||||
create table <schema>.entities_<tenant_id>_v0 as select * from <schema>.entities_<tenant_id>;
|
||||
```
|
||||
|
||||
- - `xservices_rms`
|
||||
- AuthorizationPrincipalResourceJSON\_<Target\_tenant\_Id> `eg:AuthorizationPrincipalResourceJSON_140038523`
|
||||
|
||||
```
|
||||
create table <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>_v0" as select * FROM <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>";
|
||||
```
|
||||
|
||||
Please note the single and double **quotes**
|
||||
|
||||
**Note: Please replace the value in <> according to the actual environment**
|
||||
|
||||
### 3.Prepare user Data
|
||||
|
||||
Provide a CSV file containing the new UPNs and corresponding old UPNs and new Emails.
|
||||
|
||||
Sample CSV format:
|
||||
|
||||
| oldUpn | newUpn | oldEmail | newEmail |
|
||||
| --- | --- | --- | --- |
|
||||
| xiao1 | xiao1\_New | [xiao1\_New@microfocus.com](mailto:xiao1_New@opentext.com) | [xiao1\_New@opentext.com](mailto:xiao1_New@opentext.com) |
|
||||
| xiao2 | xiao2\_New | [xiao2\_New@](mailto:xiao2_New@opentext.com) [microfocus.com](mailto:xiao1_New@opentext.com) | [xiao2\_New@opentext.com](mailto:xiao2_New@opentext.com) |
|
||||
| userTKit05 | userTKit055 | [userTKit055@](mailto:userTKit055@opentext.com) [microfocus.com](mailto:xiao1_New@opentext.com) | [userTKit055@opentext.com](mailto:userTKit055@opentext.com) |
|
||||
|
||||
**We can choose a small data set to test firstly, validate these users. If everything goes fine, we can do with the rest files.**
|
||||
|
||||
## Run Script
|
||||
|
||||
#### Notes:
|
||||
|
||||
1. This script needs to provide the old and new upn, as well as the email, the file format should be.csv.
|
||||
2. In addition, you need to specify the column number of the column corresponding to the new/old UPN and old/new Email of the corresponding file and the row number starting from the line.
|
||||
3. You must have the "root" privilege to execute the script.
|
||||
4. Script package should include two files: **changeUserUpn.sh** and **change**, and put these two files in the same level directory.
|
||||
5. The account for updating UPN should be of 3in1 type, which means that the account id and tenant id should be the same.
|
||||
6. In IdM, this script is only update for SAML users, which means that if you are using non-SAML integrated authentication, this script is not suitable
|
||||
7. Before the script runs, you need to back up the database
|
||||
8. Before the script runs, you need to turn off the user sync of the account, and you need to set the tenant to " **Inactive** ", and stop the external integration on the tenant
|
||||
|
||||
#### Follow these steps:
|
||||
|
||||
1. Upload the scripts file and User data csv file to the bastion/master node of the suite
|
||||
2. Log in to the bastion/master node as a root user, copy the scripts and data file to the toolkit pod, grant executable permissions to scripts and file.
|
||||
3. Go into the toolkit pod and run the following command in the directory where the script is located: `sh changeUserUpn.sh -a <account_id>` Where <account\_id> is the ID of the account which you want to change these users under the account. For example, `sh changeUserUpn.sh -a 123456789`
|
||||
4. Follow the prompts step by step to continue executing the script
|
||||
|
||||
**The script will be executed after you put the correct line number in mapping file.**And you can see following messages after the script is successful executed:
|
||||
|
||||

|
||||
|
||||
## Validation
|
||||
|
||||
Firstly, You can check whether the user's upn and email are updated correctly in IdM/BO and SAW. If it's OK, you need to
|
||||
|
||||
- configure OT's SAML in IdM
|
||||
- Active Tenant and turn on User auto-sync in BO.
|
||||
|
||||
Then you can do some regular validation such as:
|
||||
|
||||
- The user account's UPN doesn't change before/after migration
|
||||
To verify after SAML login the user can match to the original user account and role/permission settings aren’t changed
|
||||
- The user account's UPN has been changed after migration
|
||||
To verify after SAML login the user can match to the original user account and role/permission settings aren’t changed
|
||||
To verify after SAML login the user information can be updated to new IDP information, such as email can be updated to OT email
|
||||
- The user account never login SMAX tenant
|
||||
To verify the new SAML user account can be created properly with new UPN in both BO and Tenant
|
||||
|
||||
## Rollback
|
||||
|
||||
If you need to rollback, just rollback the database that has been backed up.
|
||||
|
||||
### Primary rollback:
|
||||
|
||||
You can re-run the change UPN script and specify the old UPN and new UPN with reversed column numbers.
|
||||
|
||||
### Secondary rollback:
|
||||
|
||||
- **Suite Administration** service database:
|
||||
- `bo_user`
|
||||
|
||||
```
|
||||
create table <schema>.user_entity_v1 as select * from <schema>.user_entity;
|
||||
|
||||
update <schema>.user_entity as S set name = B.name, email = B.email
|
||||
from <schema>.user_entity_v0 as B
|
||||
where S.id = B.id
|
||||
and S.account_id = '<tenant_id>';
|
||||
```
|
||||
|
||||
IDM:
|
||||
|
||||
- IDM service database:
|
||||
- `idm`
|
||||
|
||||
```
|
||||
create table <schema>.abstract_user_v1 as select * from <schema>.abstract_user;
|
||||
create table <schema>.abstract_user_metadata_v1 as select * from <schema>.abstract_user_metadata;
|
||||
create table <schema>.abstract_user_profile_v1 as select * from <schema>.abstract_user_profile;
|
||||
|
||||
update <schema>.abstract_user as au set name=bak.name, display_name=bak.display_name, name_lower=bak.name_lower from <schema>.abstract_user_v0 bak where au.uuid=bak.uuid and au.organization='<tenant_uuid>';
|
||||
|
||||
update <schema>.abstract_user_metadata as am set field_value=bak.field_value, field_value_lower=bak.field_value_lower from <schema>.abstract_user au, abstract_user_metadata_v0 bak where am.field_key='username' and am.uuid=bak.uuid and bak.uuid=au.uuid and au.organization='<tenant_uuid>';
|
||||
|
||||
update <schema>.abstract_user_metadata as am set field_value=bak.field_value, field_value_lower=bak.field_value_lower from <schema>.abstract_user au, abstract_user_metadata_v0 bak where am.field_key='email' and am.uuid=bak.uuid and bak.uuid=au.uuid and au.organization='<tenant_uuid>';
|
||||
|
||||
update <schema>.abstract_user_profile as ap set user_name=bak.user_name, email=bak.email from <schema>.abstract_user au, abstract_user_profile_v0 bak where ap.uuid=bak.uuid and ap.user_id=au.uuid and au.organization='<tenant_uuid>';
|
||||
```
|
||||
|
||||
- XServices databases:
|
||||
- `xservices_ems`
|
||||
|
||||
```
|
||||
create table <schema>.entities_<tenant_id>_v1 as select * from <schema>.entities_<tenant_id>;
|
||||
|
||||
-- get entity type id:
|
||||
SELECT DISTINCT id, name FROM <schema>.entity_descriptor WHERE name in ('Person');
|
||||
|
||||
-- get tenant_version such as v27.
|
||||
|
||||
-- get UPN field name: (such as schar1)
|
||||
select physical_type_name from <schema>.entityDescriptor_mapping where entity_type = 'Person' AND tenant_id = '<tenant_version>' AND logical_type_name = 'Upn';
|
||||
|
||||
-- get email field name: (such as schar2)
|
||||
select physical_type_name from <schema>.entityDescriptor_mapping where entity_type = 'Person' AND tenant_id = '<tenant_version>' AND logical_type_name = 'Email';
|
||||
|
||||
update <schema>.entities_<tenant_id> as S set <UPN_field_name> = B.<UPN_field_name>, <email_field_name> = B.<email_field_name>
|
||||
from <schema>.entities_<tenant_id>_v0 as B
|
||||
where S.entity_id = B.entity_id
|
||||
and S.entity_type_id = '<entity_type_id>';
|
||||
```
|
||||
|
||||
- - `xservices_rms`
|
||||
|
||||
```
|
||||
alter table <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>" rename to "AuthorizationPrincipalResourceJSON_<tenant_id>_v1";
|
||||
|
||||
create table <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>" as select * FROM <schema>."AuthorizationPrincipalResourceJSON_<tenant_id>_v0";
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Empty mapping file
|
||||
|
||||
If you see this msg that means the.csv file is empty.
|
||||
|
||||
```
|
||||
Try to read the file that mappings of user UPN and Email.
|
||||
time="2024-03-11 16:21:54" level=error msg="The user mappings file is empty."
|
||||
The user mappings file is empty.
|
||||
```
|
||||
|
||||
### Empty parameter
|
||||
|
||||
```
|
||||
time="2024-03-11 17:50:02" level=error msg="Required param is EMPTY,OriginName:test1,NewName:,OriginEmail:test1,NewEmail:test1"
|
||||
Required param is EMPTY,OriginName:test1,NewName:,OriginEmail:test1,NewEmail:test1
|
||||
```
|
||||
|
||||
If you see this msg that means the NewName is empty.
|
||||
|
||||
### Duplicated user
|
||||
|
||||
If you get this error, go to the Preparation and follow actions to find out the duplicated users.
|
||||
|
||||

|
||||
|
||||
More information will be added during next testing.
|
||||
|
||||
## Script Files
|
||||
|
||||
change
|
||||
|
||||
[change](attachments/686074283/686074285)
|
||||
|
||||
changeUserUpn.sh
|
||||
|
||||
[changeUserUpn.sh](attachments/686074283/686074286.sh)
|
||||
|
||||
Reference in New Issue
Block a user