Beispiel #1
0
    def test_read_config(self, label, write_config_first=True, raises=None):

        credentials = utils.load_config_file('example.jwt.json')
        if write_config_first:
            self.client.auth.gcp.configure(
                credentials=credentials,
                mount_point=self.TEST_MOUNT_POINT,
            )
        if raises is not None:
            with self.assertRaises(raises):
                self.client.auth.gcp.read_config(
                    mount_point=self.TEST_MOUNT_POINT,
                )
        else:
            read_config_response = self.client.auth.gcp.read_config(
                mount_point=self.TEST_MOUNT_POINT,
            )
            logging.debug('read_config_response: %s' % read_config_response)

            creds_dict = json.loads(credentials)
            expected_config = {
                'project_id': creds_dict['project_id'],
                'client_email': creds_dict['client_email'],
                'private_key_id': creds_dict['private_key_id'],
            }
            for k, v in expected_config.items():
                self.assertEqual(
                    first=v,
                    second=read_config_response[k],
                )
Beispiel #2
0
    def test_read_config(self, label, write_config_first=True, raises=None):

        credentials = utils.load_config_file('example.jwt.json')
        if write_config_first:
            self.client.auth.gcp.configure(
                credentials=credentials,
                mount_point=self.TEST_MOUNT_POINT,
            )
        if raises is not None:
            with self.assertRaises(raises):
                self.client.auth.gcp.read_config(
                    mount_point=self.TEST_MOUNT_POINT, )
        else:
            read_config_response = self.client.auth.gcp.read_config(
                mount_point=self.TEST_MOUNT_POINT, )
            logging.debug('read_config_response: %s' % read_config_response)

            creds_dict = json.loads(credentials)
            expected_config = {
                'project_id': creds_dict['project_id'],
                'client_email': creds_dict['client_email'],
                'private_key_id': creds_dict['private_key_id'],
            }
            for k, v in expected_config.items():
                self.assertEqual(
                    first=v,
                    second=read_config_response[k],
                )
Beispiel #3
0
 def get_active_vault_addresses(self):
     vault_addresses = []
     for config_path in self.config_paths:
         config_hcl = load_config_file(config_path)
         config = hcl.loads(config_hcl)
         try:
             vault_address = 'https://{addr}'.format(addr=config['listener']['tcp']['address'])
         except KeyError as error:
             logger.debug('Unable to find explict Vault address in config file {path}: {err}'.format(
                 path=config_path,
                 err=error,
             ))
             vault_address = 'https://127.0.0.1:8200'
             logger.debug('Using default address: {addr}'.format(addr=vault_address))
         vault_addresses.append(vault_address)
     return vault_addresses
Beispiel #4
0
 def get_active_vault_addresses(self):
     vault_addresses = []
     for config_path in self.config_paths:
         config_hcl = load_config_file(config_path)
         config = hcl.loads(config_hcl)
         try:
             vault_address = 'https://{addr}'.format(addr=config['listener']['tcp']['address'])
         except KeyError as error:
             logger.debug('Unable to find explict Vault address in config file {path}: {err}'.format(
                 path=config_path,
                 err=error,
             ))
             vault_address = 'https://127.0.0.1:8200'
             logger.debug('Using default address: {addr}'.format(addr=vault_address))
         vault_addresses.append(vault_address)
     return vault_addresses
Beispiel #5
0
 def test_login(self, label, test_params, raises, requests_mocker):
     role_name = 'hvac'
     credentials = utils.load_config_file('example.jwt.json')
     test_policies = [
         "default",
         "dev",
         "prod",
     ]
     expected_status_code = 200
     mock_url = 'http://localhost:8200/v1/auth/{mount_point}/login'.format(
         mount_point=self.TEST_MOUNT_POINT, )
     mock_response = {
         "auth": {
             "client_token": "f33f8c72-924e-11f8-cb43-ac59d697597c",
             "accessor": "0e9e354a-520f-df04-6867-ee81cae3d42d",
             "policies": test_policies,
             "lease_duration": 2764800,
             "renewable": True,
         },
     }
     requests_mocker.register_uri(
         method='POST',
         url=mock_url,
         status_code=expected_status_code,
         json=mock_response,
     )
     gcp = Gcp(adapter=Request())
     if raises is not None:
         with self.assertRaises(raises):
             gcp.login(role=role_name,
                       jwt=credentials,
                       mount_point=self.TEST_MOUNT_POINT,
                       **test_params)
     else:
         login_response = gcp.login(role=role_name,
                                    jwt=credentials,
                                    mount_point=self.TEST_MOUNT_POINT,
                                    **test_params)
         logging.debug('login_response: %s' % login_response)
         self.assertEqual(
             first=login_response['auth']['policies'],
             second=test_policies,
         )
Beispiel #6
0
 def test_write_config(self,
                       label,
                       max_ttl=3600,
                       raises=False,
                       exception_message=''):
     credentials = utils.load_config_file('example.jwt.json')
     if raises:
         with self.assertRaises(raises) as cm:
             self.client.secrets.gcp.configure(
                 credentials=credentials,
                 max_ttl=max_ttl,
                 mount_point=self.TEST_MOUNT_POINT,
             )
         self.assertIn(
             member=exception_message,
             container=str(cm.exception),
         )
     else:
         configure_response = self.client.secrets.gcp.configure(
             credentials=credentials,
             max_ttl=max_ttl,
             mount_point=self.TEST_MOUNT_POINT,
         )
         logging.debug('configure_response: %s' % configure_response)
         self.assertEqual(
             first=bool(configure_response),
             second=True,
         )
         read_configuration_response = self.client.secrets.gcp.read_config(
             mount_point=self.TEST_MOUNT_POINT, )
         logging.debug('read_configuration_response: %s' %
                       read_configuration_response)
         self.assertEqual(
             first=read_configuration_response['data']['max_ttl'],
             second=max_ttl,
         )
Beispiel #7
0
class TestLdap(HvacIntegrationTestCase, TestCase):
    TEST_LDAP_PATH = 'test-ldap'
    ldap_server = None
    mock_server_port = None
    mock_ldap_url = None

    @classmethod
    def setUpClass(cls):
        super(TestLdap, cls).setUpClass()
        logging.getLogger('ldap_test').setLevel(logging.ERROR)

        cls.mock_server_port = utils.get_free_port()
        cls.mock_ldap_url = 'ldap://localhost:{port}'.format(port=cls.mock_server_port)
        cls.ldap_server = LdapServer({
            'port': cls.mock_server_port,
            'bind_dn': LDAP_BIND_DN,
            'password': LDAP_BIND_PASSWORD,
            'base': {
                'objectclass': ['domain'],
                'dn': LDAP_BASE_DN,
                'attributes': {'dc': LDAP_BASE_DC}
            },
            'entries': LDAP_ENTRIES,
        })
        cls.ldap_server.start()

    @classmethod
    def tearDownClass(cls):
        super(TestLdap, cls).tearDownClass()
        cls.ldap_server.stop()

    def setUp(self):
        super(TestLdap, self).setUp()
        if 'ldap/' not in self.client.list_auth_backends():
            self.client.sys.enable_auth_method(
                method_type='ldap',
                path=self.TEST_LDAP_PATH
            )

    def tearDown(self):
        super(TestLdap, self).tearDown()
        self.client.disable_auth_backend(
            mount_point=self.TEST_LDAP_PATH,
        )

    @parameterized.expand([
        ('update url', dict(url=LDAP_URL)),
        ('update binddn', dict(url=LDAP_URL, bind_dn='cn=vault,ou=Users,dc=hvac,dc=network')),
        ('update upn_domain', dict(url=LDAP_URL, upn_domain='python-hvac.org')),
        ('update certificate', dict(url=LDAP_URL, certificate=utils.load_config_file('server-cert.pem'))),
        ('incorrect tls version', dict(url=LDAP_URL, tls_min_version='cats'), exceptions.InvalidRequest,
         "invalid 'tls_min_version'"),
    ])
    def test_configure(self, test_label, parameters, raises=None, exception_message=''):
        parameters.update({
            'user_dn': LDAP_USERS_DN,
            'group_dn': LDAP_GROUPS_DN,
            'mount_point': self.TEST_LDAP_PATH,
        })
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.ldap.configure(**parameters)
            self.assertIn(
                member=exception_message,
                container=str(cm.exception),
            )
        else:
            expected_status_code = 204
            configure_response = self.client.auth.ldap.configure(**parameters)
            self.assertEqual(
                first=expected_status_code,
                second=configure_response.status_code
            )

            read_config_response = self.client.auth.ldap.read_configuration(
                mount_point=self.TEST_LDAP_PATH,
            )
            for parameter, argument in parameters.items():
                if parameter == 'mount_point':
                    continue
                self.assertIn(
                    member=argument,
                    container=read_config_response['data'].values(),
                )

    def test_read_configuration(self):
        response = self.client.auth.ldap.read_configuration(
            mount_point=self.TEST_LDAP_PATH,
        )
        self.assertIn(
            member='data',
            container=response,
        )

    @parameterized.expand([
        ('no policies', 'cats'),
        ('policies as list', 'cats', ['purr-policy']),
        ('policies as invalid type', 'cats', 'purr-policy', exceptions.ParamValidationError, '"policies" argument must be an instance of list'),
    ])
    def test_create_or_update_group(self, test_label, name, policies=None, raises=None, exception_message=''):
        expected_status_code = 204
        if raises:
            with self.assertRaises(raises) as cm:
                create_response = self.client.auth.ldap.create_or_update_group(
                    name=name,
                    policies=policies,
                    mount_point=self.TEST_LDAP_PATH,
                )
            if exception_message is not None:
                self.assertIn(
                    member=exception_message,
                    container=str(cm.exception),
                )
        else:
            create_response = self.client.auth.ldap.create_or_update_group(
                name=name,
                policies=policies,
                mount_point=self.TEST_LDAP_PATH,
            )
            self.assertEqual(
                first=expected_status_code,
                second=create_response.status_code
            )

    @parameterized.expand([
        ('read configured groups', 'cats'),
        ('non-existent groups', 'cats', False, exceptions.InvalidPath),
    ])
    def test_list_groups(self, test_label, name, configure_first=True, raises=None, exception_message=None):
        if configure_first:
            self.client.auth.ldap.create_or_update_group(
                name=name,
                mount_point=self.TEST_LDAP_PATH,
            )
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.ldap.list_groups(
                    mount_point=self.TEST_LDAP_PATH,
                )
            if exception_message is not None:
                self.assertIn(
                    member=exception_message,
                    container=str(cm.exception),
                )
        else:
            list_groups_response = self.client.auth.ldap.list_groups(
                mount_point=self.TEST_LDAP_PATH,
            )
            # raise Exception(list_groups_response)
            self.assertDictEqual(
                d1=dict(keys=[name]),
                d2=list_groups_response['data'],
            )

    @parameterized.expand([
        ('read configured group', 'cats'),
        ('non-existent group', 'cats', False, exceptions.InvalidPath),
    ])
    def test_read_group(self, test_label, name, configure_first=True, raises=None, exception_message=None):
        if configure_first:
            self.client.auth.ldap.create_or_update_group(
                name=name,
                mount_point=self.TEST_LDAP_PATH,
            )
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.ldap.read_group(
                    name=name,
                    mount_point=self.TEST_LDAP_PATH,
                )
            if exception_message is not None:
                self.assertIn(
                    member=exception_message,
                    container=str(cm.exception),
                )
        else:
            read_group_response = self.client.auth.ldap.read_group(
                name=name,
                mount_point=self.TEST_LDAP_PATH,
            )
            self.assertIn(
                member='policies',
                container=read_group_response['data'],
            )

    @parameterized.expand([
        ('no policies or groups', 'cats'),
        ('policies as list', 'cats', ['purr-policy']),
        ('policies as invalid type', 'cats', 'purr-policy', None, exceptions.ParamValidationError, '"policies" argument must be an instance of list'),
        ('no groups', 'cats', ['purr-policy']),
        ('groups as list', 'cats', None, ['meow-group']),
        ('groups as invalid type', 'cats', None, 'meow-group', exceptions.ParamValidationError, '"groups" argument must be an instance of list'),
    ])
    def test_create_or_update_user(self, test_label, username, policies=None, groups=None, raises=None, exception_message=''):
        expected_status_code = 204
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.ldap.create_or_update_user(
                    username=username,
                    policies=policies,
                    groups=groups,
                    mount_point=self.TEST_LDAP_PATH,
                )
            if exception_message is not None:
                self.assertIn(
                    member=exception_message,
                    container=str(cm.exception),
                )
        else:
            create_response = self.client.auth.ldap.create_or_update_user(
                username=username,
                policies=policies,
                groups=groups,
                mount_point=self.TEST_LDAP_PATH,
            )
            self.assertEqual(
                first=expected_status_code,
                second=create_response.status_code
            )

    @parameterized.expand([
        ('read configured group', 'cats'),
        ('non-existent group', 'cats', False, exceptions.InvalidPath),
    ])
    def test_delete_group(self, test_label, name, configure_first=True, raises=None, exception_message=None):
        if configure_first:
            self.client.auth.ldap.create_or_update_group(
                name=name,
                mount_point=self.TEST_LDAP_PATH,
            )
        expected_status_code = 204
        delete_group_response = self.client.auth.ldap.delete_group(
            name=name,
            mount_point=self.TEST_LDAP_PATH,
        )
        self.assertEqual(
            first=expected_status_code,
            second=delete_group_response.status_code
        )

    @parameterized.expand([
        ('read configured user', 'cats'),
        ('non-existent user', 'cats', False, exceptions.InvalidPath),
    ])
    def test_list_users(self, test_label, username, configure_first=True, raises=None, exception_message=None):
        if configure_first:
            self.client.auth.ldap.create_or_update_user(
                username=username,
                mount_point=self.TEST_LDAP_PATH,
            )
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.ldap.list_users(
                    mount_point=self.TEST_LDAP_PATH,
                )
            if exception_message is not None:
                self.assertIn(
                    member=exception_message,
                    container=str(cm.exception),
                )
        else:
            list_users_response = self.client.auth.ldap.list_users(
                mount_point=self.TEST_LDAP_PATH,
            )
            self.assertDictEqual(
                d1=dict(keys=[username]),
                d2=list_users_response['data'],
            )

    @parameterized.expand([
        ('read configured user', 'cats'),
        ('non-existent user', 'cats', False, exceptions.InvalidPath),
    ])
    def test_read_user(self, test_label, username, configure_first=True, raises=None, exception_message=None):
        if configure_first:
            self.client.auth.ldap.create_or_update_user(
                username=username,
                mount_point=self.TEST_LDAP_PATH,
            )
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.ldap.read_user(
                    username=username,
                    mount_point=self.TEST_LDAP_PATH,
                )
            if exception_message is not None:
                self.assertIn(
                    member=exception_message,
                    container=str(cm.exception),
                )
        else:
            read_user_response = self.client.auth.ldap.read_user(
                username=username,
                mount_point=self.TEST_LDAP_PATH,
            )
            self.assertIn(
                member='policies',
                container=read_user_response['data'],
            )

    @parameterized.expand([
        ('read configured user', 'cats'),
        ('non-existent user', 'cats', False, exceptions.InvalidPath),
    ])
    def test_delete_user(self, test_label, username, configure_first=True, raises=None, exception_message=None):
        if configure_first:
            self.client.auth.ldap.create_or_update_user(
                username=username,
                mount_point=self.TEST_LDAP_PATH,
            )
        expected_status_code = 204
        delete_user_response = self.client.auth.ldap.delete_user(
            username=username,
            mount_point=self.TEST_LDAP_PATH,
        )
        self.assertEqual(
            first=expected_status_code,
            second=delete_user_response.status_code
        )

    @parameterized.expand([
        param(
            label='working creds with policy'
        ),
        param(
            label='invalid creds',
            username='******',
            password='******',
            attach_policy=False,
            raises=exceptions.InvalidRequest,
        ),
        # The following two test cases cover either side of the associated changelog entry for LDAP auth here:
        # https://github.com/hashicorp/vault/blob/master/CHANGELOG.md#0103-june-20th-2018
        param(
            label='working creds no membership with Vault version >= 0.10.3',
            attach_policy=False,
            skip_due_to_vault_version=utils.vault_version_lt('0.10.3'),
        ),
        param(
            label='working creds no membership with Vault version < 0.10.3',
            attach_policy=False,
            raises=exceptions.InvalidRequest,
            exception_message='user is not a member of any authorized group',
            skip_due_to_vault_version=utils.vault_version_ge('0.10.3'),
        ),
    ])
    def test_login(self, label, username=LDAP_USER_NAME, password=LDAP_USER_PASSWORD, attach_policy=True, raises=None,
                   exception_message='', skip_due_to_vault_version=False):
        if skip_due_to_vault_version:
            self.skipTest(reason='test case does not apply to Vault version under test')

        test_policy_name = 'test-ldap-policy'
        self.client.auth.ldap.configure(
            url=self.mock_ldap_url,
            bind_dn=self.ldap_server.config['bind_dn'],
            bind_pass=self.ldap_server.config['password'],
            user_dn=LDAP_USERS_DN,
            user_attr='uid',
            group_dn=LDAP_GROUPS_DN,
            group_attr='cn',
            insecure_tls=True,
            mount_point=self.TEST_LDAP_PATH,
        )

        if attach_policy:
            self.prep_policy(test_policy_name)
            self.client.auth.ldap.create_or_update_group(
                name=LDAP_GROUP_NAME,
                policies=[test_policy_name],
                mount_point=self.TEST_LDAP_PATH,
            )

        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.ldap.login(
                    username=username,
                    password=password,
                    mount_point=self.TEST_LDAP_PATH,
                )
            if exception_message is not None:
                self.assertIn(
                    member=exception_message,
                    container=str(cm.exception),
                )
        else:
            login_response = self.client.auth.ldap.login(
                username=username,
                password=password,
                mount_point=self.TEST_LDAP_PATH,
            )
            self.assertDictEqual(
                d1=dict(username=username),
                d2=login_response['auth']['metadata'],
            )
            self.assertEqual(
                first=login_response['auth']['client_token'],
                second=self.client.token,
            )
            if attach_policy:
                expected_policies = ['default', test_policy_name]
            else:
                expected_policies = ['default']
            self.assertEqual(
                first=expected_policies,
                second=login_response['auth']['policies']
            )
