blob: 46d7c649e73c65c053cdfde0e8dbfa64bfaecaf6 [file] [log] [blame]
Sergey Kolekonovba203982016-12-21 18:32:17 +04001package com.mirantis.mk
2
3/**
4 *
Filip Pytloun49d66302017-03-06 10:26:22 +01005 * SSH functions
Sergey Kolekonovba203982016-12-21 18:32:17 +04006 *
7 */
8
9/**
10 * Ensure entry in SSH known hosts
11 *
12 * @param url url of remote host
13 */
14def ensureKnownHosts(url) {
Filip Pytloun49d66302017-03-06 10:26:22 +010015 def hostArray = getKnownHost(url)
Sergey Galkin2576c7b2017-07-04 14:27:36 +040016 sh "test -f ~/.ssh/known_hosts && grep ${hostArray[0]} ~/.ssh/known_hosts || ssh-keyscan -H -p ${hostArray[1]} ${hostArray[0]} >> ~/.ssh/known_hosts"
Filip Pytloun49d66302017-03-06 10:26:22 +010017}
Sergey Kolekonovba203982016-12-21 18:32:17 +040018
Filip Pytloun49d66302017-03-06 10:26:22 +010019@NonCPS
20def getKnownHost(url){
21 // test for git@github.com:organization/repository like URLs
Filip Pytlouna02d5022017-08-14 11:17:55 +020022 def p = ~/[a-z0-9\._\-]+@(.+\..+)\:{1}.*/
Filip Pytloun49d66302017-03-06 10:26:22 +010023 def result = p.matcher(url)
24 def host = ""
25 if (result.matches()) {
26 host = result.group(1)
27 port = 22
28 } else {
Jakub Josef3e8dd472017-03-22 15:45:05 +010029 // test for protocol
30 if(url.indexOf("://") == -1){
31 url="ssh://" + url
32 }
Filip Pytloun49d66302017-03-06 10:26:22 +010033 parsed = new URI(url)
34 host = parsed.host
35 port = parsed.port && parsed.port > 0 ? parsed.port: 22
36 }
37 return [host,port]
Sergey Kolekonovba203982016-12-21 18:32:17 +040038}
39
40/**
41 * Execute command with ssh-agent
42 *
43 * @param cmd Command to execute
Jakub Josef43863492017-04-04 17:03:55 +020044 * @return STDOUT output
Sergey Kolekonovba203982016-12-21 18:32:17 +040045 */
46def runSshAgentCommand(cmd) {
Sergey Kulanovf36af072017-01-20 13:35:57 +020047 // if file exists, then we started ssh-agent
48 if (fileExists("$HOME/.ssh/ssh-agent.sh")) {
Jakub Josef43863492017-04-04 17:03:55 +020049 return sh(script:". ~/.ssh/ssh-agent.sh && ${cmd}", returnStdout:true)
Sergey Kulanovf36af072017-01-20 13:35:57 +020050 } else {
51 // we didn't start ssh-agent in prepareSshAgentKey() because some ssh-agent
52 // is running. Let's re-use already running agent and re-construct
53 // * SSH_AUTH_SOCK
54 // * SSH_AGENT_PID
Jakub Josef43863492017-04-04 17:03:55 +020055 return sh(script:"""
Sergey Kulanovf36af072017-01-20 13:35:57 +020056 export SSH_AUTH_SOCK=`find /tmp/ -type s -name agent.\\* 2> /dev/null | grep '/tmp/ssh-.*/agent.*' | head -n 1`
57 export SSH_AGENT_PID=`echo \${SSH_AUTH_SOCK} | cut -d. -f2`
58 ${cmd}
Jakub Josef43863492017-04-04 17:03:55 +020059 """, returnStdout: true)
Sergey Kulanovf36af072017-01-20 13:35:57 +020060 }
Sergey Kolekonovba203982016-12-21 18:32:17 +040061}
62
63/**
Filip Pytloun49d66302017-03-06 10:26:22 +010064 * Execute command with ssh-agent (shortcut for runSshAgentCommand)
65 *
66 * @param cmd Command to execute
Jakub Josef43863492017-04-04 17:03:55 +020067 * @return STDOUT output
Filip Pytloun49d66302017-03-06 10:26:22 +010068 */
69def agentSh(cmd) {
Jakub Josef43863492017-04-04 17:03:55 +020070 return runSshAgentCommand(cmd)
Filip Pytloun49d66302017-03-06 10:26:22 +010071}
72
73/**
Vasyl Saienkoe47042f2019-12-24 11:42:27 +020074 * Execute command with ssh-agent with retries and additional options
75 *
76 * @param address address of remote server
77 * @param cmd command to execute
78 * @param user the name of user to execute ssh command with
79 * @param retries number of command retries in case of failure
80 * @param wait delay between retries
81 * @param options additional ssh options
82
83 */
84def executeMachineSshCommand(address, cmd, user = 'ubuntu', retries=5, wait=10, options=null){
85 def common = new com.mirantis.mk.Common()
86 if (!options){
87 options = ['StrictHostKeyChecking': 'no', 'UserKnownHostsFile': '/dev/null']
88 }
89 String optionsString = ''
90 options.each { k,v ->
91 optionsString += "-o ${k}=${v} "
92 }
93
94 common.retry(retries, wait) {
95 return agentSh("ssh ${optionsString} ${user}@${address} '${cmd}'")
96 }
97}
98
99
100/**
Sergey Kolekonovba203982016-12-21 18:32:17 +0400101 * Setup ssh agent and add private key
102 *
103 * @param credentialsId Jenkins credentials name to lookup private key
104 */
105def prepareSshAgentKey(credentialsId) {
iberezovskiyd4240b52017-02-20 17:18:28 +0400106 def common = new com.mirantis.mk.Common()
iberezovskiy67af6c22016-12-26 18:17:21 +0400107 c = common.getSshCredentials(credentialsId)
Sergey Kulanovf36af072017-01-20 13:35:57 +0200108 // create ~/.ssh and delete file ssh-agent.sh which can be stale
109 sh('mkdir -p -m 700 ~/.ssh && rm -f ~/.ssh/ssh-agent.sh')
Filip Pytlounf1b23442017-08-17 11:24:25 +0200110 sh('pgrep -l -u `id -u` -f ssh-agent\$ >/dev/null || ssh-agent|grep -v "Agent pid" > ~/.ssh/ssh-agent.sh')
Sergey Kulanov6307d342016-12-27 14:29:31 +0200111 sh("set +x; echo '${c.getPrivateKey()}' > ~/.ssh/id_rsa_${credentialsId} && chmod 600 ~/.ssh/id_rsa_${credentialsId}; set -x")
Sergey Kolekonovba203982016-12-21 18:32:17 +0400112 runSshAgentCommand("ssh-add ~/.ssh/id_rsa_${credentialsId}")
113}
114
Vasyl Saienko658f3832019-11-27 11:20:54 +0200115/**
116 * Copy files via SCP
117 *
118 * @param source source file
119 * @param destination desination file
120 * @param options additional scp options
121
122 */
123def executeMachineScpCommand(source, destination, options=null){
124 if (!options){
125 options = ['StrictHostKeyChecking': 'no', 'UserKnownHostsFile': '/dev/null']
126 }
127 String optionsString = ''
128 options.each { k,v ->
129 optionsString += "-o ${k}=${v} "
130 }
131
132 agentSh("scp ${optionsString} ${source} ${destination}")
133}
134
135
Sergey Kolekonovba203982016-12-21 18:32:17 +0400136return this;