Metadata-Version: 2.4
Name: bdrc-db-lib2
Version: 2.0.1
Summary: Simpler BDRC Db Library and Models
Home-page: 
Author: jimk
Author-email: jimk <jimk@tbrc.org>
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 5 - Production/Stable
Requires-Python: >=3.9
Description-Content-Type: text/x-rst
Requires-Dist: pymysql
Requires-Dist: lxml
Requires-Dist: sqlalchemy~=2.0.0
Requires-Dist: mysqlclient
Requires-Dist: pytest>=8.4.2
Requires-Dist: esbonio>=0.16.5
Requires-Dist: doc8>=1.1.2
Requires-Dist: rstcheck>=6.2.5
Requires-Dist: sphinx>=7.4.7
Requires-Dist: docutils>=0.21.2
Requires-Dist: sphinx-rtd-theme>=3.1.0
Dynamic: author
Dynamic: requires-python

============
bdrc-db-lib2
============

Rewrite of package which uses a direct config file for the database
connection.

Developer notes
---------------

The most significant change is that users no longer need to
specify a section of a config file
to locate a database connection.
The former form,
``-d | --drsConfig prod:~someone/somewhere/somefile``
is no longer needed.
Clients now siimply specify a section name:
``-d | --drsConfig prod``, for example.

The name of the section is free-form.

Critical information is now given in to environment variables:

``BDRC_DB_CONFIG``
   The path to the database configuration file
   can be given using ``~`` notation to designate a user.

   .. important:: The configuration file will no longer contain the password field, or the password.

``BDRC_DB_PASSWORD``
    this is the password to the database named
    in the section given in the ``drsConfig`` parameter.

    .. note:: The implementation accepts per-configuration enviornment variables. For example, if you want
      to use a ``-d prodtest`` configuration, you can specify an environment variable named ``BDRC_PRODTEST_PASSWORD``

Development
===========

``pyproject.toml``

.. code:: shell

   python -m build --wheel bdist_wheel


Deployment
==========

.. code:: shell

   twine upload --verbose  -r testpypi dist/bdrc_db_lib-x.MM.mm-py3-none-any.whl

Installation
------------

`pyPI.org bdrc-db-lib2 <https://pypi.org/project/bdrc-db-lib/>`__

Implementation
==============

The architecture lends itself to a Docker Secrets + KMS Decryption Scheme.
The interested user can refer to
`Buda-base/ao-workflows <https://github.com/Buda-base/ao-workflows/>`__


Steps (Thanks to Perplexity)

#. Encrypt password (One-Time, secure workstation)

.. code-block:: bash

   # AWS KMS example (use AWS CLI)
   aws kms encrypt \
   --key-id arn:aws:kms:us-east-1:123456789012:key/1234abcd-12ab-34cd \
   --plaintext "mypassword123" \
   --output text \
   --query CiphertextBlob | base64 > encrypted_db_pass.b64

2. Docker Secret (Encrypted Blob)

   Add the encrypted blob into the docker image. "But wait," I hear
   you say, won't a hacker have access to the encrypted image?"
   "Yes, but only until the Docker container is started. The encrypted blob is removed at Docker startup. (See Step 3)

.. code-block:: yaml

   # docker-compose.yml
   version: '3.8'
   services:
   app:
      image: myapp:latest
      secrets:
         - db_password
      environment:
         DB_PASSWORD_FILE: /run/secrets/db_password

   secrets:
   db_password:
      file: ./encrypted_db_pass.b64
      external: false  # Don't commit


1. Decrypt at Runtime (Entry script)

   This decrypts the password blob at runtime, and then removes the
   blob from the container's file system
   The only hacker access would be if they could inspect the running container (or has injected code into some
   open source library that grants access to the Docker inspector)

.. code:: python3

   #!/usr/bin/env python3
   import boto3
   import base64
   import os
   import sys

   kms = boto3.client('kms')
   encrypted_pass = base64.b64decode(open('/run/secrets/db_password').read())
   decrypted_pass = kms.decrypt(CiphertextBlob=encrypted_pass)['Plaintext'].decode()

   os.environ['DB_PASSWORD'] = decrypted_pass
   os.unlink('/run/secrets/db_password')  # Wipe secret file

   # Start app
   exec(sys.argv[1])


Changelog
=========

+---------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------------+
| version |                                                                                                         | Comments                                                         |
+=========+=========================================================================================================+==================================================================+
+---------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------------+
| 1.0.10  |                                                                                                         | Initial                                                          |
+---------+---------------------------------------------------------------------------------------------------------+------------------------------------------------------------------+
