Can I able to use default proxy for cosmos db project - azure-cosmosdb

I have done a service using cosmos db and asp.net core .For WiFi it is working but when i try with default proxy it give the error.
SocketException: Resource temporarily unavailable
System.Net.Http.ConnectHelper.ConnectAsync(string host, int port, CancellationToken cancellationToken)
HttpRequestException: Resource temporarily unavailable
System.Net.Http.ConnectHelper.ConnectAsync(string host, int port, CancellationToken cancellationToken)
DocumentClient Create code example:
public async Task<IEnumerable<Product>> FetchProductListAsync(
Guid? itemId)
{
var feedOptions =
new FeedOptions
{
MaxItemCount = -1,
EnableCrossPartitionQuery = true
};
var query =
$"SELECT product.Id,product.Name,product.MethodOfPreparation,product.Addons,product.CurrentQuantity,product.Tag,product.Unit,product.Price FROM catalog join industry in catalog.Industy join category in industry.Category join Subcategory in category.Subcategory join product in Subcategory.Product where catalog.id = '" + itemId + "'";
var queryDefinition =
new SqlQuerySpec(query);
var orderDocumentQuery =
_docClient.CreateDocumentQuery<Product>(
UriFactory.CreateDocumentCollectionUri(
_azureCosmosDbOptions.Value.DatabaseId, "catalog"), queryDefinition, feedOptions)
.AsDocumentQuery();
var childrenSqlQuery = _docClient.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(_azureCosmosDbOptions.Value.DatabaseId, "catalog"), query).ToString();
Console.WriteLine(childrenSqlQuery);
Console.WriteLine(childrenSqlQuery);
var orderList =
new List<Product>();
while (orderDocumentQuery.HasMoreResults)
{
orderList.AddRange(
await orderDocumentQuery.ExecuteNextAsync<Product>());
Console.WriteLine(orderList);
}
return orderList;
}
I am using DucumentDb.Core 2.4.1,Please give me idea .

In node js sdk, you could set the ProxyUrl property directly.(How to use DocumentDB behind a Proxy in NodeJS)
However,it doesn't have such properties in the .NET sdk. You could try below configuration from this case:CosmosDB C# SDK ProyUrl missing
<system.net>
<defaultProxy enabled="true" useDefaultCredentials="true">
<proxy usesystemdefault="True" />
</defaultProxy>
</system.net>
However,i noticed that it only supports .net,not for .net core,from this trace.So, please refer to this case:asp.net core defaultProxy

Related

How to get Client IP Address in Dotnet-Isolated Azure Functions?

