From 2ce3b86e0ff69538935db3149d1ed2f24aea09a3 Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Mon, 13 Apr 2020 23:57:13 -0400 Subject: Simplify --- server/store/a_store-packr.go | 19 --- server/store/mem.go | 93 ----------- server/store/migrations/migrations_test.go | 110 ------------- .../mysql/20180626224600_create_issued_certs.sql | 15 -- .../20180807223808_idx_revoked_expires_at.sql | 5 - .../mysql/20180807224200_new_primary_key.sql | 11 -- .../migrations/mysql/20180822204521_add_reason.sql | 5 - .../sqlite3/20180626224600_create_issued_certs.sql | 15 -- .../20180807223808_idx_revoked_expires_at.sql | 5 - .../sqlite3/20180807224200_new_primary_key.sql | 32 ---- .../sqlite3/20180822204521_add_reason.sql | 18 --- server/store/sqldb.go | 176 --------------------- server/store/sqlite.go | 7 - server/store/store.go | 77 --------- server/store/store_test.go | 162 ------------------- server/store/string_slice.go | 38 ----- 16 files changed, 788 deletions(-) delete mode 100644 server/store/a_store-packr.go delete mode 100644 server/store/mem.go delete mode 100644 server/store/migrations/migrations_test.go delete mode 100644 server/store/migrations/mysql/20180626224600_create_issued_certs.sql delete mode 100644 server/store/migrations/mysql/20180807223808_idx_revoked_expires_at.sql delete mode 100644 server/store/migrations/mysql/20180807224200_new_primary_key.sql delete mode 100644 server/store/migrations/mysql/20180822204521_add_reason.sql delete mode 100644 server/store/migrations/sqlite3/20180626224600_create_issued_certs.sql delete mode 100644 server/store/migrations/sqlite3/20180807223808_idx_revoked_expires_at.sql delete mode 100644 server/store/migrations/sqlite3/20180807224200_new_primary_key.sql delete mode 100644 server/store/migrations/sqlite3/20180822204521_add_reason.sql delete mode 100644 server/store/sqldb.go delete mode 100644 server/store/sqlite.go delete mode 100644 server/store/store.go delete mode 100644 server/store/store_test.go delete mode 100644 server/store/string_slice.go (limited to 'server/store') 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 -} -- cgit v1.2.3