Beispiel #1
0
 public DtoProvisionResponse ProvisionClient(DtoProvisionRequest provisionRequest)
 {
     Request.Method = Method.POST;
     Request.AddJsonBody(provisionRequest);
     Request.Resource = string.Format("{0}/ProvisionClient/", Resource);
     return(new ApiRequest().ExecuteHMAC <DtoProvisionResponse>(Request, provisionRequest.Name));
 }
Beispiel #2
0
        private EnumProvisionStatus.Status ProvisionStage2()
        {
            var intermediateThumbprint = _serviceSetting.GetSetting("intermediate_thumbprint");

            if (string.IsNullOrEmpty(intermediateThumbprint.Value))
            {
                //assume stage 1 didn't finish
                return(EnumProvisionStatus.Status.NotStarted);
            }
            var intermediate = ServiceCertificate.GetCertificateFromStore(intermediateThumbprint.Value,
                                                                          StoreName.CertificateAuthority);

            if (intermediate == null)
            {
                return(EnumProvisionStatus.Status.NotStarted);
            }
            var key = GenerateSymmKey();

            var provisionRequest = new DtoProvisionRequest();

            provisionRequest.Name           = DtoGobalSettings.ClientIdentity.Name;
            provisionRequest.AdGuid         = new ServiceAD().GetADGuid(provisionRequest.Name);
            provisionRequest.SymmKey        = EncryptDataWithIntermediate(intermediate.PublicKey.Key, key);
            provisionRequest.InstallationId = DtoGobalSettings.ClientIdentity.InstallationId;

            //include some hardware details
            Logger.Debug("Gathering Hardware Details");
            var inventoryCollection = new DtoInventoryCollection();

            new ComputerSystem().Search(inventoryCollection);
            new Bios().Search(inventoryCollection);
            new Processor().Search(inventoryCollection);
            new Nic().Search(inventoryCollection);
            try
            {
                var m = Convert.ToInt64(inventoryCollection.ComputerSystem.TotalPhysicalMemory);
                provisionRequest.Memory = Convert.ToInt32(m / 1024 / 1024);
            }
            catch
            {
                provisionRequest.Memory = 0;
            }

            try
            {
                provisionRequest.Processor = inventoryCollection.Processor.Name;
            }
            catch
            {
                provisionRequest.Processor = string.Empty;
            }

            try
            {
                provisionRequest.SerialNumber = inventoryCollection.Bios.SerialNumber;
            }
            catch
            {
                provisionRequest.SerialNumber = string.Empty;
            }

            try
            {
                provisionRequest.Model = inventoryCollection.ComputerSystem.Model;
            }
            catch
            {
                provisionRequest.Model = string.Empty;
            }

            try
            {
                foreach (var nic in inventoryCollection.NetworkAdapters)
                {
                    provisionRequest.Macs.Add(nic.Mac);
                }
            }
            catch
            {
                //do nothing
            }


            inventoryCollection = null;

            var response = new APICall().ProvisionApi.ProvisionClient(provisionRequest);

            if (response == null)
            {
                return(EnumProvisionStatus.Status.Error);
            }
            if (response.ProvisionStatus == EnumProvisionStatus.Status.Reset)
            {
                Logger.Info("Client Reset Approved.  Starting Reset Process.");
                return(EnumProvisionStatus.Status.Reset);
            }
            if (response.ProvisionStatus == EnumProvisionStatus.Status.FullReset)
            {
                Logger.Info("Client Full Reset Requested.  Starting Full Reset Process.");
                return(EnumProvisionStatus.Status.FullReset);
            }
            if (response.ProvisionStatus == EnumProvisionStatus.Status.PendingReset)
            {
                Logger.Info("Client Is Pending Reset Approval.");
                return(EnumProvisionStatus.Status.PendingReset);
            }
            if (response.ProvisionStatus == EnumProvisionStatus.Status.PendingProvisionApproval)
            {
                Logger.Info("Client Is Pending Provisioning Approval");
                return(EnumProvisionStatus.Status.PendingProvisionApproval);
            }
            if (response.ProvisionStatus == EnumProvisionStatus.Status.PendingPreProvision)
            {
                Logger.Info("Client Has Not Been Pre-Provisioned And The Current Security Policy Requires It.");
                return(EnumProvisionStatus.Status.PendingPreProvision);
            }
            if (response.ProvisionStatus != EnumProvisionStatus.Status.PendingConfirmation)
            {
                return(EnumProvisionStatus.Status.Error);
            }

            var byteCert   = Convert.FromBase64String(response.Certificate);
            var base64Cert = new ServiceSymmetricEncryption().Decrypt(key, byteCert);
            var deviceCert = new X509Certificate2(Convert.FromBase64String(base64Cert));

            if (ServiceCertificate.StoreLocalMachine(deviceCert, StoreName.My))
            {
                var deviceThumbprint = _serviceSetting.GetSetting("device_thumbprint");
                deviceThumbprint.Value = deviceCert.Thumbprint;
                _serviceSetting.UpdateSettingValue(deviceThumbprint);

                var computerIdentifier = _serviceSetting.GetSetting("computer_identifier");
                computerIdentifier.Value             = response.ComputerIdentifier;
                DtoGobalSettings.ClientIdentity.Guid = response.ComputerIdentifier;
                _serviceSetting.UpdateSettingValue(computerIdentifier);

                var entropy      = _serviceSetting.GetSetting("entropy");
                var entropyBytes = ServiceDP.CreateRandomEntropy();
                entropy.Value = Convert.ToBase64String(entropyBytes);
                _serviceSetting.UpdateSettingValue(entropy);

                var encryptedKey = ServiceDP.EncryptData(key, true, entropyBytes);
                var keySetting   = _serviceSetting.GetSetting("encryption_key");
                keySetting.Value = Convert.ToBase64String(encryptedKey);
                _serviceSetting.UpdateSettingValue(keySetting);

                var settingProvisionStatus = _serviceSetting.GetSetting("provision_status");
                settingProvisionStatus.Value = Convert.ToInt16(response.ProvisionStatus).ToString();
                _serviceSetting.UpdateSettingValue(settingProvisionStatus);
            }

            return(EnumProvisionStatus.Status.PendingConfirmation);
        }
