Skip to content

Commit

Permalink
Merge pull request gravitational#439 from gravitational/ev/logout
Browse files Browse the repository at this point in the history
tsh logout implementation
  • Loading branch information
klizhentas committed Jun 2, 2016
2 parents e546e0b + 029233b commit b0ff554
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 5 deletions.
2 changes: 1 addition & 1 deletion docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ db xxxxx-xxxx-xxxx-xxxxxxx 10.0.10.2:3022 location=virginia,a
Let's use the newly created labels to filter the output of `tsh ls` and ask to show only
nodes located in Virginia:

```
```bash
> tsh --proxy=localhost ls location=virginia

Node Name Node ID Address Labels
Expand Down
16 changes: 16 additions & 0 deletions lib/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,11 @@ func (tc *TeleportClient) ConnectToProxy() (*ProxyClient, error) {
}, nil
}

// Logout locates a certificate stored for a given proxy and deletes it
func (tc *TeleportClient) Logout() error {
return trace.Wrap(tc.localAgent.DeleteKey(tc.ProxyHost, tc.Config.Username))
}

// Login logs user in using proxy's local 2FA auth access
// or used OIDC external authentication, it later
// saves the generated credentials into local keystore for future use
Expand Down Expand Up @@ -875,6 +880,17 @@ func (tc *TeleportClient) Login() error {
if err != nil {
return trace.Wrap(err)
}

// get site info:
proxy, err := tc.ConnectToProxy()
if err != nil {
return trace.Wrap(err)
}
site, err := proxy.getSite()
if err != nil {
return trace.Wrap(err)
}
tc.SiteName = site.Name
return nil
}

Expand Down
1 change: 1 addition & 0 deletions lib/client/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type LocalKeyStore interface {
GetKeys(username string) ([]Key, error)
AddKey(host string, username string, key *Key) error
GetKey(host string, username string) (*Key, error)
DeleteKey(host string, username string) error

// trusted CAs management:
AddKnownCA(domainName string, publicKeys []ssh.PublicKey) error
Expand Down
4 changes: 4 additions & 0 deletions lib/client/keyagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,7 @@ func (a *LocalKeyAgent) AddKey(host string, username string, key *Key) error {
}
return a.Agent.Add(*agentKey)
}

func (a *LocalKeyAgent) DeleteKey(host string, username string) error {
return trace.Wrap(a.keyStore.DeleteKey(host, username))
}
19 changes: 19 additions & 0 deletions lib/client/keystore.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,25 @@ func (fs *FSLocalKeyStore) AddKey(host, username string, key *Key) error {
return nil
}

// DeleteKey deletes a key from the local store
func (fs *FSLocalKeyStore) DeleteKey(host string, username string) error {
dirPath, err := fs.dirFor(host)
if err != nil {
return trace.Wrap(err)
}
files := []string{
filepath.Join(dirPath, username+fileExtCert),
filepath.Join(dirPath, username+fileExtPub),
filepath.Join(dirPath, username+fileExtKey),
}
for _, fn := range files {
if err = os.Remove(fn); err != nil {
return trace.Wrap(err)
}
}
return nil
}

// GetKey returns a key for a given host. If the key is not found,
// returns trace.NotFound error.
func (fs *FSLocalKeyStore) GetKey(host, username string) (*Key, error) {
Expand Down
15 changes: 14 additions & 1 deletion lib/client/keystore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/gravitational/teleport/lib/auth/testauthority"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
"golang.org/x/crypto/ssh"
"gopkg.in/check.v1"
)
Expand Down Expand Up @@ -82,7 +83,7 @@ func (s *KeyStoreTestSuite) TestListKeys(c *check.C) {
c.Assert(samKey.Pub, check.DeepEquals, keys[0].Pub)
}

func (s *KeyStoreTestSuite) TestKeySaveLoad(c *check.C) {
func (s *KeyStoreTestSuite) TestKeyCRUD(c *check.C) {
key := s.makeSignedKey(c, false)

// add key:
Expand All @@ -93,6 +94,18 @@ func (s *KeyStoreTestSuite) TestKeySaveLoad(c *check.C) {
keyCopy, err := s.store.GetKey("host.a", "bob")
c.Assert(err, check.IsNil)
c.Assert(key, check.DeepEquals, keyCopy)

// Delete & verify that its' gone
err = s.store.DeleteKey("host.a", "bob")
c.Assert(err, check.IsNil)
keyCopy, err = s.store.GetKey("host.a", "bob")
c.Assert(err, check.NotNil)
c.Assert(trace.IsNotFound(err), check.Equals, true)

// Delete non-existing
err = s.store.DeleteKey("non-existing-host", "non-existing-user")
c.Assert(err, check.NotNil)
c.Assert(trace.IsNotFound(err), check.Equals, true)
}

func (s *KeyStoreTestSuite) TestKeyExpiration(c *check.C) {
Expand Down
33 changes: 30 additions & 3 deletions tool/tsh/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/gravitational/teleport/lib/session"
"github.com/gravitational/teleport/lib/teleagent"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"

"github.com/buger/goterm"
"github.com/pborman/uuid"
Expand Down Expand Up @@ -124,8 +125,12 @@ func run(args []string, underTest bool) {
agent := app.Command("agent", "Start SSH agent on unix socket")
agent.Flag("socket", "SSH agent listening socket address, e.g. unix:///tmp/teleport.agent.sock").SetValue(&cf.AgentSocketAddr)

// login logs in with remote proxy and obtains certificate
login := app.Command("login", "Log in with remote proxy and get signed certificate")
// login logs in with remote proxy and obtains a "session certificate" which gets
// stored in ~/.tsh directory
login := app.Command("login", "Log in to the cluster and store the session certificate to avoid login prompts")

// logout deletes obtained session certificates in ~/.tsh
logout := app.Command("logout", "Delete a cluster certificate")

// parse CLI commands+flags:
command, err := app.Parse(args)
Expand Down Expand Up @@ -157,6 +162,8 @@ func run(args []string, underTest bool) {
onAgentStart(&cf)
case login.FullCommand():
onLogin(&cf)
case logout.FullCommand():
onLogout(&cf)
}
}

Expand All @@ -180,7 +187,27 @@ func onLogin(cf *CLIConf) {
if err := tc.Login(); err != nil {
utils.FatalError(err)
}
fmt.Println("\nlogged in successfully")
if tc.SiteName != "" {
fmt.Printf("\nYou are now logged into %s as %s\n", tc.SiteName, tc.Username)
} else {
fmt.Printf("\nYou are now logged in\n")
}
}

// onLogout deletes a "session certificate" from ~/.tsh for a given proxy
func onLogout(cf *CLIConf) {
tc, err := makeClient(cf)
if err != nil {
utils.FatalError(err)
}
if err = tc.Logout(); err != nil {
if trace.IsNotFound(err) {
fmt.Println("You are not logged in")
return
}
utils.FatalError(err)
}
fmt.Printf("%s has logged out\n", tc.Username)
}

// onListNodes executes 'tsh ls' command
Expand Down

0 comments on commit b0ff554

Please sign in to comment.