Skip to content

Commit 1718dec

Browse files
authored
Merge pull request #2 from ibm-messaging/tls-connections
Support anonymous and mutual TLS connections
2 parents 9622e59 + 0d84290 commit 1718dec

11 files changed

+416
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ generally replace the various "assert" calls that test the successful execution
112112
your own error handling or logging.
113113
* Creating a ConnectionFactory that uses a client connection to a remote queue manager - [connectionfactory_test.go](connectionfactory_test.go)
114114
* Creating a ConnectionFactory that uses a bindings connection to a local queue manager - [local_bindings_test.go](local_bindings_test.go)
115+
* Create a connection using anonymous (one-way) TLS encryption or mutual TLS authentication - [tls_connections_test.go](tls_connections_test.go)
115116
* Send/receive a text string - [sample_sendreceive_test.go](sample_sendreceive_test.go)
116117
* Send a message as Persistent or NonPersistent - [deliverymode_test.go](deliverymode_test.go)
117118
* Get by CorrelationID - [getbycorrelid_test.go](getbycorrelid_test.go)

mqjms/ConnectionFactoryImpl.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ type ConnectionFactoryImpl struct {
3030
Password string
3131

3232
TransportType int // Default to TransportType_CLIENT (0)
33+
34+
// Equivalent to SSLCipherSpec and SSLClientAuth in the MQI client, however
35+
// the names have been updated here to reflect that SSL protocols have all
36+
// been discredited.
37+
TLSCipherSpec string
38+
TLSClientAuth string // Default to TLSClientAuth_NONE
39+
40+
KeyRepository string
41+
CertificateLabel string
3342
}
3443

