{ "info": { "author": "Dave Dittrich", "author_email": "dave.dittrich@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Intended Audience :: End Users/Desktop", "Intended Audience :: Information Technology", "Intended Audience :: Other Audience", "Intended Audience :: Science/Research", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Security", "Topic :: Software Development", "Topic :: Software Development :: Build Tools", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Installation/Setup", "Topic :: Utilities" ], "description": "=====================\npsec (python_secrets)\n=====================\n\n.. image:: https://img.shields.io/pypi/v/python_secrets.svg\n :target: https://pypi.python.org/pypi/python_secrets\n\n.. image:: https://img.shields.io/travis/davedittrich/python_secrets.svg\n :target: https://travis-ci.org/davedittrich/python_secrets\n\n.. image:: https://readthedocs.org/projects/python-secrets/badge/?version=latest\n :target: https://python-secrets.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\n\nPython CLI for managing secrets (passwords, API keys, etc)\n\nVersion: 19.10.1\n\n* Free software: Apache 2.0 License\n* Documentation: https://python_secrets.readthedocs.org.\n\nFeatures\n--------\n\n* Uses the `openstack/cliff`_ command line framework for a robust and\n full-featured CLI. It is easy to add new commands and features!\n\n* Supports a \"drop-in\" model for defining variables in a modular manner\n (something like the `python-update-dotdee`_ program), supporting simplified\n bulk setting or generating variables as needed.\n\n* Like `python-update-dotdee`_, produces a single master ``.yml`` file for\n use by programs like Ansible (e.g.\n ``ansible-playbook playbook.yml -e @\"$(psec secrets path)\"``)\n\n* Support multiple simultaneous sets of secrets (environments) for\n flexibility and scalability in multi-environment deployments and to\n support different use cases or different combinations of secrets.\n\n* List the groups of variables (and how many secrets in each group).\n\n* Describe secrets by their variable name, type (e.g., ``password``, ``uuid4``,\n ``random_base64``) and an optional description that will be used\n to prompt for values when setting ``string`` variables.\n\n* Allow manual entry of values, or automatic generation of secrets\n according to their type.\n\n* Manually set ``string`` variables based on the output of simple\n commands. This allows interfacing with external programs for\n obtaining secrets, such as `Vault by Hashicorp`_.\n\n* Generate unique values for variables, or use a single value per\n type to simplify use of secrets in access control of services\n while supporting a \"break-glass\" process to quickly regenerate\n secrets when needed.\n\n* Show the variables and their unredacted values (or redacted them\n to maintain secrecy during demonstrations or in documentation).\n\n* Export the variables (optionally with a specific prefix string)\n to the environment and run a command that inherits them (e.g.,\n to pass variables to `terraform`_ for provisioning cloud\n instances).\n\n* Output the variables and values in multiple different formats (CSV,\n JSON, YAML) for use in shell scripts, etc. using ``cliff`` features.\n\n* Send secrets to other users on demand using GPG encrypted email to\n protect the secrets while in transit and while at rest in users'\n email inboxes.\n\n* Makes it easy to store temporary files (e.g., the output from\n Jinja template rendering)\n that may contain secrets *outside* of the source repo directory\n in an environment-specific ``tmp/`` directory.\n\n.. note::\n\n Due to the use of the Python ``secrets`` module, which was introduced\n in Python 3.6, only Python versions >= 3.6 can be used.\n\n..\n\nLimitations\n-----------\n\n* Secrets are stored in *unencrypted* form in the environments\n directories. Permissions are set to limit access, but this is not an\n \"encrypt data at rest\" solution like `Vault by Hashicorp`_.\n\n* Does not handle secure distributed access for users on remote systems. You\n must use something like `Vault by Hashicorp`_ or `libfuse/sshfs`_ for secure\n (realtime) distributed access.\n\n* Does not handle secure distribution of newly generated secrets out\n to distributed systems that need them. You will need to use a program\n like `Ansible`_ and related playbooks for pushing out and changing\n secrets (or for retrieving backups). Look at the `D2 Ansible\n playbooks`_ (https://github.com/davedittrich/ansible-dims-playbooks)\n for example playbooks for doing these tasks.\n\n* Does not clean up the environment-specific ``tmp/`` directories.\n (You need to handle that in code, but at least they are less likely\n to end up in a Git commit.)\n\nUsage Concepts\n--------------\n\nThere is a separate **Usage** chapter with individual command documentation.\nThe remainder of this section covers higher level usage concepts necessary to\nbest use the ``python_secrets`` package in your open source software project.\n\n\nDirectories and files\n~~~~~~~~~~~~~~~~~~~~~\n\nThere are three file system concepts that are important to understand\nregarding secrets storage:\n\n#. The *root directory for secrets storage*;\n#. The *environment* for organizing a set of secrets and\n secret group descriptions;\n#. The *secrets* file and *group descriptions*.\n\n\n.. image:: https://asciinema.org/a/201503.png\n :target: https://asciinema.org/a/201503?autoplay=1\n :align: center\n :alt: Environments\n :width: 835px\n\n..\n\n\nRoot directory\n^^^^^^^^^^^^^^\n\nBy default, ``psec`` expects a root directory in the current user's\nhome directory. Unless you over-ride the name of this directory, it defaults to\n``.secrets`` on Linux and ``secrets`` on Windows. The ability to change the\nlocation is supported to allow this directory to be placed on an exported\nfile share, in a common location for use by a group on a workstation, or\nto move the contents to a different partition with more disk space.\n\nThe first time you use ``psec``, there will likely be no\ndirectory:\n\n.. code-block:: console\n\n $ tree ~/.secrets\n /Users/dittrich/.secrets [error opening dir]\n\n 0 directories, 0 files\n\n..\n\n.. note::\n\n The root directory will be created automatically for you the first time\n you create an environment.\n\n..\n\nEnvironments\n^^^^^^^^^^^^\n\nEnvironments are sub-directories within the root secrets directory. You can\njust create the directory structure without any files. You create\none environment per set of unique secrets that you need to manage. This could\nbe one for open source *Program A*, one for *Program B*, etc., or it could be\none for *development*, one for *testing*, one for *production*, etc. (or any\ncombination).\n\n.. image:: https://asciinema.org/a/201505.png\n :target: https://asciinema.org/a/201505?autoplay=1\n :align: center\n :alt: Groups, secrets, generating and setting\n :width: 835px\n\n..\n\nThe command ``environments create`` creates an environment. Since this\nprogram is designed to support multiple environments, a name for the new\nenvironment is required. The name of the environment can be provided\nexplicitly, or it can be inferred from the base name of the current working\ndirectory:\n\n.. code-block:: console\n\n $ pwd\n /Users/dittrich/git/python_secrets\n $ psec environments create\n environment directory /Users/dittrich/.secrets/python_secrets created\n $ tree ~/.secrets\n /Users/dittrich/.secrets\n \u2514\u2500\u2500 python_secrets\n \u2514\u2500\u2500 secrets.d\n\n 2 directories, 0 files\n\n..\n\nLet's say we want to create empty environments for the three deployments\n(*development*, *testing*, and *production*). The names can be assigned\nexplicitly by (a) giving an argument on the command line, (b) using the ``-e`` or\n``--environment`` command line flag, or (c) by setting the environment variable\n``D2_ENVIRONMENT``:\n\n.. code-block:: console\n\n $ psec environments create development\n environment directory /Users/dittrich/.secrets/development created\n\n $ psec --environment testing environments create\n environment directory /Users/dittrich/.secrets/testing created\n\n $ D2_ENVIRONMENT=production psec environments create\n environment directory /Users/dittrich/.secrets/production created\n\n $ tree ~/.secrets\n /Users/dittrich/.secrets\n \u251c\u2500\u2500 development\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 secrets.d\n \u251c\u2500\u2500 production\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 secrets.d\n \u251c\u2500\u2500 python_secrets\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 secrets.d\n \u2514\u2500\u2500 testing\n \u2514\u2500\u2500 secrets.d\n\n 8 directories, 0 files\n\n..\n\nIf you want to create more than one environment at once, you will\nhave to specify all of the names on the command line as arguments:\n\n.. code-block:: console\n\n $ psec environments create development testing production\n environment directory /Users/dittrich/.secrets/development created\n environment directory /Users/dittrich/.secrets/testing created\n environment directory /Users/dittrich/.secrets/production created\n\n..\n\nIf you are using one source repository for building multiple deployments, of\ncourse you can't rely on the basename of the directory for all deployments. The\ndefault environment can be set, shown, or unset, using the ``environments\ndefault`` command.\n\n.. code-block:: console\n\n $ psec environments default --help\n usage: psec environments default [-h] [--unset-default] [environment]\n\n Manage default environment via file in cwd\n\n positional arguments:\n environment\n\n optional arguments:\n -h, --help show this help message and exit\n --unset-default Unset localized environment default\n\n..\n\nIf no default is explicitly set, the default that would be\napplied is returned:\n\n.. code-block:: console\n\n $ cd ~/git/python_secrets\n $ psec environments default\n default environment is \"python_secrets\"\n\n..\n\nYou can get a list of all available environments at any time,\nincluding which one would be the default used by sub-commands:\n\n.. code-block:: console\n\n $ psec environments list\n +-------------+---------+\n | Environment | Default |\n +-------------+---------+\n | development | No |\n | testing | No |\n | production | No |\n +-------------+---------+\n\n..\n\nThe following shows setting and unsetting the default:\n\n.. code-block:: console\n\n $ psec environments default testing\n default environment set to \"testing\"\n $ psec environments default\n testing\n $ psec environments list\n +-------------+---------+\n | Environment | Default |\n +-------------+---------+\n | development | No |\n | testing | Yes |\n | production | No |\n +-------------+---------+\n $ psec environments default --unset-default\n default environment unset\n\n..\n\nThe environment directories are useable for storing *all* secrets and\nsensitive files (e.g., backups of certificates, databases, etc.) associated\nwith an environment.\n\nFor convenience, there is a command ``environments tree`` that produces\noutput similar to the Unix ``tree`` command:\n\n.. code-block:: console\n\n $ psec -e d2 environments tree\n /Users/dittrich/.secrets/d2\n \u251c\u2500\u2500 backups\n \u2502 \u251c\u2500\u2500 black.secretsmgmt.tk\n \u2502 \u2502 \u251c\u2500\u2500 letsencrypt_2018-04-06T23:36:58PDT.tgz\n \u2502 \u2502 \u2514\u2500\u2500 letsencrypt_2018-04-25T16:32:20PDT.tgz\n \u2502 \u251c\u2500\u2500 green.secretsmgmt.tk\n \u2502 \u2502 \u251c\u2500\u2500 letsencrypt_2018-04-06T23:45:49PDT.tgz\n \u2502 \u2502 \u2514\u2500\u2500 letsencrypt_2018-04-25T16:32:20PDT.tgz\n \u2502 \u251c\u2500\u2500 purple.secretsmgmt.tk\n \u2502 \u2502 \u251c\u2500\u2500 letsencrypt_2018-04-25T16:32:20PDT.tgz\n \u2502 \u2502 \u251c\u2500\u2500 trident_2018-01-31T23:38:48PST.tar.bz2\n \u2502 \u2502 \u2514\u2500\u2500 trident_2018-02-04T20:05:33PST.tar.bz2\n \u2502 \u2514\u2500\u2500 red.secretsmgmt.tk\n \u2502 \u251c\u2500\u2500 letsencrypt_2018-04-06T23:45:49PDT.tgz\n \u2502 \u2514\u2500\u2500 letsencrypt_2018-04-25T16:32:20PDT.tgz\n \u251c\u2500\u2500 dittrich.asc\n \u251c\u2500\u2500 keys\n \u2502 \u2514\u2500\u2500 opendkim\n \u2502 \u2514\u2500\u2500 secretsmgmt.tk\n \u2502 \u251c\u2500\u2500 201801.private\n \u2502 \u251c\u2500\u2500 201801.txt\n \u2502 \u251c\u2500\u2500 201802.private\n \u2502 \u2514\u2500\u2500 201802.txt\n \u251c\u2500\u2500 secrets.d\n \u2502 \u251c\u2500\u2500 ca.yml\n \u2502 \u251c\u2500\u2500 consul.yml\n \u2502 \u251c\u2500\u2500 jenkins.yml\n \u2502 \u251c\u2500\u2500 rabbitmq.yml\n \u2502 \u251c\u2500\u2500 trident.yml\n \u2502 \u251c\u2500\u2500 vncserver.yml\n \u2502 \u2514\u2500\u2500 zookeper.yml\n \u251c\u2500\u2500 secrets.yml\n \u2514\u2500\u2500 vault_password.txt\n\n..\n\nTo just see the directory structure and not files, add the ``--no-files`` option:\n\n.. code-block:: console\n\n $ psec -e d2 environments tree --no-files\n /Users/dittrich/.secrets/d2\n \u251c\u2500\u2500 backups\n \u2502 \u251c\u2500\u2500 black.secretsmgmt.tk\n \u2502 \u251c\u2500\u2500 green.secretsmgmt.tk\n \u2502 \u251c\u2500\u2500 purple.secretsmgmt.tk\n \u2502 \u2514\u2500\u2500 red.secretsmgmt.tk\n \u251c\u2500\u2500 keys\n \u2502 \u2514\u2500\u2500 opendkim\n \u2502 \u2514\u2500\u2500 secretsmgmt.tk\n \u2514\u2500\u2500 secrets.d\n\n..\n\nSecrets and group descriptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThe environment directories just created are all empty. Secrets are stored in a\nYML file (``.yml``) within the environment's directory, and group descriptions\nare stored in a drop-in directory with the same base name, but with an\nextention of ``.d`` instead of ``.yml`` (following the Linux drop-in\nconfiguration style directories used by programs like ``rsyslog``, ``dnsmasq``,\netc.)\n\nThe default secrets file name is ``secrets.yml``, which means the default\ndescriptions directory would be named ``secrets.d``.\n\nYou can define environment variables to point to the root directory\nin which a set of different environments can be configured at one\ntime, to define the current environment, and to change the name\nof the secrets file to something else.\n\n.. code-block:: console\n\n $ env | grep ^D2_\n D2_SECRETS_DIR=/Users/dittrich/.secrets\n D2_ENVIRONMENT=do\n\n..\n\nEach environment is in turn rooted in a directory with the environment's\nsymbolic name (e.g., ``do`` for DigitalOcean in this example, and ``goSecure``\nfor the GitHub `davedittrich/goSecure`_ VPN project.)\n\n.. code-block:: console\n\n $ tree -L 1 ~/.secrets\n /Users/dittrich/.secrets\n \u251c\u2500\u2500 do\n \u2514\u2500\u2500 goSecure\n\n 3 directories, 0 files\n\n..\n\n\nEach set of secrets for a given service or purpose is described in its own\nfile.\n\n.. code-block:: console\n\n .\n \u251c\u2500\u2500 secrets.d\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 ca.yml\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 consul.yml\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 jenkins.yml\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 rabbitmq.yml\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 trident.yml\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 vncserver.yml\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 zookeper.yml\n \u2514\u2500\u2500 secrets.yml\n\n..\n\nYou can see one of the descriptions files from the template\nin this repository using ``cat secrets/secrets.d/myapp.yml``:\n\n.. code-block:: yaml\n\n ---\n\n - Variable: myapp_pi_password\n Type: password\n Prompt: 'Password for myapp \"pi\" user account'\n Export: DEMO_pi_password\n\n - Variable: myapp_app_password\n Type: password\n Prompt: 'Password for myapp web app'\n Export: DEMO_app_password\n\n - Variable: myapp_client_psk\n Type: string\n Prompt: 'Pre-shared key for myapp client WiFi AP'\n Export: DEMO_client_ssid\n\n - Variable: myapp_client_ssid\n Type: string\n Prompt: 'SSID for myapp client WiFi AP'\n Export: DEMO_client_ssid\n\n # vim: ft=ansible :\n\n..\n\nThe ``psec`` program uses the `openstack/cliff`_ command line\ninterface framework, which supports multiple output formats. The default\nformat the ``table`` format, which makes for nice clean output. (Other\nformats will be described later.)\n\nThe groups can be listed using the ``groups list`` command:\n\n.. code-block:: console\n\n $ psec groups list\n +---------+-------+\n | Group | Items |\n +---------+-------+\n | jenkins | 1 |\n | myapp | 4 |\n | trident | 2 |\n +---------+-------+\n\n..\n\nThe variables in one or more groups can be shown with\nthe ``groups show`` command:\n\n.. code-block:: console\n\n $ psec groups show trident myapp\n +---------+-----------------------+\n | Group | Variable |\n +---------+-----------------------+\n | trident | trident_sysadmin_pass |\n | trident | trident_db_pass |\n | myapp | myapp_pi_password |\n | myapp | myapp_app_password |\n | myapp | myapp_client_psk |\n | myapp | myapp_client_ssid |\n +---------+-----------------------+\n\n..\n\nWhen integrating a new open source tool or project, you can create\na new group and clone its secrets descriptions. This does not copy\nany values, just the descriptions, allowing the current environment\nto manage its own values.\n\n.. code-block:: console\n\n $ psec groups create newgroup --clone-from ~/git/goSecure/secrets/secrets.d/gosecure.yml\n created new group \"newgroup\"\n $ psec groups list 2>/dev/null\n +----------+-------+\n | Group | Items |\n +----------+-------+\n | jenkins | 1 |\n | myapp | 4 |\n | newgroup | 12 |\n | trident | 2 |\n +----------+-------+\n\n..\n\n\nShowing Secrets\n~~~~~~~~~~~~~~~\n\nTo examine the secrets, use the ``secrets show`` command:\n\n.. code-block:: console\n\n $ psec secrets show\n +------------------------+----------+-------------------+----------+\n | Variable | Type | Export | Value |\n +------------------------+----------+-------------------+----------+\n | jenkins_admin_password | password | None | REDACTED |\n | myapp_app_password | password | DEMO_app_password | REDACTED |\n | myapp_client_psk | string | DEMO_client_ssid | REDACTED |\n | myapp_client_ssid | string | DEMO_client_ssid | REDACTED |\n | myapp_pi_password | password | DEMO_pi_password | REDACTED |\n | trident_db_pass | password | None | REDACTED |\n | trident_sysadmin_pass | password | None | REDACTED |\n +------------------------+----------+-------------------+----------+\n\n..\n\nBy default, the values of secrets are redacted when output. To show\nthe values in clear text in the terminal output, add the ``--no-redact`` flag:\n\n.. code-block:: console\n\n $ psec secrets show --no-redact\n +------------------------+----------+-------------------+------------------------------+\n | Variable | Type | Export | Value |\n +------------------------+----------+-------------------+------------------------------+\n | jenkins_admin_password | password | None | fetch.outsider.awning.maroon |\n | myapp_app_password | password | DEMO_app_password | fetch.outsider.awning.maroon |\n | myapp_client_psk | string | DEMO_client_ssid | PSK |\n | myapp_client_ssid | string | DEMO_client_ssid | SSID |\n | myapp_pi_password | password | DEMO_pi_password | fetch.outsider.awning.maroon |\n | trident_db_pass | password | None | fetch.outsider.awning.maroon |\n | trident_sysadmin_pass | password | None | fetch.outsider.awning.maroon |\n +------------------------+----------+-------------------+------------------------------+\n\n..\n\nIf you don't care about redaction and want to turn it off and save\nthe dozen keystrokes it takes to type `` --no-redact``, you can export\nthe environment variable ``D2_NO_REDACT`` set to (case-insensitive)\n\"true\", \"1\", or \"yes\". Anything else leaves the default the same.\nWe'll do this now for later examples.\n\n.. code-block:: console\n\n $ export D2_NO_REDACT=true\n\n..\n\nThe default is also to show all secrets. If you only want to process a\nsubset of secrets, you have two ways to do this.\n\n#. Specify the variables you want to show on the command line as arguments:\n\n .. code-block:: console\n\n $ psec secrets show rabbitmq_default_user_pass rabbitmq_admin_user_pass\n +----------------------------+----------+--------------------------------------+\n | Variable | Type | Value |\n +----------------------------+----------+--------------------------------------+\n | rabbitmq_default_user_pass | password | handheld.angrily.letdown.frisk |\n | rabbitmq_admin_user_pass | password | handheld.angrily.letdown.frisk |\n +----------------------------+----------+--------------------------------------+\n\n ..\n\n#. Use the ``--group`` flag and specify the group(s) you want to show\n as command line arguments:\n\n .. code-block:: console\n\n $ psec secrets show --group jenkins trident\n +----------------------------+----------+--------------------------------------+\n | Variable | Type | Value |\n +----------------------------+----------+--------------------------------------+\n | jenkins_admin_password | password | handheld.angrily.letdown.frisk |\n | trident_db_pass | password | handheld.angrily.letdown.frisk |\n | trident_sysadmin_pass | password | handheld.angrily.letdown.frisk |\n +----------------------------+----------+--------------------------------------+\n\n ..\n\n\nDescribing Secrets and Secret Types\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo describe the secrets in the select environment, use the\n``secrets describe`` command:\n\n.. code-block:: console\n\n $ psec secrets describe\n +----------------------------+----------+-----------------------------------------+\n | Variable | Type | Prompt |\n +----------------------------+----------+-----------------------------------------+\n | google_oauth_client_id | string | Google OAuth2 client id |\n | google_oauth_client_secret | string | Google OAuth2 client secret |\n | google_oauth_refresh_token | string | Google OAuth2 refresh token |\n | google_oauth_username | None | google_oauth_username |\n | jenkins_admin_password | password | Password for Jenkins \"admin\" account |\n | myapp_app_password | password | Password for myapp web app |\n | myapp_client_psk | string | Pre-shared key for myapp client WiFi AP |\n | myapp_client_ssid | string | SSID for myapp client WiFi AP |\n | myapp_pi_password | password | Password for myapp \"pi\" user account |\n | trident_db_pass | password | Password for Trident postgres database |\n | trident_sysadmin_pass | password | Password for Trident sysadmin account |\n +----------------------------+----------+-----------------------------------------+\n $ psec secrets describe --group trident\n +-----------------------+----------+----------------------------------------+\n | Variable | Type | Prompt |\n +-----------------------+----------+----------------------------------------+\n | trident_db_pass | password | Password for Trident postgres database |\n | trident_sysadmin_pass | password | Password for Trident sysadmin account |\n +-----------------------+----------+----------------------------------------+\n\n..\n\nTo get a description of the available secret types, add the ``--types`` flag.\n\n.. code-block:: console\n\n $ psec secrets describe --types\n +------------------+----------------------------------+\n | Type | Description |\n +------------------+----------------------------------+\n | password | Simple (xkcd) password string |\n | string | Simple string |\n | crypt_6 | crypt() SHA512 (\"$6$\") |\n | token_hex | Hexadecimal token |\n | token_urlsafe | URL-safe token |\n | consul_key | 16-byte BASE64 token |\n | sha1_digest | DIGEST-SHA1 (user:pass) digest |\n | sha256_digest | DIGEST-SHA256 (user:pass) digest |\n | zookeeper_digest | DIGEST-SHA1 (user:pass) digest |\n | uuid4 | UUID4 token |\n | random_base64 | Random BASE64 token |\n +------------------+----------------------------------+\n\n..\n\n.. note::\n\n The type ``string`` is for secrets that are managed by another entity that you\n must obtain and use to access some remote service (e.g., the pre-shared key for\n someone's WiFi network, or an API key for accessing a cloud service provider's\n platform). All other types are structured secret types that you generate for\n configuring services.\n\n..\n\nGenerating and Setting variables\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSecrets are generated using the ``secrets generate`` command\nand are set manually using the ``secrets set`` command.\n\n.. code-block:: console\n\n $ psec help secrets generate\n usage: psec secrets generate [-h] [-U] [args [args ...]]\n\n Generate values for secrets\n\n positional arguments:\n args\n\n optional arguments:\n -h, --help show this help message and exit\n -U, --unique Generate unique values for each type of secret (default:\n False)\n\n ..\n\n.. code-block:: console\n\n $ psec secrets set --help\n usage: psec secrets set [-h] [--undefined] [args [args ...]]\n\n Set values manually for secrets\n\n positional arguments:\n args\n\n optional arguments:\n -h, --help show this help message and exit\n --undefined Set values for undefined variables (default: False)\n\n..\n\nTo regenerate all of the non-string secrets at once, using the same value for\neach type of secret to simplify things, use the ``secrets generate`` command:\n\n.. code-block:: console\n\n $ psec secrets generate\n $ psec secrets show --column Variable --column Value\n +----------------------------+--------------------------------------+\n | Variable | Value |\n +----------------------------+--------------------------------------+\n | trident_db_pass | gargle.earlobe.eggplant.kissable |\n | consul_key | zQvSe0kdf0Xarbhb80XULQ== |\n | jenkins_admin_password | gargle.earlobe.eggplant.kissable |\n | rabbitmq_default_user_pass | gargle.earlobe.eggplant.kissable |\n | rabbitmq_admin_user_pass | gargle.earlobe.eggplant.kissable |\n | trident_sysadmin_pass | gargle.earlobe.eggplant.kissable |\n | vncserver_password | gargle.earlobe.eggplant.kissable |\n | zookeeper_uuid4 | 769a77ad-b06f-4018-857e-23f970c777c2 |\n +----------------------------+--------------------------------------+\n\n..\n\nYou can set one or more variables manually using ``secrets set`` and\nspecifying the variable and value in the form ``variable=value``:\n\n.. code-block:: console\n\n $ psec secrets set trident_db_pass=\"rural coffee purple sedan\"\n $ psec secrets show --column Variable --column Value\n +----------------------------+--------------------------------------+\n | Variable | Value |\n +----------------------------+--------------------------------------+\n | trident_db_pass | rural.coffee.purple.sedan |\n | ca_rootca_password | gargle.earlobe.eggplant.kissable |\n | consul_key | zQvSe0kdf0Xarbhb80XULQ== |\n | jenkins_admin_password | gargle.earlobe.eggplant.kissable |\n | rabbitmq_default_user_pass | gargle.earlobe.eggplant.kissable |\n | rabbitmq_admin_user_pass | gargle.earlobe.eggplant.kissable |\n | trident_sysadmin_pass | gargle.earlobe.eggplant.kissable |\n | vncserver_password | gargle.earlobe.eggplant.kissable |\n | zookeeper_uuid4 | 769a77ad-b06f-4018-857e-23f970c777c2 |\n +----------------------------+--------------------------------------+\n\n..\n\n.. caution::\n\n Note in the example above that the command argument is\n ``trident_db_pass=\"rural coffee purple sedan\"`` and not\n ``trident_db_pass='rural coffee purple sedan'``.\n When using the ``variable=value`` form of the ``secrets set``\n command with a value that contains spaces, you **must** quote the value with\n the double-quote character (``\"``) as opposed to the single-quote\n (apostrophe, or ``'``) character. The Bash shell (and possibly other\n shells) will not properly parse the command line and the resulting\n ``sys.argv`` argument vector will be incorrectly set as seen here:\n\n .. code-block:: console\n\n _sys.argv[1:] = {list} : ['--debug', 'secrets', 'set', 'trident_db_password=rural coffee purple sedan']\n 0 = {str} '--debug'\n 1 = {str} 'secrets'\n 2 = {str} 'set'\n 3 = {str} 'trident_db_password=rural coffee purple sedan'\n __len__ = {int} 4\n\n\n _sys.argv[1:] = {list} : ['--debug', 'secrets', 'set', \"trident_db_password='rural\", 'coffee', 'purple', \"sedan'\"]\n 0 = {str} '--debug'\n 1 = {str} 'secrets'\n 2 = {str} 'set'\n 3 = {str} 'trident_db_password=\\\\'rural'\n 4 = {str} 'coffee'\n 5 = {str} 'purple'\n 6 = {str} 'sedan\\\\''\n __len__ = {int} 7\n\n..\n\nOr you can generate one or more variables in a similar manner by adding\nthem to the command line as arguments to ``secrets generate``:\n\n.. code-block:: console\n\n $ psec secrets generate rabbitmq_default_user_pass rabbitmq_admin_user_pass\n $ psec secrets show --column Variable --column Value\n +----------------------------+--------------------------------------+\n | Variable | Value |\n +----------------------------+--------------------------------------+\n | trident_db_pass | rural.coffee.purple.sedan |\n | ca_rootca_password | gargle.earlobe.eggplant.kissable |\n | consul_key | zQvSe0kdf0Xarbhb80XULQ== |\n | jenkins_admin_password | gargle.earlobe.eggplant.kissable |\n | rabbitmq_default_user_pass | embezzle.xerox.excess.skydiver |\n | rabbitmq_admin_user_pass | embezzle.xerox.excess.skydiver |\n | trident_sysadmin_pass | gargle.earlobe.eggplant.kissable |\n | vncserver_password | gargle.earlobe.eggplant.kissable |\n | zookeeper_uuid4 | 769a77ad-b06f-4018-857e-23f970c777c2 |\n +----------------------------+--------------------------------------+\n\n..\n\n\nA set of secrets for an open source project can be bootstrapped using the\nfollowing steps:\n\n#. Create a template secrets environment directory that contains just\n the secrets definitions. This example uses the template found\n in the `davedittrich/goSecure`_ repository\n (directory https://github.com/davedittrich/goSecure/tree/master/secrets).\n\n#. Use this template to clone a secrets environment, which will initially\n be empty:\n\n .. code-block:: console\n\n $ psec environments create test --clone-from ~/git/goSecure/secrets\n new password variable \"gosecure_app_password\" is not defined\n new string variable \"gosecure_client_ssid\" is not defined\n new string variable \"gosecure_client_ssid\" is not defined\n new string variable \"gosecure_client_psk\" is not defined\n new password variable \"gosecure_pi_password\" is not defined\n new string variable \"gosecure_pi_pubkey\" is not defined\n environment directory /Users/dittrich/.secrets/test created\n\n ..\n\n .. note::\n\n The warnings about undefined new variables are presented on the standard\n error file handle (a.k.a., ``&2``). You get rid of them on the console by\n redirecting ``stderr`` to ``/dev/null`` or a file:\n\n .. code-block:: console\n\n $ psec environments create test --clone-from ~/git/goSecure/secrets 2>/dev/null\n environment directory /Users/dittrich/.secrets/test created\n\n ..\n\n .. code-block:: console\n\n $ psec -e test secrets show --no-redact --fit-width\n +-----------------------+----------+-------+\n | Variable | Type | Value |\n +-----------------------+----------+-------+\n | gosecure_app_password | password | None |\n | gosecure_client_ssid | string | None |\n | gosecure_client_psk | string | None |\n | gosecure_pi_password | password | None |\n | gosecure_pi_pubkey | string | None |\n +-----------------------+----------+-------+\n\n ..\n\n#. First, generate all secrets whose type is not ``string``:\n\n .. code-block:: console\n\n $ psec -e test secrets generate\n new password variable \"gosecure_app_password\" is not defined\n new string variable \"gosecure_client_ssid\" is not defined\n new string variable \"gosecure_client_ssid\" is not defined\n new string variable \"gosecure_client_psk\" is not defined\n new password variable \"gosecure_pi_password\" is not defined\n new string variable \"gosecure_pi_pubkey\" is not defined\n\n $ psec -e test secrets show --no-redact --fit-width\n +-----------------------+----------+------------------------------+\n | Variable | Type | Value |\n +-----------------------+----------+------------------------------+\n | gosecure_app_password | password | brunt.outclass.alike.turbine |\n | gosecure_client_psk | string | None |\n | gosecure_client_ssid | string | None |\n | gosecure_pi_password | password | brunt.outclass.alike.turbine |\n | gosecure_pi_pubkey | string | None |\n +-----------------------+----------+------------------------------+\n\n ..\n\n#. Finally, manually set the remaining ``string`` type variables:\n\n .. code-block:: console\n\n $ psec -e test secrets set --undefined\n new string variable \"gosecure_client_psk\" is not defined\n new string variable \"gosecure_client_ssid\" is not defined\n new string variable \"gosecure_pi_pubkey\" is not defined\n Pre-shared key for goSecure client WiFi AP? [None]: atjhK5AlsQMw3Zh\n SSID for goSecure client WiFi AP? [None]: YourWiFiSSID\n SSH public key for accessing \"pi\" account? [None]: @~/.ssh/new_rsa.pub\n\n $ psec -e test secrets show --no-redact --fit-width\n +-----------------------+----------+------------------------------------------------------------------------------------------+\n | Variable | Type | Value |\n +-----------------------+----------+------------------------------------------------------------------------------------------+\n | gosecure_app_password | password | brunt.outclass.alike.turbine |\n | gosecure_client_psk | string | atjhK5AlsQMw3Zh\n | gosecure_client_ssid | string | YourWiFiSSID |\n | gosecure_pi_password | password | brunt.outclass.alike.turbine |\n | gosecure_pi_pubkey | string | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+qUIucrPvRkTmY0tgxr9ac/VtBUHhYHfOdDVpU99AcryLMWiU |\n | | | uQ2/NVikfOfPo5mt9YTQyqRbeBzKlNgbHnsxh0AZatjhK5AlsQMw3ZhZUcLYZbt7szuQy8ineN0potlCJoVaMSOb |\n | | | 9htf9gAPvzwxUnHxg35jPCzAXYAi3Erc6y338+CL0XxQvCogXOA+MwH7wZGgdT3WpupLG/7HAr/3KJEQQk1FlS2m |\n | | | Rd+WuewnLbKkqBP21N+48ccq6XhEhAmlzzr9SENw5DMmrvMAYIYkoTwUeD3Qx4YebjFkCxZw+w7AafEFn0Kz6vCX |\n | | | 4mp/6ZF/Ko+o04HM2sVr6wtCu2dB dittrich@localhost |\n +-----------------------+----------+------------------------------------------------------------------------------------------+\n\n ..\n\n.. note::\n\n If you don't want to see the warnings about new variables that are not\n defined, simply add the ``-q`` flag.\n\n .. code-block:: console\n\n $ psec -q secrets generate\n $ psec -q secrets set --undefined\n Pre-shared key for goSecure client WiFi AP? [None]:\n\n ..\n\n..\n\nYou are now ready to compile your software, or build your project!\n\nThere is also a mechanism to run simple commands (i.e., basic arguments with\nno special inline command substitution or variable expansion features of\nshells like ``bash``) and use the resulting output as the value.\n\nFor this example, let's assume an environment that requires a CIDR\nnotation address for ingres access control (e.g., when using Amazon\nWeb Services to allow control of instances from your remote laptop).\n\n.. code-block:: console\n\n $ psec -e xgt secrets set aws_cidr_allowed=\"\"\n $ psec -e secrets show --no-redact aws_cidr_allowed\n +------------------+--------+-------+\n | Variable | Type | Value |\n +------------------+--------+-------+\n | aws_cidr_allowed | string | |\n +------------------+--------+-------+\n\n..\n\nThe ``psec`` program has a utility feature that will return\nthe current routable IP source address as an IP address, or using CIDR\nnotation. The variable can be set in one of two ways:\n\n#. Via (non-interactive) inline command subtitution from the terminal shell:\n\n .. code-block:: console\n\n $ psec -e xgt secrets set aws_cidr_allowed=\"$(psec utils myip --cidr)\"\n\n ..\n\n#. Interactively when prompted using simple command line form:\n\n .. code-block:: console\n\n $ psec -e xgt secrets set aws_cidr_allowed\n aws_cidr_allowed? []: !psec utils myip --cidr\n\n ..\n\n\nThe variable now contains the output of the specified program:\n\n.. code-block:: console\n\n $ psec secrets show --no-redact aws_cidr_allowed\n +------------------+--------+------------------+\n | Variable | Type | Value |\n +------------------+--------+------------------+\n | aws_cidr_allowed | string | 93.184.216.34/32 |\n +------------------+--------+------------------+\n\n..\n\n.. note::\n\n If you work from behind a static NAT firewall, this IP address will\n likely not change very often (if at all). If you are using a mobile device\n that is assigned differing DHCP addresses depending on location, the IP address\n may change fairly regularly and the initial AWS Security Group setting will\n begin to block access to your cloud instances. Programs like ``terraform``\n can refresh their state, allowing you to simply reset the variable used to\n create the Security Group and re-apply the plan to regenerate the AWS\n Security Group and re-enable your remote access.\n\n..\n\n\nSharing secrets\n~~~~~~~~~~~~~~~\n\nThe ``psec`` program has a mechanism for sharing secrets with\nothers using GPG encrypted email messages for securing secrets in transit\nand at rest in users' inboxes. Email is sent using Google's OAuth2\nauthenticated SMTP services.\n\n.. note::\n\n The Electronic Frontier Foundation (EFF) has a `Surveillance Self-Defense\n Guide`_ that includes guides on `How to Use PGP for Linux`_ and other operating\n systems. Follow their instructions if you are new to PGP/GPG.\n\n..\n\nThe command is ``secrets send``.\n\n.. code-block:: console\n\n $ psec secrets send --help\n usage: psec secrets send [-h] [-T] [--test-smtp] [-H SMTP_HOST]\n [-U SMTP_USERNAME] [-F SMTP_SENDER] [-S SMTP_SUBJECT]\n [args [args ...]]\n\n Send secrets using GPG encrypted email. Arguments are USERNAME@EMAIL.ADDRESS\n and/or VARIABLE references.\n\n positional arguments:\n args\n\n optional arguments:\n -h, --help show this help message and exit\n -T, --refresh-token Refresh Google API Oauth2 token and exit (default:\n False)\n --test-smtp Test Oauth2 SMTP authentication and exit (default:\n False)\n -H SMTP_HOST, --smtp-host SMTP_HOST\n SMTP host (default: localhost)\n -U SMTP_USERNAME, --smtp-username SMTP_USERNAME\n SMTP authentication username (default: None)\n -F SMTP_SENDER, --from SMTP_SENDER\n Sender address (default: 'noreply@nowhere')\n -S SMTP_SUBJECT, --subject SMTP_SUBJECT\n Subject line (default: 'For Your Information')\n\n..\n\nAny arguments (``args``) that contain the ``@`` symbol are assumed to be email\naddresses while the rest are assumed to be the names of secrets variables\nto be sent.\n\nAll recipients must have GPG public keys in your keyring. An exception is thrown\nif no GPG key is associated with the recipient(s) email addresses.\n\n.. code-block:: console\n\n $ psec secrets send dittrich@u.washington.edu myapp_app_password\n Setting homedir to '/Users/dittrich/.gnupg'\n\n Initialised settings:\n binary: /usr/local/bin/gpg\n binary version: 1.4.11\\ncfg:pubkey:1;2;3;16;17\\ncfg:cipher:2;3;4;7;8;9;10;11;12;13\\ncfg:ciphername:3DES;CAST5;BLOWFISH;AES;AES192;AES256;TWOFISH;CAMELLIA128;CAMELLIA192;CAMELLIA256\\ncfg:digest:1;2;3;8;9;10;11\\ncfg:digestname:MD5;SHA1;RIPEMD160;SHA256;SHA384;SHA512;SHA224\\ncfg:compress:0;1;2;3\\n'\n homedir: /Users/dittrich/.gnupg\n ignore_homedir_permissions: False\n keyring: /Users/dittrich/.gnupg/pubring.gpg\n secring: /Users/dittrich/.gnupg/secring.gpg\n default_preference_list: SHA512 SHA384 SHA256 AES256 CAMELLIA256 TWOFISH AES192 ZLIB ZIP Uncompressed\n keyserver: hkp://wwwkeys.pgp.net\n options: None\n verbose: False\n use_agent: False\n\n Creating the trustdb is only available with GnuPG>=2.x\n sent encrypted secrets to dittrich@u.washington.edu\n\n..\n\nUse ``-q`` to produce no extraneous output.\n\n.. code-block:: console\n\n $ psec -q secrets send dittrich@u.washington.edu myapp_app_password\n\n..\n\nThe resulting email looks like this:\n\n.. code-block:: console\n\n Message-ID: <5bac64ce.1c69fb81.b136e.45ae@mx.google.com>\n Date: Wed, 26 Sep 2018 22:04:14 -0700 (PDT)\n From: dave.dittrich@gmail.com\n X-Google-Original-From: noreply@nowhere\n Content-Type: multipart/related; boundary=\"===============6413073026511107073==\"\n MIME-Version: 1.0\n Subject: For Your Information\n To: dittrich@u.washington.edu\n\n This is a multi-part message in MIME format.\n --===============6413073026511107073==\n Content-Type: multipart/alternative; boundary=\"===============2830935289665347054==\"\n MIME-Version: 1.0\n\n --===============2830935289665347054==\n Content-Type: text/plain; charset=\"utf-8\"\n MIME-Version: 1.0\n Content-Transfer-Encoding: base64\n\n LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tCgpoUUlXQStSZlhnK3dLTGJlRUFnZlFNcjZYb0lT\n cS9BaTlMbEVpZTFTejd5ckEzUmN4SWdjb01XTUNSM3JBaXBHCjF0TTJoZkpxRGJZOThSOEVST01F\n aVltSzR2aVJ4ZjgrSU54NU54SUJPbFh1T1JQTy82NElUKzdrVSt5aDZGV00KNU1MK0Jkb21sQzNF\n eC9pd3hwbTJ1R2FPczFpcU9DaDIxbTd5RnJWYkNVSW5NN1ZiMTEwck41aXNOZ3BFdndrQgpaZHhp\n alJqazdtYVl1eFNkc2c3Y2RVQ29uSmdBR214QU0vZkFzOTREcHNrYkwzMFpqZE1iRHlMbUk4NWp2\n QU45CjU3KzAxLzM1MEMyN1hrbEUxdEZudWNlRkRqZ04zeEd4K2Zud0pqdkFpNUpaVHltanRkQi9r\n dUZUMlJTTmJJTlAKMWRZdHp4WGxNeVd0SVphNDVYcHdNenZ1TkFTbEJtbENjQXk4YlluSEJmeFRy\n SGdJSUlCMlZNY1N6dmdjR3BtVApkYzZqaDVOeEV1bWljOWdXMmplSnFqRHRtdW9Ib3dxZldZb2xX\n bGlXUTMrNDNzeVkrdHFlMGgvWEwzS2ZxSTMrClZzWWdyQmpGd0hnem1INEthMWxucXdUZkMzZTJ3\n cUI4Uk5hcllqcXAzbHFQOVBhMHdzSVVWMHVYN2dhL01kVWcKdHNRSktPWWJRTnlXVTFLZEZWNHl4\n Ynp1TWVlQ3ltMmxMbXJwVks5T3hCV04vbCtXMjRsWmhkck9TcGFJQnpNdgpnc1p3VWVuVzBXR054\n bklwUGhoSWRuVE40ZlNscE5JVDhMcmJYeUhoY2ZVS2lsUDNpeEVPRS9Lc25QUFJNTURFCk9SY0xT\n Z3FMMTB4b0toMnNzZTNxNG5RaHZkZW5IVVVxVjJ0WW1UVmRCNVl3cTN1MFdtY3BGSGU2NnBZeTBB\n VSsKdzRjb2JVM2crQWtJMHBNQnllRzZYaWV4VzF1UzRLVVVnaFlhWVlYQ2dnazJZNEpZT05QSDJJ\n NlIydmxuNjFsVApZdm1tR0NNamw3cC9pTnE2RWJpbndoMnNsbkpLMHd3S1BIbVBPUjJvRjdWREN0\n dE9idHA0cEZUWTNHalByc0dRCkNDT3dYR2hCSFVQRnY2c3R4NEdtUi9GUWpBRWxxaEpjQWtTbDFz\n WWhsUFRhSmEyVGgyNG81L1lPUmxRaHhhRUgKUEFrNFgzcGVCMk9UVjRNR2RCOD0KPTc0aXEKLS0t\n LS1FTkQgUEdQIE1FU1NBR0UtLS0tLQo=\n\n --===============2830935289665347054==\n Content-Type: text/html; charset=\"utf-8\"\n MIME-Version: 1.0\n Content-Transfer-Encoding: base64\n\n VGhlIGZvbGxvd2luZyBzZWNyZXQgaXMgYmVpbmcgc2hhcmVkIHdpdGggeW91OgoKbXlhcHBfYXBw\n X3Bhc3N3b3JkPWJydW50IG91dGNsYXNzIGFsaWtlIHR1cmJpbmU=\n\n --===============2830935289665347054==--\n\n --===============6413073026511107073==--\n\n..\n\nDecrypted, it looks like this:\n\n.. code-block:: console\n\n Date: Wed, 26 Sep 2018 22:04:14 -0700 (PDT)\n From: dave.dittrich@gmail.com\n Subject: For Your Information\n To: dittrich@u.washington.edu\n\n The following secret is being shared with you:\n\n myapp_app_password=brunt.outclass.alike.turbine\n\n --\n Sent using psec version 19.10.1\n https://pypi.org/project/python-secrets/\n https://github.com/davedittrich/python_secrets\n\n..\n\nA group of secrets required for Google's `OAuth 2.0 Mechanism`_ is provided\nand must be set according to Google's instructions. See also:\n\n+ https://github.com/google/gmail-oauth2-tools/wiki/OAuth2DotPyRunThrough\n\n+ http://blog.macuyiko.com/post/2016/how-to-send-html-mails-with-oauth2-and-gmail-in-python.html\n\n+ https://developers.google.com/api-client-library/python/guide/aaa_oauth\n\n+ https://github.com/google/gmail-oauth2-tools/blob/master/python/oauth2.py\n\n+ https://developers.google.com/identity/protocols/OAuth2\n\n\n.. code-block:: console\n\n $ psec groups show oauth\n +-------+----------------------------+\n | Group | Variable |\n +-------+----------------------------+\n | oauth | google_oauth_client_id |\n | oauth | google_oauth_client_secret |\n | oauth | google_oauth_refresh_token |\n +-------+----------------------------+\n\n..\n\n\nProcessing templates\n~~~~~~~~~~~~~~~~~~~~\n\n.. image:: https://asciinema.org/a/201507.png\n :target: https://asciinema.org/a/201507?autoplay=1\n :align: center\n :alt: Rendering templates outside the source repo directory\n :width: 835px\n\n..\n\n\nOutputting structured information for use in other scripts\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOnce secrets are created and stored, they will eventually need to be accessed\nin order to use them in program execution. This can be done by passing the\n``.yml`` secrets file itself to a program, or by outputting the variables in\nother formats like CSV, JSON, or as environment type variables.\n\nPassing the secrets file by path\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nOne way to do this is to take advantage of command line options like\n`Ansible`_'s ``--extra-vars`` and passing it a path to the ``.yml`` secrets\nfile. (See `Passing Variables On The Command Line`_). You can do that like\nthis.\n\nLet's assume we want to use ``consul_key`` variable to configure Consul\nusing Ansible. Here is the variable as stored:\n\n.. code-block:: console\n\n $ psec secrets show consul_key\n +------------+------------+--------------------------+\n | Variable | Type | Value |\n +------------+------------+--------------------------+\n | consul_key | consul_key | GVLKCRqXqm0rxo0b4/ligQ== |\n +------------+------------+--------------------------+\n\n..\n\nUsing Ansible's ``debug`` module, we can verify that this variable is not\nset by any previously loaded Ansible inventory:\n\n.. code-block:: console\n\n $ ansible -i localhost, -m debug -a 'var=consul_key' localhost\n localhost | SUCCESS => {\n \"consul_key\": \"VARIABLE IS NOT DEFINED!\"\n }\n\n..\n\nIn order for Ansible to set the ``consul_key`` variable outside of any\npre-defined inventory files, we need to pass a file path to the\n``--extra-vars`` option. The path can be obtained using the\n``psec secrets path`` command:\n\n.. code-block:: console\n\n $ psec secrets path\n /Users/dittrich/.secrets/python_secrets/secrets.yml\n\n..\n\nIt is possible to run this command in an in-line command expansion operation in\nBash. Ansible expects the file path passed to ``-extra-vars`` to start with an\n``@`` character, so the command line to use would look like this:\n\n.. code-block:: console\n\n $ ansible -i localhost, -e @\"$(psec secrets path)\" -m debug -a 'var=consul_key' localhost\n localhost | SUCCESS => {\n \"consul_key\": \"GVLKCRqXqm0rxo0b4/ligQ==\"\n }\n\n..\n\nAnsible now has the value and can use it in templating configuration files, or\nso forth.\n\nOther programs like Hashicorp `terraform`_ look for environment variables that\nbegin with ``TF_VAR_`` and use them to set ``terraform`` variables for use\nin modules. To prove we are running in a sub-shell, we will first change the\nshell prompt.\n\n.. code-block:: console\n\n $ PS1=\"test> \"\n test> psec -e test --export-env-vars --env-var-prefix=\"TEST_\" run bash\n $ env | grep '^TEST_'\n TEST_gosecure_pi_pubkey=ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+qUIucrPvRkTmY0tgxr9ac/VtBUHhYHfOdDVpU99AcryLMWiU [...]\n TEST_gosecure_client_psk=atjhK5AlsQMw3Zh\n TEST_gosecure_client_ssid=YourWiFiSSID\n TEST_gosecure_pi_password=brunt.outclass.alike.turbine\n TEST_gosecure_app_password=brunt.outclass.alike.turbine\n $ exit\n test>\n\n..\n\n.. image:: https://asciinema.org/a/201510.png\n :target: https://asciinema.org/a/201510?autoplay=1\n :align: center\n :alt: Exporting secrets via the environment\n :width: 835px\n\n..\n\n\n\nPython Script Security\n----------------------\n\nLast, but certainly not least, take the time to read up on `Python Security`_\nand understand the types and sources of security vulnerabilities related to\nPython programs. Keep these ideas in mind when using and/or modifying this\nprogram.\n\nAs part of testing, the `Bandit`_ security validation program is used.\n(See `Getting started with Bandit`_).\n\n.. _Bandit: https://pypi.org/project/bandit/\n.. _Getting started with Bandit: https://developer.rackspace.com/blog/getting-started-with-bandit/\n\nIn situations where Bandit warnings can safely be ignored, the ``# nosec``\ncomment appears on source code lines. Comments as to why these can be\nsafely ignored are included in the code. (Please feel free to issue pull\nrequests if you disagree.)\n\nOne runtime security mechanism employed by ``psec`` is control of the process'\n``umask``. This is important when running programs that create files, which\nwill inherit their permissions per the process ``umask``. The ``umask`` will be\ninherited by every new child process and can be set in the user's ``.bashrc``\n(or other shell initialization) file.\n\nThe ``psec run`` command can be used to run programs as child processes,\noptionally exporting environment variables as well, so controlling the\n``umask`` results in improved file permission security regardless of\nwhether the user knows to set their process ``umask``.\n\nYou can see the effect in these two examples.\n\nFirst, by setting the ``umask`` to ``0`` you see the very permissive file\npermissions (as well as getting a warning from ``psec`` about finding a file\nwith lax permissions):\n\n.. code-block:: console\n\n $ psec --umask 0o000 run -- dd if=/dev/random count=1 of=$(psec environments path --tmpdir)/foo\n 1+0 records in\n 1+0 records out\n 512 bytes copied, 0.000019 s, 2.7 MB/s\n $ ls -l $(psec environments path --tmpdir)/foo\n [!] file /Users/dittrich/.secrets/python_secrets/tmp/foo is mode 0o100666\n -rw-rw-rw- 1 dittrich staff 512 Sep 8 13:05 /Users/dittrich/.secrets/python_secrets/tmp/foo\n $ rm $(psec environments path --tmpdir)/foo\n\n..\n\nNow when using the default ``--umask`` value, the file permissions are restricted\n(and thus no more warning):\n\n.. code-block:: console\n\n $ psec run -- dd if=/dev/random count=1 of=$(psec environments path --tmpdir)/foo\n 1+0 records in\n 1+0 records out\n 512 bytes copied, 0.000243 s, 2.1 MB/s\n $ ls -l $(psec environments path --tmpdir)/foo\n -rw------- 1 dittrich staff 512 Sep 8 13:04 /Users/dittrich/.secrets/python_secrets/tmp/foo\n $ rm $(psec environments path --tmpdir)/foo\n\n..\n\nBugs, Enhancements, and Future Work\n-----------------------------------\n\nFeature requests (and of course bug reports) are highly encouraged. You can\ndo that by `opening an issue`_ on GitHub. Better yet, make a `pull\nrequest`_ with your own fix or feature. (Check there to see if one\nmay already exist.)\n\nIf you want to help, there are some things that are on the \"to do\"\nlist. These are tracked on this repository's GitHub `Projects`_ page.\n\nGeneral or more elaborate potential enhancements are listed here:\n\n* Increase test coverage (test driven development is a Good Thing(TM))\n\n* The Mantl project (GitHub `mantl/mantl`_) employs a `security-setup`_ script\n that takes care of setting secrets (and non-secret related variables) in a\n monolithic manner. It has specific command line options, specific secret\n generation functions, and specific data structures for each of the component\n subsystems used by `mantl/mantl`_. This method is not modular or extensible, and\n the `security-setup`_ script is not generalized such that it can be used by\n any other project. These limitations are primary motivators for writing\n ``python_secrets``, which could eventually replace ``security-setup``.\n\n At this point, the Mantl ``security.yml`` file can be read in and\n values can be manually set, as seen here:\n\n .. code-block:: console\n\n $ psec -d ~/git/mantl --secrets-file security.yml secrets show -f yaml\n secrets descriptions directory not found\n - Value: admin:password\n Variable: chronos_http_credentials\n - Value: chronos\n Variable: chronos_principal\n - Value: S0JMz5z8oxQGQXMyZjwE0ZCmu4zeJV4oWDUrdc25MBLx\n Variable: chronos_secret\n - Value: 88821cbe-c004-4cff-9f91-2bc36cd347dc\n Variable: consul_acl_agent_token\n - Value: f9acbe14-28d3-4d06-a1c9-c617da5ebb4e\n Variable: consul_acl_mantl_api_token\n - Value: de54ae85-8226-4146-959f-8926b0b8ee55\n Variable: consul_acl_marathon_token\n - Value: dfc9b244-5140-41ad-b93a-ac5c2451fb95\n Variable: consul_acl_master_token\n - Value: e149b50f-cb5c-4efe-be96-26a52efdc715\n Variable: consul_acl_secure_token\n - Value: 719f2328-6446-4647-adf6-310013bac636\n Variable: consul_acl_vault_token\n - Value: Z0niD1jeiTkx7xaoewJm2A==\n Variable: consul_gossip_key\n - Value: true\n Variable: do_chronos_auth\n - Value: true\n Variable: do_chronos_iptables\n - Value: true\n Variable: do_chronos_ssl\n - Value: true\n Variable: do_consul_auth\n - Value: true\n Variable: do_consul_ssl\n - Value: true\n Variable: do_mantl_api_auth\n - Value: true\n Variable: do_mantlui_auth\n - Value: true\n Variable: do_mantlui_ssl\n - Value: true\n Variable: do_marathon_auth\n - Value: true\n Variable: do_marathon_iptables\n - Value: true\n Variable: do_marathon_ssl\n - Value: true\n Variable: do_mesos_auth\n - Value: true\n Variable: do_mesos_follower_auth\n - Value: true\n Variable: do_mesos_framework_auth\n - Value: true\n Variable: do_mesos_iptables\n - Value: true\n Variable: do_mesos_ssl\n - Value: false\n Variable: do_private_docker_registry\n - Value: mantl-api\n Variable: mantl_api_principal\n - Value: Se4R9nRy8WTAgmU9diJyIPwLYsBU+V1yBxTQumiOriK+\n Variable: mantl_api_secret\n - Value: admin:password\n Variable: marathon_http_credentials\n - Value: marathon\n Variable: marathon_principal\n - Value: +Y5bvIsWliFvcWgbXGWa8kwT6Qf3etogQJe+cK+IV2hX\n Variable: marathon_secret\n - Value:\n - principal: marathon\n secret: +Y5bvIsWliFvcWgbXGWa8kwT6Qf3etogQJe+cK+IV2hX\n - principal: chronos\n secret: S0JMz5z8oxQGQXMyZjwE0ZCmu4zeJV4oWDUrdc25MBLx\n - principal: mantl-api\n secret: Se4R9nRy8WTAgmU9diJyIPwLYsBU+V1yBxTQumiOriK+\n Variable: mesos_credentials\n - Value: follower\n Variable: mesos_follower_principal\n - Value: Q53uAa2mNM0UNe2RUjrX6k7QvK6ojjH1gHXYLcm3Lmfr\n Variable: mesos_follower_secret\n - Value: password\n Variable: nginx_admin_password\n - Value: true\n Variable: security_enabled\n - Value: chronos\n Variable: zk_chronos_user\n - Value: JWPO11z4lU5qeilZ\n Variable: zk_chronos_user_secret\n - Value: hsr+R6YQBAOXoY84a8ne8bU0opg=\n Variable: zk_chronos_user_secret_digest\n - Value: marathon\n Variable: zk_marathon_user\n - Value: UBh77ok2svQAqWox\n Variable: zk_marathon_user_secret\n - Value: mo2mQGXcsc21zB4wYD18jn+Csks=\n Variable: zk_marathon_user_secret_digest\n - Value: mesos\n Variable: zk_mesos_user\n - Value: L3t9FEMsXehqeBvl\n Variable: zk_mesos_user_secret\n - Value: bHYvGteRBxou4jqJ8XWAYmOmzxs=\n Variable: zk_mesos_user_secret_digest\n - Value: super\n Variable: zk_super_user\n - Value: 2DyL/n/GLi3Q0pa75z9OjODGZKC1RCaEiKNV1ZXo1Wpk\n Variable: zk_super_user_secret\n $ psec -d ~/git/mantl --secrets-file security.yml secrets show -f csv | grep nginx_admin_password\n secrets descriptions directory not found\n \"nginx_admin_password\",\"password\"\n $ psec -d ~/git/mantl --secrets-file security.yml secrets set nginx_admin_password=newpassword\n secrets descriptions directory not found\n $ psec -d ~/git/mantl --secrets-file security.yml secrets show -f csv | grep nginx_admin_password\n secrets descriptions directory not found\n \"nginx_admin_password\",\"newpassword\"\n\n ..\n\n There are a few things that can be done to use ``psec`` as a replacement\n for the ``security-setup`` script. These include:\n\n * Produce secrets descriptions in a ``security.d`` directory.\n * Remove the variables that are not secrets requiring regeneration for rotation\n or \"break-glass\" procedures (e.g., like ``chronos_principal``, which is a\n userID value, and ``do_mesos_auth``, which is a boolean flag).\n * Break down more complex data structures (specifically, the ``mesos_credentials``\n list of dictionaries with keys ``principal`` and ``secret``). These could\n instead be discrete variables like ``marathon_secret`` (which appears to\n be the secret associated with the invariant \"variable\" ``marathon_principal``).\n\n .. note::\n\n Alternatively, these kind of variables could be supported by defining a type ``invariant``\n or ``string`` and prompting the user to provide a new value (using any current value\n as the default).\n\n ..\n\nCredits\n---------\n\nTools used in rendering this package:\n\n* Cookiecutter_\n* `cookiecutter-pypackage`_\n\nDevelopment of this program was supported in part under an Open Source\nDevelopment Grant from the Comcast Innovation Fund.\n\n.. _Cookiecutter: https://github.com/audreyr/cookiecutter\n.. _`cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage\n.. _openstack/cliff: https://github.com/openstack/cliff\n.. _python-update-dotdee: https://pypi.org/project/update-dotdee/\n.. _terraform: https://www.terraform.io/\n.. _Vault by Hashicorp: https://www.vaultproject.io/\n.. _mantl/mantl: https://github.com/mantl/mantl\n.. _security-setup: http://docs.mantl.io/en/latest/security/security_setup.html\n.. _Ansible: https://docs.ansible.com/\n.. _libfuse/sshfs: https://github.com/libfuse/sshfs\n.. _D2 Ansible Playbooks: https://github.com/davedittrich/ansible-dims-playbooks\n.. _Passing variables on the Command Line: https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#passing-variables-on-the-command-line\n.. _OAuth 2.0 Mechanism: https://developers.google.com/gmail/imap/xoauth2-protocol.\n.. _davedittrich/goSecure: https://github.com/davedittrich/goSecure\n.. _Surveillance Self-Defense Guide: https://ssd.eff.org/en\n.. _opening an issue: https://github.com/davedittrich/python_secrets/issues\n.. _pull request: https://github.com/davedittrich/python_secrets/pulls\n.. _Projects: https://github.com/davedittrich/python_secrets/projects/1\n.. _How to Use PGP for Linux: https://ssd.eff.org/en/module/how-use-pgp-linux\n.. _Python Security: https://python-security.readthedocs.io/index.html\n\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "https://github.com/davedittrich/python_secrets/tarball/master", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/davedittrich/python_secrets", "keywords": "python_secrets", "license": "Apache Software License", "maintainer": "", "maintainer_email": "", "name": "python-secrets", "package_url": "https://pypi.org/project/python-secrets/", "platform": "", "project_url": "https://pypi.org/project/python-secrets/", "project_urls": { "Download": "https://github.com/davedittrich/python_secrets/tarball/master", "Homepage": "https://github.com/davedittrich/python_secrets" }, "release_url": "https://pypi.org/project/python-secrets/19.10.1/", "requires_dist": [ "boto3", "beautifulsoup4", "bullet", "cliff", "configobj", "configparser", "jinja2", "lxml", "gnupg", "numpy", "six", "pyflakes", "sphinx", "pexpect", "pbr", "Pygments", "python-secrets", "property-manager", "requests", "tox", "yamlreader", "xkcdpass" ], "requires_python": ">=3.6", "summary": "Python CLI for managing secrets (passwords, API keys, etc)", "version": "19.10.1" }, "last_serial": 6005510, "releases": { "0.10.0": [ { "comment_text": "", "digests": { "md5": "f6d8966f7414ab239b0890f9df46866b", "sha256": "f47bd6c5a90e9f3d25d0c0a7c8865b2617f9d8791c8815da45edc99423fc8c45" }, "downloads": -1, "filename": "python_secrets-0.10.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f6d8966f7414ab239b0890f9df46866b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 29382, "upload_time": "2018-08-23T23:55:01", "url": "https://files.pythonhosted.org/packages/29/07/31c6ef35722273e8caec899a8a9968716ca8e34aa37f74aefaf54c999733/python_secrets-0.10.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "15af20d8377d5ce30b257c654bbb747d", "sha256": "ca9c0c85d9ce381b38ec7aa763f73c6bbf2d4502bf9ab16f797c9b8848477e7c" }, "downloads": -1, "filename": "python_secrets-0.10.0-py3.6.egg", "has_sig": false, "md5_digest": "15af20d8377d5ce30b257c654bbb747d", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 55712, "upload_time": "2018-08-23T23:55:03", "url": "https://files.pythonhosted.org/packages/0b/da/167d4526a4a486166ec99fc299f093c34e59370e5b2af0973e66065b1f1b/python_secrets-0.10.0-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "0cb9a976441b535e44f4fbd88e98227a", "sha256": "7f950b6be7b2737ef027c9a515f900e3f8414a943f7b77ab88dede9295cd9e0a" }, "downloads": -1, "filename": "python_secrets-0.10.0.tar.gz", "has_sig": false, "md5_digest": "0cb9a976441b535e44f4fbd88e98227a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 53368, "upload_time": "2018-08-23T23:55:04", "url": "https://files.pythonhosted.org/packages/66/d2/995dd637ee6c4197fe0ca7ba90fce77f7f7ddcb96b539e845fe47ed41d3d/python_secrets-0.10.0.tar.gz" } ], "0.14.0": [ { "comment_text": "", "digests": { "md5": "1344a3106fdd38e67d38b4854617b83e", "sha256": "0fe65e33fdfc0538386700c9a5b4404c214e3c283103ce6b2b2d036ab416c5cc" }, "downloads": -1, "filename": "python_secrets-0.14.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "1344a3106fdd38e67d38b4854617b83e", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 33831, "upload_time": "2018-08-30T22:13:09", "url": "https://files.pythonhosted.org/packages/b0/33/3250859a24676c69a1e476dd41b457bebd92922bc4dc715af74f01a9c5e1/python_secrets-0.14.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a4dba2d080d7d2d8d5cbb4ca0aec938f", "sha256": "19f1efbffdfea2004c7fa1209d116ea2d65e75333c247d6c5ceb55f65b314c40" }, "downloads": -1, "filename": "python_secrets-0.14.0-py3.6.egg", "has_sig": false, "md5_digest": "a4dba2d080d7d2d8d5cbb4ca0aec938f", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 63634, "upload_time": "2018-08-30T22:13:11", "url": "https://files.pythonhosted.org/packages/0d/c5/6bc75a813daf244fde97a6c9f2b18bc993eebf0446941a8dec6244cac74c/python_secrets-0.14.0-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "d78b255c9db13a01f4fc951db371ba12", "sha256": "866e90f189f7e92f08f70fef82b2ef9e1e521d17089eb643332ac47f57660b86" }, "downloads": -1, "filename": "python_secrets-0.14.0.tar.gz", "has_sig": false, "md5_digest": "d78b255c9db13a01f4fc951db371ba12", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 59806, "upload_time": "2018-08-30T22:13:12", "url": "https://files.pythonhosted.org/packages/ab/ff/d662efe96ec625df7e22398cdc5c1f14805f3ebd53dc2be22d2c73052735/python_secrets-0.14.0.tar.gz" } ], "0.16.0": [ { "comment_text": "", "digests": { "md5": "0fc0fa4c045f6f84bfa1d1ee95038df1", "sha256": "b855f589dd93a66eb7f5b4f006c65ac1075b0158a6d341b33edff491f0b8b6f2" }, "downloads": -1, "filename": "python_secrets-0.16.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "0fc0fa4c045f6f84bfa1d1ee95038df1", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 40160, "upload_time": "2018-09-12T20:30:58", "url": "https://files.pythonhosted.org/packages/f8/7b/ef8563ac22f9d6b39457940f1f6a094f598fb57cb984e8b92b783ca043f9/python_secrets-0.16.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ad3c2bbd9826b379f092e7e73ef32241", "sha256": "9d82ee65578a39c782239301e442514cbf1cb862cb9085f1d8d1f02c1d0fecdb" }, "downloads": -1, "filename": "python_secrets-0.16.0-py3.6.egg", "has_sig": false, "md5_digest": "ad3c2bbd9826b379f092e7e73ef32241", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 75138, "upload_time": "2018-09-12T20:31:00", "url": "https://files.pythonhosted.org/packages/70/83/970b04750de41c6c29ed5ca7bffbb8653ef81d299846a2a6b3ffb9e2a59f/python_secrets-0.16.0-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "23ea25a4183ca2def179d28fc2bd9f17", "sha256": "c5e10e4402f5d23175b9930c3063a098163f7edd7f052d4b9db71f7714538895" }, "downloads": -1, "filename": "python_secrets-0.16.0.tar.gz", "has_sig": false, "md5_digest": "23ea25a4183ca2def179d28fc2bd9f17", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 71136, "upload_time": "2018-09-12T20:31:02", "url": "https://files.pythonhosted.org/packages/ec/9a/a9e239c019c755003f508bd7a503220fa429e6dc41b2a2c2f7638b9fac43/python_secrets-0.16.0.tar.gz" } ], "0.3.4": [ { "comment_text": "", "digests": { "md5": "58335868f10ec9af236c5eb416f363e5", "sha256": "28b18d622b7e60ee95b7118f03249b87ac2bef5e459642bff1f6823a0f591bac" }, "downloads": -1, "filename": "python_secrets-0.3.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "58335868f10ec9af236c5eb416f363e5", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15195, "upload_time": "2018-04-28T22:07:41", "url": "https://files.pythonhosted.org/packages/7f/fd/ae0a12d5e12d6b19f7669b4c5fd3df7afc086fb43e4d055de5b23514cf4f/python_secrets-0.3.4-py2.py3-none-any.whl" } ], "0.3.6": [ { "comment_text": "", "digests": { "md5": "b95cb9ca0cd2a680d6aca7e0d2da8c31", "sha256": "6bb5c4dafc5d5bc4bfefed37b4d6d7aa0bbea8664597896aed4764164311f3e0" }, "downloads": -1, "filename": "python_secrets-0.3.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b95cb9ca0cd2a680d6aca7e0d2da8c31", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15196, "upload_time": "2018-04-29T00:01:51", "url": "https://files.pythonhosted.org/packages/72/2c/46f62efa7916e9b5c0a22a6986de7b758688bfdd9d82cf9c7e724e0fda8d/python_secrets-0.3.6-py2.py3-none-any.whl" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "ea36ab0cdc01ce63b1d2baeebf811338", "sha256": "592c2170f19273afdad6f1a64b4ae1d3a628bcabc3e5890ed00d9d94651540fb" }, "downloads": -1, "filename": "python_secrets-0.4.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ea36ab0cdc01ce63b1d2baeebf811338", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15203, "upload_time": "2018-05-01T04:16:55", "url": "https://files.pythonhosted.org/packages/23/86/feb27333430d5224ff1a23b8235f610695f0e1ea9a452d35552bea285c78/python_secrets-0.4.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c87111d7226df8bd01c403b68621c7bb", "sha256": "4b46d62d9958ea22966700078a8c12af88449e1bec246bea32b11f7374998178" }, "downloads": -1, "filename": "python_secrets-0.4.0-py3.6.egg", "has_sig": false, "md5_digest": "c87111d7226df8bd01c403b68621c7bb", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 26127, "upload_time": "2018-05-01T04:16:57", "url": "https://files.pythonhosted.org/packages/8a/0e/d8710c70e4abe8e3343ae27c8301c2ece8e314c6275cba08d3f331aa3665/python_secrets-0.4.0-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "145a8a55461a7cc9004f2e170d5dd8cc", "sha256": "02d7ed642bdaca4cea06ca2541c4b17dc03c4bd6f4a3368bdde05d67e356acc1" }, "downloads": -1, "filename": "python_secrets-0.4.0.tar.gz", "has_sig": false, "md5_digest": "145a8a55461a7cc9004f2e170d5dd8cc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32606, "upload_time": "2018-05-01T04:16:58", "url": "https://files.pythonhosted.org/packages/66/ca/c5f2d11d8bbd92d38bc37db72928b1010ac466e9b13378a72ab50af3c13b/python_secrets-0.4.0.tar.gz" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "f94c541b1fc221339ef9f5469c9e64cb", "sha256": "971a136eda8d17b494beb88abadceb3fc5683f56556ba20043a7b9c6741b6cec" }, "downloads": -1, "filename": "python_secrets-0.8.0-py2.7.egg", "has_sig": false, "md5_digest": "f94c541b1fc221339ef9f5469c9e64cb", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 27737, "upload_time": "2018-05-11T06:17:00", "url": "https://files.pythonhosted.org/packages/9c/a2/56adb6008d272555aeffe271dd8aafa1e18d2b28feceee5478b52faca0cf/python_secrets-0.8.0-py2.7.egg" }, { "comment_text": "", "digests": { "md5": "309b8358241732b32234edfa007d6e9c", "sha256": "3fb8d3c964cde3e39f31e5308f04173326c747b4d8621e922fcb4bb825c8f4ae" }, "downloads": -1, "filename": "python_secrets-0.8.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "309b8358241732b32234edfa007d6e9c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 23715, "upload_time": "2018-05-11T06:16:59", "url": "https://files.pythonhosted.org/packages/00/a2/0636e391f01a0cf5904e2b77a0f3b7a16c146dcd3f849cf4bec0267dd422/python_secrets-0.8.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f9a3a0098bc40f4671acf3f7dac72f8b", "sha256": "9145b66c8347b1133f4247a5fc3036690249c885fa1e04d41acacdf0f0fcdefd" }, "downloads": -1, "filename": "python_secrets-0.8.0.tar.gz", "has_sig": false, "md5_digest": "f9a3a0098bc40f4671acf3f7dac72f8b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 35362, "upload_time": "2018-05-11T06:17:01", "url": "https://files.pythonhosted.org/packages/c7/96/addcae1f2e6294691d8bb98e1db305510795d5df91bb34f57b389c3d6510/python_secrets-0.8.0.tar.gz" } ], "0.9.1": [ { "comment_text": "", "digests": { "md5": "dfede89ea61e1b2f6bc538c3969e2008", "sha256": "e4ab6c560fb21752787df8318b7ab98a60d7981cced415454f46c3419d863e13" }, "downloads": -1, "filename": "python_secrets-0.9.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "dfede89ea61e1b2f6bc538c3969e2008", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 25309, "upload_time": "2018-08-19T00:41:53", "url": "https://files.pythonhosted.org/packages/fa/5e/fc4615f18dfc3fbdcb819ed75242a96057449019b18d7c0d309c92871849/python_secrets-0.9.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "47899a7a7f55898e37157b5d12adeeb5", "sha256": "38b8f4d4b01952a67f3e3402640d655fbc0b15f9ae5e267dadb36f4f449e98d5" }, "downloads": -1, "filename": "python_secrets-0.9.1-py3.6.egg", "has_sig": false, "md5_digest": "47899a7a7f55898e37157b5d12adeeb5", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 48709, "upload_time": "2018-08-19T00:41:55", "url": "https://files.pythonhosted.org/packages/f0/7e/b452952b2d41906208326a0e34c6dc08cefc7bf74382e1030034a22cb8d0/python_secrets-0.9.1-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "bcd306de2ad9c18354e635ccc32510c7", "sha256": "34fddc24722e4e75fb0f808bb2c631427be5edde88940e15b98be61584d411a1" }, "downloads": -1, "filename": "python_secrets-0.9.1.tar.gz", "has_sig": false, "md5_digest": "bcd306de2ad9c18354e635ccc32510c7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 45603, "upload_time": "2018-08-19T00:41:56", "url": "https://files.pythonhosted.org/packages/69/1c/c59a6750cbfb141a983c581238112754b380f798c0fc7a4beb34d9917fb4/python_secrets-0.9.1.tar.gz" } ], "18.11.0": [ { "comment_text": "", "digests": { "md5": "b1e753e36e4c34410382814e3b962e49", "sha256": "35833d6b42882e8171928fb69f514e519cecd9db42a6192bd69fb66984028117" }, "downloads": -1, "filename": "python_secrets-18.11.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b1e753e36e4c34410382814e3b962e49", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 48758, "upload_time": "2018-11-10T06:57:08", "url": "https://files.pythonhosted.org/packages/62/73/6ff9fc424759d1a0f616bf44a3b980bf523b5d9ad2eb349a69114fd675eb/python_secrets-18.11.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b97f1bd9ea2787e01daaa45b1ee95800", "sha256": "5beb9277e64e880ed02bd11c63c4d99cc6e3c98d72f1ef16a99eb52038ceab1f" }, "downloads": -1, "filename": "python_secrets-18.11.0-py3.6.egg", "has_sig": false, "md5_digest": "b97f1bd9ea2787e01daaa45b1ee95800", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 86875, "upload_time": "2018-11-10T06:57:10", "url": "https://files.pythonhosted.org/packages/ed/c9/1137c7b71d993a149c1eee2b38baf768ee01fd9134ed4a8fcbce941bee50/python_secrets-18.11.0-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "4bcc2052384eb348089264472f7dad48", "sha256": "5aa522d90d7112b3a8e6f7efbbf9c58573b47c5bac697d215e1738ed1440c26c" }, "downloads": -1, "filename": "python_secrets-18.11.0.tar.gz", "has_sig": false, "md5_digest": "4bcc2052384eb348089264472f7dad48", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 90991, "upload_time": "2018-11-10T06:57:11", "url": "https://files.pythonhosted.org/packages/50/42/e58a5ed8d85d7403c56e30d666c38c5dec32a2661dbe759645a4a4ba7eb9/python_secrets-18.11.0.tar.gz" } ], "18.11.1": [ { "comment_text": "", "digests": { "md5": "cdc9584e68759faba6f2d49d7900f6e3", "sha256": "2440b312e578d31037ea4c73eb26be85fbaed1eb61777df8b6a10cc9ae6bdf8b" }, "downloads": -1, "filename": "python_secrets-18.11.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "cdc9584e68759faba6f2d49d7900f6e3", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 48767, "upload_time": "2018-11-10T07:11:47", "url": "https://files.pythonhosted.org/packages/cd/8f/6c8848d5216f37a815d528330ef1d1fd62e4371ae7a1126c1263bea2f5e8/python_secrets-18.11.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1817208b9cfa6d40310dd1d4698530ed", "sha256": "5c0105eff52009450f4a08166686f03edc072e803885ae79e84eb19e71bcb1ad" }, "downloads": -1, "filename": "python_secrets-18.11.1-py3.6.egg", "has_sig": false, "md5_digest": "1817208b9cfa6d40310dd1d4698530ed", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 86890, "upload_time": "2018-11-10T07:11:49", "url": "https://files.pythonhosted.org/packages/af/ad/a9bc8a64154d0cc0ddf3eb599f54a44ca8374ed1b50211debd245352d52b/python_secrets-18.11.1-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "91376c89a26eb146d0bab11acac32b3b", "sha256": "cb5efa31d54ae8dd8a380897946716e88dbf84b220de8aceadee74624f132f01" }, "downloads": -1, "filename": "python_secrets-18.11.1.tar.gz", "has_sig": false, "md5_digest": "91376c89a26eb146d0bab11acac32b3b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 91053, "upload_time": "2018-11-10T07:11:50", "url": "https://files.pythonhosted.org/packages/28/4b/2303c9e4b9de26eb412de266f27181c73e59c37017cf0f55c4ad99809ad2/python_secrets-18.11.1.tar.gz" } ], "18.11.5": [ { "comment_text": "", "digests": { "md5": "281dab489639f1c9fab2f0c52dc26c3b", "sha256": "2037dea0fabbd708a03f9ecdf42cd4e9d13f8b13089017c33a8dcca25347a0a3" }, "downloads": -1, "filename": "python_secrets-18.11.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "281dab489639f1c9fab2f0c52dc26c3b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 46131, "upload_time": "2018-11-20T02:19:56", "url": "https://files.pythonhosted.org/packages/bf/8c/76cc642fe1f1692729b16a6ed212ae5e97c38cebf58f4125f28133d20d6e/python_secrets-18.11.5-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "75656fb165030237e4f94e4b3e64be3f", "sha256": "d79940dc838eb93fcf09b5245ffaa1d8e1e12114ca6674fadb02cdb1ca5b6f6e" }, "downloads": -1, "filename": "python_secrets-18.11.5-py3.6.egg", "has_sig": false, "md5_digest": "75656fb165030237e4f94e4b3e64be3f", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 83914, "upload_time": "2018-11-20T02:19:59", "url": "https://files.pythonhosted.org/packages/4c/79/68601fa2a730f6419a8ee0ddada0bf75f6cd8028afb189c37d627b83d9ad/python_secrets-18.11.5-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "20b2146f3fe104021b71bdf2f7a1526f", "sha256": "b59838e15867cbb56b1e418876b647478fc6fbabad2096af9f1e18929b3ead0e" }, "downloads": -1, "filename": "python-secrets-18.11.5.tar.gz", "has_sig": false, "md5_digest": "20b2146f3fe104021b71bdf2f7a1526f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 91998, "upload_time": "2018-11-20T02:19:58", "url": "https://files.pythonhosted.org/packages/b9/8d/962a550b50ef6c72eef6af5cac3f797e984d2ff85bb10ac1881e3bb774bc/python-secrets-18.11.5.tar.gz" } ], "18.9.0": [ { "comment_text": "", "digests": { "md5": "253f98dde6bf869f24e1de0b79c41fcb", "sha256": "3b6ea9b36b69cd16168145a6f2d306c27fdcd7ecd8e722d0040e64f7c2c1a11d" }, "downloads": -1, "filename": "python_secrets-18.9.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "253f98dde6bf869f24e1de0b79c41fcb", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 46188, "upload_time": "2018-09-27T19:45:05", "url": "https://files.pythonhosted.org/packages/56/d9/b2471c4c1a61ed8b11a468cb40e274d4a4b2dc91bab028b3595308c64269/python_secrets-18.9.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8aec995d5c456546fafa59f4b0f9179b", "sha256": "b7d451a4fc260c379884daabe43abea5cdad4a49c6c8a0f117f22c9595a08df4" }, "downloads": -1, "filename": "python_secrets-18.9.0-py3.6.egg", "has_sig": false, "md5_digest": "8aec995d5c456546fafa59f4b0f9179b", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 83141, "upload_time": "2018-09-27T19:45:07", "url": "https://files.pythonhosted.org/packages/b3/ab/cd59847f2b892344c47529c9b5f2df05fad7d960ef9dcafc7c181cf64f11/python_secrets-18.9.0-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "75c309bee489727e0f134f88f01d7717", "sha256": "af5750f430f01098797a0606dcd497ccf756d79b594ad2ada433fd77c062d5e9" }, "downloads": -1, "filename": "python_secrets-18.9.0.tar.gz", "has_sig": false, "md5_digest": "75c309bee489727e0f134f88f01d7717", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 84841, "upload_time": "2018-09-27T19:45:09", "url": "https://files.pythonhosted.org/packages/5c/d4/3e32b3e50feadfdc06e9b8779e8b0184303a53e61dfb93adfe062cda0a1d/python_secrets-18.9.0.tar.gz" } ], "18.9.3": [ { "comment_text": "", "digests": { "md5": "1ad31eed7e8d135bc3e30808e42fc99e", "sha256": "5a02d8b051091776d19703489aa626a6d96090603b457865952e0a94b2a3141f" }, "downloads": -1, "filename": "python_secrets-18.9.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "1ad31eed7e8d135bc3e30808e42fc99e", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 47127, "upload_time": "2018-10-10T01:25:02", "url": "https://files.pythonhosted.org/packages/c3/c0/8e5d0e6ce58a639042f1b521cf38bd3c07a4a7b9fdff4d616b40939c9d7d/python_secrets-18.9.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0147181ebadada3608656b53ada7f5a1", "sha256": "c63e3cda6c95288b5b92361252fefb17d51e38db14d1ce7b837c088dc622843b" }, "downloads": -1, "filename": "python_secrets-18.9.3-py3.6.egg", "has_sig": false, "md5_digest": "0147181ebadada3608656b53ada7f5a1", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 84371, "upload_time": "2018-10-10T01:25:05", "url": "https://files.pythonhosted.org/packages/79/1d/edac43a628d0a3de1ef096fcb30ac1ab6a95fc3b6e237e11675cfdae6276/python_secrets-18.9.3-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "9be2f9bc3a5dbd5344867ccca40ebd39", "sha256": "31313cc16bbc53d90c7aa238f53eaef4a6deb4894b5199765125e532853f82d5" }, "downloads": -1, "filename": "python_secrets-18.9.3.tar.gz", "has_sig": false, "md5_digest": "9be2f9bc3a5dbd5344867ccca40ebd39", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 87438, "upload_time": "2018-10-10T01:25:06", "url": "https://files.pythonhosted.org/packages/ce/88/691855eba9ea02df5db731acbdb53122d3cdf4f011414ef4f9e05e655012/python_secrets-18.9.3.tar.gz" } ], "19.10.1": [ { "comment_text": "", "digests": { "md5": "35d76eb2ad026fc68439400494a408f4", "sha256": "1d40d07c0c6494a68917165eb805beff01504a21e256d026b68f0fc4c3be8d0e" }, "downloads": -1, "filename": "python_secrets-19.10.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "35d76eb2ad026fc68439400494a408f4", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 428812, "upload_time": "2019-10-21T05:08:39", "url": "https://files.pythonhosted.org/packages/f3/d8/5368198f085bc191e39f34dc2ee4ce94534dc3782c55bccc1357343957d9/python_secrets-19.10.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c5113896ee2ad2e01fa50a136e2b08c5", "sha256": "a71fc5beb03b08889426a6557e6dbce731c39d6a0202bb398f2da4d9c69990a3" }, "downloads": -1, "filename": "python_secrets-19.10.1-py3.6.egg", "has_sig": false, "md5_digest": "c5113896ee2ad2e01fa50a136e2b08c5", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 486971, "upload_time": "2019-10-21T05:08:46", "url": "https://files.pythonhosted.org/packages/74/32/1941d1fd27a4e7f85a4051eab6c71e8258a299aabed9ac94882f6055440a/python_secrets-19.10.1-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "676fae6fa63513ea78aa5b8c78907955", "sha256": "5d18908c8a353243df4ce230842a2d330aac630c48c6cc25c722dd1b5599de77" }, "downloads": -1, "filename": "python-secrets-19.10.1.tar.gz", "has_sig": false, "md5_digest": "676fae6fa63513ea78aa5b8c78907955", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 416204, "upload_time": "2019-10-21T05:08:43", "url": "https://files.pythonhosted.org/packages/c5/77/09a481739d4e1d50e915ab2f4942c3f2832c786ea57b90a24cb04b2e2343/python-secrets-19.10.1.tar.gz" } ], "19.10.2.dev1": [ { "comment_text": "", "digests": { "md5": "a17fca2c93bf592b22f47edd78bc14b7", "sha256": "5466ae591803bd3beaae7f89e38a98bce056d7f8f9062cbd167b17ff66a0c7df" }, "downloads": -1, "filename": "python_secrets-19.10.2.dev1-py3.6.egg", "has_sig": false, "md5_digest": "a17fca2c93bf592b22f47edd78bc14b7", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 486977, "upload_time": "2019-10-21T05:08:49", "url": "https://files.pythonhosted.org/packages/81/10/b822e5ce2c9ab7c1d65288d0490db2f3d86a21435182d3e0279b20331a96/python_secrets-19.10.2.dev1-py3.6.egg" } ], "19.3.1": [ { "comment_text": "", "digests": { "md5": "e3e00c4941ed8c4e24ce147fb2be93cb", "sha256": "f73d12ac0a141b7fc1f81c4b5daf7d86b93ba935610ed8a013ba20377c3932dc" }, "downloads": -1, "filename": "python_secrets-19.3.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "e3e00c4941ed8c4e24ce147fb2be93cb", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 49648, "upload_time": "2019-03-07T01:33:41", "url": "https://files.pythonhosted.org/packages/81/9f/38452688df5a6a315743817d455e6c030bded16d973d6c3964fb27be239a/python_secrets-19.3.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2f00246a8f18cfdf67934d20bb438a29", "sha256": "1ca48685602ff0187bce0106d9179331bfdb959f20ff9af74c441dd3fc6a16ff" }, "downloads": -1, "filename": "python_secrets-19.3.1-py3.6.egg", "has_sig": false, "md5_digest": "2f00246a8f18cfdf67934d20bb438a29", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 88812, "upload_time": "2019-03-07T01:33:44", "url": "https://files.pythonhosted.org/packages/2c/39/37daaf6d2601156fb35acd07b999a8b0e624bae6fc76b6a927024bf0c244/python_secrets-19.3.1-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "41d963461544edb95a253cbd53e0672e", "sha256": "e19cabf5b40a97730d1ef174e5f969cc5d3233c3f51d9b50d24839b85db1eb4a" }, "downloads": -1, "filename": "python-secrets-19.3.1.tar.gz", "has_sig": false, "md5_digest": "41d963461544edb95a253cbd53e0672e", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 94714, "upload_time": "2019-03-07T01:33:42", "url": "https://files.pythonhosted.org/packages/b9/58/33523e3e58e4cdfb20cf872e6487e610a85ea30f73212c0e884d4a500174/python-secrets-19.3.1.tar.gz" } ], "19.4.4": [ { "comment_text": "", "digests": { "md5": "971353a423b100721576e47865560343", "sha256": "78249c56ad432299ff366e4a2c20d2648cec72fd616e58fc3a000388e1b16a29" }, "downloads": -1, "filename": "python_secrets-19.4.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "971353a423b100721576e47865560343", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 54168, "upload_time": "2019-04-22T02:00:56", "url": "https://files.pythonhosted.org/packages/b9/7f/2da1c5c7d5e36f5a88152feac6fc480da667cb7beaefb90a54fb097d9cf4/python_secrets-19.4.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8ddca456fb873493be06c04e741e6628", "sha256": "2bd2da063c3566043f2dfd857dd06dc63604313c419b8ce4124c73da01bed03e" }, "downloads": -1, "filename": "python_secrets-19.4.4-py3.6.egg", "has_sig": false, "md5_digest": "8ddca456fb873493be06c04e741e6628", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 95355, "upload_time": "2019-04-22T02:00:58", "url": "https://files.pythonhosted.org/packages/e7/cf/032d169f155944b1c8fbae82330f9e1cb06518bf4088355b617a683525c0/python_secrets-19.4.4-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "810769717395fae76d49332d805a086d", "sha256": "2a0855d91bdc0cc618de5088bfdd17658f8194998ff996e7b5aafa243aa79a10" }, "downloads": -1, "filename": "python-secrets-19.4.4.tar.gz", "has_sig": false, "md5_digest": "810769717395fae76d49332d805a086d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 97091, "upload_time": "2019-04-22T02:00:59", "url": "https://files.pythonhosted.org/packages/4f/78/9912d61696774ccb95f09dbeb5de1ff79bd8853c5ca4aa647ecdfeb334b1/python-secrets-19.4.4.tar.gz" } ], "19.5.1": [ { "comment_text": "", "digests": { "md5": "7e36de38f4295ea5f80c2fb033de94d8", "sha256": "1ec6a805159c26ea40f2eaa9563fe2bae51839ea3c4f0eaac2917abbe9ac5f1c" }, "downloads": -1, "filename": "python_secrets-19.5.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "7e36de38f4295ea5f80c2fb033de94d8", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 59545, "upload_time": "2019-05-09T06:23:53", "url": "https://files.pythonhosted.org/packages/d4/5a/404e116e37969e8d2952a253897fc1b58b0a2d4d0daeb824e4b8d908dcdb/python_secrets-19.5.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "811ee582fbc721f2ca6d2041f98d6834", "sha256": "6fe817b48c4444e08a244c7dc0d058d177d448c25499e30d8e3bd1d9372e3869" }, "downloads": -1, "filename": "python_secrets-19.5.1-py3.6.egg", "has_sig": false, "md5_digest": "811ee582fbc721f2ca6d2041f98d6834", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 111164, "upload_time": "2019-05-09T06:23:57", "url": "https://files.pythonhosted.org/packages/98/4c/702446bfa221d527855d4d10959bc115918758ad7abcbde7fdcdc6e93b83/python_secrets-19.5.1-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "90e7f5bd7ef2087541ceb02e6d5644b0", "sha256": "29f83c447013d052abdd5a59771c0735a2fc452d4356b38f20255435ed323c87" }, "downloads": -1, "filename": "python-secrets-19.5.1.tar.gz", "has_sig": false, "md5_digest": "90e7f5bd7ef2087541ceb02e6d5644b0", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 105659, "upload_time": "2019-05-09T06:23:55", "url": "https://files.pythonhosted.org/packages/88/b1/7b50c19a09e604c33c783606a22306942b85564e721c9694418b6e0b0c03/python-secrets-19.5.1.tar.gz" } ], "19.8.1": [ { "comment_text": "", "digests": { "md5": "1fae57faaeae9dfcd398f0edd8a0447e", "sha256": "01d9d70b80e4e36a102c236d59715fbb89c5a6eb800fb83a1ce840cd379120d2" }, "downloads": -1, "filename": "python_secrets-19.8.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "1fae57faaeae9dfcd398f0edd8a0447e", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 62862, "upload_time": "2019-08-22T21:43:23", "url": "https://files.pythonhosted.org/packages/6d/70/f868f2ac71f33cc055c106de4a29293d189044df3180bead9632c24cf966/python_secrets-19.8.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "971e8287927690ab0948b6a5eb579662", "sha256": "3a0dd205ddef28271d06ebea1d3fcc2d04ed06ffe47ab498c757d9f94e159515" }, "downloads": -1, "filename": "python_secrets-19.8.1-py3.6.egg", "has_sig": false, "md5_digest": "971e8287927690ab0948b6a5eb579662", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 118363, "upload_time": "2019-08-22T21:43:27", "url": "https://files.pythonhosted.org/packages/51/1a/cbb5dfc80856d791f1818601209f78d3c6e20e2a00a7c830b0b3c0662cea/python_secrets-19.8.1-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "4d5d6b0e56097a0cbf7191198f37c7da", "sha256": "583acb52cd8c2eaa13adb308c1b8a95d0e2f43f0f788a9d8f8828862cf891316" }, "downloads": -1, "filename": "python-secrets-19.8.1.tar.gz", "has_sig": false, "md5_digest": "4d5d6b0e56097a0cbf7191198f37c7da", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 109131, "upload_time": "2019-08-22T21:43:25", "url": "https://files.pythonhosted.org/packages/92/69/987190e6e6a7fa1467038b469f7d9d152ba36650be13ed3d348bd155eded/python-secrets-19.8.1.tar.gz" } ], "19.8.2": [ { "comment_text": "", "digests": { "md5": "f64ce5965647ab090bb175f3d05d4797", "sha256": "2759f2ee035f1909b8e0c6c7fc1118606bc6ae61802f844b1b18d1fb0e33ad7c" }, "downloads": -1, "filename": "python_secrets-19.8.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f64ce5965647ab090bb175f3d05d4797", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 63101, "upload_time": "2019-08-23T23:20:19", "url": "https://files.pythonhosted.org/packages/59/f5/e597e877cf37c60f887bec6e106865dc6173b4992ef5980b80c15590ba72/python_secrets-19.8.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "352e93696449a4d812341dc6f222969b", "sha256": "59bbabb445a1ac24a1542cbb0e6861d18ca48b8b22c56c81a1b6db2f8fa48176" }, "downloads": -1, "filename": "python_secrets-19.8.2-py3.6.egg", "has_sig": false, "md5_digest": "352e93696449a4d812341dc6f222969b", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 118718, "upload_time": "2019-08-23T23:20:23", "url": "https://files.pythonhosted.org/packages/b2/19/40c1f1b6cddf59780050f7ca815fe0342bb836ab3cd633be92f0d39ecfc7/python_secrets-19.8.2-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "e23dabdf6fefddb585c5a20bb9aee27d", "sha256": "3ac5cd800ceb0c414f60ef4ff00cbdf04f94c76dab667eb9f494732bf5310599" }, "downloads": -1, "filename": "python-secrets-19.8.2.tar.gz", "has_sig": false, "md5_digest": "e23dabdf6fefddb585c5a20bb9aee27d", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 109403, "upload_time": "2019-08-23T23:20:21", "url": "https://files.pythonhosted.org/packages/74/f8/243459f81ee581a6352af850911ae0d47133cd989ca554c2c7d2adce6884/python-secrets-19.8.2.tar.gz" } ], "19.8.3": [ { "comment_text": "", "digests": { "md5": "edfa07c3152daece6224fadf359faa83", "sha256": "aec56d5ce82ca5484a70ddd5f13c6ded2f28546c087d1957d81eb9d1b069cb7b" }, "downloads": -1, "filename": "python_secrets-19.8.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "edfa07c3152daece6224fadf359faa83", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 417980, "upload_time": "2019-08-29T05:30:11", "url": "https://files.pythonhosted.org/packages/6f/40/8bd2a388a916cdc302e64c24bfc7dbe83e3ca282feac49c1ff2b48ad89c6/python_secrets-19.8.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "50cfbf64ee0c766c38ce2a554f38e066", "sha256": "096d23b54fd9a57c31efa4d97a6b1b9ac58f8f73bab2e12a9acb6785472e5d73" }, "downloads": -1, "filename": "python_secrets-19.8.3-py3.6.egg", "has_sig": false, "md5_digest": "50cfbf64ee0c766c38ce2a554f38e066", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 465187, "upload_time": "2019-08-29T05:30:17", "url": "https://files.pythonhosted.org/packages/cc/3a/fc99772d043ccd66d7fb4d3a884e2df22e67ad108ce5ded9be81d588bbc5/python_secrets-19.8.3-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "04cead95b03fd10837f4405876ea6ff7", "sha256": "ac405f2feb266b77b8b1dd6d45fde79905f497f547de39bda0c9fbf43bdaa82f" }, "downloads": -1, "filename": "python-secrets-19.8.3.tar.gz", "has_sig": false, "md5_digest": "04cead95b03fd10837f4405876ea6ff7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 403218, "upload_time": "2019-08-29T05:30:14", "url": "https://files.pythonhosted.org/packages/92/4c/74b29bc2eef5bfad66061dcbd4407640ea532e30591e21c631f05f98ce0f/python-secrets-19.8.3.tar.gz" } ], "19.9.0": [ { "comment_text": "", "digests": { "md5": "17b3b811dbb1c9782c5caccdc43ab9cc", "sha256": "15d6f061a163272a183d67479edcd83198d814b2e4039345e4335da78fb42359" }, "downloads": -1, "filename": "python_secrets-19.9.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "17b3b811dbb1c9782c5caccdc43ab9cc", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 418985, "upload_time": "2019-09-06T04:37:43", "url": "https://files.pythonhosted.org/packages/e9/f8/774ad9ca21de774258ae743a578d24cbede2e5f8640fc46c6a7edccf8852/python_secrets-19.9.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a09474535c59138132125bfd472066f5", "sha256": "1a6df29b386e922ef4ca0d631ab401f964b6308245d58b85d7b0e56210708cf9" }, "downloads": -1, "filename": "python_secrets-19.9.0-py3.6.egg", "has_sig": false, "md5_digest": "a09474535c59138132125bfd472066f5", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 467450, "upload_time": "2019-09-06T04:37:49", "url": "https://files.pythonhosted.org/packages/45/2b/0485d2e10a8f3844b1ddba41e92aea8b45f1c4eeb1d4a0e68710409c4b91/python_secrets-19.9.0-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "b92fa67f23ed572ad6fbc4b4dfecbcc9", "sha256": "6343e4a60f95a6739e6c6a3b91ea2c3f7288a2c905760b382ed78e04c7e6104d" }, "downloads": -1, "filename": "python-secrets-19.9.0.tar.gz", "has_sig": false, "md5_digest": "b92fa67f23ed572ad6fbc4b4dfecbcc9", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 404225, "upload_time": "2019-09-06T04:37:46", "url": "https://files.pythonhosted.org/packages/b0/4c/df79509a7bbe51627b7c9c5a1c673986cafb2dcf8bad1e19b439e800ffce/python-secrets-19.9.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "35d76eb2ad026fc68439400494a408f4", "sha256": "1d40d07c0c6494a68917165eb805beff01504a21e256d026b68f0fc4c3be8d0e" }, "downloads": -1, "filename": "python_secrets-19.10.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "35d76eb2ad026fc68439400494a408f4", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 428812, "upload_time": "2019-10-21T05:08:39", "url": "https://files.pythonhosted.org/packages/f3/d8/5368198f085bc191e39f34dc2ee4ce94534dc3782c55bccc1357343957d9/python_secrets-19.10.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c5113896ee2ad2e01fa50a136e2b08c5", "sha256": "a71fc5beb03b08889426a6557e6dbce731c39d6a0202bb398f2da4d9c69990a3" }, "downloads": -1, "filename": "python_secrets-19.10.1-py3.6.egg", "has_sig": false, "md5_digest": "c5113896ee2ad2e01fa50a136e2b08c5", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": ">=3.6", "size": 486971, "upload_time": "2019-10-21T05:08:46", "url": "https://files.pythonhosted.org/packages/74/32/1941d1fd27a4e7f85a4051eab6c71e8258a299aabed9ac94882f6055440a/python_secrets-19.10.1-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "676fae6fa63513ea78aa5b8c78907955", "sha256": "5d18908c8a353243df4ce230842a2d330aac630c48c6cc25c722dd1b5599de77" }, "downloads": -1, "filename": "python-secrets-19.10.1.tar.gz", "has_sig": false, "md5_digest": "676fae6fa63513ea78aa5b8c78907955", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 416204, "upload_time": "2019-10-21T05:08:43", "url": "https://files.pythonhosted.org/packages/c5/77/09a481739d4e1d50e915ab2f4942c3f2832c786ea57b90a24cb04b2e2343/python-secrets-19.10.1.tar.gz" } ] }