feat: http provider signing key addition (#10641)

# Which Problems Are Solved

HTTP Request to HTTP providers for Email or SMS are not signed.

# How the Problems Are Solved

Add a Signing Key to the HTTP Provider resources, which is then used to
generate a header to sign the payload.

# Additional Changes

Additional tests for query side of the SMTP provider.

# Additional Context

Closes #10067

---------

Co-authored-by: Marco A. <marco@zitadel.com>
(cherry picked from commit 8909b9a2a6)
This commit is contained in:
Stefan Benz
2025-09-08 13:00:04 +02:00
committed by Livio Spring
parent d2d94ea088
commit 1a7cd6e1af
36 changed files with 2113 additions and 132 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"testing"
"time"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
@@ -306,9 +307,11 @@ func TestCommandSide_ChangeSMSConfigTwilio(t *testing.T) {
func TestCommandSide_AddSMSConfigHTTP(t *testing.T) {
type fields struct {
eventstore func(t *testing.T) *eventstore.Eventstore
idGenerator id.Generator
alg crypto.EncryptionAlgorithm
eventstore func(t *testing.T) *eventstore.Eventstore
idGenerator id.Generator
newEncryptedCodeWithDefault encryptedCodeWithDefaultFunc
defaultSecretGenerators *SecretGenerators
alg crypto.EncryptionAlgorithm
}
type args struct {
ctx context.Context
@@ -351,10 +354,18 @@ func TestCommandSide_AddSMSConfigHTTP(t *testing.T) {
"providerid",
"description",
"endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("12345678"),
},
),
),
),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "providerid"),
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "providerid"),
newEncryptedCodeWithDefault: mockEncryptedCodeWithDefault("12345678", time.Hour),
defaultSecretGenerators: &SecretGenerators{},
},
args: args{
ctx: context.Background(),
@@ -374,9 +385,11 @@ func TestCommandSide_AddSMSConfigHTTP(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
idGenerator: tt.fields.idGenerator,
smsEncryption: tt.fields.alg,
eventstore: tt.fields.eventstore(t),
idGenerator: tt.fields.idGenerator,
newEncryptedCodeWithDefault: tt.fields.newEncryptedCodeWithDefault,
defaultSecretGenerators: tt.fields.defaultSecretGenerators,
smsEncryption: tt.fields.alg,
}
err := r.AddSMSConfigHTTP(tt.args.ctx, tt.args.http)
if tt.res.err == nil {
@@ -394,7 +407,9 @@ func TestCommandSide_AddSMSConfigHTTP(t *testing.T) {
func TestCommandSide_ChangeSMSConfigHTTP(t *testing.T) {
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
eventstore func(*testing.T) *eventstore.Eventstore
newEncryptedCodeWithDefault encryptedCodeWithDefaultFunc
defaultSecretGenerators *SecretGenerators
}
type args struct {
ctx context.Context
@@ -474,6 +489,12 @@ func TestCommandSide_ChangeSMSConfigHTTP(t *testing.T) {
"providerid",
"description",
"endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("12345678"),
},
),
),
),
@@ -505,6 +526,12 @@ func TestCommandSide_ChangeSMSConfigHTTP(t *testing.T) {
"providerid",
"description",
"endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("12345678"),
},
),
),
),
@@ -514,17 +541,26 @@ func TestCommandSide_ChangeSMSConfigHTTP(t *testing.T) {
"providerid",
"endpoint2",
"description2",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("87654321"),
},
),
),
),
newEncryptedCodeWithDefault: mockEncryptedCodeWithDefault("87654321", time.Hour),
defaultSecretGenerators: &SecretGenerators{},
},
args: args{
ctx: context.Background(),
http: &ChangeSMSHTTP{
ResourceOwner: "INSTANCE",
ID: "providerid",
Description: gu.Ptr("description2"),
Endpoint: gu.Ptr("endpoint2"),
ResourceOwner: "INSTANCE",
ID: "providerid",
Description: gu.Ptr("description2"),
Endpoint: gu.Ptr("endpoint2"),
ExpirationSigningKey: true,
},
},
res: res{
@@ -537,7 +573,9 @@ func TestCommandSide_ChangeSMSConfigHTTP(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
eventstore: tt.fields.eventstore(t),
newEncryptedCodeWithDefault: tt.fields.newEncryptedCodeWithDefault,
defaultSecretGenerators: tt.fields.defaultSecretGenerators,
}
err := r.ChangeSMSConfigHTTP(tt.args.ctx, tt.args.http)
if tt.res.err == nil {
@@ -707,6 +745,12 @@ func TestCommandSide_ActivateSMSConfig(t *testing.T) {
"providerid",
"description",
"endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("12345678"),
},
),
),
),
@@ -917,6 +961,12 @@ func TestCommandSide_DeactivateSMSConfig(t *testing.T) {
"providerid",
"description",
"endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("12345678"),
},
),
),
eventFromEventPusher(
@@ -1083,6 +1133,12 @@ func TestCommandSide_RemoveSMSConfig(t *testing.T) {
"providerid",
"description",
"endpoint",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("12345678"),
},
),
),
),
@@ -1141,10 +1197,11 @@ func newSMSConfigTwilioChangedEvent(ctx context.Context, id, sid, senderName, de
return event
}
func newSMSConfigHTTPChangedEvent(ctx context.Context, id, endpoint, description string) *instance.SMSConfigHTTPChangedEvent {
func newSMSConfigHTTPChangedEvent(ctx context.Context, id, endpoint, description string, signingKey *crypto.CryptoValue) *instance.SMSConfigHTTPChangedEvent {
changes := []instance.SMSConfigHTTPChanges{
instance.ChangeSMSConfigHTTPEndpoint(endpoint),
instance.ChangeSMSConfigHTTPDescription(description),
instance.ChangeSMSConfigHTTPSigningKey(signingKey),
}
event, _ := instance.NewSMSConfigHTTPChangedEvent(ctx,
&instance.NewAggregate("INSTANCE").Aggregate,