ADLS SAS token is truncated when rewriting in API Management - urlencode

I have an ADLS with images that I want to display on my website.
I want to expose them through APIM. I am sending the image name and SAS token in the request which I re-write in the actual backend request with the right folder structure.
The policy -
<policies>
<inbound>
<set-variable name="BlobName" value="#(context.Request.Url.Query.GetValueOrDefault("BlobName"))" />
<set-variable name="sasToken" value="#(System.Net.WebUtility.UrlDecode(context.Request.Url.Query.GetValueOrDefault("sasToken")))" />
<base />
<set-backend-service base-url="#{
string blobName = context.Variables.GetValueOrDefault<string>("BlobName");
string sasToken = context.Variables.GetValueOrDefault<string>("sasToken");
return String.Format("https://myadls.blob.core.windows.net/UserImages/Images/{0}?{1}",blobName,sasToken);
}" />
<authentication-managed-identity resource="https://storage.azure.com/" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
The SAS token - sv=2020-08-04&st=2022-02-24T04%3A17%3A53Z&se=2022-02-24T06%3A17%3A53Z&sr=c&sp=r&sig=5B6IUrj9VSh7oZSHAOKQK7fsWLun%2B%2BL7v0o1gQJHxvU%3D
Since the SAS token and '&' sign, the sasToken string is getting truncated to 'sv=2020-08-04'
As you can see in the policy I tried to encode the SAS in c# as
System.Net.WebUtility.UrlEncode(dataLakeSasBuilder.ToSasQueryParameters(sharedKeyCredential).ToString());
But, the System.Net.WebUtility.UrlDecode did not decode the value.
Thanks in advance.

I found that encoding it in the code and decoding the string in the policy is solving this
Encoding.UTF8.GetString(Convert.FromBase64String(context.Request.Url.Query.GetValueOrDefault("sasToken")))

Related

How to get B2C id_token inside ClaimsTransformation.cs

Is it possible to get the id_token returned by B2C after authentication inside of ClaimsTransformation.cs class?
I have tried to inject IHttpContextAccessor into the class, but it gets stuck in an infinite loop, calling the same method again and again, resulting in Stack Overflow error.
Try to add the following to the Azure AD OpenID Connect technical profile:
<ClaimsTransformations>
<ClaimsTransformation Id="CreateOtherMailsFromEmail" TransformationMethod="AddItemToStringCollection">
<InputClaims>
<InputClaim ClaimTypeReferenceId="email" TransformationClaimType="item" />
<InputClaim ClaimTypeReferenceId="otherMails" TransformationClaimType="collection" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="email" TransformationClaimType="collection" />
</OutputClaims>
</ClaimsTransformation>
Reference Link : https://github.com/Azure-Samples/active-directory-b2c-custom-policy-starterpack/blob/main/LocalAccounts/TrustFrameworkBase.xml

I am trying to fetch a pdf document from Companies House API

I am trying to fetch a pdf document from API using ColdFusion and I receive this error:
<?xml version="1.0" encoding="UTF-8"?> <Error><Code>InvalidArgument</Code> <Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message><ArgumentName>Authorization</ArgumentName> <ArgumentValue>#key#</ArgumentValue> <RequestId>Some requestid</RequestId> <HostId>some host id</HostId>
400 Bad Request
Here is my code:
<cfset urlD="https://document-api.company-information.service.gov.uk/document/#documentID#/content">
<cfhttp urlD="#Url#" method="GET" result="takeDoc" resolveurl="Yes" timeout="999">
<cfhttpparam type="HEADER" name="Accept" value="application/pdf">
<cfhttpparam type="HEADER" name="content-length" value=93295 />
<cfhttpparam type="HEADER" name="Authorization" value="#key#"/>
</cfhttp>
<cfdump var="#takeDoc#">
Any ideas how to solve this final step?
I appears you are transmitting the value #key# as your Authorization instead of the value for the variable key. try putting cfoutput tags around your cfhttp tags.

Getting the Wrong Routing Key for AMQP message using RabbitMQ and Apache Camel

