{ "info": { "author": "thanhson.rf@gmail.com", "author_email": "thanhson.rf@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6" ], "description": "************\nconfigparsercrypt\n************\n\nby thanhson.rf@gmail.com (@sonnt85)\n\nA simple solution to the often annoying problem of protecting config files.\n\nconfigparsercrypt makes keeping your secrets secure on servers and source control \nrepositories easy by restricting your choices on the matter, defaulting to \na \"medium-high paranoia\" set of operations.\n\nThose choices, specifically::\n\n Use AES-128 CBC via Fernet (see https://cryptography.io/en/latest/fernet/ )\n Store keys in environment variables, or in files protected by the system.\n Provide an easy way to overwrite sensitive string data left behind by with zeroes.\n\nThis library has undergone an overhaul since last version, so if you were using 0.0.2.x,\nplease read the below carefully so you understand what has changed (A LOT!).\n\nThe major philosophical shift was to separate the duties of encryption and data \nstructure handling into the CryptKeeper classes and SecureConfig* classes. This means \nthat if you just want a consistent way to encrypt/decrypt strings and files that works\nacross all of your data structures, the CryptKeeper classes will come in handy.\n\nConfig styles currently supported::\n\n ConfigParser (see ConfigParserCrypt)\n Json (see SecureJson) -- whole-data encryption only.\n serialized dictionaries (see SecureConfig) -- whole-data encryption only.\n\nPlease let the maintainer (@sonnt85) know if you want to see another type supported.\n\nPurpose\n-------\n\nconfigparsercrypt is being developed in the context of an open-source-loving,\n\"information wants to be free\" kind of company that also does not wish to \nget totally pwned in a heartbeat when, say, github has a major security\nbreach. \n\nWe have a lot of pre-existing code that makes use of ConfigParser ini-style\nfiles and also JSON config files. The best solution for protecting our \nservices and sensitive information would be to create a drop-in replacement\nfor ConfigParser that allows us to keep 99% of the way we interact with\nconfig files, and simply wraps the decryption step.\n\nOf course, once you have decryption handled, you start to want simplified \nways of encrypting as well.\n\nThat's why configparsercrypt (as of 0.0.3) supports writing new config files.\nSee \"basic usage\" sections below to see how you can easily turn a plaintext\nvalue or file into an encrypted value or file (depending on config style).\n\nThe CryptKeeper classes can even generate new keys for you. Just make sure \nyou keep track of which keys match with your data; this library will not stop\nyou from shooting yourself in the foot!\n\nconfigparsercrypt also tries to be helpful in keeping stored keys secure. FileCryptKeeper\nhas \"paranoid\" mode on by default, which means that it will check to see whether the\nkey is in a directory protected by your operating system. If not, it will refuse to\nrun. (Turn this off using paranoid=False, if you must.)\n\nFinally, configparsercrypt contains a smattering of deployment utilities found in \nconfigparsercrypt.utils. Feel free to suggest new ones.\n\nThis library can be found at https://github.com/sonnt85 \n\nContributions and code/documentation critiques are warmly welcomed.\n\n\nHow configparsercrypt Works\n----------------------\n\nAt its core, configparsercrypt simply subclasses the configuration mechanisms we \nall know and love, and wraps certain operations (read-from-file and/or \nread-and-interpolate) in a decryption layer.\n\nThis library bases its operations on Fernet, a cryptography meta-protocol (see\nhttps://cryptography.io) developed to help programmers choose the best possible\ndefaults for their encryption tasks.\n\nThe CryptKeeper classes handle key storage, en/decryption, and key generation.\nAll SecureConfig* classes receive from_x class instantiation methods to set up\nan internal CryptKeeper. \n\nTable of Methods of key storage - CryptKeeper class - SecureConfig* classmethod:: \n\n string -- CryptKeeper -- .from_key(key_string)\n file -- FileCryptKeeper -- .from_file(key_filename)\n environment variable -- EnvCryptKeeper -- .from_env(key_env_name)\n\nAll CryptKeeper classes have a default argument of `proactive=True`, which means\nthat the CryptKeeper instance will try to store a key in that place whether it\ncurrently exists or not. If this place is not writeable, you'll get your OS's usual\nerror for an attempted operation.\n\nWhen proactive=False and locations do not exist, you'll get a KeyError for environment\nvariables or an OSError for files.\n\nIf CryptKeeper classes are instantiated without a key argument, they will generate\na key automatically for you. \n\nAnother way to generate a new key is to use the CryptKeeper classmethod `.generate_key()`.\n\nNOTICE: You can't assign a new key to a CryptKeeper object after it's been created and\nhave it work. (If that seems like misbehaviour, let me know; it's changeable.)\n\nAll of the SecureConfig* classes can be used with or without encryption keys,\nalthough you'll get a ConfigParserCryptException('bad data or no encryption key') if\nyou try to parse a data structure (such as JSON) out of encrypted text.\n\nFinally, in configparsercrypt is a class called SecureString, which is a subclass of the\nstring object. Its special function is to zero out the memory location of the string\npayload. This class has its own section and explanation at the bottom.\n\nSecureString must be considered HAZARDOUS MATERIALS and not implicitly trusted.\nSee below for why.\n\n\n\nInstallation and Requirements\n-----------------------------\n\nTo install configparsercrypt, you'll need to have the development libraries for libffi\nand libssl installed on your system. On ubuntu, therefore, you'd do this::\n\n sudo apt-get install libffi-dev libssl-dev\n\nBeyond this requirement, most users will find they can install configparsercrypt via pip:\n\n pip install configparsercrypt \n\nThe following requirements form the backbone of configparsercrypt::\n\n cryptography\n configparser\n cffi\n six\n pycparser\n\nIf you have any problems installing these requirements, please let the \nmaintainer of this package know at https://github.com/sonnt85/sonnt85/configparsercrypt\n\nConfigParserCrypt\n------------------\n\nNEW SINCE 0.1.0:\n\nConfigParserCrypt is a subclass of the configparser module's ConfigParser class.\n\nThe difference is that, when instantiated via one of the standardized cryptkeeper \nclassmethods (see above) so that a private key is supplied, ConfigParserCrypt\ndetects encrypted entries and decrypts them when demanded (i.e. when .get is used).\n\nSo, unlike SecureJson, this class encrypts and decrypts single values rather than\nentire files.\n\nAll of the usual ConfigParser methods are available.\n\nIn addition, you can set new values into the config to be encrypted by supplying\n`encrypt=True` as an argument to the .set method. See an example of this below.\n\n\n.. code-block:: python\n\n from configparsercrypt import ConfigParserCrypt\n\n # starting with an ini file that has unencrypted entries:\n configpath = '/etc/app/config.ini'\n\n key_env = 'SCP_INI_KEY'\n\n scfg = ConfigParserCrypt.from_env('SCP_INI_KEY')\n scfg.read(configpath)\n\n username = scfg.get('credentials', 'username')\n password = scfg.get('credentials', 'password')\n \n connection = GetSomeConnection(username, password)\n\n # IMPORTANT: supply encrypt=True to encrypt values.\n scfg.set('credentials', 'password', 'better_password', encrypt=True)\n \n fh=open('/path/to/new_scfp.ini', 'w')\n scfg.write(fh)\n fh.close()\n\n\nSecureJson\n----------\n\nSecureJson is a very simple wrapper around JSON data. It decrypts whole files\n(or whole strings) and can encrypt new configurations as well.\n\nUse one of the cryptkeeper classmethods above to instantiate with a key. SecureJson will \nhappily process plaintext data as well if no key is supplied.\n\nSecureJson is a subclass of SecureConfig (see below), and as such, as some\nConfigParser-like operations included.\n\n\nBasic usage (CHANGED SINCE 0.1.0):\n\n.. code-block:: python\n\n from configparsercrypt import SecureJson\n\n configpath = '/etc/app/config.json.enc'\n\n config = SecureJson.from_file('.keys/aes_key', filepath=configpath)\n\n username = config.get('credentials', 'username')\n password = SecureString(config.get('credentials', 'password'))\n\n connection = GetSomeConnection(username, password)\n\n # SecureString overwrites its string data with zeroes upon garbage collection.\n del(password)\n \n # set a new password \n config.set('credentials', 'password', 'better_password')\n \n fh=open('/path/to/config.json.enc', 'w')\n config.write(fh)\n fh.close()\n\n\n\nSecureConfig\n------------\n\nWARNING: \n\nThe way SecureConfig reads data back is via literal_eval. This approach may not\nbe without its concerns, so please do not use this class to work with data you \ndo not explicitly trust.\n\nThe lowly SecureConfig class's lot in life is to be subclassed by other objects.\nBut it can still be somewhat useful.\n\nSecureConfig stores data in serialized dictionaries, which are then encrypted\nas a whole and stored as an undecipherable blob of information. The data can only\nbe read and recovered by supplying the private key that it was encrypted with.\n\nSecureConfig provides a .cfg dictionary for raw access. It also provides many ConfigParser\nstyle interactions (see class docstring), including .get and .set methods. This works as\nlong as your data is at least 2-dimensional. \n\nYou can still use SecureConfig with 1-dimensional data (i.e. flat dictionary of key=value\npairs); you just can't use the ConfigParser style interactions. \n\nBelow is demonstrated the non-ConfigParser style of interacting with SecureConfig data.\n\nBasic Usage (CHANGED SINCE 0.1.0):\n\n.. code-block:: python\n\n from configparsercrypt import SecureConfig\n\n config = SecureConfig.from_file('.keys/aes_key', filepath='/path/to/serialized.enc')\n\n cfg = config.cfg\n\n username = cfg['username']\n password = cfg['password']\n\n connection = GetSomeConnection(username, password)\n\n\nSecureString\n------------\n\n\"RAM security is haaaard\" --Noah Kantrowitz, https://twitter.com/kantrn/status/461654722558963712\n\nSecureString is a subclass of the string object with one modification: when deleted\nand garbage-collected by python, or when its .burn() function is called, which \nexplicitly zeroes out the data.\n\nNow this documentation must spend due time convincing you why it is not \"secure\".\n\nPython generally tries to create references to 'payload' data in memory rather than\ncopy payloads whenever possible, but in those and other scenarios, you may wind up\nhaving string data copied into other locations, and SecureString won't have any idea.\n\nIn a \"tight\" scenario, e.g. where SecureString could be used to receive the `password` \nand then immediately be \"burned after reading\", SecureString can be trusted to zero\nout the string data completely. Outside of these strict scenarios, a number of \ncircumstances will create copies of your sensitive data in memory, such as \nconcatenation of strings and use of the comparison operator on strings held in lists. \n\nYou must also keep in mind that, even if you del(secure_string) and explicitly\nrun gc.collect(), your string will still be in memory if there are still references\nto that string lying around in other objects.\n\nAlso, if your python program does not complete gracefully, garbage collection may\nnot run completely or at all, so SecureString memory will not be wiped. If you want\nto insert gc.collect() statements to proactively scrape these strings, that is an\noption, but there can be performance drawbacks to aggressively running garbage \ncollection operations.\n\nFinally, different python interpreters handle memory differently, and SecureConfig \nhasn't yet been tested on more than just the standard python interpreter and the\nipython interpreter.\n\nGiven the above, SecureString cannot at this time be implicity trusted as\n\"secure\", since so much depends upon how it's used.\n\n\nFuture\n------\n\nPlanned features include::\n\n- more automated-deployment-oriented utils\n- asymmetric key deployments (e.g. RSA public key encryption)\n\n\nCONTACT\n-------\n\nLook for @sonnt85 on github if you're interested and would like to contribute!\nComments, critiques, and bug reports warmly welcomed. Pull requests encouraged.\n\n--thanhson.rf@gmail.com, spring 2014.", "description_content_type": "text/x-rst", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/sonnt85", "keywords": "", "license": "MIT", "maintainer": "thanhson.rf@gmail.com", "maintainer_email": "thanhson.rf@gmail.com", "name": "configparsercrypt", "package_url": "https://pypi.org/project/configparsercrypt/", "platform": "", "project_url": "https://pypi.org/project/configparsercrypt/", "project_urls": { "Homepage": "https://github.com/sonnt85" }, "release_url": "https://pypi.org/project/configparsercrypt/1.0.2/", "requires_dist": null, "requires_python": "", "summary": "Configuration-oriented encryption toolkit to make secure config files simple", "version": "1.0.2" }, "last_serial": 4991679, "releases": { "1.0.2": [ { "comment_text": "", "digests": { "md5": "fd7add1a99248ee795afc2a609bb01c2", "sha256": "248dc12138da54fd2cafdedd97f70c619ed3dd74cd673e013fc7aa2eceaa7938" }, "downloads": -1, "filename": "configparsercrypt-1.0.2.tar.gz", "has_sig": false, "md5_digest": "fd7add1a99248ee795afc2a609bb01c2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25000, "upload_time": "2019-03-27T09:33:11", "url": "https://files.pythonhosted.org/packages/d6/90/0bd6e49d86e2dd9f7e1fcec9b6045ba7bd6e13a16bee100dadf032e18270/configparsercrypt-1.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "fd7add1a99248ee795afc2a609bb01c2", "sha256": "248dc12138da54fd2cafdedd97f70c619ed3dd74cd673e013fc7aa2eceaa7938" }, "downloads": -1, "filename": "configparsercrypt-1.0.2.tar.gz", "has_sig": false, "md5_digest": "fd7add1a99248ee795afc2a609bb01c2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25000, "upload_time": "2019-03-27T09:33:11", "url": "https://files.pythonhosted.org/packages/d6/90/0bd6e49d86e2dd9f7e1fcec9b6045ba7bd6e13a16bee100dadf032e18270/configparsercrypt-1.0.2.tar.gz" } ] }