Skip to content

Commit

Permalink
Initial working prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
klizhentas committed Mar 14, 2015
1 parent 46369ef commit 0c425d3
Show file tree
Hide file tree
Showing 53 changed files with 4,533 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ _testmain.go
*.exe
*.test
*.prof
flymake*
61 changes: 61 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
ETCD_NODE1 := http://127.0.0.1:4001
ETCD_NODE2 := http://127.0.0.1:4002
ETCD_NODE3 := http://127.0.0.1:4003
ETCD_NODES := ${ETCD_NODE1},${ETCD_NODE2},${ETCD_NODE3}
ETCD_FLAGS := TELEPORT_TEST_ETCD_NODES=${ETCD_NODES}

test: clean
go test -v ./... -cover

test-with-etcd: clean
${ETCD_FLAGS} go test -v ./... -cover

clean:
find . -name flymake_* -delete

test-package: clean
go test -v ./$(p)

test-package-with-etcd: clean
${ETCD_FLAGS} go test -v ./$(p)

update:
rm -rf Godeps/
find . -iregex .*go | xargs sed -i 's:".*Godeps/_workspace/src/:":g'
godep save -r ./...

test-grep-package: clean
go test -v ./$(p) -check.f=$(e)

cover-package: clean
go test -v ./$(p) -coverprofile=/tmp/coverage.out
go tool cover -html=/tmp/coverage.out

cover-package-with-etcd: clean
${ETCD_FLAGS} go test -v ./$(p) -coverprofile=/tmp/coverage.out
go tool cover -html=/tmp/coverage.out

install: clean
go install github.com/gravitational/teleport/teleport

run: install
teleport -addr=localhost:2022\
-log=console\
-logSeverity=INFO\
-shell=/bin/bash\
-hostCert=./fixtures/keys/hosts/node.gravitational.io-cert.pub\
-hostPrivateKey=./fixtures/keys/hosts/node.gravitational.io\
-authSrv\
-backend=etcd\
-backendConfig='{"nodes": ["${ETCD_NODE1}","${ETCD_NODE2}","${ETCD_NODE3}"], "key": "/teleport"}'\

profile:
go tool pprof http://localhost:6060/debug/pprof/profile

sloccount:
find . -path ./Godeps -prune -o -name "*.go" -print0 | xargs -0 wc -l

# sets development etcd keys
set-etcd:
bash ./scripts/etcd.sh

109 changes: 107 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Medusa
# Teleport

Proxying SSH server with dynamic backend and ACL support

Expand Down Expand Up @@ -36,7 +36,7 @@ The goal of this project is to define a simple SSH infrastrucure that satisfies

## Proposed design

![medusa overview](/doc/img/MedusaOverview.png?raw=true "Medusa Overview")
![teleport overview](/doc/img/TeleportOverview.png?raw=true "Teleport Overview")

* Use Etcd for configuration, discovery, presence and key store
* Each server has ssh server heartbeating into the cluster
Expand All @@ -46,12 +46,117 @@ The goal of this project is to define a simple SSH infrastrucure that satisfies
* Use structured logging in syslog and json format and plug it into ES cluster


## Instalation and run

## Setting up certificates

Running teleport requires some set up of the certificates at the moment.

1. Create a server CA

This CA will be used to sign host certificates

```shell
ssh-keygen -f server_ca
```

2. Use server CA to sign the host key on your machine

```shell
# signs server cert with authority key
ssh-keygen -s server_ca -I host_auth_server -h -n auth.example.com -V +52w /etc/ssh/ssh_host_rsa_key.pub
```

3. Create a user CA

This authority will be used to sign user's public keys:

```shell
# generate key pair for authority signing user keys
ssh-keygen -f users_ca
```

4. Generate a user public/private key pair

This keypair will be used to access teleport server

```shell
ssh-keygen -f <put-user-name-here>
```

5. Use user CA to sign the user key

```shell
ssh-keygen -s users_ca -I user_username -n <put-user-name-here> -V +52w id_rsa.pub
```

Read on the guide here for more information:

https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with-ubuntu

## Running the teleport server

```shell
teleport -host=localhost -port=2022 -hostPrivateKey=/etc/ssh/ssh_host_rsa_key -caPublicKey=./path-to/users_ca.pub
```

## Connecting to teleport server

1. Start SSH agent

```shell
eval `ssh-agent`
```

2. Add the user key created to the agent (see the previous section)

```shell
ssh-add /path-to-user-private-and-public-key-directory
```

Make sure the identity has been loaded by running

```shell
ssh-add -l
```

3. Instruct ssh client to turn on agent forwarding

edit file `~./ssh/config` and add the following lines:

```
Host *
ForwardAgent yes
```

These lines allow ssh-client to use running ssh-agent for authorization with ssh server


4. If everything is correct, the following command will succeed:

