この例では、ユーザーに関する情報を含む入力テキスト ファイルを受け取って、それらを一括してポータルに追加します。ポータルで各ユーザーのロールを定義し付与します。
スクリプトの実行時に、以下の必須情報を入力します。
- ユーザー情報を含むテキスト ファイルへのパス (例: C:\users.txt)。
- ポータルに追加するユーザーのタイプ (たとえば、「組み込み」や「エンタープライズ」)。ユーザーのタイプの詳細については、「ポータルへのアクセスの管理」をご参照ください。
- ポータルをホストするコンピューターの完全修飾ドメイン名 (たとえば、「myportal.acme.com」)。このスクリプトは、ArcGIS Web Adaptor を迂回し、ポート 7443 で HTTPS を経由してポータルにアクセスします。このように、ポータルが Web 層認証を使用するように構成されている場合、スクリプトで Web 層認証を処理する必要はありません。
- ポータルに対する管理権限を持つアカウントのユーザー名とパスワード。組み込みアカウントを追加する場合、ポータルの管理権限を持つ任意のメンバーの認証情報を入力します。エンタープライズ アカウントを追加する場合、Portal for ArcGIS のインストール後に作成された初期管理者アカウントを使用します。
注意:
Python スクリプトで Web 層認証を処理する方法に関しては、この例では扱いません。
エンタープライズ アカウントの登録
エンタープライズ アカウントを登録する場合、テキスト ファイル内の各エントリの形式は次のようになります。
<login>|<email address>|<name>|<role>|<description>|<Idp UserName>
login - 登録するエンタープライズ ログイン。
- Active Directory を使用する場合、このログインの形式は sAMAccountName@DOMAIN です。ドメイン名はすべて大文字にする必要があります。
- LDAP を使用する場合、ログインは、アイデンティティ ストアの構成時に指定した「userNameAttribute」の値と同じです。
- SAML ベースのエンタープライズ ログインを使用する場合、指定されたログイン値は、SAML アイデンティティ プロバイダーの NameID 属性と同じです。
email address - login に関連付けられている電子メールであり、アイデンティティ ストアの値と同じです。ユーザー アカウントに電子メール アドレスがない場合、仮のまたは汎用的な値を指定します。
name - login に対応する、ArcGIS 組織内で使用されるエイリアスです。アイデンティティ ストアの大半は、ユーザーの氏名をデフォルトのエイリアスとして使用します。ユーザーがポータル Web サイトに接続した場合は、この名前が Web サイトの上部に表示されます。
role - これは、エンタープライズ ログインに対して ArcGIS 組織内で割り当てられるロールです。有効なロールの値は、user、publisher、admin、<custom_role_name> です。<custom_role_name> は、カスタム ロールの名前 (たとえば、hostedservicepublisher) です。
レガシー:
Portal for ArcGIS 10.3 以前のバージョンでは、カスタム ロール以外に使用できる値は org_user、org_publisher、org_admin でした。10.3.1 では、これらの値は廃止され、上記の値に置き換えられました。10.3.1 でも従来の値を使用できますが、今後のリリースでは使用できなくなる可能性がありますので注意してください。
description - 必要に応じて、アカウントを説明するテキストを含めます。このテーブルは、アイデンティティ ストアのどの属性とも対応しません。description は 250 文字を超えることはできません。
Idp UserName - オプションで、アイデンティティ プロバイダーにエンタープライズ アカウントの名前を指定します。この値を指定しない場合、代わりにログイン パラメーターに指定した値が使用されます。
ユーザーは、login、email address、name、および role を指定する必要があります。説明および Idp UserNameはオプションです。ファイルにリスト表示されている各アカウントでは、login、email address、および name に入力した値は、アイデンティティ ストアの値と完全に一致している必要があります。ポータルは、アイデンティティ ストアに接続してこれらの値を確認しません。
次に、Active Directory エンタープライズ アカウントを登録するエントリの例を示します。login は jcho111、email address は jcho@domain.com、full name は Jon Cho です。この login はユーザー ロール (user) 内に格納され、このユーザーが department b に所属しているという説明を記述します。
jcho111@DOMAIN|jcho@domain.com|Jon Cho|user|department b
次に、SAML アイデンティティ プロバイダーからエンタープライズ アカウントを登録するエントリの例を示します。ユーザーの login は rsmith@domain.com で、email address は rsmith@domain.com で、full name は Robert Smith です。login は、公開者ロール (publisher) に格納され、Idp UserName は rsmith@domain.com です。
rsmith@domain.com|rsmith@domain.com|Robert Smith|publisher||rsmith@domain.com
次に、LDAP エンタープライズ アカウントを登録するエントリの例を示します。login は sjames4513、email address は sjames@domain.com、フル ネームは Sara James です。この login はユーザー ロール (admin) 内に格納され、説明が入力されます。
sjames4513@DOMAIN|sjames@domain.com|Sara James|admin|Department Lead and GIS Manager
次に、エンタープライズ アカウントを登録するエントリの例を示します。login は srajhandas、email address は srajhandas@domain.com、フル ネームは Satish Rajhandas です。この login はユーザー ロール (user) 内に格納されます。
srajhandas@DOMAIN|srajhandas@domain.com|Satish Rajhandas|user
次に、SAML アイデンティティ プロバイダーからエンタープライズ アカウントを登録するエントリの例を示します。ユーザーの login は djohnson308 で、email address は djohnson@domain.com で、full name は Daisha Johnson です。この login はユーザー ロール (user) 内に格納され、説明が入力され、Idp UserName が djohnson@domain.com と入力されます。
djohnson308@DOMAIN|djohnson@domain.com|Daisha Johnson|user|Account Specialist|djohnson@domain.com
組み込みポータル アカウントの追加
組み込みのポータル アカウントを登録する場合は、テキスト ファイル内の各エントリの形式は次のようになります。
<username>|<password>|<email address>|<name>|<role>|<description>
- username - 組み込みアカウントに使用されるユーザー名。ユーザー名は一意である必要があります。2 人のメンバーが同じユーザー名を持つことはできません。
- password - アカウントに割り当てられるパスワード。ユーザーはポータルに最初にサイン インするときにこのパスワードを使用でき、その後、自分のプロファイルを編集してパスワードを変更することができます。
- email address - このアカウントに対応する電子メール アドレスを指定します。このパラメーターは必須です。したがって、有効なアドレスでなくても、email address に値を指定する必要があります。
- name - ArcGIS 組織内で使用されるアカウントに対応するエイリアスです。ユーザーがポータル Web サイトに接続した場合は、この名前がポータル Web サイトの上部に表示されます。
- role - ArcGIS 組織内でアカウントに対して割り当てられるロールです。有効なロールの値は、user、publisher、admin、または <custom_role_name> です。<custom_role_name> は、カスタム ロールの名前 (たとえば、hostedservicepublisher) です。
- description - オプションで、アカウントを説明するテキストを含めます。description は 250 文字を超えることはできません。
次の例では組み込みのポータル アカウントを追加します。Barbara Williams に対応するユーザー名は pub1、アカウントの email は bwilliams@domain.com です。また、pub1 を公開者ロールに追加します。
pub1|changepasswordlater|bwilliams@domain.com|Barbara Williams|publisher
次の例では組み込みのポータル アカウントを追加します。Barbara Williams に対応するユーザー名は jcho、アカウントの email は jcho@domain.com です。また、jcho を管理者ロールに追加して、そのユーザーが GIS マネージャーであるという説明を加えます。
jcho|changepasswordlater|jcho@domain.com|Jon Cho|admin|GIS Manager
#!/usr/bin/env python
# Requires Python 2.7+
# Demonstrates how to add users to Portal for ArcGIS in bulk
# For Http calls
import httplib, urllib2, urllib, json
# For system tools
import sys, os
# For reading passwords without echoing
import getpass
# Other utilities
import Queue
# Defines the entry point into the script
def main(argv):
print "This script adds users in bulk into a portal. \n"
#Get parameters
parameters = getParametersFromUser ()
portalURL = parameters['portalURL']
provider = parameters['provider']
userName = parameters['userName']
password = parameters['password']
inUserFile = parameters['inUserFile']
#Get user data from file
usersData = getUserDataFromFile(inUserFile,provider)
#Create users
createUsers (userName,password, portalURL,provider, usersData)
raw_input('Press ENTER to close the script.')
return
# This function loads all the user data in the input text file into a Python Queue.
# This usersQueue can be later passed to the createUsers function
def getUserDataFromFile(inUserFile,provider):
usersQ = Queue.Queue()
keyParams = ['username', 'password', 'email', 'fullname','role','description']
inFileHandle = open(inUserFile, 'r')
userCount = 0
print '...Processing input users file at: ' + inUserFile
entryCount = 1;
for line in inFileHandle.readlines():
userParams = line.split('|')
userParamDict = {}
if provider=="webadaptor":
if len(userParams) == 5:
for i in range (0,5):
userParamDict[keyParams[0]] = userParams[0] # login
userParamDict[keyParams[1]] = ""
userParamDict[keyParams[2]] = userParams[1] # email address
userParamDict[keyParams[3]] = userParams[2] # name
userParamDict[keyParams[4]] = userParams[3] # role
userParamDict[keyParams[5]] = userParams[4].replace('\n','') # description
usersQ.put (userParamDict)
userCount = userCount + 1
else:
print ' The format for entry %s is invalid. The format for enterprise accounts should be <login>|<email address>|<name>|<role>|<description>. \n '% (entryCount)
raise SystemExit( 'When registering enterprise accounts, the format for each entry is as follows: <login>|<email address>|<name>|<role>|<description>')
elif provider=="arcgis":
if len(userParams) == 6:
for i in range (0,6):
userParamDict[keyParams[0]] = userParams[0] # account
userParamDict[keyParams[1]] = userParams[1] # password
userParamDict[keyParams[2]] = userParams[2] # email address
userParamDict[keyParams[3]] = userParams[3] # name
userParamDict[keyParams[4]] = userParams[4] # role
userParamDict[keyParams[5]] = userParams[5].replace('\n','') # description
usersQ.put (userParamDict)
userCount = userCount + 1
else:
print ' The format for entry %s is invalid. The format for built-in portal accounts should be <account>|<password>|<email address>|<name>|<role>|<description>. \n '% (entryCount)
raise SystemExit( 'When registering built-in portal accounts, the format for each entry is as follows: <account>|<password>|<email address>|<name>|<role>|<description>')
else:
print ' The provider is incorrect. Script ended. \n'
raise SystemExit( 'The value for the user type is invalid. ')
entryCount = entryCount +1
if not ((userParamDict[keyParams[4]].lower()== "user") or (userParamDict[keyParams[4]].lower()=="publisher") or (userParamDict[keyParams[4]].lower()== "admin")):
raise SystemExit( 'The value for the user role %s in users text file is invalid. Accepted values are user or publisher or admin. ' % (userParamDict[keyParams[4]]))
inFileHandle.close()
# Create users and report results
print '...Total members to be added: ' + str(userCount)
return usersQ
# This function connects to the portal and adds members to it from a collection
def createUsers(username,password, portalUrl, provider,userParamsQ):
print '...Connecting to ' + portalUrl
token = generateToken(username,password, portalUrl)
print '...Adding users '
usersLeftInQueue = True
while usersLeftInQueue:
try:
userDict = userParamsQ.get(False)
userDict['f'] = 'json'
userDict['token'] = token
userDict['provider'] = provider
params = urllib.urlencode(userDict)
request = urllib2.Request(portalUrl + '/portaladmin/security/users/createUser?',params, { 'Referer' : portalUrl })
# POST the create request
response = urllib2.urlopen(request).read()
responseJSON = json.loads(response)
# Log results
if responseJSON.has_key('error'):
errDict = responseJSON['error']
if int(errDict['code'])==498:
message = 'Token Expired. Getting new token... Username: ' + userDict['username'] + ' will be added later'
token = generateToken(username,password, portalUrl)
userParamsQ.put(userDict)
else:
message = 'Error Code: %s \n Message: %s' % (errDict['code'],
errDict['message'])
print '\n' + message
else:
# Success
if responseJSON.has_key('status'):
resultStatus = responseJSON['status']
print '\n' + 'User: %s account created' % (userDict['username'])
print 'User: %s account created' % (userDict['username'])
except Queue.Empty:
usersLeftInQueue = False
# This function gets a token from the portal
def generateToken(username, password, portalUrl):
'''Retrieves a token to be used with API requests.'''
parameters = urllib.urlencode({'username' : username,
'password' : password,
'client' : 'referer',
'referer': portalUrl,
'expiration': 60,
'f' : 'json'})
try:
response = urllib.urlopen(portalUrl + '/sharing/rest/generateToken?',
parameters).read()
except Exception as e:
raise SystemExit( 'Unable to open the url %s/sharing/rest/generateToken' % (portalUrl))
responseJSON = json.loads(response.strip(' \t\n\r'))
# Log results
if responseJSON.has_key('error'):
errDict = responseJSON['error']
if int(errDict['code'])==498:
message = 'Token Expired. Getting new token... '
token = generateToken(username,password, portalUrl)
else:
message = 'Error Code: %s \n Message: %s' % (errDict['code'],
errDict['message'])
raise SystemExit(message)
token = responseJSON.get('token')
return token
# This function gets gets parameters from the user in interactive mode
def getParametersFromUser():
parameters = {}
# Get Location of users file
inUserFile = raw_input ("Enter path to users text file: ")
if not os.path.exists(inUserFile):
print ' File does not exist. Script ended. \n'
raise SystemExit( 'Input file: %s does not exist' % (inUserFile))
parameters['inUserFile'] = inUserFile
# Enteprise logins or built-in accounts?
userInput = raw_input ("What type of users do you want to add to the portal? Accepted values are built-in or enterprise: ")
if userInput.lower()=="built-in":
parameters['provider'] = 'arcgis'
print ' Built-in accounts will be added to the portal. \n'
elif userInput.lower()=="enterprise":
parameters['provider'] = 'webadaptor'
print ' Enterprise accounts will be added to the portal. \n'
else:
print ' The type of users is incorrect. Script ended. \n'
raise SystemExit( 'The value entered for the user type %s is invalid. Accepted values are built-in or enterprise. ' % (userInput))
# Get Portal URL
hostname = raw_input("Enter the fully qualified portal hostname (for example myportal.acme.com): ")
parameters['portalURL'] = 'https://' + hostname + ':7443/arcgis'
print ' Users will be added to portal at: ' + parameters['portalURL'] + '\n'
# Get a username and password with portal administrative privileges
parameters['userName'] = raw_input("Enter a built-in user name with portal administrative privileges:")
parameters['password'] = raw_input("Enter password: ")
print '\n'
return parameters
# Script start
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))