Merge branch 'master' into cloud-identities

This commit is contained in:
Mariano Cano 2019-05-03 17:28:04 -07:00
commit dae802482a
20 changed files with 791 additions and 277 deletions

91
Gopkg.lock generated
View file

@ -1,6 +1,14 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. # 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]] [[projects]]
digest = "1:304cb78c285eaf02ab529ad02a257cad9b4845022915e6c82f87860ac53222d8" digest = "1:304cb78c285eaf02ab529ad02a257cad9b4845022915e6c82f87860ac53222d8"
name = "github.com/alecthomas/gometalinter" name = "github.com/alecthomas/gometalinter"
@ -35,6 +43,29 @@
revision = "b90dc15cfd220ecf8bbc9043ecb928cef381f011" revision = "b90dc15cfd220ecf8bbc9043ecb928cef381f011"
version = "v0.3.4" 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]] [[projects]]
digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda" digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda"
name = "github.com/ghodss/yaml" name = "github.com/ghodss/yaml"
@ -51,6 +82,14 @@
pruneopts = "UT" pruneopts = "UT"
revision = "0ebf7795c516423a110473652e9ba3a59a504863" revision = "0ebf7795c516423a110473652e9ba3a59a504863"
[[projects]]
digest = "1:ec6f9bf5e274c833c911923c9193867f3f18788c461f76f05f62bb1510e0ae65"
name = "github.com/go-sql-driver/mysql"
packages = ["."]
pruneopts = "UT"
revision = "72cd26f257d44c1114970e19afddcd812016007e"
version = "v1.4.1"
[[projects]] [[projects]]
digest = "1:b402bb9a24d108a9405a6f34675091b036c8b056aac843bf6ef2389a65c5cf48" digest = "1:b402bb9a24d108a9405a6f34675091b036c8b056aac843bf6ef2389a65c5cf48"
name = "github.com/gogo/protobuf" name = "github.com/gogo/protobuf"
@ -174,6 +213,28 @@
revision = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c" revision = "6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c"
version = "v0.0.4" 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]] [[projects]]
digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563" digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563"
name = "github.com/modern-go/concurrent" name = "github.com/modern-go/concurrent"
@ -298,15 +359,21 @@
"utils", "utils",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "98475c4f19cda6b77e30d3f2f32f81e1ba8dfd46" revision = "8429a2f6f5d6f097b843322a9a8e80d6fd087258"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:fd8d9eb07509d8ef47fc82c99646f0b2203b2ba3c240ba77d8c457bb6109836d" digest = "1:f1f1df1e19d55a1ef1f0a63633191e7d2a99993c0a17f945c0b9ebd16b17871b"
name = "github.com/smallstep/nosql" name = "github.com/smallstep/nosql"
packages = ["."] packages = [
".",
"badger",
"bolt",
"database",
"mysql",
]
pruneopts = "UT" pruneopts = "UT"
revision = "d8f68d14f9ae04e0991dce06b44768f2d38dccf8" revision = "5a355c598075a346d9ca9b50ec10e3f86ac66148"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -402,17 +469,30 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:384310e8a567edf6d5406d93318f9460c2d8db1a07ff5b6fece95b224343e7f1" digest = "1:6b4a1c844969280f4d3e36ef4b0762e3522e701c015f688b68ef91c2ea6b5ac7"
name = "golang.org/x/tools" name = "golang.org/x/tools"
packages = [ packages = [
"go/ast/astutil", "go/ast/astutil",
"go/gcexportdata", "go/gcexportdata",
"go/internal/cgo",
"go/internal/gcimporter", "go/internal/gcimporter",
"go/packages",
"go/types/typeutil", "go/types/typeutil",
"internal/fastwalk",
"internal/gopathwalk",
"internal/semver",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "3a10b9bf0a52df7e992a8c3eb712a86d3c896c75" revision = "3a10b9bf0a52df7e992a8c3eb712a86d3c896c75"
[[projects]]
digest = "1:c25289f43ac4a68d88b02245742347c94f1e108c534dda442188015ff80669b3"
name = "google.golang.org/appengine"
packages = ["cloudsql"]
pruneopts = "UT"
revision = "54a98f90d1c46b7731eb8fb305d2a321c30ef610"
version = "v1.5.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c" digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c"
@ -591,6 +671,7 @@
"github.com/smallstep/cli/token/provision", "github.com/smallstep/cli/token/provision",
"github.com/smallstep/cli/usage", "github.com/smallstep/cli/usage",
"github.com/smallstep/nosql", "github.com/smallstep/nosql",
"github.com/smallstep/nosql/database",
"github.com/tsenart/deadcode", "github.com/tsenart/deadcode",
"github.com/urfave/cli", "github.com/urfave/cli",
"golang.org/x/crypto/ocsp", "golang.org/x/crypto/ocsp",

View file

@ -3,7 +3,7 @@
An online certificate authority and related tools for secure automated certificate management, so you can use TLS everywhere. An online certificate authority and related tools for secure automated certificate management, so you can use TLS everywhere.
[Website](https://smallstep.com) | [Website](https://smallstep.com) |
[Documentation](https://smallstep.com/docs/certificates) | [Documentation](#documentation) |
[Installation Guide](#installation-guide) | [Installation Guide](#installation-guide) |
[Getting Started](./docs/GETTING_STARTED.md) | [Getting Started](./docs/GETTING_STARTED.md) |
[Contribution Guide](./docs/CONTRIBUTING.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) [![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) [![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 ## Motivation
@ -37,7 +37,7 @@ operate DNS and reverse proxies, you know how to operate mTLS
infrastructure. infrastructure.
![Connect it all with ![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 There's just one problem: **you need certificates issued by your own
certificate authority (CA)**. Building and operating a CA, issuing certificate authority (CA)**. Building and operating a CA, issuing
@ -321,13 +321,17 @@ and best practices on running Step CA in production.
## Documentation ## 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 ## The Future

View file

@ -21,7 +21,7 @@ metadata:
data: data:
config.yaml: | config.yaml: |
logFormat: json # or text logFormat: json # or text
restrictCertificatesToNamespace: true restrictCertificatesToNamespace: false
clusterDomain: cluster.local clusterDomain: cluster.local
caUrl: https://ca.step.svc.cluster.local caUrl: https://ca.step.svc.cluster.local
certLifetime: 24h certLifetime: 24h

View file

@ -3,6 +3,7 @@ package ca
import ( import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"log"
"net/http" "net/http"
"github.com/go-chi/chi" "github.com/go-chi/chi"
@ -123,7 +124,7 @@ func (ca *CA) Run() error {
func (ca *CA) Stop() error { func (ca *CA) Stop() error {
ca.renewer.Stop() ca.renewer.Stop()
if err := ca.auth.Shutdown(); err != nil { if err := ca.auth.Shutdown(); err != nil {
return err log.Printf("error stopping ca.Authority: %+v\n", err)
} }
return ca.srv.Shutdown() 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 // Reload reloads the configuration of the CA and calls to the server Reload
// method. // method.
func (ca *CA) Reload() error { func (ca *CA) Reload() error {
var hasDB bool
if ca.config.DB != nil {
hasDB = true
}
if ca.opts.configFile == "" { if ca.opts.configFile == "" {
return errors.New("error reloading ca: configuration file is not set") return errors.New("error reloading ca: configuration file is not set")
} }
config, err := authority.LoadConfiguration(ca.opts.configFile) config, err := authority.LoadConfiguration(ca.opts.configFile)
if err != nil { 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)) newCA, err := New(config, WithPassword(ca.opts.password), WithConfigFile(ca.opts.configFile))
if err != nil { 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 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 // getTLSConfig returns a TLSConfig for the CA server with a self-renewing

View file

@ -3,7 +3,6 @@ package db
import ( import (
"crypto/x509" "crypto/x509"
"encoding/json" "encoding/json"
"strings"
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -22,7 +21,9 @@ var ErrAlreadyExists = errors.New("already exists")
// Config represents the JSON attributes used for configuring a step-ca DB. // Config represents the JSON attributes used for configuring a step-ca DB.
type Config struct { type Config struct {
Type string `json:"type"` Type string `json:"type"`
Path string `json:"path"` 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. // 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. // DB is a wrapper over the nosql.DB interface.
type DB struct { type DB struct {
nosql.DB nosql.DB
isUp bool
} }
// New returns a new database client that implements the AuthDB interface. // 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 return new(NoopDB), nil
} }
var db nosql.DB db, err := nosql.New(c.Type, c.DataSource, nosql.WithDatabase(c.Database),
switch strings.ToLower(c.Type) { nosql.WithValueDir(c.ValueDir))
case "bbolt": if err != nil {
db = &nosql.BoltDB{} return nil, errors.Wrapf(err, "Error opening database of Type %s with source %s", c.Type, c.DataSource)
if err := db.Open(c.Path); err != nil {
return nil, err
}
default:
return nil, errors.Errorf("unsupported db.type '%s'", c.Type)
} }
tables := [][]byte{revokedCertsTable, certsTable} 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 // 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. // Shutdown sends a shutdown message to the database.
func (db *DB) Shutdown() error { func (db *DB) Shutdown() error {
if db.isUp {
if err := db.Close(); err != nil { if err := db.Close(); err != nil {
return errors.Wrap(err, "database shutdown error") return errors.Wrap(err, "database shutdown error")
} }
db.isUp = false
}
return nil return nil
} }

View file

@ -5,7 +5,7 @@ import (
"testing" "testing"
"github.com/smallstep/assert" "github.com/smallstep/assert"
"github.com/smallstep/nosql" "github.com/smallstep/nosql/database"
) )
type MockNoSQLDB struct { type MockNoSQLDB struct {
@ -13,13 +13,13 @@ type MockNoSQLDB struct {
ret1, ret2 interface{} ret1, ret2 interface{}
get func(bucket, key []byte) ([]byte, error) get func(bucket, key []byte) ([]byte, error)
set func(bucket, key, value []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 close func() error
createTable func(bucket []byte) error createTable func(bucket []byte) error
deleteTable func(bucket []byte) error deleteTable func(bucket []byte) error
del func(bucket, key []byte) error del func(bucket, key []byte) error
list func(bucket []byte) ([]*nosql.Entry, error) list func(bucket []byte) ([]*database.Entry, error)
update func(tx *nosql.Tx) error update func(tx *database.Tx) error
} }
func (m *MockNoSQLDB) Get(bucket, key []byte) ([]byte, 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 return m.err
} }
func (m *MockNoSQLDB) Open(path string) error { func (m *MockNoSQLDB) Open(dataSourceName string, opt ...database.Option) error {
if m.open != nil { if m.open != nil {
return m.open(path) return m.open(dataSourceName, opt...)
} }
return m.err return m.err
} }
@ -74,14 +74,14 @@ func (m *MockNoSQLDB) Del(bucket, key []byte) error {
return m.err 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 { if m.list != nil {
return m.list(bucket) 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 { if m.update != nil {
return m.update(tx) return m.update(tx)
} }
@ -100,16 +100,16 @@ func TestIsRevoked(t *testing.T) {
}, },
"false/ErrNotFound": { "false/ErrNotFound": {
key: "sn", key: "sn",
db: &DB{&MockNoSQLDB{err: nosql.ErrNotFound, ret1: nil}}, db: &DB{&MockNoSQLDB{err: database.ErrNotFound, ret1: nil}, true},
}, },
"error/checking bucket": { "error/checking bucket": {
key: "sn", 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"), err: errors.New("error checking revocation bucket: force"),
}, },
"true": { "true": {
key: "sn", key: "sn",
db: &DB{&MockNoSQLDB{ret1: []byte("value")}}, db: &DB{&MockNoSQLDB{ret1: []byte("value")}, true},
isRevoked: true, isRevoked: true,
}, },
} }
@ -140,7 +140,7 @@ func TestRevoke(t *testing.T) {
get: func(bucket []byte, sn []byte) ([]byte, error) { get: func(bucket []byte, sn []byte) ([]byte, error) {
return nil, errors.New("force IsRevoked") return nil, errors.New("force IsRevoked")
}, },
}}, }, true},
err: errors.New("error checking revocation bucket: force IsRevoked"), err: errors.New("error checking revocation bucket: force IsRevoked"),
}, },
"error/was already revoked": { "error/was already revoked": {
@ -149,31 +149,31 @@ func TestRevoke(t *testing.T) {
get: func(bucket []byte, sn []byte) ([]byte, error) { get: func(bucket []byte, sn []byte) ([]byte, error) {
return nil, nil return nil, nil
}, },
}}, }, true},
err: ErrAlreadyExists, err: ErrAlreadyExists,
}, },
"error/database set": { "error/database set": {
rci: &RevokedCertificateInfo{Serial: "sn"}, rci: &RevokedCertificateInfo{Serial: "sn"},
db: &DB{&MockNoSQLDB{ db: &DB{&MockNoSQLDB{
get: func(bucket []byte, sn []byte) ([]byte, error) { 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 { set: func(bucket []byte, key []byte, value []byte) error {
return errors.New("force") return errors.New("force")
}, },
}}, }, true},
err: errors.New("database Set error: force"), err: errors.New("database Set error: force"),
}, },
"ok": { "ok": {
rci: &RevokedCertificateInfo{Serial: "sn"}, rci: &RevokedCertificateInfo{Serial: "sn"},
db: &DB{&MockNoSQLDB{ db: &DB{&MockNoSQLDB{
get: func(bucket []byte, sn []byte) ([]byte, error) { 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 { set: func(bucket []byte, key []byte, value []byte) error {
return nil return nil
}, },
}}, }, true},
}, },
} }
for name, tc := range tests { for name, tc := range tests {

View file

@ -95,7 +95,7 @@ e.g. `v1.0.2`
6. **Update the AUR Arch Linux package** 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 $ cd archlinux

View file

@ -102,9 +102,23 @@ and respond to requests.
* `dnsNames`: comma separated list of DNS Name(s) for the CA. * `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`. 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 * `tls`: settings for negotiating communication with the CA; includes acceptable
ciphersuites, min/max TLS version, etc. 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 ## 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 ```bash
$ step ca init $ 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 Navigate to the Google APIs developer console and pick a suitable project from the
top navbar's dropdown. 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 In the masthead navigation click **Credentials** (key symbol) and then "OAuth
consent screen" from the subnav. Fill out naming details, all mandatory fields, 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** **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**). 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 On successful completion, a confirmation modal with both `clientID` and
`clientSecret` will be presented. Please note that the `clientSecret` will `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 will not allow direct authentication of users without their own MfA credentials
per account. per account.
![OIDC credentials](oidc3.png) ![OIDC credentials](./images/oidc3.png)
Now using `clientID` and `clientSecret` run the following command to add Now using `clientID` and `clientSecret` run the following command to add
G-Suite as a provisioner to `step certificates`. Please see [`step ca G-Suite as a provisioner to `step certificates`. Please see [`step ca

40
docs/README.md Normal file
View file

@ -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)

95
docs/database.md Normal file
View file

@ -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.

228
docs/defaults.md Normal file
View file

@ -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.

View file

Before

Width:  |  Height:  |  Size: 572 KiB

After

Width:  |  Height:  |  Size: 572 KiB

View file

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View file

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View file

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View file

Before

Width:  |  Height:  |  Size: 6.2 MiB

After

Width:  |  Height:  |  Size: 6.2 MiB

View file

Before

Width:  |  Height:  |  Size: 9.5 MiB

After

Width:  |  Height:  |  Size: 9.5 MiB

View file

@ -1,11 +1,16 @@
# Commonly Asked Questions # Frequently Asked Questions
These are some commonly asked questions on the topics of PKI, TLS, X509, These are some commonly asked questions on the topics of PKI, TLS, X509,
cryptography, threshold-cryptography, etc. 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. 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 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. 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 TLS is a complicated protocol with lots of options, but the most common mode of
operation establishes a secure channel using *asymmetric cryptography* with 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 * *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 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 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 between names and public keys). Without proper secure PKI, an attacker can fake
a binding and undermine security. 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 A certificate authority (CA) stores, issues, and signs digital certificates. CAs
have their own key pair, with the private key carefully secured (often offline). 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 It also acts as a *central directory* and more generally as a *certificate
management system*, a secure location for storing and distributing key material. 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, 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 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 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. web PKI design decisions aren't appropriate for internal systems.
#### How does identity proofing work? ## 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.
In general, trust will always flow back out to you, the operator of your system. 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 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 start with a manual identity proofing mechanism and move to a more sophisticated
automated method as your system grows. 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]. 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)

View file

@ -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

210
docs/revocation.md Normal file
View file

@ -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`.
<pre><code>
<b>$ step ca init --name "Local CA" --provisioner admin --dns localhost --address ":443"</b>
</code></pre>
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": "<full step path>/db"
},
...
```
Check out our [database documentation](./database.md) to see all available
database backends and adapters.
3. Run the CA
<pre><code>
<b>$ step-ca $(step path)/config/ca.json</b>
</code></pre>
4. Create a certificate for localhost
<pre><code>
<b>$ step ca certificate localhost localhost.crt localhost.key</b>
✔ 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
<b>$ step certificate inspect --short localhost.crt</b>
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
</code></pre>
5. Renew the certificate (just to prove we can!)
<pre><code>
<b>$ step ca renew localhost.crt localhost.key</b>
✔ 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"
<b>$ step certificate inspect --short localhost.crt</b>
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
</pre></code>
6. Now let's revoke the certificate
<pre><code>
<b>$ step certificate inspect --format=json localhost.crt | jq .serial_number</b>
"59636004850364466675608080466579278406"
# the serial number is unique
<b>$ step ca revoke 59636004850364466675608080466579278406</b>
✔ 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.
</pre></code>
7. Awesome! But did it work?
<pre><code>
<b>$ step ca renew localhost.crt localhost.key</b>
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=
[...]
</pre></code>
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.
<pre><code>
<b>$ step ca revoke --cert localhost.crt --key localhost.key</b>
Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
</pre></code>
Or, revoke a certificate in two steps by first creating a revocation token and
then exchanging that token in a revocation request.
<pre><code>
<b>$ TOKEN=$(step ca token --revoke 59636004850364466675608080466579278406)</b>
✔ Key ID: n2kqNhicCCqVxJidspCQrjXWBtGwsa9zk3eBObrViy8 (sebastian@smallstep.com)
✔ Please enter the password to decrypt the provisioner key:
<b>$ echo $TOKEN | step crypto jwt inspect --insecure</b>
{
"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"
}
<b>$ step ca revoke --token $TOKEN 59636004850364466675608080466579278406</b>
Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
</pre></code>
Or, revoke a certificate in offline mode:
<pre><code>
<b>$ step ca revoke --offline 59636004850364466675608080466579278406</b>
Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
<b>$ step ca revoke --offline --cert localhost.crt --key localhost.key</b>
Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
</pre></code>
> 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)