certificates/authority/mgmt/config.go
2021-05-19 15:20:16 -07:00

357 lines
9.9 KiB
Go

package mgmt
import (
"github.com/smallstep/certificates/authority/config"
authority "github.com/smallstep/certificates/authority/config"
)
const (
DefaultAuthorityID = "00000000-0000-0000-0000-000000000000"
)
// StatusType is the type for status.
type StatusType int
const (
// StatusActive active
StatusActive StatusType = iota
// StatusDeleted deleted
StatusDeleted
)
type Claims struct {
*X509Claims `json:"x509Claims"`
*SSHClaims `json:"sshClaims"`
DisableRenewal *bool `json:"disableRenewal"`
}
type X509Claims struct {
Durations *Durations `json:"durations"`
}
type SSHClaims struct {
UserDuration *Durations `json:"userDurations"`
HostDuration *Durations `json:"hostDuration"`
}
type Durations struct {
Min string `json:"min"`
Max string `json:"max"`
Default string `json:"default"`
}
// Admin type.
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.
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"`
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 &provisioner.Duration{
Duration: time.Duration(d.Seconds)*time.Second + time.Duration(d.Nanos)*time.Nanosecond,
}
}
func durationValue(d *duration.Duration) provisioner.Duration {
if d == nil {
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) {
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)
}
*/