def add_host(self, hostname, base=None): # create dn if base is None: index = PluginRegistry.getInstance("ObjectIndex") # get the IncomingDevice-Container res = index.search({"_type": "IncomingDeviceContainer", "_parent_dn": self.type_bases["ForemanHost"]}, {"dn": 1}) if len(res) > 0: base = res[0]["dn"] else: base = self.type_bases["ForemanHost"] ForemanBackend.modifier = "foreman" device = self.get_object("ForemanHost", hostname, create=False) if device is None: self.log.debug("Realm request: creating new host with hostname: %s" % hostname) device = ObjectProxy(base, "Device") device.extend("ForemanHost") device.cn = hostname # commit now to get a uuid device.commit() # re-open to get a clean object device = ObjectProxy(device.dn) else: self.log.debug("Realm request: use existing host with hostname: %s" % hostname) try: if not device.is_extended_by("ForemanHost"): device.extend("ForemanHost") # Generate random client key h, key, salt = generate_random_key() # While the client is going to be joined, generate a random uuid and an encoded join key if not device.is_extended_by("RegisteredDevice"): device.extend("RegisteredDevice") if not device.is_extended_by("simpleSecurityObject"): device.extend("simpleSecurityObject") if device.deviceUUID is None: cn = str(uuid.uuid4()) device.deviceUUID = cn else: cn = device.deviceUUID device.status = "pending" device.status_InstallationInProgress = True if device.userPassword is None: device.userPassword = [] elif device.otp is not None: device.userPassword.remove(device.otp) device.userPassword.append("{SSHA}" + encode(h.digest() + salt).decode()) # make sure the client has the access rights he needs client_service = PluginRegistry.getInstance("ClientService") client_service.applyClientRights(device.deviceUUID) device.commit() self.mark_for_parameter_setting(hostname, {"status": "added"}) return "%s|%s" % (key, cn) except Exception as e: # remove created device again because something went wrong # self.remove_type("ForemanHost", hostname) self.log.error(str(e)) raise e finally: ForemanBackend.modifier = None
def joinClient(self, user, device_uuid, mac, info=None): """ TODO """ index = PluginRegistry.getInstance("ObjectIndex") uuid_check = re.compile(r"^[0-9a-f]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$", re.IGNORECASE) if not uuid_check.match(device_uuid): raise ValueError(C.make_error("CLIENT_UUID_INVALID", uuid=device_uuid)) # Handle info, if present more_info = [] extensions = ["simpleSecurityObject", "ieee802Device"] if info: # Check string entries for entry in filter(lambda x: x in info, ["serialNumber", "ou", "o", "l", "description"]): if not re.match(r"^[\w\s]+$", info[entry]): raise ValueError(C.make_error("CLIENT_DATA_INVALID", client=device_uuid, entry=entry, data=info[entry])) more_info.append((entry, info[entry])) if "ipHostNumber" in info: if re.match(r"^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}", info["ipHostNumber"]): more_info.append(("ipHostNumber", info["ipHostNumber"])) extensions.append("IpHost") else: raise ValueError(C.make_error("CLIENT_DATA_INVALID", client=device_uuid, entry="ipHostNumber", data=info["ipHostNumber"])) if "hostname" in info: allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE) if all(allowed.match(x) for x in info["hostname"].split(".")): more_info.append(("description", info["hostname"])) # Check desired device type if set if "deviceType" in info: if re.match(r"^(terminal|workstation|server|sipphone|switch|router|printer|scanner)$", info["deviceType"]): more_info.append(("deviceType", info["deviceType"])) else: raise ValueError(C.make_error("CLIENT_TYPE_INVALID", client=device_uuid, type=info["deviceType"])) # Check owner for presence if "owner" in info: # Take a look at the directory to see if there's such an owner DN res = index.search({'_dn': info["owner"]}, {'_dn': 1}) if len(res) == 0: raise ValueError(C.make_error("CLIENT_OWNER_NOT_FOUND", client=device_uuid, owner=info["owner"])) more_info.append(("owner", info["owner"])) # Generate random client key h, key, salt = generate_random_key() # Take a look at the directory to see if there's already a joined client with this uuid res = index.search({'_type': 'Device', 'macAddress': mac, 'extension': 'RegisteredDevice'}, {'dn': 1}) if len(res) > 0: record = ObjectProxy(res[0]['dn']) for ext in extensions: if not record.is_extended_by(ext): record.extend(ext) if record.is_extended_by("ForemanHost") and record.otp is not None: record.otp = None record.userPassword = ["{SSHA}" + encode(h.digest() + salt).decode()] for k, value in more_info: setattr(record, k, value) cn = record.deviceUUID record.status_Online = False record.status_Offline = True record.status_InstallationInProgress = False record.commit() self.log.info("UUID '%s' joined as %s" % (device_uuid, record.dn)) else: # While the client is going to be joined, generate a random uuid and an encoded join key cn = str(uuid4()) device_key = encrypt_key(device_uuid.replace("-", ""), cn + key) # Resolve manager res = index.search({'_type': 'User', 'uid': user}, {'dn': 1}) if len(res) != 1: raise GOtoException(C.make_error("USER_NOT_UNIQUE" if res else "UNKNOWN_USER", user=user)) manager = res[0]['dn'] # Create new machine entry dn = ",".join([self.env.config.get("goto.machine-rdn", default="ou=systems"), self.env.base]) record = ObjectProxy(dn, "Device") record.extend("RegisteredDevice") for ext in extensions: record.extend(ext) record.deviceUUID = cn record.deviceKey = Binary(device_key) record.cn = "mac%s" % mac.replace(":", "") record.manager = manager record.status_Offline = True record.macAddress = mac.encode("ascii", "ignore") record.userPassword = ["{SSHA}" + encode(h.digest() + salt).decode()] for k, value in more_info: setattr(record, k, value) record.commit() self.log.info("UUID '%s' joined as %s" % (device_uuid, record.dn)) # make sure the client has the access rights he needs self.applyClientRights(cn) return [key, cn]
def joinClient(self, user, device_uuid, mac, info=None): """ TODO """ index = PluginRegistry.getInstance("ObjectIndex") uuid_check = re.compile( r"^[0-9a-f]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$", re.IGNORECASE) if not uuid_check.match(device_uuid): raise ValueError(C.make_error("CLIENT_UUID_INVALID", device_uuid)) # Handle info, if present more_info = [] if info: # Check string entries for entry in filter( lambda x: x in info, ["serialNumber", "ou", "o", "l", "description"]): if not re.match(r"^[\w\s]+$", info[entry]): raise ValueError( C.make_error("CLIENT_DATA_INVALID", device_uuid, entry=entry, data=info[entry])) more_info.append((entry, info[entry])) # Check desired device type if set if "deviceType" in info: if re.match( r"^(terminal|workstation|server|sipphone|switch|router|printer|scanner)$", info["deviceType"]): more_info.append(("deviceType", info["deviceType"])) else: raise ValueError( C.make_error("CLIENT_TYPE_INVALID", device_uuid, type=info["deviceType"])) # Check owner for presence if "owner" in info: # Take a look at the directory to see if there's such an owner DN res = index.search({'_dn': info["owner"]}, {'_dn': 1}) if len(res) == 0: raise ValueError( C.make_error("CLIENT_OWNER_NOT_FOUND", device_uuid, owner=info["owner"])) more_info.append(("owner", info["owner"])) # Generate random client key h, key, salt = generate_random_key() # Take a look at the directory to see if there's already a joined client with this uuid res = index.search( { '_type': 'Device', 'macAddress': mac, 'extension': 'RegisteredDevice' }, {'dn': 1}) if len(res) > 0: record = ObjectProxy(res[0]['dn']) for ext in ["simpleSecurityObject", "ieee802Device"]: if not record.is_extended_by(ext): record.extend(ext) if record.is_extended_by("ForemanHost") and record.otp is not None: record.otp = None record.userPassword = [ "{SSHA}" + encode(h.digest() + salt).decode() ] for k, value in more_info: setattr(record, k, value) cn = record.deviceUUID record.status_Online = False record.status_Offline = True record.status_InstallationInProgress = False record.commit() self.log.info("UUID '%s' joined as %s" % (device_uuid, record.dn)) else: # While the client is going to be joined, generate a random uuid and an encoded join key cn = str(uuid4()) device_key = encrypt_key(device_uuid.replace("-", ""), cn + key) # Resolve manager res = index.search({'_type': 'User', 'uid': user}, {'dn': 1}) if len(res) != 1: raise GOtoException( C.make_error("USER_NOT_UNIQUE" if res else "UNKNOWN_USER", target=user)) manager = res[0]['dn'] # Create new machine entry dn = ",".join([ self.env.config.get("goto.machine-rdn", default="ou=systems"), self.env.base ]) record = ObjectProxy(dn, "Device") record.extend("RegisteredDevice") record.extend("ieee802Device") record.extend("simpleSecurityObject") record.deviceUUID = cn record.deviceKey = Binary(device_key) record.cn = "mac%s" % mac.replace(":", "") record.manager = manager record.status_Offline = True record.macAddress = mac.encode("ascii", "ignore") record.userPassword = [ "{SSHA}" + encode(h.digest() + salt).decode() ] for k, value in more_info: setattr(record, k, value) record.commit() self.log.info("UUID '%s' joined as %s" % (device_uuid, record.dn)) # make sure the client has the access rights he needs self.applyClientRights(cn) return [key, cn]