I would like to propagate the request-foo header value received in a service (foo) to another header header-bar for service (bar). I would like to leverage sleuth/brave instrumentation for this without including it into the business logic
foo-service --------> HTTP ------> bar-service
(request-foo) (request-bar)
There is already support in Sleuth and Brave for propagation when the header names match. For example by setting in the foo-service the following
spring.sleuth.propagation-keys=request-foo
This would propagate the request-foo header value to bar-service with the request-foo header name.
Unfortunately, in my case, I have no control over the bar-service and it expects the header value as request-bar and also no control to rename request-foo header name because the foo-service receives it also from an upstream service.
I was thinking to provide an Injector similar to the ExtraFieldInjector but is not extendable the ExtraFieldPropagation, so I would need to provide my own Propagation implementation.
Wondering do I miss something? Is there an easier approach?
Thank you.
Related
Dynamic request routing based on header-values
For our QA environment we need to configure a special kind of routing for the incoming (Ingress), but also for the outgoing (Egress) requests. So for outgoing requests the rule should evaluate a header value with a regex and capture a value from the header and build with that value the URL where the request should be redirected. The value in the header is dynamically changed, so the redirect URL can not be hardcoded.
For example if the outgoing requests goes to services-master.anydomain.com, but there's a header value forwarded-for-feature with the value verbu-1234 the request should be redirected services-verbu-1234.anydomain.com.
For incoming requests it's a similar condition. If the origin points to webapp-verbu-1234.anydomain.com, but the request goes to services-master.anydomain.com the regex should extract verbu-1234 from the origin domain and replace master in the URL with the extracted value.
I know, that it's possible to use a regex to match header values, but I'm not sure, if it's possible to use captured values from a match to influence the target URL, at least I couldn't find that in the documentation.
I don't think this is possible
But if your QA system knows the features available, and you need to do that in Istio, you might try creating a VirtualService for each feature. And multiple VirtualServices would be merged by Istio...
I am using AWS API Gateway and I want to set my Integration type to http. I have the integrated url as https:// xxxxxx.com which takes a header "apikey". I am not expecting the end user to pass the header rather I want to set the apikey to some constant value.
I see that there is a way to force the user to make him pass the header(by making header required under the Method Request section. However, I want to set it to default.
For example in all the requests which are internally calling the URL inside the API gateway should pass the header value as "12345".
You can add/remove/override headers with an Integration Request Mapping Template.
In the API Gateway console, chose the relevant api/resourece/method. Go to Integration Request > Mapping Templates and chose your Content-Type (if requests are going to be received without a Content-Type header, set the Content-Type for the mapping template to application/json, which is the default behaviour).
Then in the actual mapping template add the following:
{
#set($context.requestOverride.header.apikey= "testMe")
}
This will add (or overwrite if it already exists) a header called apikey with the value "testMe" to all http requests downstream.
If you take this route, then you will need to also map over any other headers, path parameters, query parameters or body that you wish to pass through.
You could loop through the headers and query parameters like this.
## First set the header you are adding
#set($context.requestOverride.header.apikey= "testMe")
## Loop through all incoming headers and set them for downstream request
#foreach($param in $input.params().header.keySet())
#set($context.requestOverride.header[$param]= $input.params().header.get($param))
#if($foreach.hasNext) #end
#end
## Loop through all incoming query parameters and set them for downstream request
#foreach($param in $input.params().querystring.keySet())
#set($context.requestOverride.querystring[$param]= $input.params().querystring.get($param))
#if($foreach.hasNext) #end
#end
As you need to ensure that the header apikey is set to a default value, you should set the override for apikey before looping through the rest of the headers as only the first override will take effect.
The relevant AWS documentation can be found here.
The other alternative would be to point your API Gateway at a Lambda and make the call from the Lambda instead.
Firstly thanks to #KMO for his help. The following is the solution:-
Enable Http Proxy Integration.
Add the headers apikey=xxxx and Accept-Encoding=identity under the same Integration
Request -> Http Headers.
Under Settings -> Binary Media Types set the following as separate Binary Media Types
'*', */*. I mean as two different lines.This step is needed to resolve the Gzip action while returning the response.
Add the Query parameter country in the URL Query String Parameters section.
In the Integration Request map the country parameter to ctry by adding the value under mapped from as method.request.querystring.country. This will ensure that the query parameter country you passed in the main URL will be fed to the downstream url as parameter ctry.
The advantage of this apporoach is that, even if you override the header apikey, the one set under the Http Headers will take the precedence.
I have a big set of routes
from("restlet://api1").to("dest1-rest-url");
from("restlet://api2").to("dest2-rest-url");
from("restlet://api3").to("dest3-rest-url");
..
from("restlet://api100").to("dest100-rest-url");
All the routes are spread across different files.
Now, all the destination rest url require a AUTH header to be set. It would be tedious to set at each and every place.
Is there a way, I can set/configure a header , that is appended before calling any rest API.
IMHO a possible and elegant solution would be to play with Camel interceptors.
Using wildcards on "interceptSendToEndpoint", you should be able to intercept all calls to "restlet*" (or "http*" endpoints) in order to insert/add an "Authorization" http header before continuing the route.
More info here:
http://camel.apache.org/intercept.html
Adding an answer that solved part of my problem
interceptFrom("restlet*").process( e -> { e.getOut().setHeader("Authorization":"Basic <authkey>"); });
Note : You may have to set the other parameter such as Content Type, HTTP Method , Other header, body from Incoming exchange to out going exchange.
I am using sip servlets api to make sip calls,
My requirement is to connect two calls in conference, for this I need to modify call-id for one of the invite request, but it is not allowing me to modify call-id in header part and my code is as follows:
SipServletRequest forkedRequest = linkedSession.createRequest("INVITE");
ipFactory sipFactory = (SipFactory)getServletContext().getAttribute("javax.servlet.sip.SipFactory");
SipURI sipUri = (SipURI)sipFactory.createURI("sip:msml#192.168.149.113");
forkedRequest.setRequestURI(sipUri);
forkedRequest.setContent(secondSdp,"application/sdp");
forkedRequest.addHeader("Call-ID",sipServletResponse.getCallId());
and I was getting following error:
Header[Call-ID] is system header, cant add,cant modify it!!!
Can any one suggest on this? make sure how to modify call-id
SIP Servlets Specification specifically forbids to modify the Call-ID Header which is a System Header. Please read the specification at https://jcp.org/en/jsr/detail?id=289
Which conference provider enforces you to have the same Call-ID for 2 different calls to be able to join the same conference ? This seems like a very bad design and against the SIP RFC itself https://www.rfc-editor.org/rfc/rfc3261#section-8.1.1.4
I am trying to verify the contents of the http response to find a content "abbb" in it.So my rule was
alert tcp MY_SERVER HTTP_PORTS -> any any(msg:"The page accessed has content abbb";to_client; established; content:"abb";sid:XXXXX; rev:x;)
unfortunately this rule seems not to work. Can anyone please tell if there is some issue with my rule.
For starters you need to fix the to_client part of the rule as this is not valid syntax. You will need to change this to be:
flow:to_client,established;
You can find more on flow here.
If you are just looking for the content "abbb" sent from your server to the client then you just need a simple content match like you have. I recommend using the fast pattern matcher here to improve the efficiency of the rule. So your content match would look something like:
content:"abbb"; fast_pattern:only;
Putting this together, your rule might look something like:
alert tcp MY_SERVER HTTP_PORTS -> any any(msg:"The page accessed has content abbb";
flow:to_client,established; content:"abbb"; fast_pattern:only; sid:XXXXX; rev:x;)
If this still isn't triggering then there is probably something else going on. Since you are just looking for this in the content you need to check your inspection depth in the http preprocessor. There is a server_flow_depth and a client_flow_depth. Try setting these to 0 (unlimited) and see if your rule is triggering after. For example if you had a client_flow_depth of 300 and the content "abbb" didn't come until after 500 bytes then the rule is never going to trigger because snort isn't configured to inspect that far into the payload.
If you have adaptive profiling enabled then you need to add the metadata service for http otherwise the rule won't match http traffic. This would look something like:
metadata:service http;
If you don't use adaptive profiling then it will use the ports in the rule header.