Introduction
As the different cloud-computing infrastructures are getting
stabilized, more and more applications are being deployed to these
infrastructures. Among these applications, quite a considerable number of applications
are being migrated from traditional deployment to cloud. But sometime due to certain
constraints it may not be always possible to move an entire application to
cloud but move only parts, for instance, move the presentation and business
layer to cloud but the backend database remains on-premise.
In some of my blogs (ref- one and two), I have had presented
different ways of how easily one may expose the on-premise database (i.e. the
one within the corporate network behind the firewall) to the consumer
application in the internet using the Azure building blocks. In this article, I
will try to explain an approach of how easily one may even expose their
existing on-premise FTP server across the corporate firewall to support some
application which is probably moved to cloud or other external deployment
(internet).
To achieve this, we will make use of the Azure appfabric
Service bus to expose the file from the FTP server as WCF service end points.
The WCF service can be deployed either on IIS or on any other hosting application
like console application. But while using IIS we need to make sure to enable
the auto-start for the WCF service otherwise the service would not be available
by default for consumption by any client. For the steps to be followed to
enable the auto-start, refer to this MSDN page, these steps will
make sure to start the service deployed in IIS the moment the IIS is started,
instead of waiting for the first service request to come in.
On a high level, the FTP server is basically a file
repository and provides access to the files on need basis. So, we may develop a
REST based WCF service layer which will expose some interface across appfabric
service bus and internally it will access the on-premise FTP server to access
the intended files.
Lets us now see how to achieve the above said implementation
and expose the files from on-premise FTP server across the corporate firewall
using the Windows Azure appfabric service bus.
Assumptions
The reader is aware of the following:
- REST
based WCF service implementation
- Windows
Azure AppFabric service bus and the related relay bindings
- The
mechanism to access the files in the FTP server
Steps to be followed
1. Service
Implementation
If IIS is to be used for hosting the service, then create a project
of type WCF Service Library. And if any other applications like console
application is to be used for hosting then create a project of type Console
Application.
a. Add the service
contract to expose the REST interface
[ServiceContract]
public interface IExposeFTPContract
{
[OperationContract]
[WebGet(UriTemplate = "/{fileName}")]
Message GetFile(string fileName);
}
Where "Message" represents a unit
of communication and has its definition in the namespace: System.ServiceModel.Channels.
b. Add the service
interface definition
public class ExposeFTPContract: IExposeFTPContract
{
public Message GetFile(string fileName)
{
//read
the file and return as Message object
//following
Console.WriteLines provided for tracing the calls
Console.WriteLine("Accessed at- " +
DateTime.Now.ToString());
Console.WriteLine("--------------------------------------------");
using
(FileStream fileStream = File.Open(
<complete file path to
a FTP server using the file name provided>,
FileMode.Open))
{
using
(create some suitable reader using the
fileStream, e.g. fileReader)
{
Message message =
Message.CreateMessage(MessageVersion.None,"",
fileReader);
using
(MessageBuffer messageBuffer = message.CreateBufferedCopy(1000))
{
return messageBuffer.CreateMessage();
}
}
}
}
Here the goal is to provide an interface for accessing file
from the FTP server. This is one of the ways to make the file accessible
through service interface; I believe there are other better ways as well.
2. Service
configuration
In the host configuration
file, i.e., web.config if IIS is used and app.config if a console application is
used, add the following configuration settings:
a. Add a service end
point
<services>
<service name="namespace.ExposeFTPContract"
behaviorConfiguration="ExposeFTPServiceBehavior">
<endpoint behaviorConfiguration="webhttpSharedSecretClientCredentials"
contract=”namespace.IExposeFTPContract"
binding="webHttpRelayBinding" bindingConfiguration="webHttpRelayEndpointConfig"
/>
</service>
</services>
The appfabric namespace also needs
to be provided so, in case the service is hosted in IIS, then add the attribute
address="http://<appfabric
namespace>.servicebus.windows.net/
to the "endpoint" above as:
<endpoint behaviorConfiguration="webhttpSharedSecretClientCredentials"
contract=”namespace.IExposeFTPContract"
binding="webHttpRelayBinding" bindingConfiguration="webHttpRelayEndpointConfig"
address="http://<appfabric
namespace>.servicebus.windows.net"/>
And if hosted using console application, then appfabric
namespace could be provided during the host initiation (described later in
section "3. Service Hosting").
b. Add service
behavior
<serviceBehaviors>
<behavior name="ExposeFTPServiceBehavior">
<!--
To avoid disclosing metadata information, set the value
below to false and remove the metadata
endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"
/>
<!--
To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception
information -->
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
c. Add end point
behavior
This end point behavior serves the following purposes:
- Exposes
service interface as REST and
- Provides
credential to connect to the appfabric service bus and expose the service
across the corporate firewall.
<endpointBehaviors>
<behavior name="webhttpSharedSecretClientCredentials">
<!—to
provide credential to connect to the appfabric service bus-->
<transportClientEndpointBehavior credentialType="SharedSecret">
<clientCredentials>
<sharedSecret issuerName="appfabric issuer name e.g. owner" issuerSecret="appfabric secret
key" />
</clientCredentials>
</transportClientEndpointBehavior>
<!—to
expose service interface as REST-->
<webHttp/>
</behavior>
</endpointBehaviors>
Where, the issuer name and issuer secret are the ones
available once the appfabric namespace is created using the Azure subscription.
d. Add WCF binding
The WCF binding- "webHttpRelayBinding" needs to be
configured as this will establish a duplex communication channel with the
appfabric service across the corporate firewall.
<bindings>
<webHttpRelayBinding>
<binding name="webHttpRelayEndpointConfig">
<security mode="None" relayClientAuthenticationType="None"/>
</binding>
</webHttpRelayBinding>
</bindings>
3. Service Hosting
In case the service is to be hosted in Console application
then update "main" method in program.cs in the project with the following code:
try
{
Console.Title = "Expose Client FTP through appfabric Service
Bus";
string
serviceNamespaceDomain = appfabric namespace
or could be read from the config settings;
Console.WriteLine("Service Namespace Domain : " +
serviceNamespaceDomain);
Console.WriteLine("");
//
create the service URI based on the appfabric namespace
Uri address =
ServiceBusEnvironment.CreateServiceUri("http",
serviceNamespaceDomain, "");
//
create the service host reading the configuration
ServiceHost host = new ServiceHost(typeof(ExposeFTPContract),
address);
Console.WriteLine("Starting service...");
//
create the ServiceRegistrySettings behavior for the endpoint.
//
This will make this service visible along with other services registerred
//
to the same appfabric namespace in the atom feed if one tries to access
//
the url- http://<appfabric namespace>.servicebus.windows.net
IEndpointBehavior
serviceRegistrySettings = new
ServiceRegistrySettings(DiscoveryType.Public);
foreach
(ServiceEndpoint subscriberEndpoint in
host.Description.Endpoints)
{
subscriberEndpoint.Behaviors.Add(serviceRegistrySettings);
}
//
open the service
host.Open();
Console.WriteLine("Service started...");
Console.WriteLine("Service address: " + address);
Console.WriteLine("");
Console.WriteLine("FTP files may now be accessed as:");
Console.WriteLine(address + "<file name>");
Console.WriteLine("");
Console.WriteLine("Press [Enter] to exit");
Console.WriteLine("");
Console.WriteLine("--------------------------------------------");
Console.ReadLine();
//
close the service
host.Close();
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
If IIS is used to host, make sure the hosted service and the
corresponding application pool is running.
Conclusion
Once the service is running, files from the on-premise FTP
server can be accessed over the Windows Azure AppFabric URL such as: http://<appfabric_namespace>.servicebus.windows.net/<file_name>.
The code could be enhanced based on one’s need but this
explains how easily one can expose on-premise FTP server for internet based consumer
application using the Azure appfabric service.