diff --git a/authority/authority.go b/authority/authority.go index c112bc25..e8feb1fd 100644 --- a/authority/authority.go +++ b/authority/authority.go @@ -255,7 +255,10 @@ func (a *Authority) ReloadAdminResources(ctx context.Context) error { provClxn := provisioner.NewCollection(provisionerConfig.Audiences) for _, p := range provList { if err := p.Init(provisionerConfig); err != nil { - return err + log.Printf("failed to initialize %s provisioner %q: %v\n", p.GetType(), p.GetName(), err) + p = provisioner.Disabled{ + Interface: p, Reason: err, + } } if err := provClxn.Store(p); err != nil { return err diff --git a/authority/authorize.go b/authority/authorize.go index 02147687..9fdde3be 100644 --- a/authority/authorize.go +++ b/authority/authorize.go @@ -64,6 +64,10 @@ func (a *Authority) getProvisionerFromToken(token string) (provisioner.Interface if !ok { return nil, nil, fmt.Errorf("provisioner not found or invalid audience (%s)", strings.Join(claims.Audience, ", ")) } + // If the provisioner is disabled, send an appropriate message to the client + if _, ok := p.(provisioner.Disabled); ok { + return nil, nil, errs.New(http.StatusUnauthorized, "provisioner %q is disabled due to an initialization error", p.GetName()) + } return p, &claims, nil } diff --git a/authority/provisioner/provisioner.go b/authority/provisioner/provisioner.go index a9b17066..7640cef7 100644 --- a/authority/provisioner/provisioner.go +++ b/authority/provisioner/provisioner.go @@ -33,6 +33,31 @@ type Interface interface { AuthorizeSSHRekey(ctx context.Context, token string) (*ssh.Certificate, []SignOption, error) } +// Disabled represents a disabled provisioner. Disabled provisioners are created +// when the Init methods fails. +type Disabled struct { + Interface + Reason error +} + +// MarshalJSON returns the JSON encoding of the provisioner with the disabled +// reason. +func (p Disabled) MarshalJSON() ([]byte, error) { + provisionerJSON, err := json.Marshal(p.Interface) + if err != nil { + return nil, err + } + reasonJSON, err := json.Marshal(struct { + Disabled bool `json:"disabled"` + DisabledReason string `json:"disabledReason"` + }{true, p.Reason.Error()}) + if err != nil { + return nil, err + } + reasonJSON[0] = ',' + return append(provisionerJSON[:len(provisionerJSON)-1], reasonJSON...), nil +} + // ErrAllowTokenReuse is an error that is returned by provisioners that allows // the reuse of tokens. //