Why do calls to the Service Management API work but calls to the Scheduler API fail? - azure

I'm trying to make some calls to the new Azure Scheduler API. However, all my requests come back with this error:
<Error xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Code>AuthenticationFailed</Code>
<Message>The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.</Message>
</Error>
I'm pretty sure that I have everything setup correct because I can make calls using the same code and certificate to the Azure Service Management API.
The code I'm using to attach the certificate to the web request is from the MSDN Sample. The Scheduler API calls that I've tried to make are the Check Name Availability, Create Cloud Service, and Create Job Collection.
I've also verified that my subscription is Active for the preview of the Scheduler.
Here is an example of a request I've tried:
Create Cloud Service
Request A cloud service is created by submitting an HTTP PUT operation
to the CloudServices OData collection of the Service Management API
Tenant.Replace with your subscription ID and
with your cloud service ID.
So for this I create a web request pointing to:
https://management.core.windows.net/[MySubId]/cloudServices/[MyNewServiceName]
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUri);
// Define the requred headers to specify the API version and operation type.
request.Headers.Add("x-ms-version", "2012-03-01");
request.Method = "PUT";
request.ContentType = "application/xml";
Next I add the request body as specified in the documentation:
<CloudService xmlns:i='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://schemas.microsoft.com/windowsazure'>
<Label>[MyServiceName]</Label>
<Description>testing</Description>
<GeoRegion>uswest</GeoRegion>
</CloudService>
And finally I add the certificate that I use with my subscription to the account.
// Attach the certificate to the request.
request.ClientCertificates.Add(certificate);
I try to get the response and instead I get the error shown above.
BTW - I've also tried different regions thinking maybe it was a region issue since the scheduler isn't supported in all regions, but I still get the same response.

You need to register the scheduler in your application first by calling (PUT):
<subscription id>/services?service=scheduler.JobCollections&action=register
If you want to do this in .NET you can use the new Management libraries:
var schedulerServiceClient = new SchedulerManagementClient(credentials);
var result = schedulerServiceClient.RegisterResourceProvider();
Console.WriteLine(result.RequestId);
Console.WriteLine(result.StatusCode);
Console.ReadLine();
More detail: http://fabriccontroller.net/blog/posts/a-complete-overview-to-get-started-with-the-windows-azure-scheduler/

Related

Azure Container Apps with Dapr state store failing

