Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


install:
pip install -e .[docs,test]
pip install -e .[docs,test,azure]

test:
py.test
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
# |version| and |release|, also used in various other places throughout the
# built documents.
#
version = '0.2.1'
version = '0.2.2'
release = version

# The language for content autogenerated by Sphinx. Refer to documentation
Expand Down Expand Up @@ -139,7 +139,7 @@
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#
# html_title = u'python-param-store v0.2.1'
# html_title = u'python-param-store v0.2.2'

# A shorter title for the navigation bar. Default is the same as html_title.
#
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.2.1
current_version = 0.2.2
commit = true
tag = true
tag_name = {new_version}
Expand Down
7 changes: 6 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
'six>=1.1',
]

azure_require = [
'azure-keyvault',
]

docs_require = [
'sphinx>=1.4.0',
]
Expand All @@ -32,7 +36,7 @@

setup(
name='param-store',
version='0.2.1',
version='0.2.2',
description="Parameter store for secrets",
long_description=long_description,
url='https://github.com/labd/python-param-store',
Expand All @@ -41,6 +45,7 @@
install_requires=install_requires,
tests_require=tests_require,
extras_require={
'azure': azure_require,
'docs': docs_require,
'test': tests_require,
},
Expand Down
2 changes: 1 addition & 1 deletion src/param_store/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

__all__ = ['Env', 'EC2ParameterStore']

__version__ = '0.2.1'
__version__ = '0.2.2'
72 changes: 71 additions & 1 deletion src/param_store/stores.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from itertools import islice

__all__ = [
'EC2ParameterStore'
'EC2ParameterStore',
'AzureVaultParameterStore',
]


Expand Down Expand Up @@ -44,3 +45,72 @@ def chunk(it, size):
value = parameter['Value']
result[key] = value
return result


class AzureVaultConfigurationException(Exception):
pass


class AzureVaultParameterStore(BaseStore):

def __init__(self):
from azure.keyvault import KeyVaultClient, KeyVaultAuthentication
from os import getenv

self.vault_id = getenv("AZURE_VAULT_ID", None)
self.tenant_id = getenv("AZURE_TENANT_ID", None)

self.app_id = getenv("AZURE_APP_ID", None)
self.client_id = getenv("AZURE_CLIENT_ID", None)
self.secret = getenv("AZURE_SECRET", None)

if self.app_id:
import adal

# create an adal authentication context
auth_context = adal.AuthenticationContext(
'https://login.microsoftonline.com/%s' % self.tenant_id)

def auth_callback(server, resource, scope):
user_code_info = auth_context.acquire_user_code(resource, self.app_id)

token = auth_context.acquire_token_with_device_code(resource=resource,
client_id=self.app_id,
user_code_info=user_code_info)
return token['token_type'], token['access_token']
elif self.client_id and self.secret:
from azure.common.credentials import ServicePrincipalCredentials

def auth_callback(server, resource, scope):
credentials = ServicePrincipalCredentials(
client_id=self.client_id,
secret=self.secret,
tenant=self.tenant_id,
resource="https://vault.azure.net"
)
token = credentials.token
return token['token_type'], token['access_token']
else:
raise AzureVaultConfigurationException("Either set AZURE_APP_ID or "
"(AZURE_CLIENT_ID and AZURE_SECRET)")

self.client = KeyVaultClient(KeyVaultAuthentication(auth_callback))

def load_values(self, items):
from azure.keyvault.models import KeyVaultErrorException
from azure.keyvault import KeyVaultId

if not items or not self.vault_id:
return {}

result = {}
for key in items:
try:
data = self.client.get_secret("https://%s.vault.azure.net/" % self.vault_id,
key, KeyVaultId.version_none)
except KeyVaultErrorException:
continue

result[key] = data.value

return result