Added hotp mock for client library

This commit is contained in:
Alex Lyulkov 2015-12-23 02:29:08 +03:00
parent fdef528637
commit a3998b1f20
4 changed files with 164 additions and 22 deletions

View file

@ -55,7 +55,8 @@ type NodeClient struct {
}
// ConnectToProxy returns connected and authenticated ProxyClient
func ConnectToProxy(proxyAddress string, authMethod ssh.AuthMethod, user string) (*ProxyClient, error) {
func ConnectToProxy(proxyAddress string, authMethod ssh.AuthMethod,
user string) (*ProxyClient, error) {
sshConfig := &ssh.ClientConfig{
User: user,
Auth: []ssh.AuthMethod{authMethod},
@ -208,6 +209,10 @@ func (proxy *ProxyClient) ConnectToNode(nodeAddress string, authMethod ssh.AuthM
return &NodeClient{Client: client}, nil
}
func (proxy *ProxyClient) Close() error {
return proxy.Client.Close()
}
// ConnectToNode returns connected and authenticated NodeClient
func ConnectToNode(nodeAddress string, authMethod ssh.AuthMethod, user string) (*NodeClient, error) {
sshConfig := &ssh.ClientConfig{
@ -269,6 +274,7 @@ func (client *NodeClient) Run(cmd string, output io.Writer) error {
if err := session.Run(cmd); err != nil {
return trace.Wrap(err)
}
return nil
}
@ -371,3 +377,7 @@ func (client *NodeClient) scp(scpConf scp.Command, shellCmd string) error {
return nil
}
func (client *NodeClient) Close() error {
return client.Client.Close()
}

View file

@ -66,6 +66,9 @@ type ClientSuite struct {
teleagent *teleagent.TeleAgent
dir string
dir2 string
otp *hotp.HOTP
user string
pass []byte
}
var _ = Suite(&ClientSuite{})
@ -197,20 +200,20 @@ func (s *ClientSuite) SetUpSuite(c *C) {
c.Assert(err, IsNil)
c.Assert(tsrv.Start(), IsNil)
user := "user1"
pass := []byte("utndkrn")
s.user = "user1"
s.pass = []byte("utndkrn")
hotpURL, _, err := s.a.UpsertPassword(user, pass)
hotpURL, _, err := s.a.UpsertPassword(s.user, s.pass)
c.Assert(err, IsNil)
otp, _, err := hotp.FromURL(hotpURL)
s.otp, _, err = hotp.FromURL(hotpURL)
c.Assert(err, IsNil)
otp.Increment()
s.otp.Increment()
authMethod, err := auth.NewWebPasswordAuth(user, pass, otp.OTP())
authMethod, err := auth.NewWebPasswordAuth(s.user, s.pass, s.otp.OTP())
c.Assert(err, IsNil)
tunClt, err := auth.NewTunClient(
utils.NetAddr{AddrNetwork: "tcp", Addr: tsrv.Addr()}, user, authMethod)
utils.NetAddr{AddrNetwork: "tcp", Addr: tsrv.Addr()}, s.user, authMethod)
c.Assert(err, IsNil)
rsAgent, err := reversetunnel.NewAgent(
@ -240,7 +243,7 @@ func (s *ClientSuite) SetUpSuite(c *C) {
}()
s.teleagent = teleagent.NewTeleAgent()
err = s.teleagent.Login("http://"+s.webAddress, user, string(pass), otp.OTP(), time.Minute)
err = s.teleagent.Login("http://"+s.webAddress, s.user, string(s.pass), s.otp.OTP(), time.Minute)
c.Assert(err, IsNil)
// "Command labels will be calculated only on the second heartbeat"
@ -249,7 +252,7 @@ func (s *ClientSuite) SetUpSuite(c *C) {
func (s *ClientSuite) TestRunCommand(c *C) {
nodeClient, err := ConnectToNode(s.srvAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
buf := bytes.Buffer{}
@ -260,11 +263,11 @@ func (s *ClientSuite) TestRunCommand(c *C) {
func (s *ClientSuite) TestConnectViaProxy(c *C) {
proxyClient, err := ConnectToProxy(s.proxyAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
nodeClient, err := proxyClient.ConnectToNode(s.srvAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
buf := bytes.Buffer{}
@ -275,11 +278,11 @@ func (s *ClientSuite) TestConnectViaProxy(c *C) {
func (s *ClientSuite) TestShell(c *C) {
proxyClient, err := ConnectToProxy(s.proxyAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
nodeClient, err := proxyClient.ConnectToNode(s.srvAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
shell, err := nodeClient.Shell()
@ -309,7 +312,7 @@ func (s *ClientSuite) TestShell(c *C) {
func (s *ClientSuite) TestGetServer(c *C) {
proxyClient, err := ConnectToProxy(s.proxyAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
server1Info := services.Server{
@ -399,11 +402,11 @@ func (s *ClientSuite) TestGetServer(c *C) {
func (s *ClientSuite) TestUploadFile(c *C) {
proxyClient, err := ConnectToProxy(s.proxyAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
nodeClient, err := proxyClient.ConnectToNode(s.srvAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
dir := c.MkDir()
@ -423,11 +426,11 @@ func (s *ClientSuite) TestUploadFile(c *C) {
func (s *ClientSuite) TestDownloadFile(c *C) {
proxyClient, err := ConnectToProxy(s.proxyAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
nodeClient, err := proxyClient.ConnectToNode(s.srvAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
dir := c.MkDir()
@ -447,7 +450,7 @@ func (s *ClientSuite) TestDownloadFile(c *C) {
func (s *ClientSuite) TestUploadDir(c *C) {
nodeClient, err := ConnectToNode(s.srvAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
dir1 := c.MkDir()
@ -476,7 +479,7 @@ func (s *ClientSuite) TestUploadDir(c *C) {
func (s *ClientSuite) TestDownloadDir(c *C) {
nodeClient, err := ConnectToNode(s.srvAddress,
s.teleagent.AuthMethod(), "user1")
s.teleagent.AuthMethod(), s.user)
c.Assert(err, IsNil)
dir1 := c.MkDir()
@ -502,3 +505,39 @@ func (s *ClientSuite) TestDownloadDir(c *C) {
c.Assert(err, IsNil)
c.Assert(string(bytes), Equals, string(contents2))
}
func (s *ClientSuite) TestHOTPMock(c *C) {
hotpMock, err := CreateHOTPMock(s.otp.URL(""))
c.Assert(err, IsNil)
teleagent := teleagent.NewTeleAgent()
err = teleagent.Login("http://"+s.webAddress, s.user, string(s.pass), "123456", time.Minute)
c.Assert(err, NotNil)
err = teleagent.Login("http://"+s.webAddress, s.user, string(s.pass), hotpMock.OTP(), time.Minute)
c.Assert(err, IsNil)
path := filepath.Join(s.dir, "hotpmock")
c.Assert(hotpMock.SaveToFile(path), IsNil)
token, err := GetTokenFromHOTPMockFile(path)
c.Assert(err, IsNil)
err = teleagent.Login("http://"+s.webAddress, s.user, string(s.pass), token, time.Minute)
c.Assert(err, IsNil)
token, err = GetTokenFromHOTPMockFile(path)
c.Assert(err, IsNil)
err = teleagent.Login("http://"+s.webAddress, s.user, string(s.pass), token, time.Minute)
c.Assert(err, IsNil)
hotpMock, err = LoadHOTPMockFromFile(path)
c.Assert(err, IsNil)
err = teleagent.Login("http://"+s.webAddress, s.user, string(s.pass), hotpMock.OTP(), time.Minute)
c.Assert(err, IsNil)
hotpMock, err = LoadHOTPMockFromFile(path)
c.Assert(err, IsNil)
err = teleagent.Login("http://"+s.webAddress, s.user, string(s.pass), hotpMock.OTP(), time.Minute)
c.Assert(err, NotNil)
}

94
lib/client/hotp_mock.go Normal file
View file

@ -0,0 +1,94 @@
/*
Copyright 2015 Gravitational, Inc.
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 auth implements certificate signing authority and access control server
// Authority server is composed of several parts:
//
// * Authority server itself that implements signing and acl logic
// * HTTP server wrapper for authority server
// * HTTP client wrapper
//
package client
import (
"io/ioutil"
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/gokyle/hotp"
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/gravitational/trace"
)
// HOTPMock is a HOTP that can be saved or load from file
// Using HOTPMock disables the hotp security level, don't use it in production
type HOTPMock struct {
*hotp.HOTP
}
func CreateHOTPMock(hotpURLString string) (*HOTPMock, error) {
otp, _, err := hotp.FromURL(hotpURLString)
if err != nil {
return nil, trace.Wrap(err)
}
return &HOTPMock{
HOTP: otp,
}, nil
}
func (otp *HOTPMock) SaveToFile(path string) error {
tokenBytes, err := hotp.Marshal(otp.HOTP)
if err != nil {
return trace.Wrap(err)
}
err = ioutil.WriteFile(path, tokenBytes, 0666)
if err != nil {
return trace.Wrap(err)
}
return nil
}
func LoadHOTPMockFromFile(path string) (*HOTPMock, error) {
tokenBytes, err := ioutil.ReadFile(path)
if err != nil {
return nil, trace.Wrap(err)
}
otp, err := hotp.Unmarshal(tokenBytes)
if err != nil {
return nil, trace.Wrap(err)
}
return &HOTPMock{
HOTP: otp,
}, nil
}
// GetTokenFromHOTPMockFile opens HOTPMock from file, gets token value,
// increases hotp and saves it to the file. Returns hotp token value.
func GetTokenFromHOTPMockFile(path string) (token string, e error) {
otp, err := LoadHOTPMockFromFile(path)
if err != nil {
return "", trace.Wrap(err)
}
token = otp.OTP()
err = otp.SaveToFile(path)
if err != nil {
return "", trace.Wrap(err)
}
return token, nil
}

View file

@ -137,7 +137,6 @@ func (s *Server) handleConnection(conn net.Conn) {
}
if err := s.limiter.AcquireConnection(remoteAddr); err != nil {
log.Errorf(err.Error())
//time.Sleep(5 * time.Second)
conn.Close()
return
}