Skip to content

Commit

Permalink
Merge pull request #114 from smallstep/x5c
Browse files Browse the repository at this point in the history
Add x5c provisioner capabilities
  • Loading branch information
dopey committed Oct 14, 2019
2 parents d123e4d + e107b50 commit f423fdb
Show file tree
Hide file tree
Showing 32 changed files with 1,802 additions and 243 deletions.
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ linters:
- deadcode
- staticcheck
- unused
- gosimple

run:
skip-dirs:
Expand Down
3 changes: 0 additions & 3 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
# non-go = false
# go-tests = true
# unused-packages = true
[[override]]
name = "gopkg.in/alecthomas/kingpin.v3-unstable"
revision = "63abe20a23e29e80bbef8089bd3dee3ac25e5306"

[[constraint]]
branch = "master"
Expand Down
3 changes: 0 additions & 3 deletions acme/api/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ func (h *Handler) NewAccount(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", h.Auth.GetLink(acme.AccountLink,
acme.URLSafeProvisionerName(prov), true, acc.GetID()))
api.JSONStatus(w, acc, httpStatus)
return
}

// GetUpdateAccount is the api for updating an ACME account.
Expand Down Expand Up @@ -172,7 +171,6 @@ func (h *Handler) GetUpdateAccount(w http.ResponseWriter, r *http.Request) {
}
w.Header().Set("Location", h.Auth.GetLink(acme.AccountLink, acme.URLSafeProvisionerName(prov), true, acc.GetID()))
api.JSON(w, acc)
return
}

func logOrdersByAccount(w http.ResponseWriter, oids []string) {
Expand Down Expand Up @@ -209,5 +207,4 @@ func (h *Handler) GetOrdersByAccount(w http.ResponseWriter, r *http.Request) {
}
api.JSON(w, orders)
logOrdersByAccount(w, orders)
return
}
5 changes: 0 additions & 5 deletions acme/api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ func (h *Handler) GetNonce(w http.ResponseWriter, r *http.Request) {
} else {
w.WriteHeader(http.StatusNoContent)
}
return
}

// GetDirectory is the ACME resource for returning a directory configuration
Expand All @@ -126,7 +125,6 @@ func (h *Handler) GetDirectory(w http.ResponseWriter, r *http.Request) {
}
dir := h.Auth.GetDirectory(prov)
api.JSON(w, dir)
return
}

// GetAuthz ACME api for retrieving an Authz.
Expand All @@ -149,7 +147,6 @@ func (h *Handler) GetAuthz(w http.ResponseWriter, r *http.Request) {

w.Header().Set("Location", h.Auth.GetLink(acme.AuthzLink, acme.URLSafeProvisionerName(prov), true, authz.GetID()))
api.JSON(w, authz)
return
}

// GetChallenge ACME api for retrieving a Challenge.
Expand Down Expand Up @@ -191,7 +188,6 @@ func (h *Handler) GetChallenge(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Link", link(getLink(acme.AuthzLink, acme.URLSafeProvisionerName(prov), true, ch.GetAuthzID()), "up"))
w.Header().Set("Location", getLink(acme.ChallengeLink, acme.URLSafeProvisionerName(prov), true, ch.GetID()))
api.JSON(w, ch)
return
}

// GetCertificate ACME api for retrieving a Certificate.
Expand All @@ -210,5 +206,4 @@ func (h *Handler) GetCertificate(w http.ResponseWriter, r *http.Request) {

w.Header().Set("Content-Type", "application/pem-certificate-chain; charset=utf-8")
w.Write(certBytes)
return
}
9 changes: 0 additions & 9 deletions acme/api/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ func (h *Handler) addNonce(next nextHTTP) nextHTTP {
w.Header().Set("Cache-Control", "no-store")
logNonce(w, nonce)
next(w, r)
return
}
}

Expand All @@ -57,7 +56,6 @@ func (h *Handler) addDirLink(next nextHTTP) nextHTTP {
}
w.Header().Add("Link", link(h.Auth.GetLink(acme.DirectoryLink, acme.URLSafeProvisionerName(prov), true), "index"))
next(w, r)
return
}
}

