[DONE] Better Secrets management, for Dev / Stage / Prod

@joinlook

Thanks for the suggestion.

However, I don’t see how that addresses my issue.

I.e this is the scenario.

External MongoDB TEST instance, {"db_url": "testdb.com", "API_KEY": 123}
External MongoDB PRODUCTION instance, {"db_url": "livedb.com", "API_KEY": 456}

Anvil Dev App

import SecretsApp.ServerModule as secrets_app

mongo_db_credentials =  json.loads(secrets_app.get_secret('mongo_db_key'))
print( mongo_db_credentials['db_url'],  mongo_db_credentials['API_KEY'])


Anvil Production App

import SecretsApp.ServerModule as secrets_app

mongo_db_credentials = json.loads(secrets_app.get_secret('mongo_db_key'))

print( mongo_db_credentials['db_url'],  mongo_db_credentials['API_KEY'])

I am using a print statement as psuedo equivalent as connect to external service, for demonstration purposes.

I am not following how my Production Anvil app will get the production connection url and key value of 456 but my Development Anvil app will get connection url for testing and key value of 123

I am trying to avoid having my server module aware of the backing services it is connecting to (such as a mongo DB in this example). For Example, In case I add a third stage to the development cycle to not just be Dev -> Prod, but Dev-> UAT -> Production or whatever.

I don’t see how shared SecretsApp gets me there, from what I can see, the shared secrets app, can hold only 1 set of credentials. Can you connect the dots for me ?

Unless you do a version of the algorithm suggested by Anvil Support (in original post above), which is basically to pass in the runtime app_id and maintain the mapping to secrets in the shared secret_app.

To me, this architecturally fits best as a runtime configuration. The same codebase can be run in multiple environments (accomplished with multiple apps and git push to multiple remotes).

So it makes a cleaner deployment to say run this code (based on a git commit) and to have similar config push that says “use these credentials / secrets at runtime”.

FWIW, I think I’ll end up at the @joinlook suggestion, but pass in app_id …so

so shared secrets has

def get_secrets(_app_id):
  if _app_id == "ABCDEFGHIJKL":
    data_key = anvil.secrets.get_secret('dev_mongo_credential')
  else:
    data_key = anvil.secrets.get_secret('prod_mongo_credential')
  return data_key

then my code will as sketched out will get me there.

So something like this

Anvil Dev App

import SecretsApp.ServerModule as secrets_app

mongo_db_credentials =  json.loads(secrets_app.get_secret(anvil.app.id, 'mongo_db_key'))
print( mongo_db_credentials['db_url'],  mongo_db_credentials['API_KEY'])


Anvil Production App

import SecretsApp.ServerModule as secrets_app

mongo_db_credentials = json.loads(secrets_app.get_secret(anvil.app.id, 'mongo_db_key'))

print( mongo_db_credentials['db_url'],  mongo_db_credentials['API_KEY'])

However, I think there is a better solution design possible. (Here, “Better” == “Agnostic to all Python Code”)

1 Like