Accessing the file share from Azure Worker Role - azure

We want migrate our FTP servers in Windows Azure. We created clean virtual machine image and installed FTP Server there. Now, to be able to process the files resided in the FTP directory ,directly from Windows Azure data center, we created the file share and endpoints (port 445 TCP and UDP). If we are trying to access the FTP Server's file share from the Worker Role we are getting usually 'Access to the path '...' is denied.'. We are able to access the FTP Server's file share over the remote desktop from the Worker Role, what mean the Firewall and FTP configuration are correct. Can a worker role access the file shares in the Windows Azure data center?
The code:
try
{
const string networkShare = #"...";
Directory.GetFiles(networkShare).ToList().ForEach(file => Trace.TraceInformation(file));
Thread.Sleep(10000);
Trace.WriteLine("Working", "Information");
}
catch (Exception ex)
{
Trace.TraceError(ex.ToString());
}
The exception:
Exception thrown on running: System.UnauthorizedAccessException: Access to the path '...' is denied.
Server stack trace:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileSystemEnumerableIterator`1.CommonInit()
at System.IO.FileSystemEnumerableIterator`1..ctor(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler`1 resultHandler, Boolean checkHost)
at System.IO.Directory.InternalGetFileDirectoryNames(String path, String userPathOriginal, String searchPattern, Boolean includeFiles, Boolean includeDirs, SearchOption searchOption, Boolean checkHost)
at System.IO.Directory.InternalGetFiles(String path, String searchPattern, SearchOption searchOption)
at KALCIK.NET.Plugin.ReadFromShare.ReadFromSharePlugin.Manipulate(String valueToManipulate)
at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at KALCIK.NET.Plugin.Contracts.TextManipulationPluginBase.Manipulate(String valueToManipulate)
at KALCIK.NET.CloudServices.WorkerRole.BusinessLayers.WorkOrderProcessing.ProcessWorkOrder(Tuple`2 workOrder) in c:\Development\Samples\CloudServicesPlugInSample\CloudServices.WorkerRole\BusinessLayers\WorkOrderProcessing.cs:line 56
at KALCIK.NET.CloudServices.WorkerRole.WorkOrderProcessorService.Run() in c:\Development\Samples\CloudServicesPlugInSample\CloudServices.WorkerRole\WorkOrderProcessorService.cs:line 67; TraceSource 'WaWorkerHost.exe' event

Yes the problem seems to be the user, under the host process is running. To resolve this issue you can create the new user with the administrator privileges (for example with the help of start up task, when the role is starting) and impersonate the executed code. You can see the sample implementation here.
public class WorkerRole : RoleEntryPoint
{
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle() : base(true) { }
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
public override void Run()
{
// This is a sample worker implementation. Replace with your logic.
Trace.WriteLine("TestWorkerRole entry point called", "Information");
while (true)
{
try
{
SafeTokenHandle safeTokenHandle;
var returnValue = LogonUser("username", Environment.MachineName, "password", 2, 0, out safeTokenHandle);
if (returnValue)
{
using (safeTokenHandle)
{
using (var impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle()))
{
const string networkSharePath = #"UNCPath";
Directory.GetFiles(networkSharePath).ToList().ForEach(file => Trace.TraceInformation(file));
}
}
}
Thread.Sleep(10000);
Trace.WriteLine("Working", "Information");
}
catch (Exception ex)
{
Trace.TraceError(ex.ToString());
}
}
}
}

I think it's a security issue: the user (under which the Working Role runs) is not able to authenticate on the network share. Try a "net use" before your Directory.GetFiles
"net use" from C# : Access a Remote Directory from C#

Related

InPlaceHostingManager Hosted in IIS, Access is denied error

