It is some time ago that is possible  to use Virtual Machine(VM) in Windows Azure. A good example when you could use VM is build your own FTP Server hosted in Azure. The problem is that most products are using hard disk to store the data. The question is how you could access the data from your Web or Worker Role instances. One way is access the data via FTP protocol, the other, for example, using classic Windows files sharing.

FTP server installation

For this example, you can install your own FTP server in Azure (good guide is here), but it will be enough to start the virtual machine in the Azure and share one folder. The only thing you must set up are VM Endpoints. For the FTP Server you need, at least, all of displayed below. For the file sharing are only necessary the NetBIOSSession and SMB.

image

Startup task to create privileged user

Windows Azure Worker role is running in the cloud environment under the privileged user which don’t have a rights to access shared directories. What is necessary to do is creating the Startup task where we are creating a new user, which will be used to access shared directories. The user (and his password) below must match those which has Read privileges on shared folder.

@echo off

net user testftpuser /delete
net user testftpuser #StrongPassword /add
net localgroup Administrators testftpuser /add

echo Command ends with error code %errorlevel%
exit /b %errorlevel%

Copy the code below in the file StartUpTask.cmd which should be included in the project project where Worker Role to monitoring the shares will be implemented.

image

Additionally you must set Build Action as Content and Copy to Output Directory as Copy always  on this file.

image

To ensure the task will be executed when to role is starting, add the task name as the Startup Task in the ServiceDefinition.csdef

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="WindowsAzureFileSharesClient" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2013-03.2.0">
  <WorkerRole name="WorkerRole" vmsize="ExtraSmall">
    <Startup>
      <Task commandLine="StartUpTask.cmd" executionContext="elevated" taskType="simple" />
    </Startup>
      ...
  </WorkerRole>
</ServiceDefinition>

Accessing shared directories with the impersonation

If you want to access the shared directories, you need to execute the code under the impersonated user. I implemented this as extension method ExecuteAs<T>.

        public static void ExecuteAs(this Action actionToExecute, string username, string password, string domain)
        {
            SafeTokenHandle safeTokenHandle;
            var returnValue = LogonUser(username, domain, password, 2, 0, out safeTokenHandle);

            if (returnValue)
            {
                using (safeTokenHandle)
                {
                    using (var impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle()))
                    {
                        actionToExecute();
                    }
                }
            }
            else
            {
                throw new Exception(string.Format("User {0} login failed", username));
            }
        }

With the help of method below, we are initializing the instance of the FileSystemWatcher class.

        public override bool OnStart()
        {
            new Action(InitializeFileWatcher).ExecuteAs(_username, _password, _domainName);
            return base.OnStart();
        }

        private void InitializeFileWatcher()
        {
            _fileSystemWatcher.Path = _pathToMonitor;
            _fileSystemWatcher.Created += FileSystemWatcher_OnFileCreated;
            _fileSystemWatcher.Renamed += FileSystemWatcher_OnFileRenamed;
            _fileSystemWatcher.EnableRaisingEvents = true;
        }

As usually you can find the complete solution here.