I'm writing a function in .NetCore 6.0 (C#) using Azure Functions Isolation and need to get the ip address of the client.
Is there any way to get Client IP address from the HttpRequestData OR FunctionContext object?
[Function("GetClientIP")]
public async Task<HttpResponseData> GetClientIP([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req, FunctionContext functionContext)
{ .... }
I have referred following link: but it is not for ISOLATION mode.
Remarks: I am using ISOLATION mode.
I was finally able to retrieve it by using the code below.
Please note that the header value "x-forwarded-for" is only available when hosted within azure.
public async Task<HttpResponseData> SendMessage(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req,
FunctionContext executionContext,
string requestName)
{
var headerDictionary = req.Headers.ToDictionary(x => x.Key, x => x.Value, StringComparer.Ordinal);
var key = "x-forwarded-for";
if (headerDictionary.ContainsKey(key))
{
IPAddress? ipAddress = null;
var headerValues = headerDictionary[key];
var ipn = headerValues?.FirstOrDefault()?.Split(new char[] { ',' }).FirstOrDefault()?.Split(new char[] { ':' }).FirstOrDefault();
if (IPAddress.TryParse(ipn, out ipAddress))
{
var ipAddressString = ipAddress.ToString();
}
}
}
In my case the retrieved value contained the following value
"105.224.244.204, 147.243.88.136:58088"
The first IP address in the list contains the client IP address.
I also discovered that I could have retrieved it with key value "x-azure-clientip". The reason for this is the function is hosted behind Azure Front Door.
The link goes into more detail about what headers can be expected on the request when hosted behind Azure Front Door
https://learn.microsoft.com/en-us/azure/frontdoor/front-door-http-headers-protocol

EPPLUS package works fine locally but returns Internal server error when deployed to azure server

I have my web api that uploads and reads an excel file from the client app and then afterwards saves the data into the database, the application works perfect on locally server but the problem comes when the application is deployed to azure server it returns error 500 internal server error therefore i don't understand why this happens and and don't know how i can track to understand what might be the cause below are my code blocks.
My Interface Class
public interface UploadExcelInterface
{
Task UploadMultipleClients(Client obj);
}
My Service Implementation
public class UploadExcelService : UploadExcelInterface
{
private readonly DbContext _connect;
private readonly IHttpContextAccessor httpContextAccessor;
public UploadExcelService(DbContext _connect, IHttpContextAccessor httpContextAccessor)
{
this._connect = _connect;
this.httpContextAccessor = httpContextAccessor;
}
public async Task UploadMultipleClients(Client obj)
{
var file = httpContextAccessor.HttpContext.Request.Form.Files[0];
if (file != null && file.Length > 0)
{
var folderName = Path.Combine("Datas", "ClientUPloads");
var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
var fileName = Guid.NewGuid() + ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
var fullPath = Path.Combine(pathToSave, fileName);
var clientsList = new List<Client>();
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
FileInfo excelFile = new FileInfo(Path.Combine(pathToSave, fileName));
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(excelFile))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
var rowcount = worksheet.Dimension.Rows;
for (int row = 2; row <= rowcount; row++)
{
var Names = (worksheet.Cells[row,2].Value ?? string.Empty).ToString().Trim();
var Address = (worksheet.Cells[row,3].Value ?? string.Empty).ToString().Trim();
var Title = (worksheet.Cells[row,4].Value ?? string.Empty).ToString().Trim();
var Product = (worksheet.Cells[row,5].Value ?? string.Empty).ToString().Trim();
var Order = (worksheet.Cells[row,6].Value ?? string.Empty).ToString().Trim();
var Email = (worksheet.Cells[row,7].Value ?? string.Empty).ToString().Trim();
var Price = (worksheet.Cells[row,8].Value ?? string.Empty).ToString().Trim();
clientsList.Add(new Client
{
Names = Names,
Address = Address,
Title = Title,
Product = Product,
Order = Order,
Email = Email,
Price = Price,
}
}
//adding clients into the database
foreach (Client client in clientsList)
{
var exist = _connect.client.Any(x => x.Email == client.Email);
if (!exist)
{
await _connect.client.AddAsync(client);
}
}
await _connect.SaveChangesAsync();
}
}
}
My Controller Class
[HttpPost]
public async Task UploadMultipleClients([FromForm] Client obj)
{
await uploadExcelInterface.UploadMultipleClients(obj);
}
}
Please any help regarding this error that am getting from the server, and addition on that is it possible to get the data from the excel file without uploading it to server if yes how? because i tried adding the file to memory stream an reading it from memory but it appers not work, any suggestions thanks.
My answer may not help you solve the problem directly, but it can locate the error step by step. After we fix the error, we should be able to solve the problem in this thread.
Suggestions
Please make sure you have inclue EPPlus library in your deploy content.
Enabling ASP.NET Core stdout log (Windows Server)
Azure App Service - Configure Detailed Error Logging
Why
After tested, I am sure azure webapp can support EPPlus. For 500 error, as we don't have a more specific error message to refer to, we can't quickly locate the problem. Following the suggested method, you will surely see some useful information.
E.g:
The class library of EPPlus was not found.
Folders such as Datas are not created.
The database connection string, the test environment and the production environment may be different.
...

Is it possible in a .NET Core application to retrieve a certificate from AWS Certificate Manager and use it in a HttpClient post?

