File: common.go

package info (click to toggle)
golang-github-smallstep-certificates 0.28.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,684 kB
  • sloc: sh: 367; makefile: 129
file content (202 lines) | stat: -rw-r--r-- 6,687 bytes parent folder | download | duplicates (2)
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package acme

import (
	"context"
	"crypto/x509"
	"time"

	"github.com/smallstep/certificates/authority"
	"github.com/smallstep/certificates/authority/provisioner"
)

// Clock that returns time in UTC rounded to seconds.
type Clock struct{}

// Now returns the UTC time rounded to seconds.
func (c *Clock) Now() time.Time {
	return time.Now().UTC().Truncate(time.Second)
}

var clock Clock

// CertificateAuthority is the interface implemented by a CA authority.
type CertificateAuthority interface {
	SignWithContext(ctx context.Context, cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error)
	AreSANsAllowed(ctx context.Context, sans []string) error
	IsRevoked(sn string) (bool, error)
	Revoke(context.Context, *authority.RevokeOptions) error
	LoadProvisionerByName(string) (provisioner.Interface, error)
}

// NewContext adds the given acme components to the context.
func NewContext(ctx context.Context, db DB, client Client, linker Linker, fn PrerequisitesChecker) context.Context {
	ctx = NewDatabaseContext(ctx, db)
	ctx = NewClientContext(ctx, client)
	ctx = NewLinkerContext(ctx, linker)
	// Prerequisite checker is optional.
	if fn != nil {
		ctx = NewPrerequisitesCheckerContext(ctx, fn)
	}
	return ctx
}

// PrerequisitesChecker is a function that checks if all prerequisites for
// serving ACME are met by the CA configuration.
type PrerequisitesChecker func(ctx context.Context) (bool, error)

// DefaultPrerequisitesChecker is the default PrerequisiteChecker and returns
// always true.
func DefaultPrerequisitesChecker(context.Context) (bool, error) {
	return true, nil
}

type prerequisitesKey struct{}

// NewPrerequisitesCheckerContext adds the given PrerequisitesChecker to the
// context.
func NewPrerequisitesCheckerContext(ctx context.Context, fn PrerequisitesChecker) context.Context {
	return context.WithValue(ctx, prerequisitesKey{}, fn)
}

// PrerequisitesCheckerFromContext returns the PrerequisitesChecker in the
// context.
func PrerequisitesCheckerFromContext(ctx context.Context) (PrerequisitesChecker, bool) {
	fn, ok := ctx.Value(prerequisitesKey{}).(PrerequisitesChecker)
	return fn, ok && fn != nil
}

// Provisioner is an interface that implements a subset of the provisioner.Interface --
// only those methods required by the ACME api/authority.
type Provisioner interface {
	AuthorizeOrderIdentifier(ctx context.Context, identifier provisioner.ACMEIdentifier) error
	AuthorizeSign(ctx context.Context, token string) ([]provisioner.SignOption, error)
	AuthorizeRevoke(ctx context.Context, token string) error
	IsChallengeEnabled(ctx context.Context, challenge provisioner.ACMEChallenge) bool
	IsAttestationFormatEnabled(ctx context.Context, format provisioner.ACMEAttestationFormat) bool
	GetAttestationRoots() (*x509.CertPool, bool)
	GetID() string
	GetName() string
	DefaultTLSCertDuration() time.Duration
	GetOptions() *provisioner.Options
}

type provisionerKey struct{}

// NewProvisionerContext adds the given provisioner to the context.
func NewProvisionerContext(ctx context.Context, v Provisioner) context.Context {
	return context.WithValue(ctx, provisionerKey{}, v)
}

// ProvisionerFromContext returns the current provisioner from the given context.
func ProvisionerFromContext(ctx context.Context) (v Provisioner, ok bool) {
	v, ok = ctx.Value(provisionerKey{}).(Provisioner)
	return
}

