We upgraded WebSphere Application Server to V7 and previously working applications now get 2035 authorization errors connecting to WebSphere MQ. What is different and how do we fix it?
This is an interesting question. In V6 and earlier if the User ID field on the WAS configuration panel for WMQ was left blank, WAS would use that value (NULL or blanks) as the ID it presented to WMQ on a connection. When WMQ receives a connection request that lacks a User ID it connects using the ID associated with the WMQ channel - which is always administrative and therefore always works.
As of V7, WMQ was changed to try harder to locate a User ID to send with the connection request. In the case of Java/JMS programs, the WMQ client will present the ID of the JVM on a connection request if no other ID was provided. In your case, the app server is now providing an ID whereas before it provided none, and the ID provided is not authorized to WebSphere MQ.
The very fact that this has happened means that your queue manager is configured to accept anonymous administrative connections. The first thing to do here is to lock down all unused inbound channels (those named SYSTEM.* of type RCVR, RQSTR, CLUSRCVR and SVRCONN). Next, make sure that any channels intended for administrative access (SYSTEM.ADMIN.SVRCONN for example) authenticate connections using an exit and/or SSL. If SSL is used, insure that SSLPEER is also used to limit the certificates that can connect.
Finally, once admin access is locked down, take the ID that is supposed to e used for WAS, authorize it's group accordingly and then put that ID in the channel's MCAUSER attribute. This will prevent the app from connecting to the channel as an administrator. If you want to be sure nobody can impersonate the app, set up SSL and/or an exit, the same way you did for the administrative channels.
Related
I have made a Java ExtLib XPage custom REST service (CustomServiceBean) database basing on this solution: https://setza-projects.atlassian.net/wiki/spaces/RS/pages/363593730/IBM+Domino
I modified it though to use NotesCalendar class to create, update and delete events & resource reservations (so everything in fact is processed by the calendar, I'm only using raw documents for reading $Rooms in names.nsf and $Reservations in the reservations database). Everything works fine so far, it uses current session to open the calendar. I have some concerns regarding the permissions though.
What I want (and need):
Ability to create calendar events & reservations as SPECIFIC users, I don't want just one "main" user that will create everything. I want each IBM Lotus user to be able to login with their credentials and create or update their calendar events.
This database with XPage will be deployed on our client's servers, so I don't want to require some special configuring for each user in order to be able to access my REST service.
I set up a new local installation of Lotus Server and created a new application using my XPage database as template, and I couldn't access the API neither with admin account or other accounts:
HTTP JVM: CLFAD0229E: Security exception occurred servicing request for: /db.nsf/services.xsp/api - HTTP Code: 403. For more detailed information, please consult error-log-0.xml
As soon as I added my admin account to Server configuration -> Security -> Sign or run unrestricted methods and operations, it started working again. Not only for the admin account, but also for other accounts that were just created with an internet password and weren't assigned any specific roles or permissions. I didn't even sign the database.
So my question is, is this enough in order to get it working on client's production server? It kind of makes no sense to me, but it worked on my local server so I'm not sure, I'm new to IBM Lotus and I'm just doing an integration REST service.
If not, how could I do it, so I wouldn't really need to put the end client (Lotus server owner) into the hassle of configuring each user, while still being able to access the API as any Lotus user (providing the username and password)? I can either log-in as each indepentend user, or perform some impersonation with a "main" privileged account (create entries in someone else's calendar as him), although I think there is no way to do it in Java, because .getCalendar is a method of the Session class, I tried using createSession(), but I wasn't able to.
Every notes application needs to be signed by an administrator with an ID known to the customers environment. The Id which is used to sign the db must have the appropriate rights, through the security tab in the server document. If the app is not signed properly, the app won't run. Once the app is signed, it runs in the authorized users session with the users rights.
My application is hosted by server A, and the other application is hosted by server B. "the other application" sometimes posts a request to my application, and in the request header, I can get the user id. Is it possible for me to get the user security role by this user id that is posted by "the other application". All the requests from server B are trusted.
I'm using Websphere Application server 8.0.0.5
Update
Let me rephrase the scenario, and not using "server" this time. There are A, B, C applications. When a specific user request from "the user" goes to A, A would publish an JMS event to B, and then B sends a request to C. C is my application, and B is "the other application" I mentioned above. So, the request from B to C is not an authenticated request (Not able to get the principal from the request instance). And all I can get from the request header if the user's id.
I'm not able to use isUserInRole method
The role is managed by WebSphere
As for the servlet/EJB API, you can only check if a user is in a certain role, but you cannot get the list of assigned roles.
If the user you get in the request header is authenticated by server A, you can call HttpServletRequest.isUserInRole against a list of known role names.
In your case the user is probably not authenticated by server A (because there is a trust), so this is not possible - there is no official API. I am not aware of a WebSphere specific API.
Options (all of these are only applicable, if there is really a trust)
Server B could pass the role(s) in a request header as well
Implement an EJB/web service etc. on server B, so that server A can query for the roles of a given user
If the roles are managed by an external system (LDAP etc.), you could get the roles from that system
Update (considering the comment which changes the scenario)
B could put the role of the calling user in a message property as well.
B could authenticate on C (C requires authentication from B)
If you cannot do that, and you cannot get the role neither from WebSphere or any other external system (LDAP for example), then I am not aware of another possibility.
I'm learning about RESTful interfaces. To update a server resource, say for a Contact with (id = 1) I'd PUT it:
PUT /contact/1
Now suppose the current user belongs to Organization 1, which owns Contact 1. There is also Organization 2, with Contact 2. The current user doesn't belong to Org 2 and has no rights to it. If the user hacks the web page (using Firebug for Mozilla or the "F12 debugger" for MSIE) and changes the web page request to point at /contact/2, the browser will merrily submit the request.
My server must protect against such cross-organization attacks. In my current web site design, once the user logs in I store a data object in the session (I'm using Tomcat/Java). That object stores which organization the user belongs to. Safety checking code compares the organization for the passed-back PUT request against the organization the user belongs to and sees if the passed-back data belongs to the user's organization. On detection of a hack (the user for org 1 is trying to modify contact 2, belonging to org 2) an error is returned to the browser.
I understand that REST is supposed to be stateless, but I'm currently using some state. Yet, if I pass the user information into the web page I think that this, too, can be hacked through Firebug, et.al.
How to achieve this safety without invoking server state?
Thanks,
Jerome.
RESTful services are usually stateless.
This means that every request has to be authenticated with an apikey or something else.
So the request will be /path?apikey=MYKEY and the server will handle the rights of that apikey.
By the way I've also tried stateful rest services, and the server is able to understand the session by a cookie initialized during the login (but that's not really RESTful).
If you want to try them with curl do something like:
curl -c cookie.txt -d "user=username&password=pass" "my.login.path"
curl -b cookie.txt "do.something"
I'm looking for information about authentication but I'm very newbie so I don't know any system.
My requeriments are: An user only can authenticate from one computer/mobile device/tablet.
I'm thinking about a monitoring system of MAC address and when the user connect using other device I can see this like an alert.
What other methods are there? Certificates?.
Repeat, I'm very newbie with this.
PD: My app has been development with framework Symfony2
So first of all MAC address is a network local address, which means that after it goes trough router/switch the MAC address changes, so you cannot relay on this. Even if you wanted to lookup interface MAC addres with your client software MAC's can be changed.
Secondly Certificates give you certain properties like nonrepudiation (you can calculate digital signatures on operations that users do and then the could not deny doing something in your application). But Public Key Infrastructure is really hard to manage! You would need your Certificate Authority to give valid certificates, You would need to monitor and update Certificate Revocation Lists to deny stolen/invalid/forged certificates from being treated as valid and authentic.
If it is not a security centric application and after you analyzed your options I would suggest simple form authentication (username/password/captcha). And write mechanizm that would periodicly (i.e. every second) send an AJAX request refreshing user status, thus you could recognize if user closed browser or has opened window. And in your authentication process you could check for other ACTIVE sessions for given username and deny login or act in some other fashion. If you need more informations about authentication I would recomend looking through security patterns
I've installed WebSphere MQ 7.1 on Linux platform, after which I installed WebSphere Message Broker 8.0.0.1. Now when I try to create an execution group, I get an exception: Reason code 2035. This exception states that the user is unauthorised to connect to the queue manager. I have this user added in the mqm group. I did not face any such issue when I was working with MQ 7.0.x. I searched a lot and came to know that there is user ID blocking in MQ 7.1. But, I want this user to be able to create execution group, how can I do so? Please advise.
MQ security has been improved a lot in MQ v7.1 and is different from what it used to be in earlier MQ versions. In MQ v7.1, by default all SYSTEM.channels are blocked. If you are trying to use any of these SYSTEM. channels then you will get 2035 which is MQRC_NOT_AUTHORIZED. The recommended way is to create your own SVRCONN channel for broker and create channel authentication records to allow the user to access queue manager.
Please see this link for detailed answers from T.Rob on similar issue.
Update:
A SVRCONN channel defines the endpoint of a queue manager meaning the connection information required by the clients to connect to a queue manager. Client applications use this type of channel to send and receive messages to/from a queue or a topic.
Message Broker toolkit is GUI that you can use to administer message broker, for example creating execution groups, creating flow, deploying bar files etc. Toolkit is available on Windows and I guess it's available on Linux.
I got to know that MB toolkit requires SYSTEM.BRK.CONFIG channel which is a SVRCONN channel to connect to queue manager. I am thinking this is the channel you will need to authorize to allow Message Broker to connect to MQ. Can you check if this is the case and if so create channel authentication record for that channel?
If you create a new QMgr at V7.1 or above, it comes with the following default CHLAUTH rules:
SET CHLAUTH(SYSTEM.ADMIN.SVRCONN) TYPE(ADDRESSMAP)
DESCR(Default rule to allow MQ Explorer access)
ADDRESS(*)
MCAUSER( ) USERSRC(CHANNEL)
SET CHLAUTH(SYSTEM.*) TYPE(ADDRESSMAP)
DESCR(Default rule to disable all SYSTEM channels)
ADDRESS(*)
MCAUSER( ) USERSRC(NOACCESS)
SET CHLAUTH(*) TYPE(BLOCKUSER)
DESCR(Default rule to disallow privileged users)
USERLIST(*MQADMIN)
The one on the bottom tells the QMgr "if someone tries to connect over a SVRCONN using an administrative user ID, block the connection in all cases."
To allow a connection from Broker Toolkit you have two choices as follows:
Remove mqbrkrs from the mqm group. This allows it to connect without firing the CHLAUTH rule that blocks admin users. You will of course be required to grant authorization for the mqbrkrs group to all the broker and application queues to which it needs access since it is no longer an MQ admin.
Override the CHLAUTH rule to allow the broker toolkit to connect as an admin on the SYSTEM.BROKER.CONFIG channel.
As a security specialist, I favor the first option. It is unavoidable that the MQ admin can administer the broker. However it is possible to avoid allowing the broker (and by extension all the broker flows) to administer the QMgr.
If, however, you wish to take the second route you'll need to override the CHLAUTH rule that blocks admin access. There are several ways to do this. You could delete the rule but that opens all your channels to admin connections. A more precise approach is to provide a rule just for the channel on which the administrator is to connect. For example:
SET CHLAUTH(SYSTEM.BKR.CONFIG) TYPE(BLOCKUSER) +
USERLIST('*NOACCESS')
Since WMQ applies the most specific rule, the default rule is overridden by the new one but only for the SYSTEM.BKR.CONFIG channel. The BLOCKUSER rule syntax allows us to specify who to deny but not who to allow and it takes user IDs rather than group IDs. In order to allow admin access it is necessary to specify some ID that is not *MQADMIN. I picked *NOACCESS because it cannot be an actual user ID and is a reserved word used by WMQ elsewhere. You could as easily used any user ID such as nobody or even mqm. (Blocking mqm would allow mqbrkrs but not mqm however since mqbrkrs is in the mqm group it would not restrict mqbrkrs from administering the QMgr.)
Finally, note that any channel which allows admin access should be strongly authenticated. If the only CHLAUTH rule you set is the one above, then anybody with a network route to the QMgr can connect on that channel by asserting the mqbrkrs user ID on the connection. Once connected, they would have full control over the QMgr and the ability to remotely, anonymously execute commands using the mqm or mqbrkrs user IDs. At the very least add a CHLAUTH rule to filter conenctions on this channel by IP address. Or, even better, use SSL and filter connections by the certificate distinguished name.