Setting an Azure Scheduler Job Retry Policy - azure

Using the Azure Management REST API, I'm trying to update (PATCH) an existing Scheduler job with a retry policy. The request is accepted but the json response object doesn't include the retry policy entries.
In the case of an update, other changes I make are reflected in the response.
Azure Scheduler job entity structure: http://msdn.microsoft.com/library/azure/dn528941.aspx
Azure Scheduler REST API ref: http://msdn.microsoft.com/en-us/library/azure/dn528946.aspx
I've be using Burp Suite to quickly iterate through different requests, but I never see anything to suggest the retry policy has been created.
What am I missing?
The following request will create a new job name SampleJob20 (with no retry policy)
PUT /<subid>/cloudservices/<cloudservicename>/resources/scheduler/~/JobCollections/<jobcollectionname>/jobs/SampleJob20?api-version=2014-04-01 HTTP/1.1
Content-Type: application/json
x-ms-version: 2012-03-01
Host: management.core.windows.net
Content-Length: 583
{
"startTime": "2013-01-30T12:08:00-08:00",
"action":
{
"type": "http",
"request":
{
"uri": "http://bing.com/",
"method": "GET",
"headers":
{
"Content-Type": "text/plain"
}
}
},
"recurrence":
{
"frequency": "minute",
"interval": 30,
"count": 1000
},
"state": "enabled"
}
The response for this request is:
HTTP/1.1 201 Created
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 364
Content-Type: application/json; charset=utf-8
Expires: -1
Server: 1.0.6198.148 (rd_rdfe_stable.141019-1428) Microsoft-HTTPAPI/2.0
x-ms-servedbyregion: ussouth2
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
x-ms-request-id: xxxxxxxxxxxxxxxxx
Date: Mon, 20 Oct 2014 19:13:40 GMT
{
"id":"SampleJob20",
"startTime":"2013-01-30T20:08:00Z",
"action":
{
"request":
{
"uri":"http:\/\/bing.com\/","method":"GET",
"headers":
{
"content-Type":"text\/plain"
}
},
"type":"http"
},
"recurrence":
{
"frequency":"minute",
"count":1000,
"interval":30
},
"state":"enabled",
"status":
{
"nextExecutionTime":"2014-10-20T19:38:00Z",
"executionCount":0,
"failureCount":0,
"faultedCount":0
}
}
When I try and update this job with a retry policy. The response is missing the retry policy detail.
PATCH /<subid>/cloudservices/<cloudservicename>/resources/scheduler/~/JobCollections/<jobcollectionname>/jobs/SampleJob20?api-version=2014-04-01 HTTP/1.1
Content-Type: application/json
x-ms-version: 2012-03-01
Host: management.core.windows.net
Content-Length: 451
{
"id": "SampleJob20",
"action":
{
"type": "http",
"request":
{
"uri": "http://bing.com",
"method": "GET",
"headers":
{
"Content-Type": "text/plain"
}
},
"retryPolicy":
{
"retryType":"fixed",
"retryInterval": "PT1M",
"retryCount": 3
}
}
}
If I create a new job with a retry policy the response contains the retry detail. However, the jobs retry policy cannot be updated either.

Can you try putting a new or the same job like this (It includes the retry policy in the Put request)
PUT
{
"startTime": "2013-01-30T12:08:00-08:00",
"action":
{
"type": "http",
"request":
{
"uri": "http://bing.com/",
"method": "GET",
"headers":
{
"Content-Type": "text/plain"
}
},
"retryPolicy":
{
"retryType":"fixed",
"retryInterval": "PT1M",
"retryCount": 3
}
},
"recurrence":
{
"frequency": "minute",
"interval": 30,
"count": 1000
},
"state": "enabled"
}

Related

Azure Logic App not able create client certificate authentication with converted base64 encoded pfx