I am using the InPlaceHostingManager class to integrate the manifest file for some click once applications hosted in IIS, I am trying to get the version number. See code below
try
{
iphm = new InPlaceHostingManager(new Uri(deployManifestUriStr), false);
iphm.GetManifestCompleted += new EventHandler<GetManifestCompletedEventArgs>(iphm_GetManifestCompleted);
iphm.GetManifestAsync();
}
catch (UriFormatException uriEx)
{
this._logger.Fatal(uriEx, $"Unable to load Applicaition Versions (Invalid Uri) for uri : {deployManifestUriStr}");
}
catch (PlatformNotSupportedException platformEx)
{
this._logger.Fatal(platformEx, $"Unable to load Applicaition Versions (Platform Not Supported Exception) for uri : {deployManifestUriStr}");
}
catch (ArgumentException argumentEx)
{
this._logger.Fatal(argumentEx, $"Unable to load Applicaition Versions (Argument Exception) for uri : {deployManifestUriStr}");
}
catch (UnauthorizedAccessException ex)
{
this._logger.Fatal(ex);
this._logger.Fatal(ex.InnerException);
this._logger.Fatal(ex, $"Unable to load Applicaition Versions (Unauthorized Access Exception) for uri: {deployManifestUriStr}");
}
catch (Exception ex)
{
this._logger.Fatal(ex, $"Unable to load Applicaition Versions (Exception) for uri : {deployManifestUriStr}");
}
I am getting the following error
System.UnauthorizedAccessException: Access to the path 'Deployment' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.Directory.InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj, Boolean checkHost)
at System.IO.Directory.InternalCreateDirectoryHelper(String path, Boolean checkHost)
at System.Deployment.Application.SubscriptionStore..ctor(String deployPath, String tempPath, ComponentStoreType storeType)
at System.Deployment.Application.SubscriptionStore.get_CurrentUser()
at System.Deployment.Application.DeploymentManager..ctor(Uri deploymentSource, Boolean isUpdate, Boolean isConfirmed, DownloadOptions downloadOptions, AsyncOperation optionalAsyncOp)
at System.Deployment.Application.InPlaceHostingManager..ctor(Uri deploymentManifest, Boolean launchInHostProcess)
at Logging.ApplicaitionVersionManifestHelper.Read(String deployManifestUriStr) in
The applicaition pool is running as network service. Does anyone know where the Deployment folder is?
I had a look inside InPlaceHostingManager > DeploymentManager > SubscriptionStore > Get_CurrentUser (CurrentUSer) I Found the following
public static SubscriptionStore CurrentUser
{
get
{
if (_userStore == null)
{
lock (_currentUserLock)
{
if (_userStore == null)
{
string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string deployPath = Path.Combine(folderPath, "Deployment");
string tempPath = Path.Combine(Path.GetTempPath(), "Deployment");
_userStore = new SubscriptionStore(deployPath, tempPath, ComponentStoreType.UserStore);
}
}
}
return _userStore;
}
}
After copying the code to some where I could debug it, I found the following.
string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
The above line returns nothing. This lead me to the following
Stackoverflow Post
This change fixed it for me
Open your %WINDIR%\System32\inetsrv\config\applicationHost.config and look for <applicationPoolDefaults>. Under <processModel>, make sure you have the following attributes loadUserProfile="true" setProfileEnvironment="true"
You can use Process Monitor to see which is the Deployment folder.
About how to use the Process Monitor you can refer to this link:
Process Monitor

"LocalSystem" and Linux Samba Network share access, IOException: The specified server cannot perform the requested operation

using System;
using System.IO;
using System.Linq;
namespace CreateDirectoryTest {
internal class Program {
public static void Main(string[] args) {
if (!args.Any()) {
Console.WriteLine("Error: Usage: CreateDirectoryTest.exe {paths}");
}
foreach (var arg in args) {
try {
Console.WriteLine("Need to create the folder? " + arg + " (y/n)");
var input = Console.ReadLine();
if (input != null && input.Equals("n")) {
continue;
}
Directory.CreateDirectory(arg);
} catch (Exception e) {
Console.WriteLine("Error Creating directory: " + arg);
Console.WriteLine(e);
}
}
}
}
}
The above code creates an executable CreateDirectoryTest.exe and has been tested on win 2016 server and win 10 desktop machines respectively.
eg: CreateDirectoryTest.exe \\\ip-address\data\testFolder
\\ip-address\data\testFolder is a network share on a Linux filesystem and SMB protocol is been used for the communication.
The above process was executed under administrator and system (NT Authority/ SYSTEM) users respectively on both operating systems, but this fails on win 2016 server for the system user execution scenario with the following error:
Error Creating directory: \\ip-address\data\testFolder
System.IO.IOException: The specified server cannot perform the requested operation.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.Directory.InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj, Boolean checkHost)
at System.IO.Directory.InternalCreateDirectoryHelper(String path, Boolean checkHost)
at System.IO.Directory.CreateDirectory(String path)
at CreateDirectoryTest.Program.Main(String[] args)
Could someone please suggest a solution to resolve this issue on win server 2016?
Note: Windows 2016 server is not registered in the domain, while Windows 10 is been registered and has a domain name

