From 3a2ba851264e5eaaa539fe0792b0abcbb0f5d626 Mon Sep 17 00:00:00 2001 From: Sebastian Tiedtke Date: Wed, 17 Apr 2019 14:00:24 -0700 Subject: [PATCH 01/15] Flip default for certificate restriction to namespace to false (#60) --- autocert/install/02-autocert.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autocert/install/02-autocert.yaml b/autocert/install/02-autocert.yaml index 07f722bf..90948bd7 100644 --- a/autocert/install/02-autocert.yaml +++ b/autocert/install/02-autocert.yaml @@ -21,7 +21,7 @@ metadata: data: config.yaml: | logFormat: json # or text - restrictCertificatesToNamespace: true + restrictCertificatesToNamespace: false clusterDomain: cluster.local caUrl: https://ca.step.svc.cluster.local certLifetime: 24h From b4137053cf60fd480f7317657250905cab8324d4 Mon Sep 17 00:00:00 2001 From: Mike Maxey Date: Tue, 23 Apr 2019 11:57:30 -0700 Subject: [PATCH 02/15] Update GETTING_STARTED.md --- docs/GETTING_STARTED.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index e71d4c01..1c6b3dc4 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -384,7 +384,7 @@ types of certs. Each of these provisioners must have unique keys. ## Use Custom Claims for Provisioners to Control Certificate Validity etc -It's possible to configure provisioners on the CA to issue certs using propoerties specific to their target environments. Most commonly different validity periods and disabling renewals for certs. Here's how: +It's possible to configure provisioners on the CA to issue certs using properties specific to their target environments. Most commonly different validity periods and disabling renewals for certs. Here's how: ```bash $ step ca init From cbeca9383b6627aa42c3bdd6d34dc60d617d586b Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 24 Apr 2019 17:42:14 -0700 Subject: [PATCH 03/15] Update nosql integration * shutdown and reload database on SIGHUP --- Gopkg.lock | 88 ++++++++++++++++++++++++++++++++++++++++++++++++--- ca/ca.go | 3 ++ db/db.go | 20 +++++------- db/db_test.go | 50 ++++++++++++++--------------- 4 files changed, 120 insertions(+), 41 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 48214e8e..43b0e23c 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,14 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + digest = "1:6716c9fe6333591128e72848f246fc01dc72240e1e64185d8b4e124e7280b35d" + name = "github.com/AndreasBriese/bbloom" + packages = ["."] + pruneopts = "UT" + revision = "e2d15f34fcf99d5dbb871c820ec73f710fca9815" + [[projects]] digest = "1:304cb78c285eaf02ab529ad02a257cad9b4845022915e6c82f87860ac53222d8" name = "github.com/alecthomas/gometalinter" @@ -35,6 +43,29 @@ revision = "b90dc15cfd220ecf8bbc9043ecb928cef381f011" version = "v0.3.4" +[[projects]] + digest = "1:21ac9938fb1098b3a7b0dd909fb30878d33231177fac11a2821114eb9c1088ff" + name = "github.com/dgraph-io/badger" + packages = [ + ".", + "options", + "protos", + "skl", + "table", + "y", + ] + pruneopts = "UT" + revision = "391b6d3b93e6014fe8c2971fcc0c1266e47dbbd9" + version = "v1.5.3" + +[[projects]] + branch = "master" + digest = "1:6e8109ce247a59ab1eeb5330166c12735f6590de99c9647b6162d11518d32c9a" + name = "github.com/dgryski/go-farm" + packages = ["."] + pruneopts = "UT" + revision = "6a90982ecee230ff6cba02d5bd386acc030be9d3" + [[projects]] digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda" name = "github.com/ghodss/yaml" @@ -51,6 +82,14 @@ pruneopts = "UT" revision = "0ebf7795c516423a110473652e9ba3a59a504863" +[[projects]] + digest = "1:ec6f9bf5e274c833c911923c9193867f3f18788c461f76f05f62bb1510e0ae65" + name = "github.com/go-sql-driver/mysql" + packages = ["."] + pruneopts = "UT" + revision = "72cd26f257d44c1114970e19afddcd812016007e" + version = "v1.4.1" + [[projects]] digest = "1:b402bb9a24d108a9405a6f34675091b036c8b056aac843bf6ef2389a65c5cf48" name = "github.com/gogo/protobuf" @@ -174,6 +213,28 @@ revision = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c" version = "v0.0.4" +[[projects]] + branch = "master" + digest = "1:ae08d850ba158ea3ba4a7bb90f8372608172d8920644e5a6693b940a1f4e5d01" + name = "github.com/mmcloughlin/avo" + packages = [ + "attr", + "build", + "buildtags", + "gotypes", + "internal/prnt", + "internal/stack", + "ir", + "operand", + "pass", + "printer", + "reg", + "src", + "x86", + ] + pruneopts = "UT" + revision = "2e7d06bc7ada2979f17ccf8ebf486dba23b84fc7" + [[projects]] digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563" name = "github.com/modern-go/concurrent" @@ -302,11 +363,17 @@ [[projects]] branch = "master" - digest = "1:fd8d9eb07509d8ef47fc82c99646f0b2203b2ba3c240ba77d8c457bb6109836d" + digest = "1:f1f1df1e19d55a1ef1f0a63633191e7d2a99993c0a17f945c0b9ebd16b17871b" name = "github.com/smallstep/nosql" - packages = ["."] + packages = [ + ".", + "badger", + "bolt", + "database", + "mysql", + ] pruneopts = "UT" - revision = "d8f68d14f9ae04e0991dce06b44768f2d38dccf8" + revision = "5a355c598075a346d9ca9b50ec10e3f86ac66148" [[projects]] branch = "master" @@ -402,17 +469,30 @@ [[projects]] branch = "master" - digest = "1:384310e8a567edf6d5406d93318f9460c2d8db1a07ff5b6fece95b224343e7f1" + digest = "1:6b4a1c844969280f4d3e36ef4b0762e3522e701c015f688b68ef91c2ea6b5ac7" name = "golang.org/x/tools" packages = [ "go/ast/astutil", "go/gcexportdata", + "go/internal/cgo", "go/internal/gcimporter", + "go/packages", "go/types/typeutil", + "internal/fastwalk", + "internal/gopathwalk", + "internal/semver", ] pruneopts = "UT" revision = "3a10b9bf0a52df7e992a8c3eb712a86d3c896c75" +[[projects]] + digest = "1:c25289f43ac4a68d88b02245742347c94f1e108c534dda442188015ff80669b3" + name = "google.golang.org/appengine" + packages = ["cloudsql"] + pruneopts = "UT" + revision = "54a98f90d1c46b7731eb8fb305d2a321c30ef610" + version = "v1.5.0" + [[projects]] branch = "master" digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" diff --git a/ca/ca.go b/ca/ca.go index b8dfc39b..9cb6167a 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -131,6 +131,9 @@ func (ca *CA) Stop() error { // Reload reloads the configuration of the CA and calls to the server Reload // method. func (ca *CA) Reload() error { + if err := ca.auth.Shutdown(); err != nil { + return err + } if ca.opts.configFile == "" { return errors.New("error reloading ca: configuration file is not set") } diff --git a/db/db.go b/db/db.go index bbc43ce5..a0bd3a81 100644 --- a/db/db.go +++ b/db/db.go @@ -3,7 +3,6 @@ package db import ( "crypto/x509" "encoding/json" - "strings" "time" "github.com/pkg/errors" @@ -21,8 +20,10 @@ var ErrAlreadyExists = errors.New("already exists") // Config represents the JSON attributes used for configuring a step-ca DB. type Config struct { - Type string `json:"type"` - Path string `json:"path"` + Type string `json:"type"` + DataSource string `json:"dataSource"` + ValueDir string `json:"valueDir"` + Database string `json:"database"` } // AuthDB is an interface over an Authority DB client that implements a nosql.DB interface. @@ -44,15 +45,10 @@ func New(c *Config) (AuthDB, error) { return new(NoopDB), nil } - var db nosql.DB - switch strings.ToLower(c.Type) { - case "bbolt": - db = &nosql.BoltDB{} - if err := db.Open(c.Path); err != nil { - return nil, err - } - default: - return nil, errors.Errorf("unsupported db.type '%s'", c.Type) + db, err := nosql.New(c.Type, c.DataSource, nosql.WithDatabase(c.Database), + nosql.WithValueDir(c.ValueDir)) + if err != nil { + return nil, errors.Wrapf(err, "Error opening database of Type %s with source %s", c.Type, c.DataSource) } tables := [][]byte{revokedCertsTable, certsTable} diff --git a/db/db_test.go b/db/db_test.go index c05dbd78..bd3dab6a 100644 --- a/db/db_test.go +++ b/db/db_test.go @@ -5,24 +5,24 @@ import ( "testing" "github.com/smallstep/assert" - "github.com/smallstep/nosql" + "github.com/smallstep/nosql/database" ) -type MockNoSQLDB struct { +type MockdatabaseDB struct { err error ret1, ret2 interface{} get func(bucket, key []byte) ([]byte, error) set func(bucket, key, value []byte) error - open func(path string) error + open func(dataSourceName string, opt ...database.Option) error close func() error createTable func(bucket []byte) error deleteTable func(bucket []byte) error del func(bucket, key []byte) error - list func(bucket []byte) ([]*nosql.Entry, error) - update func(tx *nosql.Tx) error + list func(bucket []byte) ([]*database.Entry, error) + update func(tx *database.Tx) error } -func (m *MockNoSQLDB) Get(bucket, key []byte) ([]byte, error) { +func (m *MockdatabaseDB) Get(bucket, key []byte) ([]byte, error) { if m.get != nil { return m.get(bucket, key) } @@ -32,56 +32,56 @@ func (m *MockNoSQLDB) Get(bucket, key []byte) ([]byte, error) { return m.ret1.([]byte), m.err } -func (m *MockNoSQLDB) Set(bucket, key, value []byte) error { +func (m *MockdatabaseDB) Set(bucket, key, value []byte) error { if m.set != nil { return m.set(bucket, key, value) } return m.err } -func (m *MockNoSQLDB) Open(path string) error { +func (m *MockdatabaseDB) Open(dataSourceName string, opt ...database.Option) error { if m.open != nil { - return m.open(path) + return m.open(dataSourceName, opt...) } return m.err } -func (m *MockNoSQLDB) Close() error { +func (m *MockdatabaseDB) Close() error { if m.close != nil { return m.close() } return m.err } -func (m *MockNoSQLDB) CreateTable(bucket []byte) error { +func (m *MockdatabaseDB) CreateTable(bucket []byte) error { if m.createTable != nil { return m.createTable(bucket) } return m.err } -func (m *MockNoSQLDB) DeleteTable(bucket []byte) error { +func (m *MockdatabaseDB) DeleteTable(bucket []byte) error { if m.deleteTable != nil { return m.deleteTable(bucket) } return m.err } -func (m *MockNoSQLDB) Del(bucket, key []byte) error { +func (m *MockdatabaseDB) Del(bucket, key []byte) error { if m.del != nil { return m.del(bucket, key) } return m.err } -func (m *MockNoSQLDB) List(bucket []byte) ([]*nosql.Entry, error) { +func (m *MockdatabaseDB) List(bucket []byte) ([]*database.Entry, error) { if m.list != nil { return m.list(bucket) } - return m.ret1.([]*nosql.Entry), m.err + return m.ret1.([]*database.Entry), m.err } -func (m *MockNoSQLDB) Update(tx *nosql.Tx) error { +func (m *MockdatabaseDB) Update(tx *database.Tx) error { if m.update != nil { return m.update(tx) } @@ -100,16 +100,16 @@ func TestIsRevoked(t *testing.T) { }, "false/ErrNotFound": { key: "sn", - db: &DB{&MockNoSQLDB{err: nosql.ErrNotFound, ret1: nil}}, + db: &DB{&MockdatabaseDB{err: database.ErrNotFound, ret1: nil}}, }, "error/checking bucket": { key: "sn", - db: &DB{&MockNoSQLDB{err: errors.New("force"), ret1: nil}}, + db: &DB{&MockdatabaseDB{err: errors.New("force"), ret1: nil}}, err: errors.New("error checking revocation bucket: force"), }, "true": { key: "sn", - db: &DB{&MockNoSQLDB{ret1: []byte("value")}}, + db: &DB{&MockdatabaseDB{ret1: []byte("value")}}, isRevoked: true, }, } @@ -136,7 +136,7 @@ func TestRevoke(t *testing.T) { }{ "error/force isRevoked": { rci: &RevokedCertificateInfo{Serial: "sn"}, - db: &DB{&MockNoSQLDB{ + db: &DB{&MockdatabaseDB{ get: func(bucket []byte, sn []byte) ([]byte, error) { return nil, errors.New("force IsRevoked") }, @@ -145,7 +145,7 @@ func TestRevoke(t *testing.T) { }, "error/was already revoked": { rci: &RevokedCertificateInfo{Serial: "sn"}, - db: &DB{&MockNoSQLDB{ + db: &DB{&MockdatabaseDB{ get: func(bucket []byte, sn []byte) ([]byte, error) { return nil, nil }, @@ -154,9 +154,9 @@ func TestRevoke(t *testing.T) { }, "error/database set": { rci: &RevokedCertificateInfo{Serial: "sn"}, - db: &DB{&MockNoSQLDB{ + db: &DB{&MockdatabaseDB{ get: func(bucket []byte, sn []byte) ([]byte, error) { - return nil, nosql.ErrNotFound + return nil, database.ErrNotFound }, set: func(bucket []byte, key []byte, value []byte) error { return errors.New("force") @@ -166,9 +166,9 @@ func TestRevoke(t *testing.T) { }, "ok": { rci: &RevokedCertificateInfo{Serial: "sn"}, - db: &DB{&MockNoSQLDB{ + db: &DB{&MockdatabaseDB{ get: func(bucket []byte, sn []byte) ([]byte, error) { - return nil, nosql.ErrNotFound + return nil, database.ErrNotFound }, set: func(bucket []byte, key []byte, value []byte) error { return nil From c242602231869e86186086518239c167b28ad227 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 25 Apr 2019 12:37:25 -0700 Subject: [PATCH 04/15] reload and shutdown trickery * Only shutdown the database once. * Be careful when reloading the CA. Depending on whether the DB has already been shutdown, and error may be unrecoverable. --- Gopkg.lock | 1 + ca/ca.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- db/db.go | 10 +++++++--- db/db_test.go | 42 +++++++++++++++++++++--------------------- 4 files changed, 75 insertions(+), 29 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 43b0e23c..bd6c951b 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -671,6 +671,7 @@ "github.com/smallstep/cli/token/provision", "github.com/smallstep/cli/usage", "github.com/smallstep/nosql", + "github.com/smallstep/nosql/database", "github.com/tsenart/deadcode", "github.com/urfave/cli", "golang.org/x/crypto/ocsp", diff --git a/ca/ca.go b/ca/ca.go index 9cb6167a..5ec05981 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -3,6 +3,7 @@ package ca import ( "crypto/tls" "crypto/x509" + "log" "net/http" "github.com/go-chi/chi" @@ -123,7 +124,7 @@ func (ca *CA) Run() error { func (ca *CA) Stop() error { ca.renewer.Stop() if err := ca.auth.Shutdown(); err != nil { - return err + log.Printf("error stopping ca.Authority: %+v\n", err) } return ca.srv.Shutdown() } @@ -131,8 +132,9 @@ func (ca *CA) Stop() error { // Reload reloads the configuration of the CA and calls to the server Reload // method. func (ca *CA) Reload() error { - if err := ca.auth.Shutdown(); err != nil { - return err + var hasDB bool + if ca.config.DB != nil { + hasDB = true } if ca.opts.configFile == "" { return errors.New("error reloading ca: configuration file is not set") @@ -140,15 +142,54 @@ func (ca *CA) Reload() error { config, err := authority.LoadConfiguration(ca.opts.configFile) if err != nil { - return errors.Wrap(err, "error reloading ca") + return errors.Wrap(err, "error reloading ca configuration") } + logShutDown := func(ss ...string) { + for _, s := range ss { + log.Println(s) + } + log.Println("Continuing to serve requests may result in inconsistent state. Shutting Down ...") + } + logContinue := func(reason string) { + log.Println(reason) + log.Println("Continuing to run with the original configuration.") + log.Println("You can force a restart by sending a SIGTERM signal and then restarting the step-ca.") + } + + // Shut down the old authority (shut down the database). If New or Reload + // fails then the CA will continue to run but the database will have been + // shutdown, which will cause errors. + if err := ca.auth.Shutdown(); err != nil { + if hasDB { + logShutDown("Attempt to shut down the ca.Authority has failed.") + return ca.Stop() + } + logContinue("Reload failed because the ca.Authority could not be shut down.") + return err + } newCA, err := New(config, WithPassword(ca.opts.password), WithConfigFile(ca.opts.configFile)) if err != nil { + if hasDB { + logShutDown("Attempt to initialize a CA with the new configuration has failed.", + "The database has already been shutdown.") + return ca.Stop() + } + logContinue("Reload failed because the CA with new configuration could " + + "not be initialized.") return errors.Wrap(err, "error reloading ca") } - return ca.srv.Reload(newCA.srv) + if err = ca.srv.Reload(newCA.srv); err != nil { + if hasDB { + logShutDown("Attempt to replace the old CA server has failed.", + "The database has already been shutdown.") + return ca.Stop() + } + logContinue("Reload failed because server could not be replaced.") + return errors.Wrap(err, "error reloading server") + } + return nil } // getTLSConfig returns a TLSConfig for the CA server with a self-renewing diff --git a/db/db.go b/db/db.go index a0bd3a81..e2d044bd 100644 --- a/db/db.go +++ b/db/db.go @@ -37,6 +37,7 @@ type AuthDB interface { // DB is a wrapper over the nosql.DB interface. type DB struct { nosql.DB + isUp bool } // New returns a new database client that implements the AuthDB interface. @@ -59,7 +60,7 @@ func New(c *Config) (AuthDB, error) { } } - return &DB{db}, nil + return &DB{db, true}, nil } // RevokedCertificateInfo contains information regarding the certificate @@ -127,8 +128,11 @@ func (db *DB) StoreCertificate(crt *x509.Certificate) error { // Shutdown sends a shutdown message to the database. func (db *DB) Shutdown() error { - if err := db.Close(); err != nil { - return errors.Wrap(err, "database shutdown error") + if db.isUp { + if err := db.Close(); err != nil { + return errors.Wrap(err, "database shutdown error") + } + db.isUp = false } return nil } diff --git a/db/db_test.go b/db/db_test.go index bd3dab6a..c2b16d57 100644 --- a/db/db_test.go +++ b/db/db_test.go @@ -8,7 +8,7 @@ import ( "github.com/smallstep/nosql/database" ) -type MockdatabaseDB struct { +type MockNoSQLDB struct { err error ret1, ret2 interface{} get func(bucket, key []byte) ([]byte, error) @@ -22,7 +22,7 @@ type MockdatabaseDB struct { update func(tx *database.Tx) error } -func (m *MockdatabaseDB) Get(bucket, key []byte) ([]byte, error) { +func (m *MockNoSQLDB) Get(bucket, key []byte) ([]byte, error) { if m.get != nil { return m.get(bucket, key) } @@ -32,56 +32,56 @@ func (m *MockdatabaseDB) Get(bucket, key []byte) ([]byte, error) { return m.ret1.([]byte), m.err } -func (m *MockdatabaseDB) Set(bucket, key, value []byte) error { +func (m *MockNoSQLDB) Set(bucket, key, value []byte) error { if m.set != nil { return m.set(bucket, key, value) } return m.err } -func (m *MockdatabaseDB) Open(dataSourceName string, opt ...database.Option) error { +func (m *MockNoSQLDB) Open(dataSourceName string, opt ...database.Option) error { if m.open != nil { return m.open(dataSourceName, opt...) } return m.err } -func (m *MockdatabaseDB) Close() error { +func (m *MockNoSQLDB) Close() error { if m.close != nil { return m.close() } return m.err } -func (m *MockdatabaseDB) CreateTable(bucket []byte) error { +func (m *MockNoSQLDB) CreateTable(bucket []byte) error { if m.createTable != nil { return m.createTable(bucket) } return m.err } -func (m *MockdatabaseDB) DeleteTable(bucket []byte) error { +func (m *MockNoSQLDB) DeleteTable(bucket []byte) error { if m.deleteTable != nil { return m.deleteTable(bucket) } return m.err } -func (m *MockdatabaseDB) Del(bucket, key []byte) error { +func (m *MockNoSQLDB) Del(bucket, key []byte) error { if m.del != nil { return m.del(bucket, key) } return m.err } -func (m *MockdatabaseDB) List(bucket []byte) ([]*database.Entry, error) { +func (m *MockNoSQLDB) List(bucket []byte) ([]*database.Entry, error) { if m.list != nil { return m.list(bucket) } return m.ret1.([]*database.Entry), m.err } -func (m *MockdatabaseDB) Update(tx *database.Tx) error { +func (m *MockNoSQLDB) Update(tx *database.Tx) error { if m.update != nil { return m.update(tx) } @@ -100,16 +100,16 @@ func TestIsRevoked(t *testing.T) { }, "false/ErrNotFound": { key: "sn", - db: &DB{&MockdatabaseDB{err: database.ErrNotFound, ret1: nil}}, + db: &DB{&MockNoSQLDB{err: database.ErrNotFound, ret1: nil}, true}, }, "error/checking bucket": { key: "sn", - db: &DB{&MockdatabaseDB{err: errors.New("force"), ret1: nil}}, + db: &DB{&MockNoSQLDB{err: errors.New("force"), ret1: nil}, true}, err: errors.New("error checking revocation bucket: force"), }, "true": { key: "sn", - db: &DB{&MockdatabaseDB{ret1: []byte("value")}}, + db: &DB{&MockNoSQLDB{ret1: []byte("value")}, true}, isRevoked: true, }, } @@ -136,44 +136,44 @@ func TestRevoke(t *testing.T) { }{ "error/force isRevoked": { rci: &RevokedCertificateInfo{Serial: "sn"}, - db: &DB{&MockdatabaseDB{ + db: &DB{&MockNoSQLDB{ get: func(bucket []byte, sn []byte) ([]byte, error) { return nil, errors.New("force IsRevoked") }, - }}, + }, true}, err: errors.New("error checking revocation bucket: force IsRevoked"), }, "error/was already revoked": { rci: &RevokedCertificateInfo{Serial: "sn"}, - db: &DB{&MockdatabaseDB{ + db: &DB{&MockNoSQLDB{ get: func(bucket []byte, sn []byte) ([]byte, error) { return nil, nil }, - }}, + }, true}, err: ErrAlreadyExists, }, "error/database set": { rci: &RevokedCertificateInfo{Serial: "sn"}, - db: &DB{&MockdatabaseDB{ + db: &DB{&MockNoSQLDB{ get: func(bucket []byte, sn []byte) ([]byte, error) { return nil, database.ErrNotFound }, set: func(bucket []byte, key []byte, value []byte) error { return errors.New("force") }, - }}, + }, true}, err: errors.New("database Set error: force"), }, "ok": { rci: &RevokedCertificateInfo{Serial: "sn"}, - db: &DB{&MockdatabaseDB{ + db: &DB{&MockNoSQLDB{ get: func(bucket []byte, sn []byte) ([]byte, error) { return nil, database.ErrNotFound }, set: func(bucket []byte, key []byte, value []byte) error { return nil }, - }}, + }, true}, }, } for name, tc := range tests { From c8fe1ad86db32c48240da0592cadf65feedd63d7 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 25 Apr 2019 18:27:11 -0700 Subject: [PATCH 05/15] Add database documentation --- docs/GETTING_STARTED.md | 16 ++++++- docs/database.md | 95 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 docs/database.md diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index 1c6b3dc4..44ced622 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -102,9 +102,23 @@ and respond to requests. * `dnsNames`: comma separated list of DNS Name(s) for the CA. -* `logger`: the default logging format for the CA is `text`. The other options +* `logger`: the default logging format for the CA is `text`. The other option is `json`. +* `db`: data persistence layer. See [database documentation](./db.md) for more +info. + + - type: `badger`, `bbolt`, `mysql`, etc. + + - dataSource: `string` that can be interpreted differently depending on the + type of the database. Usually a path to where the data is stored. See + the [database configuration docs](./db.md#configuration) for more info. + + - database: name of the database. Used for backends that may have + multiple databases. e.g. MySQL + + - valueDir: directory to store the value log in (Badger specific). + * `tls`: settings for negotiating communication with the CA; includes acceptable ciphersuites, min/max TLS version, etc. diff --git a/docs/database.md b/docs/database.md new file mode 100644 index 00000000..9a253667 --- /dev/null +++ b/docs/database.md @@ -0,0 +1,95 @@ +# Step Certificates Database + +`step certificates` uses a simple key-value interface over popular database +implementations to store persistent certificate management meta-data. + +Our recommended default database implementation is +[nosql-Badger](https://github.com/smallstep/nosql/badger) - a NoSQL interface +over the popular [Badger](https://github.com/dgraph-io/badger) database. + +## What will the database store? + +As a first pass, the database layer will store every certificate (along with +metadata surrounding the provisioning of the certificate) and revocation data +that will be used to enforce passive revocation. + +## Implementations + +Current implementations include Badger (default), BoltDB, and MysQL. + +- [ ] Memory +- [x] [BoltDB](https://github.com/etcd-io/bbolt) -- etcd fork. +- [x] [Badger](https://github.com/dgraph-io/badger) +- [x] [MariaDB/MySQL](https://github.com/go-sql-driver/mysql) +- [ ] PostgreSQL +- [ ] Cassandra +- [ ] ... + +Let us know which integration you would like to see next by opening an issue or PR. + +## Configuration + +Configuring `step certificates` to use a database is as simple as adding a +top-level `db` stanza to your `step-ca.config` (see getting started doc for +more info). Below are a few examples for supported databases: + +### Badger + +``` +{ + ... + "crt": ".step/certs/intermediate_ca.crt", + "key": ".step/secrets/intermediate_ca_key", + "db": { + "type": "badger", + "dataSource": "./stepdb", + "valueDir": "./steplogdb" # leave empty if equivalent to dataSource + }, + ... +}, +``` + +### BoltDB + +``` +{ + ... + "crt": ".step/certs/intermediate_ca.crt", + "key": ".step/secrets/intermediate_ca_key", + "db": { + "type": "bbolt", + "dataSource": "./stepdb" + }, + ... +}, +``` + +### MySQL + +``` +{ + ... + "crt": ".step/certs/intermediate_ca.crt", + "key": ".step/secrets/intermediate_ca_key", + "db": { + "type": "mysql", + "dataSource": "user:password@tcp(127.0.0.1:3306)/", + "database": "myDatabaseName" + }, + ... +}, +``` + +## Schema + +As the interface is a key-value store, the schema is very simple. We support +`tables`, `keys`, and `values`. An entry in the database is a `[]byte value` +that is indexed by `[]byte table` and `[]byte key`. + +## Data Backup + +Backing up your data is important, and it's good hygiene. We chose +[Badger](https://github.com/dgraph-io/badger) as our default file based data +storage backend because it has mature tooling for running common database +tasks. See the [documentation](https://github.com/dgraph-io/badger#database-backup) +for a guide on backing up your data. From 46c7592f34eefcb85612d66e7456eb6af791f3c9 Mon Sep 17 00:00:00 2001 From: max furman Date: Fri, 26 Apr 2019 13:08:14 -0700 Subject: [PATCH 06/15] db: Omit empty optional fields from JSON --- db/db.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/db.go b/db/db.go index e2d044bd..886c3ef7 100644 --- a/db/db.go +++ b/db/db.go @@ -22,8 +22,8 @@ var ErrAlreadyExists = errors.New("already exists") type Config struct { Type string `json:"type"` DataSource string `json:"dataSource"` - ValueDir string `json:"valueDir"` - Database string `json:"database"` + ValueDir string `json:"valueDir,omitempty"` + Database string `json:"database,omitempty"` } // AuthDB is an interface over an Authority DB client that implements a nosql.DB interface. From e4de7f07e82118b3f926716666b620db058fa9f7 Mon Sep 17 00:00:00 2001 From: max furman Date: Sat, 27 Apr 2019 13:24:53 -0700 Subject: [PATCH 07/15] docs: Add revocation document --- docs/revocation.md | 201 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 docs/revocation.md diff --git a/docs/revocation.md b/docs/revocation.md new file mode 100644 index 00000000..fc04ae0b --- /dev/null +++ b/docs/revocation.md @@ -0,0 +1,201 @@ +# Revocation + +**Active Revocation**: A certificate is no longer valid from the moment it has +been actively revoked. Clients are required to check verify certificate validity +against CRLs (Certificate Revocation Lists) or use OCSP (Online Certificate +Status Protocol). Active Revocation requires clients to take an active role +in certificate validation for the benefit of real time revocation. + +**Passive Revocation**: A certificate that has been passively revoked can no +longer be renewed. It will still be valid for the remainder of it's validity period, +but cannot be prolonged. The benefit of passive revocation is that clients +can remain simple and decentralized. Passive revocation works best with short +certificate lifetimes. + +`step certificates` currently only supports passive revocation. Active revocation +is on our roadmap. + +## How It Works + +Certificates can be created and revoked through the `step cli`. Let's walk +through some examples. + +### Requirements + +* `step` v0.10.0 ([install instructions](../README.md#installation-guide)) + +### How It Works + +1. Bootstrap your PKI. + + If you've already done this before and you have a `$STEPPATH` with certs, + secrets, and configuration files then you can move on to 1.ii. + + 1. Run `step ca init`. + +

+      $ step ca init --name "Local CA" --provisioner admin --dns localhost --address ":443"
+      
+ + Move on to step 2. + + 2. Configure a persistence layer in your `ca.json`. + + > If you did step 1.i with `step` v0.10.0 or greater then your db will + > have been configured in the previous step. + + Get your full step path by running `echo $(step path)`. Now edit + your `ca.json` by adding the following stanza as a top-level attribute: + > Your `ca.json` should be in `$(step path)/config/ca.json`. + + ``` + ... + "db": { + "type": "badger", + "dataSource": "/db" + }, + ... + ``` + + Check out our [database documentation](./database.md) to see all available + database backends and adapters. + +2. Run the CA + +

+   $ step-ca $(step path)/config/ca.json)
+   
+ +3. Create a certificate for localhost + +

