CreateEnterpriseGeodatabase pass encrypted DBA password

4643
5
04-06-2015 02:45 PM
OlegKachirski
New Contributor III

One of the parameters to arcpy.CreateEnterpriseGeodatabase_management is the database administrator password. Documentation states that it is an "Encrypted String"; however in practice it takes a plain-text password:

http://resources.arcgis.com/en/help/main/10.1/index.html#//001700000162000000

gdb_admin_password

(Optional)

Provide the password for the geodatabase administrator user. If the geodatabase administrator user already exists in the DBMS, the password you type must match the existing password. If the geodatabase administrator user does not already exist, type a valid database password for the new user. The password must meet the password policy enforced by your DBMS.

The password is a geoprocessing-encrypted string.

Encrypted String

I need to save this script on disk and use an encrypted password in it. What encryption algorithm/library is it expecting, and how does one generate such an encrypted password? Any ESRI tool available for this (it does say The password is a geoprocessing-encrypted string.)?

0 Kudos
5 Replies
JamesCrandall
MVP Frequent Contributor

I'm not sure if this would work to generate an encrypted string, but the base64 library might do what you need.  There's a ton of information and options related to encryption, passwords and hash methods so this may be just too simplified for your implementation, but perhaps this simple example will get you started.

import base64
pwd_crypted =  base64.b64encode("MyPassWORDGoesHere")
print "The encrypted password: " + pwd_crypted
pwd_decrypted = base64.b64decode(pwd_crypted)
print "The decrypted password: " + pwd_decrypted

I guess you could parameterize "MyPassWORDGoesHere" as it's just a string (per your OP requirement).  To see how the hash changes, simply change that string to something else and it will create a new encrypted password.

note: I have no idea how secure this is and is only intended to show a simple example of base64, so go read up on this topic!

Edit: Some additional attempts to implement a bit of security into my own python scripts.  This uses just raw_input, but I would think if your .py script(s) are source to Geoprocessing tools then you could implement these as arcpy.GetParameter()

username = raw_input("Type in your username")
password = raw_input("Type in your password")
pwd_crypted =  base64.b64encode(password)
password = base64.b64decode(pwd_crypted)
print pwd_crypted
print password
0 Kudos
OlegKachirski
New Contributor III

Yes, this will obscure password somewhat and it could be stored in a file encoded, but anyone who can look at the Python script will immediately know it is just base-64 and will be able to decode in one line:

'mysafepassword'.encode('base64')

'encodedpassword'.decode('base64')

What I would like to know (and ESRI please feel free to chime in any time) is what the phrase 'The password is a geoprocessing-encrypted string' actually means? There are two passwords passed to this command (sysadmin and GDB admin) and documentation states that both are 'Encrypted String'. So there is got to be a way to pass an encrypted password, one would think?

0 Kudos
AndrewQuee
Occasional Contributor III

We're in a similar position of mental disconnect as we're a government organisation that intend to share all of our codebase as open source.  Naturally, we don't want to be offering up all of our authentication information as embedded plaintext to the world, so handshaking methods like this are essential.

Encrypted strings defined (10.1)

I believe if you want to handle this via script, you'll need to call GetParameter in ArcPy, which delivers the GPEncryptedString automatically.  I found very few examples of how to do this.  Joel McCune discusses some of the implementation here, although the focus is not exactly on what you're doing.

Relevant stackexchange question.

0 Kudos
JamesCrandall
MVP Frequent Contributor

Naturally, we don't want to be offering up all of our authentication information as embedded plaintext to the world

I think that is the goal and applying any significant security maybe should exist in other layers including at this application tier.  The Geoprocessing tool is really just a façade for the script (it also collects parameters and performs other UI requirements of course).  But for the above purposes we can certainly do this.

This may be a way we can remove the plain text from input to variable setting for accessing our ArcGIS Online Organizational account (we want to hide plain text references of login credentials).  Is it hack-proof?  No, but again it satisfies a certain level of anonymity in conjunction with the normal organizational security measures already in place.

Edit: Parameter(0) is just a String.  Parameter(1) is String Hidden and does not show when typing into the input box.

import arcpy
import sys, os
import base64
import shutil
from urlparse import urljoin
import json
import urllib2, urllib
import httplib

username = arcpy.GetParameter(0)
pwd_crypted =  base64.b64encode(arcpy.GetParameter(1))
arcpy.AddMessage("The encrypted password: " + pwd_crypted)

AGOL = "yeah right.  get your own url"

def gentoken(username=None, password=None, expiration=1):
    """
    gentoken returns a token from AGOL
    :param username: valid AGOL username
    :param password: valid AGOL password for username
    :param expiration: expiration in minutes, defaults to 1 minute
    :return: token from AGOL or None if failed to get a token
    """
    token = None
    params = {'username': username,
              'password': base64.b64decode(pwd_crypted),
              'expiration': str(expiration),
              'client': 'referer',
              'f': 'json',
              'referer': AGOL}
    
    url = urljoin(AGOL, "sharing/rest/generateToken")
    data = urllib.urlencode(params)
    response = urllib2.urlopen(url, data)
    json_response = json.loads(response.read())
    
    if "token" in json_response:
        token = json_response['token']
    return token


def getOrganizationId(token):
    """
    getOrganizationId returns the id of the organization a user belongs to
    :param token: AGOl token
    :return: Id of the organization or None if failed to get an Id
    """
    url = urljoin(AGOL, 'sharing/rest/portals/self')
    headers = {'referer': AGOL}
    params = {'f': 'json', 'token': token}
    data = {}
    orgId = None
    dat = urllib.urlencode(params)
    requestObj = urllib2.urlopen(url=url, data=dat)
    responseJSON = json.loads(requestObj.read().decode('utf-8'))
    if 'id' in responseJSON:
         orgId = responseJSON['id']
         return orgId



def getOrganization(token):
    """
    getOrganizationId returns the id of the organization a user belongs to
    :param token: AGOl token
    :return: Id of the organization or None if failed to get an Id
    """
    url = urljoin(AGOL, 'sharing/rest/portals/self')
    headers = {'referer': AGOL}
    params = {'f': 'json', 'token': token}
    data = {}
    org = None
    dat = urllib.urlencode(params)
    requestObj = urllib2.urlopen(url=url, data=dat)
    org = json.loads(requestObj.read().decode('utf-8'))
    
    return org

def main():
    
    AGOLUser = username
    AGOLPassword = pwd_crypted
    token = gentoken(AGOLUser, AGOLPassword, 60)
    orgId = getOrganizationId(token)
    
    orgQuota = int(getOrganization(token)['storageQuota'])
    orgUsage = int(getOrganization(token)['storageUsage'])
    arcpy.AddMessage('Storage quota organization: {0}, storage usage organization {1}, percent used {2}'.format(orgQuota, orgUsage, 100.0 * orgUsage / orgQuota))

#let's login to AGOL and see what our storage quota info is at for the organization
main()
0 Kudos
KevinHibma
Esri Regular Contributor

Its not clear to me what you're trying to do.

The encrypted string parameter only has use with the Database tools. The Esri system has handles the encryption/decryption when gathering the password and supplying it to the database.

If you were to create your own script or model tool and want to use the encrypted string parameter to do something like authenticate against a websource -- its not going to work.

Are you saying the password you have is already encrypted? If the database you're working with accepts this encrypted string, I suspect you could just pass this into the tool where it'll encrypt it again, and pass it to the database where it should decrypt it back to your original encrypted state.

If this doesn't answer your question, can you further explain what it is you're trying to do?

0 Kudos