I am having an hard time tracking down an issue with my Camel routes. From what Ive been reading, it seems it may be something to do with my routing key header information getting screwed up, but Im not sure how to resolve this. Also, this is a Java OSGi project if thats important, but all the Camel stuffs are currently implemented in XML. Any help is appreciated.
Here's what Im trying to do:
<!-- The first route creates an object with some info in it and drop it on a rabbitmq
exchange called message.added -->
<route id="directIn">
<from uri="direct:in" />
<bean ref="connector" method="handleIncoming" />
<marshal id="marshal-one" ref="firstObject" />
<to uri="rabbitmq://localhost:5672/me.ex?exchangeType=topic&durable=false&autoDelete=true&routingKey=message.added" />
</route>
<!-- This route listens to message.added, processes the data, creates a new object, and
drops it on a different rabbitmq exchange called message.rest -->
<route id="addedOne">
<from uri="rabbitmq://localhost:5672/me.ex?exchangeType=topic&durable=false&autoDelete=true&routingKey=message.added" />
<unmarshal id="unmarshal-one" ref="firstObject" />
<bean ref="connector" method="processAndConvert" />
<marshal id="marshal-out" ref="secondObject" />
<to uri="rabbitmq://localhost:5672/me.ex?exchangeType=topic&durable=false&autoDelete=true&routingKey=message.rest" />
</route>
This code seems to have been working fine. The problem arises when we add a new bundle, which is also listening to the message.added rabbitmq message (which I believe you are allowed to do?)
<!-- This route is in a different bundle, also listening to message.added, processing
the data and creating the same object (from a common bundle) and dropping it
on the same rabbitmq exchange as before -->
<route id="addedTwo">
<from uri="rabbitmq://localhost:5672/me.ex?exchangeType=topic&durable=false&autoDelete=true&routingKey=message.added" />
<unmarshal id="unmarshal-two" ref="firstObject" />
<bean ref="someService" method="processUpdate" />
<marshal id="marshal-out2" ref="secondObject" />
<to uri="rabbitmq://localhost:5672/me.ex?exchangeType=topic&durable=false&autoDelete=true&routingKey=message.rest" />
</route>
This route fails with an error message that it is trying to unmarshal a secondObject into a firstObject in the addedTwo route.
ERROR | RabbitMQConsumer | DefaultErrorHandler ....
caught: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
Unrecognized field "secondObject" (class com.pointer.dangling.FirstObject["secondObject"])
Message History:
RouteId ProcessorId Processor
[addedTwo] [addedTwo] [ ]
[addedTwo] [unmarshal-two] [unmarshal[ref:firstObject] ]
Exchange:
Headers: {
CamelRedelivered=false,
rabbitmq.DELIVERY_TAG=1,
rabbitmq.EXCHANGE_NAME=me.ex,
rabbitmq.ROUTING_KEY=message.added
}
Body: {
"secondObject": {
// a bunch of fields for secondObject
}
}
It appears that a 'secondObject' is, at some point, making its way onto the 'message.added' exchange and being picked up by the 'addedTwo' route which tries to marshal it into a 'firstObject'. But Im not explicitly telling it to do that anywhere in the code - any ideas?
In the RabbitMQ Camel component, the routingKey endpoint option only works for Consumers (<from />).
Producers must set their routing key explicitly as a message header before the <to />. Your addedOne route should look like this:
<route id="addedOne">
<from uri="rabbitmq://localhost:5672/me.ex?exchangeType=topic&durable=false&autoDelete=true&routingKey=message.added" />
<unmarshal id="unmarshal-one" ref="firstObject" />
<bean ref="connector" method="processAndConvert" />
<marshal id="marshal-out" ref="secondObject" />
<setHeader headerName="rabbitmq.ROUTING_KEY">
<constant>message.rest</constant>
</setHeader>
<to uri="rabbitmq://localhost:5672/me.ex?exchangeType=topic&durable=false&autoDelete=true" />
</route>
See https://camel.apache.org/rabbitmq.html for more info.

Send file to Mule inbound-endpoint