My .Net core application makes a post request to an external web service using HttpClient. The external web service requires a certificate to validate against.
The certificates are installed in AWS and I have an ARN that points to the certificate.
Is it possible to get the certificate programitically from AWS Certificate Manager and use this in my HtppClient, for example this is the code I would use normally to add a certificate but I need to get it from AWS.
private HttpClientHandler HttpClientHandler()
{
var handler = new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
SslProtocols = SslProtocols.Tls12
};
handler.ClientCertificates.Add(new X509Certificate2("cert.crt")); //TODO: fetch from AWS.
return handler;
}
So, it's possible.
I installed AWSSDK.Core and AWSSDK.CertificateManager from NuGet.
Then, I created a credentials file for AWS, see instructions from Amazon
https://docs.aws.amazon.com/cli/latest/userguide/cli-config-files.html
Next, I used the AmazonCertificateManagerClient to get the certificate.
AmazonCertificateManagerClient client = new AmazonCertificateManagerClient();
var certificates = client.GetCertificateAsync(arn).Result;
I then converted the certificate from string to bytes and then add to the handler.
var handler = new HttpClientHandler{
ClientCertificateOptions = ClientCertificateOption.Manual,
SslProtocols = SslProtocols.Tls12
};
byte[] toBytes = Encoding.ASCII.GetBytes(certificates.Certificate);
var cert = new X509Certificate2(toBytes);
handler.ClientCertificates.Add(cert);
var httpClient = new HttpClient(handler);
Obviously, not production worthy code, hope it helps.
As mentioned by Zack the accepted answer does not work. It does retrieve a certificate out of ACM but it is not usable as a client certificate for HttpClient because it has no private key.
As far as I can tell there is no way to get the private key out of ACM so I ended up putting it in SecretsManager and doing something like:
var certManagerClient = new AmazonCertificateManagerClient();
var awsCert = certManagerClient.GetCertificateAsync(arn).Result;
byte[] awsBytes = Encoding.ASCII.GetBytes(awsCert.Certificate);
var cert = new X509Certificate2(awsBytes);
var secretsManagerClient = new AmazonSecretsManagerClient();
var privateKey = secretsManagerClient.GetSecretValueAsync(new GetSecretValueRequest { SecretId = secretId }).Result.SecretString;
byte[] privateKeyBytes = Convert.FromBase64String(privateKey);
var privateKey = RSA.Create();
privateKey.ImportRSAPrivateKey(new ReadOnlySpan<byte>(privateKeyBytes), out _);
var certWithPrivateKey = cert.CopyWithPrivateKey(privateKey);
And then using certWithPrivateKey in my HttpClientHandler:
var handler = new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Manual };
handler.ClientCertificates.Add(certWithPrivateKey);
If you use the AWS SDK you can get certificates using the AmazonCertificateManagerClient. See the AWS SDK documentation for details. (select Amazon.CertificateManager > AmazonCertificateManagerClient)

DotNet Core HttpClient security error

