608 lines
24 KiB
Python
608 lines
24 KiB
Python
# Copyright (c) 2024-2025 Broadcom. All Rights Reserved.
|
|
# The term "Broadcom" refers to Broadcom Inc.
|
|
# and/or its subsidiaries.
|
|
|
|
import ldap3 as ldap
|
|
import logging
|
|
import re
|
|
from lib import certificate_utils as certutil
|
|
from lib.environment import Environment
|
|
from lib.certificate_utils import build_pem_certificate
|
|
from lib.command_runner import CommandRunner
|
|
from lib.console import print_task, print_text_error
|
|
from lib.host_utils import VcVersion, get_hostname, get_vc_version
|
|
from lib.ldap_utils import Ldap, LdapException, get_user_dn
|
|
from lib.text_utils import TextFilter
|
|
from lib.console import (print_task_status)
|
|
from lib.exceptions import OperationFailed, CommandExecutionError
|
|
|
|
|
|
DIR_CLI = '/usr/lib/vmware-vmafd/bin/dir-cli'
|
|
VDCADMINTOOL = '/usr/lib/vmware-vmdir/bin/vdcadmintool'
|
|
cache_ca_keyids = None
|
|
cache_ca_certificate_map = dict()
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def get_ldap_connection(use_machine_account=False):
|
|
env = Environment.get_environment()
|
|
if use_machine_account:
|
|
user_dn = env.get_value('VMDIR_MACHINE_ACCOUNT_DN')
|
|
user_password = env.get_value('VMDIR_MACHINE_ACCOUNT_PASSWORD')
|
|
else:
|
|
sso_username = env.get_value('SSO_USERNAME')
|
|
user_password = env.get_value('SSO_PASSWORD')
|
|
user_dn = get_user_dn(sso_username)
|
|
hostname = get_hostname()
|
|
|
|
return Ldap.open_ldap_connection(node=hostname, user_dn=user_dn, password=user_password)
|
|
|
|
|
|
def close_ldap_connection(ldap_connection):
|
|
Ldap.close_ldap_connection(ldap_connection)
|
|
|
|
|
|
def perform_ldap_search(search_base, search_filter, search_attributes, search_scope=ldap.SUBTREE,
|
|
use_machine_account=False, throw_exception=False):
|
|
"""
|
|
Utility method to perform LDAP search
|
|
|
|
:param search_base: LDAP search base DN
|
|
:param search_filter: LDAP search filter
|
|
:param search_attributes: LDAP search attribute
|
|
:param search_scope: LDAP search scope (default: ldap.SUBTREE)
|
|
:param use_machine_account: Flag to use VMDir machine account instead of SSO user account
|
|
:param throw_exception: When LDAP search fails, throw exception instead of empty result
|
|
:return: list of matching object, as dict with keys from search_attributes paramerter
|
|
"""
|
|
results = []
|
|
connection = None
|
|
try:
|
|
connection = get_ldap_connection(use_machine_account)
|
|
if not Ldap.ldap_search(connection, search_base, search_filter, search_scope, search_attributes):
|
|
logger.error("Unable to perform LDAP search base_dn={}, filter={}" \
|
|
.format(search_base, search_filter))
|
|
if throw_exception:
|
|
raise LdapException(connection.result['result'], connection.result['description'])
|
|
else:
|
|
return results
|
|
if connection.result:
|
|
for entry in connection.response:
|
|
attributes = entry['attributes']
|
|
if 'dn' in search_attributes and not attributes['dn']:
|
|
attributes['dn'] = entry['dn'].replace(', cn=', ',cn=')
|
|
results.append(attributes)
|
|
finally:
|
|
if connection:
|
|
close_ldap_connection(connection)
|
|
|
|
return results
|
|
|
|
|
|
def perform_ldap_add(service_dn, object_class, attributes, use_machine_account=False):
|
|
"""
|
|
A wrapper for LDAP modify operation
|
|
"""
|
|
connection = None
|
|
try:
|
|
connection = get_ldap_connection(use_machine_account)
|
|
if not Ldap.ldap_add(connection, service_dn, object_class, attributes):
|
|
logger.error("Unable to add LDAP entry dn={}, attributes={}".format(service_dn, str(attributes)))
|
|
raise LdapException(connection.result['result'], connection.result['description'])
|
|
finally:
|
|
if connection:
|
|
close_ldap_connection(connection)
|
|
|
|
|
|
def perform_ldap_modify(service_dn, attribute, value, operation=ldap.MODIFY_REPLACE,
|
|
use_machine_account=False):
|
|
"""
|
|
A wrapper for LDAP modify operation
|
|
"""
|
|
connection = None
|
|
try:
|
|
connection = get_ldap_connection(use_machine_account)
|
|
if not Ldap.ldap_modify(connection, service_dn, attribute, operation, value):
|
|
logger.error("Unable to modify LDAP entry dn={}, attribute={}".format(service_dn, attribute))
|
|
raise LdapException(connection.result['result'], connection.result['description'])
|
|
finally:
|
|
if connection:
|
|
close_ldap_connection(connection)
|
|
|
|
|
|
def perform_ldap_delete(service_dn, use_machine_account=False):
|
|
"""
|
|
A wrapper for LDAP delete operation
|
|
"""
|
|
connection = None
|
|
try:
|
|
connection = get_ldap_connection(use_machine_account)
|
|
if not Ldap.ldap_delete(connection, service_dn):
|
|
logger.error("Unable to delete LDAP entry dn={}".format(service_dn))
|
|
raise LdapException(connection.result['result'], connection.result['description'])
|
|
finally:
|
|
if connection:
|
|
close_ldap_connection(connection)
|
|
|
|
|
|
def get_solution_users():
|
|
"""
|
|
Get solution users list from VMDir via LDAP
|
|
|
|
:return: list of solution users
|
|
"""
|
|
env = Environment.get_environment()
|
|
machine_id = env.get_value('MACHINE_ID')
|
|
domain_dn = env.get_value('SSO_DOMAIN_DN')
|
|
|
|
postfix = "-{}".format(machine_id)
|
|
search_base = "cn=ServicePrincipals,{}".format(domain_dn)
|
|
search_filter = "(&(objectClass=vmwServicePrincipal)(cn=*{}))".format(postfix)
|
|
search_attributes = ['cn']
|
|
results = perform_ldap_search(search_base, search_filter, search_attributes)
|
|
return [entry['cn'].replace(postfix, '') for entry in results]
|
|
|
|
|
|
def get_sts_tenant_certificates(include_tenant_credential=True,
|
|
include_certificate_chain=True):
|
|
"""
|
|
Get STS tenant user certificates
|
|
:return: dict(cn: certificate list)
|
|
"""
|
|
env = Environment.get_environment()
|
|
sso_domain = env.get_value('SSO_DOMAIN')
|
|
domain_dn = env.get_value('SSO_DOMAIN_DN')
|
|
|
|
base_dn = "cn={},cn=Tenants,cn=IdentityManager,cn=Services,{}".format(sso_domain, domain_dn)
|
|
if include_certificate_chain and include_tenant_credential:
|
|
ldap_filter = \
|
|
'(|(objectClass=vmwSTSTenantCredential)(&(objectclass=vmwSTSTenantTrustedCertificateChain)(cn=TrustedCertChain*)))'
|
|
elif include_tenant_credential:
|
|
ldap_filter = '(objectClass=vmwSTSTenantCredential)'
|
|
elif include_certificate_chain:
|
|
ldap_filter = '(&(objectclass=vmwSTSTenantTrustedCertificateChain)(cn=TrustedCertChain*))'
|
|
else:
|
|
return None
|
|
|
|
ldap_attributes = ['cn', 'userCertificate']
|
|
results = perform_ldap_search(base_dn, ldap_filter, ldap_attributes)
|
|
|
|
tenant_certs = dict()
|
|
for entry in results:
|
|
tenant_certs[entry['cn']] = [build_pem_certificate(cert) for cert in entry['userCertificate']]
|
|
|
|
return tenant_certs
|
|
|
|
|
|
def get_solution_user_certificate(solution_user):
|
|
"""
|
|
Get solution user certificate from VMDir via LDAP
|
|
|
|
:param solution_user: solution user
|
|
:return: Solution user certificate in PEM format
|
|
"""
|
|
env = Environment.get_environment()
|
|
machine_id = env.get_value('MACHINE_ID')
|
|
domain_dn = env.get_value('SSO_DOMAIN_DN')
|
|
|
|
base_dn = "cn={}-{},cn=ServicePrincipals,{}".format(solution_user, machine_id, domain_dn)
|
|
ldap_filter = '(objectClass=vmwServicePrincipal)'
|
|
ldap_attributes = ['userCertificate']
|
|
results = perform_ldap_search(base_dn, ldap_filter, ldap_attributes, search_scope=ldap.BASE)
|
|
certs = []
|
|
for entry in results:
|
|
for cert in entry['userCertificate']:
|
|
# only expect single certificate
|
|
certs.append(build_pem_certificate(cert))
|
|
return '\n'.join(certs)
|
|
|
|
|
|
def get_all_ca_subject_keyids(use_cache=False):
|
|
"""
|
|
Get list of subject keyId of trusted CA certificates via 'dir-cli trustedcert list' output
|
|
The result will be cached
|
|
|
|
:param use_cache: If True, the previous cached result will be used (default: True)
|
|
:return: list of subject keyIds of trusted CA certificates
|
|
"""
|
|
global cache_ca_keyids
|
|
if use_cache and cache_ca_keyids is not None:
|
|
return cache_ca_keyids
|
|
|
|
env = Environment.get_environment()
|
|
sso_username = env.get_value('SSO_USERNAME')
|
|
sso_password = env.get_value('SSO_PASSWORD')
|
|
args = [DIR_CLI, 'trustedcert', 'list', '--login', sso_username, '--password', sso_password]
|
|
ret, stdout, _ = CommandRunner(*args).run()
|
|
cache_ca_keyids = TextFilter(stdout).start_with('CN(id):').cut(':', [1]).remove_white_spaces().get_lines()
|
|
return cache_ca_keyids
|
|
|
|
|
|
def get_ca_certificate(subject_keyid, use_cache=True):
|
|
"""
|
|
Get CA certificate in VMDir via 'dir-cli trustedcert get' command output
|
|
|
|
:param subject_keyid: the certificate' subject keyId
|
|
:param use_cache: if True, the previous cached result will be used instead
|
|
:return: trusted CA certificate in PEM format
|
|
"""
|
|
global cache_ca_certificate_map
|
|
if not subject_keyid:
|
|
return None
|
|
if use_cache:
|
|
cert_cache = cache_ca_certificate_map.get(subject_keyid)
|
|
if cert_cache:
|
|
return cert_cache
|
|
|
|
env = Environment.get_environment()
|
|
sso_username = env.get_value('SSO_USERNAME')
|
|
sso_password = env.get_value('SSO_PASSWORD')
|
|
args = [DIR_CLI, 'trustedcert', 'get', '--login', sso_username, '--password', sso_password,
|
|
'--id', subject_keyid, '--outcert', '/dev/stdout']
|
|
ret, stdout, _ = CommandRunner(*args).run()
|
|
lines = TextFilter(stdout).match_block('-----BEGIN CERTIFICATE-----',
|
|
'-----END CERTIFICATE-----').get_lines()
|
|
pem_cert = '\n'.join(lines)
|
|
cache_ca_certificate_map[subject_keyid] = pem_cert
|
|
return pem_cert
|
|
|
|
|
|
def get_all_ca_certificates():
|
|
"""
|
|
Get all trusted CA certificates in VMDir via dir-cli command)
|
|
|
|
:return: list of CA certificates in PEM format
|
|
"""
|
|
subject_keyids = get_all_ca_subject_keyids(False)
|
|
certs = []
|
|
for subject_keyid in subject_keyids:
|
|
pem_cert = get_ca_certificate(subject_keyid)
|
|
certs.append(pem_cert)
|
|
return certs, subject_keyids
|
|
|
|
|
|
def get_service_principals():
|
|
"""
|
|
Get service principal list from VMDir via dir-cli
|
|
|
|
:return: list of service principals
|
|
"""
|
|
env = Environment.get_environment()
|
|
sso_username = env.get_value('SSO_USERNAME')
|
|
sso_password = env.get_value('SSO_PASSWORD')
|
|
args = [DIR_CLI, 'service', 'list', '--login', sso_username, '--password', sso_password]
|
|
ret, stdout, _ = CommandRunner(*args).run()
|
|
return TextFilter(stdout).cut(fields=[1]).get_lines()
|
|
|
|
|
|
def init_env_identity_source():
|
|
env = Environment.get_environment()
|
|
if env.get_map().get('SSO_USERNAME') is None or \
|
|
env.get_value('EXTERNAL_IDENTITY_SOURCE_CONFIGURED') is not None:
|
|
return
|
|
|
|
logger.info('Checking identity source settings')
|
|
identity_sources = get_identity_sources()
|
|
source_types = [item['type'] for item in identity_sources]
|
|
logger.info("Identity sources: {}".format(source_types))
|
|
|
|
env.set_value('EXTERNAL_IDENTITY_SOURCE_CONFIGURED', len(source_types) > 0)
|
|
|
|
|
|
def get_identity_sources(use_machine_account=False):
|
|
"""
|
|
Get the identity sources settings
|
|
|
|
return: list of configured identity source represented in the following dict object:
|
|
{
|
|
"type": one of ('AD over LDAP', 'ADFS', 'OpenLDAP')
|
|
"domain_name": domain name
|
|
"certificates": CA certificate for this identity source
|
|
}
|
|
"""
|
|
logger.info('Obtaining identity source settings')
|
|
env = Environment.get_environment()
|
|
sso_domain = env.get_value('SSO_DOMAIN')
|
|
domain_dn = env.get_value('SSO_DOMAIN_DN')
|
|
search_list = [
|
|
('AD over LDAP', 'IdentityProviders', 'IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING'),
|
|
('ADFS', 'VCIdentityProviders', 'IDENTITY_STORE_TYPE_LDAP_WITH_AD_MAPPING'),
|
|
('OpenLDAP', 'IdentityProviders', 'IDENTITY_STORE_TYPE_LDAP')
|
|
]
|
|
|
|
identity_sources = []
|
|
connection = None
|
|
try:
|
|
connection = get_ldap_connection(use_machine_account=use_machine_account)
|
|
ldap_attributes = ['vmwSTSDomainName', 'userCertificate']
|
|
for type_name, provider_cn, provider_type in search_list:
|
|
base_dn = "cn={},cn={},cn=Tenants,cn=IdentityManager,cn=Services,{}"\
|
|
.format(provider_cn, sso_domain, domain_dn)
|
|
ldap_filter = "(vmwSTSProviderType={})".format(provider_type)
|
|
if not Ldap.ldap_search(connection, base_dn, ldap_filter, ldap.SUBTREE, ldap_attributes):
|
|
# this search may return noSuchObject due to an invalid base_dn
|
|
if connection.result['result'] == 32:
|
|
continue
|
|
logger.error('Unable to perform LDAP search for the identity source setting')
|
|
raise LdapException(connection.result['result'], connection.result['description'])
|
|
if not connection.result:
|
|
continue
|
|
for entry in connection.response:
|
|
attributes = entry['attributes']
|
|
result = dict()
|
|
result['type'] = type_name
|
|
result['domain_name'] = attributes['vmwSTSDomainName']
|
|
certs = []
|
|
for cert in attributes['userCertificate']:
|
|
# only expect single certificate
|
|
certs.append(build_pem_certificate(cert))
|
|
result['certificates'] = certs
|
|
identity_sources.append(result)
|
|
logger.info("Identity source: type={}, domain={}".format(type_name, result['domain_name']))
|
|
finally:
|
|
if connection:
|
|
close_ldap_connection(connection)
|
|
|
|
return identity_sources
|
|
|
|
|
|
def get_sso_domain_nodes():
|
|
logger.info('Obtaining SSO domain nodes')
|
|
domain_dn = Environment.get_environment().get_value('SSO_DOMAIN_DN')
|
|
base_dn_list = ["ou=Domain Controllers,{}".format(domain_dn), "ou=Computers,{}".format(domain_dn)]
|
|
ldap_filter = '(objectClass=computer)'
|
|
ldap_attributes = ['cn']
|
|
nodes = []
|
|
for base_dn in base_dn_list:
|
|
results = perform_ldap_search(base_dn, ldap_filter, ldap_attributes)
|
|
for entry in results:
|
|
node = entry['cn']
|
|
if node not in nodes:
|
|
nodes.append(node)
|
|
logger.info("Found node: {}".format(node))
|
|
|
|
return nodes
|
|
|
|
|
|
def get_all_lookup_service_endpoints(search_base=None):
|
|
"""
|
|
Get all endpoint entries
|
|
:return:
|
|
"""
|
|
logger.info('Obtaining all endpoints')
|
|
domain_dn = Environment.get_environment().get_value('SSO_DOMAIN_DN')
|
|
if search_base is None:
|
|
search_base = "cn=Sites,cn=Configuration,{}".format(domain_dn)
|
|
search_filter = '(|(objectclass=vmwLKUPServiceEndpoint)(objectClass=vmwLKUPEndpointRegistration))'
|
|
search_attributes = ['dn', 'objectClass', 'vmwLKUPURI', 'vmwLKUPEndpointSslTrust', 'vmwLKUPSslTrustAnchor']
|
|
return perform_ldap_search(search_base, search_filter, search_attributes)
|
|
|
|
|
|
def get_node_trust_anchors(fqdn_or_ip):
|
|
"""
|
|
Get SSL trust anchors by filtering the endpoint URI using {fqdn_or_ip}
|
|
:param fqdn_or_ip:
|
|
:return:
|
|
"""
|
|
logger.info("Obtaining node trust anchors: fqdn_or_ip: {}".format(fqdn_or_ip))
|
|
trust_anchors = []
|
|
pattern = "^https://{0}:.*|^https://{0}/.*".format(fqdn_or_ip)
|
|
endpoints = get_all_lookup_service_endpoints()
|
|
for endpoint in endpoints:
|
|
if not re.match(pattern, endpoint['vmwLKUPURI']):
|
|
continue
|
|
for cert in sum([endpoint['vmwLKUPEndpointSslTrust'], endpoint['vmwLKUPSslTrustAnchor']], []):
|
|
pem_cert = certutil.build_pem_certificate(cert)
|
|
if pem_cert and pem_cert not in trust_anchors:
|
|
trust_anchors.append(pem_cert)
|
|
logger.info('Trust anchors found for {}: {}'.format(fqdn_or_ip, trust_anchors))
|
|
return trust_anchors
|
|
|
|
|
|
def get_endpoint_service_type(service_id):
|
|
domain_dn = Environment.get_environment().get_value('SSO_DOMAIN_DN')
|
|
search_base = "cn=Sites,cn=Configuration,{}".format(domain_dn)
|
|
search_filter = "(cn={})".format(service_id)
|
|
search_attributes = ['vmwLKUPType']
|
|
result = perform_ldap_search(search_base, search_filter, search_attributes)
|
|
if result:
|
|
return result[0]['vmwLKUPType']
|
|
|
|
search_filter = '(objectClass=vmwLKUPService)'
|
|
search_attributes = ['dn', 'vmwLKUPServiceType']
|
|
result = perform_ldap_search(search_base, search_filter, search_attributes)
|
|
for entry in result:
|
|
if service_id in entry['dn']:
|
|
# remove prefix 'urn:'
|
|
return entry['vmwLKUPServiceType'][4:]
|
|
return ''
|
|
|
|
|
|
def get_registered_vcenters():
|
|
"""
|
|
Get registered VCenters
|
|
:return: list of tuple (deployment_node_id, node_dn)
|
|
"""
|
|
logger.info('Obtaining list of registered vCenters')
|
|
domain_dn = Environment.get_environment().get_value('SSO_DOMAIN_DN')
|
|
base_dn = "cn=Sites,cn=Configuration,{}".format(domain_dn)
|
|
ldap_filter = '(vmwLKUPType=vcenterserver)'
|
|
ldap_attributes = ['vmwLKUPDeploymentNodeId', 'dn']
|
|
results = perform_ldap_search(base_dn, ldap_filter, ldap_attributes)
|
|
return [(entry['vmwLKUPDeploymentNodeId'], entry['dn']) for entry in results]
|
|
|
|
|
|
def get_endpoint_registrations(base_dn):
|
|
ldap_filter = '(objectClass=vmwLKUPEndpointRegistration)'
|
|
ldap_attributes = ['vmwLKUPURI']
|
|
results = perform_ldap_search(base_dn, ldap_filter, ldap_attributes)
|
|
return [entry['vmwLKUPURI'] for entry in results]
|
|
|
|
|
|
def init_env_cac():
|
|
env = Environment.get_environment()
|
|
# if env.get_map().get('SSO_USERNAME') is None or \
|
|
# env.get_value('CAC_CONFIGURED') is not None:
|
|
# return
|
|
if env.get_value('CAC_CONFIGURED') is not None:
|
|
return
|
|
|
|
vc_version = get_vc_version()
|
|
if vc_version >= VcVersion.V9:
|
|
logger.info('SmartCards are not supported since version {}'.format(VcVersion.V9.value))
|
|
env.set_value('CAC_CONFIGURED', False)
|
|
return
|
|
|
|
logger.info('Checking SmartCard Authentication settings')
|
|
sso_domain = env.get_value('SSO_DOMAIN')
|
|
domain_dn = env.get_value('SSO_DOMAIN_DN')
|
|
search_base = "cn={},cn=Tenants,cn=IdentityManager,cn=Services,{}".format(sso_domain, domain_dn)
|
|
search_filter = '(objectclass=vmwSTSTenant)'
|
|
search_attributes = ['vmwSTSAuthnTypes']
|
|
results = perform_ldap_search(search_base, search_filter, search_attributes, use_machine_account=True)
|
|
is_cac_configured = False
|
|
logger.info('LDAP search results: {}'.format(results))
|
|
for entry in results:
|
|
if entry['vmwSTSAuthnTypes'] == 4 or 4 in entry['vmwSTSAuthnTypes']:
|
|
is_cac_configured = True
|
|
env.set_value('CAC_CONFIGURED', is_cac_configured)
|
|
|
|
|
|
def get_smart_card_issuing_ca_certs():
|
|
logger.info('Obtaining SmartCard issuing CA certificates')
|
|
env = Environment.get_environment()
|
|
sso_domain = env.get_value('SSO_DOMAIN')
|
|
domain_dn = env.get_value('SSO_DOMAIN_DN')
|
|
search_base = \
|
|
"cn=DefaultClientCertCAStore,cn=ClientCertAuthnTrustedCAs,cn=Default,cn=ClientCertificatePolicies,"\
|
|
"cn={},cn=Tenants,cn=IdentityManager,cn=Services,{}".format(sso_domain, domain_dn)
|
|
search_filter = '(objectClass=vmwSTSTenantTrustedCertificateChain)'
|
|
search_attributes = ['userCertificate']
|
|
|
|
result = perform_ldap_search(search_base, search_filter, search_attributes, use_machine_account=True)
|
|
certs = []
|
|
for entry in result:
|
|
certs.extend(build_pem_certificate(cert) for cert in entry['userCertificate'])
|
|
|
|
return certs
|
|
|
|
|
|
def get_all_sso_sites():
|
|
domain_dn = Environment.get_environment().get_value('SSO_DOMAIN_DN')
|
|
search_base = "cn=Sites,cn=Configuration,{}".format(domain_dn)
|
|
search_filter = '(objectClass=*)'
|
|
search_attributes = ['cn']
|
|
result = perform_ldap_search(search_base, search_filter, search_attributes, search_scope=ldap.LEVEL)
|
|
return [entry['cn'] for entry in result]
|
|
|
|
|
|
def unpublish_trusted_certificate(cert_file):
|
|
"""
|
|
Unpublish certificate in VMDir
|
|
:param cert_file: Certificate file to unpublish
|
|
"""
|
|
env = Environment.get_environment()
|
|
sso_username = env.get_value('SSO_USERNAME')
|
|
sso_password = env.get_value('SSO_PASSWORD')
|
|
CommandRunner(DIR_CLI, 'trustedcert', 'unpublish', '--login', sso_username, '--password',
|
|
sso_password, '--cert', cert_file, expected_return_code=0).run()
|
|
|
|
|
|
def publish_trusted_certificate(cert_file, is_chain=False):
|
|
"""
|
|
Publish certificate in VMDir
|
|
:param cert_file: Certificate file to unpublish
|
|
:param is_chain: Publish all certificate in chain
|
|
"""
|
|
env = Environment.get_environment()
|
|
sso_username = env.get_value('SSO_USERNAME')
|
|
sso_password = env.get_value('SSO_PASSWORD')
|
|
args = [DIR_CLI, 'trustedcert', 'publish', '--login', sso_username, '--password', sso_password,
|
|
'--cert', cert_file]
|
|
if is_chain:
|
|
args.append('--chain')
|
|
CommandRunner(*args, expected_return_code=0).run()
|
|
|
|
|
|
def remove_ca_certificate_from_ldap(subject_keyid):
|
|
domain_dn = Environment.get_environment().get_value('SSO_DOMAIN_DN')
|
|
cert_dn = "cn={},cn=Certificate-Authorities,cn=Configuration,{}".format(subject_keyid, domain_dn)
|
|
perform_ldap_delete(cert_dn)
|
|
|
|
|
|
def get_sddc_manager():
|
|
# SDDC_MANAGER=$($LDAP_SEARCH -LLL -h $PSC_LOCATION -b
|
|
# "cn=$SSO_DOMAIN,cn=Tenants,cn=IdentityManager,cn=Services,$VMDIR_DOMAIN_DN"
|
|
# -D "$VMDIR_MACHINE_ACCOUNT_DN" -y $STAGE_DIR/.machine-account-password '(objectclass=vmwSTSTenant)'
|
|
# vmwSTSLogonBanner | tr -d '\n' | awk -F'::' '{print $NF}' | tr -d ' ' | base64 -d 2>/dev/null | grep 'SDDC Manager' | awk -F '[()]' '{print $2}' | grep -v '^$')
|
|
env = Environment.get_environment()
|
|
sso_domain = env.get_value('SSO_DOMAIN')
|
|
domain_dn = env.get_value('SSO_DOMAIN_DN')
|
|
search_base = "cn={},cn=Tenants,cn=IdentityManager,cn=Services,{}".format(sso_domain, domain_dn)
|
|
search_filter = '(objectClass=vmwSTSTenant)'
|
|
search_attributes = ['vmwSTSLogonBanner']
|
|
result = perform_ldap_search(search_base, search_filter, search_attributes, search_scope=ldap.LEVEL)
|
|
return [entry['cn'] for entry in result]
|
|
|
|
|
|
def update_solution_user_certificate_in_vmdir(soluser, cert_file):
|
|
env = Environment.get_environment()
|
|
sso_username = env.get_value('SSO_USERNAME')
|
|
sso_password = env.get_value('SSO_PASSWORD')
|
|
machine_id = env.get_value('MACHINE_ID')
|
|
args = [DIR_CLI, 'service', 'update', '--name', f"{soluser}-{machine_id}", '--cert',
|
|
cert_file, '--login', sso_username, '--password', sso_password]
|
|
try:
|
|
CommandRunner(*args, expected_return_code=0).run_and_get_output()
|
|
except CommandExecutionError:
|
|
error_message = f"Unable to update {soluser}-{machine_id} solution user certificate in VMDir"
|
|
logger.error(error_message)
|
|
raise OperationFailed(error_message)
|
|
|
|
|
|
# ------------------------------
|
|
# Replace a Solution User certificate in VMDir
|
|
# ------------------------------
|
|
def replace_service_principal_certificates(soluser, cert_file):
|
|
print_task(f" {soluser}")
|
|
update_solution_user_certificate_in_vmdir(soluser, cert_file)
|
|
print_task_status("OK")
|
|
|
|
|
|
def verify_service_principals():
|
|
print_task('Verifying Service Principal entries exist')
|
|
service_principals = get_service_principals()
|
|
if service_principals:
|
|
env = Environment.get_environment()
|
|
machine_id = env.get_value('MACHINE_ID')
|
|
solution_users = env.get_value('SOLUTION_USERS')
|
|
missing_service_principals = []
|
|
for solution_user in solution_users:
|
|
service_principal = "{}-{}".format(solution_user, machine_id)
|
|
if service_principal not in service_principals:
|
|
missing_service_principals.append(service_principal)
|
|
|
|
if missing_service_principals:
|
|
print_text_error('ERROR')
|
|
print_text_error("\n------------------------!!! Attention !!!------------------------ ")
|
|
print_text_error('The following Service Principal entries are missing:')
|
|
for sp in missing_service_principals:
|
|
print_text_error(" - {}".format(sp))
|
|
|
|
print_text_error('\nPlease refer to the following Knowledge Base article')
|
|
print_text_error('on using the lsdoctor utility to recreate the missing')
|
|
print_text_error('Solution User/Service Principal entries:')
|
|
print_text_error('https://knowledge.broadcom.com/external/article/320837/using-the-lsdoctor-tool.html')
|
|
else:
|
|
print_task_status("OK")
|
|
else:
|
|
print_text_error('Could not get list of Service Principal entries from VMware Directory')
|
|
|
|
|
|
def get_vmdir_state():
|
|
state_output = CommandRunner(VDCADMINTOOL, command_input='6', expected_return_code=0).run_and_get_output()
|
|
logger.info('VMware Directory state: {}'.format(state_output))
|
|
service_state = TextFilter(state_output).contain('VmDir State').cut('-', [1]).get_text().strip()
|
|
return service_state
|