/// <summary> /// A numerical representing a permission matrix. These permissions are overridden on Windows platforms, and are therefore useless on such a host. Default value on UNIX platforms are 644. If left empty, no permissioins will be applied. /// </summary> /// <param name="permissions"></param> /// <param name="filePath"></param> public void ApplySecurityPermissions(string permissions, string filePath) { // Don't apply if empty if (String.IsNullOrEmpty(permissions)) { return; } try { byte[] buffer = Encoding.Default.GetBytes(permissions); int perm = 0; foreach (byte t in buffer) { int currentPos = t; if (currentPos < '0' || currentPos > '7') { perm = -1; break; } perm <<= 3; perm |= currentPos - '0'; } _sftp.ChangePermissions(filePath, (short)perm); } catch { throw new Exception("Unable to parse permissions to integer"); } }
private void TransferPrereqs(SshClient sshClient, ServerDistro distro) { string prereqsPath = (distro == ServerDistro.RPM) ? rpmPackages : debianPackages; using (var sftpClient = new SftpClient(sshClient.ConnectionInfo)) { sftpClient.Connect(); List <string> files = ListPrereqsFiles(prereqsPath); foreach (string file in files) { using (var fileStream = new FileStream(file, FileMode.Open)) { Console.WriteLine("Uploading {0} ({1:N0} bytes)", file, fileStream.Length); sftpClient.BufferSize = 4 * 1024; // bypass Payload error large files string path = file.Remove(file.IndexOf(Path.GetFileName(file))).Replace(@"\", "/"); string filename = Path.GetFileName(file); string[] dirs = path.TrimEnd('/').Split('/'); foreach (var dir in dirs) { try { if (!sftpClient.Exists(dir)) { sftpClient.CreateDirectory(dir); } sftpClient.ChangeDirectory(dir); } catch { //Log: Directory already exists } } if (sftpClient.Exists(filename)) { sftpClient.UploadFile(fileStream, filename); } sftpClient.ChangePermissions(filename, 755); sftpClient.ChangeDirectory("/home/" + sshClient.ConnectionInfo.Username); } } } ////chmod +x for the file to be executable //var cmd = sshClient.CreateCommand("chmod +x ./" + Path.GetFileName(agentPath)); //var result = cmd.BeginExecute(); //using (var reader = new StreamReader(cmd.OutputStream, Encoding.UTF8, true, 1024, true)) //{ // while (!result.IsCompleted || !reader.EndOfStream) // { // string line = reader.ReadLine(); // if (line != null) // { // //Log: result // } // } //} //cmd.EndExecute(result); }
private static bool Upload(ref SftpClient sftp, string FileName, string Source, string TargetDir, short SetPermissions = 0) { string _stage = ""; string _file = TargetDir + FileName; try { // _stage = "Checkings"; if (SetPermissions != 0) { if (SetPermissions < 700 || SetPermissions > 777) { throw new Exception($"Wrong permissions: {SetPermissions}"); } } if (!File.Exists(Source)) { throw new Exception("Source file not found."); } if (sftp.Exists(_file)) { throw new Exception("Target file already exists."); } // _stage = "Changing remote directory"; sftp.ChangeDirectory(TargetDir); // _stage = "Uploading file"; using (FileStream fs = new FileStream(Source, FileMode.Open)) { sftp.BufferSize = 4 * 1024; sftp.UploadFile(fs, Path.GetFileName(Source)); if (SetPermissions != 0) { sftp.ChangePermissions(_file, SetPermissions); } } } catch (Exception ex) { Console.WriteLine($"[{_stage}] {ex.Message}"); return(false); } // OK return(true); }
public override string GetCommandText(ActConsoleCommand act) { string cmd = ""; switch (act.ConsoleCommand) { case ActConsoleCommand.eConsoleCommand.FreeCommand: return(GetParameterizedCommand(act)); case ActConsoleCommand.eConsoleCommand.ParametrizedCommand: return(GetParameterizedCommand(act)); case ActConsoleCommand.eConsoleCommand.Script: VerifyFTPConnected(); if (!UnixFTPClient.Exists(workdir + @"/Ginger")) { UnixFTPClient.CreateDirectory(workdir + @"/Ginger"); } string SHFilesPath = mScriptsFolder; string UnixScriptFilePath = workdir + @"/Ginger/" + act.ScriptName; using (var f = File.OpenRead(SHFilesPath + act.ScriptName)) { UnixFTPClient.UploadFile(f, UnixScriptFilePath, null); } UnixFTPClient.ChangePermissions(UnixScriptFilePath, 777); foreach (var p in act.InputValues) { if (!string.IsNullOrEmpty(p.Value)) { cmd += " " + p.ValueForDriver; } } if (UnixScriptFilePath.Trim().EndsWith(".sh", StringComparison.CurrentCultureIgnoreCase)) { return("dos2unix " + UnixScriptFilePath + ";sh " + UnixScriptFilePath + cmd); } else { return("dos2unix " + UnixScriptFilePath + "; " + UnixScriptFilePath + cmd); } default: Reporter.ToLog(eLogLevel.WARN, "Error - unknown command"); ErrorMessageFromDriver += "Error - unknown command"; return("Error - unknown command"); } }
public bool Upload(string fileName, string sourceDir, string targetDir, short setPermissions = 0) { string _stage = ""; string _sourceFile = sourceDir + fileName; string _targetFile = targetDir + fileName; try { // _stage = "Checkings"; if (setPermissions != 0) { if (setPermissions < 700 || setPermissions > 777) { throw new Exception($"Wrong permissions: {setPermissions}"); } } if (!File.Exists(_sourceFile)) { throw new Exception("Source file not found."); } if (pSFtp.Exists(_targetFile)) { throw new Exception("Target file already exists."); } // _stage = "Changing remote directory"; pSFtp.ChangeDirectory(targetDir); // _stage = "Uploading file"; using (FileStream fs = new FileStream(_sourceFile, FileMode.Open)) { pSFtp.BufferSize = 4 * 1024; pSFtp.UploadFile(fs, Path.GetFileName(_sourceFile)); if (setPermissions != 0) { pSFtp.ChangePermissions(_targetFile, setPermissions); } } } catch (Exception ex) { throw new Exception($"[Upload#{_stage}] {ex.Message}"); } // OK return(true); }
public bool RemoteChangePermissions(string fileName, short setPermissions) { string _stage = ""; // _stage = "Changing file permissions"; try { pSFtp.ChangePermissions(fileName, setPermissions); } catch (Exception ex) { throw new Exception($"[RemoteChangePermissions#{_stage}] {ex.Message}."); } return(true); }
private void TransferAgents(SshClient sshClient, ServerArchitecture arch) { string agentPath = (arch == ServerArchitecture.x64) ? x64Agent : x86Agent; using (var sftpClient = new SftpClient(sshClient.ConnectionInfo)) { sftpClient.Connect(); if (sftpClient.Exists(Path.GetFileName(agentPath))) { //Log: Agent already exists on destination return; } using (var fileStream = new FileStream(agentPath, FileMode.Open)) { string filename = Path.GetFileName(agentPath); Console.WriteLine("Uploading {0} ({1:N0} bytes)", agentPath, fileStream.Length); sftpClient.BufferSize = 4 * 1024; // bypass Payload error large files sftpClient.UploadFile(fileStream, filename); sftpClient.ChangePermissions(filename, 755); } } }
/// <summary> /// Sync <paramref name="sourceDir"/> with <paramref name="destDir"/> /// </summary> /// <param name="connectInfo">Credentials to access host where synchronization takes place.</param> /// <param name="sourceDir">Source directory on the local host.</param> /// <param name="destDir">Destination directory on the remote host</param> /// <param name="logger">Logging facility</param> /// <returns><c>true</c> if successful; otherwise, <c>false</c>.</returns> private static bool SyncTo(ConnectionInfo connectInfo, UDirectory sourceDir, UDirectory destDir, LoggerResult logger) { // Copy files over using (var sftp = new SftpClient(connectInfo)) { try { sftp.Connect(); if (!sftp.IsConnected) { return(false); } } catch { logger.Error("Cannot connect"); return(false); } // Perform recursive copy of all the folders under `sourceDir`. This is required // as the sftp client only synchronize directories at their level only, no // subdirectory. var dirs = new Queue <DirectoryInfo>(); dirs.Enqueue(new DirectoryInfo(sourceDir)); var parentPath = sourceDir; while (dirs.Count != 0) { var currentDir = dirs.Dequeue(); var currentPath = new UDirectory(currentDir.FullName); foreach (var subdir in currentDir.EnumerateDirectories()) { dirs.Enqueue(subdir); } // Get the destination path by adding to `Location` the relative path of `sourceDir` to `currentDir`. var destination = UPath.Combine(destDir, currentPath.MakeRelative(parentPath)); logger.Info("Synchronizing " + currentPath + " with " + destination.FullPath); // Try to create a remote directory. If it throws an exception, we will assume // for now that the directory already exists. See https://github.com/sshnet/SSH.NET/issues/25 try { sftp.CreateDirectory(destination.FullPath); logger.Info("Creating remote directory " + destination.FullPath); } catch (SshException) { // Do nothing, as this is when the directory already exists } // Synchronize files. foreach (var file in sftp.SynchronizeDirectories(currentPath.FullPath, destination.FullPath, "*")) { logger.Info("Updating " + file.Name); // Some of our files needs executable rights, however we do not know in advance which one // need it. For now all files will be rwxr.xr.x (0755 in octal but written in decimal for readability). sftp.ChangePermissions(destination.FullPath + "/" + file.Name, 755); } } return(true); } }
/// <summary> /// Used for temporarily uploading an ISO disk to a XenServer such that it can be mounted /// to a VM, typically for one-time initialization purposes. neonKUBE uses this as a very /// simple poor man's alternative to <b>cloud-init</b> for initializing a VM on first boot. /// </summary> /// <param name="isoPath">Path to the source ISO file on the local workstation.</param> /// <param name="srName">Optionally specifies the storage repository name. <b>neon-UUID</b> with a generated UUID will be used by default.</param> /// <returns>A <see cref="XenTempIso"/> with information about the new storage repository and its contents.</returns> /// <remarks> /// <para> /// During cluster setup on virtualization platforms like XenServer and Hyper-V, neonKUBE need /// to configure new VMs with IP addresses, hostnames, etc. Traditionally, we've relied on /// being able to SSH into the VM to perform all of these actions, but this relied on being /// VM being able to obtain an IP address via DHCP and for setup to be able to discover the /// assigned address. /// </para> /// <para> /// The dependency on DHCP is somewhat problematic, because it's conceivable that this may /// not be available for more controlled environments. We looked into using Linux <b>cloud-init</b> /// for this, but that requires additional local infrastructure for non-cloud deployments and /// was also a bit more complex than what we had time for. /// </para> /// <para> /// Instead of <b>cloud-init</b>, we provisioned our XenServer and Hyper-V node templates /// with a <b>neon-init</b> service that runs before the network service to determine /// whether a DVD (ISO) is inserted into the VM and runs the <b>neon-init.sh</b> script /// there one time, if it exists. This script will initialize the node's IP address and /// could also be used for other configuration as well, like setting user credentials. /// </para> /// <note> /// In theory, we could have used the same technique for mounting a <b>cloud-init</b> data source /// via this ISO, but we decided not to go there, at least for now (we couldn't get that working). /// </note> /// <note> /// neonKUBE doesn't use this technique for true cloud deployments (AWS, Azure, Google,...) because /// we can configure VM networking directly via the cloud APIs. /// </note> /// <para> /// The XenServer requires the temporary ISO implementation to be a bit odd. We want these temporary /// ISOs to be created directly on the XenServer host machine so users won't have to configure any /// additional infrastructure as well as to simplify cluster setup. We'll be creating a local /// ISO storage repository from a folder on the host. Any files to be added to the repository /// must exist when the repository is created and it is not possible to add, modify, or remove /// files from a repository after its been created. /// </para> /// <note> /// XenServer hosts have only 4GB of free space at the root Linux level, so you must take care /// not to create large ISOs or to allow these to accumulate. /// </note> /// <para> /// This method uploads the ISO file <paramref name="isoPath"/> from the local workstation to /// the XenServer host, creating a new folder named with a UUID. Then a new storage repository /// will be created from this folder and a <see cref="XenTempIso"/> will be returned holding /// details about the new storage repository and its contents. The setup code will use this to /// insert the ISO into a VM. /// </para> /// <para> /// Once the setup code is done with the ISO, it will eject it from the VM and call /// <see cref="RemoveTempIso(XenTempIso)"/> to remove the storage repository. /// </para> /// </remarks> public XenTempIso CreateTempIso(string isoPath, string srName = null) { Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(isoPath), nameof(isoPath)); if (string.IsNullOrEmpty(srName)) { srName = "neon-" + Guid.NewGuid().ToString("d"); } var tempIso = new XenTempIso(); // Create the temporary SR subfolder and upload the ISO file. var srMountPath = "/var/run/sr-mount"; tempIso.SrPath = LinuxPath.Combine(srMountPath, Guid.NewGuid().ToString("d")); tempIso.IsoName = $"neon-dvd-{Guid.NewGuid().ToString("d")}.iso"; if (!sftpClient.PathExists(srMountPath)) { sftpClient.CreateDirectory(srMountPath); } if (!sftpClient.PathExists(tempIso.SrPath)) { sftpClient.CreateDirectory(tempIso.SrPath); sftpClient.ChangePermissions(tempIso.SrPath, Convert.ToInt16("751", 8)); } var xenIsoPath = LinuxPath.Combine(tempIso.SrPath, tempIso.IsoName); using (var isoInput = File.OpenRead(isoPath)) { sftpClient.UploadFile(isoInput, xenIsoPath); sftpClient.ChangePermissions(xenIsoPath, Convert.ToInt16("751", 8)); } // Create the new storage repository. This command returns the [sr-uuid]. var response = SafeInvoke("sr-create", $"name-label={tempIso.IsoName}", $"type=iso", $"device-config:location={tempIso.SrPath}", $"device-config:legacy_mode=true", $"content-type=iso"); tempIso.SrUuid = response.OutputText.Trim(); // XenServer created a PBD behind the scenes for the new SR. We're going // to need its UUID so we can completely remove the SR later. Note that // doesn't seem to appear immediately so, we'll retry a few times. var retry = new ExponentialRetryPolicy(typeof(InvalidOperationException), maxAttempts: 5, initialRetryInterval: TimeSpan.FromSeconds(0.5), maxRetryInterval: TimeSpan.FromSeconds(5)); retry.Invoke( () => { var result = SafeInvokeItems("pbd-list", $"sr-uuid={tempIso.SrUuid}"); tempIso.PdbUuid = result.Items.Single()["uuid"]; // Obtain the UUID for the ISO's VDI within the SR. result = SafeInvokeItems("vdi-list", $"sr-uuid={tempIso.SrUuid}"); tempIso.VdiUuid = result.Items.Single()["uuid"]; }); return(tempIso); }
public void ChangePermissionsTest() { ConnectionInfo connectionInfo = null; // TODO: Initialize to an appropriate value SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value string path = string.Empty; // TODO: Initialize to an appropriate value short mode = 0; // TODO: Initialize to an appropriate value target.ChangePermissions(path, mode); Assert.Inconclusive("A method that does not return a value cannot be verified."); }