secrets_manager
========

This library is for use with secrets manager implementations at The Orchard.
Currently there is a flask extension in this library.

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

```bash
pip install -i https://pypi.theorchard.io/pypi/ secrets_manager
```

Usage
-----

#### Flask Extension

##### Secret retrieval format

Here is how a secret is built when retrieved from AWS secrets managers.

```python
# we look for ENVIRONMENT and SERVICE_NAME to be attached to 
# app.config before init_app is called.
secret_name = '{environment}/{service_name}/{secret_name}'.format(
                environment=app.config['ENVIRONMENT'],
                service_name=app.config['SERVICE_NAME'],
                secret_name=key)
```

##### Class Kwargs
* environment (str) (required)
  * test/dev/qa/prod
* service_name (str) (required)
  * the name of your secrets "namespace" IE.. your application
* force_remote (bool)
  * Ignores local dev/test env var lookup and always goes to secrets manager
* aws_region (str)
  * defaults to us-east-1 but you can set to a valid AWS region
* local_to_remote_name (dict)
  * this will map local env vars to remote secret names for dev/test locally

##### Example Implementation

*secrets.py*
```python
from secrets_manager.flask_ext import FlaskSecretsManager

secrets_manager_client = FlaskSecretsManager()
```

*app.py*
```python
from flask import Flask

from secrets import secrets_manager_client

app = Flask('app-name')

# optional, we default to this
app.config['AWS_REGION'] = 'us-east-1'

# required 
app.config['ENVIRONMENT'] = 'dev'

# required 
app.config['SERVICE_NAME'] = 'app-name'

# optional, if you wish to translate local env vars to remote names.
VAR_TO_SECRET_NAME = {
    'VIDEO_DB_NAME': 'ows_video_username',
    'VIDEO_DB_PASSWORD': 'ows_video_password',
    'AR_DB_NAME': 'ar_db_username',
    'AR_DB_PASSWORD': 'ar_db_password'
}

# this is where we initialize the flask extension.
# the kwarg is optional but if present it must be that key name.
secrets_manager_client.init_app(
    app,
    local_to_remote_name=VAR_TO_SECRET_NAME
)

print(secrets_manager_client.get_cred('ENV_VAR_NAME'))
```

This is implemented with bare minimum. 
TODO: We can improve on this.. maybe accept kwargs and pass to boto command?
```python
from secrets import secrets_manager_client

secrets_manager_client.store_cred(key='company', secret='theorchard')
```


##### Example Implementation 2
Using this extension without an application context. This is used for 
situations where you don't want to call AWS constantly.

*secrets.py*
```python
from secrets_manager.flask_ext import FlaskSecretsManager

# defaults to dev.. if you set to anything other then dev/test it will call AWS
# if calling AWS make sure ENV has access to make boto connection.
secrets_manager_client = FlaskSecretsManager(
    application_context=False, environment='prod', service_name='ows_test')
```

*config.py*
```python
from secrets import secrets_manager_client

# env var name or the name of the remote
# this will only get called once in lifecycle of your application.
ENV_VAR = secrets_manager_client.get_cred('ENV_VAR_NAME')

```

*app.py*
```python
from flask import Flask
import config

app = Flask('app-name')
```

#### Python Extension

For use in bare python packages (no Flask) such as pypi, lambdas, and daemons.

##### Example Implementation

*config.py*
```python
from secrets_manager.python_ext import PythonSecretsManager

secrets_manager_client = PythonSecretsManager(
    environment='prod', service_name='ows_test')

# optional, if you wish to translate local env vars to remote names.
VAR_TO_SECRET_NAME = {
    'VIDEO_DB_NAME': 'ows_video_username',
    'VIDEO_DB_PASSWORD': 'ows_video_password',
    'AR_DB_NAME': 'ar_db_username',
    'AR_DB_PASSWORD': 'ar_db_password'
}

# this will update the options dictionary
secrets_manager_client.update_options(
    local_to_remote_name=VAR_TO_SECRET_NAME,
    # environment='test',  # you could change env if you wanted on the fly
    # service_name='something_else',  # or service_name 
)

# env var name or the name of the remote secret name
ENV_VAR = secrets_manager_client.get_cred('ENV_VAR_NAME')
```

#### Lambda Extension

For use in lambdas, it is literally a wrapper for PythonSecretsManager which is preferred for non-Flask python projects.

##### Example Implementation

Identitcal to PythonSecretsManager usage:

```python
from secrets_manager.lambda_ext import LambdaSecretsManager

secrets_manager_client = LambdaSecretsManager(
    environment='prod', service_name='ows_test')

# ... continue like in the python example above
```

#### SWF Extension

##### Example Implementation

*config.py*
```python
from secrets_manager.swf_ext import SWFSecretsManager

secrets_manager_client = SWFSecretsManager(
    environment='prod', service_name='feed_test')

# optional, if you wish to translate local env vars to remote names.
VAR_TO_SECRET_NAME = {
    'VIDEO_DB_NAME': 'ows_video_username',
    'VIDEO_DB_PASSWORD': 'ows_video_password',
    'AR_DB_NAME': 'ar_db_username',
    'AR_DB_PASSWORD': 'ar_db_password'
}

# this will update the options dictionary
secrets_manager_client.update_options(
    local_to_remote_name=VAR_TO_SECRET_NAME,
    # environment='test',  # you could change env if you wanted on the fly
    # service_name='something_else',  # or service_name 
)

# env var name or the name of the remote secret name
ENV_VAR = secrets_manager_client.get_cred('ENV_VAR_NAME')
```
