public StagingTask(StagingStartMessageRequest message) { UhuruSection uhuruSection = (UhuruSection)ConfigurationManager.GetSection("uhuru"); this.TaskId = message.TaskID; this.Message = message; this.workspace = new StagingWorkspace(Path.Combine(uhuruSection.DEA.BaseDir, "staging"), message.TaskID); this.buildpacksDir = Path.GetFullPath(uhuruSection.DEA.Staging.BuildpacksDirectory); this.stagingTimeout = uhuruSection.DEA.Staging.StagingTimeoutMs; this.gitExe = Path.GetFullPath(uhuruSection.DEA.Staging.GitExecutable); var prisonInfo = new ProcessPrisonCreateInfo(); prisonInfo.Id = this.TaskId; prisonInfo.TotalPrivateMemoryLimit = (long)this.Message.Properties.Resources.MemoryMbytes * 1024 * 1024; if (uhuruSection.DEA.UseDiskQuota) { prisonInfo.DiskQuotaBytes = (long)this.Message.Properties.Resources.DiskMbytes * 1024 * 1024; prisonInfo.DiskQuotaPath = this.workspace.BaseDir; } if (uhuruSection.DEA.UploadThrottleBitsps > 0) { prisonInfo.NetworkOutboundRateLimitBitsPerSecond = uhuruSection.DEA.UploadThrottleBitsps; } this.prison = new ProcessPrison(); prison.Create(prisonInfo); }
public void Attach(ProcessPrisonCreateInfo createInfo) { if (createInfo.Id == null) { throw new ArgumentException("Id from createInfo is null", "createInfo"); } if (createInfo.WindowsPassword == null) { throw new ArgumentException("WindowsPassword from createInfo is null", "createInfo"); } this.Id = createInfo.Id; this.createInfo = createInfo; // The Job Object will disapear after a reboot or if all job's processes exit. // It is fine if it is created again with the same name id if the Job doesn't exist. try { // try only to attach and fail if it doesn't exist this.jobObject = JobObject.Attach(JobObjectNamespace() + this.Id); } catch (Win32Exception) { // try to create the job Id; this.jobObject = new JobObject(JobObjectNamespace() + this.Id); } this.WindowsPassword = this.createInfo.WindowsPassword; this.WindowsUsername = GenerateDecoratedUsername(this.Id); if (this.createInfo.DiskQuotaBytes > -1) { userQuota = DiskQuotaManager.GetDiskQuotaUser(DiskQuotaManager.GetVolumeRootFromPath(this.createInfo.DiskQuotaPath), this.WindowsUsername); } this.Created = true; }
public void Create(ProcessPrisonCreateInfo createInfo) { if (createInfo.Id == null) { this.Id = GenerateSecureGuid().ToString(); } else { this.Id = createInfo.Id; } string[] keys = new string[] { "ALLUSERSPROFILE", "APPDATA", "CommonProgramFiles", "CommonProgramFiles(x86)", "CommonProgramW6432", "COMPUTERNAME", "HOMEDRIVE", "LOCALAPPDATA", "NUMBER_OF_PROCESSORS", "OS", "Path", "PROCESSOR_ARCHITECTURE", "PROCESSOR_IDENTIFIER", "PROCESSOR_LEVEL", "PROCESSOR_REVISION", "ProgramData", "ProgramFiles", "ProgramFiles(x86)", "ProgramW6432", "PROMPT", "PSModulePath", "SystemDrive", "SystemRoot", "windir" }; this.myenvvars["HOMEPATH"] = createInfo.DiskQuotaPath; this.myenvvars["TEMP"] = Path.Combine(createInfo.DiskQuotaPath, "tmp"); this.myenvvars["TMP"] = Path.Combine(createInfo.DiskQuotaPath, "tmp"); foreach (string key in keys) { this.myenvvars[key] = Environment.GetEnvironmentVariable(key); } this.createInfo = createInfo; this.jobObject = new JobObject(JobObjectNamespace() + this.Id); this.jobObject.ActiveProcessesLimit = this.createInfo.RunningProcessesLimit; this.jobObject.JobMemoryLimitBytes = this.createInfo.TotalPrivateMemoryLimitBytes; this.jobObject.KillProcessesOnJobClose = this.createInfo.KillProcessesrOnPrisonClose; if (this.createInfo.WindowsPassword == null) { this.WindowsPassword = GenerateSecurePassword(40); } else { this.WindowsPassword = this.createInfo.WindowsPassword; } this.WindowsUsername = CreateDecoratedUser(this.Id, this.WindowsPassword); if (this.createInfo.DiskQuotaBytes > -1) { if (string.IsNullOrEmpty(this.createInfo.DiskQuotaPath)) { // set this.createInfo.DiskQuotaPath to the output of GetUserProfileDirectory throw new NotImplementedException(); } // Set the disk quota to 0 for all disks, exept disk quota path var volumesQuotas = DiskQuotaManager.GetDisksQuotaUser(this.WindowsUsername); foreach (var volumeQuota in volumesQuotas) { volumeQuota.QuotaLimit = 0; } userQuota = DiskQuotaManager.GetDiskQuotaUser(DiskQuotaManager.GetVolumeRootFromPath(this.createInfo.DiskQuotaPath), this.WindowsUsername); userQuota.QuotaLimit = this.createInfo.DiskQuotaBytes; } if (this.createInfo.UrlPortAccess > 0) { UrlsAcl.AddPortAccess(this.createInfo.UrlPortAccess, this.WindowsUsername); } if (this.createInfo.NetworkOutboundRateLimitBitsPerSecond > 0) { NetworkQos.CreateOutboundThrottlePolicy(this.WindowsUsername, this.WindowsUsername, this.createInfo.NetworkOutboundRateLimitBitsPerSecond); if (this.createInfo.UrlPortAccess > 0) { NetworkQos.CreateOutboundThrottlePolicy(this.createInfo.UrlPortAccess.ToString(), this.createInfo.UrlPortAccess, this.createInfo.NetworkOutboundRateLimitBitsPerSecond); } } this.Created = true; }
private void CleanupStagingInstances() { if (!File.Exists(this.stagingTaskRegistry.StagingStateFile)) { return; } object[] instances = JsonConvertibleObject.DeserializeFromJsonArray(File.ReadAllText(this.stagingTaskRegistry.StagingStateFile)); foreach (object obj in instances) { StagingInstance instance = null; try { instance = new StagingInstance(); instance.Properties.FromJsonIntermediateObject(obj); var prisonInfo = new ProcessPrisonCreateInfo(); prisonInfo.Id = instance.Properties.InstanceId; prisonInfo.TotalPrivateMemoryLimitBytes = instance.Properties.MemoryQuotaBytes; prisonInfo.WindowsPassword = instance.Properties.WindowsPassword; if (this.useDiskQuota) { prisonInfo.DiskQuotaBytes = instance.Properties.DiskQuotaBytes; prisonInfo.DiskQuotaPath = instance.Properties.Directory; } Logger.Info("Recovering Process Prisson: {0}", prisonInfo.Id); instance.Prison.Attach(prisonInfo); foreach (Process p in instance.Prison.jobObject.GetJobProcesses()) { if (!p.HasExited) { p.Kill(); } } if (instance.Prison.Created) { instance.Prison.Destroy(); } instance.Workspace = new StagingWorkspace(instance.Properties.Directory); instance.Cleanup(); } catch (Exception ex) { Logger.Warning("Error deleting staging environment for task {0}: {1}", instance.Properties.TaskId, ex.ToString()); } finally { this.stagingTaskRegistry.RemoveStagingInstance(instance); if (instance != null) { instance.Dispose(); } } } }
public void RecoverExistingDroplets() { if (!File.Exists(this.droplets.AppStateFile)) { this.droplets.RecoveredDroplets = true; return; } object[] instances = JsonConvertibleObject.DeserializeFromJsonArray(File.ReadAllText(this.droplets.AppStateFile)); foreach (object obj in instances) { DropletInstance instance = null; try { instance = new DropletInstance(); instance.Properties.FromJsonIntermediateObject(obj); instance.Properties.Orphaned = true; instance.Properties.ResourcesTracked = false; this.monitoring.AddInstanceResources(instance); instance.Properties.StopProcessed = false; var prisonInfo = new ProcessPrisonCreateInfo(); prisonInfo.Id = instance.Properties.InstanceId; prisonInfo.TotalPrivateMemoryLimitBytes = instance.Properties.MemoryQuotaBytes; prisonInfo.WindowsPassword = instance.Properties.WindowsPassword; if (this.useDiskQuota) { prisonInfo.DiskQuotaBytes = instance.Properties.DiskQuotaBytes; prisonInfo.DiskQuotaPath = instance.Properties.Directory; } Logger.Info("Recovering Process Prisson: {0}", prisonInfo.Id); instance.Prison.Attach(prisonInfo); if (instance.Properties.State == DropletInstanceState.Starting) { this.DetectAppReady(instance); } this.droplets.AddDropletInstance(instance); instance = null; } catch (Exception ex) { Logger.Warning(Strings.ErrorRecoveringDropletWarningMessage, instance.Properties.InstanceId, ex.ToString()); } finally { if (instance != null) { instance.Dispose(); } } } this.droplets.RecoveredDroplets = true; if (this.monitoring.Clients > 0) { Logger.Info(Strings.DeaRecoveredApplications, this.monitoring.Clients); } this.MonitorApps(); this.droplets.ForEach(delegate(DropletInstance instance) { this.RegisterInstanceWithRouter(instance); }); this.SendHeartbeat(); this.droplets.ScheduleSnapshotAppState(); }
private void StartDropletInstance(DropletInstance instance, string sha1, string executableFile, string executableUri) { try { try { instance.Lock.EnterWriteLock(); var prisonInfo = new ProcessPrisonCreateInfo(); prisonInfo.Id = instance.Properties.InstanceId; prisonInfo.TotalPrivateMemoryLimitBytes = instance.Properties.MemoryQuotaBytes; if (this.useDiskQuota) { prisonInfo.DiskQuotaBytes = instance.Properties.DiskQuotaBytes; prisonInfo.DiskQuotaPath = instance.Properties.Directory; } if (this.uploadThrottleBitsps > 0) { prisonInfo.NetworkOutboundRateLimitBitsPerSecond = this.uploadThrottleBitsps; } prisonInfo.UrlPortAccess = instance.Properties.Port; Logger.Info("Creating Process Prisson: {0}", prisonInfo.Id); instance.Prison.Create(prisonInfo); Logger.Info("Opening firewall port {0} for instance {1}", instance.Properties.Port, instance.Properties.LoggingId); FirewallTools.OpenPort(instance.Properties.Port, instance.Properties.InstanceId); instance.Properties.WindowsPassword = instance.Prison.WindowsPassword; instance.Properties.WindowsUserName = instance.Prison.WindowsUsername; } finally { instance.Lock.ExitWriteLock(); } string tgzFile = Path.Combine(this.fileResources.StagedDir, sha1 + ".tgz"); this.fileResources.PrepareAppDirectory(executableFile, executableUri, sha1, tgzFile, instance); Logger.Debug(Strings.Downloadcompleate); string starting = string.Format(CultureInfo.InvariantCulture, Strings.StartingUpInstanceOnPort, instance.Properties.LoggingId, instance.Properties.Port); Logger.Info(starting); Logger.Debug(Strings.Clients, this.monitoring.Clients); Logger.Debug(Strings.ReservedMemoryUsageMb, this.monitoring.MemoryReservedMbytes, this.monitoring.MaxMemoryMbytes); try { instance.Lock.EnterWriteLock(); instance.Properties.EnvironmentVariables.Add(VcapWindowsUserVariable, instance.Properties.WindowsUserName); instance.Properties.EnvironmentVariables.Add(VcapWindowsUserPasswordVariable, instance.Properties.WindowsPassword); instance.Prison.SetUsersEnvironmentVariables(instance.Properties.EnvironmentVariables); } finally { instance.Lock.ExitWriteLock(); } DateTime start = DateTime.Now; string startSciprtPath = this.CreateStartScript(instance); var runInfo = new ProcessPrisonRunInfo(); runInfo.WorkingDirectory = Path.Combine(instance.Properties.Directory, "app"); runInfo.FileName = startSciprtPath; instance.Prison.RunProcess(runInfo); Logger.Debug(Strings.TookXTimeToLoadConfigureAndStartDebugMessage, (DateTime.Now - start).TotalSeconds); try { instance.Lock.EnterWriteLock(); if (!instance.Properties.StopProcessed) { this.droplets.ScheduleSnapshotAppState(); } } finally { instance.Lock.ExitWriteLock(); } this.DetectAppReady(instance); } catch (Exception ex) { Logger.Warning(Strings.FailedStagingAppDir, instance.Properties.Directory, instance.Properties.LoggingId, ex.ToString()); try { instance.Lock.EnterWriteLock(); instance.Properties.State = DropletInstanceState.Crashed; instance.Properties.ExitReason = DropletExitReason.Crashed; instance.Properties.StateTimestamp = DateTime.Now; this.StopDroplet(instance); } finally { instance.Lock.ExitWriteLock(); } } }
public void Create(ProcessPrisonCreateInfo createInfo) { if (createInfo.Id == null) this.Id = GenerateSecureGuid().ToString(); else this.Id = createInfo.Id; string[] keys = new string[] { "ALLUSERSPROFILE", "APPDATA", "CommonProgramFiles", "CommonProgramFiles(x86)", "CommonProgramW6432", "COMPUTERNAME", "HOMEDRIVE", "LOCALAPPDATA", "NUMBER_OF_PROCESSORS", "OS", "Path", "PROCESSOR_ARCHITECTURE", "PROCESSOR_IDENTIFIER", "PROCESSOR_LEVEL", "PROCESSOR_REVISION", "ProgramData", "ProgramFiles", "ProgramFiles(x86)", "ProgramW6432", "PROMPT", "PSModulePath", "SystemDrive", "SystemRoot", "windir" }; this.myenvvars["HOMEPATH"] = createInfo.DiskQuotaPath; this.myenvvars["TEMP"] = Path.Combine(createInfo.DiskQuotaPath, "tmp"); this.myenvvars["TMP"] = Path.Combine(createInfo.DiskQuotaPath, "tmp"); foreach (string key in keys) { this.myenvvars[key] = Environment.GetEnvironmentVariable(key); } this.createInfo = createInfo; this.jobObject = new JobObject(JobObjectNamespace() + this.Id); this.jobObject.ActiveProcessesLimit = this.createInfo.RunningProcessesLimit; this.jobObject.JobMemoryLimitBytes = this.createInfo.TotalPrivateMemoryLimitBytes; this.jobObject.KillProcessesOnJobClose = this.createInfo.KillProcessesrOnPrisonClose; if (this.createInfo.WindowsPassword == null) this.WindowsPassword = GenerateSecurePassword(40); else this.WindowsPassword = this.createInfo.WindowsPassword; this.WindowsUsername = CreateDecoratedUser(this.Id, this.WindowsPassword); if (this.createInfo.DiskQuotaBytes > -1) { if (string.IsNullOrEmpty(this.createInfo.DiskQuotaPath)) { // set this.createInfo.DiskQuotaPath to the output of GetUserProfileDirectory throw new NotImplementedException(); } // Set the disk quota to 0 for all disks, exept disk quota path var volumesQuotas = DiskQuotaManager.GetDisksQuotaUser(this.WindowsUsername); foreach (var volumeQuota in volumesQuotas) { volumeQuota.QuotaLimit = 0; } userQuota = DiskQuotaManager.GetDiskQuotaUser(DiskQuotaManager.GetVolumeRootFromPath(this.createInfo.DiskQuotaPath), this.WindowsUsername); userQuota.QuotaLimit = this.createInfo.DiskQuotaBytes; } if (this.createInfo.UrlPortAccess > 0) { UrlsAcl.AddPortAccess(this.createInfo.UrlPortAccess, this.WindowsUsername); } if (this.createInfo.NetworkOutboundRateLimitBitsPerSecond > 0) { NetworkQos.CreateOutboundThrottlePolicy(this.WindowsUsername, this.WindowsUsername, this.createInfo.NetworkOutboundRateLimitBitsPerSecond); if (this.createInfo.UrlPortAccess > 0) { NetworkQos.CreateOutboundThrottlePolicy(this.createInfo.UrlPortAccess.ToString(), this.createInfo.UrlPortAccess, this.createInfo.NetworkOutboundRateLimitBitsPerSecond); } } this.Created = true; }
static void Main(string[] args) { Console.WriteLine("--- PrisonProcess REPL ---\n"); Console.WriteLine("Use the following keys:"); Console.WriteLine("\tc: Create a new cmd prison"); Console.WriteLine("\tn: Create a new notepad prison"); Console.WriteLine("\td: Destroy all prissons"); Console.WriteLine("\tq: Quit"); List<ProcessPrison> prisonss = new List<ProcessPrison>(); DiskQuotaManager.StartQuotaInitialization(); while (!DiskQuotaManager.IsQuotaInitialized()) { Thread.Sleep(100); } var usersDesc = WindowsUsersAndGroups.GetUsersDescription(); foreach (var desc in usersDesc.Values) { try { var id = ProcessPrison.GetIdFromUserDescription(desc); var ppci = new ProcessPrisonCreateInfo(); ppci.Id = id; ppci.TotalPrivateMemoryLimitBytes = 128 * 1024 * 1024; ppci.DiskQuotaBytes = 128 * 1024 * 1024; ppci.DiskQuotaPath = @"C:\Users\Public"; // Cannot impersonate the user to create new processes or access the user's env. ppci.WindowsPassword = "******"; var pp = new ProcessPrison(); pp.Attach(ppci); prisonss.Add(pp); } catch(ArgumentException) { } } while (true) { var key = Console.ReadKey(); if (key.Key == ConsoleKey.Q && key.Modifiers == ConsoleModifiers.Shift) break; switch (key.Key) { case ConsoleKey.C: { var ppci = new ProcessPrisonCreateInfo(); ppci.TotalPrivateMemoryLimitBytes = 128 * 1000 * 1000; ppci.DiskQuotaBytes = 128 * 1024 * 1024; ppci.DiskQuotaPath = @"C:\Users\Public"; ppci.NetworkOutboundRateLimitBitsPerSecond = 80 * 1000; var pp = new ProcessPrison(); pp.Create(ppci); pp.SetUsersEnvironmentVariable("prison", pp.Id); var ri = new ProcessPrisonRunInfo(); ri.Interactive = true; ri.FileName = @"C:\Windows\System32\cmd.exe"; ri.Arguments = String.Format(" /k title {1} & echo Wedcome to prisson {0}. & echo Running under user {1} & echo Private virtual memory limit: {2} B", pp.Id, pp.WindowsUsername, ppci.TotalPrivateMemoryLimitBytes); ri.Arguments += " & echo. & echo Cmd bomb for memory test: & echo 'set loop=cmd /k ^%loop^%' & echo 'cmd /k %loop%'"; ri.Arguments += " & echo. & echo Ruby file server for network test: & echo 'rackup -b 'run Rack::Directory.new(\"\")''"; pp.RunProcess(ri); prisonss.Add(pp); } break; case ConsoleKey.N: { var ppci = new ProcessPrisonCreateInfo(); ppci.TotalPrivateMemoryLimitBytes = 128 * 1024 * 1024; ppci.DiskQuotaBytes = 128 * 1024 * 1024; ppci.DiskQuotaPath = @"C:\Users\Public"; var pp = new ProcessPrison(); pp.Create(ppci); pp.SetUsersEnvironmentVariable("prison", pp.Id); var ri = new ProcessPrisonRunInfo(); ri.Interactive = true; ri.FileName = @"C:\Windows\System32\notepad.exe"; pp.RunProcess(ri); prisonss.Add(pp); } break; case ConsoleKey.D: foreach (var prison in prisonss) { prison.Destroy(); } prisonss.Clear(); break; case ConsoleKey.Q: return; } } var createInfo = new ProcessPrisonCreateInfo(); var p = new ProcessPrison(); p.Create(createInfo); var envs = p.GetUsersEnvironmentVariables(); var runInfo = new ProcessPrisonRunInfo(); runInfo.Interactive = false; runInfo.FileName = @"C:\Windows\System32\cmd.exe"; runInfo.FileName = @"C:\Windows\System32\PING.EXE"; // runInfo.Arguments = @"/c echo %PATH% & ping 10.0.0.10" ; runInfo.Arguments = @" /k rackup -b ""run lambda {|env| [200, {'Content-Type'=>'text/html'}, 'Hello World']}"" -P 2345"; runInfo.Arguments = " 10.0.0.10 -t"; runInfo.WorkingDirectory = @"C:\Users\Public"; runInfo.FileName = @"C:\Windows\System32\mspaint.exe"; runInfo.Arguments = ""; p.RunProcess(runInfo); //p.RunProcess(@"C:\Windows\System32\mspaint.exe"); Console.ReadKey(); p.Destroy(); }
public void CreatePrison() { if(this.Prison.Created) { this.Prison.Destroy(); } this.Lock.EnterWriteLock(); var prisonInfo = new ProcessPrisonCreateInfo(); prisonInfo.TotalPrivateMemoryLimitBytes = this.Properties.MemoryQuotaBytes; if (this.Properties.UseDiskQuota) { prisonInfo.DiskQuotaBytes = this.Properties.DiskQuotaBytes; prisonInfo.DiskQuotaPath = this.Properties.Directory; } if (this.Properties.UploadThrottleBitsps > 0) { prisonInfo.NetworkOutboundRateLimitBitsPerSecond = this.Properties.UploadThrottleBitsps; } Logger.Info("Creating Process Prisson: {0}", prisonInfo.Id); this.Prison.Create(prisonInfo); this.Properties.WindowsPassword = this.Prison.WindowsPassword; this.Properties.WindowsUserName = this.Prison.WindowsUsername; this.Properties.InstanceId = this.Prison.Id; this.Lock.ExitWriteLock(); // Explode the app into its directory and optionally bind its local runtime. Directory.CreateDirectory(this.Properties.Directory); DirectoryInfo deploymentDirInfo = new DirectoryInfo(this.Properties.Directory); DirectorySecurity deploymentDirSecurity = deploymentDirInfo.GetAccessControl(); // Owner is important to account for disk quota deploymentDirSecurity.SetOwner(new NTAccount(this.Properties.WindowsUserName)); deploymentDirSecurity.SetAccessRule( new FileSystemAccessRule( this.Properties.WindowsUserName, FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify | FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None | PropagationFlags.InheritOnly, AccessControlType.Allow)); using (new ProcessPrivileges.PrivilegeEnabler(Process.GetCurrentProcess(), ProcessPrivileges.Privilege.Restore)) { deploymentDirInfo.SetAccessControl(deploymentDirSecurity); } }