Skip to content

Commit 8a3236b

Browse files
committed
Merge branch 'main' into rtinianov_teeWorkflows
2 parents 0e49c59 + d1ced0e commit 8a3236b

9 files changed

Lines changed: 125 additions & 5 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ require (
4949
github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b
5050
github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260205130626-db2a2aab956b
5151
github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0
52-
github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997
52+
github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260528173149-f5b8336b19d9
5353
github.com/smartcontractkit/freeport v0.1.3-0.20250716200817-cb5dfd0e369e
5454
github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7
5555
github.com/smartcontractkit/libocr v0.0.0-20250912173940-f3ab0246e23d

go.sum

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/settings/cresettings/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ flowchart
5050
GatewayHTTPPerNodeRate[\GatewayHTTPPerNodeRate/]:::rate
5151
GatewayConfidentialRelayGlobalRate[\GatewayConfidentialRelayGlobalRate/]:::rate
5252
GatewayConfidentialRelayPerNodeRate[\GatewayConfidentialRelayPerNodeRate/]:::rate
53+
GatewayHTTPActionMtlsRequestRate[\GatewayHTTPActionMtlsRequestRate/]:::rate
5354
end
5455
%% TODO unused
5556
%% PerOrg.ZeroBalancePruningTimeout
@@ -216,6 +217,9 @@ flowchart
216217
subgraph PerWorkflow.Secrets
217218
PerWorkflow.Secrets.CallLimit{{CallLimit}}:::bound
218219
end
220+
subgraph PerOrg.HTTPAction
221+
PerOrg.HTTPAction.MtlsRateLimit{{PerOrg.HTTPAction.MtlsRateLimit}}:::bound
222+
end
219223
end
220224
subgraph vault
221225
VaultCiphertextSizeLimit{{VaultCiphertextSizeLimit}}:::bound

pkg/settings/cresettings/defaults.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"GatewayHTTPPerNodeRate": "100rps:100",
1414
"GatewayConfidentialRelayGlobalRate": "50rps:10",
1515
"GatewayConfidentialRelayPerNodeRate": "10rps:10",
16+
"GatewayHTTPActionMtlsRequestRate": "every30s:0",
1617
"TriggerRegistrationStatusUpdateTimeout": "0s",
1718
"BaseTriggerRetryInterval": "30s",
1819
"BaseTriggerMaxRetries": "20",
@@ -38,7 +39,10 @@
3839
"PerOrg": {
3940
"BaseTriggerRetransmitEnabled": "false",
4041
"WorkflowExecutionConcurrencyLimit": "100",
41-
"ZeroBalancePruningTimeout": "24h0m0s"
42+
"ZeroBalancePruningTimeout": "24h0m0s",
43+
"HTTPAction": {
44+
"MtlsRateLimit": "every30s:3"
45+
}
4246
},
4347
"PerOwner": {
4448
"WorkflowLimit": "1000",

pkg/settings/cresettings/defaults.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ GatewayHTTPGlobalRate = '500rps:500'
1212
GatewayHTTPPerNodeRate = '100rps:100'
1313
GatewayConfidentialRelayGlobalRate = '50rps:10'
1414
GatewayConfidentialRelayPerNodeRate = '10rps:10'
15+
GatewayHTTPActionMtlsRequestRate = 'every30s:0'
1516
TriggerRegistrationStatusUpdateTimeout = '0s'
1617
BaseTriggerRetryInterval = '30s'
1718
BaseTriggerMaxRetries = '20'
@@ -40,6 +41,9 @@ BaseTriggerRetransmitEnabled = 'false'
4041
WorkflowExecutionConcurrencyLimit = '100'
4142
ZeroBalancePruningTimeout = '24h0m0s'
4243

44+
[PerOrg.HTTPAction]
45+
MtlsRateLimit = 'every30s:3'
46+
4347
[PerOwner]
4448
WorkflowLimit = '1000'
4549
WorkflowExecutionConcurrencyLimit = '5'

pkg/settings/cresettings/settings.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ var Default = Schema{
6767
GatewayHTTPPerNodeRate: Rate(rate.Limit(100), 100),
6868
GatewayConfidentialRelayGlobalRate: Rate(rate.Limit(50), 10),
6969
GatewayConfidentialRelayPerNodeRate: Rate(rate.Limit(10), 10),
70+
GatewayHTTPActionMtlsRequestRate: Rate(rate.Every(30*time.Second), 0),
7071
TriggerRegistrationStatusUpdateTimeout: Duration(0 * time.Second),
7172
BaseTriggerRetryInterval: Duration(30 * time.Second),
7273
BaseTriggerMaxRetries: Int(20),
@@ -129,6 +130,9 @@ var Default = Schema{
129130
BaseTriggerRetransmitEnabled: Bool(false),
130131
WorkflowExecutionConcurrencyLimit: Int(100),
131132
ZeroBalancePruningTimeout: Duration(24 * time.Hour),
133+
HTTPAction: perOrgHTTPAction{
134+
MtlsRateLimit: Rate(rate.Every(30*time.Second), 3),
135+
},
132136
},
133137
PerOwner: Owners{
134138
WorkflowLimit: Int(1000),
@@ -263,6 +267,7 @@ type Schema struct {
263267
GatewayHTTPPerNodeRate Setting[config.Rate]
264268
GatewayConfidentialRelayGlobalRate Setting[config.Rate]
265269
GatewayConfidentialRelayPerNodeRate Setting[config.Rate]
270+
GatewayHTTPActionMtlsRequestRate Setting[config.Rate]
266271
TriggerRegistrationStatusUpdateTimeout Setting[time.Duration]
267272

268273
BaseTriggerRetryInterval Setting[time.Duration]
@@ -297,6 +302,7 @@ type Orgs struct {
297302
BaseTriggerRetransmitEnabled Setting[bool]
298303
WorkflowExecutionConcurrencyLimit Setting[int] `unit:"{workflow}"`
299304
ZeroBalancePruningTimeout Setting[time.Duration]
305+
HTTPAction perOrgHTTPAction
300306
}
301307

302308
type Owners struct {
@@ -401,6 +407,9 @@ type httpAction struct {
401407
RequestSizeLimit Setting[config.Size]
402408
ResponseSizeLimit Setting[config.Size]
403409
}
410+
type perOrgHTTPAction struct {
411+
MtlsRateLimit Setting[config.Rate]
412+
}
404413
type confidentialHTTP struct {
405414
CallLimit Setting[int] `unit:"{call}"`
406415
ConnectionTimeout Setting[time.Duration]

pkg/settings/cresettings/settings_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func TestSchema_Unmarshal(t *testing.T) {
7070
"GatewayUnauthenticatedRequestRateLimit": "200rps:50",
7171
"GatewayUnauthenticatedRequestRateLimitPerIP": "1rps:100",
7272
"GatewayIncomingPayloadSizeLimit": "14kb",
73-
"GatewayVaultManagementEnabled": "true",
73+
"GatewayVaultManagementEnabled": "true",
7474
"GatewayConfidentialRelayGlobalRate": "20rps:7",
7575
"GatewayConfidentialRelayPerNodeRate": "4rps:2",
7676
"PerOrg": {

pkg/types/gateway/action.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ type CacheSettings struct {
2323
ReadFromCache bool `json:"readFromCache,omitempty"` // If true, attempt to read a cached response for the request
2424
}
2525

26+
type Secret []byte
27+
28+
func (s Secret) String() string { return "[REDACTED]" }
29+
30+
type MtlsAuth struct {
31+
PrivateKey Secret `json:"privateKey"`
32+
Certificate []byte `json:"certificate"`
33+
}
34+
2635
// OutboundHTTPRequest represents an HTTP request to be sent from workflow node to the gateway.
2736
type OutboundHTTPRequest struct {
2837
URL string `json:"url"` // URL to query, only http and https protocols are supported.
@@ -35,6 +44,7 @@ type OutboundHTTPRequest struct {
3544
Body []byte `json:"body,omitempty"` // HTTP request body
3645
TimeoutMs uint32 `json:"timeoutMs,omitempty"` // Timeout in milliseconds
3746
CacheSettings CacheSettings `json:"cacheSettings"` // Best-effort cache control for the request
47+
Mtls *MtlsAuth `json:"mtlsAuth,omitempty"` // Client certificate for mTLS requests
3848

3949
// 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.
4050
MaxResponseBytes uint32 `json:"maxBytes,omitempty"`
@@ -62,6 +72,12 @@ func (req OutboundHTTPRequest) Hash() string {
6272

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

75+
if req.Mtls != nil {
76+
s.Write(req.Mtls.PrivateKey)
77+
s.Write(sep)
78+
s.Write(req.Mtls.Certificate)
79+
}
80+
6581
return hex.EncodeToString(s.Sum(nil))
6682
}
6783

pkg/types/gateway/action_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ func TestOutboundHTTPRequest_Hash(t *testing.T) {
1919
WorkflowOwner: "owner",
2020
MultiHeaders: map[string][]string{"A": {"1", "2"}},
2121
}
22+
baseWithMtls := OutboundHTTPRequest{
23+
Method: "GET",
24+
URL: "https://example.com/",
25+
WorkflowOwner: "owner",
26+
Mtls: &MtlsAuth{
27+
PrivateKey: Secret("priv-key"),
28+
Certificate: []byte("cert"),
29+
},
30+
}
2231

2332
tests := []struct {
2433
name string
@@ -111,6 +120,80 @@ func TestOutboundHTTPRequest_Hash(t *testing.T) {
111120
},
112121
sameHash: false,
113122
},
123+
{
124+
name: "Same Mtls values yields same hash",
125+
reqA: baseWithMtls,
126+
reqB: OutboundHTTPRequest{
127+
Method: "GET",
128+
URL: "https://example.com/",
129+
WorkflowOwner: "owner",
130+
Mtls: &MtlsAuth{
131+
PrivateKey: Secret("priv-key"),
132+
Certificate: []byte("cert"),
133+
},
134+
},
135+
sameHash: true,
136+
},
137+
{
138+
name: "Nil Mtls vs non-nil Mtls yields different hash",
139+
reqA: OutboundHTTPRequest{
140+
Method: "GET",
141+
URL: "https://example.com/",
142+
WorkflowOwner: "owner",
143+
},
144+
reqB: baseWithMtls,
145+
sameHash: false,
146+
},
147+
{
148+
name: "Different Mtls PrivateKey yields different hash",
149+
reqA: baseWithMtls,
150+
reqB: OutboundHTTPRequest{
151+
Method: "GET",
152+
URL: "https://example.com/",
153+
WorkflowOwner: "owner",
154+
Mtls: &MtlsAuth{
155+
PrivateKey: Secret("other-key"),
156+
Certificate: []byte("cert"),
157+
},
158+
},
159+
sameHash: false,
160+
},
161+
{
162+
name: "Different Mtls Certificate yields different hash",
163+
reqA: baseWithMtls,
164+
reqB: OutboundHTTPRequest{
165+
Method: "GET",
166+
URL: "https://example.com/",
167+
WorkflowOwner: "owner",
168+
Mtls: &MtlsAuth{
169+
PrivateKey: Secret("priv-key"),
170+
Certificate: []byte("other-cert"),
171+
},
172+
},
173+
sameHash: false,
174+
},
175+
{
176+
name: "Shifting bytes between Mtls PrivateKey and Certificate yields different hash",
177+
reqA: OutboundHTTPRequest{
178+
Method: "GET",
179+
URL: "https://example.com/",
180+
WorkflowOwner: "owner",
181+
Mtls: &MtlsAuth{
182+
PrivateKey: Secret("ab"),
183+
Certificate: []byte("cd"),
184+
},
185+
},
186+
reqB: OutboundHTTPRequest{
187+
Method: "GET",
188+
URL: "https://example.com/",
189+
WorkflowOwner: "owner",
190+
Mtls: &MtlsAuth{
191+
PrivateKey: Secret("abc"),
192+
Certificate: []byte("d"),
193+
},
194+
},
195+
sameHash: false,
196+
},
114197
}
115198

116199
for _, tt := range tests {

0 commit comments

Comments
 (0)