```
ssh -p 2022 localhost
```

## Using teleport features

## TUN subsystem

Tun subsystem uses one teleport server to access another teleport server using client public key's without extra hassle of key management.

```
ssh -p 2022 localhost -s tun:127.0.0.1:2022
```


## MUX subsystem

MUX subsystem instructs teleport to connect to remote servers, execute the desired commands, collect return back the responses to the client:

```shell
# instructs teleport to run command 'ls -l' on 127.0.0.1 port 2022 and localhost port 2022
ssh -p 2022 localhost -s mux:127.0.0.1:2022,localhost:2022/ls -l
```



Expand Down
124 changes: 124 additions & 0 deletions auth/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// 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 auth

import (
"time"

"github.com/gravitational/teleport/backend"
)

// Authority implements minimal key-management facility for generating OpenSSH
//compatible public/private key pairs and OpenSSH certificates
type Authority interface {
GenerateKeyPair(passphrase string) ([]byte, []byte, error)

// GenerateHostCert generates host certificate, it takes pkey as a signing private key (host certificate authority)
GenerateHostCert(pkey, key []byte, id, hostname string, ttl time.Duration) ([]byte, error)

// GenerateHostCert generates user certificate, it takes pkey as a signing private key (user certificate authority)
GenerateUserCert(pkey, key []byte, id, username string, ttl time.Duration) ([]byte, error)
}

func NewAuthServer(b backend.Backend, a Authority) *AuthServer {
return &AuthServer{
b: b,
a: a,
}
}

// AuthServer implements key signing, generation and ACL functionality used by teleport
type AuthServer struct {
b backend.Backend
a Authority
}

// UpsertUserKey takes user's public key, generates certificate for it
// and adds it to the authorized keys database. It returns certificate signed by user CA in case of success,
// error otherwise. The certificate will be valid for the duration of the ttl passed in.
func (s *AuthServer) UpsertUserKey(user string, key backend.AuthorizedKey, ttl time.Duration) ([]byte, error) {
cert, err := s.GenerateUserCert(key.Value, key.ID, user, ttl)
if err != nil {
return nil, err
}
key.Value = cert
if err := s.b.UpsertUserKey(user, key, ttl); err != nil {
return nil, err
}
return cert, nil
}

func (s *AuthServer) GetUsers() ([]string, error) {
return s.b.GetUsers()
}

func (s *AuthServer) DeleteUser(user string) error {
return s.b.DeleteUser(user)
}

func (s *AuthServer) GetUserKeys(user string) ([]backend.AuthorizedKey, error) {
return s.b.GetUserKeys(user)
}

// DeleteUserKey deletes user key by given ID
func (s *AuthServer) DeleteUserKey(user, key string) error {
return s.b.DeleteUserKey(user, key)
}

// GenerateKeyPair generates private and public key pair of OpenSSH style certificates
func (s *AuthServer) GenerateKeyPair(pass string) ([]byte, []byte, error) {
return s.a.GenerateKeyPair(pass)
}

// ResetHostCA generates host certificate authority and updates the backend
func (s *AuthServer) ResetHostCA(pass string) error {
priv, pub, err := s.a.GenerateKeyPair(pass)
if err != nil {
return err
}
return s.b.UpsertHostCA(backend.CA{Pub: pub, Priv: priv})
}

// ResetHostCA generates user certificate authority and updates the backend
func (s *AuthServer) ResetUserCA(pass string) error {
priv, pub, err := s.a.GenerateKeyPair(pass)
if err != nil {
return err
}
return s.b.UpsertUserCA(backend.CA{Pub: pub, Priv: priv})
}

// GetHostCAPub returns a public key for host key signing authority
func (s *AuthServer) GetHostCAPub() ([]byte, error) {
return s.b.GetHostCAPub()
}

// GetHostCAPub returns a public key for user key signing authority
func (s *AuthServer) GetUserCAPub() ([]byte, error) {
return s.b.GetUserCAPub()
}

// GenerateHostCert generates host certificate, it takes pkey as a signing private key (host certificate authority)
func (s *AuthServer) GenerateHostCert(key []byte, id, hostname string, ttl time.Duration) ([]byte, error) {
hk, err := s.b.GetHostCA()
if err != nil {
return nil, err
}
return s.a.GenerateHostCert(hk.Priv, key, id, hostname, ttl)
}

// GenerateHostCert generates user certificate, it takes pkey as a signing private key (user certificate authority)
func (s *AuthServer) GenerateUserCert(key []byte, id, username string, ttl time.Duration) ([]byte, error) {
hk, err := s.b.GetUserCA()
if err != nil {
return nil, err
}
return s.a.GenerateUserCert(hk.Priv, key, id, username, ttl)
}

const Week = time.Hour * 24 * 7
Loading

0 comments on commit 0c425d3

Please sign in to comment.