Linux – How to Jenkins on Linux do builds to Windows servers securely without A.D.

encryptionlinuxpowershellwindowswinrm

I am running Jenkins 1.6 on CentOS 7.2. I have several Windows 2012 servers without A.D. I connect to the Windows machines with local credentials. I have configured a development environment with Python and WinRM on the Linux server. For production my configuration will not work because WinRM is not encrypted.

How do I securely have Jenkins initiate builds on Windows machines without A.D.? I think my requirement of not having A.D. rules out Kerberos. (This link says that both the Linux and Windows servers must be part of the domain. I read elsewhere that it is inadvisable to join a Linux server to an A.D. domain.) I think the only solution would be to use encryption. But how do I do this?

On the Windows server that I set up with Jenkins, I tried to harden it to simulate production requirements: I used this command (from a command prompt opened as Administrator):

winrm set winrm/config/service @{AllowUnencrypted="false"}

But this made my Jenkins builds brake with an error like this:

winrm.exceptions.UnauthorizedError: 401 Unauthorized

My Jenkins builds use Python scripts with the authentication hard coded in them. I cannot have plaintext passwords in production.

If there is not a way to encrypt WinRM from the Linux/Jenkins server without A.D., what are my options for Jenkins pushing builds (running PowerShell commands) in a secure way in production?

Edit 8/16/16: I tried a different method without winrm. I set up SSH between the Linux server with Jenkins and the Windows servers.

How do I enter SSH credentials in Jenkins to do builds on other servers? The connection aspects should be about the same as a Linux server with Jenkins managing builds on other Linux servers as my Windows servers have OpenSSH. I do want to invoke a PowerShell script on the Windows server. Here is what I tried.

In the Jenkins UI, I go to the home page, then to Manage Credentials -> Configure System -> SSH Remote hosts. I click Add server and enter an IP address for the hostname. For the port I use 22. For the username I use gooduser. From the Linux back end of this Jenkins server, I can use gooduser to login via SSH to the Windows server that I entered in Jenkins. So I know the credentials work. I know port 22 is not blocked. But in the Jenkins web UI, I get "Can't connect to server" underneath the username field.

I tried not using a passphrase but pointing the keyfile to a location on the Linux server. I tried this with and without a password. I kept getting "Can't connect to server." Why I am getting this?

I tried adding additional servers beneath. I entered at least a hostname, a username, and a password. I click apply or save. I then click somewhere else in the web UI. But when I go back to SSH Hosts, all the subsequent server credentials are gone. Only the top, first SSH server's settings remain. Why do they go away? The button allows for new fields to appear. The button says "SSH sites that projects will want to connect." What does that mean?

Best Answer

You can configure each Windows server to be a Jenkins node (aka "slave" or "agent"). Then use a pipeline job to control the flow of which commands runs on which node (using node{} blocks).

This will eliminate the need for WinRM, SSH or other remote execution methods.

Securing the Jenkins node-to-master communications can be done using a per-node secret, managed by Jenkins. I do this with ~20 different machines, most Windows-based, some Linux-based, including complex build jobs that require parts that build under Windows and other parts that build under Linux.

Example pipeline code:

node("LinuxBuild") {
    sh """
        ls -l
        echo "Running under Linux!"
    """
}

node("WinBuild") {
    bat """
        dir
        echo Running under Windows!
    """
}

In the above code, LinuxBuild and WinBuild are labels given to one or more Linux or Windows nodes, accordingly.

Related Topic