Merge branch 'master' into cloud-identities
91
Gopkg.lock
generated
|
@ -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",
|
||||||
|
|
18
README.md
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
50
ca/ca.go
|
@ -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
|
||||||
|
|
24
db/db.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
|
@ -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
|
@ -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
|
@ -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
|
@ -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.
|
Before Width: | Height: | Size: 572 KiB After Width: | Height: | Size: 572 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 6.2 MiB After Width: | Height: | Size: 6.2 MiB |
Before Width: | Height: | Size: 9.5 MiB After Width: | Height: | Size: 9.5 MiB |
|
@ -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)
|
|
@ -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
|
@ -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)
|