WCF service with Ssl Certificate in Azure emulator - wcf

I have setup my my cloud using the following
http://azure.microsoft.com/en-us/documentation/articles/cloud-services-configure-ssl-certificate/
and the web role using the following http://msdn.microsoft.com/en-us/library/ms731074%28v=vs.110%29.aspx
My problem that when I use emulator I get an error That the there is a name mismatch between a certificate and the website in this case(127.0.0.1)
What can be done to solve it.

So there are two approaches you could take:
Create a separate cloud project for each environment - This way you could create a self-signed certificate for your development environment and live with the warning that the certificate is not trusted.
Get a wildcard certificate for your application - This is the approach we have taken for our application (along with the 1st one). Basically we took a wildcard SSL certificate and used that certificate in our application. Then we added an entry in hosts file located in C:\Windows\System32\drivers\etc like this:
127.0.0.1 dev.cloudportam.com
Next, we added hosts header in our dev cloud project's csdef file.
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="dev.cloudportam.com" />
<Binding name="Endpoint2" endpointName="SSL" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="8080" />
<InputEndpoint name="SSL" protocol="https" port="8082" certificate="SSL" />
</Endpoints>
Now when we launch the application, it opens up https://localhost:8082/ and we just change the address to https://dev.cloudportam.com:8082 and everything works well.

Related

How do I enable IIS Express to serve external requests

This is a re-post of an earlier issue. After a long hiatus with respect to this topic I am back to it again.
I need to make my local dev IIS Express instance available to colleagues for testing purposes. After much reading and many blind alleys, I managed to get a little bit further than I did when this was originally posted, in that I have managed to get VS 2022 to recognise the entries from the applicationHost.config that are needed, unfortunately when I debug the website, IIS Express (or rather MS Edge) responds with:
Hmmm... Cant reach this page
machinename.euro.org.local refused to connect
Note the URL is obfuscated for security reasons.
The applicationHost.config file contains the following entries:
...
<site name="appName" id="1">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\appPath\appName" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:8080:machinename.euro.org.local" />
<binding protocol="https" bindingInformation="*:44379:machinename.euro.org.local" />
</bindings>
</site>
VS confirms that the virtual directory has been successfully created.
I have made the necessary additions to HTTP.SYS:
netsh http add urlacl url=http://machinename.euro.org.local:8080/ user=everyone
and to my firewall settings:
netsh firewall add portopening TCP 8080 IISExpressWeb enable ALL
Where am I going wrong?

Multiple SSL certificates in one azure deployment

