My application receives MQTT messages via JMS on a Websphere AS. The MQTT endpoint is a Websphere MQ.
Is there any way to identify the sender of the message (the sending device, not Websphere MQ ;-) )? I could not find a matching field in the jms message header...
When creating the MQTT channel there are options to use either the MQTT Client ID or the Username for authorization checks. If the channel is configured to use JAAS and the option to use the Username is selected, I believe the MQMD.UserID inherits the Username. I don't have JAAS authentication configured but when I get some time later I'll test it and update.
I was able to test the option that uses the ClientID for authorization and it does not result in the client ID ending up in the MQMD.UserID field.
Since identity propagation is a common requirement, I'd suggest raising a Request For Enhancement (RFE) stating that either Client ID or Username should propagate to the MQMD.UserID, depending onthe channel setting.
Related
I am using IBM WebSphere MQ 8.x and would like to secure it.
How can I secure my WebSphere Queue Messaging with username/password, so that only valid user can perform operations.
this is how I am accessing Queue right now
Context jndiContext = getInitialContext();
String qcf= getJMSDetailsBean().getQueueConnectionFactory();
QueueConnectionFactory qconFactory = (QueueConnectionFactory) jndiContext.lookup(qcf);
qcon = qconFactory.createQueueConnection();
Could you please guide me on below:
How can I secure my MQ first?
After #1, How can I access MQ using QueueConnectionFactory ?
Thanks
Like many other things in technology there are multiple ways to accomplish the task you are asking about, below describes one method using the IBM MQ provided functionality.
To answer the simpler question first, if you want to pass a username and password to MQ you can call createQueueConnection with the arguments of username and password
createQueueConnection("username", "password")
On the MQ side if you can upgrade I would suggest you move to 9.0.0.5 LTS, if you cannot upgrade to v9.0 then I suggest you upgrade to 8.0.0.10 + IFIX IT25591, you can download the IFIX for this right from the APAR page at the top.
You do not mention which Operating system the queue manager is running on. For most operating system versions you can configure the queue manager to validate credentials against either the Operating System (IDPWOS) or LDAP (IDPWLDAP). You will point the QMGR CONNAUTH property to an AUTHINFO object with AUTHTYPE of either of the above options.
On Unix Operating Systems such as Linux you can configure IDPWOS authentication method (AUTHENMD) as either OS (uses crypt and compare against shadow password entries) or PAM (uses Pluggable Authentication Module). If you go with IDPWOS I recommend PAM because it can provided crypt and compare support (same as the OS method) but also supports anything you can do with PAM, for example authenticate against Windows Active Directory.
For security you want to tell MQ to adopt the user that is authenticated, this is the ADOPTCTX(YES) setting on the AUTHINFO object. You should configure the queue manager for ChlauthEarlyAdopt=Y in the qm.ini file (Note these are both now the default behavior in MQ v9.0.4 CD and higher and on 9.1.0.0 LTS (also 9.1.1 CD) and higher.
If you are sure you want every SVRCONN channel on the queue manager to require a valid username/password to be sent you can set CHCKCLNT(REQUIRED) on the AUTHINFO object. If you need to be more granular you can set this to CHCKCLNT(OPTIONAL) which means if a username and password is present, the password needs to be valid for the username, but it also means if a password is not provided MQ will not attempt authentication. You may want this if you for example have some existing channels where you use a different authentication method such as TLS certificates, or a security exit. If it is set to OPTIONAL at the QMGR level, you can setup CHLAUTH rules to uplift the setting to CHCKCLNT(REQUIRED) for specific channels.
Remember that if you make any changes to the queue manager CONNAUTH settings you need to run REFRESH SECURITY TYPE(CONNAUTH) for those to take effect.
If the MQ client is at MQ v8 or higher, the password if sent on a non-TLS channel will be protected by default with a 3DES encryption, the exception here is for Java and JMS clients you must enabled MQCSP mode (compatibility is the default).
The setting PasswordProtection=always can be set in the qm.ini to ensure that MQ enforces that the password must either be protected by the password protection feature or use a TLS channel with a non-NULL cipherspec. This also means that on non-TLS channels any client that is less than v8 will be rejected.
I'll update this answer provide some example commands to implement the settings above, please let me know if this answer is going in the direction you are looking for?
I scanned the Fix list for IBM MQ Version 8.0 and found the following of interest either related to CONNAUTH or security in general that are fixed in versions later than 8.0.0.3, this is not a complete list there are many more:
8.0.0.5:
IT12825: IBM MQV8: A CLIENT APPLICATION FAILS TO CONNECT TO A QUEUE MANAGER WITH ERROR AMQ9777: CHANNEL WAS BLOCKED.
IT11645: AN IBM MQ V8 CLIENT CONNECTION IS INCORRECTLY ALLOWED WHEN PASSWORDPROTECTION=ALWAYS AND USER_AUTHENTICATION_MQCSP=FALSE
CVE-2015-7473: IBM WebSphere MQ Improper access control for some local MQSC commands
CVE-2016-0259: IBM WebSphere MQ Improper access control for some display commands in local runmqsc
8.0.0.6:
CVE-2016-3052: IBM MQ Java clients might send a password in clear text
8.0.0.7:
IT18052: ChlauthEarlyAdopt modifications
8.0.0.8:
IT22419: All username/password authentication requests hang. Queue manager is configured to request via PAM
IT21306: Ensure consistency among mechanisms for enabling MQCSP authentication mode in Java
IT21384: Setting COM.IBM.MQ.CFG.JMQI.USEMQCSPAUTHENTICATION=Y does not enable the MQCSP authentication mode after IT15833
8.0.0.10:
IT20275: USERMAP CHLAUTH rules and ChlauthEarlyAdopt do not map to the correct user
8.0.0.11 (not release yet):
IT25591: Connection to queue manager fails after upgrade to MQ 8.0.0.10, error log reports user missing CTRL authority on qmgr (AMQ8077)
I have a local MQ which my IIB connects to in client mode (i.e. not as a trusted application). I've set check client connection security on in the QM and now the IIB can't connect because it doesn't send a password and it's sending the wrong username (by default it uses the user that the process starts with). I've seen lots of documentation around setting dbparms mq::*. I could be wrong that but that only seems to affect the MQ Input and Output nodes ? Not the actual broker and it's config manager connections to MQ?
However, I've tried setting those values so that all client connection to my QMGR get a user/passwd but it still comes across as failing and I can see in the MQ logs that it's trying to connect using the userid that the IIB process was started with (and presumably without a password).
So, how do I get IIB to ALWAYS send a user/passwd to MQ when connecting the node/config mgr to the QM using client connections??
Clarification:
I have set mq::MQ -u -p and still the node attempts to connect to the QMGR using the ID that the MQSI process is started with and not the -u param. I have no execution groups and (of course) no flows in my broker so this can only be a core IIB component that's attempting the connection.
According to the IBM Integration Bus v10.0.0.10 Knowledge Center page "Connecting to a secured WebSphere MQ queue manager" you can set this in three ways:
On each MQ Node by specifying a Security identity property.
For all MQ connections to a named queue manager
For all MQ connections.
The order of which ID will be used is the same as above, so if you have a ID setup for all queue managers, you can override it for a specific queue manager or a specific MQ Node.
If you have a queue manager you are already connecting to called for example IIBQM, you could specify the following command so that all connections to that queue manager would use the specified username and password.
mqsisetdbparms integrationNodeName -n mq::QMGR::IIBQM -u username -p password
The KC page tells how to set it all three ways. If you have any specific questions please update your question by clicking edit and add more details and I can update my answer.
Hurrah - I've worked this out !
Although, I had not enabled chcklocal or chckclnt MQ, the fact that I had a idpwldap authinfo set meant that MQ was going to LDAP to find out who the user was that I was logging in with (presumably so that it could check what group permissions it had). So, I had to put my local user into LDAP and set its group.
This got my broker working (with no execution groups or flows). Once I deployed my simple mqinput and MQ output node flow it failed due to authorisations using the same ID. I could then see that it was binding locally and not as a client (which i had first considered). Phew - all done. So, to review: the answer was to put the user id that the mqsi bip/bipbroker process runs under into LDAP. Then give various MQ permissions so that the broker NODE and it's MQ flow NODES could connect to MQ correctly and put/get etc.
thanks for your help - and maybe this will help someone else in the future when someone puts on MQ security and they have a local QM with IIB.
Is it possible to do this way:
WampSharp client app connects to a WampSharp Server, then this server sends message/call client's function?
The client can subscribe to a topic and then you can publish to this topic, specifying in the publish options' eligible property the session id of the client.
For functions this is more tricky - you would need to register the procedure with a unique name which depends on the client's session id and then call it from the server side.
I am newbie to Websphere MQ and i have some basic understanding on the concept of MQ. I know that MQ client would create a message (with MQMD and application data) and then send to MQ manager. MQ client will get the correct response back from MQ Manager. Supposedly there are many messages on the MQ Queue Manager, how does MQ client able to retrieve the right messages? What determines the uniqueness of a MQ message?
There are different ways this can be approached - one common way is for the applications processing the messages to use the message ID and correlation ID fields. The message ID can be randomly generated and saved then copied to correlation ID field to be match when the reply is sent. Applications can do gets matching on those fields in the message header.
I suggest you read through the application programming guide and reference in the knowledge center.
I'm designing a system where one server must send messages to lots of independent clients. The clients doesn't know about each other and should not be able to consume, peek or in any other way acquire knowledge about each others messages.
I therefore wonder if JMS / ActiveMq have the ability to control which clients get which messages?
I want all the clients to connect to the same JSM provider (the 'destination') and consume only messages meant for them. This would be a simple setup from the servers point of view.
An alternative would be to acquire webservice endpoints from all the clients and perform ws-calls every time the server have a message for a client. I think this alternative sound 'wrong' as I think ws calls are bloated. There is a great overhead for each ws call, and this server would have to make 1000's of call each day. In my opinion this would be suboptimal for the server...
Short answer: Use Message selector.
Detail answer:
The question doesn't mention about how conversation is initiated. So here my answers for both scenarios.
a) If client initiates the conversation (i.e. Client sends a message to server and waiting for a reply).
This is a request/reply scenario. Messaging/JMS is a decoupled communication system. But request/reply is a common pattern in JMS. It can be implemented using correlation pattern.
A unique identifier(correlation id) is sent part of the request message.
Server receives the message and sets the correlation id in the reply message.
Client uses Message selector to receive the message with the correct correlation id.
b) If server initiates the conversation (i.e. Server sends messages to the clients without client request).
In this case, similar approach can be used.
A fixed client id is assigned to each client.
Server maintains all client ids and sets client id of the recipient as correlation id of the message.
Client uses Message selector to receive the message which has correlation id equals to its client id.
Update about confidentiality.
Following info extracted from this link useful for you to understand JMS security.
JMS does not specify a security
contract or an API for controlling
message confidentiality and integrity.
Security is considered to be a
JMS-provider-specific feature. It is
controlled by a System Administrator
rather than implemented
programmatically or by the J2EE server
runtime.
Two major features of JMS security are Authentication and Authorization. According to my knowledge, JMS security for client access is focusing on protecting the JMS destinations (not the individual messages). As long as a client has access to a destination, the security role assigned to the client is applicable for all the messages belongs to the destination.
Based on this,
Solution 1: If the client code is controlled by a trusted party.
Follow my solutions in my original answer.
This will make sure the message is delivered to the right person. But will not protect anything if the client code is purposely modified to receive all messages.
Solution 2: Assign private destination and user account to each client and configure security such that user account of a client can access only its destination.
Note: Found a link about "Restrictions for message selectors to provide message level authorization". But I think it is a vendor specific custom feature.
Hope this will be helpful.