feat: action v2 signing (#8779)

# Which Problems Are Solved

The action v2 messages were didn't contain anything providing security
for the sent content.

# How the Problems Are Solved

Each Target now has a SigningKey, which can also be newly generated
through the API and returned at creation and through the Get-Endpoints.
There is now a HTTP header "Zitadel-Signature", which is generated with
the SigningKey and Payload, and also contains a timestamp to check with
a tolerance if the message took to long to sent.

# Additional Changes

The functionality to create and check the signature is provided in the
pkg/actions package, and can be reused in the SDK.

# Additional Context

Closes #7924

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Stefan Benz
2024-11-28 11:06:52 +01:00
committed by GitHub
parent 8537805ea5
commit 7caa43ab23
37 changed files with 745 additions and 122 deletions

View File

@@ -26,6 +26,7 @@ type mockExecutionTarget struct {
Endpoint string
Timeout time.Duration
InterruptOnError bool
SigningKey string
}
func (e *mockExecutionTarget) SetEndpoint(endpoint string) {
@@ -49,6 +50,9 @@ func (e *mockExecutionTarget) GetTargetID() string {
func (e *mockExecutionTarget) GetExecutionID() string {
return e.ExecutionID
}
func (e *mockExecutionTarget) GetSigningKey() string {
return e.SigningKey
}
type mockContentRequest struct {
Content string
@@ -157,6 +161,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetID: "target",
TargetType: domain.TargetTypeCall,
Timeout: time.Minute,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -186,6 +191,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
@@ -216,6 +222,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Second,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -245,6 +252,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Second,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -269,6 +277,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -297,6 +306,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetID: "target",
TargetType: domain.TargetTypeAsync,
Timeout: time.Second,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -325,6 +335,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetID: "target",
TargetType: domain.TargetTypeAsync,
Timeout: time.Minute,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -354,6 +365,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeWebhook,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -382,6 +394,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeWebhook,
Timeout: time.Second,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -411,6 +424,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeWebhook,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -440,6 +454,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
&mockExecutionTarget{
InstanceID: "instance",
@@ -448,6 +463,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
&mockExecutionTarget{
InstanceID: "instance",
@@ -456,6 +472,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
@@ -498,6 +515,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
&mockExecutionTarget{
InstanceID: "instance",
@@ -506,6 +524,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Second,
InterruptOnError: true,
SigningKey: "signingkey",
},
&mockExecutionTarget{
InstanceID: "instance",
@@ -514,6 +533,7 @@ func Test_executeTargetsForGRPCFullMethod_request(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Second,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -692,6 +712,7 @@ func Test_executeTargetsForGRPCFullMethod_response(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
targets: []target{
@@ -721,6 +742,7 @@ func Test_executeTargetsForGRPCFullMethod_response(t *testing.T) {
TargetType: domain.TargetTypeCall,
Timeout: time.Minute,
InterruptOnError: true,
SigningKey: "signingkey",
},
},
targets: []target{