Вопрос

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#

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top