I want to get the token information for ADP Client through Azure Logic App. I have the Client Certificate from ADP so I decided to use HTTP trigger from Logic App and selected authentication type "Client Certificate".
Since I cant directly use certificate in Logic app so I converted certificate into base64Encoded .pfx format, and certificate is not having any password.
below is the sample code for the request
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {},
"contentVersion": "1.0.0.0",
"outputs": {},
"triggers": {
"HTTP": {
"inputs": {
"authentication": {
"pfx": "convertedbase64string",
"type": "ClientCertificate"
},
"body": "grant_type=client_credentials&client_id=ClientId&client_secret=client_secret",
"headers": {
"content-type": "application/x-www-form-urlencoded"
},
"method": "POST",
"uri": "https://accounts.adp.com/auth/oauth/v2/token"
},
"recurrence": {
"frequency": "Month",
"interval": 15
},
"type": "Http"
}
}
},
"kind": "Stateful"
}
above request returns me bad request, can anyone help me what is going wrong here?
For converting into base64 I used below steps in power shell
$pfx_cert = get-content 'C:\sample\adpcertificate.pfx' -Encoding Byte
$output =[Convert]::ToBase64String($pfx_cert)
$output
I tried same request with client certificate using postman which is working fine, but not able to get succeed with Logic App.
Any help is much appreciated.
There are only few differences between the headers sent from Postman and the Logic App. The main difference is that Postman also sends the accept-header: "Accept": "*/*" and leaves out alle the x-ms-* headers from the logic app.
I created a Logic App with http-trigger, which I post to from Postman and Logic App to inspect the changes:
With Postman
{
"headers": {
"Connection": "keep-alive",
"Accept": "*/*",
"Accept-Encoding": "br,gzip,deflate",
"Host": "....westeurope.logic.azure.com:443",
"User-Agent": "PostmanRuntime/7.28.4",
"Postman-Token": "...-baea-4e89-9bf6-490a63968b5d",
"Content-Length": "76",
"Content-Type": "application/x-www-form-urlencoded"
},
"body": {
"$content-type": "application/x-www-form-urlencoded",
"$content": "Z3JhbnRfdHlwZT1jbGllbnRfY3JlZGVudGlhbHMmY2xpZW50X2lkPUNsaWVudElkJmNsaWVudF9zZWNyZXQ9Y2xpZW50X3NlY3JldA==",
"$formdata": [
{
"key": "grant_type",
"value": "client_credentials"
},
{
"key": "client_id",
"value": "ClientId"
},
{
"key": "client_secret",
"value": "client_secret"
}
]
}
}
With Logic App
{
"headers": {
"Connection": "Keep-Alive",
"Accept-Encoding": "gzip,deflate",
"Accept-Language": "en",
"Host": "...westeurope.logic.azure.com",
"User-Agent": "azure-logic-apps/1.0,(workflow ...; version ...)",
"x-ms-trigger-callback-url": "https://....westeurope.logic.azure.com/ <...>",
"x-ms-trigger-type": "Http",
"x-ms-workflow-id": "...",
"x-ms-workflow-version": "...",
"x-ms-workflow-name": "myworkflowname",
"x-ms-workflow-system-id": "/locations/westeurope/scaleunits/...",
"x-ms-workflow-run-id": "...",
"x-ms-workflow-operation-name": "HTTP",
"x-ms-execution-location": "westeurope",
"x-ms-workflow-subscription-id": "...",
"x-ms-workflow-resourcegroup-name": "..",
"x-ms-tracking-id": "...",
"x-ms-correlation-id": "...",
"x-ms-client-request-id": "...",
"x-ms-activity-vector": "...",
"Content-Length": "76",
"Content-Type": "application/x-www-form-urlencoded"
},
"body": {
"$content-type": "application/x-www-form-urlencoded",
"$content": "Z3JhbnRfdHlwZT1jbGllbnRfY3JlZGVudGlhbHMmY2xpZW50X2lkPUNsaWVudElkJmNsaWVudF9zZWNyZXQ9Y2xpZW50X3NlY3JldA==",
"$formdata": [
{
"key": "grant_type",
"value": "client_credentials"
},
{
"key": "client_id",
"value": "ClientId"
},
{
"key": "client_secret",
"value": "client_secret"
}
]
}
}
Solution
My solution would be to manually add the Accept-Header in the post request in the Logic App.
"headers": {
"Accept": "*/*",
// ...
},
I sadly don't have an ADP account to verify this, but I've seen other APIs break when no accept header is sent.

