Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
a51747f9
Commit
a51747f9
authored
May 27, 2015
by
Brendan Burns
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move SSH code into a common util package. Add support for SSH tunnels.
parent
b7caedee
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
176 additions
and
51 deletions
+176
-51
ssh.go
pkg/util/ssh.go
+174
-0
util.go
test/e2e/util.go
+2
-51
No files found.
pkg/util/ssh.go
0 → 100644
View file @
a51747f9
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
util
import
(
"bytes"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"github.com/golang/glog"
"golang.org/x/crypto/ssh"
)
// TODO: Unit tests for this code, we can spin up a test SSH server with instructions here:
// https://godoc.org/golang.org/x/crypto/ssh#ServerConn
type
SSHTunnel
struct
{
Config
*
ssh
.
ClientConfig
Host
string
SSHPort
int
LocalPort
int
RemoteHost
string
RemotePort
int
running
bool
sock
net
.
Listener
client
*
ssh
.
Client
}
func
(
s
*
SSHTunnel
)
copyBytes
(
out
io
.
Writer
,
in
io
.
Reader
)
{
if
_
,
err
:=
io
.
Copy
(
out
,
in
);
err
!=
nil
{
glog
.
Errorf
(
"Error in SSH tunnel: %v"
,
err
)
}
}
func
NewSSHTunnel
(
user
,
keyfile
,
host
,
remoteHost
string
,
localPort
,
remotePort
int
)
(
*
SSHTunnel
,
error
)
{
signer
,
err
:=
MakePrivateKeySigner
(
keyfile
)
if
err
!=
nil
{
return
nil
,
err
}
config
:=
ssh
.
ClientConfig
{
User
:
user
,
Auth
:
[]
ssh
.
AuthMethod
{
ssh
.
PublicKeys
(
signer
)},
}
return
&
SSHTunnel
{
Config
:
&
config
,
Host
:
host
,
SSHPort
:
22
,
LocalPort
:
localPort
,
RemotePort
:
remotePort
,
RemoteHost
:
remoteHost
,
},
nil
}
func
(
s
*
SSHTunnel
)
Open
()
error
{
var
err
error
s
.
client
,
err
=
ssh
.
Dial
(
"tcp"
,
fmt
.
Sprintf
(
"%s:%d"
,
s
.
Host
,
s
.
SSHPort
),
s
.
Config
)
if
err
!=
nil
{
return
err
}
s
.
sock
,
err
=
net
.
Listen
(
"tcp"
,
fmt
.
Sprintf
(
"localhost:%d"
,
s
.
LocalPort
))
if
err
!=
nil
{
return
err
}
s
.
running
=
true
return
nil
}
func
(
s
*
SSHTunnel
)
Listen
()
{
for
s
.
running
{
conn
,
err
:=
s
.
sock
.
Accept
()
if
err
!=
nil
{
glog
.
Errorf
(
"Error listening for ssh tunnel to %s (%v)"
,
s
.
RemoteHost
,
err
)
continue
}
if
err
:=
s
.
tunnel
(
conn
);
err
!=
nil
{
glog
.
Errorf
(
"Error starting tunnel: %v"
,
err
)
}
}
}
func
(
s
*
SSHTunnel
)
tunnel
(
conn
net
.
Conn
)
error
{
tunnel
,
err
:=
s
.
client
.
Dial
(
"tcp"
,
fmt
.
Sprintf
(
"%s:%d"
,
s
.
RemoteHost
,
s
.
RemotePort
))
if
err
!=
nil
{
return
err
}
go
s
.
copyBytes
(
tunnel
,
conn
)
go
s
.
copyBytes
(
conn
,
tunnel
)
return
nil
}
func
(
s
*
SSHTunnel
)
Close
()
error
{
// TODO: try to shutdown copying here?
s
.
running
=
false
// TODO: Aggregate errors and keep going?
if
err
:=
s
.
sock
.
Close
();
err
!=
nil
{
return
err
}
if
err
:=
s
.
client
.
Close
();
err
!=
nil
{
return
err
}
return
nil
}
func
RunSSHCommand
(
cmd
,
host
string
,
signer
ssh
.
Signer
)
(
string
,
string
,
int
,
error
)
{
// Setup the config, dial the server, and open a session.
config
:=
&
ssh
.
ClientConfig
{
User
:
os
.
Getenv
(
"USER"
),
Auth
:
[]
ssh
.
AuthMethod
{
ssh
.
PublicKeys
(
signer
)},
}
client
,
err
:=
ssh
.
Dial
(
"tcp"
,
host
,
config
)
if
err
!=
nil
{
return
""
,
""
,
0
,
fmt
.
Errorf
(
"error getting SSH client to host %s: '%v'"
,
host
,
err
)
}
session
,
err
:=
client
.
NewSession
()
if
err
!=
nil
{
return
""
,
""
,
0
,
fmt
.
Errorf
(
"error creating session to host %s: '%v'"
,
host
,
err
)
}
defer
session
.
Close
()
// Run the command.
code
:=
0
var
bout
,
berr
bytes
.
Buffer
session
.
Stdout
,
session
.
Stderr
=
&
bout
,
&
berr
if
err
=
session
.
Run
(
cmd
);
err
!=
nil
{
// Check whether the command failed to run or didn't complete.
if
exiterr
,
ok
:=
err
.
(
*
ssh
.
ExitError
);
ok
{
// If we got an ExitError and the exit code is nonzero, we'll
// consider the SSH itself successful (just that the command run
// errored on the host).
if
code
=
exiterr
.
ExitStatus
();
code
!=
0
{
err
=
nil
}
}
else
{
// Some other kind of error happened (e.g. an IOError); consider the
// SSH unsuccessful.
err
=
fmt
.
Errorf
(
"failed running `%s` on %s: '%v'"
,
cmd
,
host
,
err
)
}
}
return
bout
.
String
(),
berr
.
String
(),
code
,
err
}
func
MakePrivateKeySigner
(
key
string
)
(
ssh
.
Signer
,
error
)
{
// Create an actual signer.
file
,
err
:=
os
.
Open
(
key
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error opening SSH key %s: '%v'"
,
key
,
err
)
}
defer
file
.
Close
()
buffer
,
err
:=
ioutil
.
ReadAll
(
file
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error reading SSH key %s: '%v'"
,
key
,
err
)
}
signer
,
err
:=
ssh
.
ParsePrivateKey
(
buffer
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error parsing SSH key %s: '%v'"
,
key
,
err
)
}
return
signer
,
nil
}
test/e2e/util.go
View file @
a51747f9
...
@@ -19,7 +19,6 @@ package e2e
...
@@ -19,7 +19,6 @@ package e2e
import
(
import
(
"bytes"
"bytes"
"fmt"
"fmt"
"io/ioutil"
"math"
"math"
"math/rand"
"math/rand"
"os"
"os"
...
@@ -956,41 +955,7 @@ func SSH(cmd, host, provider string) (string, string, int, error) {
...
@@ -956,41 +955,7 @@ func SSH(cmd, host, provider string) (string, string, int, error) {
return
""
,
""
,
0
,
fmt
.
Errorf
(
"error getting signer for provider %s: '%v'"
,
provider
,
err
)
return
""
,
""
,
0
,
fmt
.
Errorf
(
"error getting signer for provider %s: '%v'"
,
provider
,
err
)
}
}
// Setup the config, dial the server, and open a session.
return
util
.
RunSSHCommand
(
cmd
,
host
,
signer
)
config
:=
&
ssh
.
ClientConfig
{
User
:
os
.
Getenv
(
"USER"
),
Auth
:
[]
ssh
.
AuthMethod
{
ssh
.
PublicKeys
(
signer
)},
}
client
,
err
:=
ssh
.
Dial
(
"tcp"
,
host
,
config
)
if
err
!=
nil
{
return
""
,
""
,
0
,
fmt
.
Errorf
(
"error getting SSH client to host %s: '%v'"
,
host
,
err
)
}
session
,
err
:=
client
.
NewSession
()
if
err
!=
nil
{
return
""
,
""
,
0
,
fmt
.
Errorf
(
"error creating session to host %s: '%v'"
,
host
,
err
)
}
defer
session
.
Close
()
// Run the command.
code
:=
0
var
bout
,
berr
bytes
.
Buffer
session
.
Stdout
,
session
.
Stderr
=
&
bout
,
&
berr
if
err
=
session
.
Run
(
cmd
);
err
!=
nil
{
// Check whether the command failed to run or didn't complete.
if
exiterr
,
ok
:=
err
.
(
*
ssh
.
ExitError
);
ok
{
// If we got an ExitError and the exit code is nonzero, we'll
// consider the SSH itself successful (just that the command run
// errored on the host).
if
code
=
exiterr
.
ExitStatus
();
code
!=
0
{
err
=
nil
}
}
else
{
// Some other kind of error happened (e.g. an IOError); consider the
// SSH unsuccessful.
err
=
fmt
.
Errorf
(
"failed running `%s` on %s: '%v'"
,
cmd
,
host
,
err
)
}
}
return
bout
.
String
(),
berr
.
String
(),
code
,
err
}
}
// getSigner returns an ssh.Signer for the provider ("gce", etc.) that can be
// getSigner returns an ssh.Signer for the provider ("gce", etc.) that can be
...
@@ -1012,21 +977,7 @@ func getSigner(provider string) (ssh.Signer, error) {
...
@@ -1012,21 +977,7 @@ func getSigner(provider string) (ssh.Signer, error) {
key
:=
filepath
.
Join
(
keydir
,
keyfile
)
key
:=
filepath
.
Join
(
keydir
,
keyfile
)
Logf
(
"Using SSH key: %s"
,
key
)
Logf
(
"Using SSH key: %s"
,
key
)
// Create an actual signer.
return
util
.
MakePrivateKeySigner
(
key
)
file
,
err
:=
os
.
Open
(
key
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error opening SSH key %s: '%v'"
,
key
,
err
)
}
defer
file
.
Close
()
buffer
,
err
:=
ioutil
.
ReadAll
(
file
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error reading SSH key %s: '%v'"
,
key
,
err
)
}
signer
,
err
:=
ssh
.
ParsePrivateKey
(
buffer
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error parsing SSH key %s: '%v'"
,
key
,
err
)
}
return
signer
,
nil
}
}
// LatencyMetrics stores data about request latency at a given quantile
// LatencyMetrics stores data about request latency at a given quantile
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment