mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 20:47:22 +00:00
fix: add register org and key pairs (#1275)
This commit is contained in:
parent
fbc75d89b2
commit
3bc3ef1f2c
@ -100,13 +100,6 @@ Auth:
|
|||||||
ConcurrentWorkers: 1
|
ConcurrentWorkers: 1
|
||||||
BulkLimit: 10000
|
BulkLimit: 10000
|
||||||
FailureCountUntilSkip: 5
|
FailureCountUntilSkip: 5
|
||||||
KeyConfig:
|
|
||||||
Size: 2048
|
|
||||||
PrivateKeyLifetime: 6h
|
|
||||||
PublicKeyLifetime: 30h
|
|
||||||
EncryptionConfig:
|
|
||||||
EncryptionKeyID: $ZITADEL_OIDC_KEYS_ID
|
|
||||||
SigningKeyRotation: 10s
|
|
||||||
|
|
||||||
Admin:
|
Admin:
|
||||||
SearchLimit: 1000
|
SearchLimit: 1000
|
||||||
|
@ -129,4 +129,11 @@ SystemDefaults:
|
|||||||
ID: $ZITADEL_DEFAULT_DOMAIN
|
ID: $ZITADEL_DEFAULT_DOMAIN
|
||||||
OriginLogin: $ZITADEL_ACCOUNTS
|
OriginLogin: $ZITADEL_ACCOUNTS
|
||||||
OriginConsole: $ZITADEL_CONSOLE
|
OriginConsole: $ZITADEL_CONSOLE
|
||||||
DisplayName: ZITADEL
|
DisplayName: ZITADEL
|
||||||
|
KeyConfig:
|
||||||
|
Size: 2048
|
||||||
|
PrivateKeyLifetime: 6h
|
||||||
|
PublicKeyLifetime: 30h
|
||||||
|
EncryptionConfig:
|
||||||
|
EncryptionKeyID: $ZITADEL_OIDC_KEYS_ID
|
||||||
|
SigningKeyRotation: 10s
|
@ -131,7 +131,7 @@ func (o *OPStorage) GetKeySet(ctx context.Context) (_ *jose.JSONWebKeySet, err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *OPStorage) SaveNewKeyPair(ctx context.Context) error {
|
func (o *OPStorage) SaveNewKeyPair(ctx context.Context) error {
|
||||||
return o.repo.GenerateSigningKeyPair(ctx, o.signingKeyAlgorithm)
|
return o.command.GenerateSigningKeyPair(ctx, o.signingKeyAlgorithm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OPStorage) assertProjectRoleScopes(app *proj_model.ApplicationView, scopes []string) ([]string, error) {
|
func (o *OPStorage) assertProjectRoleScopes(app *proj_model.ApplicationView, scopes []string) ([]string, error) {
|
||||||
|
@ -6,29 +6,14 @@ import (
|
|||||||
|
|
||||||
"gopkg.in/square/go-jose.v2"
|
"gopkg.in/square/go-jose.v2"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/authz"
|
|
||||||
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
||||||
"github.com/caos/zitadel/internal/key/model"
|
|
||||||
key_event "github.com/caos/zitadel/internal/key/repository/eventsourcing"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
oidcUser = "OIDC"
|
|
||||||
iamOrg = "IAM"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type KeyRepository struct {
|
type KeyRepository struct {
|
||||||
KeyEvents *key_event.KeyEventstore
|
|
||||||
View *view.View
|
View *view.View
|
||||||
SigningKeyRotation time.Duration
|
SigningKeyRotation time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KeyRepository) GenerateSigningKeyPair(ctx context.Context, algorithm string) error {
|
|
||||||
ctx = setOIDCCtx(ctx)
|
|
||||||
_, err := k.KeyEvents.GenerateKeyPair(ctx, model.KeyUsageSigning, algorithm)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KeyRepository) GetSigningKey(ctx context.Context, keyCh chan<- jose.SigningKey, errCh chan<- error, renewTimer <-chan time.Time) {
|
func (k *KeyRepository) GetSigningKey(ctx context.Context, keyCh chan<- jose.SigningKey, errCh chan<- error, renewTimer <-chan time.Time) {
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
@ -69,7 +54,3 @@ func (k *KeyRepository) refreshSigningKey(keyCh chan<- jose.SigningKey, errCh ch
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setOIDCCtx(ctx context.Context) context.Context {
|
|
||||||
return authz.SetCtxData(ctx, authz.CtxData{UserID: oidcUser, OrgID: iamOrg})
|
|
||||||
}
|
|
||||||
|
@ -11,10 +11,7 @@ import (
|
|||||||
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
|
|
||||||
auth_model "github.com/caos/zitadel/internal/auth/model"
|
|
||||||
auth_view "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
auth_view "github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/sdk"
|
|
||||||
org_model "github.com/caos/zitadel/internal/org/model"
|
org_model "github.com/caos/zitadel/internal/org/model"
|
||||||
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
|
org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing"
|
||||||
"github.com/caos/zitadel/internal/org/repository/view/model"
|
"github.com/caos/zitadel/internal/org/repository/view/model"
|
||||||
@ -55,51 +52,6 @@ func (repo *OrgRepository) SearchOrgs(ctx context.Context, request *org_model.Or
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *OrgRepository) RegisterOrg(ctx context.Context, register *auth_model.RegisterOrg) (*auth_model.RegisterOrg, error) {
|
|
||||||
pwPolicy, err := repo.View.PasswordComplexityPolicyByAggregateID(repo.SystemDefaults.IamID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pwPolicyView := iam_view_model.PasswordComplexityViewToModel(pwPolicy)
|
|
||||||
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
orgPolicyView := iam_view_model.OrgIAMViewToModel(orgPolicy)
|
|
||||||
users := func(ctx context.Context, domain string) ([]*es_models.Aggregate, error) {
|
|
||||||
userIDs, err := repo.View.UserIDsByDomain(domain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return repo.UserEventstore.PrepareDomainClaimed(ctx, userIDs)
|
|
||||||
}
|
|
||||||
org, aggregates, err := repo.OrgEventstore.PrepareCreateOrg(ctx, register.Org, users)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
user, userAggregates, err := repo.UserEventstore.PrepareRegisterUser(ctx, register.User, nil, pwPolicyView, orgPolicyView, org.AggregateID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
aggregates = append(aggregates, userAggregates...)
|
|
||||||
registerModel := &Register{Org: org, User: user}
|
|
||||||
|
|
||||||
member := org_model.NewOrgMemberWithRoles(org.AggregateID, user.AggregateID, orgOwnerRole)
|
|
||||||
_, memberAggregate, err := repo.OrgEventstore.PrepareAddOrgMember(ctx, member, org.AggregateID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
aggregates = append(aggregates, memberAggregate)
|
|
||||||
|
|
||||||
err = sdk.PushAggregates(ctx, repo.OrgEventstore.PushAggregates, registerModel.AppendEvents, aggregates...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return RegisterToModel(registerModel), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (repo *OrgRepository) GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error) {
|
func (repo *OrgRepository) GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error) {
|
||||||
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
|
orgPolicy, err := repo.View.OrgIAMPolicyByAggregateID(repo.SystemDefaults.IamID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -16,7 +16,6 @@ import (
|
|||||||
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
|
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
|
||||||
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
|
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
|
||||||
"github.com/caos/zitadel/internal/id"
|
"github.com/caos/zitadel/internal/id"
|
||||||
es_key "github.com/caos/zitadel/internal/key/repository/eventsourcing"
|
|
||||||
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
|
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
|
||||||
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
|
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
|
||||||
es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing"
|
es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing"
|
||||||
@ -31,7 +30,6 @@ type Config struct {
|
|||||||
AuthRequest cache.Config
|
AuthRequest cache.Config
|
||||||
View types.SQL
|
View types.SQL
|
||||||
Spooler spooler.SpoolerConfig
|
Spooler spooler.SpoolerConfig
|
||||||
KeyConfig es_key.KeyConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type EsRepository struct {
|
type EsRepository struct {
|
||||||
@ -59,7 +57,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
keyAlgorithm, err := crypto.NewAESCrypto(conf.KeyConfig.EncryptionConfig)
|
keyAlgorithm, err := crypto.NewAESCrypto(systemDefaults.KeyConfig.EncryptionConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -85,10 +83,6 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := es_key.StartKey(es, conf.KeyConfig, keyAlgorithm, idGenerator)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
iam, err := es_iam.StartIAM(
|
iam, err := es_iam.StartIAM(
|
||||||
es_iam.IAMConfig{
|
es_iam.IAMConfig{
|
||||||
Eventstore: es,
|
Eventstore: es,
|
||||||
@ -158,9 +152,8 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, co
|
|||||||
View: view,
|
View: view,
|
||||||
},
|
},
|
||||||
eventstore.KeyRepository{
|
eventstore.KeyRepository{
|
||||||
KeyEvents: key,
|
|
||||||
View: view,
|
View: view,
|
||||||
SigningKeyRotation: conf.KeyConfig.SigningKeyRotation.Duration,
|
SigningKeyRotation: systemDefaults.KeyConfig.SigningKeyRotation.Duration,
|
||||||
},
|
},
|
||||||
eventstore.ApplicationRepo{
|
eventstore.ApplicationRepo{
|
||||||
View: view,
|
View: view,
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type KeyRepository interface {
|
type KeyRepository interface {
|
||||||
GenerateSigningKeyPair(ctx context.Context, algorithm string) error
|
|
||||||
GetSigningKey(ctx context.Context, keyCh chan<- jose.SigningKey, errCh chan<- error, timer <-chan time.Time)
|
GetSigningKey(ctx context.Context, keyCh chan<- jose.SigningKey, errCh chan<- error, timer <-chan time.Time)
|
||||||
GetKeySet(ctx context.Context) (*jose.JSONWebKeySet, error)
|
GetKeySet(ctx context.Context) (*jose.JSONWebKeySet, error)
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,10 @@ package repository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
auth_model "github.com/caos/zitadel/internal/auth/model"
|
|
||||||
iam_model "github.com/caos/zitadel/internal/iam/model"
|
iam_model "github.com/caos/zitadel/internal/iam/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OrgRepository interface {
|
type OrgRepository interface {
|
||||||
RegisterOrg(context.Context, *auth_model.RegisterOrg) (*auth_model.RegisterOrg, error)
|
|
||||||
GetOrgIAMPolicy(ctx context.Context, orgID string) (*iam_model.OrgIAMPolicyView, error)
|
GetOrgIAMPolicy(ctx context.Context, orgID string) (*iam_model.OrgIAMPolicyView, error)
|
||||||
GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error)
|
GetDefaultOrgIAMPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error)
|
||||||
GetIDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error)
|
GetIDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error)
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
|
es_spol "github.com/caos/zitadel/internal/eventstore/spooler"
|
||||||
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
|
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
|
||||||
"github.com/caos/zitadel/internal/id"
|
"github.com/caos/zitadel/internal/id"
|
||||||
es_key "github.com/caos/zitadel/internal/key/repository/eventsourcing"
|
|
||||||
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
|
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,7 +26,6 @@ type Config struct {
|
|||||||
AuthRequest cache.Config
|
AuthRequest cache.Config
|
||||||
View types.SQL
|
View types.SQL
|
||||||
Spooler spooler.SpoolerConfig
|
Spooler spooler.SpoolerConfig
|
||||||
KeyConfig es_key.KeyConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type EsRepository struct {
|
type EsRepository struct {
|
||||||
|
@ -24,6 +24,7 @@ type SystemDefaults struct {
|
|||||||
IamID string
|
IamID string
|
||||||
Notifications Notifications
|
Notifications Notifications
|
||||||
WebAuthN WebAuthN
|
WebAuthN WebAuthN
|
||||||
|
KeyConfig KeyConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type ZitadelDocs struct {
|
type ZitadelDocs struct {
|
||||||
@ -97,3 +98,11 @@ type WebAuthN struct {
|
|||||||
OriginConsole string
|
OriginConsole string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type KeyConfig struct {
|
||||||
|
Size int
|
||||||
|
PrivateKeyLifetime types.Duration
|
||||||
|
PublicKeyLifetime types.Duration
|
||||||
|
EncryptionConfig *crypto.KeyConfig
|
||||||
|
SigningKeyRotation types.Duration
|
||||||
|
}
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
package eventsourcing
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/config/types"
|
|
||||||
"github.com/caos/zitadel/internal/crypto"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
|
||||||
es_int "github.com/caos/zitadel/internal/eventstore"
|
|
||||||
"github.com/caos/zitadel/internal/eventstore/models"
|
|
||||||
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
|
|
||||||
"github.com/caos/zitadel/internal/id"
|
|
||||||
key_model "github.com/caos/zitadel/internal/key/model"
|
|
||||||
"github.com/caos/zitadel/internal/key/repository/eventsourcing/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
type KeyEventstore struct {
|
|
||||||
es_int.Eventstore
|
|
||||||
keySize int
|
|
||||||
keyAlgorithm crypto.EncryptionAlgorithm
|
|
||||||
privateKeyLifetime time.Duration
|
|
||||||
publicKeyLifetime time.Duration
|
|
||||||
idGenerator id.Generator
|
|
||||||
}
|
|
||||||
|
|
||||||
type KeyConfig struct {
|
|
||||||
Size int
|
|
||||||
PrivateKeyLifetime types.Duration
|
|
||||||
PublicKeyLifetime types.Duration
|
|
||||||
EncryptionConfig *crypto.KeyConfig
|
|
||||||
SigningKeyRotation types.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func StartKey(eventstore es_int.Eventstore, config KeyConfig, keyAlgorithm crypto.EncryptionAlgorithm, generator id.Generator) (*KeyEventstore, error) {
|
|
||||||
return &KeyEventstore{
|
|
||||||
Eventstore: eventstore,
|
|
||||||
keySize: config.Size,
|
|
||||||
keyAlgorithm: keyAlgorithm,
|
|
||||||
privateKeyLifetime: config.PrivateKeyLifetime.Duration,
|
|
||||||
publicKeyLifetime: config.PublicKeyLifetime.Duration,
|
|
||||||
idGenerator: generator,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (es *KeyEventstore) GenerateKeyPair(ctx context.Context, usage key_model.KeyUsage, algorithm string) (*key_model.KeyPair, error) {
|
|
||||||
privateKey, publicKey, err := crypto.GenerateEncryptedKeyPair(es.keySize, es.keyAlgorithm)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
privateKeyExp := time.Now().UTC().Add(es.privateKeyLifetime)
|
|
||||||
publicKeyExp := time.Now().UTC().Add(es.publicKeyLifetime)
|
|
||||||
return es.CreateKeyPair(ctx, &key_model.KeyPair{
|
|
||||||
ObjectRoot: models.ObjectRoot{},
|
|
||||||
Usage: usage,
|
|
||||||
Algorithm: algorithm,
|
|
||||||
PrivateKey: &key_model.Key{
|
|
||||||
Key: privateKey,
|
|
||||||
Expiry: privateKeyExp,
|
|
||||||
},
|
|
||||||
PublicKey: &key_model.Key{
|
|
||||||
Key: publicKey,
|
|
||||||
Expiry: publicKeyExp,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (es *KeyEventstore) CreateKeyPair(ctx context.Context, pair *key_model.KeyPair) (*key_model.KeyPair, error) {
|
|
||||||
if !pair.IsValid() {
|
|
||||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-G34ga", "Name is required")
|
|
||||||
}
|
|
||||||
id, err := es.idGenerator.Next()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pair.AggregateID = id
|
|
||||||
repoKey := model.KeyPairFromModel(pair)
|
|
||||||
|
|
||||||
createAggregate := KeyPairCreateAggregate(es.AggregateCreator(), repoKey)
|
|
||||||
err = es_sdk.Push(ctx, es.PushAggregates, repoKey.AppendEvents, createAggregate)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return model.KeyPairToModel(repoKey), nil
|
|
||||||
}
|
|
@ -1,9 +1,6 @@
|
|||||||
package eventsourcing
|
package eventsourcing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/errors"
|
|
||||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||||
"github.com/caos/zitadel/internal/key/repository/eventsourcing/model"
|
"github.com/caos/zitadel/internal/key/repository/eventsourcing/model"
|
||||||
)
|
)
|
||||||
@ -13,21 +10,3 @@ func KeyPairQuery(latestSequence uint64) *es_models.SearchQuery {
|
|||||||
AggregateTypeFilter(model.KeyPairAggregate).
|
AggregateTypeFilter(model.KeyPairAggregate).
|
||||||
LatestSequenceFilter(latestSequence)
|
LatestSequenceFilter(latestSequence)
|
||||||
}
|
}
|
||||||
|
|
||||||
func KeyPairAggregate(ctx context.Context, aggCreator *es_models.AggregateCreator, pair *model.KeyPair) (*es_models.Aggregate, error) {
|
|
||||||
if pair == nil {
|
|
||||||
return nil, errors.ThrowPreconditionFailed(nil, "EVENT-d5HNJA", "existing key pair must not be nil")
|
|
||||||
}
|
|
||||||
return aggCreator.NewAggregate(ctx, pair.AggregateID, model.KeyPairAggregate, model.KeyPairVersion, pair.Sequence)
|
|
||||||
}
|
|
||||||
|
|
||||||
func KeyPairCreateAggregate(aggCreator *es_models.AggregateCreator, pair *model.KeyPair) func(ctx context.Context) (*es_models.Aggregate, error) {
|
|
||||||
return func(ctx context.Context) (*es_models.Aggregate, error) {
|
|
||||||
agg, err := KeyPairAggregate(ctx, aggCreator, pair)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return agg.AppendEvent(model.KeyPairAdded, pair)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,10 +4,7 @@ import (
|
|||||||
"github.com/caos/zitadel/internal/v2/domain"
|
"github.com/caos/zitadel/internal/v2/domain"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
auth_model "github.com/caos/zitadel/internal/auth/model"
|
|
||||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||||
org_model "github.com/caos/zitadel/internal/org/model"
|
|
||||||
usr_model "github.com/caos/zitadel/internal/user/model"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -61,11 +58,7 @@ func (l *Login) handleRegisterOrgCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
registerOrg := &auth_model.RegisterOrg{
|
err = l.command.SetUpOrg(setContext(r.Context(), ""), data.toOrgDomain(), data.toUserDomain())
|
||||||
User: data.toUserModel(),
|
|
||||||
Org: data.toOrgModel(),
|
|
||||||
}
|
|
||||||
user, err := l.authRepo.RegisterOrg(setContext(r.Context(), ""), registerOrg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.renderRegisterOrg(w, r, authRequest, data, err)
|
l.renderRegisterOrg(w, r, authRequest, data, err)
|
||||||
return
|
return
|
||||||
@ -74,7 +67,6 @@ func (l *Login) handleRegisterOrgCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Redirect(w, r, l.zitadelURL, http.StatusFound)
|
http.Redirect(w, r, l.zitadelURL, http.StatusFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
authRequest.LoginName = user.PreferredLoginName
|
|
||||||
l.renderNextStep(w, r, authRequest)
|
l.renderNextStep(w, r, authRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,29 +109,27 @@ func (l *Login) renderRegisterOrg(w http.ResponseWriter, r *http.Request, authRe
|
|||||||
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplRegisterOrg], data, nil)
|
l.renderer.RenderTemplate(w, r, l.renderer.Templates[tmplRegisterOrg], data, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d registerOrgFormData) toUserModel() *usr_model.User {
|
func (d registerOrgFormData) toUserDomain() *domain.Human {
|
||||||
if d.Username == "" {
|
if d.Username == "" {
|
||||||
d.Username = d.Email
|
d.Username = d.Email
|
||||||
}
|
}
|
||||||
return &usr_model.User{
|
return &domain.Human{
|
||||||
UserName: d.Username,
|
Username: d.Username,
|
||||||
Human: &usr_model.Human{
|
Profile: &domain.Profile{
|
||||||
Profile: &usr_model.Profile{
|
FirstName: d.Firstname,
|
||||||
FirstName: d.Firstname,
|
LastName: d.Lastname,
|
||||||
LastName: d.Lastname,
|
},
|
||||||
},
|
Password: &domain.Password{
|
||||||
Password: &usr_model.Password{
|
SecretString: d.Password,
|
||||||
SecretString: d.Password,
|
},
|
||||||
},
|
Email: &domain.Email{
|
||||||
Email: &usr_model.Email{
|
EmailAddress: d.Email,
|
||||||
EmailAddress: d.Email,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d registerOrgFormData) toOrgModel() *org_model.Org {
|
func (d registerOrgFormData) toOrgDomain() *domain.Org {
|
||||||
return &org_model.Org{
|
return &domain.Org{
|
||||||
Name: d.RegisterOrgName,
|
Name: d.RegisterOrgName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/caos/zitadel/internal/api/http"
|
"github.com/caos/zitadel/internal/api/http"
|
||||||
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
sd "github.com/caos/zitadel/internal/config/systemdefaults"
|
||||||
@ -11,6 +12,7 @@ import (
|
|||||||
global_model "github.com/caos/zitadel/internal/model"
|
global_model "github.com/caos/zitadel/internal/model"
|
||||||
"github.com/caos/zitadel/internal/telemetry/tracing"
|
"github.com/caos/zitadel/internal/telemetry/tracing"
|
||||||
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
|
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"
|
"github.com/caos/zitadel/internal/v2/repository/org"
|
||||||
proj_repo "github.com/caos/zitadel/internal/v2/repository/project"
|
proj_repo "github.com/caos/zitadel/internal/v2/repository/project"
|
||||||
usr_repo "github.com/caos/zitadel/internal/v2/repository/user"
|
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
|
//TODO: remove global model, or move to domain
|
||||||
multifactors global_model.Multifactors
|
multifactors global_model.Multifactors
|
||||||
webauthn *webauthn_helper.WebAuthN
|
webauthn *webauthn_helper.WebAuthN
|
||||||
|
|
||||||
|
keySize int
|
||||||
|
keyAlgorithm crypto.EncryptionAlgorithm
|
||||||
|
privateKeyLifetime time.Duration
|
||||||
|
publicKeyLifetime time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -48,15 +55,19 @@ type Config struct {
|
|||||||
|
|
||||||
func StartCommandSide(config *Config) (repo *CommandSide, err error) {
|
func StartCommandSide(config *Config) (repo *CommandSide, err error) {
|
||||||
repo = &CommandSide{
|
repo = &CommandSide{
|
||||||
eventstore: config.Eventstore,
|
eventstore: config.Eventstore,
|
||||||
idGenerator: id.SonyFlakeGenerator,
|
idGenerator: id.SonyFlakeGenerator,
|
||||||
iamDomain: config.SystemDefaults.Domain,
|
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)
|
iam_repo.RegisterEventMappers(repo.eventstore)
|
||||||
org.RegisterEventMappers(repo.eventstore)
|
org.RegisterEventMappers(repo.eventstore)
|
||||||
usr_repo.RegisterEventMappers(repo.eventstore)
|
usr_repo.RegisterEventMappers(repo.eventstore)
|
||||||
usr_grant_repo.RegisterEventMappers(repo.eventstore)
|
usr_grant_repo.RegisterEventMappers(repo.eventstore)
|
||||||
proj_repo.RegisterEventMappers(repo.eventstore)
|
proj_repo.RegisterEventMappers(repo.eventstore)
|
||||||
|
keypair.RegisterEventMappers(repo.eventstore)
|
||||||
|
|
||||||
//TODO: simplify!!!!
|
//TODO: simplify!!!!
|
||||||
repo.idpConfigSecretCrypto, err = crypto.NewAESCrypto(config.SystemDefaults.IDPConfigVerificationKey)
|
repo.idpConfigSecretCrypto, err = crypto.NewAESCrypto(config.SystemDefaults.IDPConfigVerificationKey)
|
||||||
@ -99,6 +110,12 @@ func StartCommandSide(config *Config) (repo *CommandSide, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
repo.webauthn = web
|
repo.webauthn = web
|
||||||
|
|
||||||
|
keyAlgorithm, err := crypto.NewAESCrypto(config.SystemDefaults.KeyConfig.EncryptionConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
repo.keyAlgorithm = keyAlgorithm
|
||||||
return repo, nil
|
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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user