community
cancel
Showing results for 
Search instead for 
Did you mean: 

Dev Space

Customize & extend the power of Alteryx. SDKs, APIs, custom tools, and more!
SOLVED

Decrypting Passwords using Python SDK

Asteroid

In my plugin GUI created with the HTML GUI SDK, I have a field for passwords:

 

 

// --- main.js ---
// ...

function setupItem(manager, AlteryxDataItems, name, element, password = false) {
    // Create a new DataItem for Alteryx
    var dataItem = new AlteryxDataItems.SimpleString(name)
    dataItem.setValue("")
    dataItem.setPassword(password)

    // Add DataItem to Alteryx Manager
    manager.addDataItem(dataItem)

    // Connect input to DataItem
    element.change((event) => dataItem.setValue(element.val()))

    // If we have a password, we need to asynchronous get the password
    dataItem.registerPropertyListener('value', function(propertyChangeEvent) {
        element.val(propertyChangeEvent.value)
    })
}

Alteryx.Gui.BeforeLoad = (manager, AlteryxDataItems, json) => {
    setupItem(manager, AlteryxDataItems, "userPassword", $("#password"), true)
}
Alteryx.Gui.AfterLoad = (manager) => {}

The password is stored, persistent and I can easily use it in the HTML frontend for connecting to an API.

 

 

My backend, however, is supposed to rely on the Python SDK in which I cannot get the decrypted password:

 

 

    def pi_init(self, str_xml: str):
        """
        Called when the Alteryx engine is ready to provide the tool configuration from the GUI.
        :param str_xml: The raw XML from the GUI.
        """
        setting_tree = Et.fromstring(str_xml)

        # Getting the user-entered settings from the GUI
        self.username = setting_tree.find("userEmail").text
        self.password = self.alteryx_engine.decrypt_password(setting_tree.find("userPassword").text, 0)

        self.alteryx_engine.output_message(self.n_tool_id, Sdk.EngineMessageType.error,
                                            'Password: {}'.format(self.password))

Sending the decrypted password through the output message is certainly wrong, but used here only for testing purposes. The documentation (https://help.alteryx.com/developer/current/Python/use/AlteryxEngineClass.htm) gives me three options for the decryption. Value 0 as above does not work, yielding the error

 

Spoiler
Error: Data Hub Import (v1.0) (2): Traceback (most recent call last):
File "SKOPOSDataHubImport_v1.0Engine.py", line 43, in pi_init
RuntimeError: DecryptPassword only works with User and Machine encrypted passwords.

For values 2 and 3 I get no error, but still an encrypted password.

 

If I read @TashaA's post here correctly, the API method for decrypting passwords should be available in 2018.2 - am I missing something?

 

Alteryx
Alteryx

Thanks for the heads up-we are looking into this right away. 

 

In the meantime, could you provide the exact version of Alteryx Designer that you have?

 

It should be under Help->About in the menu at the top left of Designer, thanks!

 

@chrisha

Alteryx
Alteryx

Hey @chrisha,

 

It looks like the missing piece is on the HTML side. (Working with the team to get this added to the documentation.)

 

We need to specify the password encryption type on the HTML side as well. 

 

Example: 

 

var passwordDataItem = new AlteryxDataItems.SimpleString('Password', {password: true, encryptionMode: 'machine'})
manager.addDataItem(passwordDataItem)

Asteroid

Hi @TashaA,

 

thanks for following up. I have added the encryptionMode to the setup:

 

function setupItem(manager, AlteryxDataItems, name, element, password = false) {
    // Create a new DataItem for Alteryx
    var dataItem = new AlteryxDataItems.SimpleString(name, { password: password, encryptionMode: 'machine' })
    dataItem.setValue("")

    // Add DataItem to Alteryx Manager
    manager.addDataItem(dataItem)

    // Connect input to DataItem
    element.change((event) => dataItem.setValue(element.val()))

    // If we have a password, we need to asynchronous get the password
    dataItem.registerPropertyListener('value', function(propertyChangeEvent) {
        element.val(propertyChangeEvent.value)
    })
}

When using AlteryxEngine.decrypt_password(..., 0) this worked well. Notably, when setting the second parameter to 2 (as I would do according to the documentation), I again get an encoded string.

 

So, everything works now. Would be great if the documentation is updated.

 

Thanks a lot, Tasha!

 

PS: Alteryx version is 2018.2.4.47804

Asteroid

Quick Follow-Up question: I can use the macro just fine locally and in the Designer installed on the server. When I upload a workflow containing the tool, however, I get an error message:

 

Traceback (most recent call last): File "SKOPOSDataHubImport_v1.0Engine.py", line 51, in pi_init RuntimeError: Internal Error: DecryptPassword - buffer too small

Since the issue only arises when the workflow is started from the Alteryx Gallery on our internal server, I'm not sure how I can further debug this. But it seems like a problem with the SDK?

Alteryx
Alteryx

Thanks for reporting this @chrisha - logging this for our team to investigate further. 

Asteroid

Thanks! Is there a chance we see a fix soon, e.g. with the next update for the server? Otherwise, I need to look for a workaround. :)

Asteroid

Another follow-up on the problem with the "Buffer too small" error: I came across this error not only on the server, but also on other machines opening a workflow containing an encrypted password for this tool. While it is shown as an error with the Python script, there already seems to be a problem on the JavaScript side: The masked password string in the HTML input is already much longer than the actual password and does not work for logging in (i.e. in the HTML GUI using JavaScript).

 

So, could this be an encryption key problem with the correct key only stored on the machine the workflow was originally created? If so, is this the intended behavior?

 

 

Alteryx
Alteryx

@chrisha

 

Thanks for following up and providing this additional information! 

 

I reached out to the dev team and they provided this response

 

"There are really two-modes of encryption that we support; USER vs MACHINE.  If you encrypt with USER, then it can be decrypted by USER on any MACHINE.  If you encrypt with MACHINE, then only same USER same MACHINE can decrypt.  For decryption errors, we will throw the same exception “Buffer too small”, so it could be a decryption error other than that and is being masked by the same exception being thrown."

 

 

 

Asteroid

Hi @TashaA,

 

thanks for your kind and helpful response!

 

To my understanding that means, that it is currently not possible to use the password encryption feature in Tools when the workflow goes to the Alteryx Server. Because the user running scheduled workflows does not necessarily need to be the same user who has created the workflow. (As far as I know, our workers are running under a different AD user, because we need to access certain network drives.)

 

One final follow-up question: How can I use the "obfuscation" mode in the Python SDK? The documentation only lists "0: Decrypt" as option, but the initial problem in the first posts shows that this is not the same as the default mode from the JavaScript SDK. Correct?

 

Thanks & best regards

Christopher