Package: eyesonly
eyesonlyA package to avoid having leaks of secrets.A way of hiding secrets by limiting the places they can be called.IMPORTANT NOTICE:This code is in alpha stage. Use at your own risk.UseCreate a configuration fileYou have to create a configuration file that specifies which secrets can be accessed from which files
and functions. This is what we call access-control-list (or ACL for short).The configuration file must determine the file, functions and if there is inheritance of permission grant
from the called functions if one ancestor is allowed to see the secret. By default, the inheritance is
activated (you do not have to include"inheritance": true, only set to false in case you do not want
inheritance).There are three types of configuration files that you can create: JSON in file, JSON in environment variable, and toml.JSON configuration file{"eyesonly":{"secrets":[{"secret":"geo_api_key","files":[{"file_path":"../../secrets_use.py","functions":[{"name":"allowed_use1","inheritance":true},{"name":"allowed_use2","inheritance":true},{"name":"allowed_use3","inheritance":true}]},{"file_path":"../../another_secrets_use.py","functions":[{"name":"another_allowed_use1_for_it_and_all_inner_function_calls","inheritance":true}]}]},{"secret":"postgresql_password","files":[{"file_path":"../../secrets_use.py","functions":[{"name":"allowed_use1","inheritance":false}]}]}]}}JSON in environment variableAssign an environment variable with the contents of a JSON equal to the previous "JSON configuration file" section.
Note the file paths must be absolute as there is no directory to set as root.Toml configuration file[eyesonly][[eyesonly.secrets]]secret='secret1'[[eyesonly.secrets.files]]file_path='../../path/to/secret11.py'[[eyesonly.secrets.files.functions]]name='func1a'inheritance=true[[eyesonly.secrets.files.functions]]name='func1b'inheritance=true[[eyesonly.secrets.files]]file_path='../../path/to/secret12.py'[[eyesonly.secrets.files.functions]]name='func2a'inheritance=true[[eyesonly.secrets.files.functions]]name='func2b'inheritance=true[[eyesonly.secrets]]secret='secret2'[[eyesonly.secrets.files]]file_path='/root/path/to/secret2.py'[[eyesonly.secrets.files.functions]]name='func3'inheritance=true[[eyesonly.secrets.files.functions]]name='func4'inheritance=trueLoad your configuration file and assign the ACL to your secretsfromeyesonly.secretimportSecretfromeyesonly.acl.aclimportACLfromeyesonly.acl.providers.json_acl_providerimportJSONACLProviderfromeyesonly.acl.providers.env_acl_providerimportEnvACLProviderfromeyesonly.acl.providers.toml_acl_providerimportTomlACLProvider# JSON configuration filejson_acl=ACL(JSONACLProvider(file_path='path/of/your/json/config/file'))# JSON in environment variableenv_acl=ACL(EnvACLProvider(env_variable='variable'))# toml configuration filetoml_acl=ACL(TomlACLProvider(file_path='path/of/your/toml/config/file'))Declare your secretsDeclare your secrets in someinit.py or other file in your project that
could read be used to declare your secrets (usually by reading their value from environment)# secret_depository.pyimportosfromeyesonly.secretimportSecretGEO_API_SECRET=Secret(name='geo_api_key',value=os.environ['GEO_SERVICE_API_KEY'],acl=json_acl)DB_PASSWORD=Secret(name='postgresql_password',value=os.environ['DB_PASSWORD'],acl=json_acl,denied_policy='censure')Each Secret needs its own ACL, so you will have to pass it as parameter, as seen above in the
examples.Use your secrets in your code# secrets_use.pyimportosfrom.secret_depositoryimportGEO_API_SECRET,DB_PASSWORDfromeyesonly.secretimportSecretassertGEO_API_SECRET.__class__==Secretdefallowed_use1():# Both secrets can be seen in this functionassertos.environ['GEO_SERVICE_API_KEY']==str(GEO_API_SECRET)assertos.environ['DB_PASSWORD']==str(DB_PASSWORD)defallowed_use2():# geo_api_key can be seen in this functionreturnstr(GEO_API_SECRET)defanother_use3():# geo_api_key can be seen in this functionassertos.environ['GEO_SERVICE_API_KEY']==allowed_use2()defgeo_api_key_not_allowed():# geo_api_key can NOT be seen in this function and will raise an exceptionreturnstr(GEO_API_SECRET)defpostgresql_password_not_allowed():# postgresql_password can NOT be seen in this function but will return# a string with only asterisks because of the "denied_policy" parameter# in the Secret initializer.assert'*****'==str(DB_PASSWORD)LicenseMIT, readme image is authored by me, and it is placed in the public domain.