ASP.NET CORE 2.2 Deployment Issue

I'm having the weirdest issue and I have no idea why.
When deploying our .net core 2.2 api to our local IIS server I get the following error message:
HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure
After checking the event log I this is the error that I find:
Application: dotnet.exe
CoreCLR Version: 4.6.27207.3
Description: The process was terminated due to an unhandled exception.
Exception Info: System.InvalidOperationException: No service for type 'Digitise.Infrastructure.Services.DatabaseMigrator' has been registered.
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Digitise.ApiBase.BaseProgram.Initialise(String[] args, IWebHost host) in C:\Projects\Digitise.AspNetCore\Digitise.ApiBase\BaseProgram.cs:line 17
at Digitise.Api.Program.Main(String[] args) in C:\Projects\Digitise.AspNetCore\Digitise.Api\Program.cs:line 27
It seems like the DI is not working correctly! The weird thing is if I run the api.exe or dotnet api.dll the API works perfectly :/
Anyone have any ideas? :)
Program.cs
public class Program
{
public static object _lock = new object();
public static bool _init = false;
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args);
Initialise(args, host);
}
public static IWebHost CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
//.UseIISIntegration()
.UseIIS()
.UseNLog()
.UseShutdownTimeout(TimeSpan.FromSeconds(10))
.Build();
public static void Initialise(string[] args, IWebHost host)
{
var logger = NLogBuilder.ConfigureNLog(Path.Combine(Directory.GetCurrentDirectory(), "NLog.config")).GetCurrentClassLogger();
try
{
logger.Debug("App init");
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
if (!_init)
{
lock (_lock)
{
if (!_init)
{
lock (_lock)
{
services.GetRequiredService<DatabaseMigrator>().Migrate();
}
}
}
}
}
catch (Exception ex)
{
logger.Error(ex, "An error occurred while starting up the app.");
throw;
}
}
host.Run();
}
catch (Exception e)
{
logger.Error(e, "Stopped app due to exception");
throw;
}
}
}
DatabaseMigrator.cs
public class DatabaseMigrator
{
private readonly TenantDbContext _tenantDbContext;
private readonly IOptions<DatabaseConfiguration> _databaseConfig;
private readonly ILogger<DatabaseMigrator> _logger;
private readonly AdminTenantDbInitialiser _adminTenantDbInitialiser;
public DatabaseMigrator(TenantDbContext tenantDbContext, IOptions<DatabaseConfiguration> databaseConfig, ILogger<DatabaseMigrator> logger, AdminTenantDbInitialiser adminTenantDbInitialiser)
{
_tenantDbContext = tenantDbContext;
_databaseConfig = databaseConfig;
_logger = logger;
_adminTenantDbInitialiser = adminTenantDbInitialiser;
}
public void Migrate()
{
//migration logic
}
}
I've just gone through a lot of pain fixing a similar problem. Pretty sure the problem is you using Directory.GetCurrentDirectory(), this does odd things when running with in-process hosting as in IIS. I replaced it with Assembly.GetExecutingAssembly().Location and all worked fine.
Clue came from Dotnet Core Multiple Startup Classes with In-Process Hosting
In my case the issue started to show up after I updated some Nuget packages. Installing the latest .NET Core SDK has helped.

Owin hosted web app using Token authentication