// MustProvisionerFromContext returns the current provisioner from the given context.
// It will panic if it's not in the context.
func MustProvisionerFromContext(ctx context.Context) Provisioner {
	var (
		v  Provisioner
		ok bool
	)
	if v, ok = ProvisionerFromContext(ctx); !ok {
		panic("acme provisioner is not the context")
	}
	return v
}

// MockProvisioner for testing
type MockProvisioner struct {
	Mret1                     interface{}
	Merr                      error
	MgetID                    func() string
	MgetName                  func() string
	MauthorizeOrderIdentifier func(ctx context.Context, identifier provisioner.ACMEIdentifier) error
	MauthorizeSign            func(ctx context.Context, ott string) ([]provisioner.SignOption, error)
	MauthorizeRevoke          func(ctx context.Context, token string) error
	MisChallengeEnabled       func(ctx context.Context, challenge provisioner.ACMEChallenge) bool
	MisAttFormatEnabled       func(ctx context.Context, format provisioner.ACMEAttestationFormat) bool
	MgetAttestationRoots      func() (*x509.CertPool, bool)
	MdefaultTLSCertDuration   func() time.Duration
	MgetOptions               func() *provisioner.Options
}

// GetName mock
func (m *MockProvisioner) GetName() string {
	if m.MgetName != nil {
		return m.MgetName()
	}
	return m.Mret1.(string)
}

// AuthorizeOrderIdentifier mock
func (m *MockProvisioner) AuthorizeOrderIdentifier(ctx context.Context, identifier provisioner.ACMEIdentifier) error {
	if m.MauthorizeOrderIdentifier != nil {
		return m.MauthorizeOrderIdentifier(ctx, identifier)
	}
	return m.Merr
}

// AuthorizeSign mock
func (m *MockProvisioner) AuthorizeSign(ctx context.Context, ott string) ([]provisioner.SignOption, error) {
	if m.MauthorizeSign != nil {
		return m.MauthorizeSign(ctx, ott)
	}
	return m.Mret1.([]provisioner.SignOption), m.Merr
}

// AuthorizeRevoke mock
func (m *MockProvisioner) AuthorizeRevoke(ctx context.Context, token string) error {
	if m.MauthorizeRevoke != nil {
		return m.MauthorizeRevoke(ctx, token)
	}
	return m.Merr
}

// IsChallengeEnabled mock
func (m *MockProvisioner) IsChallengeEnabled(ctx context.Context, challenge provisioner.ACMEChallenge) bool {
	if m.MisChallengeEnabled != nil {
		return m.MisChallengeEnabled(ctx, challenge)
	}
	return m.Merr == nil
}

// IsAttestationFormatEnabled mock
func (m *MockProvisioner) IsAttestationFormatEnabled(ctx context.Context, format provisioner.ACMEAttestationFormat) bool {
	if m.MisAttFormatEnabled != nil {
		return m.MisAttFormatEnabled(ctx, format)
	}
	return m.Merr == nil
}

func (m *MockProvisioner) GetAttestationRoots() (*x509.CertPool, bool) {
	if m.MgetAttestationRoots != nil {
		return m.MgetAttestationRoots()
	}
	return m.Mret1.(*x509.CertPool), m.Mret1 != nil
}

// DefaultTLSCertDuration mock
func (m *MockProvisioner) DefaultTLSCertDuration() time.Duration {
	if m.MdefaultTLSCertDuration != nil {
		return m.MdefaultTLSCertDuration()
	}
	return m.Mret1.(time.Duration)
}

// GetOptions mock
func (m *MockProvisioner) GetOptions() *provisioner.Options {
	if m.MgetOptions != nil {
		return m.MgetOptions()
	}
	return m.Mret1.(*provisioner.Options)
}

// GetID mock
func (m *MockProvisioner) GetID() string {
	if m.MgetID != nil {
		return m.MgetID()
	}
	return m.Mret1.(string)
}