class CustomFolderHelper(object): """ Shared code for custom (user-defined) folders in the model. These require special handling, since they do not have alias definitions. """ __class_name = 'CustomFolderHelper' __cipher_text_prefixes = ["{AES}", "{AES-256}"] def __init__(self, aliases, logger, model_context, exception_type): self.logger = logger self.model_context = model_context self.exception_type = exception_type self.alias_helper = AliasHelper(aliases, self.logger, self.exception_type) self.weblogic_helper = WebLogicHelper(self.logger) self.wlst_helper = WlstHelper(self.logger, self.exception_type) def update_security_folder(self, location, model_type, model_subtype, model_name, model_nodes): """ Update the specified security model nodes in WLST. :param location: the location for the provider :param model_type: the type of the provider to be updated, such as AuthenticationProvider :param model_subtype: the subtype of the provider to be updated, such as 'custom.my.CustomIdentityAsserter' :param model_name: the name of the provider to be updated, such as 'My custom IdentityAsserter' :param model_nodes: a child model nodes of the provider to be updated :raises: BundleAwareException of the specified type: if an error occurs """ _method_name = 'update_security_folder' location_path = self.alias_helper.get_model_folder_path(location) self.logger.entering(location_path, model_subtype, model_name, class_name=self.__class_name, method_name=_method_name) self.logger.info('WLSDPLY-12124', model_type, model_name, model_subtype, location_path, class_name=self.__class_name, method_name=_method_name) create_path = self.alias_helper.get_wlst_subfolders_path(location) self.wlst_helper.cd(create_path) # create the MBean using the model type, name, and subtype type_location = LocationContext(location).append_location(model_type) token = self.alias_helper.get_name_token(type_location) type_location.add_name_token(token, model_name) mbean_type = self.alias_helper.get_wlst_mbean_type(type_location) self.wlst_helper.create(model_name, model_subtype, mbean_type) provider_path = self.alias_helper.get_wlst_attributes_path( type_location) provider_mbean = self.wlst_helper.cd(provider_path) interface_name = model_subtype + 'MBean' bean_info = self.weblogic_helper.get_bean_info_for_interface( interface_name) if bean_info is None: ex = exception_helper.create_exception(self.exception_type, 'WLSDPLY-12125', interface_name) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex property_map = dict() for property_descriptor in bean_info.getPropertyDescriptors(): self.logger.finer('WLSDPLY-12126', str(property_descriptor), class_name=self.__class_name, method_name=_method_name) property_map[property_descriptor.getName()] = property_descriptor for model_key in model_nodes: model_value = model_nodes[model_key] property_descriptor = property_map.get(model_key) if not property_descriptor: ex = exception_helper.create_exception(self.exception_type, 'WLSDPLY-12128', model_key) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex # find the setter method for the attribute method = property_descriptor.writeMethod if not method: # this must be a read-only attribute, just log it and continue with next attribute self.logger.info('WLSDPLY-12129', str(model_key), class_name=self.__class_name, method_name=_method_name) continue self.logger.finer('WLSDPLY-12127', str(model_key), str(model_value), class_name=self.__class_name, method_name=_method_name) # determine the data type from the set method parameter_types = method.getParameterTypes() parameter_count = len(parameter_types) if parameter_count != 1: ex = exception_helper.create_exception(self.exception_type, 'WLSDPLY-12130', model_key, parameter_count) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex # if the property requires encryption, and the value is not encrypted, # encrypt the value with domain encryption. requires_encrypted = property_descriptor.getValue('encrypted') if requires_encrypted and not self.is_encrypted( model_value) and isinstance(model_value, str): model_value = self.weblogic_helper.encrypt( model_value, self.model_context.get_domain_home()) property_type = parameter_types[0] # convert the model value to the target type and call the setter with the target value. # these are done together in Java to avoid automatic Jython type conversions. try: CustomBeanUtils.callMethod(provider_mbean, method, property_type, model_value) # failure converting value or calling method except (IllegalAccessException, IllegalArgumentException, InvocationTargetException), ex: ex = exception_helper.create_exception( self.exception_type, 'WLSDPLY-12131', method, str(model_value), ex.getLocalizedMessage(), error=ex) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex
class CredentialMapHelper(object): """ Creates .ldift initialization file for user/password credential mappings """ _class_name = 'CredentialMapHelper' def __init__(self, model_context, exception_type): """ Initialize an instance of CredentialMapHelper. :param model_context: used to find domain home :param exception_type: the type of exception to be thrown """ self._model_context = model_context self._exception_type = exception_type self._logger = PlatformLogger('wlsdeploy.tool.util') self._weblogic_helper = WebLogicHelper(self._logger) self._resource_escaper = ResourcePolicyIdUtil.getEscaper() self._b64_encoder = BASE64Encoder() def create_default_init_file(self, default_mapping_nodes): """ Create a .ldift file to initialize default credential mappers. Build a hash map for use with a template file resource. Write the file to a known location in the domain. :param default_mapping_nodes: the credential mapping elements from the model """ _method_name = 'create_default_init_file' template_hash = self._build_default_template_hash( default_mapping_nodes) template_path = TEMPLATE_PATH + '/' + DEFAULT_MAPPER_INIT_FILE output_dir = File(self._model_context.get_domain_home(), SECURITY_SUBDIR) output_file = File(output_dir, DEFAULT_MAPPER_INIT_FILE) self._logger.info('WLSDPLY-01790', output_file, class_name=self._class_name, method_name=_method_name) file_template_helper.create_file(template_path, template_hash, output_file, self._exception_type) def _build_default_template_hash(self, mapping_section_nodes): """ Create a dictionary of substitution values to apply to the default credential mappers template. :param mapping_section_nodes: the credential mapping elements from the model :return: the template hash dictionary """ template_hash = dict() credential_mappings = [] resource_mappings = [] for mapping_type in mapping_section_nodes.keys(): mapping_name_nodes = mapping_section_nodes[mapping_type] for mapping_name in mapping_name_nodes.keys(): mapping = mapping_name_nodes[mapping_name] mapping_hash = self._build_mapping_hash( mapping_type, mapping_name, mapping) # add a hash with remote target details to create a single passwordCredentialMap element credential_mappings.append(mapping_hash) # add a modified hash for each local user to create resourceMap elements resource_name = mapping_hash[HASH_RESOURCE_NAME] local_users = self._get_local_users(mapping_type, mapping_name, mapping) for local_user in local_users: resource_hash = dict(mapping_hash) resource_hash[HASH_LOCAL_USER] = local_user resource_hash[HASH_RESOURCE_CN] = self._create_cn( resource_name, local_user) resource_mappings.append(resource_hash) template_hash[CREDENTIAL_MAPPINGS] = credential_mappings template_hash[RESOURCE_MAPPINGS] = resource_mappings return template_hash def _build_mapping_hash(self, mapping_type, mapping_name, mapping): """ Build a template hash for the specified mapping element from the model. :param mapping_type: the type of the mapping, such as 'CrossDomain' :param mapping_name: the mapping name from the model, such as 'map1' :param mapping: the mapping element from the model :return: the template hash """ resource_name = self._build_resource_name(mapping_type, mapping_name, mapping) remote_user = self._get_required_attribute(mapping, REMOTE_USER, mapping_type, mapping_name) credential_cn = self._create_cn(resource_name, remote_user) # the password needs to be encrypted, then base64 encoded password = self._get_required_attribute(mapping, REMOTE_PASSWORD, mapping_type, mapping_name) encrypted = self._weblogic_helper.encrypt( password, self._model_context.get_domain_home()) password_encoded = self._b64_encoder.encodeBuffer( String(encrypted).getBytes("UTF-8")) # the local user and resource CN will be updated later for each user return { HASH_CREDENTIAL_CN: credential_cn, HASH_LOCAL_USER: NULL, HASH_PASSWORD_ENCODED: password_encoded, HASH_REMOTE_USER: remote_user, HASH_RESOURCE_CN: NULL, HASH_RESOURCE_NAME: resource_name } def _build_resource_name(self, mapping_type, mapping_name, mapping): """ Build the resource name based on elements in the mapping element from the model. Example: type=<remote>, protocol=http, remoteHost=my.host, remotePort=7020, path=/myapp, method=POST :param mapping_type: the type of the mapping, such as 'CrossDomain' :param mapping_name: the mapping name from the model, such as 'map1' :param mapping: the mapping element from the model :return: the resource name """ # for cross-domain mapping, use domain for remote host, and set cross-domain protocol if mapping_type == CROSS_DOMAIN: remote_host = self._get_required_attribute(mapping, REMOTE_DOMAIN, mapping_type, mapping_name) protocol = CROSS_DOMAIN_PROTOCOL else: remote_host = self._get_required_attribute(mapping, REMOTE_HOST, mapping_type, mapping_name) protocol = dictionary_utils.get_element(mapping, PROTOCOL) # build a map of available values, some may be None resource_name_values = { ID_METHOD: dictionary_utils.get_element(mapping, METHOD), ID_PATH: dictionary_utils.get_element(mapping, PATH), ID_PROTOCOL: protocol, ID_REMOTE_HOST: remote_host, ID_REMOTE_PORT: dictionary_utils.get_element(mapping, REMOTE_PORT) } # build the resource name string resource_name = 'type=<remote>' for field in RESOURCE_FIELDS: value = dictionary_utils.get_element(resource_name_values, field) if value is not None: resource_name += ', %s=%s' % (field, value) return resource_name def _get_local_users(self, mapping_type, mapping_name, mapping): """ Get the local users list, based on the mapping element from the model. :param mapping_type: the type of the mapping, such as 'CrossDomain' :param mapping_name: the mapping name from the model, such as 'map1' :param mapping: the mapping element from the model :return: a list of local users """ if mapping_type == CROSS_DOMAIN: return [CROSS_DOMAIN_USER] local_user_value = self._get_required_attribute( mapping, USER, mapping_type, mapping_name) return TypeUtils.convertToType(list, local_user_value) def _get_required_attribute(self, dictionary, name, mapping_type, mapping_name): """ Return the value of the specified attribute from the specified dictionary. Log and throw an exception if the attribute is not found. :param dictionary: the dictionary to be checked :param name: the name of the attribute to find :param mapping_type: the type of the mapping, such as 'CrossDomain' :param mapping_name: the mapping name from the model, such as 'map1' :return: the value of the attribute :raises: Tool type exception: if an the attribute is not found """ _method_name = '_get_required_attribute' result = dictionary_utils.get_element(dictionary, name) if result is None: pwe = exception_helper.create_exception(self._exception_type, 'WLSDPLY-01791', name, mapping_type, mapping_name) self._logger.throwing(class_name=self._class_name, method_name=_method_name, error=pwe) raise pwe return result def _create_cn(self, resource_name, user): """ Create a CN string from the specified resource name and user name. The result should be escaped for use as a CN. :param resource_name: the name of the resource :param user: the user name :return: the CN string """ name = resource_name + "." + user return self._resource_escaper.escapeString(name)