I am trying to create an owin web app using token authentication, my startup does not have any special setup like the example in
https://github.com/NancyFx/Nancy/wiki/Token-Authentication
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
TokenAuthentication.Enable(pipelines, new TokenAuthenticationConfiguration(container.Resolve<ITokenizer>()));
}
}
mine is simply
public void Configuration(IAppBuilder app)
{
app.UseNancy();
}
I have the module defined like
public HomeModule(ITokenizer tokenizer)
{
Post["/login"] = _ =>
{
DefaultUserIdentityResolver resolver = new DefaultUserIdentityResolver();
//var userName = (string)this.Request.Form.Username;
//var password = (string)this.Request.Form.Password;
var claims = new List<string> { "admin", "poweruser" };
var userIdentity = resolver.GetUser("ross", claims, Context);
if (userIdentity == null)
{
return HttpStatusCode.Unauthorized;
}
var token = tokenizer.Tokenize(userIdentity, Context);
return new
{
Token = token,
};
};
}
Not much just yet I know but when when I get to tokenize I get an exception of the type Nancy.ErrorHandling.RouteExecutionEarlyExitException which really doesnt have anything in the message or stack trace to indicate the issue.
I am currently hosting over http in casini on .NET 4.5.1
Any pointers would be appreciated
Update:
Message is:
Exception of type 'Nancy.ErrorHandling.RouteExecutionEarlyExitException' was thrown.
Stack trace is:
at Nancy.Authentication.Token.Tokenizer.Tokenize(IUserIdentity userIdentity, NancyContext context)
at Samaritan.Hosting.HttpServices.HomeModule.<>c__DisplayClass11.<.ctor>b__7(Object _) in c:\src\DukeSoftware\Samaritan\Main\Samaritan.Hosting.HttpServices\HomeModule.cs:line 39
at CallSite.Target(Closure , CallSite , Func`2 , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at Nancy.Routing.Route.<>c__DisplayClass4.<Wrap>b__3(Object parameters, CancellationToken context)
I tried setting up the startup.cs like this
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseNancy();
}
}
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
TokenAuthentication.Enable(pipelines, new TokenAuthenticationConfiguration(container.Resolve<ITokenizer>()));
}
}
but I got the following exception
{"Located multiple bootstrappers:\r\n - Samaritan.Hosting.HttpServices.BootStarapper\r\n - Samaritan.Hosting.HttpServices.Bootstrapper\r\n\r\nEither remove unused bootstrapper types or specify which type to use."}
So I removed the bootsrapper and just left Startup. An instantiated tokenizer seems to be passed into the module when you declare the constructor public HomeModule(ITokenizer tokenizer)
So I didnt think the creation of the tokenizer was a problem
did you find fix?
I'm encountering the same exception. It's because I have 2 EXE files in the same directory having child of 'DefaultNancyBootstrapper' class.
I gotta use old Nancy v1.0. so it seems there's no other way but to use 'DefaultNancyBootstrapper' in only one place.

Hosting a WCF Service outside a WebRole and WorkerRole in x86 based C# console application on Windows Azure Cloud

We want to build an azure application which uses a unmanaged win32 DLL, developed in VC++(We can not compile this dll for 64-bit) for some background processing. The very first question is - Is this possible? We have tried many approaches, but none has worked. Below is the approach we are trying currently. Please help us solve the problem or suggest a better technique.
According to our knowledge we cannot use this DLL directly inside a WebRole or WorkerRole.
For this purpose we want to build a WCF service hosted inside a x86 based C# console application which can use this Win32 DLL. We will launch this application on cloud and host our WCF service.
With this approach we developed a Cloud project in visual studio 2010 and Windows Azure SDK 1.2, which is working perfectly on local emulator. But it is not running on cloud.
To date we are able to launch this application and WCF service on cloud, but the problem
is while consuming the service it is giving following errors.
The remote server returned an error: (404) Not Found.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Net.WebException: The remote server returned an error: (404) Not Found.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[WebException: The remote server returned an error: (404) Not Found.]
System.Net.HttpWebRequest.GetResponse() +7769892
System.ServiceModel.Channels.HttpChannelRequest.WaitForReply(TimeSpan timeout) +156
[EndpointNotFoundException: There was no endpoint listening at http://10.62.43.187:20000/CalculatorService/Http that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +4767763
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +1725
emuser_WCFContract.ICalcService.Add(Int32 num1, Int32 num2) +0
emuser_WebRole._Default.btnAdd_Click(Object sender, EventArgs e) in C:\projects\emuserWCF_HTTP\emuser_WebRole\Default.aspx.cs:39
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +154
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3691
We are using BasicHTTPBinding. Following are the details of our service contract, service class, and host application.
Service Contract:
[ServiceContract]
public interface ICalcService
{
[OperationContract]
int Add(int num1, int num2);
[OperationContract]
int Sub(int num1, int num2);
}
Service Implementation Class:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple,
IncludeExceptionDetailInFaults = true,
AddressFilterMode = AddressFilterMode.Any)]
public class CalcService : ICalcService
{
public int Add(int num1, int num2)
{
return num1 + num2;
}
public int Sub(int num1, int num2)
{
return num1 - num2;
}
}
Code snippet from WebRole.
We are using “HttpIn” endpoint of WebRole and its port to bind a service. In following code snippet, we are launching that Console application from onStart() method of WebRole(WebRole.cs)
ProcessStartInfo psi = new ProcessStartInfo(path);
RoleInstanceEndpoint externalEndPoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["HttpIn"];
psi.Arguments = externalEndPoint.IPEndpoint.ToString();
Global.ExternalIp = externalEndPoint.IPEndpoint.ToString();
Process dllHost = Process.Start(psi);
We know that this console application starts well on cloud, and starts hosting the WCF service.
Following is the Code snippet of console application which is hosting the WCF service.
string ep = args[0];
string baseAddress = "http://" + ep + "/CalculatorService";
ServiceHost serviceHost = new ServiceHost(typeof(CalcService), new Uri(baseAddress));
Console.WriteLine("WCFHost_x86 Is Started - v1.3");
Console.WriteLine("Endpoint Received : " + ep);
try
{
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
serviceHost.Description.Behaviors.Add(smb);
BasicHttpBinding httpBinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
serviceHost.AddServiceEndpoint(typeof(ICalcService), httpBinding, "http://" + ep + "/CalculatorService/Http");
Binding mexBinding = MetadataExchangeBindings.CreateMexHttpBinding();
Uri mexAddress = new Uri("http://" + ep + "/CalculatorService/Mex");
serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexAddress);
mexAddress = new Uri("http://" + ep + "/CalculatorService/Http/Mex");
serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexAddress);
serviceHost.Open();
Console.WriteLine("Service Started At Endpoint : " + baseAddress);
}
catch (Exception ex)
{
Console.WriteLine("Error In Starting WCF Host : " + ex.Message);
}
Console.WriteLine("Press <Enter> To Exit");
Console.ReadLine();
Following is code snippet of WCF Client that we creating on Deafault.aspx.cs page.
private static bool initilized = false;
private static ICalcService CalculatorClient;
protected void Page_Load(object sender, EventArgs e)
{
lblService.Text = "http://" + Global.ExternalIp + "/CalculatorService/Http";
lblExtIp.Text = Global.ExternalIp;
if (!initilized)
{
BasicHttpBinding httpBinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
EndpointAddress endPoint = new EndpointAddress("http://" + Global.ExternalIp + "/CalculatorService/Http");
ChannelFactory<ICalcService> factory = new ChannelFactory<ICalcService>(httpBinding, endPoint);
CalculatorClient = factory.CreateChannel();
initilized = true;
}
}
protected void btnAdd_Click(object sender, EventArgs e)
{
int num1 = Int32.Parse(txtNum1.Text);
int num2 = Int32.Parse(txtNum2.Text);
int result = CalculatorClient.Add(num1, num2);
txtResult.Text = result.ToString();
}
Please help us solve the problem or suggest a better technique. Thanks In Advance
A few shots in the dark - could it be that you require running under elevated privileges?

Resources