Beispiel #3
0
        public DtoProvisionResponse ProvisionClient(DtoProvisionRequest request)
        {
            Logger.Debug($"Received Provision Request For {request.Name}");
            var provisionResponse = new DtoProvisionResponse();
            var computerService   = new ServiceComputer();
            var currentIp         = IpServices.GetIPAddress();

            //Check if any computers with this installation id already exist
            Logger.Debug($"Installation ID: {request.InstallationId}");
            var existingComputer = computerService.GetByInstallationId(request.InstallationId);



            if (existingComputer != null)
            {
                Logger.Debug($"A Computer With This Installation Id Already Exists: {request.InstallationId}");
                var originalName = existingComputer.Name;
                Logger.Debug($"Existing Name {originalName} Request Name {request.Name}");

                existingComputer.Name            = request.Name;
                existingComputer.Guid            = Guid.NewGuid().ToString();
                existingComputer.AdGuid          = request.AdGuid;
                existingComputer.ProvisionedTime = DateTime.Now;
                existingComputer.InstallationId  = request.InstallationId;
                existingComputer.LastIp          = currentIp;

                //even though id is a match, an existing computer may be using the request name
                var doesExist = computerService.GetByName(request.Name);
                if (doesExist != null)
                {
                    if (doesExist.Id != existingComputer.Id)
                    {
                        //id's don't match, a different computer with this name already exists

                        //Check if we should reset matching installation id's.  Should not be used unless computers have the same install id, due to improper imaging
                        var forceInstallIdReset = ConfigurationManager.AppSettings["ForceInstallationIdReset"];
                        if (forceInstallIdReset.ToLower().Equals("true"))
                        {
                            Logger.Debug("Installation ID Reset Has Been Enforced From Web.config");
                            return(new DtoProvisionResponse()
                            {
                                ProvisionStatus = EnumProvisionStatus.Status.FullReset
                            });
                        }

                        if (existingComputer.ProvisionStatus == EnumProvisionStatus.Status.Reset)
                        {
                            Logger.Debug("Reset Approved.  Archiving Existing Computer And Changing Name Of This Request.");
                            var result = new ServiceComputer().ArchiveComputerKeepGroups(doesExist.Id);
                        }

                        else if (doesExist.ProvisionStatus == EnumProvisionStatus.Status.Provisioned)
                        {
                            var requireResetRequests = ServiceSetting.GetSettingValue(SettingStrings.RequireResetRequests);
                            if (requireResetRequests == "1")
                            {
                                //computer has not yet been reset and reset approval is required, return pending reset
                                Logger.Debug($"Computer Has Not Had Reset Approved {originalName}");

                                var resetRequest = new EntityResetRequest();
                                resetRequest.ComputerName   = originalName;
                                resetRequest.InstallationId = request.InstallationId;
                                resetRequest.IpAddress      = currentIp;

                                var requestResult = new ServiceResetRequest().CreateRequest(resetRequest);
                                if (!requestResult.Success)
                                {
                                    provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                                }

                                provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.PendingReset;
                                return(provisionResponse);
                            }
                            else
                            {
                                Logger.Debug("Reset Approvals Are Not Required, Archiving Existing Computer.");
                                var result = new ServiceComputer().ArchiveComputerKeepGroups(doesExist.Id);
                            }
                        }
                        else if (doesExist.ProvisionStatus == EnumProvisionStatus.Status.PreProvisioned)
                        {
                            Logger.Debug("Restoring Computer With This ID, Removing The Existing Not Provisioned Computer With This Name");
                            //current id matches computer, but a new computer has preprovisioned with this name, allow provison to occur
                            //delete the doesExist entity, allowing the archived computer to be restored
                            var result = new ServiceComputer().DeleteComputer(doesExist.Id); //requires a new instance or delete will fail
                            Logger.Debug("Remove Existing Result: " + JsonConvert.SerializeObject(result));
                        }
                        else if (doesExist.ProvisionStatus == EnumProvisionStatus.Status.ProvisionApproved ||
                                 doesExist.ProvisionStatus == EnumProvisionStatus.Status.Reset)
                        {
                            Logger.Debug("Restoring Computer With This ID, Archiving The Existing Not Provisioned Computer With This Name");
                            //current id matches computer, but a new computer has preprovisioned with this name, allow provison to occur
                            //delete the doesExist entity, allowing the archived computer to be restored
                            var result = new ServiceComputer().ArchiveComputerKeepGroups(doesExist.Id); //requires a new instance or delete will fail
                            Logger.Debug("Archive Existing Result: " + JsonConvert.SerializeObject(result));
                        }
                    }
                }

                var cert = GenerateDeviceCert(request.SymmKey, existingComputer);
                Logger.Debug($"Provisioning Computer {request.Name}");
                var addResult = computerService.UpdateComputer(existingComputer);
                if (!addResult.Success)
                {
                    new ServiceCertificate().DeleteCertificate(existingComputer.CertificateId);
                    provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                    return(provisionResponse);
                }

                provisionResponse.ProvisionStatus    = EnumProvisionStatus.Status.PendingConfirmation;
                provisionResponse.Certificate        = Convert.ToBase64String(cert);
                provisionResponse.ComputerIdentifier = existingComputer.Guid;

                return(provisionResponse);
            }

            var computerEntity = new EntityComputer();

            computerEntity.LastIp = currentIp;

            //By this point we know it's a new installation id, continue on with other checks
            //Check if this computer name is already in use
            var nameExistsEntity = computerService.GetByName(request.Name);

            if (nameExistsEntity != null)
            {
                Logger.Debug($"A Computer With This Name Exists, Continuing Checks {request.Name}");
                var tmpEntity = JsonConvert.SerializeObject(nameExistsEntity); //done this way to release the entity and not make changes on updates
                computerEntity = JsonConvert.DeserializeObject <EntityComputer>(tmpEntity);

                //if the computer is not approved or preprovisioned check if reset request is required
                if (nameExistsEntity.ProvisionStatus != EnumProvisionStatus.Status.PreProvisioned &&
                    nameExistsEntity.ProvisionStatus != EnumProvisionStatus.Status.ProvisionApproved &&
                    nameExistsEntity.ProvisionStatus != EnumProvisionStatus.Status.Reset)
                {
                    var requireResetRequests = ServiceSetting.GetSettingValue(SettingStrings.RequireResetRequests);
                    if (requireResetRequests == "1")
                    {
                        //computer has not yet been reset and reset approval is required, return pending reset
                        Logger.Debug($"Computer Has Not Had Reset Approved {request.Name}");
                        var resetRequest = new EntityResetRequest();
                        resetRequest.ComputerName   = request.Name;
                        resetRequest.InstallationId = request.InstallationId;
                        resetRequest.IpAddress      = currentIp;

                        var requestResult = new ServiceResetRequest().CreateRequest(resetRequest);
                        if (!requestResult.Success)
                        {
                            provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                        }

                        provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.PendingReset;
                        return(provisionResponse);
                    }
                    else
                    {
                        //computer has not yet been reset and no approval is required, start the reset process
                        Logger.Debug($"Reset Approval Not Required.  Starting Reset Process. {request.Name}");
                        computerEntity.ProvisionStatus = EnumProvisionStatus.Status.Reset;
                        var updateResult = computerService.UpdateComputer(computerEntity);
                        if (!updateResult.Success)
                        {
                            provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                        }

                        new ServiceCertificate().DeleteCertificate(computerEntity.CertificateId);
                        provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Reset;
                        return(provisionResponse);
                    }
                }
            }

            //Check if new provisions require pre provisioning and / or approvals
            var preProvisionRequired         = ServiceSetting.GetSettingValue(SettingStrings.RequirePreProvision);
            var provisionApprovalRequired    = ServiceSetting.GetSettingValue(SettingStrings.RequireProvisionApproval);
            var preProvisionApprovalRequired = ServiceSetting.GetSettingValue(SettingStrings.PreProvisionRequiresApproval);

            if (preProvisionRequired == "1")
            {
                Logger.Debug($"Pre-Provision Is Required {request.Name}");
                if (computerEntity.ProvisionStatus != EnumProvisionStatus.Status.Reset &&
                    computerEntity.ProvisionStatus != EnumProvisionStatus.Status.PreProvisioned && computerEntity.ProvisionStatus != EnumProvisionStatus.Status.ProvisionApproved)
                {
                    Logger.Debug($"Setting Status To Pending Pre-Provision {request.Name}");
                    provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.PendingPreProvision;
                    return(provisionResponse);
                }
                else
                {
                    Logger.Debug($"PreProvision Check Passed {request.Name}");
                }
                if (preProvisionApprovalRequired == "1" && computerEntity.ProvisionStatus == EnumProvisionStatus.Status.PreProvisioned)
                {
                    Logger.Debug($"PreProvision Check Passed. PreProvision Approval Is Required.  Setting Status To Pending Provision Approval {request.Name}");
                    //submit provision approval request
                    var approvalRequest = new EntityApprovalRequest();
                    approvalRequest.ComputerName   = request.Name;
                    approvalRequest.InstallationId = request.InstallationId;
                    approvalRequest.IpAddress      = currentIp;

                    var requestResult = new ServiceApprovalRequest().CreateRequest(approvalRequest);
                    if (!requestResult.Success)
                    {
                        provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                    }

                    provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.PendingProvisionApproval;
                    return(provisionResponse);
                }
            }
            else if (provisionApprovalRequired == "1" && computerEntity.ProvisionStatus != EnumProvisionStatus.Status.ProvisionApproved)
            {
                Logger.Debug($"Provision Approval Is Required.  Setting Status To Pending Provision Approval {request.Name}");
                //submit provision approval request
                var approvalRequest = new EntityApprovalRequest();
                approvalRequest.ComputerName   = request.Name;
                approvalRequest.InstallationId = request.InstallationId;
                approvalRequest.IpAddress      = currentIp;

                var requestResult = new ServiceApprovalRequest().CreateRequest(approvalRequest);
                if (!requestResult.Success)
                {
                    provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                }

                provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.PendingProvisionApproval;
                return(provisionResponse);
            }

            //all pre checks complete and successful, move forward with provision
            //Provisioning computer
            computerEntity.Name            = request.Name;
            computerEntity.Guid            = Guid.NewGuid().ToString();
            computerEntity.AdGuid          = request.AdGuid;
            computerEntity.ProvisionedTime = DateTime.Now;
            computerEntity.InstallationId  = request.InstallationId;
            computerEntity.LastIp          = currentIp;

            byte[] encryptedCert;
            string computerIdentifier;

            if (computerEntity.Id == 0) // this will never be true when preprovision is required
            {
                //this computer does not at exist at all, add it
                Logger.Debug($"Computer Is New, Provisioning Computer {request.Name}");
                encryptedCert = GenerateDeviceCert(request.SymmKey, computerEntity);
                var addResult = computerService.AddComputer(computerEntity);
                computerIdentifier = computerEntity.Guid;
                if (!addResult.Success)
                {
                    new ServiceCertificate().DeleteCertificate(computerEntity.CertificateId);
                    provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                    return(provisionResponse);
                }
            }
            else
            {
                //computer exists in some way
                //overwriting an existing computer, should we overwrite or archive and create a new one
                //if serial number, memory, processor name, and computer model are the same, assume it's the same computer
                Logger.Debug($"Checking If Computer With Matching Hardware Info Already Exists {request.Name}");
                var existingHardware = computerService.GetProvisionHardware(computerEntity.Id);

                var macsVerified = true;
                if (existingHardware != null)
                {
                    foreach (var requestMac in request.Macs)
                    {
                        Logger.Debug(requestMac);
                        if (!existingHardware.Macs.Contains(requestMac))
                        {
                            macsVerified = false;
                            break;
                        }
                    }
                }
                Logger.Debug("Macs Verified: " + macsVerified);
                Logger.Debug("Existing Hardware: " + JsonConvert.SerializeObject(existingHardware));
                Logger.Debug("Request Hardware: " + JsonConvert.SerializeObject(request));
                if (existingHardware != null)
                {
                    if (existingHardware.Memory == request.Memory && existingHardware.Model.Equals(request.Model) &&
                        existingHardware.Processor.Equals(request.Processor) &&
                        existingHardware.SerialNumber.Equals(request.SerialNumber) && macsVerified)
                    {
                        Logger.Debug($"Hardware Match Found, Linking To Existing Computer {request.Name}");
                        //same computer, update it
                        encryptedCert = GenerateDeviceCert(request.SymmKey, computerEntity);
                        var updateResult = computerService.UpdateComputer(computerEntity);
                        computerIdentifier = computerEntity.Guid;
                        if (!updateResult.Success)
                        {
                            provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                            return(provisionResponse);
                        }
                    }
                    else
                    {
                        //different computer, archive and add new
                        Logger.Debug($"No Hardware Match Found, Archiving Existing Computer{request.Name}");
                        var newComputer = new EntityComputer();
                        newComputer.Name            = computerEntity.Name;
                        newComputer.Guid            = Guid.NewGuid().ToString();
                        newComputer.AdGuid          = computerEntity.AdGuid;
                        newComputer.ProvisionedTime = computerEntity.ProvisionedTime;
                        newComputer.InstallationId  = computerEntity.InstallationId;
                        newComputer.LastIp          = computerEntity.LastIp;
                        encryptedCert = GenerateDeviceCert(request.SymmKey, newComputer);

                        Logger.Debug("Archiving Computer");
                        new ServiceComputer().ArchiveComputerKeepGroups(computerEntity.Id);
                        Logger.Debug("Adding New Computer");
                        var addResult = computerService.AddComputer(newComputer);
                        computerIdentifier = newComputer.Guid;
                        if (!addResult.Success)
                        {
                            new ServiceCertificate().DeleteCertificate(newComputer.CertificateId);
                            provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                            return(provisionResponse);
                        }
                    }
                }
                else
                {
                    //cannot determine if it's the same computer, when provisioning a new computer with preprovsion or provisional approval required, we should end up here
                    Logger.Debug($"Could Not Determine Hardware Match {request.Name}");
                    if (computerEntity.ProvisionStatus == EnumProvisionStatus.Status.PreProvisioned ||
                        computerEntity.ProvisionStatus == EnumProvisionStatus.Status.ProvisionApproved)
                    {
                        Logger.Debug($"Computer Is PreProvisioned Or Approved.  Provisioning Computer. {request.Name}");
                        //if status is pre-provisioned or approved, assume it's a new computer and finish provision
                        encryptedCert = GenerateDeviceCert(request.SymmKey, computerEntity);
                        var updateResult = computerService.UpdateComputer(computerEntity);
                        computerIdentifier = computerEntity.Guid;
                        if (!updateResult.Success)
                        {
                            provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                            return(provisionResponse);
                        }
                    }
                    else
                    {
                        //not sure why we ended up here, no choice but to archive existing and create new
                        //must create a new entity
                        Logger.Debug($"Archiving Existing.  Provisioning Computer. {request.Name}");
                        var newComputer = new EntityComputer();
                        newComputer.Name            = computerEntity.Name;
                        newComputer.Guid            = Guid.NewGuid().ToString();
                        newComputer.AdGuid          = computerEntity.AdGuid;
                        newComputer.ProvisionedTime = computerEntity.ProvisionedTime;
                        newComputer.InstallationId  = computerEntity.InstallationId;
                        newComputer.LastIp          = computerEntity.LastIp;
                        encryptedCert = GenerateDeviceCert(request.SymmKey, newComputer);

                        new ServiceComputer().ArchiveComputerKeepGroups(computerEntity.Id);
                        var addResult = computerService.AddComputer(newComputer);
                        computerIdentifier = newComputer.Guid;
                        if (!addResult.Success)
                        {
                            new ServiceCertificate().DeleteCertificate(newComputer.CertificateId);
                            provisionResponse.ProvisionStatus = EnumProvisionStatus.Status.Error;
                            return(provisionResponse);
                        }
                    }
                }
            }

            provisionResponse.ProvisionStatus    = EnumProvisionStatus.Status.PendingConfirmation;
            provisionResponse.Certificate        = Convert.ToBase64String(encryptedCert);
            provisionResponse.ComputerIdentifier = computerIdentifier;

            return(provisionResponse);
        }
Beispiel #4
0
 public DtoProvisionResponse ProvisionClient(DtoProvisionRequest request)
 {
     return(new ServiceProvision().ProvisionClient(request));
 }