(
method: &str,
target_uri: &str,
buf: &[u8],
used: usize,
client: &mut TcpStream,
opa_engine: Arc<OpaEngine>,
identity_cache: Arc<BinaryIdentityCache>,
entrypoint_pid:
| 3140 | // dispatch; bundling them into a struct would just shift the noise into call sites. |
| 3141 | #[allow(clippy::too_many_arguments)] |
| 3142 | async fn handle_forward_proxy( |
| 3143 | method: &str, |
| 3144 | target_uri: &str, |
| 3145 | buf: &[u8], |
| 3146 | used: usize, |
| 3147 | client: &mut TcpStream, |
| 3148 | opa_engine: Arc<OpaEngine>, |
| 3149 | identity_cache: Arc<BinaryIdentityCache>, |
| 3150 | entrypoint_pid: Arc<AtomicU32>, |
| 3151 | policy_local_ctx: Option<Arc<PolicyLocalContext>>, |
| 3152 | trusted_host_gateway: Arc<Option<IpAddr>>, |
| 3153 | secret_resolver: Option<Arc<SecretResolver>>, |
| 3154 | dynamic_credentials: Option< |
| 3155 | Arc< |
| 3156 | std::sync::RwLock< |
| 3157 | std::collections::HashMap<String, openshell_core::proto::ProviderProfileCredential>, |
| 3158 | >, |
| 3159 | >, |
| 3160 | >, |
| 3161 | denial_tx: Option<&mpsc::UnboundedSender<DenialEvent>>, |
| 3162 | activity_tx: Option<&ActivitySender>, |
| 3163 | ) -> Result<()> { |
| 3164 | // 1. Parse the absolute-form URI. `path` is marked `mut` so that, when an |
| 3165 | // L7 config applies, the canonicalized form produced below replaces it |
| 3166 | // in-place — keeping OPA evaluation and the bytes written onto the wire |
| 3167 | // in sync. See the L7 block below. |
| 3168 | let (scheme, host, port, mut path) = match parse_proxy_uri(target_uri) { |
| 3169 | Ok(parsed) => parsed, |
| 3170 | Err(e) => { |
| 3171 | let event = HttpActivityBuilder::new(openshell_ocsf::ctx::ctx()) |
| 3172 | .activity(ActivityId::Fail) |
| 3173 | .severity(SeverityId::Low) |
| 3174 | .status(StatusId::Failure) |
| 3175 | .message(format!("FORWARD parse error for {target_uri}: {e}")) |
| 3176 | .build(); |
| 3177 | ocsf_emit!(event); |
| 3178 | respond(client, b"HTTP/1.1 400 Bad Request\r\n\r\n").await?; |
| 3179 | return Ok(()); |
| 3180 | } |
| 3181 | }; |
| 3182 | let host_lc = host.to_ascii_lowercase(); |
| 3183 | |
| 3184 | if host_lc == POLICY_LOCAL_HOST { |
| 3185 | if scheme != "http" || port != 80 { |
| 3186 | respond( |
| 3187 | client, |
| 3188 | &build_json_error_response( |
| 3189 | 400, |
| 3190 | "Bad Request", |
| 3191 | "invalid_policy_local_scheme", |
| 3192 | "Use http://policy.local only", |
| 3193 | ), |
| 3194 | ) |
| 3195 | .await?; |
| 3196 | return Ok(()); |
| 3197 | } |
| 3198 | if let Some(ctx) = policy_local_ctx { |
| 3199 | return crate::policy_local::handle_forward_request( |
no test coverage detected