diff --git a/Gopkg.lock b/Gopkg.lock index 48214e8e..d4514ef2 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" @@ -298,15 +359,21 @@ "utils", ] pruneopts = "UT" - revision = "98475c4f19cda6b77e30d3f2f32f81e1ba8dfd46" + revision = "8429a2f6f5d6f097b843322a9a8e80d6fd087258" [[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" @@ -591,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/README.md b/README.md index 754069d5..6b9faafe 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) @@ -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 @@ -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/README.md) 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/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 diff --git a/ca/ca.go b/ca/ca.go index b8dfc39b..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,21 +132,64 @@ func (ca *CA) Stop() error { // Reload reloads the configuration of the CA and calls to the server Reload // method. func (ca *CA) Reload() error { + 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") } 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 bbc43ce5..886c3ef7 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,omitempty"` + Database string `json:"database,omitempty"` } // AuthDB is an interface over an Authority DB client that implements a nosql.DB interface. @@ -36,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. @@ -44,15 +46,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} @@ -63,7 +60,7 @@ func New(c *Config) (AuthDB, error) { } } - return &DB{db}, nil + return &DB{db, true}, nil } // RevokedCertificateInfo contains information regarding the certificate @@ -131,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 c05dbd78..c2b16d57 100644 --- a/db/db_test.go +++ b/db/db_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/smallstep/assert" - "github.com/smallstep/nosql" + "github.com/smallstep/nosql/database" ) type MockNoSQLDB struct { @@ -13,13 +13,13 @@ type MockNoSQLDB struct { 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) { @@ -39,9 +39,9 @@ func (m *MockNoSQLDB) Set(bucket, key, value []byte) error { return m.err } -func (m *MockNoSQLDB) Open(path string) error { +func (m *MockNoSQLDB) Open(dataSourceName string, opt ...database.Option) error { if m.open != nil { - return m.open(path) + return m.open(dataSourceName, opt...) } return m.err } @@ -74,14 +74,14 @@ func (m *MockNoSQLDB) Del(bucket, key []byte) error { return m.err } -func (m *MockNoSQLDB) List(bucket []byte) ([]*nosql.Entry, error) { +func (m *MockNoSQLDB) 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 *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{&MockNoSQLDB{err: nosql.ErrNotFound, ret1: nil}}, + db: &DB{&MockNoSQLDB{err: database.ErrNotFound, ret1: nil}, true}, }, "error/checking bucket": { key: "sn", - db: &DB{&MockNoSQLDB{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{&MockNoSQLDB{ret1: []byte("value")}}, + db: &DB{&MockNoSQLDB{ret1: []byte("value")}, true}, isRevoked: true, }, } @@ -140,7 +140,7 @@ func TestRevoke(t *testing.T) { 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": { @@ -149,31 +149,31 @@ func TestRevoke(t *testing.T) { get: func(bucket []byte, sn []byte) ([]byte, error) { return nil, nil }, - }}, + }, true}, err: ErrAlreadyExists, }, "error/database set": { rci: &RevokedCertificateInfo{Serial: "sn"}, db: &DB{&MockNoSQLDB{ 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") }, - }}, + }, true}, err: errors.New("database Set error: force"), }, "ok": { rci: &RevokedCertificateInfo{Serial: "sn"}, db: &DB{&MockNoSQLDB{ 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 }, - }}, + }, true}, }, } for name, tc := range tests { diff --git a/docs/distribution.md b/distribution.md similarity index 97% rename from docs/distribution.md rename to distribution.md index 7e3907b9..7fba390b 100644 --- a/docs/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 diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index e71d4c01..a5323832 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. @@ -384,7 +398,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 @@ -465,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, @@ -478,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 @@ -486,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..b7112d5e --- /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) + +## Table of Contents + +* **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/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. 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/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 new file mode 100644 index 00000000..c8384d46 --- /dev/null +++ b/docs/revocation.md @@ -0,0 +1,210 @@ +# Revocation + +**Active Revocation**: A certificate is no longer valid from the moment it has +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 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 +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 +through an example. + +### Requirements + +* `step` (>=v0.10.0) ([install instructions](../README.md#installation-guide)) + +### 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 step 2. + + Run `step ca init`. + +

+   $ step ca init --name "Local CA" --provisioner admin --dns localhost --address ":443"
+   
+ + 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
+   ✔ 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
+   
+ +5. 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
+   
+ +6. 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.
+   
+ +7. Awesome! 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=
+   [...]
+   
+ +8. Other ways to revoke a Certificate + + 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
+   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. + + 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 +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 + +* [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)