Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VCDA-2578, VCDA-2108, VCDA-2262] Cluster share fix and system user cluster sharing #1083

Merged
merged 14 commits into from
Jun 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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