forked from TrueCloudLab/certificates
lots of codes
This commit is contained in:
parent
7b5d6968a5
commit
2f60f20b0b
7 changed files with 600 additions and 339 deletions
|
@ -146,19 +146,21 @@ func (a *Authority) init() error {
|
||||||
|
|
||||||
// Pull AuthConfig from DB.
|
// Pull AuthConfig from DB.
|
||||||
if true {
|
if true {
|
||||||
|
if len(a.config.AuthConfig.AuthorityID)_== 0 {
|
||||||
mgmtDB, err := authMgmtNosql.New(a.db.(nosql.DB), mgmt.DefaultAuthorityID)
|
mgmtDB, err := authMgmtNosql.New(a.db.(nosql.DB), mgmt.DefaultAuthorityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_ac, err := mgmtDB.GetAuthConfig(context.Background(), mgmt.DefaultAuthorityID)
|
mgmtAuthConfig, err := mgmt.CreateAuthority(context.Background, mgmtDB, WithDefaultAuthorityID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
a.config.AuthorityConfig, err = _ac.ToCertificates()
|
a.config.AuthConfig, err := mgmtAuthConfig.ToCertificates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize key manager if it has not been set in the options.
|
// Initialize key manager if it has not been set in the options.
|
||||||
if a.keyManager == nil {
|
if a.keyManager == nil {
|
||||||
|
|
|
@ -32,23 +32,23 @@ var (
|
||||||
MaxVersion: 1.2,
|
MaxVersion: 1.2,
|
||||||
Renegotiation: false,
|
Renegotiation: false,
|
||||||
}
|
}
|
||||||
defaultBackdate = time.Minute
|
DefaultBackdate = time.Minute
|
||||||
defaultDisableRenewal = false
|
DefaultDisableRenewal = false
|
||||||
defaultEnableSSHCA = false
|
DefaultEnableSSHCA = false
|
||||||
// GlobalProvisionerClaims default claims for the Authority. Can be overriden
|
// GlobalProvisionerClaims default claims for the Authority. Can be overriden
|
||||||
// by provisioner specific claims.
|
// by provisioner specific claims.
|
||||||
GlobalProvisionerClaims = provisioner.Claims{
|
GlobalProvisionerClaims = provisioner.Claims{
|
||||||
MinTLSDur: &provisioner.Duration{Duration: 5 * time.Minute}, // TLS certs
|
MinTLSDur: &provisioner.Duration{Duration: 5 * time.Minute}, // TLS certs
|
||||||
MaxTLSDur: &provisioner.Duration{Duration: 24 * time.Hour},
|
MaxTLSDur: &provisioner.Duration{Duration: 24 * time.Hour},
|
||||||
DefaultTLSDur: &provisioner.Duration{Duration: 24 * time.Hour},
|
DefaultTLSDur: &provisioner.Duration{Duration: 24 * time.Hour},
|
||||||
DisableRenewal: &defaultDisableRenewal,
|
DisableRenewal: &DefaultDisableRenewal,
|
||||||
MinUserSSHDur: &provisioner.Duration{Duration: 5 * time.Minute}, // User SSH certs
|
MinUserSSHDur: &provisioner.Duration{Duration: 5 * time.Minute}, // User SSH certs
|
||||||
MaxUserSSHDur: &provisioner.Duration{Duration: 24 * time.Hour},
|
MaxUserSSHDur: &provisioner.Duration{Duration: 24 * time.Hour},
|
||||||
DefaultUserSSHDur: &provisioner.Duration{Duration: 16 * time.Hour},
|
DefaultUserSSHDur: &provisioner.Duration{Duration: 16 * time.Hour},
|
||||||
MinHostSSHDur: &provisioner.Duration{Duration: 5 * time.Minute}, // Host SSH certs
|
MinHostSSHDur: &provisioner.Duration{Duration: 5 * time.Minute}, // Host SSH certs
|
||||||
MaxHostSSHDur: &provisioner.Duration{Duration: 30 * 24 * time.Hour},
|
MaxHostSSHDur: &provisioner.Duration{Duration: 30 * 24 * time.Hour},
|
||||||
DefaultHostSSHDur: &provisioner.Duration{Duration: 30 * 24 * time.Hour},
|
DefaultHostSSHDur: &provisioner.Duration{Duration: 30 * 24 * time.Hour},
|
||||||
EnableSSHCA: &defaultEnableSSHCA,
|
EnableSSHCA: &DefaultEnableSSHCA,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ type ASN1DN struct {
|
||||||
// cas.Options.
|
// cas.Options.
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
*cas.Options
|
*cas.Options
|
||||||
|
AuthorityID string `json:"authorityID,omitempty"`
|
||||||
Provisioners provisioner.List `json:"provisioners"`
|
Provisioners provisioner.List `json:"provisioners"`
|
||||||
Template *ASN1DN `json:"template,omitempty"`
|
Template *ASN1DN `json:"template,omitempty"`
|
||||||
Claims *provisioner.Claims `json:"claims,omitempty"`
|
Claims *provisioner.Claims `json:"claims,omitempty"`
|
||||||
|
@ -106,7 +107,7 @@ func (c *AuthConfig) init() {
|
||||||
}
|
}
|
||||||
if c.Backdate == nil {
|
if c.Backdate == nil {
|
||||||
c.Backdate = &provisioner.Duration{
|
c.Backdate = &provisioner.Duration{
|
||||||
Duration: defaultBackdate,
|
Duration: DefaultBackdate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
31
authority/mgmt/admin.go
Normal file
31
authority/mgmt/admin.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package mgmt
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
// Admin type.
|
||||||
|
type Admin struct {
|
||||||
|
ID string `json:"-"`
|
||||||
|
AuthorityID string `json:"-"`
|
||||||
|
ProvisionerID string `json:"provisionerID"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ProvisionerName string `json:"provisionerName"`
|
||||||
|
ProvisionerType string `json:"provisionerType"`
|
||||||
|
IsSuperAdmin bool `json:"isSuperAdmin"`
|
||||||
|
Status StatusType `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAdmin builds and stores an admin type in the DB.
|
||||||
|
func CreateAdmin(ctx context.Context, db DB, name string, prov *Provisioner, isSuperAdmin bool) (*Admin, error) {
|
||||||
|
adm := &Admin{
|
||||||
|
Name: name,
|
||||||
|
ProvisionerID: prov.ID,
|
||||||
|
ProvisionerName: prov.Name,
|
||||||
|
ProvisionerType: prov.Type,
|
||||||
|
IsSuperAdmin: isSuperAdmin,
|
||||||
|
Status: StatusActive,
|
||||||
|
}
|
||||||
|
if err := db.CreateAdmin(ctx, adm); err != nil {
|
||||||
|
return nil, WrapErrorISE(err, "error creating admin")
|
||||||
|
}
|
||||||
|
return adm, nil
|
||||||
|
}
|
77
authority/mgmt/authConfig.go
Normal file
77
authority/mgmt/authConfig.go
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
package mgmt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/smallstep/certificates/authority/config"
|
||||||
|
"github.com/smallstep/certificates/authority/provisioner"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AuthConfig represents the Authority Configuration.
|
||||||
|
type AuthConfig struct {
|
||||||
|
//*cas.Options `json:"cas"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
ASN1DN *config.ASN1DN `json:"template,omitempty"`
|
||||||
|
Provisioners []*Provisioner `json:"-"`
|
||||||
|
Admins []*Admin `json:"-"`
|
||||||
|
Claims *Claims `json:"claims,omitempty"`
|
||||||
|
Backdate string `json:"backdate,omitempty"`
|
||||||
|
Status StatusType `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDefaultAuthConfig() *AuthConfig {
|
||||||
|
return &AuthConfig{
|
||||||
|
Claims: &Claims{
|
||||||
|
X509: &X509Claims{
|
||||||
|
Durations: &Durations{
|
||||||
|
Min: config.GlobalProvisionerClaims.MinTLSDur.String(),
|
||||||
|
Max: config.GlobalProvisionerClaims.MaxTLSDur.String(),
|
||||||
|
Default: config.GlobalProvisionerClaims.DefaultTLSDur.String(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SSH: &SSHClaims{
|
||||||
|
UserDurations: &Durations{
|
||||||
|
Min: config.GlobalProvisionerClaims.MinUserSSHDur.String(),
|
||||||
|
Max: config.GlobalProvisionerClaims.MaxUserSSHDur.String(),
|
||||||
|
Default: config.GlobalProvisionerClaims.DefaultUserSSHDur.String(),
|
||||||
|
},
|
||||||
|
HostDurations: &Durations{
|
||||||
|
Min: config.GlobalProvisionerClaims.MinHostSSHDur.String(),
|
||||||
|
Max: config.GlobalProvisionerClaims.MaxHostSSHDur.String(),
|
||||||
|
Default: config.GlobalProvisionerClaims.DefaultHostSSHDur.String(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DisableRenewal: config.DefaultDisableRenewal,
|
||||||
|
},
|
||||||
|
Backdate: config.DefaultBackdate.String(),
|
||||||
|
Status: StatusActive,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToCertificates converts a mgmt AuthConfig to configuration that can be
|
||||||
|
// directly used by the `step-ca` process. Resources are normalized and
|
||||||
|
// initialized.
|
||||||
|
func (ac *AuthConfig) ToCertificates() (*config.AuthConfig, error) {
|
||||||
|
claims, err := ac.Claims.ToCertificates()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
backdate, err := provisioner.NewDuration(ac.Backdate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, WrapErrorISE(err, "error converting backdate %s to duration", ac.Backdate)
|
||||||
|
}
|
||||||
|
var provs []provisioner.Interface
|
||||||
|
for _, p := range ac.Provisioners {
|
||||||
|
authProv, err := p.ToCertificates()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
provs = append(provs, authProv)
|
||||||
|
}
|
||||||
|
return &config.AuthConfig{
|
||||||
|
AuthorityID: ac.ID,
|
||||||
|
Provisioners: provs,
|
||||||
|
Template: ac.ASN1DN,
|
||||||
|
Claims: claims,
|
||||||
|
DisableIssuedAtCheck: false,
|
||||||
|
Backdate: backdate,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -1,11 +1,15 @@
|
||||||
package mgmt
|
package mgmt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/smallstep/certificates/authority/config"
|
"context"
|
||||||
authority "github.com/smallstep/certificates/authority/config"
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// DefaultAuthorityID is the default AuthorityID. This will be the ID
|
||||||
|
// of the first Authority created, as well as the default AuthorityID
|
||||||
|
// if one is not specified in the configuration.
|
||||||
DefaultAuthorityID = "00000000-0000-0000-0000-000000000000"
|
DefaultAuthorityID = "00000000-0000-0000-0000-000000000000"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,339 +23,76 @@ const (
|
||||||
StatusDeleted
|
StatusDeleted
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Claims encapsulates all x509 and ssh claims applied to the authority
|
||||||
|
// configuration. E.g. maxTLSCertDuration, defaultSSHCertDuration, etc.
|
||||||
type Claims struct {
|
type Claims struct {
|
||||||
*X509Claims `json:"x509Claims"`
|
X509 *X509Claims `json:"x509Claims"`
|
||||||
*SSHClaims `json:"sshClaims"`
|
SSH *SSHClaims `json:"sshClaims"`
|
||||||
DisableRenewal *bool `json:"disableRenewal"`
|
DisableRenewal bool `json:"disableRenewal"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// X509Claims are the x509 claims applied to the authority.
|
||||||
type X509Claims struct {
|
type X509Claims struct {
|
||||||
Durations *Durations `json:"durations"`
|
Durations *Durations `json:"durations"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SSHClaims are the ssh claims applied to the authority.
|
||||||
type SSHClaims struct {
|
type SSHClaims struct {
|
||||||
UserDuration *Durations `json:"userDurations"`
|
Enabled bool `json:"enabled"`
|
||||||
HostDuration *Durations `json:"hostDuration"`
|
UserDurations *Durations `json:"userDurations"`
|
||||||
|
HostDurations *Durations `json:"hostDurations"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Durations represents min, max, default, duration.
|
||||||
type Durations struct {
|
type Durations struct {
|
||||||
Min string `json:"min"`
|
Min string `json:"min"`
|
||||||
Max string `json:"max"`
|
Max string `json:"max"`
|
||||||
Default string `json:"default"`
|
Default string `json:"default"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admin type.
|
type AuthorityOption func(*AuthConfig) error
|
||||||
type Admin struct {
|
|
||||||
ID string `json:"-"`
|
|
||||||
AuthorityID string `json:"-"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Provisioner string `json:"provisioner"`
|
|
||||||
IsSuperAdmin bool `json:"isSuperAdmin"`
|
|
||||||
Status StatusType `json:"status"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provisioner type.
|
func WithDefaultAuthorityID(ac *AuthConfig) error {
|
||||||
type Provisioner struct {
|
ac.ID = DefaultAuthorityID
|
||||||
ID string `json:"-"`
|
|
||||||
AuthorityID string `json:"-"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Claims *Claims `json:"claims"`
|
|
||||||
Details interface{} `json:"details"`
|
|
||||||
X509Template string `json:"x509Template"`
|
|
||||||
SSHTemplate string `json:"sshTemplate"`
|
|
||||||
Status StatusType `json:"status"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthConfig represents the Authority Configuration.
|
|
||||||
type AuthConfig struct {
|
|
||||||
//*cas.Options `json:"cas"`
|
|
||||||
ID string `json:"id"`
|
|
||||||
ASN1DN *config.ASN1DN `json:"template,omitempty"`
|
|
||||||
Provisioners []*Provisioner `json:"-"`
|
|
||||||
Claims *Claims `json:"claims,omitempty"`
|
|
||||||
DisableIssuedAtCheck bool `json:"disableIssuedAtCheck,omitempty"`
|
|
||||||
Backdate string `json:"backdate,omitempty"`
|
|
||||||
Status StatusType `json:"status,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ac *AuthConfig) ToCertificates() (*config.AuthConfig, error) {
|
|
||||||
return &authority.AuthConfig{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// ToCertificates converts the landlord provisioner type to the open source
|
|
||||||
// provisioner type.
|
|
||||||
func (p *Provisioner) ToCertificates(ctx context.Context, db database.DB) (provisioner.Interface, error) {
|
|
||||||
claims, err := p.Claims.ToCertificates()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
details := p.Details.GetData()
|
|
||||||
if details == nil {
|
|
||||||
return nil, fmt.Errorf("provisioner does not have any details")
|
|
||||||
}
|
|
||||||
|
|
||||||
options, err := p.getOptions(ctx, db)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch d := details.(type) {
|
|
||||||
case *ProvisionerDetails_JWK:
|
|
||||||
k := d.JWK.GetKey()
|
|
||||||
jwk := new(jose.JSONWebKey)
|
|
||||||
if err := json.Unmarshal(k.Key.Public, &jwk); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &provisioner.JWK{
|
|
||||||
Type: p.Type.String(),
|
|
||||||
Name: p.Name,
|
|
||||||
Key: jwk,
|
|
||||||
EncryptedKey: string(k.Key.Private),
|
|
||||||
Claims: claims,
|
|
||||||
Options: options,
|
|
||||||
}, nil
|
|
||||||
case *ProvisionerDetails_OIDC:
|
|
||||||
cfg := d.OIDC
|
|
||||||
return &provisioner.OIDC{
|
|
||||||
Type: p.Type.String(),
|
|
||||||
Name: p.Name,
|
|
||||||
TenantID: cfg.TenantId,
|
|
||||||
ClientID: cfg.ClientId,
|
|
||||||
ClientSecret: cfg.ClientSecret,
|
|
||||||
ConfigurationEndpoint: cfg.ConfigurationEndpoint,
|
|
||||||
Admins: cfg.Admins,
|
|
||||||
Domains: cfg.Domains,
|
|
||||||
Groups: cfg.Groups,
|
|
||||||
ListenAddress: cfg.ListenAddress,
|
|
||||||
Claims: claims,
|
|
||||||
Options: options,
|
|
||||||
}, nil
|
|
||||||
case *ProvisionerDetails_GCP:
|
|
||||||
cfg := d.GCP
|
|
||||||
return &provisioner.GCP{
|
|
||||||
Type: p.Type.String(),
|
|
||||||
Name: p.Name,
|
|
||||||
ServiceAccounts: cfg.ServiceAccounts,
|
|
||||||
ProjectIDs: cfg.ProjectIds,
|
|
||||||
DisableCustomSANs: cfg.DisableCustomSans,
|
|
||||||
DisableTrustOnFirstUse: cfg.DisableTrustOnFirstUse,
|
|
||||||
InstanceAge: durationValue(cfg.InstanceAge),
|
|
||||||
Claims: claims,
|
|
||||||
Options: options,
|
|
||||||
}, nil
|
|
||||||
case *ProvisionerDetails_AWS:
|
|
||||||
cfg := d.AWS
|
|
||||||
return &provisioner.AWS{
|
|
||||||
Type: p.Type.String(),
|
|
||||||
Name: p.Name,
|
|
||||||
Accounts: cfg.Accounts,
|
|
||||||
DisableCustomSANs: cfg.DisableCustomSans,
|
|
||||||
DisableTrustOnFirstUse: cfg.DisableTrustOnFirstUse,
|
|
||||||
InstanceAge: durationValue(cfg.InstanceAge),
|
|
||||||
Claims: claims,
|
|
||||||
Options: options,
|
|
||||||
}, nil
|
|
||||||
case *ProvisionerDetails_Azure:
|
|
||||||
cfg := d.Azure
|
|
||||||
return &provisioner.Azure{
|
|
||||||
Type: p.Type.String(),
|
|
||||||
Name: p.Name,
|
|
||||||
TenantID: cfg.TenantId,
|
|
||||||
ResourceGroups: cfg.ResourceGroups,
|
|
||||||
Audience: cfg.Audience,
|
|
||||||
DisableCustomSANs: cfg.DisableCustomSans,
|
|
||||||
DisableTrustOnFirstUse: cfg.DisableTrustOnFirstUse,
|
|
||||||
Claims: claims,
|
|
||||||
Options: options,
|
|
||||||
}, nil
|
|
||||||
case *ProvisionerDetails_X5C:
|
|
||||||
var roots []byte
|
|
||||||
for i, k := range d.X5C.GetRoots() {
|
|
||||||
if b := k.GetKey().GetPublic(); b != nil {
|
|
||||||
if i > 0 {
|
|
||||||
roots = append(roots, '\n')
|
|
||||||
}
|
|
||||||
roots = append(roots, b...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &provisioner.X5C{
|
|
||||||
Type: p.Type.String(),
|
|
||||||
Name: p.Name,
|
|
||||||
Roots: roots,
|
|
||||||
Claims: claims,
|
|
||||||
Options: options,
|
|
||||||
}, nil
|
|
||||||
case *ProvisionerDetails_K8SSA:
|
|
||||||
var publicKeys []byte
|
|
||||||
for i, k := range d.K8SSA.GetPublicKeys() {
|
|
||||||
if b := k.GetKey().GetPublic(); b != nil {
|
|
||||||
if i > 0 {
|
|
||||||
publicKeys = append(publicKeys, '\n')
|
|
||||||
}
|
|
||||||
publicKeys = append(publicKeys, k.Key.Public...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &provisioner.K8sSA{
|
|
||||||
Type: p.Type.String(),
|
|
||||||
Name: p.Name,
|
|
||||||
PubKeys: publicKeys,
|
|
||||||
Claims: claims,
|
|
||||||
Options: options,
|
|
||||||
}, nil
|
|
||||||
case *ProvisionerDetails_SSHPOP:
|
|
||||||
return &provisioner.SSHPOP{
|
|
||||||
Type: p.Type.String(),
|
|
||||||
Name: p.Name,
|
|
||||||
Claims: claims,
|
|
||||||
}, nil
|
|
||||||
case *ProvisionerDetails_ACME:
|
|
||||||
cfg := d.ACME
|
|
||||||
return &provisioner.ACME{
|
|
||||||
Type: p.Type.String(),
|
|
||||||
Name: p.Name,
|
|
||||||
ForceCN: cfg.ForceCn,
|
|
||||||
Claims: claims,
|
|
||||||
Options: options,
|
|
||||||
}, nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("provisioner %s not implemented", p.Type.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCertificates converts the landlord provisioner claims type to the open source
|
|
||||||
// (step-ca) claims type.
|
|
||||||
func (c *Claims) ToCertificates() (*provisioner.Claims, error) {
|
|
||||||
x509, ssh := c.GetX509(), c.GetSsh()
|
|
||||||
x509Durations := x509.GetDurations()
|
|
||||||
hostDurations := ssh.GetHostDurations()
|
|
||||||
userDurations := ssh.GetUserDurations()
|
|
||||||
enableSSHCA := ssh.GetEnabled()
|
|
||||||
return &provisioner.Claims{
|
|
||||||
MinTLSDur: durationPtr(x509Durations.GetMin()),
|
|
||||||
MaxTLSDur: durationPtr(x509Durations.GetMax()),
|
|
||||||
DefaultTLSDur: durationPtr(x509Durations.GetDefault()),
|
|
||||||
DisableRenewal: &c.DisableRenewal,
|
|
||||||
MinUserSSHDur: durationPtr(userDurations.GetMin()),
|
|
||||||
MaxUserSSHDur: durationPtr(userDurations.GetMax()),
|
|
||||||
DefaultUserSSHDur: durationPtr(userDurations.GetDefault()),
|
|
||||||
MinHostSSHDur: durationPtr(hostDurations.GetMin()),
|
|
||||||
MaxHostSSHDur: durationPtr(hostDurations.GetMax()),
|
|
||||||
DefaultHostSSHDur: durationPtr(hostDurations.GetDefault()),
|
|
||||||
EnableSSHCA: &enableSSHCA,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func durationPtr(d *duration.Duration) *provisioner.Duration {
|
|
||||||
if d == nil {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &provisioner.Duration{
|
|
||||||
Duration: time.Duration(d.Seconds)*time.Second + time.Duration(d.Nanos)*time.Nanosecond,
|
func CreateDefaultAuthority(ctx context.Context, db DB) (*AuthConfig, error) {
|
||||||
|
options := []AuthorityOption{WithDefaultAuthorityID}
|
||||||
|
|
||||||
|
return CreateAuthority(ctx, db, options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateAuthority(ctx context.Context, db DB, options ...AuthorityOption) (*AuthConfig, error) {
|
||||||
|
ac := NewDefaultAuthConfig()
|
||||||
|
|
||||||
|
for _, o := range options {
|
||||||
|
if err := o(ac); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func durationValue(d *duration.Duration) provisioner.Duration {
|
if err := db.CreateAuthConfig(ctx, ac); err != nil {
|
||||||
if d == nil {
|
return nil, errors.Wrap(err, "error creating authConfig")
|
||||||
return provisioner.Duration{}
|
|
||||||
}
|
|
||||||
return provisioner.Duration{
|
|
||||||
Duration: time.Duration(d.Seconds)*time.Second + time.Duration(d.Nanos)*time.Nanosecond,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalDetails(d *ProvisionerDetails) (sql.NullString, error) {
|
// Generate default JWK provisioner.
|
||||||
b, err := json.Marshal(d.GetData())
|
|
||||||
|
provOpts := []ProvisionerOption{WithPassword("pass")}
|
||||||
|
prov, err := CreateProvisioner(ctx, db, "JWK", "changeme", provOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sql.NullString{}, nil
|
// TODO should we try to clean up?
|
||||||
}
|
return nil, WrapErrorISE(err, "error creating first provisioner")
|
||||||
return sql.NullString{
|
|
||||||
String: string(b),
|
|
||||||
Valid: len(b) > 0,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalDetails(ctx context.Context, db database.DB, typ ProvisionerType, s sql.NullString) (*ProvisionerDetails, error) {
|
admin, err := CreateAdmin(ctx, db, "Change Me", prov, true)
|
||||||
if !s.Valid {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
var v isProvisionerDetails_Data
|
|
||||||
switch typ {
|
|
||||||
case ProvisionerType_JWK:
|
|
||||||
p := new(ProvisionerDetails_JWK)
|
|
||||||
if err := json.Unmarshal([]byte(s.String), p); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if p.JWK.Key.Key == nil {
|
|
||||||
key, err := LoadKey(ctx, db, p.JWK.Key.Id.Id)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
// TODO should we try to clean up?
|
||||||
}
|
return nil, WrapErrorISE(err, "error creating first provisioner")
|
||||||
p.JWK.Key = key
|
|
||||||
}
|
|
||||||
return &ProvisionerDetails{Data: p}, nil
|
|
||||||
case ProvisionerType_OIDC:
|
|
||||||
v = new(ProvisionerDetails_OIDC)
|
|
||||||
case ProvisionerType_GCP:
|
|
||||||
v = new(ProvisionerDetails_GCP)
|
|
||||||
case ProvisionerType_AWS:
|
|
||||||
v = new(ProvisionerDetails_AWS)
|
|
||||||
case ProvisionerType_AZURE:
|
|
||||||
v = new(ProvisionerDetails_Azure)
|
|
||||||
case ProvisionerType_ACME:
|
|
||||||
v = new(ProvisionerDetails_ACME)
|
|
||||||
case ProvisionerType_X5C:
|
|
||||||
p := new(ProvisionerDetails_X5C)
|
|
||||||
if err := json.Unmarshal([]byte(s.String), p); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, k := range p.X5C.GetRoots() {
|
|
||||||
if err := k.Select(ctx, db, k.Id.Id); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &ProvisionerDetails{Data: p}, nil
|
|
||||||
case ProvisionerType_K8SSA:
|
|
||||||
p := new(ProvisionerDetails_K8SSA)
|
|
||||||
if err := json.Unmarshal([]byte(s.String), p); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, k := range p.K8SSA.GetPublicKeys() {
|
|
||||||
if err := k.Select(ctx, db, k.Id.Id); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &ProvisionerDetails{Data: p}, nil
|
|
||||||
case ProvisionerType_SSHPOP:
|
|
||||||
v = new(ProvisionerDetails_SSHPOP)
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unsupported provisioner type %s", typ)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal([]byte(s.String), v); err != nil {
|
ac.Provisioners = []*Provisioner{prov}
|
||||||
return nil, err
|
ac.Admins = []*Admin{admin}
|
||||||
}
|
|
||||||
return &ProvisionerDetails{Data: v}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalClaims(c *Claims) (sql.NullString, error) {
|
return ac, nil
|
||||||
b, err := json.Marshal(c)
|
|
||||||
if err != nil {
|
|
||||||
return sql.NullString{}, nil
|
|
||||||
}
|
}
|
||||||
return sql.NullString{
|
|
||||||
String: string(b),
|
|
||||||
Valid: len(b) > 0,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func unmarshalClaims(s sql.NullString) (*Claims, error) {
|
|
||||||
if !s.Valid {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
v := new(Claims)
|
|
||||||
return v, json.Unmarshal([]byte(s.String), v)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
|
@ -15,8 +15,8 @@ import (
|
||||||
type dbAdmin struct {
|
type dbAdmin struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
AuthorityID string `json:"authorityID"`
|
AuthorityID string `json:"authorityID"`
|
||||||
|
ProvisionerID string `json:"provisionerID"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Provisioner string `json:"provisioner"`
|
|
||||||
IsSuperAdmin bool `json:"isSuperAdmin"`
|
IsSuperAdmin bool `json:"isSuperAdmin"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
DeletedAt time.Time `json:"deletedAt"`
|
DeletedAt time.Time `json:"deletedAt"`
|
||||||
|
@ -70,6 +70,13 @@ func (db *DB) GetAdmin(ctx context.Context, id string) (*mgmt.Admin, error) {
|
||||||
return nil, mgmt.NewError(mgmt.ErrorAuthorityMismatchType,
|
return nil, mgmt.NewError(mgmt.ErrorAuthorityMismatchType,
|
||||||
"admin %s is not owned by authority %s", adm.ID, db.authorityID)
|
"admin %s is not owned by authority %s", adm.ID, db.authorityID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prov, err := db.GetProvisioner(ctx, adm.ProvisionerID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
adm.ProvisionerName = prov.Name
|
||||||
|
adm.ProvisionerType = prov.Type
|
||||||
return adm, nil
|
return adm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,8 +95,9 @@ func unmarshalAdmin(data []byte, id string) (*mgmt.Admin, error) {
|
||||||
}
|
}
|
||||||
adm := &mgmt.Admin{
|
adm := &mgmt.Admin{
|
||||||
ID: dba.ID,
|
ID: dba.ID,
|
||||||
|
AuthorityID: dba.AuthorityID,
|
||||||
|
ProvisionerID: dba.ProvisionerID,
|
||||||
Name: dba.Name,
|
Name: dba.Name,
|
||||||
Provisioner: dba.Provisioner,
|
|
||||||
IsSuperAdmin: dba.IsSuperAdmin,
|
IsSuperAdmin: dba.IsSuperAdmin,
|
||||||
}
|
}
|
||||||
if !dba.DeletedAt.IsZero() {
|
if !dba.DeletedAt.IsZero() {
|
||||||
|
@ -134,8 +142,8 @@ func (db *DB) CreateAdmin(ctx context.Context, adm *mgmt.Admin) error {
|
||||||
dba := &dbAdmin{
|
dba := &dbAdmin{
|
||||||
ID: adm.ID,
|
ID: adm.ID,
|
||||||
AuthorityID: db.authorityID,
|
AuthorityID: db.authorityID,
|
||||||
|
ProvisionerID: adm.ProvisionerID,
|
||||||
Name: adm.Name,
|
Name: adm.Name,
|
||||||
Provisioner: adm.Provisioner,
|
|
||||||
IsSuperAdmin: adm.IsSuperAdmin,
|
IsSuperAdmin: adm.IsSuperAdmin,
|
||||||
CreatedAt: clock.Now(),
|
CreatedAt: clock.Now(),
|
||||||
}
|
}
|
||||||
|
@ -156,7 +164,7 @@ func (db *DB) UpdateAdmin(ctx context.Context, adm *mgmt.Admin) error {
|
||||||
if old.DeletedAt.IsZero() && adm.Status == mgmt.StatusDeleted {
|
if old.DeletedAt.IsZero() && adm.Status == mgmt.StatusDeleted {
|
||||||
nu.DeletedAt = clock.Now()
|
nu.DeletedAt = clock.Now()
|
||||||
}
|
}
|
||||||
nu.Provisioner = adm.Provisioner
|
nu.ProvisionerID = adm.ProvisionerID
|
||||||
nu.IsSuperAdmin = adm.IsSuperAdmin
|
nu.IsSuperAdmin = adm.IsSuperAdmin
|
||||||
|
|
||||||
return db.save(ctx, old.ID, nu, old, "admin", authorityAdminsTable)
|
return db.save(ctx, old.ID, nu, old, "admin", authorityAdminsTable)
|
||||||
|
|
401
authority/mgmt/provisioner.go
Normal file
401
authority/mgmt/provisioner.go
Normal file
|
@ -0,0 +1,401 @@
|
||||||
|
package mgmt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/smallstep/certificates/authority/provisioner"
|
||||||
|
"go.step.sm/crypto/jose"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProvisionerOption func(*ProvisionerCtx)
|
||||||
|
|
||||||
|
type ProvisionerCtx struct {
|
||||||
|
JWK *jose.JSONWebKey
|
||||||
|
JWE *jose.JSONWebEncryption
|
||||||
|
X509Template, SSHTemplate string
|
||||||
|
X509TemplateData, SSHTemplateData []byte
|
||||||
|
Claims *Claims
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithJWK(jwk *jose.JSONWebKey, jwe *jose.JSONWebEncryption) func(*ProvisionerCtx) {
|
||||||
|
return func(ctx *ProvisionerCtx) {
|
||||||
|
ctx.JWK = jwk
|
||||||
|
ctx.JWE = jwe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithPassword(pass string) func(*ProvisionerCtx) {
|
||||||
|
return func(ctx *ProvisionerCtx) {
|
||||||
|
ctx.Password = pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provisioner type.
|
||||||
|
type Provisioner struct {
|
||||||
|
ID string `json:"-"`
|
||||||
|
AuthorityID string `json:"-"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Claims *Claims `json:"claims"`
|
||||||
|
Details interface{} `json:"details"`
|
||||||
|
X509Template string `json:"x509Template"`
|
||||||
|
X509TemplateData []byte `json:"x509TemplateData"`
|
||||||
|
SSHTemplate string `json:"sshTemplate"`
|
||||||
|
SSHTemplateData []byte `json:"sshTemplateData"`
|
||||||
|
Status StatusType `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provisioner) GetOptions() *provisioner.Options {
|
||||||
|
return &provisioner.Options{
|
||||||
|
X509: &provisioner.X509Options{
|
||||||
|
Template: p.X509Template,
|
||||||
|
TemplateData: p.X509TemplateData,
|
||||||
|
},
|
||||||
|
SSH: &provisioner.SSHOptions{
|
||||||
|
Template: p.SSHTemplate,
|
||||||
|
TemplateData: p.SSHTemplateData,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateProvisioner(ctx context.Context, db DB, typ, name string, opts ...ProvisionerOption) (*Provisioner, error) {
|
||||||
|
pc := new(ProvisionerCtx)
|
||||||
|
for _, o := range opts {
|
||||||
|
o(pc)
|
||||||
|
}
|
||||||
|
|
||||||
|
details, err := createJWKDetails(pc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &Provisioner{
|
||||||
|
Type: typ,
|
||||||
|
Name: name,
|
||||||
|
Claims: pc.Claims,
|
||||||
|
Details: details,
|
||||||
|
X509Template: pc.X509Template,
|
||||||
|
X509TemplateData: pc.X509TemplateData,
|
||||||
|
SSHTemplate: pc.SSHTemplate,
|
||||||
|
SSHTemplateData: pc.SSHTemplateData,
|
||||||
|
Status: StatusActive,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.CreateProvisioner(ctx, p); err != nil {
|
||||||
|
return nil, WrapErrorISE(err, "error creating provisioner")
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProvisionerDetails_JWK struct {
|
||||||
|
PubKey []byte `json:"pubKey"`
|
||||||
|
PrivKey string `json:"privKey"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func createJWKDetails(pc *ProvisionerCtx) (*ProvisionerDetails_JWK, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if pc.JWK != nil && pc.JWE == nil {
|
||||||
|
return nil, NewErrorISE("JWE is required with JWK for createJWKProvisioner")
|
||||||
|
}
|
||||||
|
if pc.JWE != nil && pc.JWK == nil {
|
||||||
|
return nil, NewErrorISE("JWK is required with JWE for createJWKProvisioner")
|
||||||
|
}
|
||||||
|
if pc.JWK == nil && pc.JWE == nil {
|
||||||
|
// Create a new JWK w/ encrypted private key.
|
||||||
|
if pc.Password == "" {
|
||||||
|
return nil, NewErrorISE("password is required to provisioner with new keys")
|
||||||
|
}
|
||||||
|
pc.JWK, pc.JWE, err = jose.GenerateDefaultKeyPair([]byte(pc.Password))
|
||||||
|
if err != nil {
|
||||||
|
return nil, WrapErrorISE(err, "error generating JWK key pair")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jwkPubBytes, err := pc.JWK.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return nil, WrapErrorISE(err, "error marshaling JWK")
|
||||||
|
}
|
||||||
|
jwePrivStr, err := pc.JWE.CompactSerialize()
|
||||||
|
if err != nil {
|
||||||
|
return nil, WrapErrorISE(err, "error serializing JWE")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ProvisionerDetails_JWK{
|
||||||
|
PubKey: jwkPubBytes,
|
||||||
|
PrivKey: jwePrivStr,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToCertificates converts the landlord provisioner type to the open source
|
||||||
|
// provisioner type.
|
||||||
|
func (p *Provisioner) ToCertificates() (provisioner.Interface, error) {
|
||||||
|
claims, err := p.Claims.ToCertificates()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch details := p.Details.(type) {
|
||||||
|
case *ProvisionerDetails_JWK:
|
||||||
|
jwk := new(jose.JSONWebKey)
|
||||||
|
if err := json.Unmarshal(details.PubKey, &jwk); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &provisioner.JWK{
|
||||||
|
Type: p.Type,
|
||||||
|
Name: p.Name,
|
||||||
|
Key: jwk,
|
||||||
|
EncryptedKey: details.PrivKey,
|
||||||
|
Claims: claims,
|
||||||
|
Options: p.GetOptions(),
|
||||||
|
}, nil
|
||||||
|
/*
|
||||||
|
case *ProvisionerDetails_OIDC:
|
||||||
|
cfg := d.OIDC
|
||||||
|
return &provisioner.OIDC{
|
||||||
|
Type: p.Type.String(),
|
||||||
|
Name: p.Name,
|
||||||
|
TenantID: cfg.TenantId,
|
||||||
|
ClientID: cfg.ClientId,
|
||||||
|
ClientSecret: cfg.ClientSecret,
|
||||||
|
ConfigurationEndpoint: cfg.ConfigurationEndpoint,
|
||||||
|
Admins: cfg.Admins,
|
||||||
|
Domains: cfg.Domains,
|
||||||
|
Groups: cfg.Groups,
|
||||||
|
ListenAddress: cfg.ListenAddress,
|
||||||
|
Claims: claims,
|
||||||
|
Options: options,
|
||||||
|
}, nil
|
||||||
|
case *ProvisionerDetails_GCP:
|
||||||
|
cfg := d.GCP
|
||||||
|
return &provisioner.GCP{
|
||||||
|
Type: p.Type.String(),
|
||||||
|
Name: p.Name,
|
||||||
|
ServiceAccounts: cfg.ServiceAccounts,
|
||||||
|
ProjectIDs: cfg.ProjectIds,
|
||||||
|
DisableCustomSANs: cfg.DisableCustomSans,
|
||||||
|
DisableTrustOnFirstUse: cfg.DisableTrustOnFirstUse,
|
||||||
|
InstanceAge: durationValue(cfg.InstanceAge),
|
||||||
|
Claims: claims,
|
||||||
|
Options: options,
|
||||||
|
}, nil
|
||||||
|
case *ProvisionerDetails_AWS:
|
||||||
|
cfg := d.AWS
|
||||||
|
return &provisioner.AWS{
|
||||||
|
Type: p.Type.String(),
|
||||||
|
Name: p.Name,
|
||||||
|
Accounts: cfg.Accounts,
|
||||||
|
DisableCustomSANs: cfg.DisableCustomSans,
|
||||||
|
DisableTrustOnFirstUse: cfg.DisableTrustOnFirstUse,
|
||||||
|
InstanceAge: durationValue(cfg.InstanceAge),
|
||||||
|
Claims: claims,
|
||||||
|
Options: options,
|
||||||
|
}, nil
|
||||||
|
case *ProvisionerDetails_Azure:
|
||||||
|
cfg := d.Azure
|
||||||
|
return &provisioner.Azure{
|
||||||
|
Type: p.Type.String(),
|
||||||
|
Name: p.Name,
|
||||||
|
TenantID: cfg.TenantId,
|
||||||
|
ResourceGroups: cfg.ResourceGroups,
|
||||||
|
Audience: cfg.Audience,
|
||||||
|
DisableCustomSANs: cfg.DisableCustomSans,
|
||||||
|
DisableTrustOnFirstUse: cfg.DisableTrustOnFirstUse,
|
||||||
|
Claims: claims,
|
||||||
|
Options: options,
|
||||||
|
}, nil
|
||||||
|
case *ProvisionerDetails_X5C:
|
||||||
|
var roots []byte
|
||||||
|
for i, k := range d.X5C.GetRoots() {
|
||||||
|
if b := k.GetKey().GetPublic(); b != nil {
|
||||||
|
if i > 0 {
|
||||||
|
roots = append(roots, '\n')
|
||||||
|
}
|
||||||
|
roots = append(roots, b...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &provisioner.X5C{
|
||||||
|
Type: p.Type.String(),
|
||||||
|
Name: p.Name,
|
||||||
|
Roots: roots,
|
||||||
|
Claims: claims,
|
||||||
|
Options: options,
|
||||||
|
}, nil
|
||||||
|
case *ProvisionerDetails_K8SSA:
|
||||||
|
var publicKeys []byte
|
||||||
|
for i, k := range d.K8SSA.GetPublicKeys() {
|
||||||
|
if b := k.GetKey().GetPublic(); b != nil {
|
||||||
|
if i > 0 {
|
||||||
|
publicKeys = append(publicKeys, '\n')
|
||||||
|
}
|
||||||
|
publicKeys = append(publicKeys, k.Key.Public...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &provisioner.K8sSA{
|
||||||
|
Type: p.Type.String(),
|
||||||
|
Name: p.Name,
|
||||||
|
PubKeys: publicKeys,
|
||||||
|
Claims: claims,
|
||||||
|
Options: options,
|
||||||
|
}, nil
|
||||||
|
case *ProvisionerDetails_SSHPOP:
|
||||||
|
return &provisioner.SSHPOP{
|
||||||
|
Type: p.Type.String(),
|
||||||
|
Name: p.Name,
|
||||||
|
Claims: claims,
|
||||||
|
}, nil
|
||||||
|
case *ProvisionerDetails_ACME:
|
||||||
|
cfg := d.ACME
|
||||||
|
return &provisioner.ACME{
|
||||||
|
Type: p.Type.String(),
|
||||||
|
Name: p.Name,
|
||||||
|
ForceCN: cfg.ForceCn,
|
||||||
|
Claims: claims,
|
||||||
|
Options: options,
|
||||||
|
}, nil
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("provisioner %s not implemented", p.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToCertificates converts the landlord provisioner claims type to the open source
|
||||||
|
// (step-ca) claims type.
|
||||||
|
func (c *Claims) ToCertificates() (*provisioner.Claims, error) {
|
||||||
|
var durs = map[string]struct {
|
||||||
|
durStr string
|
||||||
|
dur *provisioner.Duration
|
||||||
|
}{
|
||||||
|
"minTLSDur": {durStr: c.X509.Durations.Min},
|
||||||
|
"maxTLSDur": {durStr: c.X509.Durations.Max},
|
||||||
|
"defaultTLSDur": {durStr: c.X509.Durations.Default},
|
||||||
|
"minSSHUserDur": {durStr: c.SSH.UserDurations.Min},
|
||||||
|
"maxSSHUserDur": {durStr: c.SSH.UserDurations.Max},
|
||||||
|
"defaultSSHUserDur": {durStr: c.SSH.UserDurations.Default},
|
||||||
|
"minSSHHostDur": {durStr: c.SSH.HostDurations.Min},
|
||||||
|
"maxSSHHostDur": {durStr: c.SSH.HostDurations.Max},
|
||||||
|
"defaultSSHHostDur": {durStr: c.SSH.HostDurations.Default},
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
for k, v := range durs {
|
||||||
|
v.dur, err = provisioner.NewDuration(v.durStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, WrapErrorISE(err, "error parsing %s %s from claims", k, v.durStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &provisioner.Claims{
|
||||||
|
MinTLSDur: durs["minTLSDur"].dur,
|
||||||
|
MaxTLSDur: durs["maxTLSDur"].dur,
|
||||||
|
DefaultTLSDur: durs["defaultTLSDur"].dur,
|
||||||
|
DisableRenewal: &c.DisableRenewal,
|
||||||
|
MinUserSSHDur: durs["minSSHUserDur"].dur,
|
||||||
|
MaxUserSSHDur: durs["maxSSHUserDur"].dur,
|
||||||
|
DefaultUserSSHDur: durs["defaultSSHUserDur"].dur,
|
||||||
|
MinHostSSHDur: durs["minSSHHostDur"].dur,
|
||||||
|
MaxHostSSHDur: durs["maxSSHHostDur"].dur,
|
||||||
|
DefaultHostSSHDur: durs["defaultSSHHostDur"].dur,
|
||||||
|
EnableSSHCA: &c.SSH.Enabled,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func marshalDetails(d *ProvisionerDetails) (sql.NullString, error) {
|
||||||
|
b, err := json.Marshal(d.GetData())
|
||||||
|
if err != nil {
|
||||||
|
return sql.NullString{}, nil
|
||||||
|
}
|
||||||
|
return sql.NullString{
|
||||||
|
String: string(b),
|
||||||
|
Valid: len(b) > 0,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalDetails(ctx context.Context, db database.DB, typ ProvisionerType, s sql.NullString) (*ProvisionerDetails, error) {
|
||||||
|
if !s.Valid {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var v isProvisionerDetails_Data
|
||||||
|
switch typ {
|
||||||
|
case ProvisionerType_JWK:
|
||||||
|
p := new(ProvisionerDetails_JWK)
|
||||||
|
if err := json.Unmarshal([]byte(s.String), p); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if p.JWK.Key.Key == nil {
|
||||||
|
key, err := LoadKey(ctx, db, p.JWK.Key.Id.Id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.JWK.Key = key
|
||||||
|
}
|
||||||
|
return &ProvisionerDetails{Data: p}, nil
|
||||||
|
case ProvisionerType_OIDC:
|
||||||
|
v = new(ProvisionerDetails_OIDC)
|
||||||
|
case ProvisionerType_GCP:
|
||||||
|
v = new(ProvisionerDetails_GCP)
|
||||||
|
case ProvisionerType_AWS:
|
||||||
|
v = new(ProvisionerDetails_AWS)
|
||||||
|
case ProvisionerType_AZURE:
|
||||||
|
v = new(ProvisionerDetails_Azure)
|
||||||
|
case ProvisionerType_ACME:
|
||||||
|
v = new(ProvisionerDetails_ACME)
|
||||||
|
case ProvisionerType_X5C:
|
||||||
|
p := new(ProvisionerDetails_X5C)
|
||||||
|
if err := json.Unmarshal([]byte(s.String), p); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, k := range p.X5C.GetRoots() {
|
||||||
|
if err := k.Select(ctx, db, k.Id.Id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &ProvisionerDetails{Data: p}, nil
|
||||||
|
case ProvisionerType_K8SSA:
|
||||||
|
p := new(ProvisionerDetails_K8SSA)
|
||||||
|
if err := json.Unmarshal([]byte(s.String), p); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, k := range p.K8SSA.GetPublicKeys() {
|
||||||
|
if err := k.Select(ctx, db, k.Id.Id); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &ProvisionerDetails{Data: p}, nil
|
||||||
|
case ProvisionerType_SSHPOP:
|
||||||
|
v = new(ProvisionerDetails_SSHPOP)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported provisioner type %s", typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(s.String), v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ProvisionerDetails{Data: v}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshalClaims(c *Claims) (sql.NullString, error) {
|
||||||
|
b, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return sql.NullString{}, nil
|
||||||
|
}
|
||||||
|
return sql.NullString{
|
||||||
|
String: string(b),
|
||||||
|
Valid: len(b) > 0,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmarshalClaims(s sql.NullString) (*Claims, error) {
|
||||||
|
if !s.Valid {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
v := new(Claims)
|
||||||
|
return v, json.Unmarshal([]byte(s.String), v)
|
||||||
|
}
|
||||||
|
*/
|
Loading…
Reference in a new issue