Cross-platform C SDK logo

Cross-platform C SDK

Enable SSH

❮ Back
Next ❯
This page has been automatically translated using the Google Translate API services. We are working on improving texts. Thank you for your understanding and patience.

The basis of Continuous Integration is network communication or, more specifically, the possibility of executing commands remotely from one machine to another. Today the standard is SSH (Secure Shell), a protocol and application that allows executing commands over a network, adding an encryption layer between sender and receiver (Listing 1) (Listing 1). We must ensure that SSH is present and working on all machines of the Build Grid.

Listing 1: Get the list of files from a remote machine using SSH.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
C:\Users>ssh fran@192.168.1.24 ls
fran@192.168.1.24's password:
Desktop
Documents
Downloads
examples.desktop
Music
Pictures
Public
Templates
Videos
Communication of two computers via SSH indicating the encryption of the information.
Figure 1: The SSH protocol encrypts the information exchanged by two nodes.

1. SSH in Windows

Windows 10 includes support for SSH, but it is not active by default. You must activate it in Settings->Apps->Manage Optional Features->Add a Feature->OpenSSH Client/Server (Figure 2). To ensure that service is running, run services.msc and starts OpenSSH SSH Server if he is not running anymore.

Capture SSH options in Windows 10.
Figure 2: Activation of SSH in Windows.

2. SSH in macOS

SSH is also included in Apple's operating systems. To activate it:

  • Opens System Preferencesfrom the Apple menu and click on the Sharing panel.
  • Activate the option Remote Login (Figure 3).
  • This will instantly boot several services, including SFTP and SSH.

For security reasons, SSH does not access all the bash shell environment variables in macOS. This can cause a remote command to fail, but typing from a terminal on the machine itself does work. For example, this occurs when trying to run cmake or svnremote form. To correct it:

  • We add the necessary paths to the variable PATHin /.ssh/environment.
  • Listing 2: Modification of PATHin /.ssh/environment
    1
    
    PATH=$PATH:/bin:/usr/bin:/Applications/CMake.app/Contents/bin
    
  • We edit the file /etc/ssh/sshd_config, enabling the variable PermitUserEnvironment yes.
  • We stopped and re-launched the service by check Remote Login for Sharing.
  • Capture SSH options in macOS.
    Figure 3: SSH activation in macOS.

3. SSH in Linux

By default, SSH is not included in Ubuntu. For this distribution and others based on Debian, the service is installed and activated with this command.

1
sudo apt-get install openssh-server -y

4. SSH without password

Once SSH is activated on all the machines in the network, we can already execute remote commands from the Build Master as we have seen in (Listing 1) . The problem is that SSH will continuously ask us for the password of the remote user, something that will hinder the automation of the CI system. To avoid this, we have to install the rsa certificate of the Build Master on all remote machines (the Build Host ) so that they recognize the issuer of the command and do not ask for a password.

  • From the Build Master, open a terminal and type ssh-keygen. This will generate two rsa certificates in .ssh a private one, that will stay in the master and another public that will go to the host.
  • Listing 4: Generating the rsa certificate in the Master.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    fran~>ssh-keygen
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/fran/.ssh/id_rsa): 
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /home/fran/.ssh/id_rsa.
    Your public key has been saved in /home/fran/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:Up6KjbnEV4Hgfo75YM393QdQsK3Z0aTNBz0DoirrW+c fran@192.168.1.24
    The key's randomart image is:
    +---[RSA 2048]----+
    |    .      ..oo..|
    |   . . .  . .o.X.|
    |    . . o.  ..+ B|
    |   .   o.o  .+ ..|
    |    ..o.S   o..  |
    |   . %o=      .  |
    |    @.B...     . |
    |   o.=. o. . .  .|
    |    .oo  E. . .. |
    +----[SHA256]-----+
    
  • Copy the file id_rsa.pubin the user directory of each Build Host.
  • Listing 5: Pass the rsa certificate from the Master to the Host
    1
    2
    
    cd .ssh
    scp id_rsa.pub fran@192.168.1.24:/Users/fran/.ssh
    
  • Open a terminal on the Host and type:
  • Listing 6: Installing the rsa certificate
    1
    2
    3
    4
    5
    
    cd .ssh
    type id_rsa.pub >> authorized_keys   (Windows)
    ...
    cd .ssh
    cat id_rsa.pub >> authorized_keys    (macOS/Linux)
    
  • If everything went well, we can already execute a remote command without asking us for a password (Figure 4), since the SSH server running on the Build Host recognizes the Build Master computer.
  • Listing 7: SSH without password.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    C:\Users>ssh fran@192.168.1.24 ls
    Desktop
    Documents
    Downloads
    examples.desktop
    Music
    Pictures
    Public
    Templates
    Videos
    
    Ssh command on remote machine without password.
    Figure 4: Executing a command on a remote machine without using password .

5. SSH from C

The CI system must be able to launch SSH commands from the program itself instead of the terminal, in order to coordinate the Build Host to complete the tasks of the Build Profile . In (Listing 8) we see how to do it from the C language. In Launching processes you have more information about the NAppGUI multi-processing API.

Listing 8: Executing an SSH command from a C procedure.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Proc *proc = bproc_exec("ssh fran@192.168.1.24 ls", NULL, NULL);
if (proc != NULL)
{
    byte_t buffer[512];
    uint32_t rsize;
    Stream *stm = stm_memory(1024);
    while (bproc_read(proc, buffer, sizeof(buffer), &rsize, NULL) == TRUE)
        stm_write(stm, buffer, rsize);

    bproc_wait(proc);
    bproc_close(&proc);
    return stm;
}
❮ Back
Next ❯