I am using Azure Container apps with Azure Blob Store as a state store. It is a simple Hello World (weather service) app using dotnet 6. App starts up fine, on Post I am trying to save the generated weather information to Azure Blob Store as JSON. I have configured Dapr components in Azure Container Apps for StateStore using Azure blob storage. I am using storage key (secondary key) as explained in this Microsoft documentation
Upon doing a Swagger and looking at log I get the following error.
Dapr.DaprException: State operation failed: the Dapr endpoint indicated a failure. See InnerException for details.
2022-07-17T01:10:35.716245402Z ---> Grpc.Core.RpcException: Status(StatusCode="Internal", Detail="failed saving state in state store statestore: -> github.com/Azure/azure-storage-blob-go/azblob.newStorageError, /home/vsts/work/1/go/pkg/mod/github.com/!azure/azure-storage-blob-go#v0.10.0/azblob/zc_storage_error.go:42
2022-07-17T01:10:35.716524109Z ===== RESPONSE ERROR (ServiceCode=AuthenticationFailed) =====
2022-07-17T01:10:35.716795515Z Description=Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
2022-07-17T01:10:35.716812515Z RequestId:863bcef4-401e-0069-5f7a-99724b000000
2022-07-17T01:10:35.716820115Z Time:2022-07-17T01:10:35.7137648Z, Details:
2022-07-17T01:10:35.716825516Z AuthenticationErrorDetail: Issuer validation failed. Issuer did not match.
2022-07-17T01:10:35.716831516Z Code: AuthenticationFailed
Error is Authentication Failed. I am unsure what I am missing since I am not making any additional config in storage account such as VNET service end point etc. Account is enabled for Key access. Any help is appreciated.
Below is the code that I am using
using var client = new DaprClientBuilder().Build();
var forecast = new WeatherForecast()
{
Date = DateTime.Now.AddDays(1),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
};
await client.SaveStateAsync<WeatherForecast>(stateStoreName,key,forecast);
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
i think i found the answer. The issue was with metadata since the key set in metadata of the component.yaml as mentioned in the Microsoft documentation is not working. I changed it to use secretref and referred in metadata directly in the portal. Not sure why the error was showing Authentication error but it is finally working.

The SSL connection could not be established, see inner exception. - DocuSign EnvelopesApi calls ONLY to PROD environment

I have migrating our Apis to use Docusign OAuth authentication flow. While testing I found that the code works perfectly fine when I point to Docusign Demo environment. However when I point to docusign Prod environment I get the following error.
The SSL connection could not be established, see inner exception.
There inner exception is actually null.
The docusign Auth call is fine and we get the accountId as expected. However the EnvelopesApi calls are failing. I do have a ticket open with Docusign but wanted to see if any one can help.
Our Api is deployed as a Windows Service and is in dotnet core 5.0. However I have tested this by deploying the Api to an IIS website with ssl binding and I can repro the same exception.
Auth Flow - OAuth JwtFlow
API BasePath as - "https : //docusign.net/restapi" (space added on purpose)
OAuth Base Path as - "account.docusign.com"
Below code get the accountId and sets the AccessToken. This is successful.
var privateKeyBytes = Encoding.UTF8.GetBytes(docuSignKey);
try
{
_tokenInfo = apiClient.RequestJWTUserToken(docusignConfig.IntegratorKey, docusignConfig.UserIdGuid,
docusignConfig.OAuthBasePath, privateKeyBytes, docusignConfig.TokenExpiryInHours);
var userInfo = apiClient.GetUserInfo(_tokenInfo?.access_token);
var account = userInfo?.Accounts
.FirstOrDefault(la => la.IsDefault.ToLowerInvariant() == true.ToString().ToLowerInvariant())
?? userInfo?.Accounts.First();
SetApiClientConfiguration(docusignConfig);
return account?.AccountId;
}
catch (Exception ex)
{
ESignLogger.Error($"{GetType().Name}.{nameof(AuthorizeAndGetAccountId)}. Error in getting account details. " + ex.Message);
return null;
}
Below code is the envelopesApi call which fails.
var recipientResponse = await _envelopesApi.ListRecipientsAsync(accountId, envelopeId);
The URLs for eSignature REST API calls for the DocuSign production environments can be different for different customers based on where their account is provisioned.
The default URL (https://www.docusign.net/restapi) can be used in some cases.
However, the best practice is to call the User Info endpoint for the particular user (it's by account, but a user can be a member of more than one account) and for each account that user is a member of, you'll get back a baseURI that can be different than the default I just posted above.
If this wasn't your issue, it may also be that you need to download one of the certificates to your server. You can find all of DocuSign SSL certificates in this page.
Steps to check:
OAuth step to obtain an access_token. You're using the JWT grant flow. If it returns an access token from account.docusign.com then you've succeeded. Note that your client ID (integration key) needs to pass go-live before it can be used with account.docusign.com
Next use the access token with the right base url for the eSig API. You can determine the right base url by using the /oauth/userinfo API. Or if your application is just for your own company, you can just look up your DocuSign account's base URL from the API & Keys page of the eSignature Settings (admin) tool.

Logic App http trigger with AAD auth - Event grid subscription validation failure

I'm trying to create an event grid subscription that will call a logic app every time a blob is created.
To protect the logic app http endpoint, I've enabled AAD Auth following this documentation:
Enable Azure AD OAuth for your logic app
I then configured eventgrid to attach an oauth token while calling the logic following this documentation:
Publish events to Azure Active Directory protected endpoints
While creating the subscription, I received this error:
Deployment has failed with the following error:
{
"code": "Url validation",
"message": "Webhook validation handshake failed for https://prod-07.australiaeast.logic.azure.com/workflows/5aade5e78ff84281baf17c0ab70a35d8/triggers/manual/paths/invoke. Http POST request failed with response code Unknown. For troublehooting, visit https://aka.ms/esvalidation. Activity id:4d430ada-82ee-43a6-8ad4-467f6de611d8, timestamp: 7/17/2021 12:44:13 AM (UTC)."
}
Using requestbin, I checked that the oauth token was attached (see associated requestbin)
I've also validate that the token was valid by calling the logic (from postman) using the token from requestbin.
I tired the same using a function app and it worked.
So I decided to try exposing the logic app behind API management service and it worked...
So I'm guessing Azure is doing something special with the internal logic app url: https://prod-07.australiaeast.logic.azure.com/workflows/5aade5e78ff84281baf17c0ab70a35d8/triggers/manual/paths/
Does anyone encounter the same issue and was able to work around that in a better way?

Authenticated REST API call to Azure Service Bus using Managed Identity

Azure Service Bus supports managed identity access, however the only method I've found to for example send a message to a queue is using this approach that requires code and the Service Bus SDK:
var tokenProvider = TokenProvider.CreateManagedServiceIdentityTokenProvider();
QueueClient sendClient = new QueueClient($"sb://{Config.Namespace}.servicebus.windows.net/", Config.Queue, tokenProvider);
await sendClient.SendAsync(new Message(Encoding.UTF8.GetBytes(messageInfo.MessageToSend)));
await sendClient.CloseAsync();
Sources:
https://github.com/Azure-Samples/app-service-msi-servicebus-dotnet
https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-managed-service-identity
I'm looking for a way to do the same thing with a REST API call from within an Azure API Management policy. I've granted APIM, role based access to Service Bus and I'm able to get a token back, but I get this error back from Service Bus when attempting the REST API call with the managed identity token passed in the Authorization header:
MalformedToken: The credentials contained in the WRAP header are not well-formed.
It looks like Service Bus might only support WRAP or SAS tokens at this point with their REST API: https://learn.microsoft.com/en-us/rest/api/servicebus/send-message-batch
But then again how is this working behind the scenes?
TokenProvider.CreateManagedServiceIdentityTokenProvider()
Seems like it should be possible with the REST API.
It seems in the SDK they don't specify it as Authorization: Bearer tokenabcdef..... but as Authorization: tokenabcdef. Which is a bit unusual.

Unable to Get/Post Blob on Azure Storage via Rest API in C#

Upon successful consumption of Azure Rest api in c# code. I'm able to create, fetch and fetch list of containers but not blob. While accessing or uploading blobs, this gives permission issue and i.e.,
you are not authorized to perform this request with assigned permission
Progress that i have made so far:
Able to create and fetch the container.
Able to fetch the list of all the containers of storage account.
When tries to Get/Put a blob via below source code it give me error:
This request is not authorized to perform this operation using this permission.
string endPointUri = $"{azureApplicationConfiguration.Resource}/{inpContainerName}/{inpBlobName}";
var request = (HttpWebRequest)WebRequest.Create(endPointUri);
request.Method = HTTPMethod.GET.ToString();
request.Headers.Add("Authorization", $"Bearer {sasToken.access_token}");
request.Headers.Add("x-ms-date", DateTime.UtcNow.ToString("R"));
request.Headers.Add("x-ms-version", "2018-03-28");
request.ProtocolVersion = HttpVersion.Version11;
using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
{
Console.WriteLine(resp.StatusCode.ToString());
Console.ReadKey();
}
The most likely answer is that the SAS token you're using to authenticate does not support object level access. You can confirm this by checking if there is a letter o in the Signed Resource Types srt= parameter in your SAS token. Based on the fact you can list and create containers, I'd guess the current value is srt=sc. To be able to perform GET/PUT operations on a blob as well, you'll need to generate a new SAS token that includes object level permissions, which should give you a token containing srt=sco.
In case you aren't aware of it already, there is a .NET Azure Storage SDK available, which provides a layer of abstraction over the REST API and may save you some time in the long run.

Resources