mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 18:17:35 +00:00
fix: add register org and key pairs (#1275)
This commit is contained in:
@@ -2,6 +2,7 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/http"
|
||||
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
global_model "github.com/caos/zitadel/internal/model"
|
||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
||||
keypair "github.com/caos/zitadel/internal/v2/repository/keypair"
|
||||
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||
proj_repo "github.com/caos/zitadel/internal/v2/repository/project"
|
||||
usr_repo "github.com/caos/zitadel/internal/v2/repository/user"
|
||||
@@ -39,6 +41,11 @@ type CommandSide struct {
|
||||
//TODO: remove global model, or move to domain
|
||||
multifactors global_model.Multifactors
|
||||
webauthn *webauthn_helper.WebAuthN
|
||||
|
||||
keySize int
|
||||
keyAlgorithm crypto.EncryptionAlgorithm
|
||||
privateKeyLifetime time.Duration
|
||||
publicKeyLifetime time.Duration
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -48,15 +55,19 @@ type Config struct {
|
||||
|
||||
func StartCommandSide(config *Config) (repo *CommandSide, err error) {
|
||||
repo = &CommandSide{
|
||||
eventstore: config.Eventstore,
|
||||
idGenerator: id.SonyFlakeGenerator,
|
||||
iamDomain: config.SystemDefaults.Domain,
|
||||
eventstore: config.Eventstore,
|
||||
idGenerator: id.SonyFlakeGenerator,
|
||||
iamDomain: config.SystemDefaults.Domain,
|
||||
keySize: config.SystemDefaults.KeyConfig.Size,
|
||||
privateKeyLifetime: config.SystemDefaults.KeyConfig.PrivateKeyLifetime.Duration,
|
||||
publicKeyLifetime: config.SystemDefaults.KeyConfig.PublicKeyLifetime.Duration,
|
||||
}
|
||||
iam_repo.RegisterEventMappers(repo.eventstore)
|
||||
org.RegisterEventMappers(repo.eventstore)
|
||||
usr_repo.RegisterEventMappers(repo.eventstore)
|
||||
usr_grant_repo.RegisterEventMappers(repo.eventstore)
|
||||
proj_repo.RegisterEventMappers(repo.eventstore)
|
||||
keypair.RegisterEventMappers(repo.eventstore)
|
||||
|
||||
//TODO: simplify!!!!
|
||||
repo.idpConfigSecretCrypto, err = crypto.NewAESCrypto(config.SystemDefaults.IDPConfigVerificationKey)
|
||||
@@ -99,6 +110,12 @@ func StartCommandSide(config *Config) (repo *CommandSide, err error) {
|
||||
return nil, err
|
||||
}
|
||||
repo.webauthn = web
|
||||
|
||||
keyAlgorithm, err := crypto.NewAESCrypto(config.SystemDefaults.KeyConfig.EncryptionConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.keyAlgorithm = keyAlgorithm
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
|
45
internal/v2/command/key_pair.go
Normal file
45
internal/v2/command/key_pair.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
keypair "github.com/caos/zitadel/internal/v2/repository/keypair"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
oidcUser = "OIDC"
|
||||
)
|
||||
|
||||
func (r *CommandSide) GenerateSigningKeyPair(ctx context.Context, algorithm string) error {
|
||||
ctx = setOIDCCtx(ctx)
|
||||
privateCrypto, publicCrypto, err := crypto.GenerateEncryptedKeyPair(r.keySize, r.keyAlgorithm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyID, err := r.idGenerator.Next()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
privateKeyExp := time.Now().UTC().Add(r.privateKeyLifetime)
|
||||
publicKeyExp := time.Now().UTC().Add(r.publicKeyLifetime)
|
||||
|
||||
keyPairWriteModel := NewKeyPairWriteModel(keyID, domain.IAMID)
|
||||
keyAgg := KeyPairAggregateFromWriteModel(&keyPairWriteModel.WriteModel)
|
||||
keyAgg.PushEvents(
|
||||
keypair.NewAddedEvent(
|
||||
ctx,
|
||||
domain.KeyUsageSigning,
|
||||
algorithm,
|
||||
privateCrypto, publicCrypto,
|
||||
privateKeyExp, publicKeyExp),
|
||||
)
|
||||
return r.eventstore.PushAggregate(ctx, keyPairWriteModel, keyAgg)
|
||||
}
|
||||
|
||||
func setOIDCCtx(ctx context.Context) context.Context {
|
||||
return authz.SetCtxData(ctx, authz.CtxData{UserID: oidcUser, OrgID: domain.IAMID})
|
||||
}
|
61
internal/v2/command/key_pair_model.go
Normal file
61
internal/v2/command/key_pair_model.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
keypair "github.com/caos/zitadel/internal/v2/repository/keypair"
|
||||
"github.com/caos/zitadel/internal/v2/repository/project"
|
||||
)
|
||||
|
||||
type KeyPairWriteModel struct {
|
||||
eventstore.WriteModel
|
||||
|
||||
Usage domain.KeyUsage
|
||||
Algorithm string
|
||||
PrivateKey *domain.Key
|
||||
PublicKey *domain.Key
|
||||
}
|
||||
|
||||
func NewKeyPairWriteModel(aggregateID, resourceOwner string) *KeyPairWriteModel {
|
||||
return &KeyPairWriteModel{
|
||||
WriteModel: eventstore.WriteModel{
|
||||
AggregateID: aggregateID,
|
||||
ResourceOwner: resourceOwner,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (wm *KeyPairWriteModel) AppendEvents(events ...eventstore.EventReader) {
|
||||
wm.WriteModel.AppendEvents(events...)
|
||||
}
|
||||
|
||||
func (wm *KeyPairWriteModel) Reduce() error {
|
||||
for _, event := range wm.Events {
|
||||
switch e := event.(type) {
|
||||
case *keypair.AddedEvent:
|
||||
wm.Usage = e.Usage
|
||||
wm.Algorithm = e.Algorithm
|
||||
wm.PrivateKey = &domain.Key{
|
||||
Key: e.PrivateKey.Key,
|
||||
Expiry: e.PrivateKey.Expiry,
|
||||
}
|
||||
wm.PublicKey = &domain.Key{
|
||||
Key: e.PublicKey.Key,
|
||||
Expiry: e.PublicKey.Expiry,
|
||||
}
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *KeyPairWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, project.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
ResourceOwner(wm.ResourceOwner)
|
||||
}
|
||||
|
||||
func KeyPairAggregateFromWriteModel(wm *eventstore.WriteModel) *keypair.Aggregate {
|
||||
return &keypair.Aggregate{
|
||||
Aggregate: *eventstore.AggregateFromWriteModel(wm, keypair.AggregateType, keypair.AggregateVersion),
|
||||
}
|
||||
}
|
45
internal/v2/domain/key_pair.go
Normal file
45
internal/v2/domain/key_pair.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"time"
|
||||
)
|
||||
|
||||
type KeyPair struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
Usage KeyUsage
|
||||
Algorithm string
|
||||
PrivateKey *Key
|
||||
PublicKey *Key
|
||||
}
|
||||
|
||||
type KeyUsage int32
|
||||
|
||||
const (
|
||||
KeyUsageSigning KeyUsage = iota
|
||||
)
|
||||
|
||||
func (u KeyUsage) String() string {
|
||||
switch u {
|
||||
case KeyUsageSigning:
|
||||
return "sig"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
Key *crypto.CryptoValue
|
||||
Expiry time.Time
|
||||
}
|
||||
|
||||
func (k *KeyPair) IsValid() bool {
|
||||
return k.Algorithm != "" &&
|
||||
k.PrivateKey != nil && k.PrivateKey.IsValid() &&
|
||||
k.PublicKey != nil && k.PublicKey.IsValid()
|
||||
}
|
||||
|
||||
func (k *Key) IsValid() bool {
|
||||
return k.Key != nil
|
||||
}
|
14
internal/v2/repository/keypair/aggregate.go
Normal file
14
internal/v2/repository/keypair/aggregate.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package usergrant
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
AggregateType = "key_pair"
|
||||
AggregateVersion = "v1"
|
||||
)
|
||||
|
||||
type Aggregate struct {
|
||||
eventstore.Aggregate
|
||||
}
|
9
internal/v2/repository/keypair/eventstore.go
Normal file
9
internal/v2/repository/keypair/eventstore.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package usergrant
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
)
|
||||
|
||||
func RegisterEventMappers(es *eventstore.Eventstore) {
|
||||
es.RegisterFilterEventMapper(AddedEventType, AddedEventMapper)
|
||||
}
|
78
internal/v2/repository/keypair/key_pair.go
Normal file
78
internal/v2/repository/keypair/key_pair.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package usergrant
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2"
|
||||
"github.com/caos/zitadel/internal/eventstore/v2/repository"
|
||||
"github.com/caos/zitadel/internal/v2/domain"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
eventTypePrefix = eventstore.EventType("key_pair.")
|
||||
AddedEventType = eventTypePrefix + "added"
|
||||
)
|
||||
|
||||
type AddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
Usage domain.KeyUsage `json:"usage"`
|
||||
Algorithm string `json:"algorithm"`
|
||||
PrivateKey *Key `json:"privateKey"`
|
||||
PublicKey *Key `json:"publicKey"`
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
Key *crypto.CryptoValue `json:"key"`
|
||||
Expiry time.Time `json:"expiry"`
|
||||
}
|
||||
|
||||
func (e *AddedEvent) Data() interface{} {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *AddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewAddedEvent(
|
||||
ctx context.Context,
|
||||
usage domain.KeyUsage,
|
||||
algorithm string,
|
||||
privateCrypto,
|
||||
publicCrypto *crypto.CryptoValue,
|
||||
privateKeyExpiration,
|
||||
publicKeyExpiration time.Time) *AddedEvent {
|
||||
return &AddedEvent{
|
||||
BaseEvent: *eventstore.NewBaseEventForPush(
|
||||
ctx,
|
||||
AddedEventType,
|
||||
),
|
||||
Usage: usage,
|
||||
Algorithm: algorithm,
|
||||
PrivateKey: &Key{
|
||||
Key: privateCrypto,
|
||||
Expiry: privateKeyExpiration,
|
||||
},
|
||||
PublicKey: &Key{
|
||||
Key: publicCrypto,
|
||||
Expiry: publicKeyExpiration,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func AddedEventMapper(event *repository.Event) (eventstore.EventReader, error) {
|
||||
e := &AddedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
}
|
||||
|
||||
err := json.Unmarshal(event.Data, e)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "KEY-4n8vs", "unable to unmarshal key pair added")
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
Reference in New Issue
Block a user