Skip to main content

Hi,

 

Looking to call a PowerShell script that will need to be run as a different user to the service account that runs the FME Flow service.

FME Flow is a shared server and these credentials need to be secure from other users scheduling flows.

  • I could use an encrypted xml file for the credentials, but then all who use the server would have access via the FME Flow service account.
  • Putting the password in the workspace as a password, I still see it in plain text.

While these work and I can make the exposure risk lower, still don’t seem ideal,

What are my other options?

I’m a bit curious about that second option. If you create a user parameter of the type password it should encrypt the value. Can you share how you’ve set it up?


Could you hide the settings in a WebConnection? Or somewhere that requires HTTPCaller and Authentication to read?

You could encode the entire workbench? Everything that is stored in the workbench could be exposed to the editor of the workbench anyway. I think WebConnections and Encrypted workbenches are the only safe ways to store things like this from other Server users.

 


I have found the best way it to use a Web or Database connection. You can then use FME’s Python APi to extract the credentials.

https://docs.safe.com/fme/html/fmepython/api/fmewebservices/connection.html

In order to avoid anything showing up in the logs you can set the PW as an environment variable in the python script and then when calling you power shell script you can pass the PW using the environment variable. 

Here’s a snippet from one of my workspaces - There is an extra section in there which looks at if the connection type is a database connection or if the details are “embedded” at run time but that wouldn’t be relevant for you.  
 

import fme
import fmeobjects
import os
from fmegeneral.webservices import NamedConnectionManager

#sets the password to an environment variable so we don't need to expose it in the system

def get_connection(connection):
named_connection = NamedConnectionManager().getNamedConnection(connection)
conDetails = named_connection.getNameValues()
return conDetails

class FeatureProcessor(object):
"""Template Class Interface:
When using this class, make sure its name is set as the value of the 'Class to Process Features'
transformer parameter.
"""

def __init__(self):
"""Base constructor for class members."""

pass

def input(self, feature: fmeobjects.FMEFeature):

#sets password
if feature.getAttribute('CON_TYPE') == "connection":
connetionDetails=get_connection(feature.getAttribute('DATABASE_CONNECTION'))
os.environ 'DB_PASS'] = connetionDetailsn'PASSWORD']
feature.setAttribute('DB_HOST',connetionDetailsn'HOST'])
feature.setAttribute('DB_NAME',connetionDetailsn'DATASET'])
feature.setAttribute('DB_USER',connetionDetailsn'USER_NAME'])
feature.setAttribute('DB_PORT',connetionDetailsn'PORT'])

elif feature.getAttribute('CON_TYPE') == "embed":
os.environ 'DB_PASS']=feature.getAttribute('DB_PASSWORD')
feature.setAttribute('DB_HOST',feature.getAttribute('DB_HOST'))
feature.setAttribute('DB_NAME',feature.getAttribute('DB_NAME'))
feature.setAttribute('DB_USER',feature.getAttribute('DB_USER'))
feature.setAttribute('DB_PORT',feature.getAttribute('DB_PORT'))

else:
raise


In my SystemCaller I can then just use %DB_PASS% in the call to refer to the password. The variable does not get resolved in any FME logs. 

The benefit of using a Connection is that you can restrict access to it. The downside is that as soon as you share the connection with someone you kind of have to assume that the password is accessible to them because of FME Python API.

If someone has access to the superuser account (or admin?) in FME Server they essentially have access to all the connection data...so just don’t let anyone be the superuser and make sure that when sharing connections that they are only shared.

You can create a new repository and create a token which has access to run workspaces in that repo and also has access to that connection. You can then use that token to trigger that job via the REST API using that token. I don’t think you can use a token on it’s own to access the credentials. 

I think as ​@jkr_wrk has suggested encrypting the whole workspace it a pretty good idea in your scenario. And it’s much less roundabout then what I’ve suggested.

 


The easiest way is encrypting the workspace. Another option when using python is using the keyring library, as described here: https://www.geeksforgeeks.org/python/storing-passwords-with-python-keyring/. The credentials are securely stored on the OS and you can update and collect the credentials as you wish. 


Reply