-
Notifications
You must be signed in to change notification settings - Fork 413
/
options.go
183 lines (164 loc) · 5.09 KB
/
options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package authority
import (
"context"
"crypto"
"crypto/x509"
"encoding/pem"
"github.com/pkg/errors"
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/db"
"github.com/smallstep/certificates/kms"
"github.com/smallstep/certificates/sshutil"
"golang.org/x/crypto/ssh"
)
// Option sets options to the Authority.
type Option func(*Authority) error
// WithDatabase sets an already initialized authority database to a new
// authority. This option is intended to be use on graceful reloads.
func WithDatabase(db db.AuthDB) Option {
return func(a *Authority) error {
a.db = db
return nil
}
}
// WithGetIdentityFunc sets a custom function to retrieve the identity from
// an external resource.
func WithGetIdentityFunc(fn func(p provisioner.Interface, email string) (*provisioner.Identity, error)) Option {
return func(a *Authority) error {
a.getIdentityFunc = fn
return nil
}
}
// WithSSHBastionFunc sets a custom function to get the bastion for a
// given user-host pair.
func WithSSHBastionFunc(fn func(user, host string) (*Bastion, error)) Option {
return func(a *Authority) error {
a.sshBastionFunc = fn
return nil
}
}
// WithSSHGetHosts sets a custom function to get the bastion for a
// given user-host pair.
func WithSSHGetHosts(fn func(cert *x509.Certificate) ([]sshutil.Host, error)) Option {
return func(a *Authority) error {
a.sshGetHostsFunc = fn
return nil
}
}
// WithSSHCheckHost sets a custom function to check whether a given host is
// step ssh enabled. The token is used to validate the request, while the roots
// are used to validate the token.
func WithSSHCheckHost(fn func(ctx context.Context, principal string, tok string, roots []*x509.Certificate) (bool, error)) Option {
return func(a *Authority) error {
a.sshCheckHostFunc = fn
return nil
}
}
// WithKeyManager defines the key manager used to get and create keys, and sign
// certificates.
func WithKeyManager(k kms.KeyManager) Option {
return func(a *Authority) error {
a.keyManager = k
return nil
}
}
// WithX509Signer defines the signer used to sign X509 certificates.
func WithX509Signer(crt *x509.Certificate, s crypto.Signer) Option {
return func(a *Authority) error {
a.x509Issuer = crt
a.x509Signer = s
return nil
}
}
// WithSSHUserSigner defines the signer used to sign SSH user certificates.
func WithSSHUserSigner(s crypto.Signer) Option {
return func(a *Authority) error {
signer, err := ssh.NewSignerFromSigner(s)
if err != nil {
return errors.Wrap(err, "error creating ssh user signer")
}
a.sshCAUserCertSignKey = signer
// Append public key to list of user certs
pub := signer.PublicKey()
a.sshCAUserCerts = append(a.sshCAUserCerts, pub)
a.sshCAUserFederatedCerts = append(a.sshCAUserFederatedCerts, pub)
return nil
}
}
// WithSSHHostSigner defines the signer used to sign SSH host certificates.
func WithSSHHostSigner(s crypto.Signer) Option {
return func(a *Authority) error {
signer, err := ssh.NewSignerFromSigner(s)
if err != nil {
return errors.Wrap(err, "error creating ssh host signer")
}
a.sshCAHostCertSignKey = signer
// Append public key to list of host certs
pub := signer.PublicKey()
a.sshCAHostCerts = append(a.sshCAHostCerts, pub)
a.sshCAHostFederatedCerts = append(a.sshCAHostFederatedCerts, pub)
return nil
}
}
// WithX509RootCerts is an option that allows to define the list of root
// certificates to use. This option will replace any root certificate defined
// before.
func WithX509RootCerts(rootCerts ...*x509.Certificate) Option {
return func(a *Authority) error {
a.rootX509Certs = rootCerts
return nil
}
}
// WithX509FederatedCerts is an option that allows to define the list of
// federated certificates. This option will replace any federated certificate
// defined before.
func WithX509FederatedCerts(certs ...*x509.Certificate) Option {
return func(a *Authority) error {
a.federatedX509Certs = certs
return nil
}
}
// WithX509RootBundle is an option that allows to define the list of root
// certificates. This option will replace any root certificate defined before.
func WithX509RootBundle(pemCerts []byte) Option {
return func(a *Authority) error {
certs, err := readCertificateBundle(pemCerts)
if err != nil {
return err
}
a.rootX509Certs = certs
return nil
}
}
// WithX509FederatedBundle is an option that allows to define the list of
// federated certificates. This option will replace any federated certificate
// defined before.
func WithX509FederatedBundle(pemCerts []byte) Option {
return func(a *Authority) error {
certs, err := readCertificateBundle(pemCerts)
if err != nil {
return err
}
a.federatedX509Certs = certs
return nil
}
}
func readCertificateBundle(pemCerts []byte) ([]*x509.Certificate, error) {
var block *pem.Block
var certs []*x509.Certificate
for len(pemCerts) > 0 {
block, pemCerts = pem.Decode(pemCerts)
if block == nil {
break
}
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
continue
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, err
}
certs = append(certs, cert)
}
return certs, nil
}