+   $ step ca certificate localhost localhost.crt localhost.key
+   ✔ Key ID: n2kqNhicCCqVxJidspCQrjXWBtGwsa9zk3eBObrViy8 (sebastian@smallstep.com)
+   ✔ Please enter the password to decrypt the provisioner key:
+   ✔ CA: https://ca.smallstep.com
+   ✔ Certificate: localhost.crt
+   ✔ Private Key: localhost.key
+
+   $ step certificate inspect --short localhost.crt
+   X.509v3 TLS Certificate (ECDSA P-256) [Serial: 2400...2409]
+     Subject:     localhost
+     Issuer:      Smallstep Intermediate CA
+     Provisioner: sebastian@smallstep.com [ID: n2kq...Viy8]
+     Valid from:  2019-04-23T22:55:54Z
+             to:  2019-04-24T22:55:54Z
+   
+ +4. Renew the certificate (just to prove we can!) + +

+   $ step ca renew localhost.crt localhost.key
+   ✔ Would you like to overwrite localhost.crt [y/n]: y
+   Your certificate has been saved in localhost.crt.
+
+   # Make sure the from timestamp is "newer"
+   $ step certificate inspect --short localhost.crt
+   X.509v3 TLS Certificate (ECDSA P-256) [Serial: 5963...8406]
+     Subject:     localhost
+     Issuer:      Smallstep Intermediate CA
+     Provisioner: sebastian@smallstep.com [ID: n2kq...Viy8]
+     Valid from:  2019-04-23T22:57:50Z
+             to:  2019-04-24T22:57:50Z
+   
+ +5. Now let's revoke the certificate + +

