Skip to content

Commit 7b5d696

Browse files
committed
first commit
1 parent f84c8f8 commit 7b5d696

35 files changed

+2032
-212
lines changed

Diff for: acme/db/nosql/nosql.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ var (
2323

2424
// DB is a struct that implements the AcmeDB interface.
2525
type DB struct {
26-
db nosqlDB.DB
26+
db nosqlDB.DB
27+
authorityID string
2728
}
2829

2930
// New configures and returns a new ACME DB backend implemented using a nosql DB.
30-
func New(db nosqlDB.DB) (*DB, error) {
31+
func New(db nosqlDB.DB, authorityID string) (*DB, error) {
3132
tables := [][]byte{accountTable, accountByKeyIDTable, authzTable,
3233
challengeTable, nonceTable, orderTable, ordersByAccountIDTable, certTable}
3334
for _, b := range tables {
@@ -36,7 +37,7 @@ func New(db nosqlDB.DB) (*DB, error) {
3637
string(b))
3738
}
3839
}
39-
return &DB{db}, nil
40+
return &DB{db, authorityID}, nil
4041
}
4142

4243
// save writes the new data to the database, overwriting the old data if it

Diff for: api/api.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/go-chi/chi"
2222
"github.com/pkg/errors"
2323
"github.com/smallstep/certificates/authority"
24+
"github.com/smallstep/certificates/authority/config"
2425
"github.com/smallstep/certificates/authority/provisioner"
2526
"github.com/smallstep/certificates/errs"
2627
"github.com/smallstep/certificates/logging"
@@ -32,7 +33,7 @@ type Authority interface {
3233
// context specifies the Authorize[Sign|Revoke|etc.] method.
3334
Authorize(ctx context.Context, ott string) ([]provisioner.SignOption, error)
3435
AuthorizeSign(ott string) ([]provisioner.SignOption, error)
35-
GetTLSOptions() *authority.TLSOptions
36+
GetTLSOptions() *config.TLSOptions
3637
Root(shasum string) (*x509.Certificate, error)
3738
Sign(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
3839
Renew(peer *x509.Certificate) ([]*x509.Certificate, error)

Diff for: api/sign.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"encoding/json"
66
"net/http"
77

8-
"github.com/smallstep/certificates/authority"
8+
"github.com/smallstep/certificates/authority/config"
99
"github.com/smallstep/certificates/authority/provisioner"
1010
"github.com/smallstep/certificates/errs"
1111
)
@@ -37,11 +37,11 @@ func (s *SignRequest) Validate() error {
3737

3838
// SignResponse is the response object of the certificate signature request.
3939
type SignResponse struct {
40-
ServerPEM Certificate `json:"crt"`
41-
CaPEM Certificate `json:"ca"`
42-
CertChainPEM []Certificate `json:"certChain"`
43-
TLSOptions *authority.TLSOptions `json:"tlsOptions,omitempty"`
44-
TLS *tls.ConnectionState `json:"-"`
40+
ServerPEM Certificate `json:"crt"`
41+
CaPEM Certificate `json:"ca"`
42+
CertChainPEM []Certificate `json:"certChain"`
43+
TLSOptions *config.TLSOptions `json:"tlsOptions,omitempty"`
44+
TLS *tls.ConnectionState `json:"-"`
4545
}
4646

4747
// Sign is an HTTP handler that reads a certificate request and an

Diff for: api/ssh.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/pkg/errors"
1212
"github.com/smallstep/certificates/authority"
13+
"github.com/smallstep/certificates/authority/config"
1314
"github.com/smallstep/certificates/authority/provisioner"
1415
"github.com/smallstep/certificates/errs"
1516
"github.com/smallstep/certificates/templates"
@@ -22,12 +23,12 @@ type SSHAuthority interface {
2223
RenewSSH(ctx context.Context, cert *ssh.Certificate) (*ssh.Certificate, error)
2324
RekeySSH(ctx context.Context, cert *ssh.Certificate, key ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, error)
2425
SignSSHAddUser(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error)
25-
GetSSHRoots(ctx context.Context) (*authority.SSHKeys, error)
26-
GetSSHFederation(ctx context.Context) (*authority.SSHKeys, error)
26+
GetSSHRoots(ctx context.Context) (*config.SSHKeys, error)
27+
GetSSHFederation(ctx context.Context) (*config.SSHKeys, error)
2728
GetSSHConfig(ctx context.Context, typ string, data map[string]string) ([]templates.Output, error)
2829
CheckSSHHost(ctx context.Context, principal string, token string) (bool, error)
29-
GetSSHHosts(ctx context.Context, cert *x509.Certificate) ([]authority.Host, error)
30-
GetSSHBastion(ctx context.Context, user string, hostname string) (*authority.Bastion, error)
30+
GetSSHHosts(ctx context.Context, cert *x509.Certificate) ([]config.Host, error)
31+
GetSSHBastion(ctx context.Context, user string, hostname string) (*config.Bastion, error)
3132
}
3233

3334
// SSHSignRequest is the request body of an SSH certificate request.
@@ -86,7 +87,7 @@ type SSHCertificate struct {
8687
// SSHGetHostsResponse is the response object that returns the list of valid
8788
// hosts for SSH.
8889
type SSHGetHostsResponse struct {
89-
Hosts []authority.Host `json:"hosts"`
90+
Hosts []config.Host `json:"hosts"`
9091
}
9192

9293
// MarshalJSON implements the json.Marshaler interface. Returns a quoted,
@@ -239,8 +240,8 @@ func (r *SSHBastionRequest) Validate() error {
239240
// SSHBastionResponse is the response body used to return the bastion for a
240241
// given host.
241242
type SSHBastionResponse struct {
242-
Hostname string `json:"hostname"`
243-
Bastion *authority.Bastion `json:"bastion,omitempty"`
243+
Hostname string `json:"hostname"`
244+
Bastion *config.Bastion `json:"bastion,omitempty"`
244245
}
245246

246247
// SSHSign is an HTTP handler that reads an SignSSHRequest with a one-time-token

Diff for: authority/admin.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package authority
2+
3+
// Admin is the type definining Authority admins. Admins can update Authority
4+
// configuration, provisioners, and even other admins.
5+
type Admin struct {
6+
ID string `json:"-"`
7+
AuthorityID string `json:"-"`
8+
Name string `json:"name"`
9+
Provisioner string `json:"provisioner"`
10+
IsSuperAdmin bool `json:"isSuperAdmin"`
11+
IsDeleted bool `json:"isDeleted"`
12+
}

Diff for: authority/authority.go

+29-12
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,25 @@ import (
1313
"github.com/smallstep/certificates/cas"
1414

1515
"github.com/pkg/errors"
16+
"github.com/smallstep/certificates/authority/config"
17+
"github.com/smallstep/certificates/authority/mgmt"
18+
authMgmtNosql "github.com/smallstep/certificates/authority/mgmt/db/nosql"
1619
"github.com/smallstep/certificates/authority/provisioner"
1720
casapi "github.com/smallstep/certificates/cas/apiv1"
1821
"github.com/smallstep/certificates/db"
1922
"github.com/smallstep/certificates/kms"
2023
kmsapi "github.com/smallstep/certificates/kms/apiv1"
2124
"github.com/smallstep/certificates/kms/sshagentkms"
2225
"github.com/smallstep/certificates/templates"
26+
"github.com/smallstep/nosql"
2327
"go.step.sm/crypto/pemutil"
2428
"golang.org/x/crypto/ssh"
2529
)
2630

27-
const (
28-
legacyAuthority = "step-certificate-authority"
29-
)
30-
3131
// Authority implements the Certificate Authority internal interface.
3232
type Authority struct {
33-
config *Config
33+
config *config.Config
34+
mgmtDB *mgmt.DB
3435
keyManager kms.KeyManager
3536
provisioners *provisioner.Collection
3637
db db.AuthDB
@@ -55,14 +56,14 @@ type Authority struct {
5556
startTime time.Time
5657

5758
// Custom functions
58-
sshBastionFunc func(ctx context.Context, user, hostname string) (*Bastion, error)
59+
sshBastionFunc func(ctx context.Context, user, hostname string) (*config.Bastion, error)
5960
sshCheckHostFunc func(ctx context.Context, principal string, tok string, roots []*x509.Certificate) (bool, error)
60-
sshGetHostsFunc func(ctx context.Context, cert *x509.Certificate) ([]Host, error)
61+
sshGetHostsFunc func(ctx context.Context, cert *x509.Certificate) ([]config.Host, error)
6162
getIdentityFunc provisioner.GetIdentityFunc
6263
}
6364

6465
// New creates and initiates a new Authority type.
65-
func New(config *Config, opts ...Option) (*Authority, error) {
66+
func New(config *config.Config, opts ...Option) (*Authority, error) {
6667
err := config.Validate()
6768
if err != nil {
6869
return nil, err
@@ -92,7 +93,7 @@ func New(config *Config, opts ...Option) (*Authority, error) {
9293
// project without the limitations of the config.
9394
func NewEmbedded(opts ...Option) (*Authority, error) {
9495
a := &Authority{
95-
config: &Config{},
96+
config: &config.Config{},
9697
certificates: new(sync.Map),
9798
}
9899

@@ -116,7 +117,7 @@ func NewEmbedded(opts ...Option) (*Authority, error) {
116117
}
117118

118119
// Initialize config required fields.
119-
a.config.init()
120+
a.config.Init()
120121

121122
// Initialize authority from options or configuration.
122123
if err := a.init(); err != nil {
@@ -143,6 +144,22 @@ func (a *Authority) init() error {
143144
}
144145
}
145146

147+
// Pull AuthConfig from DB.
148+
if true {
149+
mgmtDB, err := authMgmtNosql.New(a.db.(nosql.DB), mgmt.DefaultAuthorityID)
150+
if err != nil {
151+
return err
152+
}
153+
_ac, err := mgmtDB.GetAuthConfig(context.Background(), mgmt.DefaultAuthorityID)
154+
if err != nil {
155+
return err
156+
}
157+
a.config.AuthorityConfig, err = _ac.ToCertificates()
158+
if err != nil {
159+
return err
160+
}
161+
}
162+
146163
// Initialize key manager if it has not been set in the options.
147164
if a.keyManager == nil {
148165
var options kmsapi.Options
@@ -314,7 +331,7 @@ func (a *Authority) init() error {
314331
}
315332

316333
// Merge global and configuration claims
317-
claimer, err := provisioner.NewClaimer(a.config.AuthorityConfig.Claims, globalProvisionerClaims)
334+
claimer, err := provisioner.NewClaimer(a.config.AuthorityConfig.Claims, config.GlobalProvisionerClaims)
318335
if err != nil {
319336
return err
320337
}
@@ -326,7 +343,7 @@ func (a *Authority) init() error {
326343
return err
327344
}
328345
// Initialize provisioners
329-
audiences := a.config.getAudiences()
346+
audiences := a.config.GetAudiences()
330347
a.provisioners = provisioner.NewCollection(audiences)
331348
config := provisioner.Config{
332349
Claims: claimer.Claims(),

Diff for: authority/config.go renamed to authority/config/config.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package authority
1+
package config
22

33
import (
44
"encoding/json"
@@ -15,6 +15,10 @@ import (
1515
"github.com/smallstep/certificates/templates"
1616
)
1717

18+
const (
19+
legacyAuthority = "step-certificate-authority"
20+
)
21+
1822
var (
1923
// DefaultTLSOptions represents the default TLS version as well as the cipher
2024
// suites used in the TLS certificates.
@@ -28,10 +32,12 @@ var (
2832
MaxVersion: 1.2,
2933
Renegotiation: false,
3034
}
31-
defaultBackdate = time.Minute
32-
defaultDisableRenewal = false
33-
defaultEnableSSHCA = false
34-
globalProvisionerClaims = provisioner.Claims{
35+
defaultBackdate = time.Minute
36+
defaultDisableRenewal = false
37+
defaultEnableSSHCA = false
38+
// GlobalProvisionerClaims default claims for the Authority. Can be overriden
39+
// by provisioner specific claims.
40+
GlobalProvisionerClaims = provisioner.Claims{
3541
MinTLSDur: &provisioner.Duration{Duration: 5 * time.Minute}, // TLS certs
3642
MaxTLSDur: &provisioner.Duration{Duration: 24 * time.Hour},
3743
DefaultTLSDur: &provisioner.Duration{Duration: 24 * time.Hour},
@@ -151,9 +157,9 @@ func LoadConfiguration(filename string) (*Config, error) {
151157
return &c, nil
152158
}
153159

154-
// initializes the minimal configuration required to create an authority. This
160+
// Init initializes the minimal configuration required to create an authority. This
155161
// is mainly used on embedded authorities.
156-
func (c *Config) init() {
162+
func (c *Config) Init() {
157163
if c.DNSNames == nil {
158164
c.DNSNames = []string{"localhost", "127.0.0.1", "::1"}
159165
}
@@ -246,13 +252,13 @@ func (c *Config) Validate() error {
246252
return err
247253
}
248254

249-
return c.AuthorityConfig.Validate(c.getAudiences())
255+
return c.AuthorityConfig.Validate(c.GetAudiences())
250256
}
251257

252-
// getAudiences returns the legacy and possible urls without the ports that will
258+
// GetAudiences returns the legacy and possible urls without the ports that will
253259
// be used as the default provisioner audiences. The CA might have proxies in
254260
// front so we cannot rely on the port.
255-
func (c *Config) getAudiences() provisioner.Audiences {
261+
func (c *Config) GetAudiences() provisioner.Audiences {
256262
audiences := provisioner.Audiences{
257263
Sign: []string{legacyAuthority},
258264
Revoke: []string{legacyAuthority},

Diff for: authority/config_test.go renamed to authority/config/config_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package authority
1+
package config
22

33
import (
44
"fmt"

Diff for: authority/config/ssh.go

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package config
2+
3+
import (
4+
"github.com/pkg/errors"
5+
"github.com/smallstep/certificates/authority/provisioner"
6+
"go.step.sm/crypto/jose"
7+
"golang.org/x/crypto/ssh"
8+
)
9+
10+
// SSHConfig contains the user and host keys.
11+
type SSHConfig struct {
12+
HostKey string `json:"hostKey"`
13+
UserKey string `json:"userKey"`
14+
Keys []*SSHPublicKey `json:"keys,omitempty"`
15+
AddUserPrincipal string `json:"addUserPrincipal,omitempty"`
16+
AddUserCommand string `json:"addUserCommand,omitempty"`
17+
Bastion *Bastion `json:"bastion,omitempty"`
18+
}
19+
20+
// Bastion contains the custom properties used on bastion.
21+
type Bastion struct {
22+
Hostname string `json:"hostname"`
23+
User string `json:"user,omitempty"`
24+
Port string `json:"port,omitempty"`
25+
Command string `json:"cmd,omitempty"`
26+
Flags string `json:"flags,omitempty"`
27+
}
28+
29+
// HostTag are tagged with k,v pairs. These tags are how a user is ultimately
30+
// associated with a host.
31+
type HostTag struct {
32+
ID string
33+
Name string
34+
Value string
35+
}
36+
37+
// Host defines expected attributes for an ssh host.
38+
type Host struct {
39+
HostID string `json:"hid"`
40+
HostTags []HostTag `json:"host_tags"`
41+
Hostname string `json:"hostname"`
42+
}
43+
44+
// Validate checks the fields in SSHConfig.
45+
func (c *SSHConfig) Validate() error {
46+
if c == nil {
47+
return nil
48+
}
49+
for _, k := range c.Keys {
50+
if err := k.Validate(); err != nil {
51+
return err
52+
}
53+
}
54+
return nil
55+
}
56+
57+
// SSHPublicKey contains a public key used by federated CAs to keep old signing
58+
// keys for this ca.
59+
type SSHPublicKey struct {
60+
Type string `json:"type"`
61+
Federated bool `json:"federated"`
62+
Key jose.JSONWebKey `json:"key"`
63+
publicKey ssh.PublicKey
64+
}
65+
66+
// Validate checks the fields in SSHPublicKey.
67+
func (k *SSHPublicKey) Validate() error {
68+
switch {
69+
case k.Type == "":
70+
return errors.New("type cannot be empty")
71+
case k.Type != provisioner.SSHHostCert && k.Type != provisioner.SSHUserCert:
72+
return errors.Errorf("invalid type %s, it must be user or host", k.Type)
73+
case !k.Key.IsPublic():
74+
return errors.New("invalid key type, it must be a public key")
75+
}
76+
77+
key, err := ssh.NewPublicKey(k.Key.Key)
78+
if err != nil {
79+
return errors.Wrap(err, "error creating ssh key")
80+
}
81+
k.publicKey = key
82+
return nil
83+
}
84+
85+
// PublicKey returns the ssh public key.
86+
func (k *SSHPublicKey) PublicKey() ssh.PublicKey {
87+
return k.publicKey
88+
}
89+
90+
// SSHKeys represents the SSH User and Host public keys.
91+
type SSHKeys struct {
92+
UserKeys []ssh.PublicKey
93+
HostKeys []ssh.PublicKey
94+
}

0 commit comments

Comments
 (0)