403 Forbidden when accessing Kroger API from Azure-Hosted .Net Core 3.1 app

Problem: I need to determine the nature of this failure so I can know how to further troubleshoot. I have come up with a few hypothesis:
- could be a firewall/proxy configuration within Azure
- could be a misconfiguration with Kroger's API
- could be a public certificate rejection from Azure app
- could be something totally unrelated to any of above
Details: I’m attempting to connect to Kroger's developer API. The following code has been simplified for this post. (I have been using IHttpClientFactory previously to generate my HTTPClient). This works locally, but once it’s deployed to an Azure web service, I am presented with a 403 message (which appears to be coming from Azure and not the external API):
You don't have permission to access http://api.kroger.com on this server.
This same code works within Azure for other 3rd party APIs over HTTPS, so the suspicion I have had is that this error comes from not using correct client certificates, so Azure attempts to call over http?
I have tried many things to resolve this, including uploading a public certificate that I downloaded from https://api.kroger.com to my azure app service. It appears to pull the certificate correctly, but the request still fails with the same message.
Relevant code is below (Without using client certificate):
using(var client = _requestFactory.CreateClient()))
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("basic", _clientId);
client.DefaultRequestHeaders.Add("Accept", "application/json");
var newRequest = new Dictionary<string, string>
{
{ "grant_type", "client_credentials" },
{ "scope", "product.compact" }
};
var response = await client.PostAsync($"https://api.kroger.com/v1/connect/oauth2/token", new FormUrlEncodedContent(newRequest));
return Ok(await response.Content.ReadAsStringAsync());
}
Below is the full response from the server.
{
"version": "1.1",
"content": {
"headers": [{
"key": "Content-Type",
"value": ["text/html"]
}, {
"key": "Content-Length",
"value": ["299"]
}, {
"key": "Expires",
"value": ["Sat, 08 Feb 2020 19:18:55 GMT"]
}]
},
"statusCode": 403,
"reasonPhrase": "Forbidden",
"headers": [{
"key": "Server",
"value": ["AkamaiGHost"]
}, {
"key": "Mime-Version",
"value": ["1.0"]
}, {
"key": "Date",
"value": ["Sat, 08 Feb 2020 19:18:55 GMT"]
}, {
"key": "Connection",
"value": ["close"]
}, {
"key": "Set-Cookie",
"value": ["akaalb_Digital_ALB_API=~op=KT_Digital_API_KCVG_F5:api-kcvg|~rv=47~m=api-kcvg:0|~os=75b4a9ec926d2a9e67035451773cec6c~id=63ba4b3e2a027e4d53b693e2fded5ac3; path=/; HttpOnly; Secure; SameSite=None"]
}],
"trailingHeaders": [],
"requestMessage": {
"version": "1.1",
"content": {
"headers": [{
"key": "Content-Type",
"value": ["application/x-www-form-urlencoded"]
}, {
"key": "Content-Length",
"value": ["51"]
}]
},
"method": {
"method": "POST"
},
"requestUri": "https://api.kroger.com/v1/connect/oauth2/token",
"headers": [{
"key": "Authorization",
"value": ["basic {removed}"]
}, {
"key": "Accept",
"value": ["application/json"]
}, {
"key": "Request-Context",
"value": ["appId={removed}"]
}, {
"key": "Request-Id",
"value": ["|{removed}"]
}, {
"key": "traceparent",
"value": ["{removed}"]
}],
"properties": {}
},
"isSuccessStatusCode": false
}
"headers": [{
"key": "Server",
"value": ["AkamaiGHost"]
}
Almost certainly Akamai issue. I have seen 403 errors due to header order or even user-Agent header that Akamai does not like.

Why does Mountebank predicate cause 200 instead of 500 in response?

Teaching self mountebank. I want to create a mock endpoint such that by issuing POST command to http://localhost:2525/test?mock-response-code=500, the response code will be 500 and the message body will be some custom text.
When I create the imposter, however, and run the relevant curl command, I am getting a 200 response.
curl -i -X POST http://localhost:2525/imposters --data '#createImposter_r500.ejs'
info: [mb:2525] POST /imposters
info: [http:61161] Open for business...
HTTP/1.1 201 Created
Access-Control-Allow-Origin: *
Location: http://localhost:2525/imposters/61161
Content-Type: application/json; charset=utf-8
Content-Length: 767
Date: Sun, 18 Aug 2019 13:57:57 GMT
Connection: keep-alive
{
"protocol": "http",
"port": 61161,
"numberOfRequests": 0,
"recordRequests": false,
"requests": [],
"stubs": [
{
"responses": [
{
"is": {
"statusCode": 500
}
}
],
"predicates": [
{
"equals": {
"path": "/test",
"method": "POST",
"query": {
"mock-response-code": 500
}
}
}
],
"_links": {
"self": {
"href": "http://localhost:2525/imposters/61161/stubs/0"
}
}
}
],
"_links": {
"self": {
"href": "http://localhost:2525/imposters/61161"
},
"stubs": {
"href": "http://localhost:2525/imposters/61161/stubs"
}
}
}
createImposter_r500.ejs:
{
"protocol": "http",
"stubs": [{
"responses": [
{ "is": { "statusCode": 500 }}
],
"predicates": [{
"equals": {
"path": "/test",
"method": "POST",
"query": {"mock-response-code": 500}
}
}]
}]
}
Here is what happens when I try using that URL:
curl -i -X POST http://localhost:61161/test?mock-response-code=500
info: [http:61161] ::1:61429 => POST /test?mock-response-code=500
HTTP/1.1 200 OK
Connection: close
Date: Sun, 18 Aug 2019 14:18:06 GMT
Transfer-Encoding: chunked
Here is some debug output:
debug: [http:62650] ::1:63139 ESTABLISHED
info: [http:62650] ::1:63139 => POST /test?mock-response-code=400
debug: [http:62650] ::1:63139 => {"requestFrom":"::1:63139","method":"POST","path":"/test","query":{"mock-response-code":"400"},"headers":{"Host":"localhost:62650","User-Agent":"curl/7.54.0","Accept":"*/*"},"body":"","ip":"::1"}
debug: [http:62650] no predicate match
debug: [http:62650] generating response from {"is":{}}
debug: [http:62650] ::1:63139 <= {"statusCode":200,"headers":{"Connection":"close"},"body":"","_mode":"text"}
debug: [http:62650] ::1:63139 CLOSED
(Port is different from above b/c it's from a different run.)
I found the answer myself with continued experimentation.
Quotation marks - that simple.
"query": {"mock-response-code": "400"}
rather than
"query": {"mock-response-code": 400}

How can I insert many documents at once?

When I want to insert a document using CouchDB, I send a request like this one:
POST http://localhost:5984/blogging/
Accept: application/json
Content-Type: application/json
{
"name": "Example",
"value": 5
}
And it Works. But, what if I want to insert two documents at once? I try:
POST http://localhost:5984/blogging/
Accept: application/json
Content-Type: application/json
[
{
"name": "Example 2",
"value": 6
},
{
"name": "Example 3",
"value": 7
}
]
And it answers me:
HTTP/1.1 400 Bad Request
Cache-Control: must-revalidate
Connection: close
Content-Length: 66
Content-Type: application/json
Date: Thu, 28 Feb 2019 08:03:52 GMT
Server: CouchDB/2.3.0 (Erlang OTP/19)
X-Couch-Request-ID: 9ed2f39fcf
X-CouchDB-Body-Time: 0
{
"error": "bad_request",
"reason": "Document must be a JSON object"
}
Well, first of all, I would suggest you to check this API from the documentation: http://docs.couchdb.org/en/1.6.1/api/database/bulk-api.html#inserting-documents-in-bulk
And, apart from that, you aren't sending a valid JSON object. I would change your request in this way:
POST http://localhost:5984/blogging/_bulk_docs
Accept: application/json
Content-Type: application/json
{
"docs": [
{
"name": "Example 2",
"value": 6
},
{
"name": "Example 3",
"value": 7
}
]
}

Parse multipart/related response and save attachment to file

I'm doing a simple POST that returns the below. I'm expecting a .txt.gz file. I need to know how to retrieve the attachment. I've tried creating a buffer, delimiting, and splitting before writing the file, but it always comes back as corrupt.
The request library explains how to consume a PUT request for an attachment, but not how to consume a response back.
Can anyone help? Been at this for a week now.
JSON.stringify(res)
{
"statusCode": 200,
"body": {
"type": "Buffer",
"data": [
13,
10,
45,
45(..truncated)
]
},
"headers": {
"set-cookie": [
"JSESSIONIDSSO=982EF51351B9497045DB6AB5A2D50DBF; Path=/; Secure; HttpOnly",
"JSESSIONID=995EF8A4A893860159CE463582E4CDDD; Path=/logcollectionservice; Secure; HttpOnly",
"SoapSession.id=-2851099334472488788"
],
"x-frame-options": "SAMEORIGIN",
"strict-transport-security": "max-age=31536000; includeSubdomains",
"content-type": "multipart/related; type=\"text/xml\"; start=\"<852C508C64251E692C9217DFA4EB7433>\"; boundary=\"----=_Part_109_17473961.1526352793275\"",
"transfer-encoding": "chunked",
"date": "Tue, 15 May 2018 02:53:13 GMT",
"connection": "close",
"server": ""
},
"request": {
"uri": {
"protocol": "https:",
"slashes": true,
"auth": null,
"host": "50.22.22.22:8443",
"port": "8443",
"hostname": "50.22.22.22",
"hash": null,
"search": null,
"query": null,
"pathname": "/logcollectionservice/services/DimeGetFileService",
"path": "/logcollectionservice/services/DimeGetFileService",
"href": "https://50.22.22.22:8443/logcollectionservice/services/DimeGetFileService"
},
"method": "POST",
"headers": {
"Authorization": "Basic YWRt123123123123123123",
"SOAPAction": "http://schemas.cisco.com/ast/soap/action/#LogCollectionPort#GetOneFile",
"content-length": 467
}
}
}
res.body
------=_Part_183_12814895.1526363698144
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: binary
Content-Id: <5DDAB109C3B14685FF6B0EA83D2CF8E4>
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body>
<ns1:GetOneFileResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://schemas.cisco.com/ast/soap/"><DataHandler
href="cid:36F92AA211EE04B422D4B07AB07D841A" xsi:type="ns2:DataHandler"
xmlns:ns2="DimeGetFileService"/></ns1:GetOneFileResponse>
</soapenv:Body></soapenv:Envelope>
------=_Part_183_12814895.1526363698144
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-Id: <36F92AA211EE04B422D4B07AB07D841A>
����o�:���W��U����<��퐖.�I��8!h�0�l��?~���m�z��;'����>��oL���'Ϗ��3
'�tSV�EO�8zÂ���[a0����.��`�4wbO�q��FI���:�n܍>��e-
��!^#"�U5��;��^����U[V���s˽��q_��̣
����{gm����r��
���c��㬌Pf]Z�����cs���#ߵ� (truncated)
------=_Part_183_12814895.1526363698144--

Resources