I have a class library to perform Rest API calls built in 4.6.1 framework. I have used System.Net.Http V4 HttpClient for managing calls. This library works in normal dotnet apps. Recently I tried it for a DotNet Core app, it failed with security error. Later I modified library as suggested in post. It had some progress but the app fails with error as shown below
Error message: An error occurred while sending the request.
Innerexception message: A security error occurred.
StackTrace:
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Threading.Tasks.RendezvousAwaitable`1.GetResult()
at System.Net.Http.WinHttpHandler.d__105.MoveNext()
Library Code:
private readonly HttpClient _client = null;
private ICredentials somecred;
public Program()
{
HttpClientHandler clientHandler = new HttpClientHandler { Credentials = somecred, UseDefaultCredentials = false };
_client=new HttpClient(new MessageHandler(clientHandler, TimeSpan.FromSeconds(1), 1), false);
_client.Timeout = TimeSpan.FromSeconds(90);
_client.BaseAddress = new Uri("https://somedomain.com/");
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.DefaultConnectionLimit = 10;
ServicePointManager.Expect100Continue = true;
}
public async Task<IOperationResponse> GetData()
{
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
using (HttpResponseMessage httpResponse =
await _client.SendAsync(new HttpRequestMessage(HttpMethod.Head, "api/getdata"), HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)
)
{
if (httpResponse != null) { ... }
}
}
internal class MessageHandler : DelegatingHandler
{
public MessageHandler(HttpMessageHandler innerHandler, TimeSpan retryInterval, int retryCount) : base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
HttpResponseMessage response = null;
//!! security error in below line
response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
}
Please let me know, what needs to be done for this library to run for DotNet Core apps. Thanks.
I have tested your code locally with a core project and an external 4.5 library and the only way I could get the security error to trigger was if the target site did not have the correct level of security (i.e was not correctly setup with SSL). When targeting a site that had SSL configured correctly the call went through.
Ensure that your target has SSL setup or target another known working SSL site to test against to see if you still encounter the issue.
I made following code change as per my colleague suggestion and that fixed it.
//original code
_client.BaseAddress = new Uri("https://xyz.abc.somedomain.com/");
//fix code
_client.BaseAddress = new Uri("https://abc.somedomain.com/");
_client.DefaultRequestHeaders.Host = "xyz.abc.somedomain.com";
I'm marking this as answer, though i do not completely understand this behavior.

Impersonate core service in Tridion 2011 SP1 HR1

I am trying to impersonate the Core Service in Tridion 2011 SP1 HR1 and I get this error:
The message could not be processed because the action
'http://www.sdltridion.com/ContentManager/CoreService/2011/ISessionAwareCoreService/Impersonate' is invalid or unrecognized.
Why does this happen? I have to be blind to not see why it isn't working...
About the server: new installation of Tridion 2011 SP1 HR1
My code looks like this:
client = Client.GetCoreService();
if (string.IsNullOrEmpty(username)) username = HttpContext.Current.User.Identity.Name;
client.Impersonate(username);
and this is the GetCoreService method:
public static SessionAwareCoreServiceClient GetCoreService()
{
AppSettingsReader reader = new AppSettingsReader();
string coreServiceUrl = (string)reader.GetValue("CoreServiceEndPoint", typeof(string));
int dataSize = (int)reader.GetValue("DataSize", typeof(int));
var quotas = new System.Xml.XmlDictionaryReaderQuotas
{
MaxStringContentLength = dataSize,
MaxArrayLength = dataSize,
MaxBytesPerRead = dataSize
};
var httpBinding = new WSHttpBinding
{
MaxReceivedMessageSize = 10485760,
ReaderQuotas = quotas,
Security = { Mode = SecurityMode.Message, Transport = { ClientCredentialType = HttpClientCredentialType.Windows } }
};
var endpoint = new EndpointAddress(coreServiceUrl);
var result = new SessionAwareCoreServiceClient(httpBinding, endpoint);
return result;
}
extract from appsettings (replaced actual hostname with "hostname"):
<add key="CoreServiceEndPoint" value="http://hostname/WebServices/CoreService.svc/wsHttp_2010" />
<add key="DataSize" value="41943040" />
Take a look at this sample from an open source project for notification which does what you need
http://code.google.com/p/tridion-notification-framework/source/browse/NotificationService/NotificationService/CoreService/Client.cs
Here is the working line which impersonates
public static SessionAwareCoreServiceClient GetCoreService()
{
var result = GetNewClient<SessionAwareCoreServiceClient>();
result.Impersonate(ConfigurationManager.AppSettings.Get("adminUser"));
return result;
}
Also take a look at the way the client is created in the sample in the same CS file, and the App Settings. I think you are using an old endpoint address, it should be http://hostname/webservices/CoreService2011.svc/wsHttp rather than http://hostname/WebServices/CoreService.svc/wsHttp_2010
You are connecting to an old Core Service wsHttp endpoint.
If you are using the 2011 SP1 client, you need to connect to the following endpoint instead:
http://hostname/webservices/CoreService2011.svc/wsHttp

Resources