【IAM身份中心】如何将用户与组从CSV批量导入到华为云IAM身份中心
无论您是使用SAML2.0将外部身份源(IdP)连接到华为云IAM身份中心(后续都简称为IAM身份中心),还是直接使用华为云IAM身份中心,您都需要先在IAM身份中心里创建所有的用户与组。
当然,如果您选择的是对接外部身份源(IdP),并且IdP支持通过SCIM进行用户和组的自动预置,我强烈建议您使用SCIM来简化在IAM身份中心里用户和组的生命周期管理。当使用SCIM时,IAM身份中心的用户、组以及用户与组的关联关系,将会实施与IdP保持同步,这将意味着您只需要在IdP上维护用户和组,而不需要在IAM中心上重复这份工作。
关于如何配置外部身份源(IdP)与自动预置(SCIM),您可以参考其他链接(比如IAM身份中心如何对接微软Entra ID),或者咨询你的身份提供商厂家。
如果您的身份提供商(IdP) 尚不支持自动预置,那么您就需要在IAM身份中心上手动创建用户和组。尽管手动创建用户和组的操作并不复杂,但您可以面临非常大且乏味的重复工作。
在这篇文章中,我会想你提供一个方法,使用CSV文件,实现在IAM身份中心上用户和组的批量创建。
前期准备
- 您运行环境需要具备Python的执行环境,我想您可以非常容易获取到它;
- 您需要安装华为云IAM身份中心的sdk,您可以在cmd中执行如下命令进行安装:
pip install huaweicloudsdkidentitycenterstore
- 在IAM身份中心所在的账号,或者组织上IAM身份中心的委托管理员账号上,创建一个IAM用户,该用户需要需要具备以下权限,并获取该用户的秘钥。(该用户可在使用后删除)
{
"Version": "5.0",
"Statement": [
{
"Effect": "Allow",
"Action": [
"IdentityCenter:user:create",
"IdentityCenter:group:create",
"IdentityCenter:group:list",
"IdentityCenter:groupMembership:create"
]
},
{
"Effect": "Allow",
"Action": [
"organizations:delegatedAdministrators:list"
]
}
]
}
将用户和组批量创建到IAM身份中心
准备好待导入的csv文件
- 创建一个任意名称的csv文件(如user_import.csv),它的首行需要包含如下:userName,emailAddress,givenName,familyName,displayName,memberOf。
需要注意的是,memberOf列将包含您要在IAM身份中心里,所创建用户所属的用户组。您可以使用“;”分隔组名,已实现用户可以被关联到多个组。如果IAM身份中心上还没有同名的组,那么该脚本会帮您在IAM身份中心创建这些组。
同时,要使此功能正常工作,该csv中每个用户都必须指定userName,emailAddress,givenName,familyName,displayName的值,如果缺少任意一个,用户都无法成功创建。userName和emailAddress不可以与其他用户重复。

