aboutsummaryrefslogtreecommitdiff
path: root/server/store
diff options
context:
space:
mode:
Diffstat (limited to 'server/store')
-rw-r--r--server/store/a_store-packr.go19
-rw-r--r--server/store/mem.go93
-rw-r--r--server/store/migrations/migrations_test.go110
-rw-r--r--server/store/migrations/mysql/20180626224600_create_issued_certs.sql15
-rw-r--r--server/store/migrations/mysql/20180807223808_idx_revoked_expires_at.sql5
-rw-r--r--server/store/migrations/mysql/20180807224200_new_primary_key.sql11
-rw-r--r--server/store/migrations/mysql/20180822204521_add_reason.sql5
-rw-r--r--server/store/migrations/sqlite3/20180626224600_create_issued_certs.sql15
-rw-r--r--server/store/migrations/sqlite3/20180807223808_idx_revoked_expires_at.sql5
-rw-r--r--server/store/migrations/sqlite3/20180807224200_new_primary_key.sql32
-rw-r--r--server/store/migrations/sqlite3/20180822204521_add_reason.sql18
-rw-r--r--server/store/sqldb.go176
-rw-r--r--server/store/sqlite.go7
-rw-r--r--server/store/store.go77
-rw-r--r--server/store/store_test.go162
-rw-r--r--server/store/string_slice.go38
16 files changed, 0 insertions, 788 deletions
diff --git a/server/store/a_store-packr.go b/server/store/a_store-packr.go
deleted file mode 100644
index 7b63e4b..0000000
--- a/server/store/a_store-packr.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Code generated by github.com/gobuffalo/packr. DO NOT EDIT.
-
-package store
-
-import "github.com/gobuffalo/packr"
-
-// You can use the "packr clean" command to clean up this,
-// and any other packr generated files.
-func init() {
- packr.PackJSONBytes("migrations", "migrations_test.go", "\"H4sIAAAAAAAA/6xW32/bNhB+lv6KA4ENUqfSBbanDH5IY7frlh9t5BQbgsClpZNNRCIVknJqFPnfhyNlW07TdAX2kkjU/fjuu++ObkVxK5YIjVwa4aRWNo5l02rjIIkjVgonFsLiyN7VLI5Y1Tj6J/VI6s5Jf9YItxoZoUp60Tb8HXUWDT22wq22/0eVrHF7YLCqsfDhHFon1ZLFccSW0q26BS90M1rql/auflkauUYzajYBwxyGNo1wTvWW0uGvLI5CKXhgZroFqjVV8bL/zA5zWWfQFSsz8liqzUhYi8Z9z8rgXScNsjiN46pTBczQuvzDqXR4tmM0cfCiL5HPUvgSR7ZblNLA0RjYHne5yACNP7V3Nb9oUSXBMAN21GCjzeaIpXHUJ+XnemqMNonzfhmwKyUWNYLToFtUEEJDoZXCgpB4504NkWVAaUOalDDwk1pbTNL4YVDR2Sb/cPpcQbICbflbdKjWCTv7J/9wOp9N8xlLYTwGxsgmcjy/lW3CzjXsLQDVWhqtGlQO1sJIKoGAPsSR52JXLd4nLj3gbiuJ0ip6969kd6JVJZdJ6r/wc3QwBuaKNpjy98JYnMkGYQzOdBhOj8vSwPjpMuZ/XFAtW3dr78tvmr4/znMy7TKYEyoaBH7SGYPKESRZAXF3ZdFkoG/JRFt+qvVt104fxbrKp5cs/Z3MiEDKTn6Euw8RRw+AtcXH3zv/oESDnsnntEVeb7RphJvk50lKGtlJ60ldeZ4PZRVHRpW+B+IWk+ubxcZhBr9RLKFKfomiTIwqffuqSn4m06pxPG+NVK5K2PynzywD64xUS2+ZxtE8YB5DueDTz1gk7ORyejybwuR4dvz6OJ8OttacCGHwC4T4j4t4MtrVD0b47uiEsJPLi/d7iO/ewPTvd/ksfzbVE3P3KNtg4igxvKA+Tl5nUEqDhdNm07Pn51EQwWGF7QbnyWlq6PDnfifyN7Le761cd6ZA0tVEmqN9nswrila53Ylqu9j521ovEv/0p5Yq2TsBe8FpWqmxoxF8RCOrDbiVcOBWaBCkBeGgRmEdaDW4kUh3plNfy/JcDzjtrVjfNzdtWrdJPMqvM/ZuagldC/fa3No4Urtitmz4dlKPB1U02e7zVRumWRzIxA+i4Keokp4iFZbZIwiClGPxrqO9ZzoFK2FBDSvaQfp/EE3vOlEnr76Fx+AajSVKBpweUvOfcUz0vfoRbh7ieDTyF03PTV0P2r/NIdHS0nFCKpIMWNEgWHSgqyFmH5kP7i659F8mW6gnWjlU7olbjNalDVusvQ7TdHN9Ex6+PMRR0XvulBJ+BPn1NpEmYZzktx27g9s5jaNKG5hnIP0YCrX0N7OP53mRFUj+zlKcQFTUX3P7aZL8XDSYpPthIrOeyvnXcxgWUxQ5I5sG/X4elhNtIVV7SD5YSL9zG4NoW1Rl0h9k+zSvhcWkSn0WH9FTeL0FeuNvWO8Ue4OguyuLfsRRObOByujGN/STd/5E7IOwIMBghQZVgUBASRVkpmlfWE4ryFhH0EPS/gcl/yjqDi+qxJ+m/Ey0f+HGJun1qxuehwsmvdm1Y72vPbTfazS00I+MD+fXvc+XwbrX7L8BAAD//4C0Bmk7CwAA\"")
- packr.PackJSONBytes("migrations", "mysql/20180626224600_create_issued_certs.sql", "\"H4sIAAAAAAAA/5SR0UrDMBSG7/MUh92swxVSYYjuqtoMirUbXQsbIk1oDhrqupLGrX17aV21TkGEXIXv//nOObYNFzv1rIVBSEpyFzE3ZhC7twEDfwHhMga28dfxGriqqjeUaYbaVBwsAsBzbFIlORyEzl6Eti5ns0mXCZMgmLZEqVWRqVK8VmeUxxZuEsQwenwadWSmURiUqTAcpDBo1A4/qbFzfUVt6tjUAUpv2ueMuxjWpdJY/Tem8bDPUXIwqmhUYSznS4l+EOKY5thwMFib9mcV+Q9utIV7tgWrH31CJvN+a37osQ1wJet0aLUMf+xuaP1r/qT3Z08/xhTOKsnwsN7+WBAvWq5Oh/1eMyfvAQAA//+OXEmHBQIAAA==\"")
- packr.PackJSONBytes("migrations", "mysql/20180807223808_idx_revoked_expires_at.sql", "\"H4sIAAAAAAAA/9LVVdDOzUwvSixJVQgt4HL0CXENUghxdPJxVUjILC4uTU2JT04tKilOUHAJ8g9Q8PRzcY1QSMhMqYgvSi3Lz05NiU+tKMgsSi2OTyxJsObiQjbPJb88D5+Jji4uBAxU0EiAiiboJCCJa1pzAQIAAP//O0rcq7kAAAA=\"")
- packr.PackJSONBytes("migrations", "mysql/20180807224200_new_primary_key.sql", "\"H4sIAAAAAAAA/5TOzarCMBAF4H2e4izvRfsErmIzQrBNa0zArhKxQYr4Q1NR314qFrJ1Nwxz5nxZhtm5O/b7IcDeGC8MaRi+LAi+i/EeWncI/RA9A4SuatRallw3WFMzZwAXAnlV2FLBd62HVCY9AbemclLlmkpSBiupt2bKWSU3liCVoN2YfrpTeLnxy5//Tv8LxlKiuD4uvyM/u0Q5AVJoWvkOAAD//1KTCm8VAQAA\"")
- packr.PackJSONBytes("migrations", "mysql/20180822204521_add_reason.sql", "\"H4sIAAAAAAAA/9LVVdDOzUwvSixJVQgt4HL0CXENUghxdPJxVUjILC4uTU2JT04tKilOUHB0cVFw9vcJ9fVTSMhNLS5OTE9NUAhxjQhR8PMPUfAL9fGx5uJCNs4lvzwPn4EuQf4BGCZaAwIAAP//am0hrZEAAAA=\"")
- packr.PackJSONBytes("migrations", "sqlite3/20180626224600_create_issued_certs.sql", "\"H4sIAAAAAAAA/5SR0UrDMBSG7/MUh92swxVSYYjuqtoMirUbXQsbIk1oDhrqupLGrX17aV21TkGEXIXv//nOObYNFzv1rIVBSEpyFzE3ZhC7twEDfwHhMga28dfxGriqqjeUaYbaVBwsAsBzbFIlORyEzl6Eti5ns0mXCZMgmLZEqVWRqVK8VmeUxxZuEsQwenwadWSmURiUqTAcpDBo1A4/qbFzfUVt6tjUAUpv2ueMuxjWpdJY/Tem8bDPUXIwqmhUYSznS4l+EOKY5thwMFib9mcV+Q9utIV7tgWrH31CJvN+a37osQ1wJet0aLUMf+xuaP1r/qT3Z08/xhTOKsnwsN7+WBAvWq5Oh/1eMyfvAQAA//+OXEmHBQIAAA==\"")
- packr.PackJSONBytes("migrations", "sqlite3/20180807223808_idx_revoked_expires_at.sql", "\"H4sIAAAAAAAA/9LVVdDOzUwvSixJVQgt4HIJ8g9Q8PRzcY1QSMhMqYgvSi3Lz05NiU+tKMgsSi2OTyxJsObiQtbkkl+ex+Uc5OoY4kpAo4K/n0JCZnFxaWpKfHJqUUlxgoJGAlRdgo5CApJSTWsuQAAAAP//Yo/PZJkAAAA=\"")
- packr.PackJSONBytes("migrations", "sqlite3/20180807224200_new_primary_key.sql", "\"H4sIAAAAAAAA/9yTUWucQBSF3+dXXPISpS5oIZTWJ5u9W6TumI4jJITgDDq0wyaujNPs7r8vugaN3RaWUigFn5xz9Zxzv1ks4M2T/mqkVZA35JphxBF49DFBELptv6uqKJWxbVGrnQCHAAhdCYgpx0/I4IbF64jdwWe887qzjToU3fmzNOU3aZy3V1cu5DT+kiPQlAPNk6QXNkbXpW7kYzsTL3EV5QmHy/uHy15ZGiWtqgppBVTSKquf1KgK3r/zF36w8APw/Q/dExzH1L7RRrXnjhn1vN2oSoDV9UHX1gkmlvxBI3fFRh0EWLW3xA1JTDNkvCslPdnasRUPxtAejLE8GL16MBjwYPiLSwAyTPCaw598BlYsXb82J0KyZOnNqW2LkEQJR/ZrEhjSaI0wDyzCF4ZiusTbDpZ9MV1FSmcD4ExX5YaETJlcbnf1ayrjVQ8S3sYZz2bOto/VwOhJDs8D8OL+4eIfA9D/Gb/uzeQSgvMS3e3A/A2Zx67+LzL7TH+NzB8BAAD//5JBr+QsBQAA\"")
- packr.PackJSONBytes("migrations", "sqlite3/20180822204521_add_reason.sql", "\"H4sIAAAAAAAA/6SSQWvbQBCF7/srHrnEpjJIhVBanVRrUkTlVbpZQUIp2sUa0sW1Ylbb2P73RbFdG+MeSmBv82b2vZlvMsG7pXvyNjDqlchKTQo6+1wSjOv739w2c/ahN8jyHNOqrGcSZsl9b5/YQNODhqw0ZF2WyOk2q0uNq6tUiNPJ+fO6E1NFmaZLw5uO1wYjARjXGhRS0xdSuFPFLFOP+EqP0VBb8LYZ6i/Wz39aP3p/czNGLYtvNf318CpcedfN3cr+6s/EB4PX339cvyrnnm3gtrHBoLWBg1vyUZV8/BBP4mQSJ4jjT8NLdm28WTnP/f+2eX55XnBrEFy3dV0YJSeW4r3GrpsFbw0Cb4IYp6KQ96T0sJTq4tZ2W4lwDB3hGCvC0WuEvYEI+1/GArinkqYabxmDW1XNznhJRa6qu4sopf/GbJdJkcxmhPPAJj0wVMicHgZYNs3pKSp5Du3o9FTj9E8AAAD//xeZkE/uAgAA\"")
-}
diff --git a/server/store/mem.go b/server/store/mem.go
deleted file mode 100644
index 8f27854..0000000
--- a/server/store/mem.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package store
-
-import (
- "fmt"
- "sync"
- "time"
-)
-
-var _ CertStorer = (*memoryStore)(nil)
-
-// memoryStore is an in-memory CertStorer
-type memoryStore struct {
- sync.Mutex
- certs map[string]*CertRecord
-}
-
-// Get a single *CertRecord
-func (ms *memoryStore) Get(id string) (*CertRecord, error) {
- ms.Lock()
- defer ms.Unlock()
- r, ok := ms.certs[id]
- if !ok {
- return nil, fmt.Errorf("unknown cert %s", id)
- }
- return r, nil
-}
-
-// SetRecord records a *CertRecord
-func (ms *memoryStore) SetRecord(record *CertRecord) error {
- ms.Lock()
- defer ms.Unlock()
- ms.certs[record.KeyID] = record
- return nil
-}
-
-// List returns all recorded certs.
-// By default only active certs are returned.
-func (ms *memoryStore) List(includeExpired bool) ([]*CertRecord, error) {
- var records []*CertRecord
- ms.Lock()
- defer ms.Unlock()
-
- for _, value := range ms.certs {
- if !includeExpired && value.Expires.Before(time.Now().UTC()) {
- continue
- }
- records = append(records, value)
- }
- return records, nil
-}
-
-// Revoke an issued cert by id.
-func (ms *memoryStore) Revoke(ids []string) error {
- ms.Lock()
- defer ms.Unlock()
- for _, id := range ids {
- ms.certs[id].Revoked = true
- }
- return nil
-}
-
-// GetRevoked returns all revoked certs
-func (ms *memoryStore) GetRevoked() ([]*CertRecord, error) {
- var revoked []*CertRecord
- all, _ := ms.List(false)
- for _, r := range all {
- if r.Revoked {
- revoked = append(revoked, r)
- }
- }
- return revoked, nil
-}
-
-// Close the store. This will clear the contents.
-func (ms *memoryStore) Close() error {
- ms.Lock()
- defer ms.Unlock()
- ms.certs = nil
- return nil
-}
-
-func (ms *memoryStore) clear() {
- for k := range ms.certs {
- delete(ms.certs, k)
- }
-}
-
-// newMemoryStore returns an in-memory CertStorer.
-func newMemoryStore() *memoryStore {
- return &memoryStore{
- certs: make(map[string]*CertRecord),
- }
-}
diff --git a/server/store/migrations/migrations_test.go b/server/store/migrations/migrations_test.go
deleted file mode 100644
index 482450b..0000000
--- a/server/store/migrations/migrations_test.go
+++ /dev/null
@@ -1,110 +0,0 @@
-package migrations
-
-import (
- "database/sql"
- "fmt"
- "io/ioutil"
- "math/rand"
- "os"
- "os/user"
- "path"
- "path/filepath"
- "reflect"
- "testing"
-
- "github.com/go-sql-driver/mysql"
- _ "github.com/mattn/go-sqlite3"
- migrate "github.com/rubenv/sql-migrate"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-)
-
-func TestSQLiteMigrations(t *testing.T) {
- subdir := "sqlite3"
- db, err := sql.Open(subdir, ":memory:")
- require.NoError(t, err, "Unable to open sqlite connection")
- runMigrations(t, db, subdir)
- db.Close()
-}
-
-func TestMySQLMigrations(t *testing.T) {
- if os.Getenv("MYSQL_TEST") == "" {
- t.Skip("No MYSQL_TEST environment variable")
- }
- r := require.New(t)
- subdir := "mysql"
- dsn := mysql.NewConfig()
- dsn.Net = "tcp"
- dsn.ParseTime = true
- dsn.Addr = os.Getenv("MYSQL_TEST_HOST")
- dsn.Passwd = os.Getenv("MYSQL_TEST_PASS")
- u, _ := user.Current()
- if testUser, ok := os.LookupEnv("MYSQL_TEST_USER"); ok {
- dsn.User = testUser
- } else {
- dsn.User = u.Username
- }
- db, err := sql.Open(subdir, dsn.FormatDSN())
- r.NoError(err, "Unable to open mysql connection")
-
- rnd := make([]byte, 4)
- rand.Read(rnd)
- suffix := fmt.Sprintf("_%x", string(rnd))
- _, err = db.Exec("CREATE DATABASE migrations_test" + suffix)
- r.NoError(err)
- _, err = db.Exec("USE migrations_test" + suffix)
- r.NoError(err)
- runMigrations(t, db, subdir)
- db.Exec("DROP DATABASE IF EXISTS migrations_test" + suffix)
- db.Close()
-}
-
-func runMigrations(t *testing.T, db *sql.DB, directory string) {
- a := assert.New(t)
- r := require.New(t)
- m := &migrate.FileMigrationSource{
- Dir: directory,
- }
- files, err := filepath.Glob(path.Join(directory, "*.sql"))
- // Verify that there is at least one migration to run
- r.NoError(err, "No migrations to run")
- r.NotEmpty(files)
- // Verify that migrating up works
- n, err := migrate.Exec(db, directory, m, migrate.Up)
- if a.NoError(err) {
- a.Len(files, n)
- }
- // Verify that a subsequent run has no migrations
- n, err = migrate.Exec(db, directory, m, migrate.Up)
- if a.NoError(err) {
- a.Equal(0, n)
- }
- // Verify that reversing migrations works
- n, err = migrate.Exec(db, directory, m, migrate.Down)
- if a.NoError(err) {
- a.Len(files, n)
- }
-}
-
-// Test that all migration directories contain the same set of migrations files.
-func TestMigationDirectoryContents(t *testing.T) {
- names := map[string][]string{}
- contents, err := ioutil.ReadDir(".")
- assert.NoError(t, err)
- for _, i := range contents {
- if i.IsDir() {
- dir := path.Join(i.Name(), "*.sql")
- files, _ := filepath.Glob(dir)
- trimmed := []string{}
- for _, f := range files {
- trimmed = append(trimmed, filepath.Base(f))
- }
- names[i.Name()] = trimmed
- }
- }
- // Use one entry from the `names` map as a reference for all the others.
- first := names[reflect.ValueOf(names).MapKeys()[0].String()]
- for _, v := range names {
- assert.EqualValues(t, first, v)
- }
-}
diff --git a/server/store/migrations/mysql/20180626224600_create_issued_certs.sql b/server/store/migrations/mysql/20180626224600_create_issued_certs.sql
deleted file mode 100644
index c5b80e0..0000000
--- a/server/store/migrations/mysql/20180626224600_create_issued_certs.sql
+++ /dev/null
@@ -1,15 +0,0 @@
--- +migrate Up
-CREATE TABLE IF NOT EXISTS `issued_certs` (
- `key_id` varchar(255) NOT NULL,
- `principals` varchar(255) DEFAULT "[]",
- `created_at` datetime DEFAULT '1970-01-01 00:00:01',
- `expires_at` datetime DEFAULT '1970-01-01 00:00:01',
- `revoked` tinyint(1) DEFAULT 0,
- `raw_key` text,
- PRIMARY KEY (`key_id`)
-);
-CREATE INDEX `idx_expires_at` ON `issued_certs` (`expires_at`);
-CREATE INDEX `idx_revoked_expires_at` ON `issued_certs` (`revoked`, `expires_at`);
-
--- +migrate Down
-DROP TABLE `issued_certs`;
diff --git a/server/store/migrations/mysql/20180807223808_idx_revoked_expires_at.sql b/server/store/migrations/mysql/20180807223808_idx_revoked_expires_at.sql
deleted file mode 100644
index fe82dd5..0000000
--- a/server/store/migrations/mysql/20180807223808_idx_revoked_expires_at.sql
+++ /dev/null
@@ -1,5 +0,0 @@
--- +migrate Up
-ALTER TABLE `issued_certs` DROP INDEX `idx_revoked_expires_at`;
-
--- +migrate Down
-ALTER TABLE `issued_certs` ADD INDEX `idx_revoked_expires_at` (`revoked`,`expires_at`);
diff --git a/server/store/migrations/mysql/20180807224200_new_primary_key.sql b/server/store/migrations/mysql/20180807224200_new_primary_key.sql
deleted file mode 100644
index ed6a3c2..0000000
--- a/server/store/migrations/mysql/20180807224200_new_primary_key.sql
+++ /dev/null
@@ -1,11 +0,0 @@
--- +migrate Up
-ALTER TABLE `issued_certs`
- DROP PRIMARY KEY,
- ADD COLUMN `id` INT PRIMARY KEY AUTO_INCREMENT FIRST,
- ADD UNIQUE INDEX `idx_key_id` (`key_id`);
-
--- +migrate Down
-ALTER TABLE `issued_certs`
- DROP PRIMARY KEY,
- DROP COLUMN `id`,
- ADD PRIMARY KEY (`key_id`);
diff --git a/server/store/migrations/mysql/20180822204521_add_reason.sql b/server/store/migrations/mysql/20180822204521_add_reason.sql
deleted file mode 100644
index 85fdd4d..0000000
--- a/server/store/migrations/mysql/20180822204521_add_reason.sql
+++ /dev/null
@@ -1,5 +0,0 @@
--- +migrate Up
-ALTER TABLE `issued_certs` ADD COLUMN `message` TEXT NOT NULL;
-
--- +migrate Down
-ALTER TABLE `issued_certs` DROP COLUMN `message`; \ No newline at end of file
diff --git a/server/store/migrations/sqlite3/20180626224600_create_issued_certs.sql b/server/store/migrations/sqlite3/20180626224600_create_issued_certs.sql
deleted file mode 100644
index c5b80e0..0000000
--- a/server/store/migrations/sqlite3/20180626224600_create_issued_certs.sql
+++ /dev/null
@@ -1,15 +0,0 @@
--- +migrate Up
-CREATE TABLE IF NOT EXISTS `issued_certs` (
- `key_id` varchar(255) NOT NULL,
- `principals` varchar(255) DEFAULT "[]",
- `created_at` datetime DEFAULT '1970-01-01 00:00:01',
- `expires_at` datetime DEFAULT '1970-01-01 00:00:01',
- `revoked` tinyint(1) DEFAULT 0,
- `raw_key` text,
- PRIMARY KEY (`key_id`)
-);
-CREATE INDEX `idx_expires_at` ON `issued_certs` (`expires_at`);
-CREATE INDEX `idx_revoked_expires_at` ON `issued_certs` (`revoked`, `expires_at`);
-
--- +migrate Down
-DROP TABLE `issued_certs`;
diff --git a/server/store/migrations/sqlite3/20180807223808_idx_revoked_expires_at.sql b/server/store/migrations/sqlite3/20180807223808_idx_revoked_expires_at.sql
deleted file mode 100644
index ae9ca3d..0000000
--- a/server/store/migrations/sqlite3/20180807223808_idx_revoked_expires_at.sql
+++ /dev/null
@@ -1,5 +0,0 @@
--- +migrate Up
-DROP INDEX `idx_revoked_expires_at`;
-
--- +migrate Down
-CREATE INDEX `idx_revoked_expires_at` ON `issued_certs` (`revoked`, `expires_at`);
diff --git a/server/store/migrations/sqlite3/20180807224200_new_primary_key.sql b/server/store/migrations/sqlite3/20180807224200_new_primary_key.sql
deleted file mode 100644
index 40f333c..0000000
--- a/server/store/migrations/sqlite3/20180807224200_new_primary_key.sql
+++ /dev/null
@@ -1,32 +0,0 @@
--- +migrate Up
-CREATE TABLE `issued_certs_new` (
- `id` INTEGER PRIMARY KEY,
- `key_id` varchar(255) UNIQUE NOT NULL,
- `principals` varchar(255) DEFAULT '[]',
- `created_at` datetime DEFAULT '1970-01-01 00:00:01',
- `expires_at` datetime DEFAULT '1970-01-01 00:00:01',
- `revoked` tinyint(1) DEFAULT '0',
- `raw_key` text
-);
-INSERT INTO `issued_certs_new` (key_id, principals, created_at, expires_at, revoked, raw_key)
- SELECT key_id, principals, created_at, expires_at, revoked, raw_key FROM `issued_certs`;
-DROP TABLE `issued_certs`;
-ALTER TABLE `issued_certs_new` RENAME TO `issued_certs`;
-CREATE INDEX `idx_expires_at` ON `issued_certs` (`expires_at`);
-
--- +migrate Down
-CREATE TABLE IF NOT EXISTS `issued_certs_old` (
- `key_id` varchar(255) NOT NULL,
- `principals` varchar(255) DEFAULT "[]",
- `created_at` datetime DEFAULT '1970-01-01 00:00:01',
- `expires_at` datetime DEFAULT '1970-01-01 00:00:01',
- `revoked` tinyint(1) DEFAULT 0,
- `raw_key` text,
- PRIMARY KEY (`key_id`)
-);
-
-INSERT INTO `issued_certs_old` (key_id, principals, created_at, expires_at, revoked, raw_key)
- SELECT key_id, principals, created_at, expires_at, revoked, raw_key FROM `issued_certs`;
-DROP TABLE `issued_certs`;
-ALTER TABLE `issued_certs_old` RENAME TO `issued_certs`;
-CREATE INDEX `idx_expires_at` ON `issued_certs` (`expires_at`); \ No newline at end of file
diff --git a/server/store/migrations/sqlite3/20180822204521_add_reason.sql b/server/store/migrations/sqlite3/20180822204521_add_reason.sql
deleted file mode 100644
index 07e9d49..0000000
--- a/server/store/migrations/sqlite3/20180822204521_add_reason.sql
+++ /dev/null
@@ -1,18 +0,0 @@
--- +migrate Up
-ALTER TABLE `issued_certs` ADD COLUMN `message` TEXT NOT NULL DEFAULT "";
-
--- +migrate Down
-CREATE TABLE `issued_certs_new` (
- `id` INTEGER PRIMARY KEY,
- `key_id` varchar(255) UNIQUE NOT NULL,
- `principals` varchar(255) DEFAULT '[]',
- `created_at` datetime DEFAULT '1970-01-01 00:00:01',
- `expires_at` datetime DEFAULT '1970-01-01 00:00:01',
- `revoked` tinyint(1) DEFAULT '0',
- `raw_key` text
-);
-INSERT INTO `issued_certs_new` (key_id, principals, created_at, expires_at, revoked, raw_key)
- SELECT key_id, principals, created_at, expires_at, revoked, raw_key FROM `issued_certs`;
-DROP TABLE `issued_certs`;
-ALTER TABLE `issued_certs_new` RENAME TO `issued_certs`;
-CREATE INDEX `idx_expires_at` ON `issued_certs` (`expires_at`); \ No newline at end of file
diff --git a/server/store/sqldb.go b/server/store/sqldb.go
deleted file mode 100644
index 8ca34a9..0000000
--- a/server/store/sqldb.go
+++ /dev/null
@@ -1,176 +0,0 @@
-package store
-
-import (
- "fmt"
- "log"
- "net"
- "time"
-
- "github.com/go-sql-driver/mysql"
- "github.com/gobuffalo/packr"
- multierror "github.com/hashicorp/go-multierror"
- "github.com/jmoiron/sqlx"
- "github.com/nsheridan/cashier/server/config"
- "github.com/pkg/errors"
- migrate "github.com/rubenv/sql-migrate"
-)
-
-var _ CertStorer = (*sqlStore)(nil)
-
-// sqlStore is an sql-based CertStorer
-type sqlStore struct {
- conn *sqlx.DB
-
- get *sqlx.Stmt
- set *sqlx.Stmt
- listAll *sqlx.Stmt
- listCurrent *sqlx.Stmt
- revoked *sqlx.Stmt
-}
-
-// newSQLStore returns a *sql.DB CertStorer.
-func newSQLStore(c config.Database) (*sqlStore, error) {
- var driver string
- var dsn string
- switch c["type"] {
- case "mysql":
- driver = "mysql"
- address := c["address"]
- _, _, err := net.SplitHostPort(address)
- if err != nil {
- address = address + ":3306"
- }
- m := mysql.NewConfig()
- m.User = c["username"]
- m.Passwd = c["password"]
- m.Addr = address
- m.Net = "tcp"
- m.DBName = c["dbname"]
- if m.DBName == "" {
- m.DBName = "certs" // Legacy database name
- }
- m.ParseTime = true
- dsn = m.FormatDSN()
- case "sqlite":
- driver = "sqlite3"
- dsn = c["filename"]
- }
-
- conn, err := sqlx.Connect(driver, dsn)
- if err != nil {
- return nil, fmt.Errorf("sqlStore: could not get a connection: %v", err)
- }
- if err := autoMigrate(driver, conn); err != nil {
- return nil, fmt.Errorf("sqlStore: could not update schema: %v", err)
- }
-
- db := &sqlStore{
- conn: conn,
- }
-
- if db.set, err = conn.Preparex("INSERT INTO issued_certs (key_id, principals, created_at, expires_at, raw_key, message) VALUES (?, ?, ?, ?, ?, ?)"); err != nil {
- return nil, fmt.Errorf("sqlStore: prepare set: %v", err)
- }
- if db.get, err = conn.Preparex("SELECT * FROM issued_certs WHERE key_id = ?"); err != nil {
- return nil, fmt.Errorf("sqlStore: prepare get: %v", err)
- }
- if db.listAll, err = conn.Preparex("SELECT * FROM issued_certs"); err != nil {
- return nil, fmt.Errorf("sqlStore: prepare listAll: %v", err)
- }
- if db.listCurrent, err = conn.Preparex("SELECT * FROM issued_certs WHERE expires_at >= ?"); err != nil {
- return nil, fmt.Errorf("sqlStore: prepare listCurrent: %v", err)
- }
- if db.revoked, err = conn.Preparex("SELECT * FROM issued_certs WHERE revoked = 1 AND ? <= expires_at"); err != nil {
- return nil, fmt.Errorf("sqlStore: prepare revoked: %v", err)
- }
- return db, nil
-}
-
-func autoMigrate(driver string, conn *sqlx.DB) error {
- log.Print("Executing any pending schema migrations")
- var err error
- migrate.SetTable("schema_migrations")
- srcs := &migrate.PackrMigrationSource{
- Box: packr.NewBox("migrations"),
- Dir: driver,
- }
- n, err := migrate.Exec(conn.DB, driver, srcs, migrate.Up)
- if err != nil {
- err = multierror.Append(err)
- return err
- }
- log.Printf("Executed %d migrations", n)
- if err != nil {
- log.Fatalf("Errors were found running migrations: %v", err)
- }
- return nil
-}
-
-// Get a single *CertRecord
-func (db *sqlStore) Get(id string) (*CertRecord, error) {
- if err := db.conn.Ping(); err != nil {
- return nil, errors.Wrap(err, "unable to connect to database")
- }
- r := &CertRecord{}
- return r, db.get.Get(r, id)
-}
-
-// SetRecord records a *CertRecord
-func (db *sqlStore) SetRecord(rec *CertRecord) error {
- if err := db.conn.Ping(); err != nil {
- return errors.Wrap(err, "unable to connect to database")
- }
- _, err := db.set.Exec(rec.KeyID, rec.Principals, rec.CreatedAt, rec.Expires, rec.Raw, rec.Message)
- return err
-}
-
-// List returns all recorded certs.
-// By default only active certs are returned.
-func (db *sqlStore) List(includeExpired bool) ([]*CertRecord, error) {
- if err := db.conn.Ping(); err != nil {
- return nil, errors.Wrap(err, "unable to connect to database")
- }
- recs := []*CertRecord{}
- if includeExpired {
- if err := db.listAll.Select(&recs); err != nil {
- return nil, err
- }
- } else {
- if err := db.listCurrent.Select(&recs, time.Now()); err != nil {
- return nil, err
- }
- }
- return recs, nil
-}
-
-// Revoke an issued cert by id.
-func (db *sqlStore) Revoke(ids []string) error {
- var err error
- if err = db.conn.Ping(); err != nil {
- return errors.Wrap(err, "unable to connect to database")
- }
- q, args, err := sqlx.In("UPDATE issued_certs SET revoked = 1 WHERE key_id IN (?)", ids)
- if err != nil {
- return err
- }
- q = db.conn.Rebind(q)
- _, err = db.conn.Exec(q, args...)
- return err
-}
-
-// GetRevoked returns all revoked certs
-func (db *sqlStore) GetRevoked() ([]*CertRecord, error) {
- if err := db.conn.Ping(); err != nil {
- return nil, errors.Wrap(err, "unable to connect to database")
- }
- var recs []*CertRecord
- if err := db.revoked.Select(&recs, time.Now().UTC()); err != nil {
- return nil, err
- }
- return recs, nil
-}
-
-// Close the connection to the database
-func (db *sqlStore) Close() error {
- return db.conn.Close()
-}
diff --git a/server/store/sqlite.go b/server/store/sqlite.go
deleted file mode 100644
index 8f38bd2..0000000
--- a/server/store/sqlite.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// +build cgo
-
-package store
-
-import (
- _ "github.com/mattn/go-sqlite3" // required by sql driver
-)
diff --git a/server/store/store.go b/server/store/store.go
deleted file mode 100644
index 88ec7ce..0000000
--- a/server/store/store.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package store
-
-import (
- "encoding/json"
- "fmt"
- "time"
-
- "github.com/nsheridan/cashier/lib"
- "github.com/nsheridan/cashier/server/config"
- "golang.org/x/crypto/ssh"
-)
-
-// New returns a new configured database.
-func New(c config.Database) (CertStorer, error) {
- switch c["type"] {
- case "mysql", "sqlite":
- return newSQLStore(c)
- case "mem":
- return newMemoryStore(), nil
- }
- return nil, fmt.Errorf("unable to create store with driver %s", c["type"])
-}
-
-// CertStorer records issued certs in a persistent store for audit and
-// revocation purposes.
-type CertStorer interface {
- Get(id string) (*CertRecord, error)
- SetRecord(record *CertRecord) error
- List(includeExpired bool) ([]*CertRecord, error)
- Revoke(id []string) error
- GetRevoked() ([]*CertRecord, error)
- Close() error
-}
-
-// A CertRecord is a representation of a ssh certificate used by a CertStorer.
-type CertRecord struct {
- ID int `json:"-" db:"id"`
- KeyID string `json:"key_id" db:"key_id"`
- Principals StringSlice `json:"principals" db:"principals"`
- CreatedAt time.Time `json:"created_at" db:"created_at"`
- Expires time.Time `json:"expires" db:"expires_at"`
- Revoked bool `json:"revoked" db:"revoked"`
- Raw string `json:"-" db:"raw_key"`
- Message string `json:"message" db:"message"`
-}
-
-// MarshalJSON implements the json.Marshaler interface for the CreatedAt and
-// Expires fields.
-// The resulting string looks like "2017-04-11 10:00:00 +0000"
-func (c *CertRecord) MarshalJSON() ([]byte, error) {
- type Alias CertRecord
- f := "2006-01-02 15:04:05 -0700"
- return json.Marshal(&struct {
- *Alias
- CreatedAt string `json:"created_at"`
- Expires string `json:"expires"`
- }{
- Alias: (*Alias)(c),
- CreatedAt: c.CreatedAt.Format(f),
- Expires: c.Expires.Format(f),
- })
-}
-
-func parseTime(t uint64) time.Time {
- return time.Unix(int64(t), 0)
-}
-
-// MakeRecord converts a Certificate to a CertRecord
-func MakeRecord(cert *ssh.Certificate) *CertRecord {
- return &CertRecord{
- KeyID: cert.KeyId,
- Principals: StringSlice(cert.ValidPrincipals),
- CreatedAt: parseTime(cert.ValidAfter),
- Expires: parseTime(cert.ValidBefore),
- Raw: string(lib.GetPublicKey(cert)),
- }
-}
diff --git a/server/store/store_test.go b/server/store/store_test.go
deleted file mode 100644
index 90a494e..0000000
--- a/server/store/store_test.go
+++ /dev/null
@@ -1,162 +0,0 @@
-package store
-
-import (
- "crypto/rand"
- "crypto/rsa"
- "encoding/json"
- "io/ioutil"
- "os"
- "os/user"
- "testing"
- "time"
-
- "github.com/nsheridan/cashier/testdata"
- "github.com/stretchr/testify/assert"
-
- "golang.org/x/crypto/ssh"
-)
-
-func TestParseCertificate(t *testing.T) {
- a := assert.New(t)
- now := uint64(time.Now().Unix())
- r, _ := rsa.GenerateKey(rand.Reader, 1024)
- pub, _ := ssh.NewPublicKey(r.Public())
- c := &ssh.Certificate{
- KeyId: "id",
- ValidPrincipals: StringSlice{"principal"},
- ValidBefore: now,
- CertType: ssh.UserCert,
- Key: pub,
- }
- s, _ := ssh.NewSignerFromKey(r)
- c.SignCert(rand.Reader, s)
- rec := MakeRecord(c)
-
- a.Equal(c.KeyId, rec.KeyID)
- a.Equal(c.ValidPrincipals, []string(rec.Principals))
- a.Equal(c.ValidBefore, uint64(rec.Expires.Unix()))
- a.Equal(c.ValidAfter, uint64(rec.CreatedAt.Unix()))
-}
-
-func testStore(t *testing.T, db CertStorer) {
- defer db.Close()
-
- r := &CertRecord{
- KeyID: "a",
- Principals: []string{"b"},
- CreatedAt: time.Now().UTC(),
- Expires: time.Now().UTC().Add(-1 * time.Second),
- Raw: "AAAAAA",
- }
- if err := db.SetRecord(r); err != nil {
- t.Error(err)
- }
-
- // includeExpired = false should return 0 results
- recs, err := db.List(false)
- if err != nil {
- t.Error(err)
- }
- if len(recs) > 0 {
- t.Errorf("Expected 0 results, got %d", len(recs))
- }
- // includeExpired = false should return 1 result
- recs, err = db.List(true)
- if err != nil {
- t.Error(err)
- }
- if recs[0].KeyID != r.KeyID {
- t.Error("key mismatch")
- }
-
- c, _, _, _, _ := ssh.ParseAuthorizedKey(testdata.Cert)
- cert := c.(*ssh.Certificate)
- cert.ValidBefore = uint64(time.Now().Add(1 * time.Hour).UTC().Unix())
- cert.ValidAfter = uint64(time.Now().Add(-5 * time.Minute).UTC().Unix())
- rec := MakeRecord(cert)
- if err := db.SetRecord(rec); err != nil {
- t.Error(err)
- }
-
- ret, err := db.Get("key")
- if err != nil {
- t.Error(err)
- }
- if ret.KeyID != cert.KeyId {
- t.Error("key mismatch")
- }
- if err := db.Revoke([]string{"key"}); err != nil {
- t.Error(err)
- }
-
- revoked, err := db.GetRevoked()
- if err != nil {
- t.Error(err)
- }
- if len(revoked) != 1 {
- t.Errorf("Expected 1 revoked key, got %d", len(revoked))
- }
- for _, k := range revoked {
- if k.KeyID != "key" {
- t.Errorf("Unexpected key: %s", k.KeyID)
- }
- }
-}
-
-func TestMemoryStore(t *testing.T) {
- db := newMemoryStore()
- testStore(t, db)
-}
-
-func TestMySQLStore(t *testing.T) {
- if os.Getenv("MYSQL_TEST") == "" {
- t.Skip("No MYSQL_TEST environment variable")
- }
- u, _ := user.Current()
- sqlConfig := map[string]string{
- "type": "mysql",
- "password": os.Getenv("MYSQL_TEST_PASS"),
- "address": os.Getenv("MYSQL_TEST_HOST"),
- }
- if testUser, ok := os.LookupEnv("MYSQL_TEST_USER"); ok {
- sqlConfig["username"] = testUser
- } else {
- sqlConfig["username"] = u.Username
- }
- db, err := newSQLStore(sqlConfig)
- if err != nil {
- t.Error(err)
- }
- testStore(t, db)
-}
-
-func TestSQLiteStore(t *testing.T) {
- f, err := ioutil.TempFile("", "sqlite_test_db")
- if err != nil {
- t.Error(err)
- }
- defer os.Remove(f.Name())
- config := map[string]string{"type": "sqlite", "filename": f.Name()}
- db, err := newSQLStore(config)
- if err != nil {
- t.Error(err)
- }
- testStore(t, db)
-}
-
-func TestMarshalCert(t *testing.T) {
- a := assert.New(t)
- c := &CertRecord{
- KeyID: "id",
- Principals: []string{"user"},
- CreatedAt: time.Date(2017, time.April, 10, 13, 0, 0, 0, time.UTC),
- Expires: time.Date(2017, time.April, 11, 10, 0, 0, 0, time.UTC),
- Raw: "ABCDEF",
- }
- b, err := json.Marshal(c)
- if err != nil {
- t.Error(err)
- }
- want := `{"key_id":"id","principals":["user"],"revoked":false,"created_at":"2017-04-10 13:00:00 +0000","expires":"2017-04-11 10:00:00 +0000","message":""}`
- a.JSONEq(want, string(b))
-}
diff --git a/server/store/string_slice.go b/server/store/string_slice.go
deleted file mode 100644
index a443cdd..0000000
--- a/server/store/string_slice.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package store
-
-import (
- "database/sql/driver"
- "encoding/json"
-)
-
-// StringSlice is a []string which will be stored in a database as a JSON array.
-type StringSlice []string
-
-var _ driver.Valuer = (*StringSlice)(nil)
-
-// Value implements the driver.Valuer interface, marshalling the raw value to
-// a JSON array.
-func (s StringSlice) Value() (driver.Value, error) {
- v, err := json.Marshal(s)
- if err != nil {
- return nil, err
- }
- return string(v), err
-}
-
-// Scan implements the sql.Scanner interface, unmarshalling the value coming
-// off the wire and storing the result in the StringSlice.
-func (s *StringSlice) Scan(value interface{}) error {
- if value == nil {
- s = &StringSlice{}
- return nil
- }
- var err error
- v, err := driver.String.ConvertValue(value)
- if err == nil {
- if v, ok := v.([]byte); ok {
- err = json.Unmarshal(v, s)
- }
- }
- return err
-}