Skip to content

Commit

Permalink
[VCDA-2578, VCDA-2108, VCDA-2262] Cluster share fix and system user c…
Browse files Browse the repository at this point in the history
…luster sharing (vmware#1083)

* added support for tenant header

Signed-off-by: ltimothy <ltimothy@vmware.com>

* incorporating native system and TKG sharing

Signed-off-by: ltimothy <ltimothy@vmware.com>

* working TKG-s sysadmin sharing

Signed-off-by: ltimothy <ltimothy@vmware.com>

* using ClusterAclEntry for payload

Signed-off-by: ltimothy <ltimothy@vmware.com>

* retrieving TKG org id for sharing def entity

Signed-off-by: ltimothy <ltimothy@vmware.com>

* added getting org id for native entities

Signed-off-by: ltimothy <ltimothy@vmware.com>

* edited cluster org needed message for sys users

Signed-off-by: ltimothy <ltimothy@vmware.com>

* more efficient getting org id for TKG

Signed-off-by: ltimothy <ltimothy@vmware.com>

* added dataclass_json for cluster acl entry

Signed-off-by: ltimothy <ltimothy@vmware.com>
  • Loading branch information
ltimothy7 authored Jun 28, 2021
1 parent 006b648 commit a41ecd9
Show file tree
Hide file tree
Showing 19 changed files with 230 additions and 68 deletions.
36 changes: 24 additions & 12 deletions container_service_extension/client/cluster_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -1089,10 +1089,14 @@ def cluster_share(ctx, name, acl, users, vdc, org, k8_runtime, cluster_id):
k8_runtime = shared_constants.ClusterEntityKind.TKG.value

client = ctx.obj['client']
# TODO(CLI): Check regarding is sysadmin client check
if not org:
ctx_profiles = ctx.obj['profiles']
org = ctx_profiles.get('org')
# Users should be explicit in their intent about the org on which the
# command needs to be executed.
is_system_user = client.is_sysadmin()
if not is_system_user and org is None:
org = ctx.obj['profiles'].get('org_in_use')
elif is_system_user and org is None:
raise Exception("Need to specify cluster org since logged in user is in system org") # noqa: E501

users_list = list(users)
cluster = Cluster(client, k8_runtime)
cluster.share_cluster(cluster_id, name, users_list, access_level_id,
Expand Down Expand Up @@ -1182,10 +1186,14 @@ def cluster_share_list(ctx, should_print_all, name, vdc, org, k8_runtime,

# Determine cluster type and retrieve cluster id if needed
client = ctx.obj['client']
# TODO(CLI): Check regarding is sysadmin client check
if not org:
ctx_profiles = ctx.obj['profiles']
org = ctx_profiles.get('org')
# Users should be explicit in their intent about the org on which the
# command needs to be executed.
is_system_user = client.is_sysadmin()
if not is_system_user and org is None:
org = ctx.obj['profiles'].get('org_in_use')
elif is_system_user and org is None:
raise Exception("Need to specify cluster org since logged in user is in system org") # noqa: E501

cluster = Cluster(client, k8_runtime)
share_entries = cluster.list_share_entries(cluster_id, name, org, vdc)
client_utils.print_paginated_result(share_entries, should_print_all)
Expand Down Expand Up @@ -1264,10 +1272,14 @@ def cluster_unshare(ctx, name, users, vdc, org, k8_runtime, cluster_id):
k8_runtime = shared_constants.ClusterEntityKind.TKG.value

client = ctx.obj['client']
# TODO(CLI): Check regarding why sysadmin check is excluded here
if not org:
ctx_profiles = ctx.obj['profiles']
org = ctx_profiles.get('org')
# Users should be explicit in their intent about the org on which the
# command needs to be executed.
is_system_user = client.is_sysadmin()
if not is_system_user and org is None:
org = ctx.obj['profiles'].get('org_in_use')
elif is_system_user and org is None:
raise Exception("Need to specify cluster org since logged in user is in system org") # noqa: E501

users_list = list(users)
cluster = Cluster(client, k8_runtime)
cluster.unshare_cluster(cluster_id, name, users_list, org, vdc)
Expand Down
3 changes: 2 additions & 1 deletion container_service_extension/client/command_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
cli_constants.GroupKey.OVDC: ['enable', 'disable', 'list', 'info']
},
vcd_client.ApiVersion.VERSION_35.value: {
cli_constants.GroupKey.CLUSTER: ['create', 'resize'],
cli_constants.GroupKey.CLUSTER: ['create', 'resize', 'share',
'share-list', 'unshare'],
cli_constants.GroupKey.OVDC: ['compute-policy', 'info']
},
vcd_client.ApiVersion.VERSION_36.value: {
Expand Down
24 changes: 14 additions & 10 deletions container_service_extension/client/de_cluster_tkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,16 +416,13 @@ def share_cluster(self, cluster_id, cluster_name, users: list,
f'level: {curr_access_level}')

# share TKG def entity
payload = {
shared_constants.AccessControlKey.GRANT_TYPE:
shared_constants.MEMBERSHIP_GRANT_TYPE,
shared_constants.AccessControlKey.ACCESS_LEVEL_ID:
access_level_id,
shared_constants.AccessControlKey.MEMBER_ID: None
}
acl_entry = common_models.ClusterAclEntry(
grantType=shared_constants.MEMBERSHIP_GRANT_TYPE,
accessLevelId=access_level_id,
memberId=None)
for _, user_id in name_to_id.items():
payload[shared_constants.AccessControlKey.MEMBER_ID] = user_id
acl_svc.share_def_entity(payload)
acl_entry.memberId = user_id
acl_svc.share_def_entity(acl_entry)

def unshare_cluster(self, cluster_id, cluster_name, users: list, org=None,
vdc=None):
Expand Down Expand Up @@ -461,6 +458,11 @@ def list_share_entries(self, cluster_id, cluster_name, org=None, vdc=None):

org_user_id_to_name_dict = vcd_utils.create_org_user_id_to_name_dict(
self._client, org)
# Consider system users if client is from system org
if self._client.is_sysadmin():
sys_org_user_id_to_name_dict = vcd_utils.create_org_user_id_to_name_dict( # noqa:E501
self._client, shared_constants.SYSTEM_ORG_NAME)
org_user_id_to_name_dict.update(sys_org_user_id_to_name_dict)
acl_svc = cluster_acl_svc.ClusterACLService(cluster_id, self._client)
page_num = result_count = 0
while True:
Expand All @@ -474,7 +476,9 @@ def list_share_entries(self, cluster_id, cluster_name, org=None, vdc=None):
acl_values = []
for entry in values:
acl_entry = common_models.ClusterAclEntry(**entry)
acl_entry.username = org_user_id_to_name_dict.get(acl_entry.memberId) # noqa: E501
# If there is no username found, the user must be a system
# user, so a generic name is shown
acl_entry.username = org_user_id_to_name_dict.get(acl_entry.memberId, shared_constants.SYSTEM_USER_GENERIC_NAME) # noqa: E501
acl_values.append(acl_entry.construct_filtered_dict(
include=CLUSTER_ACL_LIST_FIELDS))
result_count += len(values)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
CSE_SERVICE_NAME = 'cse'
CSE_SERVICE_NAMESPACE = 'cse'
EXCHANGE_TYPE = 'direct'
SYSTEM_ORG_NAME = 'system'

# DEPLOY RIGHTS; used by authorization framework to weed out unauthorized calls
CSE_NATIVE_DEPLOY_RIGHT_NAME = 'CSE NATIVE DEPLOY RIGHT'
Expand Down Expand Up @@ -707,3 +706,8 @@ class VdcNetworkInfoKey(str, Enum):

# Pagination constants for used IP addresses
USED_IP_ADDRESS_PAGE_SIZE = 10

# Context headers
TENANT_CONTEXT_HEADER = 'X-VMWARE-VCLOUD-TENANT-CONTEXT'
AUTH_CONTEXT_HEADER = 'X-VMWARE-VCLOUD-AUTH-CONTEXT'
VCLOUD_AUTHORIZATION_HEADER = 'X-vCloud-Authorization'
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ class ClusterEntityKind(Enum):
CSE_PAGINATION_FIRST_PAGE_NUMBER = 1
CSE_PAGINATION_DEFAULT_PAGE_SIZE = 25

# System org constants
SYSTEM_ORG_NAME = 'system'
SYSTEM_USER_GENERIC_NAME = 'system user'


@unique
class ServerAction(str, Enum):
Expand Down Expand Up @@ -189,6 +193,11 @@ class AccessControlKey(str, Enum):
USERNAME = 'username'


DEF_ENTITY_ACCESS_CONTROL_KEYS = [AccessControlKey.GRANT_TYPE,
AccessControlKey.ACCESS_LEVEL_ID,
AccessControlKey.MEMBER_ID]


@unique
class ClusterAclKey(str, Enum):
ACCESS_SETTING = 'accessSetting'
Expand Down
58 changes: 54 additions & 4 deletions container_service_extension/common/utils/pyvcloud_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from pyvcloud.vcd.vdc import VDC
import requests

import container_service_extension.common.constants.server_constants as server_constants # noqa: E501
import container_service_extension.common.constants.shared_constants as shared_constants # noqa: E501
from container_service_extension.common.utils.core_utils import extract_id_from_href # noqa: E501
from container_service_extension.common.utils.core_utils import NullPrinter
Expand Down Expand Up @@ -92,7 +91,7 @@ def get_sys_admin_client(api_version: Optional[str]):
log_bodies=log_wire)
credentials = vcd_client.BasicLoginCredentials(
server_config['vcd']['username'],
server_constants.SYSTEM_ORG_NAME,
shared_constants.SYSTEM_ORG_NAME,
server_config['vcd']['password'])
client.set_credentials(credentials)
return client
Expand Down Expand Up @@ -592,6 +591,26 @@ def get_ovdcs_by_page(
return vdc_results


def get_org_user_names(client: vcd_client.Client, org_name):
"""Get a set of user names in an org.
:param vcd_client.Client client: current client
:param str org_name: org name to search for users
:return: set of user names
:rtype: set
"""
org_href = client.get_org_by_name(org_name).get('href')
org = vcd_org.Org(client, org_href)
str_elem_users: list = org.list_users()
user_names: set = set()
for user_str_elem in str_elem_users:
curr_user_dict = to_dict(user_str_elem, exclude=[])
user_name = curr_user_dict['name']
user_names.add(user_name)
return user_names


def create_org_user_id_to_name_dict(client: vcd_client.Client, org_name):
"""Get a dictionary of users ids to user names.
Expand All @@ -603,9 +622,9 @@ def create_org_user_id_to_name_dict(client: vcd_client.Client, org_name):
"""
org_href = client.get_org_by_name(org_name).get('href')
org = vcd_org.Org(client, org_href)
users: list = org.list_users()
str_elem_users: list = org.list_users()
user_id_to_name_dict = {}
for user_str_elem in users:
for user_str_elem in str_elem_users:
curr_user_dict = to_dict(user_str_elem, exclude=[])
user_name = curr_user_dict['name']
user_urn = shared_constants.USER_URN_PREFIX + \
Expand All @@ -625,3 +644,34 @@ def get_user_role_name(client: vcd_client.Client):
:rtype: str
"""
return client.get_vcloud_session().get('roles')


def get_org_id_from_vdc_name(client: vcd_client.Client, vdc_name: str):
"""Return org id given vdc name.
:param vcd_client.Client client: vcd client
:param str vdc_name: vdc name
:return: org id, with no prefix, e.g., '12345'
:rtype: str
"""
if client.is_sysadmin():
resource_type = vcd_client.ResourceType.ADMIN_ORG_VDC.value
else:
resource_type = vcd_client.ResourceType.ORG_VDC.value
query = client.get_typed_query(
query_type_name=resource_type,
query_result_format=vcd_client.QueryResultFormat.ID_RECORDS,
equality_filter=('name', vdc_name))
records = list(query.execute())
if len(records) == 0:
return None

# Process org id
if client.is_sysadmin():
org_urn_id = records[0].attrib['org']
else:
org_name = records[0].attrib['orgName']
org_resource = client.get_org_by_name(org_name)
org_urn_id = org_resource.attrib['id']
return extract_id(org_urn_id)
3 changes: 1 addition & 2 deletions container_service_extension/installer/config_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@

from container_service_extension.common.constants.server_constants import \
CONFIG_DECRYPTION_ERROR_MSG
from container_service_extension.common.constants.server_constants import SYSTEM_ORG_NAME # noqa: E501
from container_service_extension.common.constants.server_constants import \
VCENTER_LOGIN_ERROR_MSG
from container_service_extension.common.constants.server_constants import VERSION_V1 # noqa: E501
from container_service_extension.common.constants.shared_constants import \
SUPPORTED_VCD_API_VERSIONS
SUPPORTED_VCD_API_VERSIONS, SYSTEM_ORG_NAME
from container_service_extension.common.utils.core_utils import check_file_permissions # noqa: E501
from container_service_extension.common.utils.core_utils import check_keys_and_value_types # noqa: E501
from container_service_extension.common.utils.core_utils import get_duplicate_items_in_list # noqa: E501
Expand Down
10 changes: 5 additions & 5 deletions container_service_extension/installer/configure_cse.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def check_cse_installation(config, msg_update_callback=utils.NullPrinter()):
log_headers=log_wire,
log_bodies=log_wire)
credentials = BasicLoginCredentials(config['vcd']['username'],
server_constants.SYSTEM_ORG_NAME,
shared_constants.SYSTEM_ORG_NAME,
config['vcd']['password'])
client.set_credentials(credentials)

Expand Down Expand Up @@ -281,7 +281,7 @@ def install_cse(config_file_name, config, skip_template_creation,
log_headers=log_wire,
log_bodies=log_wire)
credentials = BasicLoginCredentials(config['vcd']['username'],
server_constants.SYSTEM_ORG_NAME,
shared_constants.SYSTEM_ORG_NAME,
config['vcd']['password'])
client.set_credentials(credentials)
msg = f"Connected to vCD as system administrator: " \
Expand Down Expand Up @@ -468,7 +468,7 @@ def install_template(template_name, template_revision, config_file_name,
log_headers=log_wire,
log_bodies=log_wire)
credentials = BasicLoginCredentials(config['vcd']['username'],
server_constants.SYSTEM_ORG_NAME,
shared_constants.SYSTEM_ORG_NAME,
config['vcd']['password'])
client.set_credentials(credentials)
msg = f"Connected to vCD as system administrator: " \
Expand Down Expand Up @@ -637,7 +637,7 @@ def upgrade_cse(config_file_name, config, skip_template_creation,
log_headers=log_wire,
log_bodies=log_wire)
credentials = BasicLoginCredentials(config['vcd']['username'],
server_constants.SYSTEM_ORG_NAME,
shared_constants.SYSTEM_ORG_NAME,
config['vcd']['password'])
client.set_credentials(credentials)
msg = f"Connected to vCD as system administrator: " \
Expand Down Expand Up @@ -1241,7 +1241,7 @@ def _register_def_schema(client: Client,
# recreated and newly added rights are effective for the user.
client.logout()
credentials = BasicLoginCredentials(config['vcd']['username'],
server_constants.SYSTEM_ORG_NAME, # noqa: E501
shared_constants.SYSTEM_ORG_NAME, # noqa: E501
config['vcd']['password'])
client.set_credentials(credentials)
except cse_exception.DefNotSupportedException:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from container_service_extension.common.constants.server_constants import MQTT_EXTENSION_VENDOR # noqa: E501
from container_service_extension.common.constants.server_constants import MQTT_EXTENSION_VERSION # noqa: E501
from container_service_extension.common.constants.server_constants import MQTTExtKey # noqa: E501
from container_service_extension.common.constants.server_constants import SYSTEM_ORG_NAME # noqa: E501
from container_service_extension.common.constants.shared_constants import SYSTEM_ORG_NAME # noqa: E501
from container_service_extension.common.utils.core_utils import NullPrinter
from container_service_extension.common.utils.server_utils import should_use_mqtt_protocol # noqa: E501
from container_service_extension.lib.telemetry.constants import COLLECTOR_ID
Expand Down
Loading

0 comments on commit a41ecd9

Please sign in to comment.