Expand Down Expand Up @@ -87,7 +85,6 @@ func (h *Handler) verifyContentType(next nextHTTP) nextHTTP {
}
api.WriteError(w, acme.MalformedErr(errors.Errorf(
"expected content-type to be in %s, but got %s", expected, ct)))
return
}
}

Expand All @@ -106,7 +103,6 @@ func (h *Handler) parseJWS(next nextHTTP) nextHTTP {
}
ctx := context.WithValue(r.Context(), jwsContextKey, jws)
next(w, r.WithContext(ctx))
return
}
}

Expand Down Expand Up @@ -202,7 +198,6 @@ func (h *Handler) validateJWS(next nextHTTP) nextHTTP {
return
}
next(w, r)
return
}
}

Expand Down Expand Up @@ -248,7 +243,6 @@ func (h *Handler) extractJWK(next nextHTTP) nextHTTP {
ctx = context.WithValue(ctx, accContextKey, acc)
}
next(w, r.WithContext(ctx))
return
}
}

Expand All @@ -275,7 +269,6 @@ func (h *Handler) lookupProvisioner(next nextHTTP) nextHTTP {
}
ctx = context.WithValue(ctx, provisionerContextKey, p)
next(w, r.WithContext(ctx))
return
}
}

Expand Down Expand Up @@ -355,7 +348,6 @@ func (h *Handler) verifyAndExtractJWSPayload(next nextHTTP) nextHTTP {
isEmptyJSON: string(payload) == "{}",
})
next(w, r.WithContext(ctx))
return
}
}

Expand All @@ -372,6 +364,5 @@ func (h *Handler) isPostAsGet(next nextHTTP) nextHTTP {
return
}
next(w, r)
return
}
}
8 changes: 0 additions & 8 deletions acme/api/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ var testBody = []byte("foo")

func testNext(w http.ResponseWriter, r *http.Request) {
w.Write(testBody)
return
}

func TestHandlerAddNonce(t *testing.T) {
Expand Down Expand Up @@ -471,7 +470,6 @@ func TestHandlerParseJWS(t *testing.T) {
assert.FatalError(t, err)
assert.Equals(t, gotRaw, expRaw)
w.Write(testBody)
return
},
statusCode: 200,
}
Expand Down Expand Up @@ -923,7 +921,6 @@ func TestHandlerLookupJWK(t *testing.T) {
assert.FatalError(t, err)
assert.Equals(t, _jwk, jwk)
w.Write(testBody)
return
},
statusCode: 200,
}
Expand Down Expand Up @@ -1114,7 +1111,6 @@ func TestHandlerExtractJWK(t *testing.T) {
assert.FatalError(t, err)
assert.Equals(t, _jwk.KeyID, pub.KeyID)
w.Write(testBody)
return
},
statusCode: 200,
}
Expand All @@ -1139,7 +1135,6 @@ func TestHandlerExtractJWK(t *testing.T) {
assert.FatalError(t, err)
assert.Equals(t, _jwk.KeyID, pub.KeyID)
w.Write(testBody)
return
},
statusCode: 200,
}
Expand Down Expand Up @@ -1448,7 +1443,6 @@ func TestHandlerValidateJWS(t *testing.T) {
ctx: context.WithValue(context.Background(), jwsContextKey, jws),
next: func(w http.ResponseWriter, r *http.Request) {
w.Write(testBody)
return
},
statusCode: 200,
}
Expand Down Expand Up @@ -1479,7 +1473,6 @@ func TestHandlerValidateJWS(t *testing.T) {
ctx: context.WithValue(context.Background(), jwsContextKey, jws),
next: func(w http.ResponseWriter, r *http.Request) {
w.Write(testBody)
return
},
statusCode: 200,
}
Expand Down Expand Up @@ -1510,7 +1503,6 @@ func TestHandlerValidateJWS(t *testing.T) {
ctx: context.WithValue(context.Background(), jwsContextKey, jws),
next: func(w http.ResponseWriter, r *http.Request) {
w.Write(testBody)
return
},
statusCode: 200,
}
Expand Down
3 changes: 0 additions & 3 deletions acme/api/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ func (h *Handler) NewOrder(w http.ResponseWriter, r *http.Request) {

w.Header().Set("Location", h.Auth.GetLink(acme.OrderLink, acme.URLSafeProvisionerName(prov), true, o.GetID()))
api.JSONStatus(w, o, http.StatusCreated)
return
}