3544
// CreateContext implements the JMS method to create a connection to an IBM MQ
@@ -50,6 +59,34 @@ func (cf ConnectionFactoryImpl) CreateContext() (jms20subset.JMSContext, jms20su
5059
cd.ConnectionName = cf.Hostname + "(" + strconv.Itoa(cf.PortNumber) + ")"
5160
cno.ClientConn = cd
5261

62+
// Fill in the fields relating to TLS channel connections
63+
if cf.TLSCipherSpec != "" {
64+
cd.SSLCipherSpec = cf.TLSCipherSpec
65+
}
66+
67+
switch cf.TLSClientAuth {
68+
case TLSClientAuth_REQUIRED:
69+
cd.SSLClientAuth = ibmmq.MQSCA_REQUIRED
70+
case TLSClientAuth_NONE:
71+
case "":
72+
cd.SSLClientAuth = ibmmq.MQSCA_OPTIONAL
73+
default:
74+
cd.SSLClientAuth = -1 // Trigger an error message
75+
}
76+
77+
// Set up the reference to the key repository file, if it has been specified.
78+
if cf.KeyRepository != "" {
79+
sco := ibmmq.NewMQSCO()
80+
sco.KeyRepository = cf.KeyRepository
81+
82+
if cf.CertificateLabel != "" {
83+
sco.CertificateLabel = cf.CertificateLabel
84+
}
85+
86+
cno.SSLConfig = sco
87+
88+
}
89+
5390
} else if cf.TransportType == TransportType_BINDINGS {
5491

5592
// Indicate to use Bindings connections.

mqjms/Constants.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@ const TransportType_CLIENT int = 0
1616
// Used to configure the TransportType property of the ConnectionFactory,
1717
// to use a local bindings connection to the queue manager
1818
const TransportType_BINDINGS int = 1
19+
20+
// Used to configure the TLSClientAuth property to indicate that a client
21+
// certificate should not be sent.
22+
const TLSClientAuth_NONE string = "NONE"
23+
24+
// Used to configure the TLSClientAuth property to indicate that a client
25+
// certificate must be sent to the queue manager, as part of mutual TLS.
26+
const TLSClientAuth_REQUIRED string = "REQUIRED"

tls-samples/DigiCertRootCA.pem

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
3+
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4+
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
5+
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
6+
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
7+
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
8+
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
9+
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
10+
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
11+
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
12+
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
13+
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
14+
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
15+
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
16+
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
17+
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
18+
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
19+
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
20+
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
21+
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
22+
-----END CERTIFICATE-----

tls-samples/README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Running the TLS tests
2+
The TLS connection tests found in [tls_connections_test.go](../tls_connections_test.go)
3+
demonstrate how to configure two different patterns of TLS;
4+
- Anonymous ("one way") TLS to encrypt traffic between the client application
5+
and the queue manager
6+
- Mutual TLS authentication, where the client application also authenticates itself
7+
to the queue manager by providing a client certificate
8+
9+
In order to successfully run the TLS examples you must first apply some specific
10+
configuration to your queue manager using the following three steps;
11+
12+
13+
## Step 1: Define the queue manager channels
14+
The tests assume that two new channels have been created on the queue manager - one
15+
to demonstrate anonymous TLS, and the other for mutual TLS.
16+
17+
You can define the necessary channels by executing the following runmqsc commands
18+
against your queue manager. Note that if your queue manager is configured to block
19+
all access by default (for example a queue manager hosted by the [IBM MQ on Cloud service](https://cloud.ibm.com/catalog/services/mq) or using the developer configuration for the [public MQ Docker container](https://github.com/ibm-messaging/mq-container/blob/6c72c894f775752a8ec8944d73dde4264711f0ff/incubating/mqadvanced-server-dev/10-dev.mqsc.tpl#L42))
20+
then you will also need to execute the `SET CHLAUTH` command associated with each
21+
channel, otherwise you will receive a `MQRC_NOT_AUTHORIZED` after the TLS
22+
connection has been established.
23+
```
24+
DEFINE CHANNEL(TLS.ANON.SVRCONN) CHLTYPE(SVRCONN) SSLCIPH(ANY_TLS12) SSLCAUTH(OPTIONAL) REPLACE
25+
SET CHLAUTH(TLS.ANON.SVRCONN) TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT(REQUIRED) DESCR('Allow applications to connect') ACTION(REPLACE)
26+
27+
DEFINE CHANNEL(TLS.MUTUAL.SVRCONN) CHLTYPE(SVRCONN) SSLCIPH(ANY_TLS12) SSLCAUTH(REQUIRED) REPLACE
28+
SET CHLAUTH(TLS.MUTUAL.SVRCONN) TYPE(ADDRESSMAP) ADDRESS('*') USERSRC(CHANNEL) CHCKCLNT(REQUIRED) DESCR('Allow applications to connect') ACTION(REPLACE)
29+
```
30+
31+
32+
## Step 2: Import the queue manager certificate into the client key store
33+
The [anon-tls.kdb](anon-tls.kdb) and [mutual-tls.kdb](mutual-tls.kdb) files are
34+
keystores that contain certificates that are used when the test applications
35+
connect to the queue manager.
36+
37+
The keystores have been configured to contain the public certificate for the DigiCert Root
38+
certificate authority (CA) so that the tests will automatically work against any
39+
queue manager that presents a certificate issued by DigiCert (such as queue
40+
managers hosted by the IBM MQ on Cloud service), however if your queue manager
41+
uses a certificate issued by a different certificate authority then you will need
42+
to import the public part of that certificate into both of the keystores in order
43+
for the tests to pass.
44+
45+
To do this, obtain a copy of the public certificate for your queue manager in PEM
46+
format, and import it into each of the keystores as follows;
47+
```
48+
gsk8capicmd -cert -add -db anon-tls.kdb -file MyQMgrCert.pem -label MyQMgrCert -stashed -type kdb -format ascii
49+
gsk8capicmd -cert -add -db mutual-tls.kdb -file MyQMgrCert.pem -label MyQMgrCert -stashed -type kdb -format ascii
50+
```
51+
Note that the `gsk8capicmd` command is included in the [IBM MQ redistributable client installation](https://ibm.biz/mq91cdredistclients)
52+
in the `./gskit8/bin` directory, or if you have a local queue manager installation
53+
then you can substitute that command for the `ikeycmd` command instead.
54+
55+
56+
## Step 3: Import the client certificate into the queue manager key store
57+
For the mutual TLS scenario you must also configure the queue manager so that it
58+
trusts the certificate that will be presented by the client application. The client
59+
will present the certificate with the label `SampleClientA` in [mutual-tls.kdb](mutual-tls.kdb),
60+
but for convenience the same certificate is also included in this directory
61+
as [SampleClientA.pem](SampleClientA.pem).
62+
63+
The technique for importing the client certificate into the queue manager keystore
64+
depends on the type of queue manager you are using, for example;
65+
- For IBM MQ on Cloud queue managers you can import the certificate into the Trust
66+
Store as [described here](https://cloud.ibm.com/docs/services/mqcloud?topic=mqcloud-mqoc_jms_tls#twoway_mqoc_jms_tls)
67+
- For software installed MQ queue managers on Linux, use the `runmqckm` command [as described here](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.sec.doc/q012830_.htm)
68+
69+
Note that in both cases you must refresh the queue manager security configuration
70+
in order for the new certificate to take effect - for example by executing the
71+
runmqsc command `REFRESH SECURITY TYPE(SSL)` or equivalent.
72+
73+
74+
## Reference: Creating your own key store files
75+
The [anon-tls.kdb](anon-tls.kdb) and [mutual-tls.kdb](mutual-tls.kdb) files in
76+
this directory have been pre-defined for use with the TLS tests defined in this
77+
repository, however you will create equivalent files for use with your own
78+
applications.
79+
80+
The following commands demonstrate how the pre-defined files were created using
81+
the `gsk8capicmd` command. As noted above this command is supplied with the IBM
82+
MQ redistributable client installation, but if you have a local queue manager
83+
installation then you can substitute the `ikeycmd` command instead.
84+
85+
```
86+
# Create the anon-tls key store
87+
gsk8capicmd -keydb -create -db anon-tls.kdb -pw myKeystorePW -type kdb -expire 0 -stash
88+
89+
# Import the DigiCert Root CA certificate so that queue managers with certificates
90+
# issued by that CA will be trusted by default
91+
gsk8capicmd -cert -add -db anon-tls.kdb -file DigiCertRootCA.pem -label DigiCertRootCA -stashed -type kdb -format ascii
92+
93+
# Create the mutual-tls key store
94+
gsk8capicmd -keydb -create -db mutual-tls.kdb -pw myMutualKeystorePW -type kdb -expire 0 -stash
95+
96+
# Import the DigiCert Root CA certificate so that queue managers with certificates
97+
# issued by that CA will be trusted by default
98+
gsk8capicmd -cert -add -db mutual-tls.kdb -file DigiCertRootCA.pem -label DigiCertRootCA -stashed -type kdb -format ascii
99+
100+
# Create a new self-signed private key and certificate inside the mutual-tls keystore.
101+
# The client will present this certificate to identify itself to the queue manager
102+
gsk8capicmd -cert -create -db mutual-tls.kdb -pw myMutualKeystorePW -sig_alg SHA256WithRSA -expire 3650 -label SampleClientA -dn "O=Sample Client Corporation, C=UK"
103+
104+
# Extract the public part of the self-signed certificate so that it can be added
105+
# to the queue manager keystore in order that the queue manager trust the client
106+
gsk8capicmd -cert -extract -db mutual-tls.kdb -pw myMutualKeystorePW -label SampleClientA -target SampleClientA.pem
107+
```

tls-samples/SampleClientA.pem

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIICITCCAYqgAwIBAgIIOQlzLC+tO3cwDQYJKoZIhvcNAQELBQAwMTELMAkGA1UE
3+
BhMCVUsxIjAgBgNVBAoTGVNhbXBsZSBDbGllbnQgQ29ycG9yYXRpb24wHhcNMTkw
4+
OTA0MTgzNjA4WhcNMjkwOTAyMTgzNjA4WjAxMQswCQYDVQQGEwJVSzEiMCAGA1UE
5+
ChMZU2FtcGxlIENsaWVudCBDb3Jwb3JhdGlvbjCBnzANBgkqhkiG9w0BAQEFAAOB
6+
jQAwgYkCgYEAv+dovBFeunMYwf+iN3viHwx5LJ4zgR0YLdedFXBiWocSs5P2TXfg
7+
JXtSTqHYKXnfD25JXc2EJP6mqftvRovHWoOZ0p2EM1V1my4erojvEiEZJaK3yHIT
8+
VNkF5ceTpco6VK++GJl7ElTbnpSs5YlIMsfwIpknpYzPp4F6J+RI4PsCAwEAAaNC
9+
MEAwHQYDVR0OBBYEFHpB4uZu1Wfqy1IgWKmsQHhhLHZ9MB8GA1UdIwQYMBaAFHpB
10+
4uZu1Wfqy1IgWKmsQHhhLHZ9MA0GCSqGSIb3DQEBCwUAA4GBAKJmISVSOOYkgU8T
11+
z+PYZyNgmxInnO8CPHyOXSCSwNPhQEh++5bwUt7+Ogvfmq5Xtl1m0u479L46yosd
12+
j7M3q4CizNcpyQBLzgP5BbCoebcnNqakbeZ9MmA+fWnFyKSWtT2868LbKg2mezvA
13+
MgcCMXwzVgAQQfVQFevRdPLgVbdl
14+
-----END CERTIFICATE-----

tls-samples/anon-tls.kdb

4.96 KB
Binary file not shown.

tls-samples/anon-tls.sth

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
��5��(<9<늳Y�DoS��~NM�耒�Q�k�@�>m�(\h���� "&b *ï|&:B��Lw�S�#.d��?kR����U�'� �/��S��,�k�?CwTԡU o�&�y�jJ�J��Wh��=�ec.��#� I�-���Zʀ�� �]���9�ŽG�M� BË�&�n�)��H���,�'��3�`

tls-samples/mutual-tls.kdb

9.84 KB
Binary file not shown.

tls-samples/mutual-tls.sth

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
� Sh���b�4w�������q��n0[��숛�14Y��-�
2+
�V�78�2�@� ,e��s��G�"K%q�'����X#:�&îq��P^jZQ���G$d�,�в�ƖV)c���\�tճ��@�I���
3+
49c 9'zN�Lj���}�6� 9�Zp H���߹�:��&ϫ~4��Ã�"Exі�~

0 commit comments

Comments
 (0)