Pre-Requisites :
1. Docker runtime
2. .NET runtime
3. Two set of certs/keys(ex : CA-Cert.crt, Client-key.p12)
MQ Server Setup :
create a directory "keys", navigate to "keys" directory in terminal/command-prompt and run the commands listed below.
Creating CA Certificates
Create a Key Repository for the CA
runmqakm -keydb -create -db myCA.kdb -type cms
Create your self-signed CA Certificate
runmqakm -cert -create -db myCA.kdb -type cms -label "myCAcertificate" -dn "CN=MyCA,O=myOrganisation,OU=myDepartment,L=myLocation,C=IN" -expire 1000 -size 4096 -sig_alg SHA256WithRSA -ca true
Extract the CA Certificate
runmqakm -cert -extract -db myCA.kdb -type cms -label "myCAcertificate" -target myCAcertfile.crt -format ascii
Creating Queue Manager Certificates
Create a Key Repository for the Queue Manager Certificate
runmqakm -keydb -create -db qm.kdb -type cms -stash
Generate a certificate request file for the queue manager,along with a private key
runmqakm -certreq -create -db qm.kdb -type cms -dn "CN=QM,O=myOrganisation,OU=myDepartment,L=myLocation,C=IN" -label "ibmwebspheremqqm" -file qm.req -sig_alg SHA256WithRSA -size 4096
-label : should be "ibmwebspheremq<qmgrname>"
-size : should be 4096KB
Sign the Queue Manager certificate with CA
runmqakm -cert -sign -db myCA.kdb -label "myCAcertificate" -expire 365 -format ascii -file qm.req -target qm.crt
Add the public certificate of the CA to the key repository of the queue manager
runmqakm -cert -add -db qm.kdb -type cms -file myCAcertfile.crt -label "theCAcert"
Receive the certificate (now signed by the CA) into the queue manager’s key repository:
runmqakm -cert -receive -db qm.kdb -type cms -file qm.crt
Note : Set the path name for Queue Manager's key repository. We will be using a Queue Manager by name 'qm'. The &KDB_PATH& refers to the path where the qm.kdb has been created.
Create and configure a Queue Manager for the SSL connectivity
crtmqm <QueueManager>
strmqm <QueueManager>
runmqsc <QueueManager>
ALTER QMGR SSLKEYR('&KDB_PATH&\qm')
DEFINE CHANNEL(<ChannelName>) CHLTYPE(SVRCONN) TRPTYPE(TCP)
SSLCAUTH(REQUIRED) SSLCIPH('ANY_TLS12_OR_HIGHER')
DEFINE QLOCAL(<QueueName>)
DEFINE LISTENER(<ListenerName>) TRPTYPE(TCP) PORT(1414)
START LISTENER(<ListenerName>)
REFRESH SECURITY(*)
Create Client Certificates
Creating a Key Repository for the Client Application
runmqakm -keydb -create -db myapp.p12 -type pkcs12 -stash -pw "password"
Create a Certificate Request
runmqakm -certreq -create -db myapp.p12 -type pkcs12 -label "ibmwebspheremqroot" -dn "CN=myApp,O=myOrganisation,OU=myDepartment,L=myLocation,C=IN" -file myapp.req -size 4096 -sig_alg SHA256WithRSA
-label : Should be "ibmwebspheremq<active-user-name>"
Sign the application cert with the CA
runmqakm -cert -sign -db myCA.kdb -label "myCAcertificate" -expire 365 -format ascii -file myapp.req -target myapp.crt
Add the CA certificate to the key repository of the application
runmqakm -cert -add -db myapp.p12 -type pkcs12 -file myCAcertfile.crt -label "theCAcert"
Receive the certificate (now signed by the CA) into the application’s key repository
runmqakm -cert -receive -db myapp.p12 -type pkcs12 -file myapp.crt
Follow below steps in the Client machine(RHEL) :
First, We will install the certificates and add the CA to the trusted store on the local Linux machine, then use the same certs within the container.
Local Linux Machine Steps :
In Linux, certificates are managed by OpenSSL. There are two types of certificates that need to be installed/added to the personal/trusted store :
1. Private Key of the Client.
2. CA certificate which is used to sign both Queue-Manager and Client’s certificates.
1. Installing the Private key of the client : On Linux, you can install the client’s private key through a piece of code, similar to the approach you have already followed.
The private key is typically stored in a .pfx (PKCS#12) format during installation.
The below piece of code will install the cert. The program has to be updated with appropriate keystore and password values. The sample code below uses the keystore "myapp.p12" and password used to create that keystore. Make sure you provide the correct path to the client key(myapp.p12).
for ex., X509Certificate2 certificate1 = new X509Certificate2("/path/to/the/key/myapp.p12", "*****");
Note : The *.pfx files will be installed into this directory "/root/.dotnet/corefx/cryptography/x509stores/my/".
try
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
X509Certificate2 certificate1 = new X509Certificate2("myapp.p12", "*****");
//Create a collection and add two of the certificates.
X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Add(certificate1);
//Add certificates to the store.
store.Add(certificate1);
store.AddRange(collection);
X509Certificate2Collection collection2 = new X509Certificate2Collection();
collection2.Import("myapp.p12", "*****", X509KeyStorageFlags.PersistKeySet);
foreach (X509Certificate2 cert in collection2)
{
store.Add(cert);
Console.WriteLine("Certificate installed successfully");
}
}
catch (Exception e)
{
throw e;
}
2. Adding the CA into trusted Store : The CA we used to sign the client and Queue-Manager certificate need to be added to the trusted store.
Navigate to "/etc/pki/ca-trust/source/anchors/" directory, place a copy of the CA certificate in this folder. ex., "CA.crt"
run the "update-ca-trust"
To verify the CA is added to trusted store, run the "opnessl verify CA.crt", it will log OK if the cert is added.
Note : It adds the CA into following trusted store "ca-bundle.crt and ca-bundle.trust.crt". Path to ca-bundle.crt and ca-bundle.trust.crt is "/etc/ssl/certs/"
Inside the Container :
The certs we just installed/added are in the Local linux machine, the application inside the container cannot access private-key or ca-bundle to verify the server certificate.
So, we need to add the installed *.pfx, ca-bundle.crt and ca-bundle.trust.crt into container as well.
Let's start by creating a directory which conatins all the pre-requisites.
1. Create a new directory "SimplePut"
2. Copy SimplePut.cs and SimplePut.csproj files to the SimplePut folder created in Step 1 from the following location:
Windows : MQ_INST_PATH\tools\dotnet\samples\cs\core\base\SimplePut
Linux : MQ_INST_PATH/samp/dotnet/samples/cs/core/base/SimplePut
3. Remove the following line from SimplePut.csproj file
<HintPath>..\bin\amqmxmsstd.dll</HintPath>
4. Copy amqmxmsstd.dll file to the SimplePut folder created in Step 1 from the following location:
Windows : MQ_INST_PATH\bin
Linux : MQ_INST_PATH/lib64
5. Get a copy of the *.pfx files from the "/root/.dotnet/corefx/cryptography/x509stores/my/"(Local Machine directory).
Create a directory with "certificates", place the copied *.pfx files inside this directory.
The .NET runtime expects the client's private key to be available in the following default location: /root/.dotnet/corefx/cryptography/x509stores/my/
We will copy these certifiactes into "/root/.dotnet/corefx/cryptography/x509stores/my/" this location inside the conatiner.
6. Get a copy of the ca-bundle.crt and ca-bundle.trust.crt from the "/etc/ssl/certs/" (alternate location of ca-bundles "/etc/pki/tls/certs")
Create a directory with "cabundle", Place both ca-bundle.crt and ca-bundle.trust.crt files inside this directory.
This is needed to verify whether the certificate sent by the QM(MQServer) is signed by a trusted CA.
Writing the dockerfile :
1. Create a "dockerfile" inside the SimplePut directory.
2. copy the below content inside the dockerfile
# ---- Build Stage ----
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app
# Copy project files and restore dependencies
COPY *.csproj ./
RUN dotnet restore
# Copy the entire source code and build the application
COPY . ./
RUN dotnet publish -c Release -o out
# ---- Runtime Stage ----
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
# Copy required certificates
COPY certificates /root/.dotnet/corefx/cryptography/x509stores/my/
# copy the installed private key into the default location where the .NET runtime expects it
COPY cabundle /etc/ssl/certs/
# copy the CA bundle into the default location where the .NET runtime expects it
### RUN grep -i "CN-Name" /etc/ssl/certs/ca-bundle.trust.crt
## Uncomment the above line to verify that the CA cert is included in the system CA bundle
# replace "CN-Name" with the actual common name of your CA cert
# Copy the published output from the build stage
COPY --from=build /app/out .
# Set the entry point
ENTRYPOINT ["dotnet", "SimplePut.dll"]
Running the dockerfile :
1. Open command prompt to build the docker image.
2. To verify whether docker is installed or not, issue the following command on command line as follows:
docker -v
Output (latest version): Docker version 28.0.4, build b8034c0
If not, please install Docker for Linux/windows containers from Docker website.
3. Navigate to your project folder and use the below command to build your Docker image.
"docker build -t simpleput ."
Note: Image_name should be lowercase alphabets.
4. Docker image with simpleput will be successfully created. Output as follows:
Building 9.3s (20/20) FINISHED
------------------ Output of other commands ----------------
=> exporting to image 0.4s
=> => exporting layers 0.3s
=> => writing image sha256:13d6a5964a5852d9419e650b56ff87532e0fc19cf6a42eba0da7447c83dcf567 0.0s
=> => naming to docker.io/library/simpleput
5. Running the Docker Image :
Issue "docker run simpleput -q queue-name -h host-name -l channel-name -p port-num -k *SYSTEM/*USER -s cipher-spec"
e.x. docker run simpleput -q LQ -h localhost -l CHL -p 1414 -k *SYSTEM -s TLS_RSA_WITH_AES_128_CBC_SHA256
Output :
Start of SimplePut Application
MQ Parameters
1) queueName = queue-name
2) keyRepository = *SYSTEM/*USER
3) cipherSpec = cipher-spec
4) host = host-name
5) port = port-num
6) channel = channel-name
7) numberOfMsgs = 1
8) sslPeerName =
9) keyResetCount = 0
10) sslCertRevocationCheck = False
Connecting to queue manager..
done
Accessing queue queue-name.. done
Message 1 <test message>.. put successfully onto the queue
Closing queue.. done
Disconnecting queue manager.. done
End of SimplePut Application
Note :
1. Keep only one *.pfx certificate in the "certifiactes" directory and try to connect. There will be two *.pfx files present, please place one cert at a time and try out independently for each cert.
2. Verify the key-size for 4096KB, CA-cert and Queue Manager set-up.