Skip To Content

예: 포털에 구성원 추가

이 예에서는 사용자에 관한 정보가 있는 입력 텍스트 파일을 사용하여 포털에 일괄적으로 구성원을 추가합니다. 포털의 각 사용자에 대한 역할을 정의하고 부여합니다.

스크립트를 실행할 때 다음 필수 정보를 입력합니다.

  • 사용자 정보를 포함하는 텍스트 파일 경로(예시: C:\users.txt)입니다.
  • 포털에 추가하려는 사용자 유형(예: 빌트인 또는 엔터프라이즈). 사용자 유형에 대해 자세히 알아보려면 포털에 대한 접근 관리를 참고하세요.
  • 포털을 호스팅하는 머신의 정규화된 도메인 이름(예: myportal.acme.com). 스크립트는 ArcGIS Web Adaptor를 무시하고 포트 7443에서 HTTPS를 통해 포털에 접근합니다. 이런 방법으로 스크립트는 포털이 웹 티어 인증을 사용하도록 구성되어 있어도 해당 인증을 처리할 필요가 없습니다.
  • 포털에 대한 관리 권한을 가진 계정의 사용자 이름과 비밀번호. 빌트인 계정을 추가하는 경우 관리 권한이 있는 포털 구성원의 자격 증명을 제공합니다. 기관별 계정을 추가하는 경우 Portal for ArcGIS 설치 후 생성된 초기 관리자 계정을 사용합니다.
비고:

파이썬 스크립트가 웹티어 인증을 처리하는 방법은 이 예시에서 설명되지 않습니다.

엔터프라이즈 계정 등록

엔터프라이즈 계정을 등록할 때 텍스트 파일의 각 항목에 대한 형식은 다음과 같습니다.

<login>|<email address>|<name>|<role>|<description>|<Idp UserName>

  • login - 등록할 엔터프라이즈 로그인입니다.

    • Active Directory를 사용하면 이 로그인은 sAMAccountName@DOMAIN 형식입니다. 도메인 이름은 모두 대문자여야 합니다.
    • LDAP를 사용하는 경우 로그인은 ID 저장소 구성 시 지정한 userNameAttribute 값과 일치합니다.
    • SAML 기반 엔터프라이즈 로그인을 사용하는 경우 지정된 로그인 값은 SAML ID 공급자의 NameID 속성과 일치합니다.
  • email address - 로그인과 연결된 이메일 주소로, ID 저장소의 값과 일치합니다. 사용자 계정에 이메일 주소가 포함되지 않은 경우 false 또는 일반 값을 제공하세요.

  • name - ArcGIS 기관에서 사용되는 로그인에 대한 별칭입니다. 대부분의 ID 저장소에서는 사용자의 전체 이름을 기본 별칭으로 사용합니다. 사용자가 포털 웹사이트에 연결되면 웹사이트 상단에 이 이름이 나타납니다.

  • 사용자 유형 - 사용자가 할당받을 사용자 유형의 이름입니다. 드롭다운 목록에서 사용 가능한 사용자 유형을 선택합니다. 호환 가능한 역할 및 애드온 라이선스 수를 클릭하면 선택한 사용자 유형과 호환되는 항목에 대해 자세히 알아볼 수 있습니다. 자세한 내용은 사용자 유형, 역할, 권한을 참고하세요.
  • 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 - 필요한 경우 계정을 설명하는 텍스트를 포함합니다. 이 값은 ID 저장소의 어떠한 속성에도 해당하지 않습니다. 설명은 250자를 초과할 수 없습니다.

  • Idp UserName - 필요한 경우 ID 공급자에서 엔터프라이즈 계정의 사용자 이름을 지정합니다. 이 값이 제공되지 않으면 로그인 매개변수에 대해 지정된 값이 대신 사용됩니다.

login, email address, name, role 값을 제공해야 합니다. description 및 ldp UserName은 선택 사항입니다. 파일에 나열된 각 계정에 대해 login, email address 및 name에 입력한 값이 ID 저장소의 값과 정확히 일치하는지 확인하세요. 포털은 ID 저장소에 연결하여 이러한 값의 유효성을 검사하지 않습니다.

