Skip to content
Snippets Groups Projects
Commit 128c384b authored by ale's avatar ale
Browse files

Add a couple of basic tests

parent 0eaefcea
No related branches found
No related tags found
No related merge requests found
...@@ -81,12 +81,7 @@ type KeyStore struct { ...@@ -81,12 +81,7 @@ type KeyStore struct {
validator sso.Validator validator sso.Validator
} }
// NewKeyStore creates a new KeyStore with the given config and returns it. func newKeyStoreWithBackend(config *Config, db Database) (*KeyStore, error) {
func NewKeyStore(config *Config) (*KeyStore, error) {
if err := config.check(); err != nil {
return nil, err
}
ssoKey, err := ioutil.ReadFile(config.SSOPublicKeyFile) ssoKey, err := ioutil.ReadFile(config.SSOPublicKeyFile)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -96,24 +91,32 @@ func NewKeyStore(config *Config) (*KeyStore, error) { ...@@ -96,24 +91,32 @@ func NewKeyStore(config *Config) (*KeyStore, error) {
return nil, err return nil, err
} }
// There is only one supported backend type, ldap.
ldap, err := backend.NewLDAPBackend(config.LDAPConfig)
if err != nil {
return nil, err
}
s := &KeyStore{ s := &KeyStore{
userKeys: make(map[string]userKey), userKeys: make(map[string]userKey),
service: config.SSOService, service: config.SSOService,
validator: v, validator: v,
db: ldap, db: db,
} }
go s.expire() go s.expireLoop()
return s, nil return s, nil
} }
func (s *KeyStore) expire() { // NewKeyStore creates a new KeyStore with the given config and returns it.
for t := range time.NewTicker(600 * time.Second).C { func NewKeyStore(config *Config) (*KeyStore, error) {
if err := config.check(); err != nil {
return nil, err
}
// There is only one supported backend type, ldap.
ldap, err := backend.NewLDAPBackend(config.LDAPConfig)
if err != nil {
return nil, err
}
return newKeyStoreWithBackend(config, ldap)
}
func (s *KeyStore) expire(t time.Time) {
s.mx.Lock() s.mx.Lock()
for u, k := range s.userKeys { for u, k := range s.userKeys {
if k.expiry.Before(t) { if k.expiry.Before(t) {
...@@ -124,6 +127,11 @@ func (s *KeyStore) expire() { ...@@ -124,6 +127,11 @@ func (s *KeyStore) expire() {
} }
s.mx.Unlock() s.mx.Unlock()
} }
func (s *KeyStore) expireLoop() {
for t := range time.NewTicker(600 * time.Second).C {
s.expire(t)
}
} }
// Open the user's key store with the given password. If successful, // Open the user's key store with the given password. If successful,
......
package server
import (
"bytes"
"context"
"io/ioutil"
"os"
"path/filepath"
"testing"
"time"
"golang.org/x/crypto/ed25519"
"git.autistici.org/id/go-sso"
"git.autistici.org/id/keystore/userenckey"
)
type testContext struct {
dir string
pubkeyPath string
signer sso.Signer
}
func newTestContext(t testing.TB) *testContext {
dir, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal(err)
}
ctx := &testContext{
dir: dir,
pubkeyPath: filepath.Join(dir, "public.key"),
}
pub, priv, err := ed25519.GenerateKey(nil)
if err != nil {
t.Fatal("ed25519.GenerateKey():", err)
}
ctx.signer, err = sso.NewSigner(priv)
if err != nil {
t.Fatal("sso.NewSigner():", err)
}
ioutil.WriteFile(ctx.pubkeyPath, pub, 0644)
return ctx
}
func (c *testContext) Close() {
os.RemoveAll(c.dir)
}
func (c *testContext) sign(user, service, domain string) string {
tkt, _ := c.signer.Sign(sso.NewTicket(user, service, domain, "", nil, 600*time.Second))
return tkt
}
type testDB struct {
keys map[string][][]byte
}
func (t *testDB) GetPrivateKeys(_ context.Context, username string) ([][]byte, error) {
keys, ok := t.keys[username]
if !ok {
return nil, nil
}
return keys, nil
}
var (
privKey = []byte("fairly secret key")
pw = []byte("equally secret password")
encPrivKey []byte
)
func init() {
var err error
encPrivKey, err = userenckey.Encrypt(privKey, pw)
if err != nil {
panic(err)
}
}
func TestKeystore_OpenAndGet(t *testing.T) {
c := newTestContext(t)
defer c.Close()
db := &testDB{
keys: map[string][][]byte{
"testuser": [][]byte{encPrivKey},
},
}
keystore, err := newKeyStoreWithBackend(&Config{
SSOPublicKeyFile: c.pubkeyPath,
SSOService: "keystore/",
SSODomain: "domain",
}, db)
if err != nil {
t.Fatal(err)
}
// Decrypt the private key with the right password.
err = keystore.Open(context.Background(), "testuser", string(pw), 60)
if err != nil {
t.Fatal("keystore.Open():", err)
}
keystore.expire(time.Now())
// Sign a valid SSO ticket and use it to obtain the private
// key we just stored.
ssoTicket := c.sign("testuser", "keystore/", "domain")
result, err := keystore.Get("testuser", ssoTicket)
if err != nil {
t.Fatal("keystore.Get():", err)
}
if !bytes.Equal(result, privKey) {
t.Fatalf("keystore.Get() returned bad key: got %v, expected %v", result, privKey)
}
}
func TestKeystore_Expire(t *testing.T) {
c := newTestContext(t)
defer c.Close()
db := &testDB{
keys: map[string][][]byte{
"testuser": [][]byte{encPrivKey},
},
}
keystore, err := newKeyStoreWithBackend(&Config{
SSOPublicKeyFile: c.pubkeyPath,
SSOService: "keystore/",
SSODomain: "domain",
}, db)
if err != nil {
t.Fatal(err)
}
// Decrypt the private key with the right password.
err = keystore.Open(context.Background(), "testuser", string(pw), 60)
if err != nil {
t.Fatal("keystore.Open():", err)
}
keystore.expire(time.Now().Add(3600 * time.Second))
// Sign a valid SSO ticket and use it to obtain the private
// key we just stored.
ssoTicket := c.sign("testuser", "keystore/", "domain")
_, err = keystore.Get("testuser", ssoTicket)
if err != errNoKeys {
t.Fatal("keystore.Get():", err)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment