Open-source FTP-to-Azure blob storage: multiple users, one blob storage account

A little while ago, I came across an excellent article by Maarten Balliauw in which he described a project he was working on to support FTP directly to Azure’s blob storage. I discovered it while doing some research on a similar concept I was working on. At the time of writing this post though, Maarten wasn’t  sharing his source code and even if he did decide to at some point soon, his project appears to focus on permitting access to the entire blob storage account. This wasn’t really what I was looking for but it was very similar…

My goal: FTP to Azure blobs, many users: one blob storage account with ‘home directories’

I wanted a solution to enable multiple users to access the same storage account, but to have their own unique portion of it – thereby mimicking an actual FTP server. A bit like giving authenticated user’s their own ‘home folder’ on your Azure Blob storage account.

This would ultimately give your Azure application the ability to accept incoming FTP connections and store files directly into blob storage via any popular FTP client – mimicking a file and folder structure and permitting access only to regions of the blob storage account you determine. There are many potential uses for this kind of implementation, especially when you consider that blob storage can feed into the Microsoft CDN…

Features

  • Deploy within a worker-role
  • Support for most common FTP commands
  • Custom authentication API: because you determine the authentication and authorisation APIs, you control who has access to what, quickly and easily
  • Written in C#

How it works

In my implementation, I wanted the ability to literally ‘fake’ a proper FTP server to any popular FTP client: the server component to be running on Windows Azure. I wanted to have some external web service do my authentication (you could host yours on Windows Azure, too) and then only allow each user access to their own tiny portion of my Azure Blob Storage account.

It turns out, Azure’s containers did exactly what I wanted, more or less. All I had to do was to come up with a way of authenticating clients via FTP and returning which container they have access to (the easy bit), and write an FTP to Azure ‘bridge’ (adapting and extending a project by Mohammed Habeeb to run in Azure as a worker role).

Here’s how my first implementation works:

A quick note on authentication

When an FTP client authenticates, I grab the username and password sent by the client, pass that into my web service for authentication, and if successful, I return a container name specific to that customer. In this way, the remote user can only work with blobs within that container. In essence, it is their own ‘home directory’ on my master Azure Blob Storage account.

The FTP server code will deny authentication for any user who does not have a container name associated with them, so just return null to the login procedure if you’re not going to give them access (I’m assuming you don’t want to return a different error code for ‘bad password’ vs. ‘bad username’ – which is a good thing).

Your authentication API could easily be adapted to permit access to the same container by multiple users, too.

Simulating a regular file system from blob storage

Azure Blob Storage doesn’t work like a traditional disk-based system in that it doesn’t actually have a hierarchical directory structure – but the FTP service simulates one so that FTP clients can work in the traditional way. Mohammed’s initial C# FTP server code was superb: he wrote it so that the file system could be replaced back in 2007 – to my knowledge, before Azure existed, but it’s like he meant for it to be used this way (that is to say, it was so painless to adapt it one could be forgiven for thinking this. Mohammed, thanks!).

Now I have my FTP server, modified and adapted to work for Azure, there are many ways in which this project can be expanded…

Over to you (and the rest of the open source community)

It’s my first open source project and I actively encourage you to help me improve it. When I started out, most of this was ‘proof of concept’ for a similar idea I was working on. As I look back over the past few weekends of work, there are many things I’d change but I figured there’s enough here to make a start.

If you decide to use it “as is” (something I don’t advise at this stage), do remember that it’s not going to be perfect and you’ll need to do a little leg work – it’s a work in progress and it wasn’t written (at least initially) to be an open-source project. Drop me a note to let me know how you’re using it though, it’s always fun to see where these things end up once you’ve released them into the wild.

Where to get it

Head on over to the FTP to Azure Blob Storage Bridge project on CodePlex.

It’s free for you to use however you want. It carries all the usual caveats and warnings as other ‘free open-source’ software: use it at your own risk.

If you do use it and it works well for you, drop me an email and it’ll make me happy. :)