// GetOrder ACME api for retrieving an order.
Expand All @@ -121,7 +120,6 @@ func (h *Handler) GetOrder(w http.ResponseWriter, r *http.Request) {

w.Header().Set("Location", h.Auth.GetLink(acme.OrderLink, acme.URLSafeProvisionerName(prov), true, o.GetID()))
api.JSON(w, o)
return
}

// FinalizeOrder attemptst to finalize an order and create a certificate.
Expand Down Expand Up @@ -160,5 +158,4 @@ func (h *Handler) FinalizeOrder(w http.ResponseWriter, r *http.Request) {

w.Header().Set("Location", h.Auth.GetLink(acme.OrderLink, acme.URLSafeProvisionerName(prov), true, o.ID))
api.JSON(w, o)
return
}
6 changes: 4 additions & 2 deletions authority/provisioner/acme.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,12 @@ func (p *ACME) AuthorizeSign(ctx context.Context, _ string) ([]SignOption, error
return nil, errors.Errorf("unexpected method type %d in context", m)
}
return []SignOption{
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
// modifiers / withOptions
newProvisionerExtensionOption(TypeACME, p.Name, ""),
newValidityValidator(p.claimer.MinTLSCertDuration(), p.claimer.MaxTLSCertDuration()),
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
// validators
defaultPublicKeyValidator{},
newValidityValidator(p.claimer.MinTLSCertDuration(), p.claimer.MaxTLSCertDuration()),
}, nil
}

Expand Down
39 changes: 17 additions & 22 deletions authority/provisioner/acme_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,28 +155,23 @@ func TestACME_AuthorizeSign(t *testing.T) {
if assert.NotNil(t, got) {
assert.Len(t, 4, got)

_pdd := got[0]
pdd, ok := _pdd.(profileDefaultDuration)
assert.True(t, ok)
assert.Equals(t, pdd, profileDefaultDuration(86400000000000))

_peo := got[1]
peo, ok := _peo.(*provisionerExtensionOption)
assert.True(t, ok)
assert.Equals(t, peo.Type, 6)
assert.Equals(t, peo.Name, "test@acme-provisioner.com")
assert.Equals(t, peo.CredentialID, "")
assert.Equals(t, peo.KeyValuePairs, nil)

_vv := got[2]
vv, ok := _vv.(*validityValidator)
assert.True(t, ok)
assert.Equals(t, vv.min, time.Duration(300000000000))
assert.Equals(t, vv.max, time.Duration(86400000000000))

_dpkv := got[3]
_, ok = _dpkv.(defaultPublicKeyValidator)
assert.True(t, ok)
for _, o := range got {
switch v := o.(type) {
case *provisionerExtensionOption:
assert.Equals(t, v.Type, int(TypeACME))
assert.Equals(t, v.Name, tt.prov.GetName())
assert.Equals(t, v.CredentialID, "")
assert.Len(t, 0, v.KeyValuePairs)
case profileDefaultDuration:
assert.Equals(t, time.Duration(v), tt.prov.claimer.DefaultTLSCertDuration())
case defaultPublicKeyValidator:
case *validityValidator:
assert.Equals(t, v.min, tt.prov.claimer.MinTLSCertDuration())
assert.Equals(t, v.max, tt.prov.claimer.MaxTLSCertDuration())
default:
assert.FatalError(t, errors.Errorf("unexpected sign option of type %T", v))
}
}
}
}
})
Expand Down
22 changes: 13 additions & 9 deletions authority/provisioner/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ func (p *AWS) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er
}

