Redesign authentication protocol
This commit is contained in:
@ -5,6 +5,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"forge.cadoles.com/wpetit/go-http-peering/client"
|
||||
peeringCrypto "forge.cadoles.com/wpetit/go-http-peering/crypto"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/memory"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/server"
|
||||
|
||||
peering "forge.cadoles.com/wpetit/go-http-peering"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/crypto"
|
||||
)
|
||||
@ -15,19 +20,35 @@ func TestAdvertise(t *testing.T) {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
id, pk, client, store := setup(t)
|
||||
store := memory.NewStore()
|
||||
serverPK := mustGeneratePrivateKey()
|
||||
clientPK := mustGeneratePrivateKey()
|
||||
peerID := peering.NewPeerID()
|
||||
|
||||
serverToken, err := peeringCrypto.CreateServerToken(serverPK, "test", peerID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
advertise := server.AdvertiseHandler(store, &serverPK.PublicKey)
|
||||
|
||||
client := client.New(
|
||||
client.WithHTTPClient(NewHTTPClientMock(advertise)),
|
||||
client.WithPrivateKey(clientPK),
|
||||
client.WithServerToken(serverToken),
|
||||
)
|
||||
|
||||
attrs := peering.PeerAttributes{}
|
||||
if err := client.Advertise(attrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
peer, err := store.Get(id)
|
||||
peer, err := store.Get(peerID)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if g, e := peer.ID, id; g != e {
|
||||
if g, e := peer.ID, peerID; g != e {
|
||||
t.Errorf("peer.ID: got '%v', expected '%v'", g, e)
|
||||
}
|
||||
|
||||
@ -40,11 +61,7 @@ func TestAdvertise(t *testing.T) {
|
||||
t.Error("peer.LastContact should not be time.Time zero value")
|
||||
}
|
||||
|
||||
if peer.LastAddress == "" {
|
||||
t.Error("peer.LastAddress should not be empty")
|
||||
}
|
||||
|
||||
pem, err := crypto.EncodePublicKeyToPEM(pk.Public())
|
||||
pem, err := crypto.EncodePublicKeyToPEM(clientPK.Public())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -4,6 +4,10 @@ import (
|
||||
"testing"
|
||||
|
||||
peering "forge.cadoles.com/wpetit/go-http-peering"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/client"
|
||||
peeringCrypto "forge.cadoles.com/wpetit/go-http-peering/crypto"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/memory"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/server"
|
||||
)
|
||||
|
||||
func TestPing(t *testing.T) {
|
||||
@ -12,33 +16,67 @@ func TestPing(t *testing.T) {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
id, _, client, store := setup(t)
|
||||
store := memory.NewStore()
|
||||
serverPK := mustGeneratePrivateKey()
|
||||
clientPK := mustGeneratePrivateKey()
|
||||
peerID := peering.NewPeerID()
|
||||
|
||||
attrs := peering.PeerAttributes{}
|
||||
if err := client.Advertise(attrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
peer, err := store.Get(id)
|
||||
// Generate a server token for the peer client
|
||||
serverToken, err := peeringCrypto.CreateServerToken(serverPK, "test", peerID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
advertise := server.AdvertiseHandler(store, &serverPK.PublicKey)
|
||||
// Create advertise client
|
||||
c := client.New(
|
||||
client.WithHTTPClient(NewHTTPClientMock(advertise)),
|
||||
client.WithPrivateKey(clientPK),
|
||||
client.WithServerToken(serverToken),
|
||||
)
|
||||
|
||||
// Advertise client with empty peer attributes
|
||||
attrs := peering.PeerAttributes{}
|
||||
if err := c.Advertise(attrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Retrieve peer from store
|
||||
peer, err := store.Get(peerID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Store last contact after advertising
|
||||
lastContact := peer.LastContact
|
||||
|
||||
if err := store.Accept(id); err != nil {
|
||||
// Accept peer
|
||||
if err := store.Accept(peerID); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err := client.Ping(); err != nil {
|
||||
// Create ping authenticated handler
|
||||
ping := server.Authenticate(store, &serverPK.PublicKey)(server.PingHandler(store))
|
||||
|
||||
// Create client
|
||||
c = client.New(
|
||||
client.WithHTTPClient(NewHTTPClientMock(ping)),
|
||||
client.WithPrivateKey(clientPK),
|
||||
client.WithServerToken(serverToken),
|
||||
)
|
||||
|
||||
// Do ping
|
||||
if err := c.Ping(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
peer, err = store.Get(id)
|
||||
// Retrieve peer
|
||||
peer, err = store.Get(peerID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Assert that last contact has changed after ping
|
||||
if peer.LastContact == lastContact {
|
||||
t.Error("peer.LastContact should have been updated")
|
||||
}
|
||||
|
@ -6,7 +6,11 @@ import (
|
||||
"time"
|
||||
|
||||
peering "forge.cadoles.com/wpetit/go-http-peering"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/client"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/crypto"
|
||||
peeringCrypto "forge.cadoles.com/wpetit/go-http-peering/crypto"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/memory"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/server"
|
||||
)
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
@ -15,42 +19,77 @@ func TestUpdate(t *testing.T) {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
id, pk, client, store := setup(t)
|
||||
store := memory.NewStore()
|
||||
serverPK := mustGeneratePrivateKey()
|
||||
clientPK := mustGeneratePrivateKey()
|
||||
peerID := peering.NewPeerID()
|
||||
|
||||
attrs := peering.PeerAttributes{}
|
||||
|
||||
if err := client.Advertise(attrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := store.Accept(id); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
attrs["Label"] = "Foo Bar"
|
||||
if err := client.UpdateAttributes(attrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
peer, err := store.Get(id)
|
||||
// Generate a server token for the peer client
|
||||
serverToken, err := peeringCrypto.CreateServerToken(serverPK, "test", peerID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if g, e := peer.ID, id; g != e {
|
||||
advertise := server.AdvertiseHandler(store, &serverPK.PublicKey)
|
||||
// Create advertise client
|
||||
c := client.New(
|
||||
client.WithHTTPClient(NewHTTPClientMock(advertise)),
|
||||
client.WithPrivateKey(clientPK),
|
||||
client.WithServerToken(serverToken),
|
||||
)
|
||||
|
||||
// Advertise client with empty peer attributes
|
||||
attrs := peering.PeerAttributes{}
|
||||
if err := c.Advertise(attrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Accept peer
|
||||
if err := store.Accept(peerID); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Create authenticated update handler
|
||||
update := server.Authenticate(store, &serverPK.PublicKey)(server.UpdateHandler(store))
|
||||
|
||||
// Create update client
|
||||
c = client.New(
|
||||
client.WithHTTPClient(NewHTTPClientMock(update)),
|
||||
client.WithPrivateKey(clientPK),
|
||||
client.WithServerToken(serverToken),
|
||||
)
|
||||
|
||||
// Update local attributes
|
||||
attrs["Label"] = "Foo Bar"
|
||||
|
||||
// Update attributes
|
||||
if err := c.UpdateAttributes(attrs); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Retrieve peer from store
|
||||
peer, err := store.Get(peerID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Assert that peer's ID did not change
|
||||
if g, e := peer.ID, peerID; g != e {
|
||||
t.Errorf("peer.ID: got '%v', expected '%v'", g, e)
|
||||
}
|
||||
|
||||
// Assert that stored attributes are the same as the local ones
|
||||
if g, e := peer.Attributes, attrs; !reflect.DeepEqual(g, e) {
|
||||
t.Errorf("peer.Attributes: got '%v', expected '%v'", g, e)
|
||||
}
|
||||
|
||||
// Assert that lastContact has changed
|
||||
var defaultTime time.Time
|
||||
if peer.LastContact == defaultTime {
|
||||
t.Error("peer.LastContact should not be time.Time zero value")
|
||||
}
|
||||
|
||||
pem, err := crypto.EncodePublicKeyToPEM(pk.Public())
|
||||
pem, err := crypto.EncodePublicKeyToPEM(clientPK.Public())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -3,15 +3,8 @@ package test
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
peering "forge.cadoles.com/wpetit/go-http-peering"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/client"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/memory"
|
||||
"forge.cadoles.com/wpetit/go-http-peering/server"
|
||||
"net/http/httptest"
|
||||
)
|
||||
|
||||
func mustGeneratePrivateKey() *rsa.PrivateKey {
|
||||
@ -22,43 +15,22 @@ func mustGeneratePrivateKey() *rsa.PrivateKey {
|
||||
return privateKey
|
||||
}
|
||||
|
||||
func startServer(store peering.Store) (int, error) {
|
||||
listener, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
mux := createServerMux(store)
|
||||
go http.Serve(listener, mux)
|
||||
port := listener.Addr().(*net.TCPAddr).Port
|
||||
return port, nil
|
||||
type HTTPClientMock struct {
|
||||
handler http.Handler
|
||||
recorder *httptest.ResponseRecorder
|
||||
}
|
||||
|
||||
func createServerMux(store peering.Store) *http.ServeMux {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc(peering.AdvertisePath, server.AdvertiseHandler(store))
|
||||
update := server.Authenticate(store)(server.UpdateHandler(store))
|
||||
mux.Handle(peering.UpdatePath, update)
|
||||
ping := server.Authenticate(store)(server.PingHandler(store))
|
||||
mux.Handle(peering.PingPath, ping)
|
||||
return mux
|
||||
func (c *HTTPClientMock) Do(r *http.Request) (*http.Response, error) {
|
||||
w := httptest.NewRecorder()
|
||||
c.recorder = w
|
||||
c.handler.ServeHTTP(w, r)
|
||||
return w.Result(), nil
|
||||
}
|
||||
|
||||
func setup(t *testing.T) (peering.PeerID, *rsa.PrivateKey, *client.Client, peering.Store) {
|
||||
store := memory.NewStore()
|
||||
|
||||
port, err := startServer(store)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pk := mustGeneratePrivateKey()
|
||||
id := peering.NewPeerID()
|
||||
|
||||
c := client.New(
|
||||
client.WithBaseURL(fmt.Sprintf("http://127.0.0.1:%d", port)),
|
||||
client.WithPrivateKey(pk),
|
||||
client.WithPeerID(id),
|
||||
)
|
||||
|
||||
return id, pk, c, store
|
||||
func (c *HTTPClientMock) Recorder() *httptest.ResponseRecorder {
|
||||
return c.recorder
|
||||
}
|
||||
|
||||
func NewHTTPClientMock(h http.Handler) *HTTPClientMock {
|
||||
return &HTTPClientMock{h, nil}
|
||||
}
|
||||
|
Reference in New Issue
Block a user