+   $ step certificate inspect --format=json localhost.crt | jq .serial_number
+   "59636004850364466675608080466579278406"
+   # the serial number is unique
+
+   $ step ca revoke 59636004850364466675608080466579278406
+   ✔ Key ID: n2kqNhicCCqVxJidspCQrjXWBtGwsa9zk3eBObrViy8 (sebastian@smallstep.com)
+   ✔ Please enter the password to decrypt the provisioner key:
+   ✔ CA: https://ca.smallstep.com
+   Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
+   
+ +6. Ok cool! But did it work? + +

+   $ step ca renew localhost.crt localhost.key
+   error renewing certificate: Unauthorized
+
+   # log trace from CA:
+   [...]
+   WARN[0569] duration="82.782µs" duration-ns=82782
+     error="renew: certificate has been revoked"
+     fields.time="2019-04-23T16:03:01-07:00" method=POST
+     name=ca path=/renew protocol=HTTP/1.1 referer=
+     remote-address=127.0.0.1 request-id=bivpj9a3q563rpjheh5g
+     size=40 status=401 user-agent=Go-http-client/1.1 user-id=
+   [...]
+   
+ +7. Other ways to revoke a Certificate + + Use the original certificate and key and authorize the revoke request using + mTLS (doesn't require a provisioner). + +

+   $ step ca revoke --cert localhost.crt --key localhost.key
+   Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
+   
+ + Or, revoke a certificate in two steps by first creating a revocation token and + then exchanging that token in a revocation request. + +

+   $ TOKEN=$(step ca token --revoke 59636004850364466675608080466579278406)
+   ✔ Key ID: n2kqNhicCCqVxJidspCQrjXWBtGwsa9zk3eBObrViy8 (sebastian@smallstep.com)
+   ✔ Please enter the password to decrypt the provisioner key:
+
+   $ echo $TOKEN | step crypto jwt inspect --insecure
+   {
+     "header": {
+       "alg": "ES256",
+       "kid": "uxEunU9UhUo96lRvKgpEtRevkzbN5Yq88AFFtb1nSGg",
+       "typ": "JWT"
+     },
+     "payload": {
+       "aud": "https://localhost:443/1.0/revoke",
+       "exp": 1556395590,
+       "iat": 1556395290,
+       "iss": "sebastian@smallstep.com",
+       "jti": "1f222fc1a22530b7bcd2a40d7308c566c8e49f90413bc350e07bfabc8002b79b",
+       "nbf": 1556395290,
+       "sha": "fef4c75a050e1f3a31175ca4f4fdb711cbef1efcd374fcae4700596604eb8e5a",
+       "sub": "59636004850364466675608080466579278406"
+     },
+     "signature": "M1wX0ea3VXwS5rIim0TgtcCXHDtvP1GWD15cJSvVkrHNO6XMYl6m3ZmnWdwMi976msv-n2GTG3h6dJ3j2ImdfQ"
+   }
+
+   $ step ca revoke --token $TOKEN 59636004850364466675608080466579278406
+   Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
+   
+ + Or, revoke a certificate in offline mode: + +

+   $ step ca revoke --offline 59636004850364466675608080466579278406
+   Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
+
+   $ step ca revoke --offline --cert localhost.crt --key localhost.key
+   Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
+   
+ + > NOTE: you can only revoke a certificate once. Any repeated attempts to revoke + > the same serial number will fail. + +## Now What? + +[Use TLS Everywhere](https://smallstep.com/blog/use-tls.html) and let us know +what you think of our tools. Hit us on [twitter](twitter.com/smallsteplabs) or +get in touch through our [Gitter](https://gitter.im/smallstep/community) +to chat with us in real time. + +## Further Reading + +* [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html) +* [Everything you should know about certificates and PKI but are too afraid to ask](https://smallstep.com/blog/everything-pki.html) From a27c2dea7d46981d4694eeef53bd3d1cb952496d Mon Sep 17 00:00:00 2001 From: max furman Date: Mon, 29 Apr 2019 11:21:40 -0700 Subject: [PATCH 08/15] docs: update revocation doc --- docs/revocation.md | 107 +++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/docs/revocation.md b/docs/revocation.md index fc04ae0b..ace4893a 100644 --- a/docs/revocation.md +++ b/docs/revocation.md @@ -1,15 +1,18 @@ # Revocation **Active Revocation**: A certificate is no longer valid from the moment it has -been actively revoked. Clients are required to check verify certificate validity -against CRLs (Certificate Revocation Lists) or use OCSP (Online Certificate -Status Protocol). Active Revocation requires clients to take an active role -in certificate validation for the benefit of real time revocation. +been actively revoked. Clients are required to check against centralized +sources of certificate validity information (e.g. by using CRLs (Certificate +Revocation Lists) or OCSP (Online Certificate Status Protocol)) to +verify that certificates have not been revoked. Active Revocation requires +clients to take an active role in certificate validation for the benefit of +real time revocation. **Passive Revocation**: A certificate that has been passively revoked can no longer be renewed. It will still be valid for the remainder of it's validity period, but cannot be prolonged. The benefit of passive revocation is that clients -can remain simple and decentralized. Passive revocation works best with short +can verify certificates in a simple, decentralized manner without relying on +centralized 3rd parties. Passive revocation works best with short certificate lifetimes. `step certificates` currently only supports passive revocation. Active revocation @@ -18,55 +21,55 @@ is on our roadmap. ## How It Works Certificates can be created and revoked through the `step cli`. Let's walk -through some examples. +through an example. ### Requirements -* `step` v0.10.0 ([install instructions](../README.md#installation-guide)) +* `step` (>=v0.10.0) ([install instructions](../README.md#installation-guide)) -### How It Works +### Let's Get To It 1. Bootstrap your PKI. - If you've already done this before and you have a `$STEPPATH` with certs, - secrets, and configuration files then you can move on to 1.ii. + > If you've already done this before and you have a `$STEPPATH` with certs, + > secrets, and configuration files then you can move on to step 2. - 1. Run `step ca init`. - -

-      $ step ca init --name "Local CA" --provisioner admin --dns localhost --address ":443"
-      
- - Move on to step 2. - - 2. Configure a persistence layer in your `ca.json`. - - > If you did step 1.i with `step` v0.10.0 or greater then your db will - > have been configured in the previous step. - - Get your full step path by running `echo $(step path)`. Now edit - your `ca.json` by adding the following stanza as a top-level attribute: - > Your `ca.json` should be in `$(step path)/config/ca.json`. - - ``` - ... - "db": { - "type": "badger", - "dataSource": "/db" - }, - ... - ``` - - Check out our [database documentation](./database.md) to see all available - database backends and adapters. - -2. Run the CA + Run `step ca init`.

-   $ step-ca $(step path)/config/ca.json)
+   $ step ca init --name "Local CA" --provisioner admin --dns localhost --address ":443"
    
