commit python-castellan for openSUSE:Factory
Hello community, here is the log from the commit of package python-castellan for openSUSE:Factory checked in at 2019-05-03 22:39:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-castellan (Old) and /work/SRC/openSUSE:Factory/.python-castellan.new.5148 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-castellan" Fri May 3 22:39:59 2019 rev:8 rq:692817 version:1.2.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-castellan/python-castellan.changes 2018-10-09 15:53:40.722317479 +0200 +++ /work/SRC/openSUSE:Factory/.python-castellan.new.5148/python-castellan.changes 2019-05-03 22:40:01.654938630 +0200 @@ -1,0 +2,25 @@ +Mon Apr 8 13:56:51 UTC 2019 - cloud-devel@suse.de + +- update to version 1.2.2 + - Bump HashiCorp Vault version for tests. + - Change openstack-dev to openstack-discuss + - fix tox python3 overrides + - Fix Vault K/V API compatibility. + - Add release note link in README + - Switch to stestr + - Add Castellan Oslo Config Driver. + - Fix length usage in VaultKeyManager.create_key. + - vault: add AppRole support + - Update reno for stable/rocky + - Update min tox version to 2.0 + - Don't quote {posargs} in tox.ini + - Use template for lower-constraints + - Add method to wrap HashiCorp Vault HTTP API calls. + - Set py3 tests according to Stein runtimes. + - add python 3.6 unit test job + - vault: support configuration of KV mountpoint + - add python 3.7 unit test job + - import zuul job settings from project-config + - Add code to generate private keys + +------------------------------------------------------------------- Old: ---- castellan-0.19.0.tar.gz New: ---- castellan-1.2.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-castellan.spec ++++++ --- /var/tmp/diff_new_pack.E9P1Bf/_old 2019-05-03 22:40:02.474940334 +0200 +++ /var/tmp/diff_new_pack.E9P1Bf/_new 2019-05-03 22:40:02.474940334 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-castellan # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -12,50 +12,55 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # Name: python-castellan -Version: 0.19.0 +Version: 1.2.2 Release: 0 Summary: Generic Key Manager interface for OpenStack License: Apache-2.0 Group: Development/Languages/Python URL: https://launchpad.net/castellan -Source0: https://files.pythonhosted.org/packages/source/c/castellan/castellan-0.19.0.... +Source0: https://files.pythonhosted.org/packages/source/c/castellan/castellan-1.2.2.t... BuildRequires: openstack-macros BuildRequires: python2-barbicanclient >= 4.5.2 BuildRequires: python2-cryptography >= 2.1 BuildRequires: python2-keystoneauth1 >= 3.4.0 -BuildRequires: python2-oslo.config >= 5.2.0 +BuildRequires: python2-oslo.config >= 6.4.0 BuildRequires: python2-oslo.log >= 3.36.0 BuildRequires: python2-oslotest +BuildRequires: python2-pifpaf BuildRequires: python2-python-subunit +BuildRequires: python2-reno BuildRequires: python2-setuptools -BuildRequires: python2-testrepository +BuildRequires: python2-stestr BuildRequires: python2-testscenarios BuildRequires: python2-testtools BuildRequires: python3-barbicanclient >= 4.5.2 BuildRequires: python3-cryptography >= 2.1 BuildRequires: python3-keystoneauth1 >= 3.4.0 -BuildRequires: python3-oslo.config >= 5.2.0 +BuildRequires: python3-oslo.config >= 6.4.0 BuildRequires: python3-oslo.log >= 3.36.0 BuildRequires: python3-oslotest +BuildRequires: python3-pifpaf BuildRequires: python3-python-subunit +BuildRequires: python3-reno BuildRequires: python3-setuptools -BuildRequires: python3-testrepository +BuildRequires: python3-stestr BuildRequires: python3-testscenarios BuildRequires: python3-testtools Requires: python-Babel >= 2.3.4 +Requires: python-barbicanclient >= 4.5.2 Requires: python-cryptography >= 2.1 Requires: python-keystoneauth1 >= 3.4.0 -Requires: python-oslo.config >= 5.2.0 +Requires: python-oslo.config >= 6.4.0 Requires: python-oslo.context >= 2.19.2 +Requires: python-oslo.i18n >= 3.15.3 Requires: python-oslo.log >= 3.36.0 -Requires: python-oslo.policy -Requires: python-oslo.serialization Requires: python-oslo.utils >= 3.33.0 +Requires: python-stevedore >= 1.20.0 BuildArch: noarch %python_subpackages @@ -73,9 +78,8 @@ This package contains the documentation %prep -%autosetup -p1 -n castellan-0.19.0 +%autosetup -p1 -n castellan-1.2.2 %py_req_cleanup -sed -i 's/^warning-is-error.*/warning-is-error = 0/g' setup.cfg %build %{python_build} @@ -88,11 +92,7 @@ %{python_install} %check -%{python_expand rm -rf .testrepository -# Functional tests require a working Keystone infrastructure -export OS_TEST_PATH=./castellan/tests/unit -$python setup.py test -} +%python_exec -m stestr.cli run %files %{python_files} %license LICENSE ++++++ _service ++++++ --- /var/tmp/diff_new_pack.E9P1Bf/_old 2019-05-03 22:40:02.498940383 +0200 +++ /var/tmp/diff_new_pack.E9P1Bf/_new 2019-05-03 22:40:02.498940383 +0200 @@ -1,8 +1,8 @@ <services> <service mode="disabled" name="renderspec"> - <param name="input-template">https://raw.githubusercontent.com/openstack/rpm-packaging/stable/rocky/openstack/castellan/castellan.spec.j2</param> + <param name="input-template">https://raw.githubusercontent.com/openstack/rpm-packaging/stable/stein/openstack/castellan/castellan.spec.j2</param> <param name="output-name">python-castellan.spec</param> - <param name="requirements">https://raw.githubusercontent.com/openstack/castellan/stable/rocky/requirements.txt</param> + <param name="requirements">https://raw.githubusercontent.com/openstack/castellan/stable/stein/requirements.txt</param> <param name="changelog-email">cloud-devel@suse.de</param> <param name="changelog-provider">gh,openstack,castellan</param> </service> ++++++ castellan-0.19.0.tar.gz -> castellan-1.2.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/.stestr.conf new/castellan-1.2.2/.stestr.conf --- old/castellan-0.19.0/.stestr.conf 1970-01-01 01:00:00.000000000 +0100 +++ new/castellan-1.2.2/.stestr.conf 2019-02-28 19:02:40.000000000 +0100 @@ -0,0 +1,4 @@ +[DEFAULT] +test_path=./castellan/tests +top_dir=./ + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/.testr.conf new/castellan-1.2.2/.testr.conf --- old/castellan-0.19.0/.testr.conf 2018-08-21 22:00:55.000000000 +0200 +++ new/castellan-1.2.2/.testr.conf 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -[DEFAULT] -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ - OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ - OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./castellan/tests} $LISTOPT $IDOPTION -test_id_option=--load-list $IDFILE -test_list_option=--list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/.zuul.yaml new/castellan-1.2.2/.zuul.yaml --- old/castellan-0.19.0/.zuul.yaml 2018-08-21 22:00:55.000000000 +0200 +++ new/castellan-1.2.2/.zuul.yaml 2019-02-28 19:02:40.000000000 +0100 @@ -51,18 +51,18 @@ jobs: - castellan-functional-vault - castellan-functional-devstack - - openstack-tox-lower-constraints - barbican-simple-crypto-devstack-tempest-castellan-from-git gate: jobs: - castellan-functional-vault - castellan-functional-devstack - - openstack-tox-lower-constraints - barbican-simple-crypto-devstack-tempest-castellan-from-git templates: - - openstack-python-jobs - - openstack-python35-jobs - - release-notes-jobs-python3 - - publish-openstack-docs-pti - check-requirements + - openstack-lower-constraints-jobs + - openstack-python-jobs + - openstack-python36-jobs + - openstack-python37-jobs - periodic-stable-jobs + - publish-openstack-docs-pti + - release-notes-jobs-python3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/AUTHORS new/castellan-1.2.2/AUTHORS --- old/castellan-0.19.0/AUTHORS 2018-08-21 22:04:14.000000000 +0200 +++ new/castellan-1.2.2/AUTHORS 2019-02-28 19:06:34.000000000 +0100 @@ -7,6 +7,7 @@ Brianna Poulos <brianna.poulos@jhuapl.edu> Chris Solis <cnsolis@us.ibm.com> Christopher Solis <cnsolis@us.ibm.com> +Corey Bryant <corey.bryant@canonical.com> Dai Dang Van <daidv@vn.fujitsu.com> Davanum Srinivas <davanum@gmail.com> Dave McCowan <dmccowan@cisco.com> @@ -17,6 +18,7 @@ Fernando Diaz <diazjf@us.ibm.com> Flavio Percoco <flaper87@gmail.com> James E. Blair <jeblair@redhat.com> +James Page <james.page@ubuntu.com> Jamie Lennox <jamielennox@gmail.com> Jeremy Liu <liujiong@gohighsec.com> Jeremy Stanley <fungi@yuggoth.org> @@ -27,7 +29,10 @@ Kaitlin Farr <kaitlin.farr@jhuapl.edu> Kiran_totad <kiran.totad@nectechnologies.in> Michael McCune <msm@redhat.com> +Moises Guimaraes de Medeiros <moguimar@redhat.com> +Moisés Guimarães de Medeiros <moguimar@redhat.com> Monty Taylor <mordred@inaugust.com> +Nguyen Van Trung <trungnv@vn.fujitsu.com> Niall Bunting <niall.bunting@hpe.com> OpenStack Release Bot <infra-root@openstack.org> Paul Bourke <paul.bourke@oracle.com> @@ -38,9 +43,9 @@ Tim Kelsey <tim.kelsey@hp.com> Tom Cocozzello <tjcocozz@us.ibm.com> Van Hung Pham <hungpv@vn.fujitsu.com> +Vu Cong Tuan <tuanvc@vn.fujitsu.com> Yushiro FURUKAWA <y.furukawa_2@jp.fujitsu.com> Zhao Lei <zhaolei@cn.fujitsu.com> -Zuul <zuul@review.openstack.org> bhavani.cr <bhavani.r@nectechnologies.in> dane-fichter <dane.fichter@jhuapl.edu> gaofei <gao.fei@inspur.com> @@ -52,6 +57,8 @@ rajat29 <rajat.sharma@nectechnologies.in> sonu.kumar <sonu.kumar@nectechnologies.in> ting.wang <ting.wang@easystack.cn> +wu.chunyang <wu.chunyang@99cloud.net> xhzhf <guoyongxhzhf@163.com> yushangbin <yushb@gohighsec.com> +zhangzs <zhangzhaoshan@inspur.com> “Fernando <diazjf@us.ibm.com> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/ChangeLog new/castellan-1.2.2/ChangeLog --- old/castellan-0.19.0/ChangeLog 2018-08-21 22:04:14.000000000 +0200 +++ new/castellan-1.2.2/ChangeLog 2019-02-28 19:06:34.000000000 +0100 @@ -1,13 +1,49 @@ CHANGES ======= -0.19.0 +1.2.2 +----- + +* Set py3 tests according to Stein runtimes + +1.2.1 +----- + +* Fix length usage in VaultKeyManager.create\_key +* add python 3.7 unit test job + +1.2.0 +----- + +* Change openstack-dev to openstack-discuss + +1.1.0 +----- + +* Add Castellan Oslo Config Driver +* Use template for lower-constraints +* Update min tox version to 2.0 +* vault: support configuration of KV mountpoint +* vault: add AppRole support +* Don't quote {posargs} in tox.ini + +1.0.0 +----- + +* Add method to wrap HashiCorp Vault HTTP API calls + +0.20.1 ------ -* Add code to generate private keys +* Bump HashiCorp Vault version for tests +* Fix Vault K/V API compatibility +* add python 3.6 unit test job * import zuul job settings from project-config -* Update UPPER\_CONSTRAINTS\_FILE for stable/rocky -* Update .gitreview for stable/rocky +* Update reno for stable/rocky +* Switch to stestr +* Add release note link in README +* Add code to generate private keys +* fix tox python3 overrides 0.18.0 ------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/PKG-INFO new/castellan-1.2.2/PKG-INFO --- old/castellan-0.19.0/PKG-INFO 2018-08-21 22:04:15.000000000 +0200 +++ new/castellan-1.2.2/PKG-INFO 2019-02-28 19:06:34.000000000 +0100 @@ -1,10 +1,10 @@ Metadata-Version: 1.1 Name: castellan -Version: 0.19.0 +Version: 1.2.2 Summary: Generic Key Manager interface for OpenStack Home-page: https://docs.openstack.org/castellan/latest/ Author: OpenStack -Author-email: openstack-dev@lists.openstack.org +Author-email: openstack-discuss@lists.openstack.org License: UNKNOWN Description: ========= Castellan @@ -16,6 +16,7 @@ * Documentation: https://docs.openstack.org/castellan/latest * Source: https://git.openstack.org/cgit/openstack/castellan * Bugs: https://bugs.launchpad.net/castellan + * Release notes: https://docs.openstack.org/releasenotes/castellan Team and repository tags ======================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/README.rst new/castellan-1.2.2/README.rst --- old/castellan-0.19.0/README.rst 2018-08-21 22:00:55.000000000 +0200 +++ new/castellan-1.2.2/README.rst 2019-02-28 19:02:40.000000000 +0100 @@ -8,6 +8,7 @@ * Documentation: https://docs.openstack.org/castellan/latest * Source: https://git.openstack.org/cgit/openstack/castellan * Bugs: https://bugs.launchpad.net/castellan +* Release notes: https://docs.openstack.org/releasenotes/castellan Team and repository tags ======================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/RELEASENOTES.rst new/castellan-1.2.2/RELEASENOTES.rst --- old/castellan-0.19.0/RELEASENOTES.rst 2018-08-21 22:04:15.000000000 +0200 +++ new/castellan-1.2.2/RELEASENOTES.rst 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -========= -castellan -========= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan/_config_driver.py new/castellan-1.2.2/castellan/_config_driver.py --- old/castellan-0.19.0/castellan/_config_driver.py 1970-01-01 01:00:00.000000000 +0100 +++ new/castellan-1.2.2/castellan/_config_driver.py 2019-02-28 19:02:40.000000000 +0100 @@ -0,0 +1,141 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +r""" +Castellan Oslo Config Driver +---------------------------- + +This driver is an oslo.config backend driver implemented with Castellan. It +extends oslo.config's capabilities by enabling it to retrieve configuration +values from a secret manager behind Castellan. + +The setup of a Castellan configuration source is as follow:: + + [DEFAULT] + config_source = castellan_config_group + + [castellan_config_group] + driver = castellan + config_file = castellan.conf + mapping_file = mapping.conf + +In the following sessions, you can find more information about this driver's +classes and its options. + +The Driver Class +================ + +.. autoclass:: CastellanConfigurationSourceDriver + +The Configuration Source Class +============================== + +.. autoclass:: CastellanConfigurationSource + +""" +from castellan.common.exception import KeyManagerError +from castellan.common.exception import ManagedObjectNotFoundError +from castellan import key_manager + +from oslo_config import cfg +from oslo_config import sources +from oslo_log import log + +LOG = log.getLogger(__name__) + + +class CastellanConfigurationSourceDriver(sources.ConfigurationSourceDriver): + """A backend driver for configuration values served through castellan. + + Required options: + - config_file: The castellan configuration file. + + - mapping_file: A configuration/castellan_id mapping file. This file + creates connections between configuration options and + castellan ids. The group and option name remains the + same, while the value gets stored a secret manager behind + castellan and is replaced by its castellan id. The ids + will be used to fetch the values through castellan. + """ + + _castellan_driver_opts = [ + cfg.StrOpt( + 'config_file', + required=True, + sample_default='etc/castellan/castellan.conf', + help=('The path to a castellan configuration file.'), + ), + cfg.StrOpt( + 'mapping_file', + required=True, + sample_default='etc/castellan/secrets_mapping.conf', + help=('The path to a configuration/castellan_id mapping file.'), + ), + ] + + def list_options_for_discovery(self): + return self._castellan_driver_opts + + def open_source_from_opt_group(self, conf, group_name): + conf.register_opts(self._castellan_driver_opts, group_name) + + return CastellanConfigurationSource( + group_name, + conf[group_name].config_file, + conf[group_name].mapping_file) + + +class CastellanConfigurationSource(sources.ConfigurationSource): + """A configuration source for configuration values served through castellan. + + :param config_file: The path to a castellan configuration file. + + :param mapping_file: The path to a configuration/castellan_id mapping file. + """ + + def __init__(self, group_name, config_file, mapping_file): + conf = cfg.ConfigOpts() + conf(args=[], default_config_files=[config_file]) + + self._name = group_name + self._mngr = key_manager.API(conf) + self._mapping = {} + + cfg.ConfigParser(mapping_file, self._mapping).parse() + + def get(self, group_name, option_name, opt): + try: + group_name = group_name or "DEFAULT" + + castellan_id = self._mapping[group_name][option_name][0] + + return (self._mngr.get("ctx", castellan_id).get_encoded().decode(), + cfg.LocationInfo(cfg.Locations.user, castellan_id)) + + except KeyError: + # no mapping 'option = castellan_id' + LOG.info("option '[%s] %s' not present in '[%s] mapping_file'", + group_name, option_name, self._name) + + except KeyManagerError: + # bad mapping 'option =' without a castellan_id + LOG.warning("missing castellan_id for option " + "'[%s] %s' in '[%s] mapping_file'", + group_name, option_name, self._name) + + except ManagedObjectNotFoundError: + # good mapping, but unknown castellan_id by secret manager + LOG.warning("invalid castellan_id for option " + "'[%s] %s' in '[%s] mapping_file'", + group_name, option_name, self._name) + + return (sources._NoValue, None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan/key_manager/vault_key_manager.py new/castellan-1.2.2/castellan/key_manager/vault_key_manager.py --- old/castellan-0.19.0/castellan/key_manager/vault_key_manager.py 2018-08-21 22:00:30.000000000 +0200 +++ new/castellan-1.2.2/castellan/key_manager/vault_key_manager.py 2019-02-28 19:02:40.000000000 +0100 @@ -29,6 +29,7 @@ from keystoneauth1 import loading from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import timeutils import requests import six @@ -43,10 +44,19 @@ from castellan.key_manager import key_manager DEFAULT_VAULT_URL = "http://127.0.0.1:8200" +DEFAULT_MOUNTPOINT = "secret" vault_opts = [ cfg.StrOpt('root_token_id', help='root token for vault'), + cfg.StrOpt('approle_role_id', + help='AppRole role_id for authentication with vault'), + cfg.StrOpt('approle_secret_id', + help='AppRole secret_id for authentication with vault'), + cfg.StrOpt('kv_mountpoint', + default=DEFAULT_MOUNTPOINT, + help='Mountpoint of KV store in Vault to use, for example: ' + '{}'.format(DEFAULT_MOUNTPOINT)), cfg.StrOpt('vault_url', default=DEFAULT_VAULT_URL, help='Use this endpoint to connect to Vault, for example: ' @@ -88,17 +98,121 @@ loading.register_session_conf_options(self._conf, VAULT_OPT_GROUP) self._session = requests.Session() self._root_token_id = self._conf.vault.root_token_id + self._approle_role_id = self._conf.vault.approle_role_id + self._approle_secret_id = self._conf.vault.approle_secret_id + self._cached_approle_token_id = None + self._approle_token_ttl = None + self._approle_token_issue = None + self._kv_mountpoint = self._conf.vault.kv_mountpoint self._vault_url = self._conf.vault.vault_url if self._vault_url.startswith("https://"): self._verify_server = self._conf.vault.ssl_ca_crt_file or True else: self._verify_server = False + self._vault_kv_version = None def _get_url(self): if not self._vault_url.endswith('/'): self._vault_url += '/' return self._vault_url + def _get_api_version(self): + if self._vault_kv_version: + return self._vault_kv_version + + resource_url = '{}v1/sys/internal/ui/mounts/{}'.format( + self._get_url(), + self._kv_mountpoint + ) + resp = self._do_http_request(self._session.get, resource_url) + + if resp.status_code == requests.codes['not_found']: + self._vault_kv_version = '1' + else: + self._vault_kv_version = resp.json()['data']['options']['version'] + + return self._vault_kv_version + + def _get_resource_url(self, key_id=None): + return '{}v1/{}/{}{}'.format( + self._get_url(), + self._kv_mountpoint, + + '' if self._get_api_version() == '1' else + 'data/' if key_id else + 'metadata/', # no key_id is for listing and 'data/' doesn't works + + key_id if key_id else '?list=true') + + @property + def _approle_token_id(self): + if (all((self._approle_token_issue, self._approle_token_ttl)) and + timeutils.is_older_than(self._approle_token_issue, + self._approle_token_ttl)): + self._cached_approle_token_id = None + return self._cached_approle_token_id + + def _build_auth_headers(self): + if self._root_token_id: + return {'X-Vault-Token': self._root_token_id} + + if self._approle_token_id: + return {'X-Vault-Token': self._approle_token_id} + + if self._approle_role_id: + params = { + 'role_id': self._approle_role_id + } + if self._approle_secret_id: + params['secret_id'] = self._approle_secret_id + approle_login_url = '{}v1/auth/approle/login'.format( + self._get_url() + ) + token_issue_utc = timeutils.utcnow() + try: + resp = self._session.post(url=approle_login_url, + json=params, + verify=self._verify_server) + except requests.exceptions.Timeout as ex: + raise exception.KeyManagerError(six.text_type(ex)) + except requests.exceptions.ConnectionError as ex: + raise exception.KeyManagerError(six.text_type(ex)) + except Exception as ex: + raise exception.KeyManagerError(six.text_type(ex)) + + if resp.status_code in _EXCEPTIONS_BY_CODE: + raise exception.KeyManagerError(resp.reason) + if resp.status_code == requests.codes['forbidden']: + raise exception.Forbidden() + + resp = resp.json() + self._cached_approle_token_id = resp['auth']['client_token'] + self._approle_token_issue = token_issue_utc + self._approle_token_ttl = resp['auth']['lease_duration'] + return {'X-Vault-Token': self._approle_token_id} + + return {} + + def _do_http_request(self, method, resource, json=None): + verify = self._verify_server + headers = self._build_auth_headers() + + try: + resp = method(resource, headers=headers, json=json, verify=verify) + except requests.exceptions.Timeout as ex: + raise exception.KeyManagerError(six.text_type(ex)) + except requests.exceptions.ConnectionError as ex: + raise exception.KeyManagerError(six.text_type(ex)) + except Exception as ex: + raise exception.KeyManagerError(six.text_type(ex)) + + if resp.status_code in _EXCEPTIONS_BY_CODE: + raise exception.KeyManagerError(resp.reason) + if resp.status_code == requests.codes['forbidden']: + raise exception.Forbidden() + + return resp + def create_key_pair(self, context, algorithm, length, expiration=None, name=None): """Creates an asymmetric key pair.""" @@ -157,34 +271,22 @@ raise exception.KeyManagerError( "Unknown type for value : %r" % value) - headers = {'X-Vault-Token': self._root_token_id} - try: - resource_url = self._get_url() + 'v1/secret/' + key_id - record = { - 'type': type_value, - 'value': binascii.hexlify(value.get_encoded()).decode('utf-8'), - 'algorithm': (value.algorithm if hasattr(value, 'algorithm') - else None), - 'bit_length': (value.bit_length if hasattr(value, 'bit_length') - else None), - 'name': value.name, - 'created': value.created - } - resp = self._session.post(resource_url, - verify=self._verify_server, - json=record, - headers=headers) - except requests.exceptions.Timeout as ex: - raise exception.KeyManagerError(six.text_type(ex)) - except requests.exceptions.ConnectionError as ex: - raise exception.KeyManagerError(six.text_type(ex)) - except Exception as ex: - raise exception.KeyManagerError(six.text_type(ex)) - - if resp.status_code in _EXCEPTIONS_BY_CODE: - raise exception.KeyManagerError(resp.reason) - if resp.status_code == requests.codes['forbidden']: - raise exception.Forbidden() + record = { + 'type': type_value, + 'value': binascii.hexlify(value.get_encoded()).decode('utf-8'), + 'algorithm': (value.algorithm if hasattr(value, 'algorithm') + else None), + 'bit_length': (value.bit_length if hasattr(value, 'bit_length') + else None), + 'name': value.name, + 'created': value.created + } + if self._get_api_version() != '1': + record = {'data': record} + + self._do_http_request(self._session.post, + self._get_resource_url(key_id), + json=record) return key_id @@ -196,13 +298,18 @@ msg = _("User is not authorized to use key manager.") raise exception.Forbidden(msg) + if length % 8: + msg = _("Length must be multiple of 8.") + raise ValueError(msg) + key_id = uuid.uuid4().hex - key_value = os.urandom(length or 32) + key_value = os.urandom((length or 256) // 8) key = sym_key.SymmetricKey(algorithm, - length or 32, + length or 256, key_value, key_id, name or int(time.time())) + return self._store_key_value(key_id, key) def store(self, context, key_value, **kwargs): @@ -227,27 +334,16 @@ if not key_id: raise exception.KeyManagerError('key identifier not provided') - headers = {'X-Vault-Token': self._root_token_id} - try: - resource_url = self._get_url() + 'v1/secret/' + key_id - resp = self._session.get(resource_url, - verify=self._verify_server, - headers=headers) - except requests.exceptions.Timeout as ex: - raise exception.KeyManagerError(six.text_type(ex)) - except requests.exceptions.ConnectionError as ex: - raise exception.KeyManagerError(six.text_type(ex)) - except Exception as ex: - raise exception.KeyManagerError(six.text_type(ex)) + resp = self._do_http_request(self._session.get, + self._get_resource_url(key_id)) - if resp.status_code in _EXCEPTIONS_BY_CODE: - raise exception.KeyManagerError(resp.reason) - if resp.status_code == requests.codes['forbidden']: - raise exception.Forbidden() if resp.status_code == requests.codes['not_found']: raise exception.ManagedObjectNotFoundError(uuid=key_id) record = resp.json()['data'] + if self._get_api_version() != '1': + record = record['data'] + key = None if metadata_only else binascii.unhexlify(record['value']) clazz = None @@ -283,23 +379,9 @@ if not key_id: raise exception.KeyManagerError('key identifier not provided') - headers = {'X-Vault-Token': self._root_token_id} - try: - resource_url = self._get_url() + 'v1/secret/' + key_id - resp = self._session.delete(resource_url, - verify=self._verify_server, - headers=headers) - except requests.exceptions.Timeout as ex: - raise exception.KeyManagerError(six.text_type(ex)) - except requests.exceptions.ConnectionError as ex: - raise exception.KeyManagerError(six.text_type(ex)) - except Exception as ex: - raise exception.KeyManagerError(six.text_type(ex)) + resp = self._do_http_request(self._session.delete, + self._get_resource_url(key_id)) - if resp.status_code in _EXCEPTIONS_BY_CODE: - raise exception.KeyManagerError(resp.reason) - if resp.status_code == requests.codes['forbidden']: - raise exception.Forbidden() if resp.status_code == requests.codes['not_found']: raise exception.ManagedObjectNotFoundError(uuid=key_id) @@ -315,26 +397,13 @@ msg = _("Invalid secret type: %s") % object_type raise exception.KeyManagerError(reason=msg) - headers = {'X-Vault-Token': self._root_token_id} - try: - resource_url = self._get_url() + 'v1/secret/?list=true' - resp = self._session.get(resource_url, - verify=self._verify_server, - headers=headers) - keys = resp.json()['data']['keys'] - except requests.exceptions.Timeout as ex: - raise exception.KeyManagerError(six.text_type(ex)) - except requests.exceptions.ConnectionError as ex: - raise exception.KeyManagerError(six.text_type(ex)) - except Exception as ex: - raise exception.KeyManagerError(six.text_type(ex)) + resp = self._do_http_request(self._session.get, + self._get_resource_url()) - if resp.status_code in _EXCEPTIONS_BY_CODE: - raise exception.KeyManagerError(resp.reason) - if resp.status_code == requests.codes['forbidden']: - raise exception.Forbidden() if resp.status_code == requests.codes['not_found']: keys = [] + else: + keys = resp.json()['data']['keys'] objects = [] for obj_id in keys: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan/options.py new/castellan-1.2.2/castellan/options.py --- old/castellan-0.19.0/castellan/options.py 2018-08-21 22:00:30.000000000 +0200 +++ new/castellan-1.2.2/castellan/options.py 2019-02-28 19:02:40.000000000 +0100 @@ -39,7 +39,9 @@ def set_defaults(conf, backend=None, barbican_endpoint=None, barbican_api_version=None, auth_endpoint=None, retry_delay=None, number_of_retries=None, verify_ssl=None, - api_class=None, vault_root_token_id=None, vault_url=None, + api_class=None, vault_root_token_id=None, + vault_approle_role_id=None, vault_approle_secret_id=None, + vault_kv_mountpoint=None, vault_url=None, vault_ssl_ca_crt_file=None, vault_use_ssl=None, barbican_endpoint_type=None): """Set defaults for configuration values. @@ -54,6 +56,10 @@ :param number_of_retries: Use this attribute to set number of retries. :param verify_ssl: Use this to specify if ssl should be verified. :param vault_root_token_id: Use this for the root token id for vault. + :param vault_approle_role_id: Use this for the approle role_id for vault. + :param vault_approle_secret_id: Use this for the approle secret_id + for vault. + :param vault_kv_mountpoint: Mountpoint of KV store in vault to use. :param vault_url: Use this for the url for vault. :param vault_use_ssl: Use this to force vault driver to use ssl. :param vault_ssl_ca_crt_file: Use this for the CA file for vault. @@ -98,6 +104,15 @@ if vault_root_token_id is not None: conf.set_default('root_token_id', vault_root_token_id, group=vkm.VAULT_OPT_GROUP) + if vault_approle_role_id is not None: + conf.set_default('approle_role_id', vault_approle_role_id, + group=vkm.VAULT_OPT_GROUP) + if vault_approle_secret_id is not None: + conf.set_default('approle_secret_id', vault_approle_secret_id, + group=vkm.VAULT_OPT_GROUP) + if vault_kv_mountpoint is not None: + conf.set_default('kv_mountpoint', vault_kv_mountpoint, + group=vkm.VAULT_OPT_GROUP) if vault_url is not None: conf.set_default('vault_url', vault_url, group=vkm.VAULT_OPT_GROUP) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan/tests/functional/key_manager/test_vault_key_manager.py new/castellan-1.2.2/castellan/tests/functional/key_manager/test_vault_key_manager.py --- old/castellan-0.19.0/castellan/tests/functional/key_manager/test_vault_key_manager.py 2018-08-21 22:00:30.000000000 +0200 +++ new/castellan-1.2.2/castellan/tests/functional/key_manager/test_vault_key_manager.py 2019-02-28 19:02:40.000000000 +0100 @@ -17,11 +17,13 @@ """ import abc import os +import uuid from oslo_config import cfg from oslo_context import context from oslo_utils import uuidutils from oslotest import base +import requests from testtools import testcase from castellan.common import exception @@ -109,3 +111,129 @@ base.BaseTestCase): def get_context(self): return context.get_admin_context() + + +TEST_POLICY = ''' +path "{backend}/*" {{ + capabilities = ["create", "read", "update", "delete", "list"] +}} + +path "sys/internal/ui/mounts/{backend}" {{ + capabilities = ["read"] +}} +''' + +AUTH_ENDPOINT = 'v1/sys/auth/{auth_type}' +POLICY_ENDPOINT = 'v1/sys/policy/{policy_name}' +APPROLE_ENDPOINT = 'v1/auth/approle/role/{role_name}' + + +class VaultKeyManagerAppRoleTestCase(VaultKeyManagerOSLOContextTestCase): + + mountpoint = 'secret' + + def _create_key_manager(self): + key_mgr = vault_key_manager.VaultKeyManager(cfg.CONF) + + if ('VAULT_TEST_URL' not in os.environ or + 'VAULT_TEST_ROOT_TOKEN' not in os.environ): + raise testcase.TestSkipped('Missing Vault setup information') + + self.root_token_id = os.environ['VAULT_TEST_ROOT_TOKEN'] + self.vault_url = os.environ['VAULT_TEST_URL'] + + test_uuid = str(uuid.uuid4()) + vault_policy = 'policy-{}'.format(test_uuid) + vault_approle = 'approle-{}'.format(test_uuid) + + self.session = requests.Session() + self.session.headers.update({'X-Vault-Token': self.root_token_id}) + + self._mount_kv(self.mountpoint) + self._enable_approle() + self._create_policy(vault_policy) + self._create_approle(vault_approle, vault_policy) + + key_mgr._approle_role_id, key_mgr._approle_secret_id = ( + self._retrieve_approle(vault_approle) + ) + key_mgr._kv_mountpoint = self.mountpoint + key_mgr._vault_url = self.vault_url + return key_mgr + + def _mount_kv(self, vault_mountpoint): + backends = self.session.get( + '{}/v1/sys/mounts'.format(self.vault_url)).json() + if vault_mountpoint not in backends: + params = { + 'type': 'kv', + 'options': { + 'version': 2, + } + } + self.session.post( + '{}/v1/sys/mounts/{}'.format(self.vault_url, + vault_mountpoint), + json=params) + + def _enable_approle(self): + params = { + 'type': 'approle' + } + self.session.post( + '{}/{}'.format( + self.vault_url, + AUTH_ENDPOINT.format(auth_type='approle') + ), + json=params, + ) + + def _create_policy(self, vault_policy): + params = { + 'rules': TEST_POLICY.format(backend=self.mountpoint), + } + self.session.put( + '{}/{}'.format( + self.vault_url, + POLICY_ENDPOINT.format(policy_name=vault_policy) + ), + json=params, + ) + + def _create_approle(self, vault_approle, vault_policy): + params = { + 'token_ttl': '60s', + 'token_max_ttl': '60s', + 'policies': [vault_policy], + 'bind_secret_id': 'true', + 'bound_cidr_list': '127.0.0.1/32' + } + self.session.post( + '{}/{}'.format( + self.vault_url, + APPROLE_ENDPOINT.format(role_name=vault_approle) + ), + json=params, + ) + + def _retrieve_approle(self, vault_approle): + approle_role_id = ( + self.session.get( + '{}/v1/auth/approle/role/{}/role-id'.format( + self.vault_url, + vault_approle + )).json()['data']['role_id'] + ) + approle_secret_id = ( + self.session.post( + '{}/v1/auth/approle/role/{}/secret-id'.format( + self.vault_url, + vault_approle + )).json()['data']['secret_id'] + ) + return (approle_role_id, approle_secret_id) + + +class VaultKeyManagerAltMountpointTestCase(VaultKeyManagerAppRoleTestCase): + + mountpoint = 'different-secrets' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan/tests/unit/test_config_driver.py new/castellan-1.2.2/castellan/tests/unit/test_config_driver.py --- old/castellan-0.19.0/castellan/tests/unit/test_config_driver.py 1970-01-01 01:00:00.000000000 +0100 +++ new/castellan-1.2.2/castellan/tests/unit/test_config_driver.py 2019-02-28 19:02:40.000000000 +0100 @@ -0,0 +1,108 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Functional test cases for the Castellan Oslo Config Driver. + +Note: This requires local running instance of Vault. +""" +import tempfile + +from oslo_config import cfg +from oslo_config import fixture + +from oslotest import base + +from castellan import _config_driver +from castellan.common.objects import opaque_data +from castellan.tests.unit.key_manager import fake + + +class CastellanSourceTestCase(base.BaseTestCase): + + def setUp(self): + super(CastellanSourceTestCase, self).setUp() + self.driver = _config_driver.CastellanConfigurationSourceDriver() + self.conf = cfg.ConfigOpts() + self.conf_fixture = self.useFixture(fixture.Config(self.conf)) + + def test_incomplete_driver(self): + # The group exists, but does not specify the + # required options for this driver. + self.conf_fixture.load_raw_values( + group='incomplete_driver', + driver='castellan', + ) + source = self.conf._open_source_from_opt_group('incomplete_driver') + + self.assertIsNone(source) + self.assertEqual(self.conf.incomplete_driver.driver, 'castellan') + + def test_complete_driver(self): + self.conf_fixture.load_raw_values( + group='castellan_source', + driver='castellan', + config_file='config.conf', + mapping_file='mapping.conf', + ) + + with base.mock.patch.object( + _config_driver, + 'CastellanConfigurationSource') as source_class: + self.driver.open_source_from_opt_group( + self.conf, 'castellan_source') + + source_class.assert_called_once_with( + 'castellan_source', + self.conf.castellan_source.config_file, + self.conf.castellan_source.mapping_file) + + def test_fetch_secret(self): + # fake KeyManager populated with secret + km = fake.fake_api() + secret_id = km.store("fake_context", + opaque_data.OpaqueData(b"super_secret!")) + + # driver config + config = "[key_manager]\nbackend=vault" + mapping = "[DEFAULT]\nmy_secret=" + secret_id + + # creating temp files + with tempfile.NamedTemporaryFile() as config_file: + config_file.write(config.encode("utf-8")) + config_file.flush() + + with tempfile.NamedTemporaryFile() as mapping_file: + mapping_file.write(mapping.encode("utf-8")) + mapping_file.flush() + + self.conf_fixture.load_raw_values( + group='castellan_source', + driver='castellan', + config_file=config_file.name, + mapping_file=mapping_file.name, + ) + + source = self.driver.open_source_from_opt_group( + self.conf, + 'castellan_source') + + # replacing key_manager with fake one + source._mngr = km + + # testing if the source is able to retrieve + # the secret value stored in the key_manager + # using the secret_id from the mapping file + self.assertEqual("super_secret!", + source.get("DEFAULT", + "my_secret", + cfg.StrOpt(""))[0]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan.egg-info/PKG-INFO new/castellan-1.2.2/castellan.egg-info/PKG-INFO --- old/castellan-0.19.0/castellan.egg-info/PKG-INFO 2018-08-21 22:04:14.000000000 +0200 +++ new/castellan-1.2.2/castellan.egg-info/PKG-INFO 2019-02-28 19:06:34.000000000 +0100 @@ -1,10 +1,10 @@ Metadata-Version: 1.1 Name: castellan -Version: 0.19.0 +Version: 1.2.2 Summary: Generic Key Manager interface for OpenStack Home-page: https://docs.openstack.org/castellan/latest/ Author: OpenStack -Author-email: openstack-dev@lists.openstack.org +Author-email: openstack-discuss@lists.openstack.org License: UNKNOWN Description: ========= Castellan @@ -16,6 +16,7 @@ * Documentation: https://docs.openstack.org/castellan/latest * Source: https://git.openstack.org/cgit/openstack/castellan * Bugs: https://bugs.launchpad.net/castellan + * Release notes: https://docs.openstack.org/releasenotes/castellan Team and repository tags ======================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan.egg-info/SOURCES.txt new/castellan-1.2.2/castellan.egg-info/SOURCES.txt --- old/castellan-0.19.0/castellan.egg-info/SOURCES.txt 2018-08-21 22:04:15.000000000 +0200 +++ new/castellan-1.2.2/castellan.egg-info/SOURCES.txt 2019-02-28 19:06:34.000000000 +0100 @@ -1,6 +1,6 @@ .coveragerc .mailmap -.testr.conf +.stestr.conf .zuul.yaml AUTHORS CONTRIBUTING.rst @@ -16,6 +16,7 @@ test-requirements.txt tox.ini castellan/__init__.py +castellan/_config_driver.py castellan/i18n.py castellan/options.py castellan.egg-info/PKG-INFO @@ -63,6 +64,7 @@ castellan/tests/functional/key_manager/test_key_manager.py castellan/tests/functional/key_manager/test_vault_key_manager.py castellan/tests/unit/__init__.py +castellan/tests/unit/test_config_driver.py castellan/tests/unit/test_options.py castellan/tests/unit/test_utils.py castellan/tests/unit/credentials/__init__.py @@ -100,11 +102,15 @@ playbooks/devstack/run.yaml releasenotes/notes/add-vault-provider-29a4c19fe67ab51f.yaml releasenotes/notes/deprecate-auth-endpoint-b91a3e67b5c7263f.yaml +releasenotes/notes/fix-vault-create-key-b4340a3067cbd93c.yaml releasenotes/notes/support-legacy-fixed-key-id-9fa897b547111610.yaml +releasenotes/notes/vault-approle-support-5ea04daea07a152f.yaml +releasenotes/notes/vault-kv-mountpoint-919eb547764a0c74.yaml releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/pike.rst releasenotes/source/queens.rst +releasenotes/source/rocky.rst releasenotes/source/unreleased.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan.egg-info/entry_points.txt new/castellan-1.2.2/castellan.egg-info/entry_points.txt --- old/castellan-0.19.0/castellan.egg-info/entry_points.txt 2018-08-21 22:04:14.000000000 +0200 +++ new/castellan-1.2.2/castellan.egg-info/entry_points.txt 2019-02-28 19:06:34.000000000 +0100 @@ -2,6 +2,9 @@ barbican = castellan.key_manager.barbican_key_manager:BarbicanKeyManager vault = castellan.key_manager.vault_key_manager:VaultKeyManager +[oslo.config.driver] +castellan = castellan._config_driver:CastellanConfigurationSourceDriver + [oslo.config.opts] castellan.config = castellan.options:list_opts castellan.tests.functional.config = castellan.tests.functional.config:list_opts diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan.egg-info/pbr.json new/castellan-1.2.2/castellan.egg-info/pbr.json --- old/castellan-0.19.0/castellan.egg-info/pbr.json 2018-08-21 22:04:14.000000000 +0200 +++ new/castellan-1.2.2/castellan.egg-info/pbr.json 2019-02-28 19:06:34.000000000 +0100 @@ -1 +1 @@ -{"git_version": "a99da51", "is_release": true} \ No newline at end of file +{"git_version": "9a34dc9", "is_release": true} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/castellan.egg-info/requires.txt new/castellan-1.2.2/castellan.egg-info/requires.txt --- old/castellan-0.19.0/castellan.egg-info/requires.txt 2018-08-21 22:04:14.000000000 +0200 +++ new/castellan-1.2.2/castellan.egg-info/requires.txt 2019-02-28 19:06:34.000000000 +0100 @@ -2,7 +2,7 @@ Babel!=2.4.0,>=2.3.4 cryptography>=2.1 python-barbicanclient>=4.5.2 -oslo.config>=5.2.0 +oslo.config>=6.4.0 oslo.context>=2.19.2 oslo.i18n>=3.15.3 oslo.log>=3.36.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/lower-constraints.txt new/castellan-1.2.2/lower-constraints.txt --- old/castellan-0.19.0/lower-constraints.txt 2018-08-21 22:00:55.000000000 +0200 +++ new/castellan-1.2.2/lower-constraints.txt 2019-02-28 19:02:40.000000000 +0100 @@ -33,7 +33,7 @@ netifaces==0.10.4 openstackdocstheme==1.18.1 os-client-config==1.28.0 -oslo.config==5.2.0 +oslo.config==6.4.0 oslo.context==2.19.2 oslo.i18n==3.15.3 oslo.log==3.36.0 @@ -66,7 +66,7 @@ Sphinx==1.6.2 sphinxcontrib-websupport==1.0.1 stevedore==1.20.0 -testrepository==0.0.18 +stestr==2.0.0 testscenarios==0.4 testtools==2.2.0 traceback2==1.4.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/releasenotes/notes/fix-vault-create-key-b4340a3067cbd93c.yaml new/castellan-1.2.2/releasenotes/notes/fix-vault-create-key-b4340a3067cbd93c.yaml --- old/castellan-0.19.0/releasenotes/notes/fix-vault-create-key-b4340a3067cbd93c.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/castellan-1.2.2/releasenotes/notes/fix-vault-create-key-b4340a3067cbd93c.yaml 2019-02-28 19:02:40.000000000 +0100 @@ -0,0 +1,10 @@ +--- +fixes: + - | + Fixed VaultKeyManager.create_key() to consider the `length` param as bits + instead of bytes for the key length. This was causing a discrepancy between + keys generated by the HashiCorp Vault backend and the OpenStack Barbican + backend. Considering `km` as an instance of a key manager, the following + code `km.create_key(ctx, "AES", 256)` was generating a 256 bit AES key when + Barbican is configured as the backend, but generating a 2048 bit AES key + when Vault was configured as the backend. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/releasenotes/notes/reno.cache new/castellan-1.2.2/releasenotes/notes/reno.cache --- old/castellan-0.19.0/releasenotes/notes/reno.cache 2018-08-21 22:04:15.000000000 +0200 +++ new/castellan-1.2.2/releasenotes/notes/reno.cache 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ ---- -file-contents: {} -notes: [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/releasenotes/notes/vault-approle-support-5ea04daea07a152f.yaml new/castellan-1.2.2/releasenotes/notes/vault-approle-support-5ea04daea07a152f.yaml --- old/castellan-0.19.0/releasenotes/notes/vault-approle-support-5ea04daea07a152f.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/castellan-1.2.2/releasenotes/notes/vault-approle-support-5ea04daea07a152f.yaml 2019-02-28 19:02:40.000000000 +0100 @@ -0,0 +1,7 @@ +--- +features: + - | + Added support for AppRole based authentication to the Vault + key manager configured using new approle_role_id and + optional approle_secret_id options. + (https://www.vaultproject.io/docs/auth/approle.html) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/releasenotes/notes/vault-kv-mountpoint-919eb547764a0c74.yaml new/castellan-1.2.2/releasenotes/notes/vault-kv-mountpoint-919eb547764a0c74.yaml --- old/castellan-0.19.0/releasenotes/notes/vault-kv-mountpoint-919eb547764a0c74.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/castellan-1.2.2/releasenotes/notes/vault-kv-mountpoint-919eb547764a0c74.yaml 2019-02-28 19:02:40.000000000 +0100 @@ -0,0 +1,6 @@ +--- +features: + - | + Added configuration option to the Vault key manager to allow + the KV store mountpoint in Vault to be specified; the existing + default of 'secret' is maintained. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/releasenotes/source/index.rst new/castellan-1.2.2/releasenotes/source/index.rst --- old/castellan-0.19.0/releasenotes/source/index.rst 2018-08-21 22:00:55.000000000 +0200 +++ new/castellan-1.2.2/releasenotes/source/index.rst 2019-02-28 19:02:40.000000000 +0100 @@ -6,5 +6,6 @@ :maxdepth: 1 unreleased + rocky queens pike diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/releasenotes/source/rocky.rst new/castellan-1.2.2/releasenotes/source/rocky.rst --- old/castellan-0.19.0/releasenotes/source/rocky.rst 1970-01-01 01:00:00.000000000 +0100 +++ new/castellan-1.2.2/releasenotes/source/rocky.rst 2019-02-28 19:02:40.000000000 +0100 @@ -0,0 +1,6 @@ +=================================== + Rocky Series Release Notes +=================================== + +.. release-notes:: + :branch: stable/rocky diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/requirements.txt new/castellan-1.2.2/requirements.txt --- old/castellan-0.19.0/requirements.txt 2018-08-21 22:00:30.000000000 +0200 +++ new/castellan-1.2.2/requirements.txt 2019-02-28 19:02:40.000000000 +0100 @@ -6,7 +6,7 @@ Babel!=2.4.0,>=2.3.4 # BSD cryptography>=2.1 # BSD/Apache-2.0 python-barbicanclient>=4.5.2 # Apache-2.0 -oslo.config>=5.2.0 # Apache-2.0 +oslo.config>=6.4.0 # Apache-2.0 oslo.context>=2.19.2 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/setup.cfg new/castellan-1.2.2/setup.cfg --- old/castellan-0.19.0/setup.cfg 2018-08-21 22:04:15.000000000 +0200 +++ new/castellan-1.2.2/setup.cfg 2019-02-28 19:06:34.000000000 +0100 @@ -4,7 +4,7 @@ description-file = README.rst author = OpenStack -author-email = openstack-dev@lists.openstack.org +author-email = openstack-discuss@lists.openstack.org home-page = https://docs.openstack.org/castellan/latest/ classifier = Environment :: OpenStack @@ -26,6 +26,8 @@ oslo.config.opts = castellan.tests.functional.config = castellan.tests.functional.config:list_opts castellan.config = castellan.options:list_opts +oslo.config.driver = + castellan = castellan._config_driver:CastellanConfigurationSourceDriver castellan.drivers = barbican = castellan.key_manager.barbican_key_manager:BarbicanKeyManager vault = castellan.key_manager.vault_key_manager:VaultKeyManager diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/test-requirements.txt new/castellan-1.2.2/test-requirements.txt --- old/castellan-0.19.0/test-requirements.txt 2018-08-21 22:00:55.000000000 +0200 +++ new/castellan-1.2.2/test-requirements.txt 2019-02-28 19:02:40.000000000 +0100 @@ -9,7 +9,8 @@ sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD openstackdocstheme>=1.18.1 # Apache-2.0 oslotest>=3.2.0 # Apache-2.0 -testrepository>=0.0.18 # Apache-2.0/BSD +stestr>=2.0.0 # Apache-2.0 +fixtures>=3.0.0 # Apache-2.0/BSD testscenarios>=0.4 # Apache-2.0/BSD testtools>=2.2.0 # MIT bandit>=1.1.0 # Apache-2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/tools/setup-vault-env.sh new/castellan-1.2.2/tools/setup-vault-env.sh --- old/castellan-0.19.0/tools/setup-vault-env.sh 2018-08-21 22:00:30.000000000 +0200 +++ new/castellan-1.2.2/tools/setup-vault-env.sh 2019-02-28 19:02:40.000000000 +0100 @@ -1,7 +1,7 @@ #!/bin/bash set -eux if [ -z "$(which vault)" ]; then - VAULT_VERSION=0.7.3 + VAULT_VERSION=0.10.4 SUFFIX=zip case `uname -s` in Darwin) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/castellan-0.19.0/tox.ini new/castellan-1.2.2/tox.ini --- old/castellan-0.19.0/tox.ini 2018-08-21 22:00:55.000000000 +0200 +++ new/castellan-1.2.2/tox.ini 2019-02-28 19:02:40.000000000 +0100 @@ -1,30 +1,31 @@ [tox] -minversion = 1.6 -envlist = py35,py27,pep8 +minversion = 2.0 +envlist = py36,py27,pep8 skipsdist = True [testenv] -basepython = python3 usedevelop = True install_command = pip install {opts} {packages} setenv = VIRTUAL_ENV={envdir} OS_TEST_PATH=./castellan/tests/unit deps = - -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt?h=stable/rocky} + -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt -commands = python setup.py testr --slowest --testr-args='{posargs}' +commands = stestr run --slowest {posargs} [testenv:py27] basepython = python2.7 [testenv:pep8] +basepython = python3 commands = flake8 bandit -r castellan -x tests -s B105,B106,B107,B607 [testenv:bandit] +basepython = python3 # This command runs the bandit security linter against the castellan # codebase minus the tests directory. Some tests are being excluded to # reduce the number of positives before a team inspection, and to ensure a @@ -37,20 +38,30 @@ bandit -r castellan -x tests -s B105,B106,B107,B607 [testenv:venv] +basepython = python3 commands = {posargs} [testenv:debug] +basepython = python3 commands = oslo_debug_helper {posargs} [testenv:cover] +basepython = python3 +setenv = + PYTHON=coverage run --source $project --parallel-mode commands = - python setup.py testr --coverage --testr-args='{posargs}' - coverage report + stestr run {posargs} + coverage combine + coverage html -d cover + coverage xml -o cover/coverage.xml + coverage report [testenv:docs] +basepython = python3 commands = python setup.py build_sphinx [testenv:releasenotes] +basepython = python3 commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [testenv:functional] @@ -59,7 +70,7 @@ setenv = VIRTUAL_ENV={envdir} OS_TEST_PATH=./castellan/tests/functional -commands = python setup.py testr --slowest --testr-args='{posargs}' +commands = stestr run --slowest {posargs} [testenv:functional-vault] passenv = HOME @@ -69,9 +80,10 @@ VIRTUAL_ENV={envdir} OS_TEST_PATH=./castellan/tests/functional commands = - {toxinidir}/tools/setup-vault-env.sh pifpaf -e VAULT_TEST run vault -- python setup.py testr --slowest --testr-args='{posargs}' + {toxinidir}/tools/setup-vault-env.sh pifpaf -e VAULT_TEST run vault -- stestr run --slowest {posargs} [testenv:genconfig] +basepython = python3 commands = oslo-config-generator --config-file=etc/castellan/functional-config-generator.conf oslo-config-generator --config-file=etc/castellan/sample-config-generator.conf @@ -87,6 +99,7 @@ import_exceptions = castellan.i18n [testenv:lower-constraints] +basepython = python3 deps = -c{toxinidir}/lower-constraints.txt -r{toxinidir}/test-requirements.txt
participants (1)
-
root