I am using wso2 APIM 1.8 for rest to soap conversion.
My rest resource for GET is defined as follow in publisher
/add?*
so it will have any number of query parameters e.g /add?a=1& b=3 or /add?a=1&b=2&c=3
what my requirement is I want to read these dynamic(some parameters are optional) values(a,b,c etc) in the extended in sequence and used that value in payload factory mediator to create the soap payload.How it is possible to read these values?
After going through the ESB doc1 found that this can be done using $url
synapse xpath variable.
<log level="custom">
<property name="SYMBOL" expression="$url:a"></property>
<property name="SYMBOL2" expression="$url:c"></property>
</log>
https://docs.wso2.com/display/ESB481/Synapse+XPath+Variables#SynapseXPathVariables-$url
Related
I am using Apigee as gateway to our application. Several applications will hit Apigee and Apigee will in-turn route the request to backend servers. Every incoming request will have a JWT token.
I want Apigee to pass that token to a auth server and auth server will validate if the token is valid or not.
If token is invalid(if auth server return any status other then 200) , I want Apigee to return 403 error as response to request else pass the request to backend server.
How can I implement this kind of shared flow? Is it even possible with Apigee ? Is there any better way to achieve this?
You can do that.
Create a shared flow for Authentication/Authorization which includes ServiceCallout policy which will make a call to auth server.
Based on result for Unauthorized/Bad request you can raise a fault response with help of RaiseFault.
If the response is OK it will proceed smooth to backend.
Sample shared flow.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SharedFlowBundle revision="1" name="Auth">
<Policies>
<Policy>AssignVariableJwks</Policy> <!-- Assign Input values if needed via AssignMessage policy -->
<Policy>RequestAuthServer</Policy> <!-- Extrnal auth server call using ServiceCallout policy -->
<Policy>TokenNotFoundValidation</Policy> <!-- Validate response and raise fault if needed using RaiseFault policy -->
</Policies>
<Resources/>
<Spec/>
<subType>SharedFlow</subType>
<SharedFlows>
<SharedFlow>default</SharedFlow>
</SharedFlows>
</SharedFlowBundle>
For above shared flow create & attach required policies with logic and you're good to go.
I wish to restrict access to certain methods in my RESTful API. I am trying to do this via products for simplicity allowing access to the resource /athletes* but I don't see a way of any finer control i.e. I wish to only allow GET requests and not POST and DELETE. Is there a syntax for expressing this in the custom resource path section of a product or do I need to handle this via a conditional flow e.g. to check for the product name to see if they can access?
I do this with Scopes but I had to do one little kludge at the end. This assumes you're using at least client_credentials grants for access_tokens (VerifyAPIKey policy doesn't directly support Scopes).
First create an API Proxy for, say, /v1/content (base path /v1, path suffix /content). Then create two resources.
<Flows>
<Flow name="Content Read">
<Description/>
<Request>
<Step>
<FaultRules/>
<Name>RegEx-Check-Scope-READ-Content</Name>
</Step>
</Request>
<Response />
<Condition>(proxy.pathsuffix MatchesPath "/content") and (request.verb = "GET")</Condition>
</Flow>
<Flow name="Content Create">
<Description/>
<Request>
<Step>
<FaultRules/>
<Name>RegEx-Check-Scope-POST-Content</Name>
</Step>
</Request>
<Response />
<Condition>(proxy.pathsuffix MatchesPath "/content") and (request.verb = "POST")</Condition>
</Flow>
Then create a product with scopes for CONTENT-READ and CONTENT-WRITE something like this:
Now, you could either create a second product with only CONTENT-READ to restrict some apps to Read only or you could generate your access_token with scopes like this:
<OAuthV2 name="GenerateAccessTokenClient">
<Operation>GenerateAccessToken</Operation>
<ExpiresIn>3600000</ExpiresIn>
<SupportedGrantTypes>
<GrantType>client_credentials</GrantType>
</SupportedGrantTypes>
<GrantType>request.formparam.grant_type</GrantType>
<Scope>request.formparam.scope</Scope>
<GenerateResponse/>
</OAuthV2>
Probably easier to enforce the App level using two products, but passing scopes also let the User is a 3-legged Oauth add restrictions. Regardless, when you generated the access_token the policy will create an Apigee variable called "scope" which will include the scopes you included when you generated the access_token. If you don't specify scopes when you generate the access_token you will get ALL scopes from the product included in the scopes variable like this:
scope: CONTENT-READ CONTENT-WRITE
It's just one long string, separated by spaces. And there didn't seem to be an easy way to put this into the Condition for the flow, so I added a RegEx policy to check if the allowed scope is in the scope variable, like this:
<RegularExpressionProtection async="false" continueOnError="false" enabled="true" name="RegEx-Check-Scope-POST-Content">
<DisplayName>RegEx Check Scope POST-Content</DisplayName>
<FaultRules/>
<Properties/>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>>
<Variable name="scope">
<Pattern>^((?!CONTENT-WRITE).)*$</Pattern>
</Variable>
<Source>request</Source>
</RegularExpressionProtection>
Where the regex returns true if CONTENT-WRITE is not in the scope string. And if the regex returns true, then it raises a fault and stops processing so the App doesn't get to POST.
Let me know if that makes sense (it's a few steps...)
On the API proxies page (not the Product page), you can add resources. Therein, you can indicate the method (or request verb) you allow. This is the same as using conditions on your Flows based on the request verb. For instance, if you add <Condition>(request.verb = "POST")</Condition> to your API flow in your bundle, that means that particular flow will execute only when your request verb is POST. All other verbs for the base path of that bundle will be ignored.
This way, you only allow specific request verbs for your API bundle.
If you're trying to have fine control of resource + verb using API Products, you can set the variable flow.resource.name within the API proxy code to be:
"/" + request.verb + "/" + proxy.pathsuffix
This will leave you with something like /GET/products/1234-567. The variable flow.resource.name is the one that's validated against the API Resource Paths configured for the API products, when using the VerifyAPIKey policy.
I created a key/value map using the platform API defined in this doc. I used the API-scoped url to create a key/value map named countrymap.
https://api.enterprise.apigee.com/v1/o/{org_name}/apis/{api_name}/keyvaluemaps
and plugged in the sample weather api I made while following the tutorials.
However I could not seem to refer to this map when I added a KeyValueMapOperations policy inside the API proxy. I tried adding a mapIdentifier="countrymap" to the definition (based on the samples) but it still does not see it.
<KeyValueMapOperations async="false" continueOnError="false" enabled="true" mapIdentifier="countrymap" name="keyvaluemapoperations-2">
<DisplayName>KeyValueMapOperations-2</DisplayName>
<FaultRules/>
<Properties/>
<ExclusiveCache>false</ExclusiveCache>
<ExpiryTimeInSecs>-1</ExpiryTimeInSecs>
<Get assignTo="my.country" index="1">
<Key>
<Parameter ref="apigee.countryCode"></Parameter>
</Key>
</Get>
<Scope>organization</Scope>
</KeyValueMapOperations>
The policy works if I add an <InitialEntries> definition to the code above.
According to the Key/Value Maps docs:
Key/ValueMaps provide an API for storing arbitrary name/value pairs
that can be access at runtime by custom policies, or for other custom
runtime requirements such as protocol support.
Do custom policies include the KeyValueMapOperations policy? What am I missing here?
As you mentioned, you put the KeyValueMap in the scope of the api. To access that KVM, you'll need to use:
<Scope>apiproxy</Scope>
See the details for configuring the policy here.
Step 1: Verify if teh keyvalumap is correctly created:
/v1/o/{org_name}/apis/{api_name}/keyvaluemaps" --> this should list the countrymap KVM
Step 2: Populate the KVM before trying to do a GET call on it.You can populate it either by using API Calls (apigee.com/docs/api/api_methods/62-update-keyvaluemap) , or by Using PUT operation of KeyValueMapOperations as shown here (apigee.com/docs/api-services/content/persist-data-using-keyvaluemap)
Step 3: Check the entries of KVM
/v1/o/{org_name}/apis/{api_name}/keyvaluemaps/countrymap
Step 4: You can use the same KeyValueMapOperations Polices as given in example to do a get on the KVM
I was also facing this issue and after making below change in KeyValueMapOperations, it started working for me.
<Scope>apiproxy</Scope>
<Parameter>apigee.countryCode</Parameter>
This question is of two parts
Is it possible to provide Path Variables for Spring Web Flow?
Is it possible to hide the execution key in the URL
The current URL is as follows: http://localhost/bugs/ticket/?execution=e2s1
Here, the associated Web Flow location pattern is
<flow:flow-location-pattern value="/**/flow.xml" />
where the Folder Structure is: bugs/ticket/flow.xml
Is it possible to provide the ticket ID in the URL itself and point to the appropriate flow - i.e. the URL should be http://localhost/bugs/ticket/102?execution=e2s1, but still the flow is taken from bugs/ticket/flow.xml
I tried with the following patterns - value="/**/*/flow.xml", flow-path id="bugs/ticket/*" etc, but to no avail.
Also, is it possible to hide the execution key also in the URL? Is it possible to send it via say HTTP header which can be pulled in at Spring Web Flow ?
This does not answer all your questions
This is how I send parameters into the flow
External Page
Enter Flow
Flow
<view-state>
<on-entry>
<set name="variable2.field" value="requestParameters.uid"/>
</on-entry>
</view-state>
I try to get nodes by type from D7 over xml-rpc.
I used this example:http://drupal.org/node/1304802
This example provide an xml to create a node...
Anyone can help me how to get nodes by type like this XML?
Thanks,
IB
The code below should work. I have just tested it on my Drupal installation using the Firefox plugin called Poster.
Remember to set the correct URL to your endpoint. Considering a Drupal instance on http://localhost/test and an endpoint called "api", the resulting URL to access the endpoint is http://localhost/test/?q=api.
One last thing: if you have enabled authentication for your endpoint you must access the node with a user which has permissions to do so. You can set the username and password when using Poster.
<?xml version='1.0' ?>
<methodCall>
<methodName>node.retrieve</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>nid</name>
<value>
<string>INSERT THE NODE'S ID HERE</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>