I have a problem similar to (but not the same) as this:
Azure web role - Multiple ssl certs pointing to a single endpoint
My azure package contains multiple sites. Some of these sites are on domain abc and others are on domain def. I need to secure both domains with SSL but can't figure out how (if it's possible) to do this.
Here's an example of my config:
<Sites>
<Site name="sub1.abc" physicalDirectory="***">
<Bindings>
<Binding name="HttpIn" endpointName="HttpIn" hostHeader="sub1-staging.abc.com" />
<Binding name="HttpsInABC" endpointName="HttpsInABC" hostHeader="sub1.abc.com" />
</Bindings>
</Site>
<Site name="sub1.def" physicalDirectory="***">
<Bindings>
<Binding name="HttpIn" endpointName="HttpIn" hostHeader="sub1-staging.def.com" />
<Binding name="HttpsInDEF" endpointName="HttpsInDEF" hostHeader="sub1.def.com" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="HttpIn" protocol="http" port="80" />
<InputEndpoint name="HttpsInABC" protocol="https" port="443" certificate="abc" />
<InputEndpoint name="HttpsInDEF" protocol="https" port="443" certificate="def" />
</Endpoints>
<Certificates>
<Certificate name="abc" storeLocation="LocalMachine" storeName="My" />
<Certificate name="def" storeLocation="LocalMachine" storeName="My" />
</Certificates>
This configuration gives me the following error:
The same local port '443' is assigned to endpoints HttpsInABC and
HttpsInDEF in role ***.
Any suggestions on how I can work around this without having to host them separately?
Based on #JoelDSouza's answer:
Will using different ports work for you
What are the implications of SSL on ports 444/445/446 etc. in Windows Azure?
You can use multiple SSL certificates and add them all to the same endpoint by automating the process of installing the certificates on the machine and add HTTPS bindings to IIS.
IIS 8 (Windows Server 2012) supports SNI, which enables you to add a "hostheader" to the HTTPS binding.
I'm a Microsoft Technical Evangelist and I have posted a detailed explanation and a sample "plug & play" source-code at:
http://www.vic.ms/microsoft/windows-azure/multiples-ssl-certificates-on-windows-azure-cloud-services/
I fear you are out of luck - as noted in the article you linked to, one SSL certificate per server IP. I guess by hosting them separately (that feels odd to say considering it's cloud based) you will get two IPs and therefore can add an SSL certificate to each IP address.
You could perhaps move everything to one domain and use folders within that domain to host the separate sites - that's the only way you will be able to secure everything with your SSL certificate without having two hosting packages:
ie instead of:
www.domain1.com and www.domain2.com use www.mydomain.com/domain1/ and www.mydomain.com/domain2/
Will using different ports work for you? You can use SSL cert 1 with myapp.cloudapp.net:443 and SSL cert 2 with myapp.cloudapp.net:8443
If you don't need wildcard certificates you can use a multi-domain certificate. This way you only need one certificate. The downside is that each sub-domain needs to be specified, which can get expensive if you have a lot.

Cannot get SSL to work on Azure instance

I've been tearing my hear out trying to figure out why SSL works in one of my Azure projects but not in another.
When I navigate to my site, say https://foo.com, I can't even connect to the site. Browsers can't connect at all and curl says "couldn't connect to host". However, if I go to my cloudapp.net URL (e.g. https://foo.cloudapp.net), it can connect but browsers will complain and say my cert is for *.foo.com. Note: I am able to connect to http://foo.com without any trouble.
Here's my code with certain values obfuscated.
ServiceDefinition.csdef:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="MyApp" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="www" vmsize="Small">
<Sites>
<Site name="Web">
<VirtualApplication name="r" physicalDirectory="../Foo/Bar" />
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
<Binding name="Endpoint2" endpointName="Endpoint2" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
<InputEndpoint name="Endpoint2" protocol="https" port="443" certificate="STAR.foo.com" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
<Certificates>
<Certificate name="STAR.foo.com" storeLocation="LocalMachine" storeName="My" />
</Certificates>
</WebRole>
</ServiceDefinition>
my cert is uploaded, the thumbprint matches (in this example it's also "1234567890")
ServiceConfiguration.csfg:
<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="myApp" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="1" osVersion="*">
<Role name="www">
<Instances count="2" />
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
</ConfigurationSettings>
<Certificates>
<Certificate name="STAR.foo.com" thumbprint="1234567890" thumbprintAlgorithm="sha1" />
</Certificates>
</Role>
</ServiceConfiguration>
Azure Console:
I have verified that:
My cert is uploaded
It's SHA1
It's thumbprint matches what I've specified in ServiceConfiguration.cscfg (in this example it's "1234567890")
The certs for the Certificate Authorities are also present (for me it's "PositiveSSL CA" and "AddTrust External CA root")
For the Azure instance, it confirms there are 2 endpoints (port 80 and port 443)
Why would I not be able to connect at all via https://foo.com, but my https://foo.cloudapp.net will load (although triggering a browser warning)? This seem to indicate my configuration is correct but something else is off... ideas?
I think you may be looking in the wrong place for your problem!
How have you mapped foo.com to your site's address?
Note that Azure instances are given dynamic IP addresses - what address your site may be on NOW may not be what its on tomorrow. The recommendation for Azure is to add a "www" CNAME DNS entry in your domain records that points at "foo.cloudapp.net".
This way, when someone browses to www.foo.com, the DNS server will (invisibly) say "hey, actually, that site is as foo.cloudapp.net. The browser will then ask for the IP address of foo.cloudapp.net. This domain is managed by Microsoft who will return the current IP address for your site.
If you want foo.com to still get you to www.foo.com, you'll have to setup DNS redirection so that whenever someone types foo.com into their browser, they're redirected to www.foo.com. This will then cuase the browser to resolve foo.cloudapp.net and then the HTTP request will be sent to your site. Some domain hosters charge for this (typically a nominal fee), some offer it as a free service.
HTH.

Using WCF on Localhost on Azure

In summary
How do I acces a WCF service on localhost when hosted in IIS on Azure? Azure does not bind localhost or 127.0.0.1 to my website.
Details
I have an ASP.Net application hosted on Azure. I have added a .svc and some workflows that I want to use via WCF. To keep matters simple, my web app simply calls the service on localhost, so I have endpoints like these in web.config;
<client>
<endpoint address="http://localhost:8080/Router.svc/Case" binding="basicHttpBinding" contract="NewOrbit.ExVerifier.Model.Workflow.Case.ICaseWorkflow" name="Case" />
<endpoint address="http://localhost:8080/Workflow/Case/Case_default1.xamlx" binding="basicHttpBinding" contract="*" name="Case_default1" />
</client>
This works just fine on my local machine. The problem is that when I publish this to Azure, the Website in IIS does not get a binding to localhost, instead the bindings are always to the actual IP address of the server.
It ends up looking like this in applicationHost.config:
<bindings>
<binding protocol="http" bindingInformation="10.61.90.44:80:" />
<binding protocol="https" bindingInformation="10.61.90.44:443:" />
<binding protocol="http" bindingInformation="10.61.90.44:8081:" />
</bindings>
So, as soon as my web app tries to call the service on localhost (or 127.0.0.1 for that matter) it fails instantly.
Needless to say, if I rdp on to the server and change the binding then all is fine.
What I find really odd is that there are tons of examples out there where people are accessing WCF services on localhost on Azure so I can't figure out why this is so. I have set the osFamily to 2 and in order to debug this I have enabled web publishing and remote desktop access which I guess, in theory, could mess things up.
What I have already looked at
I can rewrite the end-point address in my code at runtime to substitute localhost for the actual address or create the endpoint dynamically as described by Ron in the answers. Unfortunately I am using the WCF Routing service so I can version workflows. This means that my code calls the Router endpoint and the WCF Router in turns calls the actual service/workflow using an endpoint specified in web.config. I don't have control over the Routing services endpoint resolution without, I think, writing a whole set of routing logic which just seems to be a lot of work when all I want is to call localhost :)
Switching to using named pipes; Alas, it causes some strange issues with workflows, probably due to duplexing, and I am on a deadline so haven't got time to get to the bottom of that at the minute.
You have to build the endpoint address dynamically.
Step 1:
In your ServiceDefinition.csdef you need to declare an Endpoint.
<ServiceDefinition name="MyFirstAzureWorkflow" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WorkflowWeb" vmsize="ExtraSmall">
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="WorkflowService" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="WorkflowService" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
</WebRole>
</ServiceDefinition>
Step 2:
When you want to call the service
var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["WorkflowService"].IPEndpoint;
var uri = new Uri(string.Format(
"http://{0}:{1}/MyService.xamlx",
endpoint.Address,
endpoint.Port));
var proxy = new ServiceClient(
new BasicHttpBinding(),
new EndpointAddress(uri));
Okay, so this is how I solved it. IMHO it's a hack but at least it works.
Basically, I need to add a "*" binding, so I can do this in Powershell. The general recipe is here: http://blogs.msdn.com/b/tomholl/archive/2011/06/28/hosting-services-with-was-and-iis-on-windows-azure.aspx
That deals with adding Named Pipes support, but the principle is the same. I just changed the Powershell script to:
import-module WebAdministration
# Set up a binding to 8080 for the services
Get-WebSite "*Web*" | Foreach-Object {
$site = $_;
$siteref = "IIS:/Sites/" + $site.Name;
New-ItemProperty $siteref -name bindings -value #{protocol="http";bindingInformation="*:8080:"}
}
This now allows me to use http://127.0.0.1:8080/service.svc to access my service.
Note: You do need to follow the rest of the recipe to set elevated execution context and change the powershell execution mode, so do follow it carefully

WCF set Endpoint and Binding dynamically in code

Yes, I've read the other questions on SO, MSDN, and other sites, but I found no answers as clear as I can understand. I need to set my Silverlight application's WCF references relative to the site that it's loaded from, but I can't get it to work. There is no problem with the service itself, it is working. When I move from local to my real server, I get errors in my SL app complaining about not connecting to localhost.
Here is my ServiceReferences.ClientConfig file:
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_AccountManager">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
<binding name="CustomBinding_FileManager">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
<binding name="CustomBinding_SiteManager">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:60322/AccountManager.svc"
binding="customBinding" bindingConfiguration="CustomBinding_AccountManager"
contract="AccountManager.AccountManager" name="CustomBinding_AccountManager" />
<endpoint address="http://localhost:60322/FileManager.svc" binding="customBinding"
bindingConfiguration="CustomBinding_FileManager" contract="FileManager.FileManager"
name="CustomBinding_FileManager" />
<endpoint address="http://localhost:60322/SiteManager.svc" binding="customBinding"
bindingConfiguration="CustomBinding_SiteManager" contract="SiteManager.SiteManager"
name="CustomBinding_SiteManager" />
</client>
</system.serviceModel>
</configuration>
Yes, I will optimize the buffer/message sizes and I know the possible DoS exploits, forget about it for now, I need them for big file transfers. An approach I tried is while instantiating the clients, I've used this code:
fileManager = new FileManagerClient(new BasicHttpBinding(), new EndpointAddress("http://" + Settings.Host + "/FileManager.svc"));
accManager = new AccountManagerClient(new BasicHttpBinding(), new EndpointAddress("http://" + Settings.Host + "/AccountManager.svc"));
where Settings.Host is my own method which returns me the host that the SL app is running from, tested, works. When I uploaded my XAP and tried, it still wanted to go for http://localhost:60322/AccountManager.svc, after further investigation, I've realized that there are still lots of references to localhost, in unseen files:
AccountManager.disco:
<?xml version="1.0" encoding="utf-8"?>
<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/">
<contractRef ref="http://localhost:60322/AccountManager.svc?wsdl" docRef="http://localhost:60322/AccountManager.svc" xmlns="http://schemas.xmlsoap.org/disco/scl/" />
</discovery>
Parts of AccountManager.wsdl:
... <wsdl:import namespace="" location="http://localhost:60322/AccountManager.svc?wsdl=wsdl0" />...
...[lots of operation declarations]...
<wsdl:service name="AccountManager">
<wsdl:port name="CustomBinding_AccountManager" binding="tns:CustomBinding_AccountManager">
<soap12:address location="http://localhost:60322/AccountManager.svc" />
<wsa10:EndpointReference>
<wsa10:Address>http://localhost:60322/AccountManager.svc</wsa10:Address>
</wsa10:EndpointReference>
</wsdl:port>
</wsdl:service>
Part of AccountManager1.xsd:
<xs:import schemaLocation="http://localhost:60322/AccountManager.svc?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/Leftouch.Data.Summary" />
Part of configuration.svcinfo:
<endpoint normalizedDigest="<?xml version="1.0" encoding="utf-16"?><Data address="http://localhost:60322/AccountManager.svc" binding="customBinding" bindingConfiguration="CustomBinding_AccountManager" contract="AccountManager.AccountManager" name="CustomBinding_AccountManager" />" digest="<?xml version="1.0" encoding="utf-16"?><Data address="http://localhost:60322/AccountManager.svc" binding="customBinding" bindingConfiguration="CustomBinding_AccountManager" contract="AccountManager.AccountManager" name="CustomBinding_AccountManager" />" contractName="AccountManager.AccountManager" name="CustomBinding_AccountManager" />
Part of Reference.svcmap:
</ClientOptions>
<MetadataSources>
<MetadataSource Address="http://localhost:60322/AccountManager.svc" Protocol="http" SourceId="1" />
</MetadataSources>
<Metadata>
<MetadataFile FileName="AccountManager2.xsd" MetadataType="Schema" ID="e473b2d5-7af3-4390-87c3-a4fc3f54fb96" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?xsd=xsd2" />
<MetadataFile FileName="AccountManager1.xsd" MetadataType="Schema" ID="fd3a1ae0-b38b-4586-8622-5b0ee07e39fb" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?xsd=xsd0" />
<MetadataFile FileName="AccountManager.xsd" MetadataType="Schema" ID="6a49ee64-6eac-40e2-bcff-26418435e777" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?xsd=xsd1" />
<MetadataFile FileName="AccountManager.disco" MetadataType="Disco" ID="9ec9a8cc-0cf0-4264-a526-b5a6c08f7d36" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?disco" />
<MetadataFile FileName="AccountManager1.wsdl" MetadataType="Wsdl" ID="54a5b2c0-9d0e-4043-a7e4-d27ae6674bfc" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?wsdl=wsdl0" />
<MetadataFile FileName="AccountManager.wsdl" MetadataType="Wsdl" ID="f8923013-3a6c-412b-b7da-bee5a5a7bb64" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?wsdl" />
..and ALL these again for other 2 services too.
I am not a master of web services/bindings/endpoints/operation contracts or any related stuff. I just want to make my totally already-nice-working (when URI is hardcoded) system work for relative URIs, that's all I need. There must be a simple solution. Can someone explain what exactly those file types and declarations resemble, which are important and which are optional, and how can I create dynamic service references in the cleanest form. Please, with explanations. I've already seen lots of posts and articles about dynamic service bindings and references, but honestly, everything gets messed up and I end up not understanding anything from it. Any constructive criticism and solutions are welcome.
Is the config file for your service (not the client) using endpoints with fully qualified addresses (like your client config)? If so, the reason you're seeing all those localhost references is because when you add the service reference, it's going to carry through that address in the generated files.
Update the endpoint in your service config file to either use the fully qualified address on that machine (i.e., http://somname.com/service.svc), or set the baseAddresses in the config file to the machine name.
Additionally, if you're using WCF 4.0 (VS 2010/.NET 4.0), you can have WCF create a default endpoint for your service(s) by ommitting the endpoints from the config file altogether (as I understand it - we're just moving to 4.0 at work now, so I haven't played with the new features).
EDITED TO ADD
New approach, same basic idea (that the URI is being imported from somewhere). Based on your comments below, it sounds like your service's config is set up fine, with no hard-coded URIs pointing to localhost.
When you move your application to the target server(s), are you updating your reference to your service (via the Add Service Reference) as well, or simply moving the files that generates from your local box to the target server?
If you are, I'm wondering if that might be the source of your problem. I would think that specifying the service address when you create the client should override anything in the WSDL-related files, but maybe its not.
Something to try:
Delete the <client> section from your Web.config. Then, when you create the client, do so like this:
fileManager = new FileManagerClient(new BasicHttpBinding("CustomBinding_FileManager"), new EndpointAddress("http://" + Settings.Host + "/FileManager.svc"));
Make sure you pass in the name of the binding configuration section in the BasicHttpBinding constructor, otherwise you'll get the binding with the default values, not the larger values you specified.
The idea here is to eliminate any chance that the client config file settings are overriding what you're passing in on the FileManagerClient creation.
I'd consider it less than ideal to have to update the service reference for every deployment to each individual server - what you're trying to accomplish makes sense. I do something similar in an n-tier app I've written - the only difference is that I don't use service references, I generate the proxy via SvcUtil and then generate channels via ChannelFactory<T>, which is another route you might want to look at.
If none of this help, please feel free to e-mail me (my e-mail address is in my profile) - it might be easier to figure this out via e-mail exchange and then post the final solution.