-3. Create a certificate for localhost + Move on to step 3. + +2. Configure a persistence layer in your `ca.json`. + + > If you did step 1 with `step` v0.10.0 or greater then your db will + > have been configured in the previous step. + + Get your full step path by running `echo $(step path)`. Now edit + your `ca.json` by adding the following stanza as a top-level attribute: + > Your `ca.json` should be in `$(step path)/config/ca.json`. + + ``` + ... + "db": { + "type": "badger", + "dataSource": "/db" + }, + ... + ``` + + Check out our [database documentation](./database.md) to see all available + database backends and adapters. + +3. Run the CA + +

+   $ step-ca $(step path)/config/ca.json
+   
+ +4. Create a certificate for localhost

    $ step ca certificate localhost localhost.crt localhost.key
@@ -85,7 +88,7 @@ through some examples.
              to:  2019-04-24T22:55:54Z
    
-4. Renew the certificate (just to prove we can!) +5. Renew the certificate (just to prove we can!)

    $ step ca renew localhost.crt localhost.key
@@ -102,7 +105,7 @@ through some examples.
              to:  2019-04-24T22:57:50Z
    
-5. Now let's revoke the certificate +6. Now let's revoke the certificate

    $ step certificate inspect --format=json localhost.crt | jq .serial_number
@@ -116,7 +119,7 @@ through some examples.
    Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
    
-6. Ok cool! But did it work? +7. Awesome! But did it work?

    $ step ca renew localhost.crt localhost.key
@@ -133,10 +136,10 @@ through some examples.
    [...]
    
