Merge "add developer documentation about the key manager"
This commit is contained in:
commit
9725ef3710
@ -181,3 +181,60 @@ keystone ``Session`` and auth plugin objects(for example, ``Token`` or
|
||||
methodology, where available. For more information on using sessions with
|
||||
keystone, please see
|
||||
http://docs.openstack.org/developer/python-keystoneclient/using-sessions.html
|
||||
|
||||
Storing sensitive information
|
||||
-----------------------------
|
||||
|
||||
During the course of development, there is often cause to store sensitive
|
||||
information (for example, login credentials) in the records for a cluster,
|
||||
job, or some other record. Storing secret information this way is **not**
|
||||
safe. To mitigate the risk of storing this information, sahara provides
|
||||
access to the OpenStack Key Manager service (implemented by the
|
||||
`barbican project <http://docs.openstack.org/developer/barbican/>`_) through
|
||||
the `castellan library <http://docs.openstack.org/developer/castellan/>`_.
|
||||
|
||||
To utilize the external key manager, the functions in
|
||||
``sahara.service.castellan.utils`` are provided as wrappers around the
|
||||
castellan library. These functions allow a developer to store, retrieve, and
|
||||
delete secrets from the manager. Secrets that are managed through the key
|
||||
manager have an identifier associated with them. These identifiers are
|
||||
considered safe to store in the database.
|
||||
|
||||
The following are some examples of working with secrets in the sahara
|
||||
codebase. These examples are considered basic, any developer wishing to
|
||||
learn more about the advanced features of storing secrets should look to
|
||||
the code and docstrings contained in the ``sahara.service.castellan`` module.
|
||||
|
||||
**Storing a secret**
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
from sahara.service.castellan import utils as key_manager
|
||||
|
||||
password = 'SooperSecretPassword'
|
||||
identifier = key_manager.store_secret(password)
|
||||
|
||||
**Retrieving a secret**
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
from sahara.service.castellan import utils as key_manager
|
||||
|
||||
password = key_manager.get_secret(identifier)
|
||||
|
||||
**Deleting a secret**
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
from sahara.service.castellan import utils as key_manager
|
||||
|
||||
key_manager.delete_secret(identifier)
|
||||
|
||||
When storing secrets through this interface it is important to remember that
|
||||
if an external key manager is being used, each stored secret creates an
|
||||
entry in an external service. When you are finished using the secret it is
|
||||
good practice to delete it, as not doing so may leave artifacts in those
|
||||
external services.
|
||||
|
||||
For more information on configuring sahara to use the OpenStack Key
|
||||
Manager service, see :ref:`external_key_manager_usage`.
|
||||
|
@ -193,6 +193,8 @@ These options will also be present in the generated sample configuration
|
||||
file. For instructions on creating the configuration file please see the
|
||||
:doc:`configuration.guide`.
|
||||
|
||||
.. _external_key_manager_usage:
|
||||
|
||||
External key manager usage
|
||||
--------------------------
|
||||
|
||||
|
@ -17,53 +17,60 @@ from castellan.common.objects import passphrase as key
|
||||
from castellan.key_manager import key_manager as km
|
||||
|
||||
|
||||
"""sahara.service.castellan.sahara_key_manager
|
||||
|
||||
This module contains the KeyManager class that will be used by the
|
||||
castellan library, it is not meant for direct usage within sahara.
|
||||
"""
|
||||
|
||||
|
||||
class SaharaKeyManager(km.KeyManager):
|
||||
'''Sahara specific key manager
|
||||
"""Sahara specific key manager
|
||||
|
||||
This manager is a thin wrapper around the secret being stored. It is
|
||||
intended for backward compatible use only. It will not store keys
|
||||
or generate UUIDs but instead return the secret that is being stored.
|
||||
This behavior allows Sahara to continue storing secrets in its database
|
||||
while using the Castellan key manager abstraction.
|
||||
'''
|
||||
"""
|
||||
def __init__(self, configuration=None):
|
||||
pass
|
||||
|
||||
def create_key(self, context, algorithm=None, length=0,
|
||||
expiration=None, **kwargs):
|
||||
'''creates a key
|
||||
"""creates a key
|
||||
|
||||
algorithm, length, and expiration are unused by sahara keys.
|
||||
'''
|
||||
"""
|
||||
return key.Passphrase(passphrase=kwargs.get('passphrase', ''))
|
||||
|
||||
def create_key_pair(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def store(self, context, key, expiration=None, **kwargs):
|
||||
'''store a key
|
||||
"""store a key
|
||||
|
||||
in normal usage a store_key will return the UUID of the key as
|
||||
dictated by the key manager. Sahara would then store this UUID in
|
||||
its database to use for retrieval. As sahara is not actually using
|
||||
a key manager in this context it will return the key's payload for
|
||||
storage.
|
||||
'''
|
||||
"""
|
||||
return key.get_encoded()
|
||||
|
||||
def get(self, context, key_id, **kwargs):
|
||||
'''get a key
|
||||
"""get a key
|
||||
|
||||
since sahara is not actually storing key UUIDs the key_id to this
|
||||
function should actually be the key payload. this function will
|
||||
simply return a new SaharaKey based on that value.
|
||||
'''
|
||||
"""
|
||||
return key.Passphrase(passphrase=key_id)
|
||||
|
||||
def delete(self, context, key_id, **kwargs):
|
||||
'''delete a key
|
||||
"""delete a key
|
||||
|
||||
as there is no external key manager, this function will not
|
||||
perform any external actions. therefore, it won't change anything.
|
||||
'''
|
||||
"""
|
||||
pass
|
||||
|
@ -20,22 +20,24 @@ from sahara import context
|
||||
|
||||
|
||||
def delete_secret(id, ctx=None):
|
||||
'''delete a secret from the external key manager
|
||||
"""delete a secret from the external key manager
|
||||
|
||||
if no context is provided, the current context is used.
|
||||
|
||||
'''
|
||||
:param id: The identifier of the secret to delete
|
||||
:param ctx: The context, and associated authentication, to use with
|
||||
this operation (defaults to the current context)
|
||||
"""
|
||||
if ctx is None:
|
||||
ctx = context.current()
|
||||
key_manager.API().delete(ctx, id)
|
||||
|
||||
|
||||
def get_secret(id, ctx=None):
|
||||
'''get a secret associated with an id
|
||||
"""get a secret associated with an id
|
||||
|
||||
if no context is provided, the current context is used.
|
||||
|
||||
'''
|
||||
:param id: The identifier of the secret to retrieve
|
||||
:param ctx: The context, and associated authentication, to use with
|
||||
this operation (defaults to the current context)
|
||||
"""
|
||||
if ctx is None:
|
||||
ctx = context.current()
|
||||
key = key_manager.API().get(ctx, id)
|
||||
@ -43,11 +45,12 @@ def get_secret(id, ctx=None):
|
||||
|
||||
|
||||
def store_secret(secret, ctx=None):
|
||||
'''store a secret and return its identifier
|
||||
"""store a secret and return its identifier
|
||||
|
||||
if no context is provided, the current context is used.
|
||||
|
||||
'''
|
||||
:param secret: The secret to store, this should be a string
|
||||
:param ctx: The context, and associated authentication, to use with
|
||||
this operation (defaults to the current context)
|
||||
"""
|
||||
if ctx is None:
|
||||
ctx = context.current()
|
||||
key = passphrase.Passphrase(secret)
|
||||
|
Loading…
Reference in New Issue
Block a user