I'm working on a WCF project and right now I have four ServiceContract,
three (e.g. A, B, C) of them are accessable via http, endpoints with: mexHttpBinding / webHttpBinding
the fourht (e.g. D) is accessable via https, endpoints: mexHttpsBinding / webHttpBinding with Transport security mode
and every of them are REST based. The service will be run on IIS 8.
I want to achieve the following:
restrict acces from "outside" to A, B and C (communicate only on localhost with a webproject on the same server)
make D public becaues it receives data from an external source
I read a lot of articles and posts about this (e.g. IPFilter, namedpipes, stackoverflow answers, etc.) but sadly I haven't found the perfect solution yet.
I think, the best would be to do this on "server-level", so with IIS configuration, but I don't know how can I use different rules for
different contracts/endpoints.
What would be the best solution to solve this?
I'd a similar scenario, and I used IPFilter to do the work.
As you just want to restrict the access by external address, it can be good solution, it's simple and easy to implement.
Related
In a microservice world, what is the recommended way of configuring the endpoint of a downstream API?
For example, if Service A needs to invoke an endpoint in Service B, we have two options:
a. Make the hostname and port number of Service B's API configurable in Service A (service-b:8080) and append the path URI in your code
or
b. Make the complete endpoint configurable in Service A (http://service-b:8080/somepath)
While I like the idea of making the endpoint configurable, it leaves a lot of room for error because the entire path needs to be specified. It also doesn't fit well when multiple endpoints need to be called from Service A to Service B which may potentially have different paths, requiring us to configure multiple endpoints.
On the other hand, option (a) seems more scalable due to above mentioned reasons.
Most search results online just demonstrated how a service can call another service and uses a hardcoded URL to demo this. It would be good to know how is the community doing this in real world projects.
P.S: We use Spring Webflux and deploy to k8s.
I have seen mostly that teams use option a, where the serviceB "baseUrl" (which is basically https://serviceb-hostname:8080) is injected as environment property (kubernetes configmap) into the application during deployment.
The specific API specific paths are configured in application yaml or in the "proxy config" class itself as constants (eg. ServiceBProxy.java - proxy classes are those which will make rest-calls to the dependent services like service B).
Here is a portion of application yaml from one of the microservices (from one of my projects):
authorizationService:
baseUri: ${authorizationServiceBaseUri}/api
tenantService:
baseUri: ${tenantServiceBaseUri}/api/v1
tenantsUri: ${tenantService.baseUri}/tenants
settingsService:
baseUri: ${settingsServiceBaseUri}
iamService:
fetchBatchSize: 500
baseUri: ${iamServiceBaseUri}
Here the values of iamServiceBaseUri,settingsServiceBaseUri,tenantServiceBaseUri,authorizationServiceBaseUri are all injected during deployment. And each of them contains the clusterIP with port.
as you can see, I am relatively new on SO please don't kill me after posting this question :) I will do my best to describe the dilemma I am currently in.
I am creating something like a "Guardian Service" that is hosted on Windows Azure inside a Worker Role. This service has external ports, that can be accessed via HTTPS to allow clients to call it's service methods.
The WCF service is meant to call other services hosted in other Worker Roles that have only internal ports open, and which can be accessed only through the use of the Guardian Service. That's the main idea. Similar to a proxy or something.
I read already an excellent article from Jim O'Neil, what the caveats are when you try to access internal service points from within other WCF Services hosted in worker Roles:
His blog Troubleshooting Endpoints on a WCF Web Role
This is not the point for this question, and totally clear to me how to do that.
I have no idea at the moment, how I could do this, without implementing every contract from every single service I want to make accessible from within the Guardian Service to the outside world.
There must be a better way to decouple those things.
Any tips are appreciated.
Thank you.
I do not know the exact requirements for your project but I would say that what you are looking for is WCF Routing. I've used it in the past to redirect requests for different versions of Workflow instances.
The way it works is completely transparent to the client connecting to its endpoint. The router implementation must decide where to send the requests to, based on the request data (message headers and body).
In your case, if you are using SOAP and namespaces correctly, you might be able to base your decision on the message soap address and then send the request to the correct endpoint. You could also look at the Action property of the message.
Some links that might be useful:
http://msdn.microsoft.com/en-us/library/ee517423.aspx
http://www.codeproject.com/Articles/227699/RoutingService-on-Azure
I have a winforms application that is consuming a WCF service. So far, the WCF service is a selfhosted service on the local pc. It contains several interfaces (one per program functionallity).
As an improvement I want to expose the service to the internet, so I can call it using a new mobile app. This can be easily done by configuring the router/firewall and use some kind of dynamic dns or remember the ip address (in worst case scenario).
But now, here comes the real question:
In a next step I will distribute the winforms app to several locations (call it customers), acompagnied with their local WCF service en their mobile app. In order to allow the customer to connect to their wcf service (using the mobile app), I can set up now a dynamic dns for each customer, but I don't want to do that. First of all, the best dyndns services are not free, or you have to renew periodically. Second, I want to offer the customers my own dns service so I can 'forward' their wcf call to their own local service.
The wcfdnsrouter should be located at a public webhost, where the customers ip address is provided with an ip-updater (as it is often the case for other dyndns services)
As an example, imagine this:
Customer A; IP1; endpoint: http://wcfdnsrouter.com/A
Customer B; IP2; endpoint: http://wcfdnsrouter.com/B
Where I want that
wcfdnsrouter.com/A will forward (or route?) ALL calls to IP1
and
wcfdnsrouter.com/B will forward (or route?) ALL calls to IP2
With this scenario, the customer can access his service using mobile app from every place on earth. Hardware configuration on customers site is not a problem.
The goal is to use a parameter, rather than having an other url per customer. This should reduce the configuration and avoid duplicating my service. However, it is still an open trace (in this case, I need to create a subdomain and copy the wcfdnsrouter that is nothing more than a ordinary routingservice).
So, the entry point seems to be a restfull service that routes the message to another ip address\service.
I did already some research about routingservices, but I think I'll not get where I want. Contentbased routing is not an option since I don't want to change all my interfaces to have a criteria. I do not see how to make the link between the parameter in the restfull service with the ip addres I need to call (so another service).
Security is not realy a issue at this moment.
Please note that is question is NOT about (free) dns services. The purpose is to create it myself. Activating a new customer should not be more than installing the auto-ip-updater and assigning some kind of code (like A and B) in the example.
I need some advice how to do that. Maybe I'm on the wrong track thinking about routing? Maybe there is a very easy way that I mis?
Thanks in advance!
Let's say you've got a WCF service that is accessible via HTTP and HTTPS, but you want only certain methods to be available with HTTPS-- how can I check if the current request is HTTPS? Since HttpContext is empty, you can't simply check HttpContext.Current.Request.IsSecureConnection -- any other ideas? Thanks in advance.
Consider that WCF applications can also be hosted as a Windows service, with no ASP.NET at all, in which case there is no such thing as "secure" vs. "insecure." That is one reason why WCF does not attempt to make this information available.
One option would be to run the WCF service in ASP.NET Compatibility Mode, where you do have access to the HttpContext.Current instance.
My choice, however, would simply be to create a different, SSL-only service for the secure operations. I really think you'd want to do this anyway, so the contract is explicit; otherwise you're left doing runtime checks and clients may have no idea that the methods they're trying to use aren't allowed.
"Best practice" in a web service is to make these types of restrictions as explicit as possible, and having a separate service available only over SSL is by far the clearest means of describing your service's restrictions.
( Building on comment from #Aaronaught within answer by Matt Ellen... )
It looks like
OperationContext.Current.RequestContext.RequestMessage.Headers.To.Scheme
contains "http" or "https" among others (msdn).
HTTPS is served over a different port to HTTP. Assuming you know the ports, perhaps checking that would suffice.
How about:
var iwrc = WebOperationContext.Current.IncomingRequest;
var isHttps = iwrc.UriTemplateMatch.BaseUri.Scheme.Equals("https", StringComparison.InvariantCultureIgnoreCase);
This is very easy, does not rely on port numbers and works just fine in a self-host WCF server (with no IIS in site sight).
I'm trying to build a WCF self hosted service (eventually in a windows service) that will receive binary and text base messages from remote thick clients that have no accounts on my hosted machine. I'm trying to figure out both my binding options and security options, and in reading the patterns and practices guides, my head has completely spun around at least once.
The clients would be authenticated against a custom SQL based method, so I'd like to be able to pass that info in the initial login request and then set an authorization token of some kind. (This part of the problem is probably outside the scope of the question, but I included it in case it might make a difference.)
Any thoughts at all would be very helpfull.
Ryan
The choice of binding and security option depends on the usage of your WCF service. Is it just for your rich client or are you planning to expose it to the world as API? If it's just for your rich app, does it run on LAN or over untrusted, unreliable Internet?
With WCF you can configure the service to expose multiple endpoints with different bindings, for example both SOAP and REST. In general, I'd start with something stateless and lightweight like basicHttpBinding and webHttpBinding, passing user and password on every request. Once you have that up and running you can optimize cache authentication, provide binary endpoint etc.. only if it actually helps.
There's no need to have just one binding. Having said that if it's self hosted you're "on your own" here. I've never looked at what's involved.