다음은 Active Directory 엔터프라이즈 계정을 등록하는 입력의 한 예로 로그인은 jcho111, 이메일 주소가 jcho@domain.com이고 전체 이름이 Jon Cho입니다. 이 로그인은 User 사용자 역할 및 Viewer 사용자 유형에 배치되며 department b의 사용자로 기술됩니다.

jcho111@DOMAIN|jcho@domain.com|Jon Cho|Viewer|user|department b

다음은 SAML ID 공급자에서 엔터프라이즈 계정을 등록하는 입력의 예입니다. 사용자 로그인은 rsmith@domain.com이고, 이메일 주소는 rsmith@domain.com이며 전체 이름은 Robert Smith입니다. 이 로그인은 IDP 사용자 이름이 rsmith@domain.com인 발행자 역할 publisher 및 Creator 사용자 유형에 배치됩니다.

rsmith@domain.com|rsmith@domain.com|Robert Smith|Creator|publisher||rsmith@domain.com

다음은 이메일 주소가 sjames@domain.com이고 전체 이름이 Sara James인 로그인 sjames4513에 대한 LDAP 엔터프라이즈 계정을 등록하는 입력의 예입니다. 이 로그인은 Admin 사용자 역할 및 GIS Professional 사용자 유형에 배치되며 설명이 제공됩니다.

sjames4513@DOMAIN|sjames@domain.com|Sara James|GISProfessional|admin|Department Lead and GIS Manager

다음은 이메일 주소가 srajhandas@domain.com이고 전체 이름이 Satish Rajhandas인 로그인 srajhandas에 대한 엔터프라이즈 계정을 등록하는 입력의 예입니다. 이 로그인은 User 사용자 역할 및 Viewer 사용자 유형에 배치됩니다.

srajhandas@DOMAIN|srajhandas@domain.com|Satish Rajhandas|Viewer|user

다음은 SAML ID 공급자에서 엔터프라이즈 계정을 등록하는 입력의 예입니다. 사용자 로그인은 djohnson308이고, 이메일 주소는 djohnson@domain.com이며 전체 이름은 Daisha Johnson입니다. 이 로그인은 User 사용자 역할 및 Creator 사용자 유형에 배치되고 설명이 제공되며 IDP 사용자 이름은 djohnson@domain.com으로 정의됩니다.

djohnson308@DOMAIN|djohnson@domain.com|Daisha Johnson|Creator|user|Account Specialist|djohnson@domain.com

빌트인 포털 계정 추가

빌트인 포털 계정을 등록할 때 텍스트 파일의 각 항목에 대한 형식은 다음과 같습니다.

<username>|<password>|<email address>|<name>|<user type>|<role>|<description>

  • username - 빌트인 계정에 사용되는 사용자 이름입니다. 사용자 이름은 고유해야 합니다. 두 구성원이 동일한 사용자 이름을 가질 수는 없습니다.
  • password - 계정에 할당된 비밀번호입니다. 사용자는 포털에 처음 로그인할 때 이 비밀번호를 사용한 다음 프로필을 편집하여 비밀번호를 변경할 수 있습니다.
  • email address - 이 계정에 대한 이메일 주소를 제공합니다. 이 매개변수는 필수 항목이므로 유효한 주소가 아닌 경우에도 이메일 주소 값을 제공해야 합니다.
  • name - ArcGIS 기관에서 사용되는 계정에 대한 별칭입니다. 사용자가 포털 웹사이트에 연결되면 포털 웹사이트 상단에 해당 이름이 나타납니다.
  • 사용자 유형 - 사용자가 할당받을 사용자 유형의 이름입니다. 드롭다운 목록에서 사용 가능한 사용자 유형을 선택합니다. 호환 가능한 역할 및 애드온 라이선스 수를 클릭하면 선택한 사용자 유형과 호환되는 항목에 대해 자세히 알아볼 수 있습니다. 자세한 내용은 사용자 유형, 역할, 권한을 참고하세요.
  • role - ArcGIS 기관에서 계정의 역할입니다. 올바른 역할 값은 user, publisher, admin, <custom_role_name>입니다. 여기서 <custom_role_name>은 hostedservicepublisher 같은 사용자 정의 역할의 이름입니다.
  • description - 필요한 경우 계정을 설명하는 텍스트를 포함합니다. 설명은 250자를 초과할 수 없습니다.