Advertisement
15 comments
  1. Wesley Wilson said:

    Richard, Justin’s issue with PASV mode seems to be a blocking issue. You can’t do PASV mode with a server behind the Azure Load Balancer, because in PASV mode, the client picks the data port and sends using that new port. Azure only lets you open up 5 ports. The article you referenced at http://blog.maartenballiauw.be/post/2010/03/15/Using-FTP-to-access-Windows-Azure-Blob-Storage.aspx deals with this issue.

    Have you found a work-around to enable PASV mode in an Azure role?

    I have enabled IIS FTP on an Azure role and have run into the same issue. Any thoughts?

    Thanks,
    Wesley

  2. Richard said:

    Hi Wesley

    Thanks for taking the time to read the article and leave a comment. Much appreciated!

    You’re quite right – the code has been built to work in active mode, not passive. For that, you’ll only need to open port 21 on the server for incoming connections. I haven’t looked at getting active to work for the same reasons you list. Additionally, I’ve yet to test how the active connection fairs when pitted against multiple connected clients; for that I need the community’s help in actively identifying these types of issues, and perhaps helping me test and fix them to.

    When I get a few spare moments, I’m going to get right on the case. In the mean time, if you’d like to perhaps help out, feel free to head on over to Codeplex and submit a request to join…

    Thanks!

    Richard.

  3. thanks for the followup Richard,
    guess what I’m looking for is where to plug in my Blob storage creds and define the FTP user/pass … not really a C#/Azure person (yet)… learning as I go and kinda hit a brick wall trying to understand what I needed to do to make this work ;)

  4. Richard Parker said:

    Hi,

    There is a comment in-code for the section where you make a call off to your own authentication API for authenticating users. It simply expects any string value back (the container name) for an authorised user, or a NULL/Empty string for any unauthenticated user. You don’t define users in the code, per sé.

    Your blob storage credentials can simply override the default store I’ve added.

    Hopefully, in the next few weeks, I’ll have a new version available that’s a bit easier to integrate – if you’d like to wait for that?

    Thanks,

    Richard.

  5. Hi Richard,
    just wondering if you has a more complete / updated version of this…
    I’ve looked at the project but … can’t seem to work out what I actually need to do it get it up and running.
    If there’s a sample which I can at least start with an F5 in VS and connect to in FileZilla then I can tweak it from there, but … it seems to be missing something at the moment :)
    thanks
    OBM

  6. Richard said:

    Hi OBM. First, thanks for reading the article and downloading the code. As it stands, it’s not ‘production ready’, but it should be relatively straightforward to get it up and running – whether that’s on the live environment or in local development. If you can be more specific with what problem you’re having I can try to provide you with some tips to get it up and running. I don’t have a more up to date version of the code yet – this is a project I’m working on in my spare time: updates will be released on an ad-hoc basis.

    Thanks,

    Richard.

  7. Justin said:

    I’m using FileZilla to connect to the FTP Server, but I get the following:

    Status: Connecting to 127.0.0.1:21…
    Status: Connection established, waiting for welcome message…
    Response: 220 FTP to Windows Azure Blob Storage Bridge Ready
    Command: USER fvglogin2
    Response: 331 User fvglogin2 logged in, needs password
    Command: PASS ****
    Response: 220 Password ok, FTP server ready
    Status: Connected
    Status: Retrieving directory listing…
    Command: PWD
    Response: 257 “/” PWD Successful.
    Command: TYPE I
    Response: 200 Binary transfer mode active.
    Command: PASV
    Error: Disconnected from server: ECONNABORTED – Connection aborted
    Error: Failed to retrieve directory listing

  8. Richard said:

    Hello

    There are a few causes of this error. Could you describe a little more about your setup? Are you seeing this with development storage or live, for example? If you want to zip up your code and send it to me perhaps I can try to replicate it and figure out what the issue is. Thanks, Richard. (me (at) richard (dot) parker (dot) name.

  9. Justin said:

    I’ve downloaded change set 51845, but I’m not sure where to add users, passwords, and associated containers… Do you have any documentation on how to configure your app?

    Thanks.

  10. Richard said:

    Safae, you need to remove the [at] and replace it with an ‘@’ symbol.

  11. safae said:

    can you please confirm your e-mail address?

  12. safae said:

    Hi, I’ve downloaded your code but I dont know how to configure it to accept requests from FTP clients (filezilla for example); mainly for authentication. Also there is no endpoint defined in configuration file of the worker role, so how can this server be exposed in Azure.
    thanks for answering.

  13. Richard said:

    Hi safae,
    Drop me a mail to me [at] richard.parker.name… Let me know which changeset version of the code you’ve downloaded from CodePlex, and, if you can, a copy of your sample project.
    Thanks,
    Richard.

Leave a Reply

Fill in your details below or click an icon to log in:

Gravatar
WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 261 other followers