-7. Other ways to revoke a Certificate +8. Other ways to revoke a Certificate - Use the original certificate and key and authorize the revoke request using - mTLS (doesn't require a provisioner). + Use the certificate and key. This method does not require a provisioner + because it uses the certificate and key to authenticate the request.

    $ step ca revoke --cert localhost.crt --key localhost.key
@@ -188,12 +191,12 @@ through some examples.
    > NOTE: you can only revoke a certificate once. Any repeated attempts to revoke
    > the same serial number will fail.
 
-## Now What?
+## What's next?
 
 [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html) and let us know
-what you think of our tools. Hit us on [twitter](twitter.com/smallsteplabs) or
-get in touch through our [Gitter](https://gitter.im/smallstep/community)
-to chat with us in real time.
+what you think of our tools. Get in touch over
+[twitter](twitter.com/smallsteplabs) or through our
+[Gitter](https://gitter.im/smallstep/community) to chat with us in real time.
 
 ## Further Reading
 

From 2b96e7a94cac330efc906f57245250c77b2aba7c Mon Sep 17 00:00:00 2001
From: max furman 
Date: Mon, 29 Apr 2019 13:41:21 -0700
Subject: [PATCH 09/15] docs: revoke page

---
 docs/revocation.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/docs/revocation.md b/docs/revocation.md
index ace4893a..7402d3d1 100644
--- a/docs/revocation.md
+++ b/docs/revocation.md
@@ -18,6 +18,9 @@ certificate lifetimes.
 `step certificates` currently only supports passive revocation. Active revocation
 is on our roadmap.
 
+Run `step help ca revoke` from the command line for full documentation, list of
+command line flags, and examples.
+
 ## How It Works
 
 Certificates can be created and revoked through the `step cli`. Let's walk
@@ -191,6 +194,9 @@ through an example.
    > NOTE: you can only revoke a certificate once. Any repeated attempts to revoke
    > the same serial number will fail.
 
+   Run `step help ca revoke` from the command line for full documentation, list of
+   command line flags, and examples.
+
 ## What's next?
 
 [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html) and let us know

From 8ab04bd5037a856786db826f676f4f1d0444b188 Mon Sep 17 00:00:00 2001
From: max furman 
Date: Mon, 29 Apr 2019 17:50:30 -0700
Subject: [PATCH 10/15] docs sub repo update

---
 README.md                                     |  14 +-
 docs/GETTING_STARTED.md                       |   6 +-
 docs/README.md                                |  40 +++
 docs/defaults.md                              | 228 ++++++++++++++++++
 docs/distribution.md                          | 116 ---------
 .../images}/connect-with-mtls-2.png           | Bin
 docs/{ => images}/oidc1.png                   | Bin
 docs/{ => images}/oidc2.png                   | Bin
 docs/{ => images}/oidc3.png                   | Bin
 {images => docs/images}/step-ca-2-legged.gif  | Bin
 {images => docs/images}/step-ca-3-legged.gif  | Bin
 docs/{common-questions.md => questions.md}    |  35 +--
 docs/recommendations.md                       | 207 ----------------
 docs/revocation.md                            |   2 +-
 14 files changed, 301 insertions(+), 347 deletions(-)
 create mode 100644 docs/README.md
 create mode 100644 docs/defaults.md
 delete mode 100644 docs/distribution.md
 rename {images => docs/images}/connect-with-mtls-2.png (100%)
 rename docs/{ => images}/oidc1.png (100%)
 rename docs/{ => images}/oidc2.png (100%)
 rename docs/{ => images}/oidc3.png (100%)
 rename {images => docs/images}/step-ca-2-legged.gif (100%)
 rename {images => docs/images}/step-ca-3-legged.gif (100%)
 rename docs/{common-questions.md => questions.md} (86%)
 delete mode 100644 docs/recommendations.md

diff --git a/README.md b/README.md
index 754069d5..ec11c411 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 An online certificate authority and related tools for secure automated certificate management, so you can use TLS everywhere.
 
 [Website](https://smallstep.com) |
-[Documentation](https://smallstep.com/docs/certificates) |
+[Documentation](#documentation) |
 [Installation Guide](#installation-guide) |
 [Getting Started](./docs/GETTING_STARTED.md) |
 [Contribution Guide](./docs/CONTRIBUTING.md)
@@ -321,13 +321,17 @@ and best practices on running Step CA in production.
 
 ## Documentation
 
-Documentation can be found in three places:
+Documentation can be found in a handful of different places:
 
-1. On the command line with `step ca help xxx` where `xxx` is the subcommand you are interested in. Ex: `step help ca provisioners list`
+1. The [docs](./docs) sub-repo has an index of documentation and tutorials.
 
-2. On the web at https://smallstep.com/docs/certificates
+2. On the command line with `step ca help xxx` where `xxx` is the subcommand
+you are interested in. Ex: `step help ca provisioners list`.
 
-3. On your browser by running `step ca help --http :8080` and visiting http://localhost:8080
+3. On the web at https://smallstep.com/docs/certificates.
+
+4. On your browser by running `step ca help --http :8080` from the command line
+and visiting http://localhost:8080.
 
 ## The Future
 
diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md
index 44ced622..a5323832 100644
--- a/docs/GETTING_STARTED.md
+++ b/docs/GETTING_STARTED.md
@@ -479,7 +479,7 @@ one we'll use in this example, is G-Suite.
 Navigate to the Google APIs developer console and pick a suitable project from the
 top navbar's dropdown.
 
-![Google Dev Console](oidc1.png)
+![Google Dev Console](./images/oidc1.png)
 
 In the masthead navigation click **Credentials** (key symbol) and then "OAuth
 consent screen" from the subnav. Fill out naming details, all mandatory fields,
@@ -492,7 +492,7 @@ Move back to **Credentials** on the subnav and choose "OAuth client ID" from the
 **Create credentials** dropdown. Since OIDC will be used from the `step CLI` pick **Other**
 from the available options and pick a name (e.g. **Step CLI**).
 
-![Create credential](oidc2.png)
+![Create credential](./images/oidc2.png)
 
 On successful completion, a confirmation modal with both `clientID` and
 `clientSecret` will be presented. Please note that the `clientSecret` will
@@ -500,7 +500,7 @@ allow applications access to the configured OAuth consent screen. However, it
 will not allow direct authentication of users without their own MfA credentials
 per account.
 
-![OIDC credentials](oidc3.png)
+![OIDC credentials](./images/oidc3.png)
 
 Now using `clientID` and `clientSecret` run the following command to add
 G-Suite as a provisioner to `step certificates`. Please see [`step ca
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..06968809
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,40 @@
+# Step Certificates Documentation
+
+Index of Documentation and Tutorials for using and deploying the `step certificates`.
+
+[![GitHub release](https://img.shields.io/github/release/smallstep/certificates.svg)](https://github.com/smallstep/certificates/releases)
+[![Join the chat at https://gitter.im/smallstep/community](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/smallstep/community)
+[![CA Image](https://images.microbadger.com/badges/image/smallstep/step-ca.svg)](https://microbadger.com/images/smallstep/step-ca)
+[![Go Report Card](https://goreportcard.com/badge/github.com/smallstep/certificates)](https://goreportcard.com/report/github.com/smallstep/certificates)
+[![Build Status](https://travis-ci.com/smallstep/certificates.svg?branch=master)](https://travis-ci.com/smallstep/certificates)
+[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
+[![CLA assistant](https://cla-assistant.io/readme/badge/smallstep/certificates)](https://cla-assistant.io/smallstep/certificates)
+
+[![GitHub stars](https://img.shields.io/github/stars/smallstep/certificates.svg?style=social)](https://github.com/smallstep/certificates/stargazers)
+[![Twitter followers](https://img.shields.io/twitter/follow/smallsteplabs.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=smallsteplabs)
+
+## Index
+
+* **General Info**
+    * [Website](https://smallstep.com)
+    * [Installation Guide](../README.md#installation-guide)
+    * [Getting Started](./GETTING_STARTED.md): in depth guide on getting started
+      with `step certificates`, including all configuration options.
+    * [Contribution Guide](./CONTRIBUTING.md)
+    * [Sane Defaults](./defaults.md): default algorithms and attributes used
+      in cryptographic primitives and why they were selected.
+    * [Frequently Asked Questions](./questions.md)
+    * Check out our [Blog](https://smallstep.com/blog/). We post quality
+      educational content as well as periodic updates on new releases.
+* **API**: Guides to using the API via the `step` CLI.
+    * [Revoking Certificates](./revocation.md)
+    * [Persistence Layer](./database.md): description and guide to using `step certificates`'
+      persistence layer for storing certificate management metadata.
+* **Tutorials**: Guides for deploying and getting started with `step` in various environments.
+    * [Docker](./docker.md)
+    * [Kubernetes](../autocert/README.md)
+
+## Further Reading
+
+* [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html)
+* [Everything you should know about certificates and PKI but are too afraid to ask](https://smallstep.com/blog/everything-pki.html)
diff --git a/docs/defaults.md b/docs/defaults.md
new file mode 100644
index 00000000..6c775413
--- /dev/null
+++ b/docs/defaults.md
@@ -0,0 +1,228 @@
+# Default Algorithms and Attributes for Tokens, Keys, Certificates, etc.
+
+The `step` ecosystem aims to be a "easy to use and hard to misuse" suite of PKI
+tools. This means we need to select sane defaults for the myriad
+configuration options that exist when using cryptographic primitives and higher
+order abstractions (e.g. JWTs).
+
+Below we document significant configuration options that we have selected as
+defaults. These selections will change and evolve over time; security and
+cryptography are constantly changing in response to real world pressures. We
+intend for this document be an accurate representation of current best practices
+in the industry, and to have these practices codified as defaults in the `step
+certificates` code base. If you have questions, suggestions, or comments about
+any of these decisions please let us know by opening an issue on this repo,
+reaching out through [Twitter](twitter.com/smallsteplabs), or through our
+[Gitter](https://gitter.im/smallstep/community) to chat with us in real time.
+
+## Tokens
+
+We use JWTs (JSON Web Tokens) to prove authenticity and identity within the
+Step ecosystem. JWTs have received negative attention because they are easy to
+misuse and misconfigure. We agree! But lots of things are easy to misuse. We also
+believe that when configured well JWTs are a great way to sign and encode data.
+Our JWT's are, by default, short-lived (5 minute lifespan) and one time use
+during the lifetime of the Step CA. We use a 1 minute clock drift leeway
+because that was the recommended default in the reputable JWT package that we
+chose. If using Step JWTs or your own JWTs in your code be sure to verify and
+validate every single standard attribute of the JWT. JWTs, like all
+cryptographic tools, are useless without proper attention to configuration and
+guidelines.
+
+## Keys
+
+RSA keys don't scale very well. To get 128 bits of security, you need 3,072-bit
+RSA keys, which are noticeably slower. ECDSA keys provide an alternative
+that offers better security and better performance. At 256 bits, ECDSA keys
+provide 128 bits of security. A small number of older clients don't support
+ECDSA, but most modern clients do.
+
+**Default Key Type**: ECDSA
+
+**Default Curve Bits**: P-256
+
+We've chosen the AES encryption algorithm (aka Rijndael) for writing private
+keys to disk because it was the official choice of the Advanced
+Encryption Standard contest. The three supported key sizes are 128, 192, and
+256. Each of these is considered to be unbreakable for the forseeable future,
+therefore we chose 128 bits as our default because the performance is
+better (as compared to the greater key sizes) and because we agree, with
+the designers of the algorithm, that 128 bits are quite sufficient for
+most security needs.
+
+**Default PEMCipher**: AES128
+
+## X.509 Certificate Defaults
+
+### Root Certificate
+
+* Validity (10 year window)
+  * **Not Before**: Now
+
+  * **Not After**: Now + 10 years
+
+    A 10 year window seems advisable until software and tools can be written
+    for rotating the root certificate.
+
+* **Basic Constraints**
+  * **CA**: TRUE
+
+    The root certificate is a Certificate Authority, it will be used to sign
+    other Certificates.
+
+  * **pathlen**: 1
+
+    The path length constraint expresses the number of possible intermediate
+    CA certificates in a path built from an end-entity certificate up to the
+    CA certificate. An absent path length constraint means that there is no
+    limitation to the number of intermediate certificates from end-entity to
+    the CA certificate. The smallstep PKI has only one intermediate CA
+    certificate between end-entity certificates and the root CA certificcate.
+
+* **Key Usage** describes how the certificate can be used.
+  * **Certificate Sign**
+
+    Indicates that our root public key will be used to verify a signature on
+    certificates.
+
+  * **CRL Sign**
+
+    Indicates that our root public key will be used to verify a signature on
+    revocation information, such as CRL.
+
+### Intermediate Certificate
+
+* Validity (10 year window)
+  * **Not Before**: Now
+  * **Not After**: Now + 10 years
+
+    A 10 year window seems advisable until software and tools can be written
+    for rotating the root certificate.
+
+* **Basic Constraints**
+  * **CA**: TRUE
+
+    The intermediate certificate is a Certificate Authority, used to sign
+    end-entity (service, process, job, etc.) certificates.
+  * **pathlen**: 0
+
+    The path length constraint expresses the number of possible intermediate
+    CA certificates in a path built from an end-entity certificate up to the
+    CA certificate. An absent path length constraint means that there is no
+    limitation to the number of intermediate certificates from end-entity to
+    the CA certificate. There are no additional intermediary certificates in
+    the path between the smallstep intermediate CA and end-entity certificates.
+
+* **Key Usage**
+  * **Certificate Signing**
+
+    Indicates that our the intermediate private key can be used to sign
+    certificate requests.
+
+  * **CRL Sign**
+
+    Indicates that this public key can be used to verify a signature on
+    revocation information, such as CRL.
+
+### Leaf Certificate - End Entity Certificate (certificates returned by the CA)
+
+* Validity (24 hour window)
+  * **Not Before**: Now
+  * **Not After**: Now + 24 hours
+
+    The default is a 24hr window. This value is somewhat arbitrary, however,
+    our goal is to have seamless end-entity certificate rotation (we are
+    getting close). Rotating certificates frequently is good security hygiene
+    because it gives bad actors very little time to form an attack and limits
+    the usefulness of any single private key in the system. We will continue
+    to work towards decreasing this window because we believe it significantly
+    reduces probability and effectiveness of any attack.
+
+* **Key Usage**
+  * **Key Encipherment**
+
+    Indicates that a certificate will be used with a protocol that encrypts keys.
+
+  * **Digital Signature**
+
+    Indicates that this public key may be used as a digital signature to
+    support security services that enable entity authentication and data
+    origin authentication with integrity.
+
+* **Extended Key Usage**
+  * **TLS Web Server Authentication**
+
+    Certificate can be used as the server side certificate in the TLS protocol.
+
+  * **TLS Web Client Authentication**
+
+    Certificate can be used as the client side certificate in the TLS protocol.
+
+## Default TLS Configuration Options
+
+* **Min TLS Version**: TLS 1.2
+* **Max TLS Version**: TLS 1.2
+
+  The PCI Security Standards Council required all payment processors
+  and merchants to move to TLS 1.2 and above by June 30, 2018. By setting
+  TLS 1.2 as the default for all tls protocol negotiation we encourage our
+  users to adopt the same security conventions.
+
+* **Default Cipher Suites**:
+
+  ```
+  [
+      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
+      "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+  ]
+  ```
+
+  The default 'ciphersuites' are a list of two cipher combinations. For
+  communication between services running step there is no need for cipher suite
+  negotiation. The server can specify a single cipher suite which the client is
+  already known to support.
+
+  Reasons for selecting `TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305`:
+  * ECDHE key exchange algorithm has perfect forward secrecy
+  * ECDSA has smaller keys and better performance (than RSA)
+  * CHACHA20 with POLY1305 is the cipher mode used by google.
+  * CHACHA20's performance is better than GCM and CBC.
+
+
+  The http2 spec requires the `TLS_ECDHE_(RSA|ECDSA)_WITH_AES_128_GCM_SHA256`
+  ciphersuite be accepted by the server, therefore it makes our list of
+  default ciphersuites until we build the functionality to modify our defaults
+  based on http version.
+
+* **Approved Cipher Suites**:
+
+  ```
+  [
+    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+    "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
+    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
+  ]
+  ```
+
+  Above is a list of step approved cipher suites. Not all communication
+  can be mediated with step TLS functionality. For those connections the list of
+  server supported cipher suites must have more options - in case older clients
+  do not support our favored cipher suite.
+
+  Reasons for selecting these cipher suites can be found in the following
+  [ssllabs article](https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices#23-use-secure-cipher-suites).
+
+* **Renegotation**: Never
+
+  TLS renegotiation significantly complicates the state machine and has been
+  the source of numerous, subtle security issues. Therefore, by default we
+  disable it.
diff --git a/docs/distribution.md b/docs/distribution.md
deleted file mode 100644
index 7e3907b9..00000000
--- a/docs/distribution.md
+++ /dev/null
@@ -1,116 +0,0 @@
-# Distribution
-
-This section describes how to build and deploy publicly available releases of
-the Step CA.
-
-## Creating A New Release
-
-New releases are (almost) entirely built and deployed by Travis-CI. Creating a new
-release is as simple as pushing a new github tag.
-
-**Definitions**:
-
-* **Standard Release**: ready for public use. no `-rc*` suffix on the version.
-e.g. `v1.0.2`
-* **Release Candidate**: not ready for public use, still testing. must have a
-`-rc*` suffix. e.g. `v1.0.2-rc` or `v1.0.2-rc.4`
-
-1. **Update the version of step/cli**
-
-    ```
-    $ dep ensure -update github.com/smallstep/cli
-    ```
-
-2. **Commit all changes.**
-
-    Make sure that the local checkout is up to date with the remote origin and
-    that all local changes have been pushed.
-
-    ```
-    $ git pull --rebase origin master
-    $ git push
-    ```
-
-3. **Tag it!**
-
-    1. **Find the most recent tag.**
-
-        ```
-        $ git fetch --tags
-        $ git tag
-        ```
-
-        The new tag needs to be the logical successor of the most recent existing tag.
-        See [versioning](#versioning) section for more information on version numbers.
-
-    2. **Select the type and value of the next tag.**
-
-        Is the new release a *release candidate* or a *standard release*?
-
-        1. Release Candidate
-
-            If the most recent tag is a standard release, say `v1.0.2`, then the version
-            of the next release candidate should be `v1.0.3-rc.1`. If the most recent tag
-            is a release candidate, say `v1.0.2-rc.3`, then the version of the next
-            release candidate should be `v1.0.2-rc.4`.
-
-        2. Standard Release
-
-            If the most recent tag is a standard release, say `v1.0.2`, then the version
-            of the next standard release should be `v1.0.3`. If the most recent tag
-            is a release candidate, say `v1.0.2-rc.3`, then the version of the next
-            standard release should be `v1.0.3`.
-
-
-    3. **Create a local tag.**
-
-        ```
-        $ git tag v1.0.3   # standard release
-        ...or
-        $ git tag v1.0.3-rc.1  # release candidate
-        ```
-
-    4. **Push the new tag to the remote origin.**
-
-        ```
-        $ git push origin tag v1.0.3   # standard release
-        ...or
-        $ git push origin tag v1.0.3-rc.1  # release candidate
-        ```
-
-4. Check the build status at
-[Travis-CI](https://travis-ci.com/smallstep/certificates/builds/).
-
-    Travis will begin by verifying that there are no compilation or linting errors
-    and then run the unit tests. Assuming all the checks have passed, Travis will
-    build Darwin and Linux artifacts (for easily installing `step`) and upload them
-    as part of the [Github Release](https://github.com/smallstep/certificates/releases).
-
-    Travis will build and upload the following artifacts:
-
-    * **step-certificates_1.0.3_amd64.deb**: debian package for installation on linux.
-    * **step-certificates_1.0.3_linux_amd64.tar.gz**: tarball containing a statically compiled linux binary.
-    * **step-certificates_1.0.3_darwin_amd64.tar.gz**: tarball containing a statically compiled darwin binary.
-    * **step-certificates.tar.gz**: tarball containing a git archive of the full repo.
-
-6. **Update the AUR Arch Linux package**
-
-    **NOTE**: if you plan to release `cli` next then you can skip this step.
-
-    ```
-    $ cd archlinux
-
-    # Get up to date...
-    $ git pull origin master
-    $ make
-
-    $ ./update --ca v1.0.3
-    ```
-
-*All Done!*
-
-## Versioning
-
-We use [SemVer](http://semver.org/) for versioning. See the
-[tags on this repository](https://github.com/smallstep/certificates) for all
-available versions.
diff --git a/images/connect-with-mtls-2.png b/docs/images/connect-with-mtls-2.png
similarity index 100%
rename from images/connect-with-mtls-2.png
rename to docs/images/connect-with-mtls-2.png
diff --git a/docs/oidc1.png b/docs/images/oidc1.png
similarity index 100%
rename from docs/oidc1.png
rename to docs/images/oidc1.png
diff --git a/docs/oidc2.png b/docs/images/oidc2.png
similarity index 100%
rename from docs/oidc2.png
rename to docs/images/oidc2.png
diff --git a/docs/oidc3.png b/docs/images/oidc3.png
similarity index 100%
rename from docs/oidc3.png
rename to docs/images/oidc3.png
diff --git a/images/step-ca-2-legged.gif b/docs/images/step-ca-2-legged.gif
similarity index 100%
rename from images/step-ca-2-legged.gif
rename to docs/images/step-ca-2-legged.gif
diff --git a/images/step-ca-3-legged.gif b/docs/images/step-ca-3-legged.gif
similarity index 100%
rename from images/step-ca-3-legged.gif
rename to docs/images/step-ca-3-legged.gif
diff --git a/docs/common-questions.md b/docs/questions.md
similarity index 86%
rename from docs/common-questions.md
rename to docs/questions.md
index 21e70ff1..723d232d 100644
--- a/docs/common-questions.md
+++ b/docs/questions.md
@@ -1,11 +1,16 @@
-# Commonly Asked Questions
+# Frequently Asked Questions
 
 These are some commonly asked questions on the topics of PKI, TLS, X509,
 cryptography, threshold-cryptography, etc.
-We hope to reduce the amount of hand-waving in these responses as we add
+Hopefully we will reduce the amount of hand-waving in these responses as we add
 more features to the Step toolkit over time.
 
-#### What's TLS & PKI?
+> We encourage you to read
+> [our blog post on everything relating to PKI](https://smallstep.com/blog/everything-pki.html)
+> as we believe it to be a solid resource that answers many of of the questions
+> listed below.
+
+## What are TLS & PKI?
 
 TLS stands for *transport layer security*. It used to be called *secure sockets
 layer* (or SSL), but technically SSL refers to an older version of the protocol.
@@ -16,7 +21,9 @@ intended recipient, and cannot be modified in transit.
 
 TLS is a complicated protocol with lots of options, but the most common mode of
 operation establishes a secure channel using *asymmetric cryptography* with
-*digital certificates* (or just certificates for short). First, some quick definitions:
+*digital certificates* (or just certificates for short).
+
+First, some quick definitions:
 * *Asymmetric cryptography* (a.k.a., public key cryptography) is an underappreciated
 gift from mathematics to computer science. It uses a *key pair*: a private key
 known only to the recipient of the message, and a public key that can be broadly
@@ -40,7 +47,7 @@ and procedures for managing digital certificates (i.e., managing the bindings
 between names and public keys). Without proper secure PKI, an attacker can fake
 a binding and undermine security.
 
-#### What's a certificate authority?
+## What's a certificate authority?
 
 A certificate authority (CA) stores, issues, and signs digital certificates. CAs
 have their own key pair, with the private key carefully secured (often offline).
@@ -73,7 +80,7 @@ and verifying the identity of the requesting entities before establishing bindin
 It also acts as a *central directory* and more generally as a *certificate
 management system*, a secure location for storing and distributing key material.
 
-#### Why not just use Verisign, Entrust, Let's Encrypt, etc?
+## Why not just use Verisign, Entrust, Let's Encrypt, etc?
 
 The web's *open public key infrastructure* (web PKI), while far from perfect,
 is an important foundation for securing the web. So why not use it for securing
@@ -86,14 +93,7 @@ communication for your own internal infrastructure? There are several reasons:
 More broadly, the answer is that web PKI was designed for the web. A lot of the
 web PKI design decisions aren't appropriate for internal systems.
 
-#### How does identity proofing work?
-
-Good question. However you want it to. Details here. Give some options: simple
-meat-space token-based method should probably be default. But we should also
-support the use of a CI/CD pipeline or orchestrator as a *registration authority*
-so you can automate certificate provisioning.
-
-Also talk about ACME, if we decide to support it.
+## How does identity proofing work?
 
 In general, trust will always flow back out to you, the operator of your system.
 With that in mind, the simplest form of identity proofing is manual: [describe
@@ -104,6 +104,11 @@ designs, to help with this. If you integrate with our other tools its easy to
 start with a manual identity proofing mechanism and move to a more sophisticated
 automated method as your system grows.
 
-#### I already have PKI in place. Can I use this with my own root certificate?
+## I already have PKI in place. Can I use this with my own root certificate?
 
 Absolutely. [Details here].
+
+## Furher Reading
+
+* [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html)
+* [Everything you should know about certificates and PKI but are too afraid to ask](https://smallstep.com/blog/everything-pki.html)
diff --git a/docs/recommendations.md b/docs/recommendations.md
deleted file mode 100644
index c0c02d45..00000000
--- a/docs/recommendations.md
+++ /dev/null
@@ -1,207 +0,0 @@
-## Sane Recommendations
-
-TLS, PKI, X509, HTTPS, etc. all require configuration. All of
-these technologies allow the user to "shoot themselves in the foot" by
-misconfiguring them and reducing their benefits significantly. Therefore,
-offering an easy to use solution that works out of the box means choosing and
-enforcing sane default configurations for all these technologies.
-
-Below we document some of the significant default configuration that we recommend.
-This document is a moving target: security and cryptography are constanly
-changing and evolving - vulnerabilities are found, new algorithms are created,
-etc. We inted for this document be an accurate representation of current
-best practices in the industry, and to have these practices codified as defaults
-in the `certificates` code base. If you have questions, suggestions, or comments
-about any of these decisions please let us know.
-
-### Tokens
-
-We use JWTs (JSON Web Tokens to prove authenticity and identity within the Step
-ecosystem. JWTs have received negative attention because they are easy to
-misuse, misconfigure.
-We agree! But lots of things are easy to misuse. We also believe
-that when configured well JWTs are a great way to sign and encode data. Our JWT's
-are, by default, short-lived (5 minute lifespan) and can only be used once during
-the lifetime of the Step CA. We use a 1 minute clock drift leeway because that
-was the recommended default in the reputable JWT package that we chose. If using
-Step JWTs or your own JWTs in your code be sure to verify and validate every
-single standard attributed of the JWT. JWTs, like all cryptographic tools,
-are useless without proper attention to configuration and guidelines.
-
-### Keys
-
-  ```
-  // RSA keys don't scale very well. To get 128 bits of security, you need 3,072-bit
-  // RSA keys, which are noticeably slower. ECDSA keys provide an alternative
-  // that offers better security and better performance. At 256 bits, ECDSA keys
-  // provide 128 bits of security. A small number of older clients don't support
-  // ECDSA, but most modern clients do.
-  Default Key Type: ECDSA
-  Default Curve Bits: P-256
-
-  // Encryption algorithm for writing private keys to disk. We've chosen AES
-  // (aka Rijndael) because it was the official choice of the Advanced Encryption
-  // Standard contest. The three supported key sizes are 128, 192, and 256. Each
-  // of these is considered to be unbreakable for the forseeable future, therefore
-  // we chose 128 bits as our default because the performance is better
-  // (as compared to the greater key sizes) and because we agree, with the
-  // designers of the algorithm, that 128 bits are quite sufficient for most
-  // security needs.
-  Default PEMCipher: AES128
-  ```
-
-### X.509 Certificate Defaults
-
-* **root certificate**
-
-  ```
-  * Validity (10 year window)
-    * Not Before: Now
-    // A 10 year window seems advisable until software and tools can be written
-    // for rotating the root certificate.
-    * Not After: Now + 10 years
-  * Basic Constraints
-    // The root certificate is a Certificate Authority, it will be used to sign
-    // other Certificates.
-    * CA: TRUE
-    // The path length constraint expresses the number of possible intermediate
-    // CA certificates in a path built from an end-entity certificate up to the
-    // CA certificate. An absent path length constraint means that there is no
-    // limitation to the number of intermediate certificates from end-entity to
-    // the CA certificate. The smallstep PKI has only one intermediate CA
-    //certificate between end-entity certificates and the root CA certificcate.
-    * pathlen: 1
-  * Key Usage // Describes how the keys can be used.
-    // Indicates that a certificate will be used with a protocol that encrypts keys.
-    * Key Encipherment
-    // Indicates that our root public key will be used to verify a signature on
-    // certificates.
-    * Certificate Signing
-    // Indicates that our root public key will be used to verify a signature on
-    // revocation
-    // information, such as CRL.
-    * CRL Sign
-    // Indicates that our root public key may be used as a digital signature to
-    // support security services that enable entity authentication and data
-    // origin authentication with integrity.
-    * Digital Signature
-  ```
-
-* **intermediate certificate**
-
-  ```
-  * Validity (10 year window)
-    * Not Before: Now
-    // A 10 year window seems advisable until software and tools can be written
-    // for rotating the intermediates certificates without considerable agony
-    // on the part of the user.
-    * Not After: Now + 10 years
-  * Basic Constraints
-    // The intermediate certificate is a Certificate Authority, used to sign
-    // end-entity (service, process, job, etc.) certificates.
-    * CA: TRUE
-    // The path length constraint expresses the number of possible intermediate
-    // CA certificates in a path built from an end-entity certificate up to the
-    // CA certificate. An absent path length constraint means that there is no
-    // limitation to the number of intermediate certificates from end-entity to
-    // the CA certificate. There are no additional intermediary certificates in
-    // the path between the smallstep intermediate CA and end-entity certificates.
-    * pathlen: 0
-  * Key Usage
-    // Indicates that a certificate will be used with a protocol that encrypts keys.
-    * Key Encipherment
-    // Indicates that our root public key will be used to verify a signature on
-    // certificates.
-    * Certificate Signing
-    // Indicates that this public key can be used to verify a signature on
-    // revocation information, such as CRL.
-    * CRL Sign
-    // Indicates that this public key may be used as a digital signature to
-    // support security services that enable entity authentication and data
-    // origin authentication with integrity.
-    * Digital Signature
-  * Extended Key Usage
-    // Certificate can be used as the server side certificate in the TLS protocol.
-    * TLS Web Server Authentication
-    // Certificate can be used as the client side certificate in the TLS protocol.
-    * TLS Web Client Authentication
-  ```
-
-* **Leaf Certificate - End Entity Certificate** (certificates returned by the CA)
-
-  ```
-  * Validity (24 hour window)
-    * Not Before: Now
-    // The default is a 24hr window. This value is somewhat arbitrary, however,
-    // our goal is to have seamless end-entity certificate rotation (we are
-    // getting close). Rotating certificates frequently is good security hygiene
-    // because it gives bad actors very little time to form an attack and limits
-    // the usefulness of any single private key in the system. We will continue
-    // to work towards decreasing this window because we believe it significantly
-    // reduces probability and effectiveness of any attack.
-    * Not After: Now + 24 hours
-  * Key Usage
-    // Indicates that a certificate will be used with a protocol that encrypts keys.
-    * Key Encipherment
-    // Indicates that this public key may be used as a digital signature to
-    // support security services that enable entity authentication and data
-    // origin authentication with integrity.
-    * Digital Signature
-  * Extended Key Usage
-    // Certificate can be used as the server side certificate in the TLS protocol.
-    * TLS Web Server Authentication
-    // Certificate can be used as the client side certificate in the TLS protocol.
-    * TLS Web Client Authentication
-  ```
-
-### Default TLS Configuration Options
-
-  ```
-  // The PCI Security Standards Council is requiring all payment processors
-  // and merchants to move to TLS 1.2 and above by June 30, 2018. By setting
-  // TLS 1.2 as the default for all tls protocol negotiation we encourage our
-  // users to adopt the same security conventions.
-  * MinVersion: TLS 1.2
-  * MaxVersion: TLS 1.2
-
-  // https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices#23-use-secure-cipher-suites
-  // The default 'ciphersuites' is a single cipher combination. For communication
-  // between services running step there is no need for cipher suite negotiation.
-  // The server can specify a single cipher suite which the client is already
-  // known to support. Reasons for selecting "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305":
-  //  - ECDHE key exchange algorithm has perfect forward secrecy
-  //  - ECDSA has smaller keys and better performance (than RSA)
-  //  - CHACHA20 with POLY1305 is the cipher mode used by google.
-  //  - CHACHA20's performance is better than GCM and CBC.
-  // NOTE: The http2 spec requires the "TLS_ECDHE_(RSA|ECDSA)_WITH_AES_128_GCM_SHA256"
-  // ciphersuite be accepted by the server, therefore it makes our list of
-  // default ciphersuites until we build the functionality to modify our defaults
-  // based on http version.
-  * DefaultCipherSuites: [
-      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
-      "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
-    ]
-  // The following is a list of step approved cipher suites. Not all communication
-  // can be mediated with step TLS functionality. For those connections the list of
-  // server supported cipher suites must have more options - in case older clients
-  // do not support our favored cipher suite. Reasons for selecting these cipher
-  // suites can be found in the ssllabs article cited above.
-  * ApprovedCipherSuites: [
-      "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
-      "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
-      "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
-      "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
-      "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
-      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
-      "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
-      "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
-      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
-      "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
-      "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
-      "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
-    ]
-  // TLS renegotiation significantly complicates the state machine and has been
-  // the source of numerous, subtle security issues. Therefore, by default we
-  // disable it.
-  * Renegotation: Never
-
diff --git a/docs/revocation.md b/docs/revocation.md
index 7402d3d1..c8384d46 100644
--- a/docs/revocation.md
+++ b/docs/revocation.md
@@ -201,7 +201,7 @@ through an example.
 
 [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html) and let us know
 what you think of our tools. Get in touch over
-[twitter](twitter.com/smallsteplabs) or through our
+[Twitter](twitter.com/smallsteplabs) or through our
 [Gitter](https://gitter.im/smallstep/community) to chat with us in real time.
 
 ## Further Reading

From fdfce81dff74c3cbaae76ccfa15c79ecce36b73e Mon Sep 17 00:00:00 2001
From: max furman 
Date: Mon, 29 Apr 2019 17:51:35 -0700
Subject: [PATCH 11/15] docs: direct to readme not dir

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index ec11c411..6c1b1197 100644
--- a/README.md
+++ b/README.md
@@ -323,7 +323,7 @@ and best practices on running Step CA in production.
 
 Documentation can be found in a handful of different places:
 
-1. The [docs](./docs) sub-repo has an index of documentation and tutorials.
+1. The [docs](./docs/README.md) sub-repo has an index of documentation and tutorials.
 
 2. On the command line with `step ca help xxx` where `xxx` is the subcommand
 you are interested in. Ex: `step help ca provisioners list`.

From fe08dcb532c470e6807af42b975741d0d8cb5343 Mon Sep 17 00:00:00 2001
From: max furman 
Date: Mon, 29 Apr 2019 23:54:25 -0700
Subject: [PATCH 12/15] docs: index -> toc

---
 docs/README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/README.md b/docs/README.md
index 06968809..b7112d5e 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -13,7 +13,7 @@ Index of Documentation and Tutorials for using and deploying the `step certifica
 [![GitHub stars](https://img.shields.io/github/stars/smallstep/certificates.svg?style=social)](https://github.com/smallstep/certificates/stargazers)
 [![Twitter followers](https://img.shields.io/twitter/follow/smallsteplabs.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=smallsteplabs)
 
-## Index
+## Table of Contents
 
 * **General Info**
     * [Website](https://smallstep.com)

From cd5c7e713458cf21e88f604d3c17bc8c2e4e69da Mon Sep 17 00:00:00 2001
From: max furman 
Date: Tue, 30 Apr 2019 11:07:54 -0700
Subject: [PATCH 13/15] dep update cli and add distribution.md back

---
 Gopkg.lock      |   2 +-
 distribution.md | 116 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 distribution.md

diff --git a/Gopkg.lock b/Gopkg.lock
index bd6c951b..d4514ef2 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -359,7 +359,7 @@
     "utils",
   ]
   pruneopts = "UT"
-  revision = "98475c4f19cda6b77e30d3f2f32f81e1ba8dfd46"
+  revision = "8429a2f6f5d6f097b843322a9a8e80d6fd087258"
 
 [[projects]]
   branch = "master"
diff --git a/distribution.md b/distribution.md
new file mode 100644
index 00000000..7e3907b9
--- /dev/null
+++ b/distribution.md
@@ -0,0 +1,116 @@
+# Distribution
+
+This section describes how to build and deploy publicly available releases of
+the Step CA.
+
+## Creating A New Release
+
+New releases are (almost) entirely built and deployed by Travis-CI. Creating a new
+release is as simple as pushing a new github tag.
+
+**Definitions**:
+
+* **Standard Release**: ready for public use. no `-rc*` suffix on the version.
+e.g. `v1.0.2`
+* **Release Candidate**: not ready for public use, still testing. must have a
+`-rc*` suffix. e.g. `v1.0.2-rc` or `v1.0.2-rc.4`
+
+1. **Update the version of step/cli**
+
+    ```
+    $ dep ensure -update github.com/smallstep/cli
+    ```
+
+2. **Commit all changes.**
+
+    Make sure that the local checkout is up to date with the remote origin and
+    that all local changes have been pushed.
+
+    ```
+    $ git pull --rebase origin master
+    $ git push
+    ```
+
+3. **Tag it!**
+
+    1. **Find the most recent tag.**
+
+        ```
+        $ git fetch --tags
+        $ git tag
+        ```
+
+        The new tag needs to be the logical successor of the most recent existing tag.
+        See [versioning](#versioning) section for more information on version numbers.
+
+    2. **Select the type and value of the next tag.**
+
+        Is the new release a *release candidate* or a *standard release*?
+
+        1. Release Candidate
+
+            If the most recent tag is a standard release, say `v1.0.2`, then the version
+            of the next release candidate should be `v1.0.3-rc.1`. If the most recent tag
+            is a release candidate, say `v1.0.2-rc.3`, then the version of the next
+            release candidate should be `v1.0.2-rc.4`.
+
+        2. Standard Release
+
+            If the most recent tag is a standard release, say `v1.0.2`, then the version
+            of the next standard release should be `v1.0.3`. If the most recent tag
+            is a release candidate, say `v1.0.2-rc.3`, then the version of the next
+            standard release should be `v1.0.3`.
+
+
+    3. **Create a local tag.**
+
+        ```
+        $ git tag v1.0.3   # standard release
+        ...or
+        $ git tag v1.0.3-rc.1  # release candidate
+        ```
+
+    4. **Push the new tag to the remote origin.**
+
+        ```
+        $ git push origin tag v1.0.3   # standard release
+        ...or
+        $ git push origin tag v1.0.3-rc.1  # release candidate
+        ```
+
+4. Check the build status at
+[Travis-CI](https://travis-ci.com/smallstep/certificates/builds/).
+
+    Travis will begin by verifying that there are no compilation or linting errors
+    and then run the unit tests. Assuming all the checks have passed, Travis will
+    build Darwin and Linux artifacts (for easily installing `step`) and upload them
+    as part of the [Github Release](https://github.com/smallstep/certificates/releases).
+
+    Travis will build and upload the following artifacts:
+
+    * **step-certificates_1.0.3_amd64.deb**: debian package for installation on linux.
+    * **step-certificates_1.0.3_linux_amd64.tar.gz**: tarball containing a statically compiled linux binary.
+    * **step-certificates_1.0.3_darwin_amd64.tar.gz**: tarball containing a statically compiled darwin binary.
+    * **step-certificates.tar.gz**: tarball containing a git archive of the full repo.
+
+6. **Update the AUR Arch Linux package**
+
+    **NOTE**: if you plan to release `cli` next then you can skip this step.
+
+    ```
+    $ cd archlinux
+
+    # Get up to date...
+    $ git pull origin master
+    $ make
+
+    $ ./update --ca v1.0.3
+    ```
+
+*All Done!*
+
+## Versioning
+
+We use [SemVer](http://semver.org/) for versioning. See the
+[tags on this repository](https://github.com/smallstep/certificates) for all
+available versions.

From 25c710c056defc5515f7ff1d4c31ff0f38a05e31 Mon Sep 17 00:00:00 2001
From: max furman 
Date: Tue, 30 Apr 2019 11:11:18 -0700
Subject: [PATCH 14/15] docs: indent note in distribution.md

---
 distribution.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/distribution.md b/distribution.md
index 7e3907b9..7fba390b 100644
--- a/distribution.md
+++ b/distribution.md
@@ -95,7 +95,7 @@ e.g. `v1.0.2`
 
 6. **Update the AUR Arch Linux package**
 
-    **NOTE**: if you plan to release `cli` next then you can skip this step.
+    > **NOTE**: if you plan to release `cli` next then you can skip this step.
 
     ```
     $ cd archlinux

From cff99b01513cf957650e3486782fda74d86c586d Mon Sep 17 00:00:00 2001
From: max furman 
Date: Wed, 1 May 2019 16:00:34 -0700
Subject: [PATCH 15/15] Fix images url in top level README

---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 6c1b1197..6b9faafe 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ An online certificate authority and related tools for secure automated certifica
 [![GitHub stars](https://img.shields.io/github/stars/smallstep/certificates.svg?style=social)](https://github.com/smallstep/certificates/stargazers)
 [![Twitter followers](https://img.shields.io/twitter/follow/smallsteplabs.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=smallsteplabs)
 
-![Animated terminal showing step certificates in practice](https://github.com/smallstep/certificates/raw/master/images/step-ca-2-legged.gif)
+![Animated terminal showing step certificates in practice](https://github.com/smallstep/certificates/raw/master/docs/images/step-ca-2-legged.gif)
 
 ## Motivation
 
@@ -37,7 +37,7 @@ operate DNS and reverse proxies, you know how to operate mTLS
 infrastructure.
 
 ![Connect it all with
-mTLS](https://raw.githubusercontent.com/smallstep/certificates/master/images/connect-with-mtls-2.png)
+mTLS](https://raw.githubusercontent.com/smallstep/certificates/master/docs/images/connect-with-mtls-2.png)
 
 There's just one problem: **you need certificates issued by your own
 certificate authority (CA)**. Building and operating a CA, issuing