// Check for the sign ssh method, default to sign X.509
if m := MethodFromContext(ctx); m == SignSSHMethod {
if p.claimer.IsSSHCAEnabled() == false {
if MethodFromContext(ctx) == SignSSHMethod {
if !p.claimer.IsSSHCAEnabled() {
return nil, errors.Errorf("ssh ca is disabled for provisioner %s", p.GetID())
}
return p.authorizeSSHSign(payload)
Expand All @@ -296,10 +296,12 @@ func (p *AWS) AuthorizeSign(ctx context.Context, token string) ([]SignOption, er
}

return append(so,
// modifiers / withOptions
newProvisionerExtensionOption(TypeAWS, p.Name, doc.AccountID, "InstanceID", doc.InstanceID),
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
// validators
defaultPublicKeyValidator{},
commonNameValidator(payload.Claims.Subject),
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
newProvisionerExtensionOption(TypeAWS, p.Name, doc.AccountID, "InstanceID", doc.InstanceID),
newValidityValidator(p.claimer.MinTLSCertDuration(), p.claimer.MaxTLSCertDuration()),
), nil
}
Expand Down Expand Up @@ -466,13 +468,15 @@ func (p *AWS) authorizeSSHSign(claims *awsPayload) ([]SignOption, error) {
signOptions = append(signOptions, sshCertificateDefaultsModifier(defaults))

return append(signOptions,
// set the default extensions
// Set the default extensions.
&sshDefaultExtensionModifier{},
// checks the validity bounds, and set the validity if has not been set
&sshCertificateValidityModifier{p.claimer},
// validate public key
// Set the validity bounds if not set.
sshDefaultValidityModifier(p.claimer),
// Validate public key
&sshDefaultPublicKeyValidator{},
// require all the fields in the SSH certificate
// Validate the validity period.
&sshCertificateValidityValidator{p.claimer},
// Require all the fields in the SSH certificate
&sshCertificateDefaultValidator{},
), nil
}
22 changes: 13 additions & 9 deletions authority/provisioner/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ func (p *Azure) AuthorizeSign(ctx context.Context, token string) ([]SignOption,
}

// Check for the sign ssh method, default to sign X.509
if m := MethodFromContext(ctx); m == SignSSHMethod {
if p.claimer.IsSSHCAEnabled() == false {
if MethodFromContext(ctx) == SignSSHMethod {
if !p.claimer.IsSSHCAEnabled() {
return nil, errors.Errorf("ssh ca is disabled for provisioner %s", p.GetID())
}
return p.authorizeSSHSign(claims, name)
Expand All @@ -284,9 +284,11 @@ func (p *Azure) AuthorizeSign(ctx context.Context, token string) ([]SignOption,
}

return append(so,
defaultPublicKeyValidator{},
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
// modifiers / withOptions
newProvisionerExtensionOption(TypeAzure, p.Name, p.TenantID),
profileDefaultDuration(p.claimer.DefaultTLSCertDuration()),
// validators
defaultPublicKeyValidator{},
newValidityValidator(p.claimer.MinTLSCertDuration(), p.claimer.MaxTLSCertDuration()),
), nil
}
Expand Down Expand Up @@ -323,13 +325,15 @@ func (p *Azure) authorizeSSHSign(claims azurePayload, name string) ([]SignOption
signOptions = append(signOptions, sshCertificateDefaultsModifier(defaults))

return append(signOptions,
// set the default extensions
// Set the default extensions.
&sshDefaultExtensionModifier{},
// checks the validity bounds, and set the validity if has not been set
&sshCertificateValidityModifier{p.claimer},
// validate public key
// Set the validity bounds if not set.
sshDefaultValidityModifier(p.claimer),
// Validate public key
&sshDefaultPublicKeyValidator{},
// require all the fields in the SSH certificate
// Validate the validity period.
&sshCertificateValidityValidator{p.claimer},
// Require all the fields in the SSH certificate
&sshCertificateDefaultValidator{},
), nil
}
Expand Down
2 changes: 2 additions & 0 deletions authority/provisioner/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ func (c *Collection) LoadByCertificate(cert *x509.Certificate) (Interface, bool)
return c.Load("gcp/" + string(provisioner.Name))
case TypeACME:
return c.Load("acme/" + string(provisioner.Name))
case TypeX5C:
return c.Load("x5c/" + string(provisioner.Name))
default:
return c.Load(string(provisioner.CredentialID))
}
Expand Down

0 comments on commit f423fdb

Please sign in to comment.