I'm trying to send a form with a file and two inputs to an Mule inbound-endpoint. I've got a custom-processor, and a flow defined like that:
<custom-processor class="informa.app.classifier.transformers.MyfileUploadProcessor" name="fileuploadprocessor"></custom-processor>
<flow name="httpTest">
<http:inbound-endpoint
address="http://tango.privada.informa:11002/services/fileupload"></http:inbound-endpoint>
<processor ref="fileuploadprocessor"/>
</flow>
In the class MyfileUploadProcessor:
public class MyfileUploadProcessor implements MessageProcessor {
#Override
public MuleEvent process(MuleEvent event) throws MuleException {
// TODO Auto-generated method stub
String response = "success";
MuleMessage mulemessage = event.getMessage();
String countryCode = mulemessage.getInboundProperty("username");
String sourceCode = mulemessage.getInboundProperty("password");
InputStream input = (InputStream) mulemessage.getPayload();
...
And to test, a simple html:
<form action="http://tango.privada.informa:11002/services/fileupload" method="post"
enctype="multipart/form-data">
<p>Country Code :<input type="text" name="username" /></p>
<p>Source Code :<input type="text" name="password" /></p>
<p>File :<input type="file" name="payload" /></p>
<p><input type="submit" name="submit" value="submit" />
<input type="reset" name="reset" value="reset"></p>
</form>
</body>
</html>
The issue is I can't create a file from the payload of the mulemessage and I don't know how to get the value of the inputs in the form...what I'm doing wrong? any clues?
Thanks in advance
You need to configure the HTTP connector to use the org.mule.transport.http.HttpMultipartMuleMessageFactory in order to handle multipart/form-data HTTP POSTs.
For this, add the following to your configuration:
<http:connector name="httpConnector">
<service-overrides messageFactory="org.mule.transport.http.HttpMultipartMuleMessageFactory"/>
</http:connector>
With this in place, the payload form field will become the streaming payload of the Mule message and all the other fields values will be in inbound attachments (any part header will be in inbound headers).
Great answer from David (a life saver for me !! cudos david)
for what it is worth some extra items I didn't realize at first the httpConnector has to be used as http transport reference a full flow would be
<http:connector name="httpConnector" doc:name="HTTP\HTTPS">
<service-overrides
messageFactory="org.mule.transport.http.HttpMultipartMuleMessageFactory" />
</http:connector>
<flow name="AttachmentTestFlow1" doc:name="AttachmentTestFlow1">
<http:inbound-endpoint connector-ref="httpConnector" doc:name="HTTP" exchange-pattern="request-response" host="localhost" port="8081"/>
<component class="ProcessAttachment" doc:name="Java" />
</flow>
I was able to upload using jmeter adding two attachments, the first
has a paramter name = "payload" and mime-type="multipart/form-data"
the second has a user specificed name, e.g "attachment"
This can then be processed by a normal mule flow, or a component
public String process(#Payload String payload, #InboundAttachments("*") Map<String, DataHandler> headers ) throws IOException{
InputStream in = headers.get("attachment").getDataSource().getInputStream();

Collecting Query string values from URL in Silverlight and WCF application

I am trying to retrieve query string values from a url. And the app should be a silverlight app.
For Eg: The sample URL might look like http://<hostname>/silverlightApp/Default.aspx?S=Name|address|title|sal|...
I should be able to take the query string and built a Silverlight UI.
Can this be done or Silverlight is not a good candidate for this type.
There are multiple ways you can do this. In the hosting page, you can pull out query string values using Request.QueryString, and then pass them to Silverlight using the initParams tag, i.e.:
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2"
width="100%" height="100%">
<param name="source" value="/ClientBin/MyApplication.xap" />
<param name="onerror" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40620.0" />
<param name="autoUpgrade" value="true" />
<param name="windowless" value="true" />
<param name="initParams" value="<%=InitParameters %>" />
<param name="splashScreenSource" value="<%=SplashScreenSource %>" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40620.0" style="text-decoration: none;">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight"
style="border-style: none" />
</a>
</object>
Or from within the Silverlight application itself, you can grab the querystring and other parts of the URI by using HtmlPage.Document.documentUri, e.g.:
Uri uri = HtmlPage.Document.DocumentUri;
And once you've got the actual querystring, you can parse it using regular expressions, or whatever your poison of choice happens to be.
HTH.
See System.Web.HttpUtility.ParseQueryString() Method, which parses a query string into a NameValueCollection.
[Later] Sorry, the Silverlight runtime seems to be without the System.Web namespace.
See system.Uri.Query in the System namespace provided with Silverlight runtime.
The Query property contains any query information included in the URI. Query information is separated from the path information by a question mark (?) and continues to the end of the URI. The query information returned includes the leading question mark.
The query information is escaped according to RFC 3986.
The following example writes the query ?date= today to the console.
Uri baseUri = new Uri ("http://www.contoso.com/");
Uri myUri = new Uri (baseUri, "catalog/shownew.htm?date=today");
outputBlock.Text += "Uri.Query: ";
outputBlock.Text += myUri.Query;
outputBlock.Text += "\n";