async def do_update(self, data): """ Update NFS Service Configuration. `servers` represents number of servers to create. When `allow_nonroot` is set, it allows non-root mount requests to be served. `bindip` is a list of IP's on which NFS will listen for requests. When it is unset/empty, NFS listens on all available addresses. `v4` when set means that we switch from NFSv3 to NFSv4. `v4_v3owner` when set means that system will use NFSv3 ownership model for NFSv4. `v4_krb` will force NFS shares to fail if the Kerberos ticket is unavailable. `v4_domain` overrides the default DNS domain name for NFSv4. `mountd_port` specifies the port mountd(8) binds to. `rpcstatd_port` specifies the port rpc.statd(8) binds to. `rpclockd_port` specifies the port rpclockd_port(8) binds to. .. examples(websocket):: Update NFS Service Configuration to listen on 192.168.0.10 and use NFSv4 :::javascript { "id": "6841f242-840a-11e6-a437-00e04d680384", "msg": "method", "method": "pool.resilver.update", "params": [{ "bindip": [ "192.168.0.10" ], "v4": true }] } """ if data.get("v4") is False: data.setdefault("v4_v3owner", False) old = await self.config() new = old.copy() new.update(data) verrors = ValidationErrors() new_v4_krb_enabled = (new["v4_krb"] or await self.middleware.call("kerberos.keytab.query")) if new["v4"] and new_v4_krb_enabled and not await self.middleware.call( "system.is_freenas"): if await self.middleware.call("failover.licensed"): gc = await self.middleware.call("datastore.config", "network.globalconfiguration") if not gc["gc_hostname_virtual"] or gc["gc_domain"]: verrors.add( "nfs_update.v4", "Enabling kerberos authentication on TrueNAS HA requires setting the virtual hostname and " "domain") if osc.IS_LINUX: if len(new['bindip']) > 1: verrors.add( 'nfs_update.bindip', 'Listening on more than one address is not supported') bindip_choices = await self.bindip_choices() for i, bindip in enumerate(new['bindip']): if bindip not in bindip_choices: verrors.add(f'nfs_update.bindip.{i}', 'Please provide a valid ip address') if new["v4"] and new_v4_krb_enabled and await self.middleware.call( 'activedirectory.get_state') != "DISABLED": """ In environments with kerberized NFSv4 enabled, we need to tell winbindd to not prefix usernames with the short form of the AD domain. Directly update the db and regenerate the smb.conf to avoid having a service disruption due to restarting the samba server. """ if await self.middleware.call('smb.get_smb_ha_mode') == 'LEGACY': raise ValidationError( 'nfs_update.v4', 'Enabling kerberos authentication on TrueNAS HA requires ' 'the system dataset to be located on a data pool.') ad = await self.middleware.call('activedirectory.config') await self.middleware.call('datastore.update', 'directoryservice.activedirectory', ad['id'], {'ad_use_default_domain': True}) await self.middleware.call('etc.generate', 'smb') await self.middleware.call('service.reload', 'cifs') if not new["v4"] and new["v4_v3owner"]: verrors.add("nfs_update.v4_v3owner", "This option requires enabling NFSv4") if new["v4_v3owner"] and new["userd_manage_gids"]: verrors.add( "nfs_update.userd_manage_gids", "This option is incompatible with NFSv3 ownership model for NFSv4" ) if not new["v4"] and new["v4_domain"]: verrors.add("nfs_update.v4_domain", "This option does not apply to NFSv3") if verrors: raise verrors await self.nfs_compress(new) await self._update_service(old, new) await self.nfs_extend(new) return new
def get_extension(self, vcp_url, fingerprint): try: cp = configparser.ConfigParser() cp.read(self.middleware.call_sync('vcenter.property_file_path')) version = self.middleware.call_sync('vcenter.get_plugin_version') description = vim.Description() description.label = cp.get('RegisterParam', 'label') description.summary = cp.get('RegisterParam', 'description') ext = vim.Extension() ext.company = cp.get('RegisterParam', 'company') ext.version = version ext.key = cp.get('RegisterParam', 'key') ext.description = description ext.lastHeartbeatTime = datetime.now() server_info = vim.Extension.ServerInfo() server_info.serverThumbprint = fingerprint server_info.type = vcp_url.split(':')[0].upper() # sysgui protocol server_info.url = vcp_url server_info.description = description server_info.company = cp.get('RegisterParam', 'company') server_info.adminEmail = ['ADMIN EMAIL'] ext.server = [server_info] client = vim.Extension.ClientInfo() client.url = vcp_url client.company = cp.get('RegisterParam', 'company') client.version = version client.description = description client.type = "vsphere-client-serenity" ext.client = [client] event_info = [] for e in cp.get('RegisterParam', 'events').split(","): ext_event_type_info = vim.Extension.EventTypeInfo() ext_event_type_info.eventID = e event_info.append(ext_event_type_info) task_info = [] for t in cp.get('RegisterParam', 'tasks').split(","): ext_type_info = vim.Extension.TaskTypeInfo() ext_type_info.taskID = t task_info.append(ext_type_info) # Register custom privileges required for vcp RBAC priv_info = [] for priv in cp.get('RegisterParam', 'auth').split(","): ext_type_info = vim.Extension.PrivilegeInfo() ext_type_info.privID = priv ext_type_info.privGroupName = self.PRIVATE_GROUP_NAME priv_info.append(ext_type_info) ext.taskList = task_info ext.eventList = event_info ext.privilegeList = priv_info resource_list = self.create_event_keyvalue_pairs() ext.resourceList = resource_list return ext except configparser.NoOptionError as e: raise ValidationError('vcenter_update.get_extension', f'Property Missing : {e}')
async def do_update(self, data): """ `hostname` list of ip addresses or hostnames of LDAP servers with which to communicate in order of preference. Failover only occurs if the current LDAP server is unresponsive. `basedn` specifies the default base DN to use when performing ldap operations. The base must be specified as a Distinguished Name in LDAP format. `binddn` specifies the default bind DN to use when performing ldap operations. The bind DN must be specified as a Distinguished Name in LDAP format. `anonbind` use anonymous authentication. `ssl` establish SSL/TLS-protected connections to the LDAP server(s). GSSAPI signing is disabled on SSL/TLS-protected connections if kerberos authentication is used. `certificate` LDAPs client certificate to be used for certificate- based authentication. `validate_certificates` specifies whether to perform checks on server certificates in a TLS session. If enabled, TLS_REQCERT demand is set. The server certificate is requested. If no certificate is provided or if a bad certificate is provided, the session is immediately terminated. If disabled, TLS_REQCERT allow is set. The server certificate is requested, but all errors are ignored. `kerberos_realm` in which the server is located. This parameter is only required for SASL GSSAPI authentication to the remote LDAP server. `kerberos_principal` kerberos principal to use for SASL GSSAPI authentication to the remote server. If `kerberos_realm` is specified without a keytab, then the `binddn` and `bindpw` are used to perform to obtain the ticket necessary for GSSAPI authentication. `timeout` specifies a timeout (in seconds) after which calls to synchronous LDAP APIs will abort if no response is received. `dns_timeout` specifies the timeout (in seconds) after which the poll(2)/select(2) following a connect(2) returns in case of no activity for openldap. For nslcd this specifies the time limit (in seconds) to use when connecting to the directory server. This directly impacts the length of time that the LDAP service tries before failing over to a secondary LDAP URI. `has_samba_schema` determines whether to configure samba to use the ldapsam passdb backend to provide SMB access to LDAP users. This feature requires the presence of Samba LDAP schema extensions on the remote LDAP server. """ verrors = ValidationErrors() must_reload = False old = await self.config() new = old.copy() new.update(data) new['uri_list'] = await self.hostnames_to_uris(new) await self.common_validate(new, old, verrors) verrors.check() if old != new: must_reload = True if new['enable']: try: await self.middleware.call('ldap.ldap_validate', new) except Exception as e: raise ValidationError('ldap_update', str(e)) await self.ldap_compress(new) await self.middleware.call('datastore.update', 'directoryservice.ldap', old['id'], new, {'prefix': 'ldap_'}) if must_reload: if new['enable']: await self.middleware.call('ldap.start') else: await self.middleware.call('ldap.stop') return await self.config()
async def do_update(self, data): """ Update active directory configuration. `domainname` full DNS domain name of the Active Directory domain. `bindname` username used to perform the intial domain join. `bindpw` password used to perform the initial domain join. User- provided credentials are used to obtain a kerberos ticket, which is used to perform the actual domain join. `verbose_logging` increase logging during the domain join process. `use_default_domain` controls whether domain users and groups have the pre-windows 2000 domain name prepended to the user account. When enabled, the user appears as "administrator" rather than "EXAMPLE\administrator" `allow_trusted_doms` enable support for trusted domains. If this parameter is enabled, then separate idmap backends _must_ be configured for each trusted domain, and the idmap cache should be cleared. `allow_dns_updates` during the domain join process, automatically generate DNS entries in the AD domain for the NAS. If this is disabled, then a domain administrator must manually add appropriate DNS entries for the NAS. This parameter is recommended for TrueNAS HA servers. `disable_freenas_cache` disables active caching of AD users and groups. When disabled, only users cached in winbind's internal cache are visible in GUI dropdowns. Disabling active caching is recommended in environments with a large amount of users. `site` AD site of which the NAS is a member. This parameter is auto- detected during the domain join process. If no AD site is configured for the subnet in which the NAS is configured, then this parameter appears as 'Default-First-Site-Name'. Auto-detection is only performed during the initial domain join. `kerberos_realm` in which the server is located. This parameter is automatically populated during the initial domain join. If the NAS has an AD site configured and that site has multiple kerberos servers, then the kerberos realm is automatically updated with a site-specific configuration to use those servers. Auto-detection is only performed during initial domain join. `kerberos_principal` kerberos principal to use for AD-related operations outside of Samba. After intial domain join, this field is updated with the kerberos principal associated with the AD machine account for the NAS. `nss_info` controls how Winbind retrieves Name Service Information to construct a user's home directory and login shell. This parameter is only effective if the Active Directory Domain Controller supports the Microsoft Services for Unix (SFU) LDAP schema. `timeout` timeout value for winbind-related operations. This value may need to be increased in environments with high latencies for communications with domain controllers or a large number of domain controllers. Lowering the value may cause status checks to fail. `dns_timeout` timeout value for DNS queries during the initial domain join. This value is also set as the NETWORK_TIMEOUT in the ldap config file. `createcomputer` Active Directory Organizational Unit in which new computer accounts are created. The OU string is read from top to bottom without RDNs. Slashes ("/") are used as delimiters, like `Computers/Servers/NAS`. The backslash ("\\") is used to escape characters but not as a separator. Backslashes are interpreted at multiple levels and might require doubling or even quadrupling to take effect. When this field is blank, new computer accounts are created in the Active Directory default OU. The Active Directory service is started after a configuration update if the service was initially disabled, and the updated configuration sets `enable` to `True`. The Active Directory service is stopped if `enable` is changed to `False`. If the configuration is updated, but the initial `enable` state is `True`, and remains unchanged, then the samba server is only restarted. During the domain join, a kerberos keytab for the newly-created AD machine account is generated. It is used for all future LDAP / AD interaction and the user-provided credentials are removed. """ await self.middleware.call("smb.cluster_check") verrors = ValidationErrors() old = await self.config() new = old.copy() new.update(data) new['domainname'] = new['domainname'].upper() try: await self.update_netbios_data(old, new) except Exception as e: raise ValidationError('activedirectory_update.netbiosname', str(e)) await self.common_validate(new, old, verrors) verrors.check() if new['enable']: if await self.middleware.call('failover.licensed'): if await self.middleware.call('systemdataset.is_boot_pool'): raise ValidationError( 'activedirectory.enable', 'Active Directory may not be enabled while ' 'system dataset is on the boot pool' ) if new['enable'] and not old['enable']: """ Currently run two health checks prior to validating domain. 1) Attempt to kinit with user-provided credentials. This is used to verify that the credentials are correct. 2) Check for an overly large time offset. System kerberos libraries may not report the time offset as an error during kinit, but the large time offset will prevent libads from using the ticket for the domain join. """ try: domain_info = await self.domain_info(new['domainname']) except CallError as e: raise ValidationError('activedirectory.domainname', e.errmsg) if abs(domain_info['Server time offset']) > 180: raise ValidationError( 'activedirectory.domainname', 'Time offset from Active Directory domain exceeds maximum ' 'permitted value. This may indicate an NTP misconfiguration.' ) try: await self.validate_credentials(new) except CallError as e: if new['kerberos_principal']: method = "activedirectory.kerberos_principal" else: method = "activedirectory.bindpw" try: msg = e.errmsg.split(":")[-1:][0].strip() except Exception: raise e if msg == 'Cannot read password while getting initial credentials': # non-interactive kinit fails with KRB5_LIBOS_CANTREADPWD if password is expired # rather than prompting for password change if method == 'activedirectory.kerberos_principal': msg = 'Kerberos keytab is no longer valid.' else: msg = f'Active Directory account password for user {new["bindname"]} is expired.' elif msg == "Client's credentials have been revoked while getting initial credentials": # KRB5KDC_ERR_CLIENT_REVOKED means that the account has been locked in AD msg = 'Active Directory account is locked.' elif msg == 'KDC policy rejects request while getting initial credentials': # KRB5KDC_ERR_POLICY msg = ( 'Active Directory security policy rejected request to obtain kerberos ticket. ' 'This may occur if the bind account has been configured to deny interactive ' 'logons or require two-factor authentication. Depending on organizational ' 'security policies, one may be required to pre-generate a kerberos keytab ' 'and upload to TrueNAS server for use during join process.' ) if not msg: # failed to parse, re-raise original error message raise raise ValidationError( method, f'Failed to validate bind credentials: {msg}' ) new = await self.ad_compress(new) ret = await super().do_update(new) diff = await self.diff_conf_and_registry(new) await self.middleware.call('sharing.smb.apply_conf_diff', 'GLOBAL', diff) job = None if not old['enable'] and new['enable']: job = (await self.middleware.call('activedirectory.start')).id elif not new['enable'] and old['enable']: job = (await self.middleware.call('activedirectory.stop')).id elif new['enable'] and old['enable']: await self.middleware.call('service.restart', 'idmap') ret.update({'job_id': job}) return ret