Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pkg/settings/cresettings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ flowchart
subgraph PerWorkflow.Secrets
PerWorkflow.Secrets.CallLimit{{CallLimit}}:::bound
end
subgraph PerOrg.HTTPAction
PerOrg.HTTPAction.MtlsAuthAllowed[/PerOrg.HTTPAction.MtlsAuthAllowed/]:::gate
end
end
subgraph vault
VaultCiphertextSizeLimit{{VaultCiphertextSizeLimit}}:::bound
Expand Down
5 changes: 4 additions & 1 deletion pkg/settings/cresettings/defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@
"PerOrg": {
"BaseTriggerRetransmitEnabled": "false",
"WorkflowExecutionConcurrencyLimit": "100",
"ZeroBalancePruningTimeout": "24h0m0s"
"ZeroBalancePruningTimeout": "24h0m0s",
"HTTPAction": {
"MtlsAuthAllowed": "false"
}
},
"PerOwner": {
"WorkflowLimit": "1000",
Expand Down
3 changes: 3 additions & 0 deletions pkg/settings/cresettings/defaults.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ BaseTriggerRetransmitEnabled = 'false'
WorkflowExecutionConcurrencyLimit = '100'
ZeroBalancePruningTimeout = '24h0m0s'

[PerOrg.HTTPAction]
MtlsAuthAllowed = 'false'

[PerOwner]
WorkflowLimit = '1000'
WorkflowExecutionConcurrencyLimit = '5'
Expand Down
19 changes: 13 additions & 6 deletions pkg/settings/cresettings/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,12 @@ var Default = Schema{
VaultMaxPerOracleUnexpiredBlobCount: Int(1000),

PerOrg: Orgs{
BaseTriggerRetransmitEnabled: Bool(false),
BaseTriggerRetransmitEnabled: Bool(false),
WorkflowExecutionConcurrencyLimit: Int(100),
ZeroBalancePruningTimeout: Duration(24 * time.Hour),
HTTPAction: perOrgHTTPAction{
MtlsAuthAllowed: Bool(false),
},
},
PerOwner: Owners{
WorkflowLimit: Int(1000),
Expand Down Expand Up @@ -260,10 +263,10 @@ type Schema struct {
GatewayConfidentialRelayPerNodeRate Setting[config.Rate]
TriggerRegistrationStatusUpdateTimeout Setting[time.Duration]

BaseTriggerRetryInterval Setting[time.Duration]
BaseTriggerMaxRetries Setting[int] `unit:"{attempt}"`
BaseTriggerPruneAge Setting[time.Duration]
BaseTriggerMaxSendsPerTick Setting[int] `unit:"{event}"`
BaseTriggerRetryInterval Setting[time.Duration]
BaseTriggerMaxRetries Setting[int] `unit:"{attempt}"`
BaseTriggerPruneAge Setting[time.Duration]
BaseTriggerMaxSendsPerTick Setting[int] `unit:"{event}"`

VaultCiphertextSizeLimit Setting[config.Size]
VaultShareSizeLimit Setting[config.Size]
Expand All @@ -289,9 +292,10 @@ type Schema struct {
PerWorkflow Workflows `scope:"workflow"`
}
type Orgs struct {
BaseTriggerRetransmitEnabled Setting[bool]
BaseTriggerRetransmitEnabled Setting[bool]
WorkflowExecutionConcurrencyLimit Setting[int] `unit:"{workflow}"`
ZeroBalancePruningTimeout Setting[time.Duration]
HTTPAction perOrgHTTPAction
}

type Owners struct {
Expand Down Expand Up @@ -396,6 +400,9 @@ type httpAction struct {
RequestSizeLimit Setting[config.Size]
ResponseSizeLimit Setting[config.Size]
}
type perOrgHTTPAction struct {
MtlsAuthAllowed Setting[bool]
}
type confidentialHTTP struct {
CallLimit Setting[int] `unit:"{call}"`
ConnectionTimeout Setting[time.Duration]
Expand Down
2 changes: 1 addition & 1 deletion pkg/settings/cresettings/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func TestSchema_Unmarshal(t *testing.T) {
"GatewayUnauthenticatedRequestRateLimit": "200rps:50",
"GatewayUnauthenticatedRequestRateLimitPerIP": "1rps:100",
"GatewayIncomingPayloadSizeLimit": "14kb",
"GatewayVaultManagementEnabled": "true",
"GatewayVaultManagementEnabled": "true",
"GatewayConfidentialRelayGlobalRate": "20rps:7",
"GatewayConfidentialRelayPerNodeRate": "4rps:2",
"PerOrg": {
Expand Down
16 changes: 16 additions & 0 deletions pkg/types/gateway/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ type CacheSettings struct {
ReadFromCache bool `json:"readFromCache,omitempty"` // If true, attempt to read a cached response for the request
}

type Secret []byte

func (s Secret) String() string { return "[REDACTED]" }

type MtlsAuth struct {
PrivateKey Secret `json:"privateKey"`
Certificate []byte `json:"certificate"`
}

// OutboundHTTPRequest represents an HTTP request to be sent from workflow node to the gateway.
type OutboundHTTPRequest struct {
URL string `json:"url"` // URL to query, only http and https protocols are supported.
Expand All @@ -35,6 +44,7 @@ type OutboundHTTPRequest struct {
Body []byte `json:"body,omitempty"` // HTTP request body
TimeoutMs uint32 `json:"timeoutMs,omitempty"` // Timeout in milliseconds
CacheSettings CacheSettings `json:"cacheSettings"` // Best-effort cache control for the request
Mtls *MtlsAuth `json:"mtlsAuth,omitempty"` // Client certificate for mTLS requests

// Maximum number of bytes to read from the response body. If the gateway max response size is smaller than this value, the gateway max response size will be used.
MaxResponseBytes uint32 `json:"maxBytes,omitempty"`
Expand Down Expand Up @@ -62,6 +72,12 @@ func (req OutboundHTTPRequest) Hash() string {

s.Write([]byte(strconv.FormatUint(uint64(req.MaxResponseBytes), 10)))

if req.Mtls != nil {
s.Write(req.Mtls.PrivateKey)
s.Write(sep)
s.Write(req.Mtls.Certificate)
}

return hex.EncodeToString(s.Sum(nil))
}

Expand Down
83 changes: 83 additions & 0 deletions pkg/types/gateway/action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ func TestOutboundHTTPRequest_Hash(t *testing.T) {
WorkflowOwner: "owner",
MultiHeaders: map[string][]string{"A": {"1", "2"}},
}
baseWithMtls := OutboundHTTPRequest{
Method: "GET",
URL: "https://example.com/",
WorkflowOwner: "owner",
Mtls: &MtlsAuth{
PrivateKey: Secret("priv-key"),
Certificate: []byte("cert"),
},
}

tests := []struct {
name string
Expand Down Expand Up @@ -111,6 +120,80 @@ func TestOutboundHTTPRequest_Hash(t *testing.T) {
},
sameHash: false,
},
{
name: "Same Mtls values yields same hash",
reqA: baseWithMtls,
reqB: OutboundHTTPRequest{
Method: "GET",
URL: "https://example.com/",
WorkflowOwner: "owner",
Mtls: &MtlsAuth{
PrivateKey: Secret("priv-key"),
Certificate: []byte("cert"),
},
},
sameHash: true,
},
{
name: "Nil Mtls vs non-nil Mtls yields different hash",
reqA: OutboundHTTPRequest{
Method: "GET",
URL: "https://example.com/",
WorkflowOwner: "owner",
},
reqB: baseWithMtls,
sameHash: false,
},
{
name: "Different Mtls PrivateKey yields different hash",
reqA: baseWithMtls,
reqB: OutboundHTTPRequest{
Method: "GET",
URL: "https://example.com/",
WorkflowOwner: "owner",
Mtls: &MtlsAuth{
PrivateKey: Secret("other-key"),
Certificate: []byte("cert"),
},
},
sameHash: false,
},
{
name: "Different Mtls Certificate yields different hash",
reqA: baseWithMtls,
reqB: OutboundHTTPRequest{
Method: "GET",
URL: "https://example.com/",
WorkflowOwner: "owner",
Mtls: &MtlsAuth{
PrivateKey: Secret("priv-key"),
Certificate: []byte("other-cert"),
},
},
sameHash: false,
},
{
name: "Shifting bytes between Mtls PrivateKey and Certificate yields different hash",
reqA: OutboundHTTPRequest{
Method: "GET",
URL: "https://example.com/",
WorkflowOwner: "owner",
Mtls: &MtlsAuth{
PrivateKey: Secret("ab"),
Certificate: []byte("cd"),
},
},
reqB: OutboundHTTPRequest{
Method: "GET",
URL: "https://example.com/",
WorkflowOwner: "owner",
Mtls: &MtlsAuth{
PrivateKey: Secret("abc"),
Certificate: []byte("d"),
},
},
sameHash: false,
},
}

for _, tt := range tests {
Expand Down
Loading