다음은 Barbara Williams에 대한 사용자 이름이 pub1이고 이메일 계정이 bwilliams@domain.com인 빌트인 포털 계정을 추가하는 입력의 예입니다. 발행자 역할에도 pub1을 추가합니다.

pub1|changepasswordlater|bwilliams@domain.com|Barbara Williams|Creator|publisher

다음은 Jon Cho에 대한 사용자 이름이 jcho이고 이메일 계정이 jcho@domain.com인 빌트인 포털 계정을 추가하는 입력의 예입니다. 관리자 역할에도 jcho를 추가하고 GIS 관리자로 설명합니다.

jcho|changepasswordlater|jcho@domain.com|Jon Cho|GISProfessional|admin|GIS Manager

#!/usr/bin/env python
# Requires Python 2.7+

# Demonstrates how to add users to the ArcGIS Enterprise portal in bulk

# For Http calls
import 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()
    inFileHandle = open(inUserFile, 'r')
    userCount = 0
    print '...Processing input users file at: ' + inUserFile
    entryCount = 1
    roleID = {'admin':'org_admin', 'publisher':'org_publisher', 'user':'org_user', 'viewer':'iAAAAAAAAAAAAAAA'}
    for line in inFileHandle.readlines():
        userParams = line.strip('\n').split('|')
        userParamDict = {}
        if provider=="enterprise":
            keyParams = ['username', 'email', 'fullname', 'role', 'userLicenseTypeId', 'description', 'idpUsername', 'firstname', 'lastname']
            if len(userParams) == len(keyParams):
                for i, param in enumerate(keyParams):
                    userParamDict[param] = userParams[i]
                if userParamDict['role'] in roleID.keys():
                    userParamDict['role'] = roleID[userParamDict['role']]
                else:
                    print('The value for the user role "{}" in users text file is invalid.'.format(userParamDict['role']))
                    print('Accepted values are viewer, user, publisher, or admin.')
                    raise SystemExit('Invalid user role')
                usersQ.put(userParamDict)
                userCount = userCount + 1
            else:
                print('The format for entry "{}" is invalid.\nThe format for enterprise accounts is:'.format(line.strip('\n')))
                print(' <login>|<email address>|<full name>|<role>|<user type id>|<description>|<idp username>|<first name>|<last name>')
                raise SystemExit('Invalid format')
        elif provider=="arcgis":
            keyParams = ['username', 'password', 'email', 'fullname', 'role', 'userLicenseTypeId', 'description', 'firstname', 'lastname']
            if len(userParams) == len(keyParams):
                for i, param in enumerate(keyParams):
                    userParamDict[param] = userParams[i]
                if userParamDict['role'] in roleID.keys():
                    userParamDict['role'] = roleID[userParamDict['role']]
                else:
                    print('The value for the user role "{}" in users text file is invalid.'.format(userParamDict['role']))
                    print('Accepted values are viewer, user, publisher, or admin.')
                    raise SystemExit('Invalid user role')
                usersQ.put (userParamDict)
                userCount = userCount + 1
            else:
                print('The format for entry "{}" is invalid.\nThe format for built-in accounts is:'.format(line.strip('\n')))
                print(' <account>|<password>|<email address>|<full name>|<role>|<description>|<first name>|<last name>|<level>')
                raise SystemExit('Invalid format')
        else:
            raise SystemExit( 'The value for the user type is invalid. ')
        entryCount = entryCount +1
    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 'User: %s account created' % (userDict['username'])
        except Queue.Empty:
              usersLeftInQueue = False

# This function gets a token from the portal
def generateToken(username, password, portalUrl):
    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):
        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'] = 'enterprise'
        print '   Enterprise accounts will be added to the portal. \n'
    else:
        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'] = getpass.getpass("Enter password: ")
    print '\n'

    return  parameters

# Script start
if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))