Setting CORS rules using Azure.Storage.Blobs - azure

I'm trying to migrate from the deprecated Microsoft.WindowsAzure.Storage to Azure.Storage. In my API app, I have a method that I call occasionally to programmatically set the CORS rules in my Azure Storage account.
How do I add CORS rules to the properties using the new Azure.Storage.Blobs?
My original code that worked under Microsoft.WindowsAzure.Storage is as follows. In the following code, the _client is an instance of CloudBlobClient. I understand that in Azure.Storage.Blobs, I need to use BlobServiceClient which I now do but as I said, some parts of the following code are not working because some methods/properties are no longer there. I'm sure they're moved somewhere else but I haven't been able to figure out where.
public async Task ConfigureCors()
{
var ALLOWED_CORS_ORIGINS = new List<String> { "http://localhost:49065", "https://myappdomain.com", "https://www.myappdomain", "https://login.microsoftonline.com" };
var ALLOWED_CORS_HEADERS = new List<String> { "x-ms-meta-qqfilename", "Content-Type", "x-ms-blob-type", "x-ms-blob-content-type" };
const CorsHttpMethods ALLOWED_CORS_METHODS = CorsHttpMethods.Get | CorsHttpMethods.Delete | CorsHttpMethods.Put | CorsHttpMethods.Options;
const int ALLOWED_CORS_AGE_DAYS = 5;
var properties = await _client.GetServicePropertiesAsync();
properties.DefaultServiceVersion = "2013-08-15";
await _client.SetServicePropertiesAsync(properties);
var addRule = true;
if (addRule)
{
var ruleWideOpenWriter = new CorsRule()
{
AllowedHeaders = ALLOWED_CORS_HEADERS,
AllowedOrigins = ALLOWED_CORS_ORIGINS,
AllowedMethods = ALLOWED_CORS_METHODS,
MaxAgeInSeconds = (int)TimeSpan.FromDays(ALLOWED_CORS_AGE_DAYS).TotalSeconds
};
properties.Cors.CorsRules.Clear();
properties.Cors.CorsRules.Add(ruleWideOpenWriter);
await _client.SetServicePropertiesAsync(properties);
}
}
Looks like I can get and set properties by changing _client.GetServicePropertiesAsync() to _client.GetPropertiesAsync() but DefaultServiceVersion is no longer there. Also I can't seem to find the right way to set CORS rules.
I'd appreciate your suggestions. Thanks!

