I'm currently having one design problem that is:
I have a distributed system where I have a main "data service", that receives requests and handout the data, and some workers that are created using the same container image.
However, I want some these workers to have access to diferent data. The data service could just accept all requests and trust the workers, but as the workers may in the future have user code, I want a no-trust environment.
One way I though of doing is to assign a "random key" (private/public key, one-time password, token...) for each worker at it's creation, send this key to the data service and the data service would know which resources the worker would have access to.
I think that's not too dificult to create, but I wouldn't want to recreate the wheel, specialy something that deals with security.
Do you guys know any authentication/authorization method (Kerberos, SAML, OIDC, etc) that solves this problem?
BTW, we're using Keycloak for SSO and I think that it uses OIDC, but as far as I know it is password based and I have a hard time thinking if it could solve this problem.
Related
I am working on oracle SOA, I created a asynchrous connection and I was able to get the message that I was successful. Now as a client, how can I check if my service is working correctly. I am a newbie, any help would be appreciated.
As a client you don't. you can't, know the service is working. That is the, um, magic of SOA. You submit your request and just have to trust that the service will keep its side of the contact.
So, this service does something. Eventually. There must be some tangible output - an order placed, a password reset, a report generated. At that point the service should communicate the outcome to the client by some mechanism depending on the nature of your application and the service in question - probably email or SMS, but perhaps a record in a table or a generated web page.
This it really a design or architectural question. A Service is a process: there's a triggering action - the client's submission - and an outcome, which is what the client wants (or an exception). In between is a set of business sub-routines which are largely invisible to the client (although a long running service might have windows, like Amazon's order tracking service).
You need to design your service so that it communicates the outcome to the client in some fashion. The precise details will obviously depend on what your service does.
The place I'm working at is trying to establish some ground rules, and the debate we're having now is local libraries vs web services for code reuse. Web services seem to be the popular pick in most companies, and that's what most of the developers here are leaning toward.
I just can't see how you can effectively use web services for any serious work. How can I safely execute multiple service calls if I can't use a transaction?
Let's say I have a cron job that grabs customers from our database who meet a certain condition that they need to be notified of. They are sent a fax, an email, and a ticket is created to track the issue internally. That is 3 different service calls that would happen for each customer in a for loop.
If an error occurs anywhere in there, it's possible that, for example, a fax and email is sent to the customer, but a ticket is not created. Or worse, this cron job could contain a bug on that causes it to fail at the same point every time, and it repeatedly emails the same customer. If the libraries were all local, everything could just be wrapped in a transaction, and none of that would happen. But we're using web services in this example.
Note that the email and fax methods actually insert the data into an email queue and a fax queue, which in turn are handled with a cron job. So the call to the "send email" and "send fax" service methods would be safe to rollback.
An option is to put this entire chunk of code in the web service itself, so the web service itself would call the email, fax, and ticket creating methods in a transaction. But then we're creating a web service method just for the use of a transaction; there is no valid reason we would ever actually need to call this method from anywhere except this one cron script.
How would you generally handle this method?
I would handle it by building a SAGA, an abstraction over a long running business process that has internal state, responds to external events, and interacts with external systems.
I would do this because your problem statement is incomplete: what happens when you can't send the email because the server is down? What if the fax system isn't working, but the other two aren't?
When you can't invoke one, should you retry? For how long? What happens if you can't raise a ticket for four hours, should you escalate to someone? Should this get a response, so something needs to track ticket status and escalate after some time? Should you email the original submitter some time, if you can't carry out any notification actions?
Using a saga is a model for when you can't just have a transaction, because it might potentially span hours of real time before the actions are complete - and holding a database lock that long, ouch.
Moving to a SOA means moving away from some of your older assumptions. One of those is that you should write methods and invoke them, to one where you encapsulate the behaviour of the system at a higher level and expose that as services.
If you try and build a web service that is like a local library, your life is going to suck. Approach this from the view that you want services that own data, and own behaviour related to that data, and encapsulate the details inside that.
(As an aside, I suspect that sending those things off from cron is actually part of a bigger business process, right, where cron does stuff, and sends notification as a consequence of that. Your service might well want to expose that entire sequence as a saga instead.)
Anyway, point is: you don't encapsulate things in a service because you want a transaction, and you don't put things in a transaction just to make them atomic. Those are separate concerns, and should be treated separately.
PS: if you use a transaction, don't you email twice if the email sent but the ticket wasn't created? You actually need a finer grained set of updates anyhow.
does anybody know agood way in granting a connection from one service to another, so that both services benefits fromeach other?
I would like to have an easy but never the less safe way to do a connection between my server and another server, but I don't know how to do that.
It should be ...
easy, so that neither the user nor the service providers have to waste alot of time
traffic effecient, so that traffic is not wasted and conenction is fast
encrypted, so that no person in between can use the transmitted data
and it should be an open and flexible standard, so that there could be more connections to other services (with my server in the middle of this star connection and no connection in between all providers) and that I don't have to pay a fee ;).
the example in the title is something I think about, because when you have a twitter account you somehow connect facebook to your account and facebook can show your twitterfeeds on your account.
but I don't want a provider to gather a lot of information beside the really important one that the user want to transmit. so I don't want the provide to get the username of my user and I don't really need to know how my user is named there.
It's like a post-office box. you just have to know where to put your letter, but you don't need to know the box owner's name.
and I don't want the mail-carrier to know what he is delivering, so it should be encrypted.
every clue how to do that would be fine, because I don't know anything about this :)
thank you in advance, Andreas
What you need is OAuth, check out the "Getting Started" guide to learn all about it
And the wiki entry
What kind of server do you people see in real projects?
1) Web Services MUST be stateless: Basically you must send username/password with every request, every request must use HTTPS and I will authenticate and load the User object everytime if needed.
2) A Session for Web Services: like in a web container so I can at least save the authenticated User object and have something similar to a session ID so I don't need to authenticate, load and check the User on every request.
3) Sticky Service (persistent service across requests): https://jax-ws.dev.java.net/nonav/2.1/docs/statefulWebservice.html
I understand the scalability problems of stateful services (and of web application sessions), but sometimes you must have some kind of state, for example for a shopping cart. But you can also put this state in the database (use the back-end as a kind of session argh) or passing the entire state to the client (the client becomes responsible for resending the entire shopping cart).
The truth is, at least for web applications, the session helps a lot in many situations. Scalability issues can be ignored if your system accepts that "the user must start over doing whatever he is doing if his web server happens to go down" or you can try a session cluster if that's unacceptable.
How it is for web services? I am inclined to conclude that web services are very different than web applications and accept option 1) (always stateless), but it would be nice to hear other opinions based on real project experience.
While it's only a small difference but it should still be mentioned:
It's not state in web services that kill scalability, rather it's state on the App Server that's hosting the web services that will kill scalability. The moment you say that this user needs to access this server (as done in sticky sessions) you are effectively limiting your scalability options. The point you want to get to is that 'Any of your free load-balanced App servers' can handle this web service request and if I add 1 more App Server I should be able to handle % more users.
It's totally fine (and personally recommended) if you want to maintain state to pass in an authentication token and on each request get the service to retrieve your 'state' from a data store (preferably a redundant and partitioned one, e.g. distributed+replicated key/value data store). That's how Amazon does it with SimpleDb and Google with BigTable.
Ebay takes a slightly different approach and stores most of the clients state in a cookie so it gets passed in with every request. Although it generates a lot more traffic, it still scalable as any of their servers can still handle the request.
If you want a scalable data store I would recommend looking at redis it has speed and features that can't be beat in a key/value data store.
You should also check out highscalability.com if you want access to good material on how to build fast and scalable services.
Ideally webservices (and web sites) should be stateless.
Unfortunately this takes very well thought out problem domain, and clear separation of concerns.
I've found that in practice most real-world web sites depend on state even though this limits their scalability.
I've also found that many real-world web-services also rely on state.
Ultimately the 'right' decision is the one that works for the specific problem, so it's probably okay to write a webservice that relies on state, and refactor it later if scalability becomes an issue.
Highly dependent on whether the service is single transaction oriented (say getting stock quotes) or if the output from the service is dependent on a data provided from a particular client across multiple transactions(in that case state must be maintained.)
As far as scalability issues, storing state in a database isn't actually a bad way to go (in fact it's probably the only way to go if you're load balancing your service across a server farm.)
I think with Flex clients the state is moved out of the service and into the client tier. Keep the services stateless and let the clients maintain the state needed. The services stay simple, and the clients are free to mash them together as they wish.
You seem to be equating state and authentication. Perhaps you're accustomed to storing username and password in session state?
This is not necessary, even with old ASMX web services. Simply pass whatever information you need to your "Login" operation. This operation will be defined to return an "Authentication Ticket" header.
All other operations that require authentication will require this "Authentication Ticket" header. They will each check the header to see if it represents a valid, authenticated user. If so, then they will perform their task. If not, then they will return a SOAP Fault indicating that authentication is required.
No state is required. Simply make sure that the authentication ticket can be validated on any server your service runs on (for instance, in a web farm), and you'll be fine.
Are there any alternatives to LogonUser and for impersonating given account in order to access network resources? I'm looking for the method of impersonation which would let me connect to machine in foreign domains (or, workgroup machines for the same matter).
For initial data I have: machine name, username (or domain\username), cleartext password.
I know there's a way to establish connection using WNetAddConnection to a \\machinename\ipc$, then most network functions will run in a context of that account, however win2008 added another twist and some functions still use the account, that thread is running under.
I'm also aware, that there's some way to get an impersonation token using SSPI. Have anyone experimented with those tokens, are they good for accessing shares, SCM, remote registry and stuff? Is is what WNetAddConnection is using?
EDIT: To clarify, the reason I cannot use LogonUser is because I need to impersonate user in a non-trusted domain or workgroup
EDIT2: Another clarification: the item I'm trying to implement is similar to psexec, e.g.:
program should not modify host or active directory configuration (e.g.: create temporary local users, etc). Moreover assumption cannot be made that it is running on DC or not
there can be no assumptions made about which software is pre-installed on the remote host, only condition given is that windows file sharing is enabled on target
Account/password is known to be working on target, but target machine may be in local domain, foreign domain, not in domain at all.
EDIT3: I would really love to hear more about SSPI InitializeSecurityContext / AcquireCredentialsHandle option. Is there anybody who has been working with this API extensively? Is it possible to use the tokens returned with impersonation, so that a thread can access network shares and copy files, etc? Can someone post a working code snippet?
EDIT4: Thanks to Marsh Ray, problem got resolved. If anyone is looking to see the proof-of-concept code, it is here
If you're wanting to "access network resources" outside of your forest, do that with WNetAddConnection2/3 as you mentioned, or use the standard RPC APIs with RPC_ C__ AUTHN__ GSS__ NEGOTIATE and and explicit credentials structure.
Normally, "impersonation" is something that happens on the server side. The server side will be able to impersonate the connection as the account you're connecting as.
But the key is this: impersonation only makes sense for impersonating an account the server can access in his local SAM/domain/forest directory. If the client and server are in different forests, they clearly can't agree on the SID of an account for an impersonation token (except for the case of well-known SIDs like Administrator which serve mainly to confuse this kind of thing), and that seems necessary to check against DACLs etc.
Perhaps what you want is to call LogonUserEx with the LOGON32__ LOGON__ NEW__ CREDENTIALS flag. This should succeed (even in a different forest - it doesn't actually authenticate the credentials you give it) giving you a token with the username/password you specified. You may have to use DuplicateToken to turn this into an impersonation token. Then you can use SetThreadToken to replace the token on your thread.
IMHO this isn't really "impersonation", you're just using the credentials outright, but it allows you to access network resources transparently as the arbitrary username/password you supply.
Edit: Oh yeah, be aware that there is no protection against man-in-the-middle on this type of connection. The client especially cannot strongly authenticate the server (short of heroics like IPSEC), so in theory you can't trust anything the server tells you.
The theory goes that you pass the credentials as a SEC_WINNT_AUTH_IDENTITY structure to the AcquireCredentialsHandle function that creates the handle used in InitializeSecurityContext. I never tried this on foreign domains though and I don't know if it works.
Doing this directly and reliably via the Windows API seems next to impossible, plus Windows does so much work behind the scenes to make network access "just work". Plus the impersonation side of things only works for the single thread that called the APIs.
But... you can run a whole program under a different user... such as when you run a service.
So you could edit the registry in your main program to run various services under different security tokens and use IPC/Sockets to communicate with those processes from your main application. ie. a whole bunch (or restarting and reconfiguring the same process) of helper processes running under the different user(s) which your main app abuses.
I realize this is a hack but it seems viable ;)
You could open a command line, map the drive using the plaintext username and password. Then disconnect the drive:
net use m: \\machinename\share password /user:username
... do stuff ...
net use m: /delete
http://technet.microsoft.com/en-us/library/cc756153(WS.10).aspx