准备执行的脚本
- 接下来,创建一个py脚本(如IdC_Import_User.py),并将如下代码复制到其中保存。您可以使用记事本或者其他文本编辑器编辑该文件。
-
将<REGIONID>替换为IAM身份中心所在的region id;
- 将<IDCSTORE>替换为IAM身份中心的身份存储ID(您可以在IAM身份中心的总览页找到它);
- 将<CSVLOCATION>替换为csv文件所在的位置;
- 将<ACCESS_KEY><SECRET_KEY>替换为之前准备的用户秘钥。
#system
import csv
import logging
#HuaweiCloud SDK
from huaweicloudsdkcore.exceptions import exceptions
from huaweicloudsdkcore.http.http_config import HttpConfig
#Identity Store
from huaweicloudsdkcore.auth.credentials import BasicCredentials
from huaweicloudsdkidentitycenterstore.v1.region.identitycenterstore_region import IdentityCenterStoreRegion
from huaweicloudsdkidentitycenterstore.v1 import *
#########################################
# Please replace the configuration firstly
REGION = "REGIONID"
IDC_STORE_ID = "<IDCSTORE>"
FILE_URL = "<CSVLOCATION>"
ACCESS_KEY = "<ACCESS_KEY>"
SECRET_KEY = "<SECRET_KEY>"
#########################################
groupInfo = dict()
failedUserList = list()
logging.basicConfig(
level=logging.INFO,
filename='./run.log',
filemode='w',
format="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
def get_users_from_csv():
users = list()
with open(FILE_URL, 'r') as fTable:
readers = csv.DictReader(fTable)
for reader in readers:
users.append(reader)
return users
def create_user(client, user):
try:
request = CreateUserRequest()
request.identity_store_id = IDC_STORE_ID
namebody = NameDto(
family_name=user['familyName'],
given_name=user['givenName']
)
listEmailsbody = [
EmailDto(
primary=True,
type="Work",
value=user['emailAddress']
)
]
request.body = CreateUserReqBody(
password_mode="EMAIL",
user_name=user['userName'],
name=namebody,
emails=listEmailsbody,
display_name=user['displayName']
)
response = client.create_user(request)
userID = response.user_id
return userID
except Exception as e:
logging.error(f"Failed to create user: {user['userName']}. Reason: {e}")
def list_groups(client):
try:
request = ListGroupsRequest()
request.identity_store_id = IDC_STORE_ID
response = client.list_groups(request)
global groupInfo
for item in response.groups:
groupInfo[item.display_name] = item.group_id
return
except exceptions.ClientRequestException as e:
logging.error(f"Error Code: {e.status_code}, Error Message: {e.error_msg}")
def create_group(client, group_name):
try:
request = CreateGroupRequest()
request.identity_store_id = IDC_STORE_ID
request.body = CreateGroupReqBody(
display_name=group_name
)
response = client.create_group(request)
groupID = response.group_id
return groupID
except exceptions.ClientRequestException as e:
logging.error(f"Failed to create group: {group_name}")
logging.error(f"Error Code: {e.status_code}, Error Message: {e.error_msg}")
def create_group_membership(client, group_id, group_name, user_id, user_name):
try:
request = CreateGroupMembershipRequest()
request.identity_store_id = IDC_STORE_ID
memberIdbody = MemberIdDto(
user_id=user_id
)
request.body = CreateGroupMembershipReqBody(
member_id=memberIdbody,
group_id=group_id
)
response = client.create_group_membership(request)
except exceptions.ClientRequestException as e:
logging.error(f"Failed to create membership, group mame: {group_name}, user name: {user_name}")
logging.error(f"Error Code: {e.status_code}, Error Message: {e.error_msg}")
def process_user(client, user):
userId = create_user(client, user)
if not userId:
logging.debug(f"Failed to create user : {user['userName']}")
failedUserList.append(user['userName'])
return
if not user["memberOf"]:
return
groups = user["memberOf"].split(';')
for groupName in groups:
global groupInfo
if groupName not in groupInfo:
id = create_group(client,groupName)
groupInfo[groupName] = id
logging.info(f"Create group success : {groupName}")
groupId = groupInfo[groupName]
create_group_membership(client, groupId, groupName, userId, user['userName'])
return
def get_clients(region: str):
basicCredentials = BasicCredentials(ACCESS_KEY, SECRET_KEY)
identityStoreClient = IdentityCenterStoreClient.new_builder() \
.with_credentials(basicCredentials) \
.with_region(IdentityCenterStoreRegion.value_of(region)) \
.build()
return identityStoreClient
def IdC_Import_User():
logging.info(f"Begin to Import user from {FILE_URL} to {IDC_STORE_ID}, region is {REGION}")
client = get_clients(REGION)
list_groups(client)
logging.info(f"Total group fount in IAM Identity Center: {len(groupInfo)}")
users = get_users_from_csv()
logging.info(f"Total user in csv file: {len(users)}")
for user in users:
process_user(client, user)
logging.info(f"Total user number: {len(users)}, failed user number: {len(failedUserList)}")
logging.info(f"Failed user list: {failedUserList}")
if __name__ == "__main__":
IdC_Import_User()
2. 在执行脚本后,你会得到一个名为run.log的日志文件,在文件中,你会获取创建失败的用户列表;你可以检查下这些用户创建失败的原因,并重新执行脚本或者在控制台上手工创建它们。

结尾
通过该脚本,可以在当您的身份提供商(IdP)不支持SCIM自动预置时,提高您首次在IAM身份中心上批量创建用户的效率。
一般该脚本会在您第一次使用IAM身份中心时并且由大量用户和组创建的工作场景下使用它。一旦您将用户批量创建好,后续的用户和组的生命周期管理,您可以在控制台上做维护。
- 点赞
- 收藏
- 关注作者
评论(0)