You can use the code below when using Azure.Storage.Blobs(I'm using sync method, please change it to async method if you need that):
var properties = blobServiceClient.GetProperties().Value;
properties.DefaultServiceVersion = "xxx";
BlobCorsRule rule = new BlobCorsRule();
rule.AllowedHeaders= "x-ms-meta-qqfilename,Content-Type,x-ms-blob-type,x-ms-blob-content-type";
rule.AllowedMethods = "GET,DELETE,PUT,OPTIONS";
rule.AllowedOrigins = "http://localhost:49065,https://myappdomain.com,https://www.myappdomain,https://login.microsoftonline.com";
rule.MaxAgeInSeconds = 3600; // in seconds
properties.Cors.Add(rule);
blobServiceClient.SetProperties(properties);

Related

Amazon Translate - Formality Setting in .Net?

When trying to use the Formality setting (https://aws.amazon.com/about-aws/whats-new/2022/10/amazon-translate-formality-customization-support-dutch-korean-mexican-spanish/ ) in code behind (.Net), I keep getting System.NullReferenceException: 'Object reference not set to an instance of an object.'
Here's the code I'm running - everything works as expected until I add in request.Settings.Formality = "FORMAL";`
using (var client = new AmazonTranslateClient(awsCredentials, selectedRegion))
{
var request = new Amazon.Translate.Model.TranslateTextRequest();
request.Text = toTranslate;
request.SourceLanguageCode = sourceLanguage;
request.TargetLanguageCode = translateLanguage;
request.Settings.Formality = "FORMAL";
`Looking at the limited examples in other languages from the AWS documentation doesn't indicate anything else that's needed. I also tried the Profanity setting and the same results - System.NullReferenceException.
I also tried making the call later via the using statement that looks like this with the same error:`
var response = client.TranslateTextAsync(request).GetAwaiter().GetResult();
response.AppliedSettings.Formality = translationFormality;
`
Updated code with solution that worked for me:
using (var client = new AmazonTranslateClient(awsCredentials, selectedRegion))
{
var request = new Amazon.Translate.Model.TranslateTextRequest();
request.Text = toTranslate;
request.SourceLanguageCode = sourceLanguage; // SourceLanguageItem.LanguageCode;
request.TargetLanguageCode = translateLanguage; // TranslateLanguageItem.LanguageCode;
TranslationSettings settings = new TranslationSettings();
settings.Formality = "FORMAL";
request.Settings = settings;

Access Azure Data Explorer with Kusto.Data in Azure Function -- Kusto failed to send request -- local debugging works

I am having the following problem and an extensive search online didn't provide any good results.
When trying to access my Azure Data Explorer Database and querying using the Kusto.Data SDK in an Azure Function, it yields the following error:
Kusto client failed to send a request to the service: 'An unknown, invalid, or unsupported option or level was specified in a getsockopt or setsockopt call.'
However, running the Function on my local machine, everything works fine.
Edit: The function excepts at using (var reader = await queryProvider.ExecuteQueryAsync(Database, query, clientRequestProperties))
EDIT2 - SOLUTION:
You can downgrade the NuGet Kusto.Data Package to Version 9.4.1, this solves the problem and doesn't throw any error anymore. If you still encounter difficulties, you can try to directly access the ADX database via http requests:
const string tenantId = "<tenantId>";
const string client_id = "<clientId>";
const string client_secret = "<client_secret>";
const string Cluster = "<cluster_adress";
const string Database = "<database_name>";
var authUrl = "https://login.microsoftonline.com/<tenantId>/oauth2/token";
var param = new Dictionary<string, string>
{
{"client_id",client_id},
{"grant_type","client_credentials"},
{"client_secret",client_secret},
{"resource","https://help.kusto.windows.net"}
};
var data = new FormUrlEncodedContent(param);
using var authClient = new HttpClient();
var response = await authClient.PostAsync(authUrl, data);
string result = response.Content.ReadAsStringAsync().Result;
//parse result
var resultJson = System.Text.Json.JsonDocument.Parse(result);
//retrieve access token
var accessToken = resultJson.RootElement.GetProperty("access_token");
//-----------------------------------------------------------------------------------------------
var dataXUrl = Cluster + "/v1/rest/query";
var database = Database;
var dataXQuery = "sample_table| where Time > ago(2min)";
var body = new Dictionary<string, string>
{
{"db",database},
{"csl",dataXQuery}
};
using var dataXClient = new HttpClient();
dataXClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.ToString());
dataXClient.DefaultRequestHeaders.Add("Accept", "application/json");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, dataXUrl);
request.Content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
var table = await dataXClient.SendAsync(request);
//pretty print
var obj = JsonConvert.DeserializeObject(table.Content.ReadAsStringAsync());
var tableJSON = JsonConvert.SerializeObject(obj, Formatting.Indented);
log.LogInformation("\n\n" + tableJSON);
I am having the same issue on a continuous webjob on an Azure App Service. The Kusto nuget version I am using is 10.1.0
Downgrading to nuget 9.4.1 solved the problem immediately.
FYI - This only seems to affect 10.1.0. The earlier 10.x.x versions should work.
The ADX team believes they will have this fixed in the next nuget version.

How do I authenticate with azure/identity module in node.js?

I am using a node.js application (v12.18.2, not in the browser) to access an Azure blob store. My existing code using #azure/storage-blob v10.5.0 is working and the authentication code looks like this:
const Azure = require( '#azure/storage-blob' );
let containerUriWithSAS = `${credentials.container_uri}?${credentials.sas_token}`;
let pipeline = Azure.StorageURL.newPipeline( new Azure.AnonymousCredential() );
let ContainerURL = new Azure.ContainerURL( containerUriWithSAS, pipeline );
Using this code to authenticate and then using, for example, ContainerURL.listBlobFlatSegment() to list objects works perfectly. I can create, get, delete, and list objects.
When I upgraded to #azure/storage-blob v12.1.2, there were some breaking changes. Now my code looks like:
//const{ DefaultAzureCredential } = require( '#azure/identity' ); // tried this instead of AnonymousCredential
const{ BlobServiceClient, AnonymousCredential } = require( '#azure/storage-blob' );
let containerUriWithSAS = `${credentials.container_uri}?${credentials.sas_token}`;
//let defaultAzureCredential = new DefaultAzureCredential();
let anonymousCredential = new AnonymousCredential();
let blobServiceClient = new BlobServiceClient( containerUriWithSAS, anonymousCredential );
const containerName = 'MyContainer';
const containerClient = blobServiceClient.getContainerClient( containerName );
const createContainerResponse = await containerClient.create();
On one (Linux) machine, I cannot connect to the server at all (the create() call times out). On another (Windows), the create() call throws an error which tells me that "The requested URI does not represent any resource on the server".
I've verified that the URI is exactly the same as one used by the working code but obviously I'm missing something in my understanding of the authentication process. How do I make my new code do what my old code did?
Also, it seems that I have to create a container before I can create objects, which I didn't have to do before. Is that part of my confusion?
BlobServiceClient should be created like below (not like with container URI you are doing). Also, note you don't need AnonymousCredential.
const { BlobServiceClient } = require("#azure/storage-blob");
const account = "<account name>";
const sas = "<service Shared Access Signature Token>";
const blobServiceClient = new BlobServiceClient(
`https://${account}.blob.core.windows.net${sas}`
);
const containerName = 'MyContainer';
const containerClient = blobServiceClient.getContainerClient(containerName);
// and go on doing your stuffs

Azure Node SDK - 500 response with filter option

I am seeing a weird error on the with Azure Node SDK where I get a 500 error back anytime i include anything in the filter attribute of the options parameter. I am using the Usage Details call within the ConsumptionManagementClient class. Code is below:
const credentials = await MsRest.loginWithServicePrincipalSecret(config.appId, config.apiKey, config.tenantId);
let client = new ConsumptionManagementClient(credentials, subscriptionId);
const scope = `/subscriptions/${subscriptionId}`;
const options = { filter: "usageStart ge datetime'2017-10-13T00:00:00.000Z'"};
let usage = await client.usageDetails.list(scope, options);
The above code produces a 500 error(even tried searching for other things another example being "billableQuantity ge 0.001") but it seems to error out no matter what i give it.
The code works fine when i try using another one of the options paramters:
const credentials = await MsRest.loginWithServicePrincipalSecret(config.appId, config.apiKey, config.tenantId);
let client = new ConsumptionManagementClient(credentials, subscriptionId);
const scope = `/subscriptions/${subscriptionId}`;
const options = { top: 50 };
let usage = await client.usageDetails.list(scope, options);
Any ideas? Thanks in advance for the help!

ADFS 2.0 custom login page implementation - "The request scope is not valid or is not supported"

I am trying to work out how to set up my SharePoint 2013 to use a custom login page to login through ADFS 2.0 instead of the standard one.
I am following this tutorial: http://blog.helloitsliam.com/Lists/Posts/Post.aspx?ID=76
After making the changes to web.config I have written the following code to my page:
using (var wsFactory = new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress(endpoint)))
{
wsFactory.Credentials.UserName.UserName = signInControl.UserName;
wsFactory.Credentials.UserName.Password = signInControl.Password;
wsFactory.TrustVersion = TrustVersion.WSTrust13;
var wsChannel = wsFactory.CreateChannel();
var requestSecurityToken = new RequestSecurityToken { RequestType = RequestTypes.Issue, AppliesTo = new EndpointReference(AppliesToEndpointUrl), KeyType = KeyTypes.Symmetric };
try
{
var genericSecurityToken = wsChannel.Issue(requestSecurityToken) as GenericXmlSecurityToken;
var securityTokenHandlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
var securityToken = securityTokenHandlers.ReadToken(new XmlTextReader(new StringReader(genericSecurityToken.TokenXml.OuterXml)));
SPSecurity.RunWithElevatedPrivileges(() =>
Microsoft.SharePoint.IdentityModel.SPFederationAuthenticationModule.Current.SetPrincipalAndWriteSessionToken(securityToken));
var rUrl = Request.QueryString.Get("Source");
Response.Redirect(String.IsNullOrEmpty(rUrl) ? "~/Pages/Default.aspx" : rUrl);
}
catch (Exception ex)
{
Response.Write(ex.StackTrace);
}
The debugger throws the following error on the wsChannel.Issue method invocation:
ID3082: The request scope is not valid or is unsupported.
Now, how should I investigate the cause of such error?

Resources