Merge remote-tracking branch 'origin/master' into ev/log

This commit is contained in:
Ev Kontsevoy 2016-05-08 11:53:57 -07:00
commit bd9ad5782c
15 changed files with 242 additions and 100 deletions

View file

@ -34,8 +34,11 @@ test: integration
.PHONY:integration
integration: bbox
docker run $(DOCKERFLAGS) $(NOROOT) -i $(BBOX) \
/bin/bash -c "$(MAKE) -C $(SRCDIR) FLAGS='-cover' integration"
echo "Disabled for now"
#
# TODO (ev) enable before next release
# docker run $(DOCKERFLAGS) $(NOROOT) -i $(BBOX) \
# /bin/bash -c "$(MAKE) -C $(SRCDIR) FLAGS='-cover' integration"
#
# Builds docs

View file

@ -323,7 +323,7 @@ func (i *TeleInstance) NewClient(login string, site string, host string, port in
return nil, err
}
tc, err = client.NewClient(&client.Config{
Login: login,
Username: login,
ProxyHost: i.Config.Proxy.SSHAddr.Addr,
Host: host,
HostPort: port,

View file

@ -53,10 +53,7 @@ type IntSuite struct {
// bootstrap check
func TestIntegrations(t *testing.T) { check.TestingT(t) }
var _ = check.Suite(&IntSuite{
priv: []byte(testauthority.Priv),
pub: []byte(testauthority.Pub),
})
var _ = check.Suite(&IntSuite{})
func (s *IntSuite) TearDownSuite(c *check.C) {
var err error
@ -71,6 +68,9 @@ func (s *IntSuite) SetUpSuite(c *check.C) {
utils.InitLoggerForTests()
SetTestTimeouts(100)
s.priv, s.pub, err = testauthority.New().GenerateKeyPair("")
c.Assert(err, check.IsNil)
// find 10 free litening ports to use
s.ports, err = utils.GetFreeTCPPorts(AllocatePortsNum)
if err != nil {

View file

@ -17,6 +17,7 @@ package testauthority
import (
"crypto/rand"
random "math/rand"
"time"
"github.com/gravitational/teleport"
@ -32,43 +33,12 @@ func New() *Keygen {
return &Keygen{}
}
const (
Priv = `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvJGHcmQNWUjY2eKasmw171qZR0B5FOnzy/nAGB1JAE+QokFe
Bjo8Gkk3L2TSuVNn0NI5uo5Jwp7GYtbfSbowo11E922Bwp0sFoVzeeUMyLud9EPz
Hl8+VvE8WEa1lC4D4aqravAfTeeePrONIYoBttX5oYXQ7aZkM8N7yS7KWNOZpy9f
n1vkSCpDOK29edLHWVyiDcXzULxEbXhPFl9Ly9shuEbqic2LRggxBnh3fhy53u8X
5qj8bp+21GGsQJaZYZtc9ieNYamo/KQcA0hFfUgTmV74ehY0vZ7yQk+2dW22cFqw
Dv+xNmnNHlfuYhHNCfk8rnztxfbqHfifgCArQQIDAQABAoIBADhq8jNva+8CtJ68
BbzMU3bBjIqc550yQhcNKkQMvwKwy31AQXlrgv/6V+B+Me3w3mbD/zGp0LfB+Wkp
ELVmV5cJGNFOmjw3+jDizKHzvddxCtlCW0MDDAvHMV7YCQvEmLSz84WTQkp0ugvY
fKlEOS8S5hVFjDUOS3yRSD/xF+lrIlYUaR4gXnDAJZx9ttgfZlHOp8ehxk+1bn59
3Fv1fCXcCKmKUlTk1kFasD8P+2M3MKP42Ih5ap9cfLSVPiBS/6JRBxIlZrHM9/2a
w6vEp+qMwwgCmxLPMwZfem6LNHO/huTrWKf4ltVubb5bUXIe22udKp2WK4NWc3Ka
uG8EleECgYEA4A9Mwd0QJs0j1kpuJDNIjfFx6IROv3QAb0QPq0+192ZF8P9AEj8B
TNDQVzb/skM+2NDdvhZ5v4+OJQcUNpEskhX+5ikk8QHGAUY6vT8rO6oiIRMaxLuJ
OEDc2Qms1OmctTmgSVyaxfXIK2/GDdvOizt0Z7Y7abza4bigEm49hyMCgYEA13MI
H429Ua0tnVVmGJ/4OjnKbgtF7i02r50vDVktPruKWNy1bhRkRyaOoCH7Zt9WXF2j
GapZZN1N/clO4vf9gikH0VCo4Tc2JR635dXdfISlt8NLXmR800Ms1UCAKlwIOQjz
dgHcvEbvFwSe1MFgOJVGL82G2rUA/zDVOKdjXEsCgYAZxyjZlQlqrWdWHDIX0B6k
1gZ47d/xfvMd2gLDfuQ8lnOtinBgqQcJQ2z028sHQ11TrJQWbpeLRoTgFbRposIx
/H3bFRi+8alKND5Fz6K1tpk+nOgTglADPNMr1UUhKc9xujOKvTDBXcmt1ao/pe5Z
bnmyBPFI9QVpusgP1scVaQKBgE5mJYaV5VZbVkXyVXyQeZt2fBsfLwtEmKm+4OhS
kwxI4kcDyWGNOhBKD4xl0T3V928VA8zLGEyD22WGY5Zj93PtylJ4r3uEw8cuLm0M
LdSp0EPWZQ6sMmAOCbpwBjNj2fonL7C5bMF2bnpJzCJPW9w7NZcfivr68qnp8yzy
fE2RAoGBALWvlHVH/29KOVmM52sOk49tcyc3czjs/YANvbokiItxOB8VPY6QQQnS
/CBsCZxUuWegYmkUnstHDmY1LYqjxW4goOqizIksaReivPmsTuQ1qd+aqXTfg2pt
uy6c6X17xkP5q2Lq4i90ikyWm3Oc25aUEw48pRyK/6rABRUzpDLB
-----END RSA PRIVATE KEY-----`
Pub = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8kYdyZA1ZSNjZ4pqybDXvWplHQHkU6fPL+cAYHUkAT5CiQV4GOjwaSTcvZNK5U2fQ0jm6jknCnsZi1t9JujCjXUT3bYHCnSwWhXN55QzIu530Q/MeXz5W8TxYRrWULgPhqqtq8B9N554+s40higG21fmhhdDtpmQzw3vJLspY05mnL1+fW+RIKkM4rb150sdZXKINxfNQvERteE8WX0vL2yG4RuqJzYtGCDEGeHd+HLne7xfmqPxun7bUYaxAlplhm1z2J41hqaj8pBwDSEV9SBOZXvh6FjS9nvJCT7Z1bbZwWrAO/7E2ac0eV+5iEc0J+TyufO3F9uod+J+AICtB`
)
func (n *Keygen) GetNewKeyPairFromPool() ([]byte, []byte, error) {
return n.GenerateKeyPair("")
}
func (n *Keygen) GenerateKeyPair(passphrase string) ([]byte, []byte, error) {
return []byte(Priv), []byte(Pub), nil
randomKey := testPairs[(random.Int() % len(testPairs))]
return randomKey.Priv, randomKey.Pub, nil
}
func (n *Keygen) GenerateHostCert(pkey, key []byte, hostname, authDomain string, role teleport.Role, ttl time.Duration) ([]byte, error) {
@ -126,3 +96,134 @@ func (n *Keygen) GenerateUserCert(pkey, key []byte, teleportUsername string, all
}
return ssh.MarshalAuthorizedKey(cert), nil
}
type PreparedKeyPair struct {
Priv []byte
Pub []byte
}
// for unit tests we have 4 pre-generated pub/priv keypairs
var (
testPairs = []PreparedKeyPair{
{
Priv: []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvJGHcmQNWUjY2eKasmw171qZR0B5FOnzy/nAGB1JAE+QokFe
Bjo8Gkk3L2TSuVNn0NI5uo5Jwp7GYtbfSbowo11E922Bwp0sFoVzeeUMyLud9EPz
Hl8+VvE8WEa1lC4D4aqravAfTeeePrONIYoBttX5oYXQ7aZkM8N7yS7KWNOZpy9f
n1vkSCpDOK29edLHWVyiDcXzULxEbXhPFl9Ly9shuEbqic2LRggxBnh3fhy53u8X
5qj8bp+21GGsQJaZYZtc9ieNYamo/KQcA0hFfUgTmV74ehY0vZ7yQk+2dW22cFqw
Dv+xNmnNHlfuYhHNCfk8rnztxfbqHfifgCArQQIDAQABAoIBADhq8jNva+8CtJ68
BbzMU3bBjIqc550yQhcNKkQMvwKwy31AQXlrgv/6V+B+Me3w3mbD/zGp0LfB+Wkp
ELVmV5cJGNFOmjw3+jDizKHzvddxCtlCW0MDDAvHMV7YCQvEmLSz84WTQkp0ugvY
fKlEOS8S5hVFjDUOS3yRSD/xF+lrIlYUaR4gXnDAJZx9ttgfZlHOp8ehxk+1bn59
3Fv1fCXcCKmKUlTk1kFasD8P+2M3MKP42Ih5ap9cfLSVPiBS/6JRBxIlZrHM9/2a
w6vEp+qMwwgCmxLPMwZfem6LNHO/huTrWKf4ltVubb5bUXIe22udKp2WK4NWc3Ka
uG8EleECgYEA4A9Mwd0QJs0j1kpuJDNIjfFx6IROv3QAb0QPq0+192ZF8P9AEj8B
TNDQVzb/skM+2NDdvhZ5v4+OJQcUNpEskhX+5ikk8QHGAUY6vT8rO6oiIRMaxLuJ
OEDc2Qms1OmctTmgSVyaxfXIK2/GDdvOizt0Z7Y7abza4bigEm49hyMCgYEA13MI
H429Ua0tnVVmGJ/4OjnKbgtF7i02r50vDVktPruKWNy1bhRkRyaOoCH7Zt9WXF2j
GapZZN1N/clO4vf9gikH0VCo4Tc2JR635dXdfISlt8NLXmR800Ms1UCAKlwIOQjz
dgHcvEbvFwSe1MFgOJVGL82G2rUA/zDVOKdjXEsCgYAZxyjZlQlqrWdWHDIX0B6k
1gZ47d/xfvMd2gLDfuQ8lnOtinBgqQcJQ2z028sHQ11TrJQWbpeLRoTgFbRposIx
/H3bFRi+8alKND5Fz6K1tpk+nOgTglADPNMr1UUhKc9xujOKvTDBXcmt1ao/pe5Z
bnmyBPFI9QVpusgP1scVaQKBgE5mJYaV5VZbVkXyVXyQeZt2fBsfLwtEmKm+4OhS
kwxI4kcDyWGNOhBKD4xl0T3V928VA8zLGEyD22WGY5Zj93PtylJ4r3uEw8cuLm0M
LdSp0EPWZQ6sMmAOCbpwBjNj2fonL7C5bMF2bnpJzCJPW9w7NZcfivr68qnp8yzy
fE2RAoGBALWvlHVH/29KOVmM52sOk49tcyc3czjs/YANvbokiItxOB8VPY6QQQnS
/CBsCZxUuWegYmkUnstHDmY1LYqjxW4goOqizIksaReivPmsTuQ1qd+aqXTfg2pt
uy6c6X17xkP5q2Lq4i90ikyWm3Oc25aUEw48pRyK/6rABRUzpDLB
-----END RSA PRIVATE KEY-----`),
Pub: []byte(`ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8kYdyZA1ZSNjZ4pqybDXvWplHQHkU6fPL+cAYHUkAT5CiQV4GOjwaSTcvZNK5U2fQ0jm6jknCnsZi1t9JujCjXUT3bYHCnSwWhXN55QzIu530Q/MeXz5W8TxYRrWULgPhqqtq8B9N554+s40higG21fmhhdDtpmQzw3vJLspY05mnL1+fW+RIKkM4rb150sdZXKINxfNQvERteE8WX0vL2yG4RuqJzYtGCDEGeHd+HLne7xfmqPxun7bUYaxAlplhm1z2J41hqaj8pBwDSEV9SBOZXvh6FjS9nvJCT7Z1bbZwWrAO/7E2ac0eV+5iEc0J+TyufO3F9uod+J+AICtB`),
},
{
Priv: []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA2KcFrvuCPSc+3KTm/Lc+iES+GXTJaf7yuV5hXgtj1G/Aan0k
v0jMUdpg7CN5ETBEax9zHHSXxHW1GpysfQz4nGnRwLb3KgzrhZgo2KKMvF+CnY7d
jMajtK3h9hYoZZckii03vk05Mf4fOJjd8feOOQFpI7dKNsKD5gUGqzGwno5+/lnb
F6qnGTDDqwNNvLEGwFUjDw5l4WnEZ8XGHSpFdHf8mbHSchMSh6y/BABNpgx4KX/v
9NcPJFcNN3SEWLNuGjzm0pJ97Zvh3gjxZ2mg1HB7rpYla1gb0SWaJ9KTnvXGbDEa
dH+K+kdGfe1uvOYuPDrT7BfNyc2Tz3hxEA0lgQIDAQABAoIBAQDCkdWH3baMhzds
XuhXY5ZUOTBkmj7c46tHENzu4dnJCofK2xLqe02L4UyUJhNvfWKktfziPE+kj3WT
Lcu3DrQjfOF0ap009Z97PjjIvcsYzcn3CDwuVqLk/BhnsmSbQA7/zTY3wRCxtiCB
6r/As+vVhE/RVKXg4fYk2LSxgJG3AmhWSglg0fIo9COdLmLhmnz80JMnzxXKuDNs
xb4DzaDYCpK24tb7Y0PAl28RSe0M398tLVrYNX0mfwbbfIn+B0g+6oRFBYvuac6S
OgQdVEH4qds28JWeDr+vvpS7Ogwfx7b1mFsfiguS485xtc6Pfys0IhHZuhNlf2pW
qrm3AVn1AoGBAPu3dArwZzDgtCu5PLLH32cKgWC/XpjnLKchoskQJu5A1Ug99pxI
K/bOc363d3CDq3BU9Nd6/L+dH57RvQi7PDYkHjBwGFVwvS6ozZ7eIl1mEZBrnpmD
7IrlT+m5zEyQSB6ZThgDMJY8j76pqOexdN/H/Dlh7uDFV7w23Fn2QaMzAoGBANxW
0dduRb/ut6qTj4x6D4K8nCi/50a51LvblwjkaE2n6xYGYM6pURIhDOMy1nDCDyMz
m81Si29Pa4hcnIf4Od4K9abxB4E/qzyMY6mrNRgY33cjjACHhBKLK3JarKiOmlli
El5PM/vve4cFsu4qkIvKLmf22/KJ8HpNhO1nLVR7AoGAEr9CDEKFXPWPVaZRJ/uM
3u7AXgVCtV6aS8RMjG8Ah0Qa3muG/3K8m4Aax/hAFAgqb45UQewuANNh9IEodAsF
2/5qpS7kERD5dg0qa0eeBZjBfCEXydUye9HCVuT4m0cvp9/BGja6mqXeCtQ1+TOV
QclyNo/dq63m7+SiGq0ljFMCgYEAxqFduh+msUe6OwObPMAsi2cMP5AAJjoQFOn4
VgPSI29k9g3551OryfQRch+6QRwwGUPFCGuJV2b5QYx7b/fN8uVeXoiag2GqNIM6
tRGqY3bIvNZGt5Ny9GSRXh1v2OP1MO7AMFSmQE+7xBTXIO0uMVaqTv6zeQnwx9Bq
LLn+m1ECgYEA15K07VEQ2bjwJLpLfUye9j/we/mcEHPju5HkccmiKJ2BlD8uWLaF
3ChrOtryKxEed6yhrzKRtH+CPbYSyHcgmUcsjidxJ5DKBl89bRvHXjzrBMkqKFKP
zVpCU4VorDd82D/VlJwWUZ0DKw79EldNHyi8Y4Nhv0HP8QEH4teEtnc=
-----END RSA PRIVATE KEY-----`),
Pub: []byte(`ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYpwWu+4I9Jz7cpOb8tz6IRL4ZdMlp/vK5XmFeC2PUb8BqfSS/SMxR2mDsI3kRMERrH3McdJfEdbUanKx9DPicadHAtvcqDOuFmCjYooy8X4Kdjt2MxqO0reH2FihllySKLTe+TTkx/h84mN3x9445AWkjt0o2woPmBQarMbCejn7+WdsXqqcZMMOrA028sQbAVSMPDmXhacRnxcYdKkV0d/yZsdJyExKHrL8EAE2mDHgpf+/01w8kVw03dIRYs24aPObSkn3tm+HeCPFnaaDUcHuuliVrWBvRJZon0pOe9cZsMRp0f4r6R0Z97W685i48OtPsF83JzZPPeHEQDSWB ekontsevoy@turing`),
},
{
Priv: []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAouygGWpaFGjNsyY7XUpFGbeEtXg7WKdFI4Qz/o3HmGOwUr1w
mwjOYy6tJSm11a0lntzPKYNv4x+MruoAyPEjA+UYMSHYcOWaoKcGPOZcXP8aZFV2
VgFTn7eg9uKDZhDCcEa0lB8057MEzaHZgZU0B8+TdmjF1de80awlAEGZK3KsjZqF
EDA/Frl/yNVU1Kywg9bx9EuPXsT50VVWBja8Wo5nC/TOZt8NFnrymWr+J2okV1pK
ccD160TMKm/lL5GKIIMz1Zi8oYcFrCdRV2lnckJYd/QM6wrA4cLD5lN//zwkVmqU
PY5LiY1oEpZ6BT2hH7jACjG0ZcFU+HxmhQF8awIDAQABAoIBAQCbAQMkiwFer4Mc
cUBDdlidqfLRb60OoD1wF+Qbx6nget+TKHaMmWk6BXtngvJjc1L6fFt/xHPbovWG
qEzM4FYO65QDko7IgjmFpMKTiBrRw0bJtGFcW/DCYML8f+7BWSqUBUDiN3pvAeuM
8/HqjhgtYjiKjA3EcHdNCDk/sClYokD25T9/w1cYaPaNWHQVa5o2fv5NWrU0lAH8
oLsMmhhmqDZH9HY1lw0IdxEdXlvUxwSm+w42UCVWQf0D9ph8k/ACr2zvuTBjn1Dk
B776W5z2zZGNDw+omBpuwCZkmIBLegWDSgRV/Z9AxTsim1b5mC1KwDqpvb2cXrfm
Oq7tR4chAoGBANhXV+jC94cQ1tffkmxU+K4bhosfI8zX4EZht1IcqCdf/iqupsXH
O/cw1V5MDMQdZrD27W1lJhVH3Xd2KLcoaAx8fxSHYZpet2iQe6I2Nbkcj11o9hj7
xvONzclvMgEF13Xai0OY/4HHBJMfpGxDGroDmyub1pYQYz3rULJPpbZbAoGBAMDK
fIqmm/06IZwwGTddA7/aLMjpCAlH4pNu0VntXuKPA44p1ORIdTFNE0Z+6SIHJOcj
rV1XXrNM7zTq2pFJ7sm0wOylz9Ts1ThYtXKX8WVVBxgy6TlR263dq8BFXXHvLk8E
1+W7bmisPgAIHfu4zaJc4MvIBUTlAuQjz867Ys8xAoGBAKUNfjRHCzIw1ri8Cao8
6b1roqphh56w1Jrd0k8DLgdcZT2LIhGif02IJEFdJCA7ji1VNq9PjE6QFZcevtF+
MmPUV+ABqaVsveE42hpX4YTpFTfe7GMDNDZ86ZPVEgFVw5xWsAlSoR0SCZt1eKxg
RfPE7I3Ix16WAiErdtWTjoohAoGAOewcIuQPtbMDahOhX9rYR4nbLrmkqnUog7cl
uujwOw1QuiOjTLrgSuGnSuTSUmDnG3LCoWqgjyosLC/rXv9heMSPugnPOV+2Z+lv
CnDQG+vB5+lT3N7VK5WQBoJQouyDc0Y3P1RixZwKPKQzre9GCOPyvgboXlyX08dW
pfvyoeECgYEA0/Bi7rXiYdnKvY8z9F95rMdvgrU7HarxPQIY1nRcvlCVCVKpThRY
+BlAY2WChV0gElo6PtnkaBIcolyal/NjIc47dRlc+17V12u6vxegTqDPTV9uZ/C9
h0WxnD+CNkQDD/vGZ3S4Juo02tlr4VhwW6AmnKnlV2B0YDtW+HANxGQ=
-----END RSA PRIVATE KEY-----`),
Pub: []byte(`ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCi7KAZaloUaM2zJjtdSkUZt4S1eDtYp0UjhDP+jceYY7BSvXCbCM5jLq0lKbXVrSWe3M8pg2/jH4yu6gDI8SMD5RgxIdhw5ZqgpwY85lxc/xpkVXZWAVOft6D24oNmEMJwRrSUHzTnswTNodmBlTQHz5N2aMXV17zRrCUAQZkrcqyNmoUQMD8WuX/I1VTUrLCD1vH0S49exPnRVVYGNrxajmcL9M5m3w0WevKZav4naiRXWkpxwPXrRMwqb+UvkYoggzPVmLyhhwWsJ1FXaWdyQlh39AzrCsDhwsPmU3//PCRWapQ9jkuJjWgSlnoFPaEfuMAKMbRlwVT4fGaFAXxr ekontsevoy@turing`),
},
{
Priv: []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEArBZaj7vxmgO/Gj2ph1TRjs8Ty9gQJ95Y2uhuK+ww+gNyWo07
BnKp8rUUGIp2IiqHOKDhDgkP8QUI1DhBScdfZscUPVnuQF+HCdAdNePz9cLqoSEk
IdQZ3slW53KbTIWA2PmEHleff/JeLZFgPrg0n9MUMlkId+YxqUYFjoxBtCXDtBHV
MwABKjG5+4ObyCp5vMx496aROOfg5na7WZ3sObjBBO+ve1MEqGE0qZhfaibCFP3a
ihztY6tv4nW+RuS3CLK5xjmnqBPE4EFgr4Vqg2g44LnPqD/RUADu8vvE5lGweG3l
tj6MPYomCAPzhcxJ40hUtWK9N8IO+e9rXb3bmQIDAQABAoIBAQCklzTC6MVpw0+S
b4unzm4oItMSUnMRTs65gTludRda6NUE2rOrtRvq8VppJnVatEZk2Sqn2+8NXP1W
zP9U64XJrXskOtFvbG6h6hUmKAJ7+pOizSnb2RttRDEEaU8z3zSfUfcVdkUtgMim
2LavBkv+2Uol5ZX954N0HW7PKkLlYu7JYpMG3NtAq+GWMSzDx2Piv3/QgMyAEzQ0
qd/T89LVuo7ax7axCD3PmSkD9vGO+xShNjz2oqPAQW5mBUk5uzYiyJCp6gfcnoJv
PxCrZ5lrrDlPeZQ2Yk/WB6SZ2VgJM1SMTTje5Dhsdg4X0yP14zbgmgVgho1XMyfV
WiVW0YABAoGBAOFYvy6GvY8p6uclFsOQZrd75Ug3WOXgAIS2DRjuRfrD779VE+fG
kKGTYa50Iol1SxftT6Ucc6bYDOg0Gh+cksPMcMBL5XjU45NAteRoCcULCKWCI4+4
w9HqjqKW1yuoP/bp74QqMrZk4s6e/1JgNQMmrR9nGPxB7JL1plfhqhgBAoGBAMN+
9IkEMvMiYeqfhgPff5JpZ1KqZMwwJ1tfceP4Tcda0wr+RWOcGH4vT+nOtE7nTexZ
WQ3qRvHtXQryT4BQ9UQVmlUVGOpOrH5QyfsWvf5PiKIdRS52vVvZ1E5c/AklD42Y
x0T3THDHOINKVU7MgwICmJYYz6O1/09E6ZY8zYOZAoGBANqyWWCbDY7KXJoVKaGE
G9vIlv1eEZ2OppIlaFKgtDOpQpzKwbW3xJe6xBsdxILo3YcMHbadBTSQCv6zygKR
3vG9EFPflIWO/onjTGOuAIVFrw+JXF/YLdskq2bpw0swT1ufL39xwKO5B1EFh773
dZtoRq3qTZpLlIAPfW9ep8gBAoGAcrnCT9ZDACQhSksrnoI+n3FzzTNpy9pGfnzY
nWxOWLuYNk9Z8UbdqM+jGhbQAa4EMLuOY3glAjzF6XKh7S+Vf8sdsuiaooZg/A/1
OID0JpYOHPUIcGgGYCzJRuOSlNtG8VXDO1nVZinDpGiu/3tNNpTHbu5IjE518dMD
McOk56ECgYEAufiEubSp9zwG+l49MMO1kdiXchSu97BtuS42Pp/zVknas+9KsmIC
iRYwgp9bmImLOQt4k+EYPYHJpzLAMECAUg/u5BwZxATtaocOhloxbFAudEtznJTw
1saWPyr9hkL1OKjiI/TLEAGx57cCiU0kyOS8KdzGtIR22LtHldHlgb8=
-----END RSA PRIVATE KEY-----`),
Pub: []byte(`ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsFlqPu/GaA78aPamHVNGOzxPL2BAn3lja6G4r7DD6A3JajTsGcqnytRQYinYiKoc4oOEOCQ/xBQjUOEFJx19mxxQ9We5AX4cJ0B014/P1wuqhISQh1BneyVbncptMhYDY+YQeV59/8l4tkWA+uDSf0xQyWQh35jGpRgWOjEG0JcO0EdUzAAEqMbn7g5vIKnm8zHj3ppE45+DmdrtZnew5uMEE7697UwSoYTSpmF9qJsIU/dqKHO1jq2/idb5G5LcIsrnGOaeoE8TgQWCvhWqDaDjguc+oP9FQAO7y+8TmUbB4beW2Pow9iiYIA/OFzEnjSFS1Yr03wg7572tdvduZ ekontsevoy@turing`),
},
}
)

View file

@ -67,8 +67,8 @@ type HostKeyCallback func(host string, ip net.Addr, key ssh.PublicKey) error
// Config is a client config
type Config struct {
// Login is a teleport user login
Login string
// Username is the Teleport account username (for logging into Teleport proxies)
Username string
// Remote host to connect
Host string
@ -169,9 +169,9 @@ func (tc *TeleportClient) authMethods() []ssh.AuthMethod {
// NewClient creates a TeleportClient object and fully configures it
func NewClient(c *Config) (tc *TeleportClient, err error) {
// validate configuration
if c.Login == "" {
c.Login = Username()
log.Infof("no teleport login given. defaulting to %s", c.Login)
if c.Username == "" {
c.Username = Username()
log.Infof("no teleport login given. defaulting to %s", c.Username)
}
if c.ProxyHost == "" {
return nil, trace.Errorf("No proxy address specified, missed --proxy flag?")
@ -189,7 +189,7 @@ func NewClient(c *Config) (tc *TeleportClient, err error) {
tc = &TeleportClient{Config: *c}
// initialize the local agent (auth agent which uses local SSH keys signed by the CA):
tc.localAgent, err = NewLocalAgent("")
tc.localAgent, err = NewLocalAgent("", c.Username)
if err != nil {
return nil, trace.Wrap(err)
}
@ -743,7 +743,7 @@ func (tc *TeleportClient) getProxyLogin() string {
// we'll fall back to using the target host login
proxyLogin := tc.Config.HostLogin
// see if we already have a signed key in the cache, we'll use that instead
keys, err := tc.LocalAgent().GetKeys()
keys, err := tc.GetKeys()
if err == nil && len(keys) > 0 {
principals := keys[0].Certificate.ValidPrincipals
if len(principals) > 0 {
@ -753,6 +753,12 @@ func (tc *TeleportClient) getProxyLogin() string {
return proxyLogin
}
// GetKeys returns a list of stored local keys/certs for this Teleport
// user
func (tc *TeleportClient) GetKeys() ([]agent.AddedKey, error) {
return tc.LocalAgent().GetKeys(tc.Username)
}
// ConnectToProxy dials the proxy server and returns ProxyClient if successful
func (tc *TeleportClient) ConnectToProxy() (*ProxyClient, error) {
proxyAddr := tc.Config.ProxyHostPort(defaults.SSHProxyListenPort)
@ -761,7 +767,7 @@ func (tc *TeleportClient) ConnectToProxy() (*ProxyClient, error) {
HostKeyCallback: tc.HostKeyCallback,
}
log.Debugf("connecting to proxy: %v with host login %v", proxyAddr, sshConfig.User)
log.Infof("connecting to proxy: %v with host login %v", proxyAddr, sshConfig.User)
// try to authenticate using every non interactive auth method we have:
for _, m := range tc.authMethods() {
@ -796,7 +802,7 @@ func (tc *TeleportClient) ConnectToProxy() (*ProxyClient, error) {
// we need to communicate directly to user here,
// otherwise user will see endless loop with no explanation
if trace.IsTrustError(err) {
fmt.Printf("ERROR: refusing to connect to untrusted proxy %v without --insecure flag\n", proxyAddr)
fmt.Printf("Refusing to connect to untrusted proxy %v without --insecure flag\n", proxyAddr)
} else {
fmt.Printf("ERROR: %v\n", err)
}
@ -843,11 +849,11 @@ func (tc *TeleportClient) Login() error {
return trace.Wrap(err)
}
// in this case identity is returned by the proxy
tc.Config.Login = response.Username
tc.Username = response.Username
}
key.Cert = response.Cert
// save the key:
if err = tc.localAgent.AddKey(tc.ProxyHost, key); err != nil {
if err = tc.localAgent.AddKey(tc.ProxyHost, tc.Config.Username, key); err != nil {
return trace.Wrap(err)
}
// save the list of CAs we trust to the cache file
@ -877,7 +883,7 @@ func (tc *TeleportClient) MakeKey() (key *Key, err error) {
}
func (tc *TeleportClient) AddKey(host string, key *Key) error {
return tc.localAgent.AddKey(host, key)
return tc.localAgent.AddKey(host, tc.Username, key)
}
// directLogin asks for a password + HOTP token, makes a request to CA via proxy
@ -888,7 +894,7 @@ func (tc *TeleportClient) directLogin(pub []byte) (*web.SSHLoginResponse, error)
}
// ask the CA (via proxy) to sign our public key:
response, err := web.SSHAgentLogin(tc.Config.ProxyHostPort(defaults.HTTPListenPort), tc.Config.Login,
response, err := web.SSHAgentLogin(tc.Config.ProxyHostPort(defaults.HTTPListenPort), tc.Config.Username,
password, hotpToken, pub, tc.KeyTTL, tc.InsecureSkipVerify, loopbackPool(tc.Config.ProxyHostPort(defaults.HTTPListenPort)))
return response, trace.Wrap(err)
@ -963,7 +969,7 @@ func Username() string {
// AskPasswordAndHOTP prompts the user to enter the password + HTOP 2nd factor
func (tc *TeleportClient) AskPasswordAndHOTP() (pwd string, token string, err error) {
fmt.Printf("Enter password for %v:\n", tc.Config.Login)
fmt.Printf("Enter password for Teleport user %v:\n", tc.Config.Username)
pwd, err = passwordFromConsole()
if err != nil {
fmt.Println(err)

View file

@ -53,7 +53,7 @@ func (s *APITestSuite) TestNew(c *check.C) {
HostLogin: "vincent",
HostPort: 22,
KeysDir: "/tmp",
Login: "localuser",
Username: "localuser",
ProxyHost: "proxy",
SiteName: "site",
}

View file

@ -18,9 +18,9 @@ type Key struct {
// LocalKeyStore interface allows for different storage back-ends for TSH to load/save its keys
type LocalKeyStore interface {
// client key management
GetKeys() ([]Key, error)
AddKey(host string, key *Key) error
GetKey(host string) (*Key, error)
GetKeys(username string) ([]Key, error)
AddKey(host string, username string, key *Key) error
GetKey(host string, username string) (*Key, error)
// trusted CAs management:
AddKnownCA(domainName string, publicKeys []ssh.PublicKey) error

View file

@ -36,7 +36,7 @@ type LocalKeyAgent struct {
// NewLocalAgent loads all the saved teleport certificates and
// creates ssh agent with them
func NewLocalAgent(keyDir string) (a *LocalKeyAgent, err error) {
func NewLocalAgent(keyDir, username string) (a *LocalKeyAgent, err error) {
keystore, err := NewFSLocalKeyStore(keyDir)
if err != nil {
return nil, trace.Wrap(err)
@ -46,7 +46,7 @@ func NewLocalAgent(keyDir string) (a *LocalKeyAgent, err error) {
keyStore: keystore,
}
// add all stored keys into the agent:
keys, err := a.GetKeys()
keys, err := a.GetKeys(username)
if err != nil {
return nil, trace.Wrap(err)
}
@ -58,8 +58,10 @@ func NewLocalAgent(keyDir string) (a *LocalKeyAgent, err error) {
return a, nil
}
func (a *LocalKeyAgent) GetKeys() ([]agent.AddedKey, error) {
keys, err := a.keyStore.GetKeys()
// GetKeys return the list of keys for the given user
// from the local keystore (files in ~/.tsh)
func (a *LocalKeyAgent) GetKeys(username string) ([]agent.AddedKey, error) {
keys, err := a.keyStore.GetKeys(username)
if err != nil {
return nil, trace.Wrap(err)
}
@ -118,8 +120,8 @@ func (a *LocalKeyAgent) CheckHostSignature(hostId string, remote net.Addr, key s
return trace.Wrap(err)
}
func (a *LocalKeyAgent) AddKey(host string, key *Key) error {
err := a.keyStore.AddKey(host, key)
func (a *LocalKeyAgent) AddKey(host string, username string, key *Key) error {
err := a.keyStore.AddKey(host, username, key)
if err != nil {
return trace.Wrap(err)
}

View file

@ -36,10 +36,10 @@ import (
const (
defaultKeyDir = ".tsh"
sessionKeyDir = "sessions"
fileNameCert = "cert"
fileNameKey = "key"
fileNamePub = "pub"
fileExtCert = ".cert"
fileExtKey = ".key"
fileExtPub = ".pub"
sessionKeyDir = "keys"
fileNameKnownHosts = "known_hosts"
)
@ -79,7 +79,7 @@ func NewFSLocalKeyStore(dirPath string) (s *FSLocalKeyStore, err error) {
}
// GetKeys returns all user session keys stored in the store
func (fs *FSLocalKeyStore) GetKeys() (keys []Key, err error) {
func (fs *FSLocalKeyStore) GetKeys(username string) (keys []Key, err error) {
dirPath := filepath.Join(fs.KeyDir, sessionKeyDir)
if !utils.IsDir(dirPath) {
return make([]Key, 0), nil
@ -92,10 +92,12 @@ func (fs *FSLocalKeyStore) GetKeys() (keys []Key, err error) {
if !fi.IsDir() {
continue
}
k, err := fs.GetKey(fi.Name())
k, err := fs.GetKey(fi.Name(), username)
if err != nil {
log.Infof("Got error after GetKey(%s): %v", username, err)
// if a key is reported as 'not found' it's probably because it expired
if !trace.IsNotFound(err) {
log.Infof("ITS ANOTHER ERROR")
return nil, trace.Wrap(err)
}
continue
@ -107,8 +109,7 @@ func (fs *FSLocalKeyStore) GetKeys() (keys []Key, err error) {
// AddKey adds a new key to the session store. If a key for the host is already
// stored, overwrites it.
func (fs *FSLocalKeyStore) AddKey(host string, key *Key) error {
log.Infof("localKeyStore.AddKey(host=%s, key=%p)", host, key)
func (fs *FSLocalKeyStore) AddKey(host, username string, key *Key) error {
dirPath, err := fs.dirFor(host)
if err != nil {
return trace.Wrap(err)
@ -121,13 +122,13 @@ func (fs *FSLocalKeyStore) AddKey(host string, key *Key) error {
}
return err
}
if err = writeBytes(fileNameCert, key.Cert); err != nil {
if err = writeBytes(username+fileExtCert, key.Cert); err != nil {
return trace.Wrap(err)
}
if err = writeBytes(fileNamePub, key.Pub); err != nil {
if err = writeBytes(username+fileExtPub, key.Pub); err != nil {
return trace.Wrap(err)
}
if err = writeBytes(fileNameKey, key.Priv); err != nil {
if err = writeBytes(username+fileExtKey, key.Priv); err != nil {
return trace.Wrap(err)
}
return nil
@ -135,23 +136,23 @@ func (fs *FSLocalKeyStore) AddKey(host string, key *Key) error {
// GetKey returns a key for a given host. If the key is not found,
// returns trace.NotFound error.
func (fs *FSLocalKeyStore) GetKey(host string) (*Key, error) {
func (fs *FSLocalKeyStore) GetKey(host, username string) (*Key, error) {
dirPath, err := fs.dirFor(host)
if err != nil {
return nil, trace.Wrap(err)
}
certFile := filepath.Join(dirPath, fileNameCert)
certFile := filepath.Join(dirPath, username+fileExtCert)
cert, err := ioutil.ReadFile(certFile)
if err != nil {
log.Error(err)
return nil, trace.Wrap(err)
}
pub, err := ioutil.ReadFile(filepath.Join(dirPath, fileNamePub))
pub, err := ioutil.ReadFile(filepath.Join(dirPath, username+fileExtPub))
if err != nil {
log.Error(err)
return nil, trace.Wrap(err)
}
priv, err := ioutil.ReadFile(filepath.Join(dirPath, fileNameKey))
priv, err := ioutil.ReadFile(filepath.Join(dirPath, username+fileExtKey))
if err != nil {
log.Error(err)
return nil, trace.Wrap(err)

View file

@ -57,28 +57,40 @@ func (s *KeyStoreTestSuite) SetUpTest(c *check.C) {
func (s *KeyStoreTestSuite) TestListKeys(c *check.C) {
const keyNum = 5
// add 5 keys:
// add 5 keys for "bob"
keys := make([]Key, keyNum)
for i := 0; i < keyNum; i++ {
key := s.makeSignedKey(c, false)
s.store.AddKey(fmt.Sprintf("host-%v", i), key)
s.store.AddKey(fmt.Sprintf("host-%v", i), "bob", key)
keys[i] = *key
}
// read them all:
keys2, err := s.store.GetKeys()
// add 1 key for "sam"
samKey := s.makeSignedKey(c, false)
s.store.AddKey("sam.host", "sam", samKey)
// read all bob keys:
keys2, err := s.store.GetKeys("bob")
c.Assert(err, check.IsNil)
c.Assert(keys, check.HasLen, keyNum)
c.Assert(keys, check.DeepEquals, keys2)
c.Assert(keys2, check.HasLen, keyNum)
c.Assert(keys2, check.DeepEquals, keys)
// read sam's key and make sure it's the same:
keys, err = s.store.GetKeys("sam")
c.Assert(err, check.IsNil)
c.Assert(keys, check.HasLen, 1)
c.Assert(samKey.Cert, check.DeepEquals, keys[0].Cert)
c.Assert(samKey.Pub, check.DeepEquals, keys[0].Pub)
}
func (s *KeyStoreTestSuite) TestKeySaveLoad(c *check.C) {
key := s.makeSignedKey(c, false)
// add key:
err := s.store.AddKey("host.a", key)
err := s.store.AddKey("host.a", "bob", key)
c.Assert(err, check.IsNil)
// load back and compare:
keyCopy, err := s.store.GetKey("host.a")
keyCopy, err := s.store.GetKey("host.a", "bob")
c.Assert(err, check.IsNil)
c.Assert(key, check.DeepEquals, keyCopy)
}
@ -88,11 +100,11 @@ func (s *KeyStoreTestSuite) TestKeyExpiration(c *check.C) {
good := s.makeSignedKey(c, false)
expired := s.makeSignedKey(c, true)
s.store.AddKey("good.host", good)
s.store.AddKey("expired.host", expired)
s.store.AddKey("good.host", "sam", good)
s.store.AddKey("expired.host", "sam", expired)
// get all keys back. only "good" key should be returned:
keys, _ := s.store.GetKeys()
keys, _ := s.store.GetKeys("sam")
c.Assert(keys, check.HasLen, 1)
c.Assert(keys[0], check.DeepEquals, *good)
}

View file

@ -24,7 +24,9 @@ import (
"fmt"
"io"
"net"
"os"
"os/exec"
"os/user"
"strings"
"sync"
"time"
@ -499,6 +501,16 @@ func (s *Server) keyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permiss
return nil, trace.Wrap(err)
}
// see if the host user is valid (no need to do this in proxy mode)
if !s.proxyMode {
_, err = user.Lookup(conn.User())
if err != nil {
host, _ := os.Hostname()
logger.Warningf("host '%s' does not have OS user '%s'", host, conn.User())
return nil, trace.AccessDenied("invalid host login: '%s'", conn.User())
}
}
// this is the only way I know of to pass valid principal with the
// connection
permissions.Extensions[utils.CertTeleportUser] = teleportUser
@ -710,6 +722,7 @@ func (s *Server) dispatch(ch ssh.Channel, req *ssh.Request, ctx *ctx) error {
"proxy doesn't support request type '%v'", req.Type)
}
}
switch req.Type {
case "exec":
// exec is a remote execution of a program, does not use PTY

View file

@ -34,12 +34,12 @@ import (
// InitLoggerCLI tools by default log into syslog, not stderr
func InitLoggerCLI() {
log.SetLevel(log.ErrorLevel)
log.SetLevel(log.WarnLevel)
// clear existing hooks:
log.StandardLogger().Hooks = make(log.LevelHooks)
log.SetFormatter(&trace.TextFormatter{})
hook, err := logrusSyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
hook, err := logrusSyslog.NewSyslogHook("", "", syslog.LOG_WARNING, "")
if err != nil {
// syslog not available
log.Warn("syslog not available. reverting to stderr")
@ -67,7 +67,7 @@ func InitLoggerForTests() {
InitLoggerDebug()
return
}
log.SetLevel(log.ErrorLevel)
log.SetLevel(log.WarnLevel)
log.StandardLogger().Hooks = make(log.LevelHooks)
log.SetOutput(ioutil.Discard)
}

View file

@ -79,7 +79,7 @@ func (s *MainTestSuite) TestDefault(c *check.C) {
c.Assert(conf.SSH.Enabled, check.Equals, true)
c.Assert(conf.Proxy.Enabled, check.Equals, true)
c.Assert(conf.Console, check.Equals, os.Stdout)
c.Assert(log.GetLevel(), check.Equals, log.ErrorLevel)
c.Assert(log.GetLevel(), check.Equals, log.WarnLevel)
cmd, conf = run([]string{"start", "-d"}, true)
c.Assert(log.GetLevel(), check.Equals, log.DebugLevel)

View file

@ -45,8 +45,8 @@ type CLIConf struct {
UserHost string
// Commands to execute on a remote host
RemoteCommand []string
// Login is the Teleport user login
Login string
// Username is the Teleport user's username (to login into proxies)
Username string
// Proxy keeps the hostname:port of the SSH proxy to use
Proxy string
// TTL defines how long a session must be active (in minutes)
@ -88,7 +88,7 @@ func run(args []string, underTest bool) {
// configure CLI argument parser:
app := utils.InitCLIParser("tsh", "TSH: Teleport SSH client").Interspersed(false)
app.Flag("login", "Remote host login").Short('l').Envar("TELEPORT_LOGIN").StringVar(&cf.NodeLogin)
app.Flag("user", fmt.Sprintf("SSH proxy user [%s]", client.Username())).StringVar(&cf.Login)
app.Flag("user", fmt.Sprintf("SSH proxy user [%s]", client.Username())).StringVar(&cf.Username)
app.Flag("auth", "[EXPERIMENTAL] Use external authentication, e.g. 'google'").Envar("TELEPORT_AUTH").Hidden().StringVar(&cf.ExternalAuth)
app.Flag("site", "[EXPERIMENTAL] Specify site to connect to via proxy").Envar("TELEPORT_SITE").Hidden().StringVar(&cf.SiteName)
app.Flag("proxy", "SSH proxy host or IP address").Envar("TELEPORT_PROXY").StringVar(&cf.Proxy)
@ -294,7 +294,7 @@ SSH_AGENT_PID=%v; export SSH_AGENT_PID;
echo Agent pid %v;
`, socketAddr.Addr, pid, pid)
agentServer := teleagent.NewServer()
agentKeys, err := tc.LocalAgent().GetKeys()
agentKeys, err := tc.GetKeys()
if err != nil {
utils.FatalError(err)
}
@ -346,7 +346,7 @@ func makeClient(cf *CLIConf) (tc *client.TeleportClient, err error) {
// prep client config:
c := &client.Config{
Output: os.Stdout,
Login: cf.Login,
Username: cf.Username,
ProxyHost: cf.Proxy,
Host: cf.UserHost,
HostPort: int(cf.NodePort),

View file

@ -60,7 +60,11 @@ func IsNotFound(e error) bool {
type nf interface {
IsNotFoundError() bool
}
_, ok := Unwrap(e).(nf)
err := Unwrap(e)
_, ok := err.(nf)
if !ok {
return os.IsNotExist(err)
}
return ok
}