1- use std:: collections:: BTreeMap ;
21use std:: sync:: Arc ;
32
3+ use crate :: execution:: hmac:: { sign_hmac, BooleanOrProgram } ;
44use crate :: executors:: common:: HttpExecutionResponse ;
55use crate :: executors:: dedupe:: { request_fingerprint, ABuildHasher , SharedResponse } ;
6- use crate :: utils:: expression:: execute_expression_with_value;
76use dashmap:: DashMap ;
87use hive_router_config:: HiveRouterConfig ;
98use tokio:: sync:: OnceCell ;
109
1110use async_trait:: async_trait;
1211
1312use bytes:: { BufMut , Bytes , BytesMut } ;
14- use hmac:: { Hmac , Mac } ;
1513use http:: HeaderMap ;
1614use http:: HeaderValue ;
1715use http_body_util:: BodyExt ;
1816use http_body_util:: Full ;
1917use hyper:: Version ;
2018use hyper_tls:: HttpsConnector ;
2119use hyper_util:: client:: legacy:: { connect:: HttpConnector , Client } ;
22- use sha2:: Sha256 ;
2320use tokio:: sync:: Semaphore ;
2421use tracing:: debug;
25- use vrl:: compiler:: Program as VrlProgram ;
2622
2723use crate :: executors:: common:: HttpExecutionRequest ;
2824use crate :: executors:: error:: SubgraphExecutorError ;
@@ -32,7 +28,6 @@ use crate::utils::consts::COLON;
3228use crate :: utils:: consts:: COMMA ;
3329use crate :: utils:: consts:: QUOTE ;
3430use crate :: { executors:: common:: SubgraphExecutor , json_writer:: write_and_escape_string} ;
35- use vrl:: core:: Value as VrlValue ;
3631
3732#[ derive( Debug ) ]
3833pub struct HTTPSubgraphExecutor {
@@ -48,18 +43,10 @@ pub struct HTTPSubgraphExecutor {
4843
4944const FIRST_VARIABLE_STR : & [ u8 ] = b",\" variables\" :{" ;
5045const FIRST_QUOTE_STR : & [ u8 ] = b"{\" query\" :" ;
51- const FIRST_EXTENSION_STR : & [ u8 ] = b",\" extensions\" :{" ;
46+ pub const FIRST_EXTENSION_STR : & [ u8 ] = b",\" extensions\" :{" ;
5247
5348pub type HttpClient = Client < HttpsConnector < HttpConnector > , Full < Bytes > > ;
5449
55- type HmacSha256 = Hmac < Sha256 > ;
56-
57- #[ derive( Debug ) ]
58- pub enum BooleanOrProgram {
59- Boolean ( bool ) ,
60- Program ( Box < VrlProgram > ) ,
61- }
62-
6350impl HTTPSubgraphExecutor {
6451 pub fn new (
6552 subgraph_name : String ,
@@ -92,80 +79,6 @@ impl HTTPSubgraphExecutor {
9279 }
9380 }
9481
95- fn sign_hmac (
96- & self ,
97- execution_request : & HttpExecutionRequest ,
98- body : & mut Vec < u8 > ,
99- first_extension : & mut bool ,
100- ) -> Result < ( ) , SubgraphExecutorError > {
101- let should_sign_hmac = match & self . should_sign_hmac . as_ref ( ) {
102- BooleanOrProgram :: Boolean ( b) => * b,
103- BooleanOrProgram :: Program ( expr) => {
104- // .subgraph
105- let subgraph_value = VrlValue :: Object ( BTreeMap :: from ( [ (
106- "name" . into ( ) ,
107- VrlValue :: Bytes ( Bytes :: from ( self . subgraph_name . to_owned ( ) ) ) ,
108- ) ] ) ) ;
109- // .request
110- let request_value: VrlValue = execution_request. client_request . into ( ) ;
111- let target_value = VrlValue :: Object ( BTreeMap :: from ( [
112- ( "subgraph" . into ( ) , subgraph_value) ,
113- ( "request" . into ( ) , request_value) ,
114- ] ) ) ;
115- let result = execute_expression_with_value ( expr, target_value) ;
116- match result {
117- Ok ( VrlValue :: Boolean ( b) ) => b,
118- Ok ( _) => {
119- return Err ( SubgraphExecutorError :: HMACSignatureError (
120- "HMAC signature expression did not evaluate to a boolean" . to_string ( ) ,
121- ) ) ;
122- }
123- Err ( e) => {
124- return Err ( SubgraphExecutorError :: HMACSignatureError ( format ! (
125- "HMAC signature expression evaluation error: {}" ,
126- e
127- ) ) ) ;
128- }
129- }
130- }
131- } ;
132-
133- if should_sign_hmac {
134- if self . config . hmac_signature . secret . is_empty ( ) {
135- return Err ( SubgraphExecutorError :: HMACSignatureError (
136- "HMAC signature secret is empty" . to_string ( ) ,
137- ) ) ;
138- }
139- let mut mac = HmacSha256 :: new_from_slice ( self . config . hmac_signature . secret . as_bytes ( ) )
140- . map_err ( |e| {
141- SubgraphExecutorError :: HMACSignatureError ( format ! (
142- "Failed to create HMAC instance: {}" ,
143- e
144- ) )
145- } ) ?;
146- let mut body_without_extensions = body. clone ( ) ;
147- body_without_extensions. put ( CLOSE_BRACE ) ;
148- mac. update ( & body_without_extensions) ;
149- let result = mac. finalize ( ) ;
150- let result_bytes = result. into_bytes ( ) ;
151- if * first_extension {
152- body. put ( FIRST_EXTENSION_STR ) ;
153- * first_extension = false ;
154- } else {
155- body. put ( COMMA ) ;
156- }
157- body. put ( QUOTE ) ;
158- body. put ( self . config . hmac_signature . extension_name . as_bytes ( ) ) ;
159- body. put ( QUOTE ) ;
160- body. put ( COLON ) ;
161- let hmac_hex = hex:: encode ( result_bytes) ;
162- body. put ( QUOTE ) ;
163- body. put ( hmac_hex. as_bytes ( ) ) ;
164- body. put ( QUOTE ) ;
165- }
166- Ok ( ( ) )
167- }
168-
16982 fn build_request_body < ' exec , ' req > (
17083 & self ,
17184 execution_request : & HttpExecutionRequest < ' exec , ' req > ,
@@ -213,7 +126,14 @@ impl HTTPSubgraphExecutor {
213126 let mut first_extension = true ;
214127
215128 if !self . config . hmac_signature . is_disabled ( ) {
216- self . sign_hmac ( execution_request, & mut body, & mut first_extension) ?;
129+ sign_hmac (
130+ & self . should_sign_hmac ,
131+ & self . config . hmac_signature ,
132+ & self . subgraph_name ,
133+ execution_request. client_request ,
134+ & mut first_extension,
135+ & mut body,
136+ ) ?;
217137 }
218138
219139 if let Some ( extensions) = & execution_request. extensions {
0 commit comments