Beispiel #8
0
class TestGcp(HvacIntegrationTestCase, TestCase):
    TEST_MOUNT_POINT = 'gcp-test'

    def setUp(self):
        super(TestGcp, self).setUp()
        if '%s/' % self.TEST_MOUNT_POINT not in self.client.list_auth_backends(
        ):
            self.client.enable_auth_backend(
                backend_type='gcp',
                mount_point=self.TEST_MOUNT_POINT,
            )

    def tearDown(self):
        super(TestGcp, self).tearDown()
        self.client.disable_auth_backend(mount_point=self.TEST_MOUNT_POINT, )

    @parameterized.expand([
        param(
            'success',
            credentials=utils.load_config_file('example.jwt.json'),
        ),
        param(
            'set invalid credentials',
            credentials='some invalid JWT',
            raises=exceptions.InvalidRequest,
        ),
    ])
    def test_configure(self, label, credentials='', raises=None):
        if raises:
            with self.assertRaises(raises):
                self.client.auth.gcp.configure(
                    credentials=credentials,
                    mount_point=self.TEST_MOUNT_POINT,
                )
        else:
            configure_response = self.client.auth.gcp.configure(
                credentials=credentials,
                mount_point=self.TEST_MOUNT_POINT,
            )
            logging.debug('configure_response: %s' % configure_response)
            self.assertEqual(
                first=bool(configure_response),
                second=True,
            )

    @parameterized.expand([
        param('success', ),
        param('no config written yet',
              write_config_first=False,
              raises=exceptions.InvalidPath)
    ])
    def test_read_config(self, label, write_config_first=True, raises=None):

        credentials = utils.load_config_file('example.jwt.json')
        if write_config_first:
            self.client.auth.gcp.configure(
                credentials=credentials,
                mount_point=self.TEST_MOUNT_POINT,
            )
        if raises is not None:
            with self.assertRaises(raises):
                self.client.auth.gcp.read_config(
                    mount_point=self.TEST_MOUNT_POINT, )
        else:
            read_config_response = self.client.auth.gcp.read_config(
                mount_point=self.TEST_MOUNT_POINT, )
            logging.debug('read_config_response: %s' % read_config_response)

            creds_dict = json.loads(credentials)
            expected_config = {
                'project_id': creds_dict['project_id'],
                'client_email': creds_dict['client_email'],
                'private_key_id': creds_dict['private_key_id'],
            }
            for k, v in expected_config.items():
                self.assertEqual(
                    first=v,
                    second=read_config_response[k],
                )

    @parameterized.expand([
        # param(
        #     'success',  # TODO: figure out why this is returning a 405
        # ),
        param(
            'no existing config',
            write_config_first=False,
            raises=exceptions.UnexpectedError,
        ),
    ])
    def test_delete_config(self, label, write_config_first=True, raises=None):

        if write_config_first:
            self.client.auth.gcp.configure(mount_point=self.TEST_MOUNT_POINT, )
        if raises is not None:
            with self.assertRaises(raises):
                self.client.auth.gcp.delete_config(
                    mount_point=self.TEST_MOUNT_POINT, )
        else:
            delete_config_response = self.client.auth.gcp.delete_config(
                mount_point=self.TEST_MOUNT_POINT, )
            logging.debug('delete_config_response: %s' %
                          delete_config_response)
            self.assertEqual(
                first=bool(delete_config_response),
                second=True,
            )

    @parameterized.expand([
        param('success iam', role_type='iam', bound_service_accounts=['*']),
        param(
            'iam no bound service account',
            role_type='iam',
            raises=exceptions.InvalidRequest,
            exception_message=
            'IAM role type must have at least one service account',
        ),
        param(
            'success gce',
            role_type='gce',
        ),
        param(
            'invalid role type',
            role_type='hvac',
            raises=exceptions.ParamValidationError,
            exception_message='unsupported role_type argument provided',
        ),
    ])
    def test_create_role(self,
                         label,
                         role_type,
                         policies=None,
                         bound_service_accounts=None,
                         raises=None,
                         exception_message=''):
        role_name = 'hvac'
        project_id = 'test-hvac-project-not-a-real-project'
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.gcp.create_role(
                    name=role_name,
                    role_type=role_type,
                    project_id=project_id,
                    policies=policies,
                    bound_service_accounts=bound_service_accounts,
                    mount_point=self.TEST_MOUNT_POINT,
                )
            self.assertIn(
                member=exception_message,
                container=str(cm.exception),
            )
        else:
            create_role_response = self.client.auth.gcp.create_role(
                name=role_name,
                role_type=role_type,
                project_id=project_id,
                policies=policies,
                bound_service_accounts=bound_service_accounts,
                mount_point=self.TEST_MOUNT_POINT,
            )
            logging.debug('create_role_response: %s' % create_role_response)
            self.assertEqual(
                first=bool(create_role_response),
                second=True,
            )

    @parameterized.expand([
        param(
            'success add',
            add=['test'],
        ),
        param(
            'success remove',
            remove=['test'],
        ),
        param(
            'fail upon no changes',
            raises=exceptions.InvalidRequest,
            exception_message=
            'must provide at least one value to add or remove',
        ),
        # TODO: wrong role type (gce)
    ])
    def test_edit_service_accounts_on_iam_role(self,
                                               label,
                                               add=None,
                                               remove=None,
                                               create_role_first=True,
                                               raises=None,
                                               exception_message=''):
        role_name = 'hvac'
        project_id = 'test-hvac-project-not-a-real-project'
        if create_role_first:
            self.client.auth.gcp.create_role(
                name=role_name,
                role_type='iam',
                project_id=project_id,
                bound_service_accounts=[
                    '*****@*****.**'
                ],
                mount_point=self.TEST_MOUNT_POINT,
            )
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.gcp.edit_service_accounts_on_iam_role(
                    name=role_name,
                    add=add,
                    remove=remove,
                    mount_point=self.TEST_MOUNT_POINT,
                )
            self.assertIn(
                member=exception_message,
                container=str(cm.exception),
            )
        else:
            edit_sa_on_iam_response = self.client.auth.gcp.edit_service_accounts_on_iam_role(
                name=role_name,
                add=add,
                remove=remove,
                mount_point=self.TEST_MOUNT_POINT,
            )
            logging.debug('create_role_response: %s' % edit_sa_on_iam_response)
            self.assertEqual(
                first=bool(edit_sa_on_iam_response),
                second=True,
            )

    @parameterized.expand([
        param(
            'success add',
            add=['test-key:test-value'],
        ),
        param(
            'success remove',
            remove=['test-key:test-value'],
        ),
        param(
            'fail upon no changes',
            raises=exceptions.InvalidRequest,
            exception_message=
            'must provide at least one value to add or remove',
        ),
        # TODO: wrong role type (iam)
    ])
    def test_edit_labels_on_gce_role(self,
                                     label,
                                     add=None,
                                     remove=None,
                                     create_role_first=True,
                                     raises=None,
                                     exception_message=''):
        role_name = 'hvac'
        project_id = 'test-hvac-project-not-a-real-project'
        if create_role_first:
            self.client.auth.gcp.create_role(
                name=role_name,
                role_type='gce',
                project_id=project_id,
                bound_service_accounts=[
                    '*****@*****.**'
                ],
                mount_point=self.TEST_MOUNT_POINT,
            )
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.gcp.edit_labels_on_gce_role(
                    name=role_name,
                    add=add,
                    remove=remove,
                    mount_point=self.TEST_MOUNT_POINT,
                )
            self.assertIn(
                member=exception_message,
                container=str(cm.exception),
            )
        else:
            edit_labled_response = self.client.auth.gcp.edit_labels_on_gce_role(
                name=role_name,
                add=add,
                remove=remove,
                mount_point=self.TEST_MOUNT_POINT,
            )
            logging.debug('create_role_response: %s' % edit_labled_response)
            self.assertEqual(
                first=bool(edit_labled_response),
                second=True,
            )

    @parameterized.expand([
        param('success', ),
        param(
            'nonexistent role',
            create_role_first=False,
            raises=exceptions.InvalidPath,
        ),
    ])
    def test_read_role(self,
                       label,
                       create_role_first=True,
                       raises=None,
                       exception_message=''):
        role_name = 'hvac'
        project_id = 'test-hvac-project-not-a-real-project'
        if create_role_first:
            self.client.auth.gcp.create_role(
                name=role_name,
                role_type='gce',
                project_id=project_id,
                bound_service_accounts=[
                    '*****@*****.**'
                ],
                mount_point=self.TEST_MOUNT_POINT,
            )
        if raises:
            with self.assertRaises(raises) as cm:
                self.client.auth.gcp.read_role(
                    name=role_name,
                    mount_point=self.TEST_MOUNT_POINT,
                )
            self.assertIn(
                member=exception_message,
                container=str(cm.exception),
            )
        else:
            read_role_response = self.client.auth.gcp.read_role(
                name=role_name,
                mount_point=self.TEST_MOUNT_POINT,
            )
            logging.debug('create_role_response: %s' % read_role_response)
            if utils.vault_version_ge('1.0.0'):
                returned_project_id = read_role_response['bound_projects']
                expected_project_id = [project_id]
            else:
                returned_project_id = read_role_response['project_id']
                expected_project_id = project_id
            self.assertEqual(first=returned_project_id,
                             second=expected_project_id)

    @parameterized.expand([
        param('success one role', ),
        param(
            'success multiple roles',
            num_roles_to_create=7,
        ),
        param(
            'no roles',
            num_roles_to_create=0,
            raises=exceptions.InvalidPath,
        ),
    ])
    def test_list_roles(self, label, num_roles_to_create=1, raises=None):
        project_id = 'test-hvac-project-not-a-real-project'
        roles_to_create = ['hvac%s' % n for n in range(0, num_roles_to_create)]
        logging.debug('roles_to_create: %s' % roles_to_create)
        for role_to_create in roles_to_create:
            create_role_response = self.client.auth.gcp.create_role(
                name=role_to_create,
                role_type='gce',
                project_id=project_id,
                bound_service_accounts=[
                    '*****@*****.**'
                ],
                mount_point=self.TEST_MOUNT_POINT,
            )
            logging.debug('create_role_response: %s' % create_role_response)

        if raises is not None:
            with self.assertRaises(raises):
                self.client.auth.gcp.list_roles(
                    mount_point=self.TEST_MOUNT_POINT, )
        else:
            list_roles_response = self.client.auth.gcp.list_roles(
                mount_point=self.TEST_MOUNT_POINT, )
            logging.debug('list_roles_response: %s' % list_roles_response)
            self.assertEqual(
                first=list_roles_response['keys'],
                second=roles_to_create,
            )

    @parameterized.expand([
        param('success', ),
        param(
            'nonexistent role name',
            configure_role_first=False,
        ),
    ])
    def test_delete_role(self, label, configure_role_first=True, raises=None):
        role_name = 'hvac'
        project_id = 'test-hvac-project-not-a-real-project'
        if configure_role_first:
            create_role_response = self.client.auth.gcp.create_role(
                name=role_name,
                role_type='gce',
                project_id=project_id,
                bound_service_accounts=[
                    '*****@*****.**'
                ],
                mount_point=self.TEST_MOUNT_POINT,
            )
            logging.debug('create_role_response: %s' % create_role_response)

        if raises is not None:
            with self.assertRaises(raises):
                self.client.auth.gcp.delete_role(
                    role=role_name,
                    mount_point=self.TEST_MOUNT_POINT,
                )
        else:
            delete_role_response = self.client.auth.gcp.delete_role(
                role=role_name,
                mount_point=self.TEST_MOUNT_POINT,
            )
            logging.debug('delete_role_response: %s' % delete_role_response)
            self.assertEqual(
                first=bool(delete_role_response),
                second=True,
            )