Compare commits

..

43 Commits

Author SHA1 Message Date
Tom Jefferson
a28c8a3acb Update version to 9.3.0.4-r2. Update go to 1.18 and re-vendor (#411)
* Update version to 9.3.0.4-r2. Update go to 1.18 and re-vendor dependencies
2023-03-02 13:37:17 +00:00
Tom Jefferson
4311c04634 Merge pull request #376 from mq-cloudpak/amf-1831-version-length-930
Handle multi-digit portions of VRMF
2023-02-24 12:05:51 +00:00
Tom Jefferson
5ff3c358ed Merge branch 'v9.3.0.x' into amf-1831-version-length-930 2023-02-24 09:56:21 +00:00
Tom Jefferson
880fa699ef Merge pull request #404 from mq-cloudpak/tadj-9.3.0.4-update
Update version to 9.3.0.4-r1 and update ubi
2023-02-08 16:26:23 +00:00
Tom Jefferson
bd7c7cd91d Update version to 9.3.0.4-r1 and update ubi 2023-02-08 13:05:07 +00:00
Tom Jefferson
fb2e7c71e1 Update gosec behaviour and version (#397)
* Update gosec behaviour and fix resulting gosec vulnerabilities (#399)

Co-authored-by: KIRAN DARBHA <kirandarbha@in.ibm.com>
2023-02-07 22:03:13 +00:00
Alex Mirski-Fitton
923407e77f Fix setting buildkit disable environment variable 2023-02-06 14:43:43 +00:00
Simon Hirst
2181258e38 Updating gosec to 2.14.0
Updating gosec to 2.14.0
2023-02-01 14:41:02 +00:00
Simon Hirst
015481bd3e Updating gosec to 2.14.0 2023-02-01 12:46:28 +00:00
Alex Mirski-Fitton
27dada90d6 Handle multi-digit portions of VRMF 2023-01-24 13:34:08 +00:00
Alec Painter
de2d068bb6 Merge pull request #368 from mq-cloudpak/sjh-dec-lts-update
Version updates for January release
2023-01-11 08:23:14 +00:00
Simon Hirst
fd34ea0a78 Updating UBI and changelog 2023-01-09 15:07:51 +00:00
Simon Hirst
ad02f98858 Updating versions for January LTS release 2023-01-09 15:02:22 +00:00
Tom Jefferson
27679a6c58 Merge pull request #355 from mq-cloudpak/sjh-dec-updates
Updates for December LTS release
2022-12-06 17:57:38 +00:00
Simon Hirst
592ebdf555 Updating .travis.yml and Dockerfile-server UBI version and RELEASE 2022-12-06 15:32:53 +00:00
Alec Painter
35101841cc Merge pull request #348 from mq-cloudpak/ahp-9301-ubi
updated go-version & ubi
2022-11-14 10:34:39 +00:00
Alec-Painter
9033fd67d7 updated go-version & ubi 2022-11-14 10:11:38 +00:00
Alec Painter
066db7bf04 Merge pull request #341 from mq-cloudpak/ahp-nov-ga-9301r3
update release version for 9.3.0.1-r3
2022-10-21 12:07:29 +01:00
Alec-Painter
c64c188ae5 update release version for 9.3.0.1-r3 2022-10-21 09:06:27 +01:00
Tom Jefferson
8889ced3c8 Merge pull request #338 from mq-cloudpak/tadj-ipgate-go-toolset-930x
Update go toolset
2022-10-10 15:57:40 +01:00
Tom Jefferson
c4bf74bdf5 Update go toolset 2022-10-10 15:08:27 +01:00
Tom Jefferson
090a761aef Merge pull request #332 from mq-cloudpak/tadj-create-9.3.0.1-r2
Update ubi/go/release for 9.3.0.1-r2
2022-09-28 20:05:17 +01:00
Tom Jefferson
11d6685c45 Update ubi/go/release for 9.3.0.1-r2 2022-09-28 19:44:37 +01:00
Alec Painter
45934d8a59 Merge pull request #324 from mq-cloudpak/ahp-9.3.0.1-r1
Updated changelog for 9.3.0.1
2022-09-14 11:25:10 +01:00
Alec Painter
c9de739331 Merge branch 'v9.3.0.x' into ahp-9.3.0.1-r1 2022-09-14 10:37:27 +01:00
Alec-Painter
c78bc602b0 Updated changelog for 9.3.0.1 2022-09-14 10:31:07 +01:00
Alec Painter
f78ac15820 Merge pull request #323 from mq-cloudpak/ahp-9.3.0.1-r1
* Added MQ 9.3.0.1-r1

* Updated ubi & go-toolset versions
2022-09-12 12:15:27 +01:00
Alec-Painter
0e05030047 updated ubi & go version 2022-09-12 11:20:04 +01:00
Alec-Painter
46869e4df4 updated to version 9.3.0.1-r1 2022-09-12 11:18:12 +01:00
Alex Mirski-Fitton
8ba8ae4f6c Merge pull request #313 from mq-cloudpak/amf-credential-helper-go-version-930
Pin docker-credential-helpers for old go installs
2022-08-22 13:25:11 +01:00
Alex Mirski-Fitton
03e939a49b Pin docker-credential-helpers for old go installs 2022-08-22 11:49:54 +01:00
Tom Jefferson
f60281688e Merge pull request #310 from mq-cloudpak/tadj-update-ubi-930x
Update ubi and go version
2022-08-09 14:02:43 +01:00
Tom Jefferson
c3a23b7a1b Update ubi and go version 2022-08-08 21:34:09 +01:00
Prerna Srivastava
1941fc1675 Merge pull request #300 from mq-cloudpak/WS_fixes
Ws fixes
2022-08-05 14:24:32 +05:30
Prerna Srivastava
167319022f WS fix 2022-08-05 13:46:47 +05:30
Prerna Srivastava
fb1d17764a ws fixes 2022-08-05 12:04:04 +05:30
Tom Jefferson
5a20b85759 Merge pull request #294 from mq-cloudpak/tadj-add-august-cd-version
Update release for 9.3.0.0-r3 release
2022-08-01 15:59:29 +01:00
Tom Jefferson
d4668af82f Update release for 9.3.0.0-r3 release 2022-08-01 15:22:09 +01:00
Simon Hirst
ce8a34b1bb Push fake master to different namespace 2022-08-01 14:29:29 +01:00
Simon Hirst
f9852fb553 Push fake master to different namespace 2022-08-01 14:03:32 +01:00
Alex Mirski-Fitton
3957d487c3 Merge pull request #270 from mq-cloudpak/amf-9300r2
Update base images for 9.3.0.0-r2 release
2022-07-01 14:36:45 +01:00
Alex Mirski-Fitton
6427e0d84b Update base images for 9.3.0.0-r2 release 2022-07-01 11:54:21 +01:00
Alex Mirski-Fitton
9f12fc5a04 [ci skip]: Setting up v9.3.0.x branch 2022-06-28 15:46:05 +01:00
87 changed files with 488 additions and 3229 deletions

2
.dockerignore Normal file
View File

@@ -0,0 +1,2 @@
downloads
.git

1
.gitignore vendored
View File

@@ -1,4 +1,3 @@
.dockerignore
.DS_Store
.vscode
test/docker/coverage

View File

@@ -1,4 +1,4 @@
# © Copyright IBM Corporation 2018, 2023
# © Copyright IBM Corporation 2018, 2020
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -18,16 +18,16 @@ sudo: required
language: go
go:
- "1.18.10"
- "1.18.9"
services:
- docker
env:
global:
- MAIN_BRANCH=v9.3.2
- MAIN_BRANCH=v9.3.0.x
- TAGCACHE_FILE=tagcache
- RELEASE=r1
- RELEASE=r2
go_import_path: "github.com/ibm-messaging/mq-container"
@@ -38,51 +38,51 @@ go_import_path: "github.com/ibm-messaging/mq-container"
jobs:
include:
- stage: basic-build
if: branch != v9.3.2 AND tag IS blank
if: branch != v9.3.0.x AND tag IS blank
name: "Basic AMD64 build"
os: linux
env:
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_932_ARCHIVE_REPOSITORY_DEV_AMD64
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_930_ARCHIVE_REPOSITORY_DEV_AMD64
script: bash -e travis-build-scripts/run.sh
# CD Build
- stage: global-tag
if: branch = v9.3.2 AND type != pull_request OR tag =~ ^release-candidate*
if: branch = v9.3.0.x AND type != pull_request OR tag =~ ^release-candidate*
name: "Generate Global Tag"
os: linux
script: bash -e travis-build-scripts/global-tag.sh
- stage: build
if: branch = v9.3.2 OR tag =~ ^release-candidate*
if: branch = v9.3.0.x OR tag =~ ^release-candidate*
name: "Multi-Arch AMD64 build"
os: linux
env:
- BUILD_ALL=true
- MQ_ARCHIVE_REPOSITORY=$MQ_932_ARCHIVE_REPOSITORY_AMD64
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_932_ARCHIVE_REPOSITORY_DEV_AMD64
- MQ_ARCHIVE_REPOSITORY=$MQ_930_ARCHIVE_REPOSITORY_AMD64
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_930_ARCHIVE_REPOSITORY_DEV_AMD64
script: bash -e travis-build-scripts/run.sh
- stage: build
if: branch = v9.3.2 OR tag =~ ^release-candidate*
if: branch = v9.3.0.x OR tag =~ ^release-candidate*
name: "Multi-Arch S390X build"
os: linux-s390
env:
- BUILD_ALL=true
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
- MQ_ARCHIVE_REPOSITORY=$MQ_932_ARCHIVE_REPOSITORY_S390X
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_932_ARCHIVE_REPOSITORY_DEV_S390X
- MQ_ARCHIVE_REPOSITORY=$MQ_930_ARCHIVE_REPOSITORY_S390X
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_930_ARCHIVE_REPOSITORY_DEV_S390X
script: bash -e travis-build-scripts/run.sh
- stage: build
if: branch = v9.3.2 OR tag =~ ^release-candidate*
if: branch = v9.3.0.x OR tag =~ ^release-candidate*
name: "Multi-Arch PPC64LE build"
os: linux-ppc64le
env:
- BUILD_ALL=true
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
- MQ_ARCHIVE_REPOSITORY=$MQ_932_ARCHIVE_REPOSITORY_PPC64LE
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_932_ARCHIVE_REPOSITORY_DEV_PPC64LE
- MQ_ARCHIVE_REPOSITORY=$MQ_930_ARCHIVE_REPOSITORY_PPC64LE
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_930_ARCHIVE_REPOSITORY_DEV_PPC64LE
script: bash -e travis-build-scripts/run.sh
- stage: push-manifest
if: branch = v9.3.2 AND type != pull_request OR tag =~ ^release-candidate*
if: branch = v9.3.0.x AND type != pull_request OR tag =~ ^release-candidate*
name: "Push Manifest-list to registry"
env:
- PUSH_MANIFEST_ONLY=true

View File

@@ -1,10 +1,6 @@
{
"settingsInheritedFrom": "whitesource-config/whitesource-config@master",
"scanSettings": {
"configMode": "LOCAL",
"baseBranches": ["private-master", "v9.2.0.x-eus", "v9.3.0.x"]
},
"issueSettings": {
"issueRepoName": "whitesource-scan-issues"
}
"baseBranches": ["private-master", "v9.2.0.x-eus", "v9.2.5"]
}
}

View File

@@ -1,23 +1,12 @@
# Change log
## 9.3.2.1 (2023-04)
## 9.3.0.3-LTS (2023-01)
* Updated to MQ version 9.3.2.1
* Updated to MQ version 9.3.0.3
## 9.3.2.0 (2023-02)
## 9.3.0.1-LTS (2022-09)
* Updated to MQ version 9.3.2.0
* Queue manager certificates with the same Subject Distinguished Name (DN) as the issuer (CA) certificate are not supported. A certificate must have a unique Subject Distinguished Name.
* New logging environment variables: MQ_LOGGING_CONSOLE_SOURCE, MQ_LOGGING_CONSOLE_FORMAT, MQ_LOGGING_CONSOLE_EXCLUDE_ID. The LOG_FORMAT variable is deprecated.
* New environment variable: MQ_QMGR_LOG_FILE_PAGES
## 9.3.1.0-r2 (2022-11)
* Queue manager attribute SSLKEYR is now set to blank instead of '/run/runmqserver/tls/key' if key and certificate are not supplied.
## 9.3.1.0 (2022-10)
* Updated to MQ version 9.3.1.0
* Updated to MQ version 9.3.0.1
## 9.3.0.0 (2022-06)

View File

@@ -1,4 +1,4 @@
# © Copyright IBM Corporation 2015, 2023
# © Copyright IBM Corporation 2015, 2022
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,32 +13,37 @@
# limitations under the License.
ARG BASE_IMAGE=registry.access.redhat.com/ubi8/ubi-minimal
ARG BASE_TAG=8.7-1107
ARG BASE_TAG=8.7-1085
ARG BUILDER_IMAGE=registry.access.redhat.com/ubi8/go-toolset
ARG BUILDER_TAG=1.18.10-1
ARG BUILDER_TAG=1.18.9-13
ARG GO_WORKDIR=/opt/app-root/src/go/src/github.com/ibm-messaging/mq-container
ARG MQ_ARCHIVE="downloads/9.3.2.1-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz"
ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/9.3.0.4-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz"
###############################################################################
# Build stage to build Go code
###############################################################################
FROM $BUILDER_IMAGE:$BUILDER_TAG as builder
# The URL to download the MQ installer from in tar.gz format
# This assumes an archive containing the MQ Non-Install packages
ARG MQ_URL
ARG IMAGE_REVISION="Not specified"
ARG IMAGE_SOURCE="Not specified"
ARG IMAGE_TAG="Not specified"
ARG GO_WORKDIR
ARG MQ_ARCHIVE
USER 0
WORKDIR /opt/mqm
# Download and extract MQ files, to get the MQ client needed to compile.
# Only extract certain MQ files to make the build quicker
RUN curl --fail --location $MQ_URL | tar --extract --gunzip \
&& chown -R 1001:root /opt/mqm/*
WORKDIR $GO_WORKDIR/
ADD $MQ_ARCHIVE /opt/mqm
ENV CGO_CFLAGS="-I/opt/mqm/inc/" \
CGO_LDFLAGS_ALLOW="-Wl,-rpath.*" \
PATH="${PATH}:/opt/mqm/bin"
COPY go.mod go.sum ./
COPY cmd/ ./cmd
COPY internal/ ./internal
COPY pkg/ ./pkg
COPY vendor/ ./vendor
ENV CGO_CFLAGS="-I/opt/mqm/inc/" \
CGO_LDFLAGS_ALLOW="-Wl,-rpath.*" \
PATH="${PATH}:/opt/mqm/bin"
RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\" -X \"main.ImageTag=$IMAGE_TAG\"" ./cmd/runmqserver/ \
&& go build ./cmd/chkmqready/ \
&& go build ./cmd/chkmqhealthy/ \
@@ -53,44 +58,11 @@ RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"
&& go test -v ./internal/... \
&& go vet ./cmd/... ./internal/...
###############################################################################
# Build stage to reduce MQ packages included using genmqpkg
###############################################################################
FROM $BASE_IMAGE:$BASE_TAG AS mq-redux
ARG BASE_IMAGE
ARG BASE_TAG
ARG MQ_ARCHIVE
WORKDIR /tmp/mq
ENV genmqpkg_inc32=0 \
genmqpkg_incadm=1 \
genmqpkg_incamqp=0 \
genmqpkg_incams=1 \
genmqpkg_inccbl=0 \
genmqpkg_inccics=0 \
genmqpkg_inccpp=0 \
genmqpkg_incdnet=0 \
genmqpkg_incjava=1 \
genmqpkg_incjre=1 \
genmqpkg_incman=0 \
genmqpkg_incmqbc=0 \
genmqpkg_incmqft=0 \
genmqpkg_incmqsf=0 \
genmqpkg_incmqxr=0 \
genmqpkg_incnls=1 \
genmqpkg_incras=1 \
genmqpkg_incsamp=1 \
genmqpkg_incsdk=0 \
genmqpkg_inctls=1 \
genmqpkg_incunthrd=0 \
genmqpkg_incweb=1
ADD $MQ_ARCHIVE /opt/mqm-noinstall
# Run genmqpkg to reduce the MQ packages included
RUN /opt/mqm-noinstall/bin/genmqpkg.sh -b /opt/mqm-redux
###############################################################################
# Main build stage, to build MQ image
###############################################################################
FROM $BASE_IMAGE:$BASE_TAG AS mq-server
# The MQ packages to install - see install-mq.sh for default value
ARG MQ_URL
ARG BASE_IMAGE
ARG BASE_TAG
@@ -107,14 +79,15 @@ LABEL summary="IBM MQ Advanced Server" \
io.k8s.description="Simplify, accelerate and facilitate the reliable exchange of data with a security-rich messaging solution — trusted by the worlds most successful enterprises" \
base-image=$BASE_IMAGE \
base-image-release=$BASE_TAG
COPY --from=mq-redux /opt/mqm-redux/ /opt/mqm/
COPY setup-image.sh /usr/local/bin/
COPY install-mq.sh /usr/local/bin/
COPY install-mq-server-prereqs.sh /usr/local/bin/
# Install MQ. To avoid a "text file busy" error here, we sleep before installing.
RUN env \
&& mkdir /opt/mqm \
&& chmod u+x /usr/local/bin/install-*.sh \
&& chmod u+x /usr/local/bin/setup-image.sh \
&& sleep 1 \
&& install-mq-server-prereqs.sh \
&& setup-image.sh \
&& install-mq.sh \
&& /opt/mqm/bin/security/amqpamcf \
&& chown -R 1001:root /opt/mqm/*
COPY --from=builder $GO_WORKDIR/runmqserver /usr/local/bin/
@@ -137,9 +110,7 @@ RUN chmod ug+x /usr/local/bin/runmqserver \
EXPOSE 1414 9157 9443
ENV MQ_OVERRIDE_DATA_PATH=/mnt/mqm/data MQ_OVERRIDE_INSTALLATION_NAME=Installation1 MQ_USER_NAME="mqm" PATH="${PATH}:/opt/mqm/bin"
ENV MQ_GRACE_PERIOD=30
ENV LANG=en_US.UTF-8 AMQ_DIAGNOSTIC_MSG_SEVERITY=1 AMQ_ADDITIONAL_JSON_LOG=1
ENV MQ_LOGGING_CONSOLE_EXCLUDE_ID=AMQ5041I,AMQ5052I,AMQ5051I,AMQ5037I,AMQ5975I
ENV WLP_LOGGING_MESSAGE_FORMAT=json
ENV LANG=en_US.UTF-8 AMQ_DIAGNOSTIC_MSG_SEVERITY=1 AMQ_ADDITIONAL_JSON_LOG=1 LOG_FORMAT=basic
# We can run as any UID
USER 1001
ENV MQ_CONNAUTH_USE_HTP=false
@@ -150,6 +121,9 @@ ENTRYPOINT ["runmqserver"]
###############################################################################
# Use the Go toolset image, which already includes gcc and the MQ SDK
FROM builder as cbuilder
# The URL to download the MQ installer from in tar.gz format
# This assumes an archive containing the MQ Non-Install packages
ARG MQ_URL
USER 0
# Install the Apache Portable Runtime code (used for htpasswd hash checking)
RUN yum --assumeyes --disableplugin=subscription-manager install apr-devel apr-util-openssl apr-util-devel

110
Makefile
View File

@@ -20,13 +20,6 @@
include config.env
include source-branch.env
# arch_uname is the platform architecture according to the uname program. Can be differ by OS, e.g. `arm64` on macOS, but `aarch64` on Linux.
arch_uname := $(shell uname -m)
# arch_go is the platform architecture in Go-style (e.g. amd64, ppc64le, s390x or arm64).
arch_go := $(if $(findstring x86_64,$(arch_uname)),amd64,$(if $(findstring aarch64,$(arch_uname)),arm64,$(arch_uname)))
# ARCH is the platform architecture in Go-style (e.g. amd64, ppc64le, s390x or arm64).
# Override this to build an image for a different architecture. Note that RUN instructions will not be able to succeed without the help of emulation provided by packages like qemu-user-static.
ARCH ?= $(arch_go)
# RELEASE shows what release of the container code has been built
RELEASE ?=
# MQ_ARCHIVE_REPOSITORY is a remote repository from which to pull the MQ_ARCHIVE (if required)
@@ -48,7 +41,7 @@ MQ_SDK_ARCHIVE ?= $(MQ_ARCHIVE_DEV_$(MQ_VERSION))
# Options to `go test` for the Docker tests
TEST_OPTS_DOCKER ?=
# Timeout for the Docker tests
TEST_TIMEOUT_DOCKER ?= 45m
TEST_TIMEOUT_DOCKER ?= 30m
# MQ_IMAGE_ADVANCEDSERVER is the name of the built MQ Advanced image
MQ_IMAGE_ADVANCEDSERVER ?=ibm-mqadvanced-server
# MQ_IMAGE_DEVSERVER is the name of the built MQ Advanced for Developers image
@@ -67,6 +60,8 @@ MQ_DELIVERY_REGISTRY_NAMESPACE ?=
MQ_DELIVERY_REGISTRY_USER ?=
# MQ_DELIVERY_REGISTRY_CREDENTIAL is the password/API key for the remote registry (if required)
MQ_DELIVERY_REGISTRY_CREDENTIAL ?=
# ARCH is the platform architecture (e.g. amd64, ppc64le or s390x)
ARCH ?= $(if $(findstring x86_64,$(shell uname -m)),amd64,$(shell uname -m))
# LTS is a boolean value to enable/disable LTS container build
LTS ?= false
# VOLUME_MOUNT_OPTIONS is used when bind-mounting files from the "downloads" directory into the container. By default, SELinux labels are automatically re-written, but this doesn't work on some filesystems with extended attributes (xattrs). You can turn off the label re-writing by setting this variable to be blank.
@@ -111,17 +106,12 @@ endif
# Try to figure out which archive to use from the architecture
ifeq "$(ARCH)" "amd64"
MQ_ARCHIVE_ARCH:=X86-64
MQ_ARCHIVE_DEV_ARCH:=X64
MQ_ARCHIVE_ARCH=X86-64
MQ_ARCHIVE_DEV_ARCH=X64
else ifeq "$(ARCH)" "ppc64le"
MQ_ARCHIVE_ARCH:=PPC64LE
MQ_ARCHIVE_DEV_ARCH:=PPC64LE
MQ_ARCHIVE_ARCH=PPC64LE
else ifeq "$(ARCH)" "s390x"
MQ_ARCHIVE_ARCH:=S390X
MQ_ARCHIVE_DEV_ARCH:=S390X
else ifeq "$(ARCH)" "arm64"
MQ_ARCHIVE_ARCH:=ARM64
MQ_ARCHIVE_DEV_ARCH:=ARM64
MQ_ARCHIVE_ARCH=S390X
endif
# If this is a fake master build, push images to alternative location (pipeline wont consider these images GA candidates)
@@ -176,13 +166,6 @@ ifeq ($(shell [ ! -z $(TRAVIS) ] && [ "$(TRAVIS_PULL_REQUEST)" = "false" ] && [
MQ_MANIFEST_TAG_SUFFIX=.$(TIMESTAMPFLAT).$(GIT_COMMIT)
endif
# Make sure we don't use VOLUME_MOUNT_OPTIONS for Podman on macOS
ifeq "$(COMMAND)" "podman"
ifeq "$(shell uname -s)" "Darwin"
VOLUME_MOUNT_OPTIONS:=
endif
endif
PATH_TO_MQ_TAG_CACHE=$(TRAVIS_BUILD_DIR)/.tagcache
ifneq "$(TRAVIS)" "$(EMPTY)"
ifneq ("$(wildcard $(PATH_TO_MQ_TAG_CACHE))","")
@@ -302,7 +285,7 @@ build-devjmstest:
test-devserver: test/docker/vendor
$(info $(SPACER)$(shell printf $(TITLE)"Test $(MQ_IMAGE_DEVSERVER):$(MQ_TAG) on $(shell $(COMMAND) --version)"$(END)))
$(COMMAND) inspect $(MQ_IMAGE_DEVSERVER):$(MQ_TAG)
cd test/docker && TEST_IMAGE=$(MQ_IMAGE_DEVSERVER):$(MQ_TAG) EXPECTED_LICENSE=Developer DEV_JMS_IMAGE=$(DEV_JMS_IMAGE) IBMJRE=false DOCKER_API_VERSION=$(DOCKER_API_VERSION) go test -parallel $(NUM_CPU) -timeout $(TEST_TIMEOUT_DOCKER) -tags mqdev $(TEST_OPTS_DOCKER)
cd test/docker && TEST_IMAGE=$(MQ_IMAGE_DEVSERVER):$(MQ_TAG) EXPECTED_LICENSE=Developer DEV_JMS_IMAGE=$(DEV_JMS_IMAGE) IBMJRE=true DOCKER_API_VERSION=$(DOCKER_API_VERSION) go test -parallel $(NUM_CPU) -timeout $(TEST_TIMEOUT_DOCKER) -tags mqdev $(TEST_OPTS_DOCKER)
.PHONY: coverage
coverage:
@@ -337,17 +320,14 @@ test-advancedserver-cover: test/docker/vendor coverage
# Command to build the image
# Args: imageName, imageTag, dockerfile, extraArgs, dockerfileTarget
# If the ARCH variable has been changed from the default value (arch_go variable), then the `--platform` parameter is added
# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget
define build-mq
rm -f .dockerignore && echo ".git\ndownloads\n!downloads/$4" > .dockerignore
define build-mq-command
$(COMMAND) build \
--tag $1:$2 \
--file $3 \
$4 \
--build-arg IMAGE_REVISION="$(IMAGE_REVISION)" \
--build-arg IMAGE_SOURCE="$(IMAGE_SOURCE)" \
--build-arg IMAGE_TAG="$1:$2" \
--build-arg MQ_ARCHIVE="downloads/$4" \
--label version=$(MQ_VERSION) \
--label name=$1 \
--label build-date=$(shell date +%Y-%m-%dT%H:%M:%S%z) \
@@ -356,12 +336,69 @@ define build-mq
--label vcs-ref=$(IMAGE_REVISION) \
--label vcs-type=git \
--label vcs-url=$(IMAGE_SOURCE) \
$(if $(findstring $(arch_go),$(ARCH)),,--platform=linux/$(ARCH)) \
$(EXTRA_LABELS) \
--target $5 \
.
endef
# Build using a separate container to host the MQ download files.
# To minimize the layers in the resulting image, the download files can't be part of the build context.
# The "docker build" command (and "podman build" on macOS) don't allow you to mount a directory into the build, so a
# separate container is used to host a web server.
# Note that for Podman, this means that you need to be using the "rootful" mode, because the rootless mode doesn't allow
# much control of networking, so the containers can't talk to each other.
define build-mq-using-web-server
$(COMMAND) network create $(BUILD_SERVER_NETWORK)
$(COMMAND) run \
--rm \
--name $(BUILD_SERVER_CONTAINER) \
--network $(BUILD_SERVER_NETWORK) \
--volume $(DOWNLOADS_DIR):/opt/app-root/src$(VOLUME_MOUNT_OPTIONS) \
--detach \
registry.access.redhat.com/ubi8/nginx-120 nginx -g "daemon off;" || ($(COMMAND) network rm $(BUILD_SERVER_NETWORK) && exit 1)
BUILD_SERVER_IP=$$($(COMMAND) inspect -f '{{ .NetworkSettings.Networks.$(BUILD_SERVER_NETWORK).IPAddress }}' $(BUILD_SERVER_CONTAINER)); \
DOCKER_BUILDKIT=0 $(call build-mq-command,$1,$2,$3,--network build --build-arg MQ_URL=http://$$BUILD_SERVER_IP:8080/$4,$5) || ($(COMMAND) rm -f $(BUILD_SERVER_CONTAINER) && $(COMMAND) network rm $(BUILD_SERVER_NETWORK) && exit 1)
$(COMMAND) rm -f $(BUILD_SERVER_CONTAINER)
$(COMMAND) network rm $(BUILD_SERVER_NETWORK)
endef
# When building with Docker, always use the web server build because you can't use bind-mounted volumes.
# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget
define build-mq-docker
$(call build-mq-using-web-server,$1,$2,$3,$4,$5)
endef
# Make sure we don't use VOLUME_MOUNT_OPTIONS for Podman on macOS
ifeq "$(COMMAND)" "podman"
ifeq "$(shell uname -s)" "Darwin"
VOLUME_MOUNT_OPTIONS:=
endif
endif
# When building with Podman on macOS (Darwin), use the web server build because you can't use bind-mounted volumes with `podman build` on macOS
# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget
define build-mq-podman-Darwin
$(call build-mq-using-web-server,$1,$2,$3,$4,$5)
endef
# When building with Podman on Linux, just pass the downloads directory as a volume
# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget
define build-mq-podman-Linux
$(call build-mq-command,$1,$2,$3,--volume $(DOWNLOADS_DIR):/var/downloads$(VOLUME_MOUNT_OPTIONS) --build-arg MQ_URL=file:///var/downloads/$4,$5)
endef
# When building with Podman, just pass the downloads directory as a volume
# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget
define build-mq-podman
$(call build-mq-podman-$(shell uname -s),$1,$2,$3,$4,$5)
endef
# Build an MQ image. The commands used are slightly different between Docker and Podman
# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget
define build-mq
$(call build-mq-$(COMMAND),$1,$2,$3,$4,$5)
endef
###############################################################################
# Build targets
###############################################################################
@@ -400,12 +437,9 @@ build-sdk: downloads/$(MQ_ARCHIVE_DEV)
.PHONY: log-build-env
log-build-vars:
$(info $(SPACER)$(shell printf $(TITLE)"Build environment"$(END)))
@echo arch_uname=$(arch_uname)
@echo arch_go=$(arch_go)
@echo "ARCH=$(ARCH) (origin:$(origin ARCH))"
@echo MQ_VERSION="$(MQ_VERSION) (origin:$(origin MQ_VERSION))"
@echo MQ_ARCHIVE="$(MQ_ARCHIVE) (origin:$(origin MQ_ARCHIVE))"
@echo MQ_ARCHIVE_DEV_ARCH=$(MQ_ARCHIVE_DEV_ARCH)
@echo ARCH=$(ARCH)
@echo MQ_VERSION=$(MQ_VERSION)
@echo MQ_ARCHIVE=$(MQ_ARCHIVE)
@echo MQ_ARCHIVE_DEV=$(MQ_ARCHIVE_DEV)
@echo MQ_IMAGE_DEVSERVER=$(MQ_IMAGE_DEVSERVER)
@echo MQ_IMAGE_ADVANCEDSERVER=$(MQ_IMAGE_ADVANCEDSERVER)
@@ -546,7 +580,7 @@ gosec:
.PHONY: update-release-information
update-release-information:
sed -i.bak 's/ARG MQ_ARCHIVE=.*-LinuxX64.tar.gz"/ARG MQ_ARCHIVE="downloads\/$(MQ_VERSION)-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz"/g' Dockerfile-server && rm Dockerfile-server.bak
sed -i.bak 's/ARG MQ_URL=.*-LinuxX64.tar.gz"/ARG MQ_URL="https:\/\/public.dhe.ibm.com\/ibmdl\/export\/pub\/software\/websphere\/messaging\/mqadv\/$(MQ_VERSION)-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz"/g' Dockerfile-server && rm Dockerfile-server.bak
$(eval MQ_VERSION_1=$(shell echo '${MQ_VERSION}' | rev | cut -c 3- | rev))
sed -i.bak 's/IBM_MQ_.*_LINUX_X86-64_NOINST.tar.gz/IBM_MQ_${MQ_VERSION_1}_LINUX_X86-64_NOINST.tar.gz/g' docs/building.md && rm docs/building.md.bak
sed -i.bak 's/ibm-mqadvanced-server:.*-amd64/ibm-mqadvanced-server:$(MQ_VERSION)-amd64/g' docs/security.md

View File

@@ -27,10 +27,7 @@ Note that in order to use the image, it is necessary to accept the terms of the
- **LICENSE** - Set this to `accept` to agree to the MQ Advanced for Developers license. If you wish to see the license you can set this to `view`.
- **LANG** - Set this to the language you would like the license to be printed in.
- **MQ_QMGR_NAME** - Set this to the name you want your Queue Manager to be created with.
- **MQ_QMGR_LOG_FILE_PAGES** - Set this to control the value for LogFilePages passed to the "crtmqm" command. Cannot be changed after queue manager creation.
- **MQ_LOGGING_CONSOLE_SOURCE** - Specifies a comma-separated list of sources for logs which are mirrored to the container's stdout. The valid values are "qmgr" and "web". Defaults to "qmgr".
- **MQ_LOGGING_CONSOLE_FORMAT** - Changes the format of the logs which are printed on the container's stdout. Set to "json" to use JSON format (JSON object per line); set to "basic" to use a simple human-readable format. Defaults to "basic".
- **MQ_LOGGING_CONSOLE_EXCLUDE_ID** - Excludes log messages with the specified ID. The log messages still appear in the log file on disk, but are excluded from the container's stdout. Defaults to "AMQ5041I,AMQ5052I,AMQ5051I,AMQ5037I,AMQ5975I".
- **LOG_FORMAT** - Set this to change the format of the logs which are printed on the container's stdout. Set to "json" to use JSON format (JSON object per line); set to "basic" to use a simple human-readable format. Defaults to "basic".
- **MQ_ENABLE_METRICS** - Set this to `true` to generate Prometheus metrics for your Queue Manager.
See the [default developer configuration docs](docs/developer-config.md) for the extra environment variables supported by the MQ Advanced for Developers image.
@@ -41,7 +38,7 @@ If you want to use IBM MQ on [Kubernetes](https://kubernetes.io), you can find a
## Issues and contributions
For issues relating specifically to the container image or Helm chart, please use the [GitHub issue tracker](https://github.com/ibm-messaging/mq-container/issues). Pull requests are not currently accepted.
For issues relating specifically to the container image or Helm chart, please use the [GitHub issue tracker](https://github.com/ibm-messaging/mq-container/issues). If you do submit a Pull Request related to this Docker image, please indicate in the Pull Request that you accept and agree to be bound by the terms of the [IBM Contributor License Agreement](CLA.md).
## License
@@ -49,11 +46,11 @@ The Dockerfiles and associated code and scripts are licensed under the [Apache L
Licenses for the products installed within the images are as follows:
- [IBM MQ Advanced for Developers](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-CAUEQC) (International License Agreement for Non-Warranted Programs). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above.
- [IBM MQ Advanced](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-UPFX-8MW49T) (International Program License Agreement). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above.
- [IBM MQ Advanced](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-CAUEBE) (International Program License Agreement). This license may be viewed from an image using the `LICENSE=view` environment variable as described above or by following the link above.
Note: The IBM MQ Advanced for Developers license does not permit further distribution and the terms restrict usage to a developer machine.
## Copyright
© Copyright IBM Corporation 2015, 2023
© Copyright IBM Corporation 2015, 2022

View File

@@ -1,4 +1,4 @@
# © Copyright IBM Corporation 2017, 2022
# © Copyright IBM Corporation 2017, 2020
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -20,31 +20,19 @@
SRC_DIR = src
BUILD_DIR = ./build
ARCH ?= $(if $(findstring x86_64,$(shell uname -m)),amd64,$(if $(findstring aarch64,$(shell uname -m)),aarch64,$(shell uname -m)))
# Flags passed to the C compiler. Need to use gnu11 to get POSIX functions needed for file locking.
CFLAGS.amd64 := -m64
CFLAGS.ppc64le := -m64
CFLAGS.s390x := -m64
# -m64 is not a valid compiler option on aarch64/arm64 (ARM)
CFLAGS.arm64 :=
CFLAGS += -std=gnu11 -fPIC -Wall ${CFLAGS.${ARCH}}
CFLAGS += -std=gnu11 -fPIC -Wall -m64
LIB_APR = -L/usr/lib64 -lapr-1 -laprutil-1
LIB_MQ = -L/opt/mqm/lib64 -lmqm_r
all: $(BUILD_DIR)/mqhtpass.so $(BUILD_DIR)/htpass_test $(BUILD_DIR)/log_test
all: $(BUILD_DIR)/mqhtpass.so $(BUILD_DIR)/htpass_test
$(BUILD_DIR)/log.o : $(SRC_DIR)/log.c $(SRC_DIR)/log.h
mkdir -p ${dir $@}
gcc $(CFLAGS) -c $(SRC_DIR)/log.c -o $@
$(BUILD_DIR)/log_test : $(BUILD_DIR)/log.o
mkdir -p ${dir $@}
gcc $(CFLAGS) $(SRC_DIR)/log_test.c $^ -o $@
# Run Logging tests, and print log if they fail
$@ || (cat log_test*.log && exit 1)
$(BUILD_DIR)/htpass.o : $(SRC_DIR)/htpass.c $(SRC_DIR)/htpass.h
mkdir -p ${dir $@}
gcc $(CFLAGS) -c $(SRC_DIR)/htpass.c -I /usr/include/apr-1 -o $@

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2021, 2022
© Copyright IBM Corporation 2021
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -124,7 +124,7 @@ void log_printf(const char *source_file, int source_line, const char *level, con
if (strftime(date_buf, sizeof date_buf, "%FT%T", utc))
{
// Round microseconds down to milliseconds, for consistency
cur += snprintf(cur, end-cur, ", \"ibm_datetime\":\"%s.%03ldZ\"", date_buf, now.tv_usec / (long)1000);
cur += snprintf(cur, end-cur, ", \"ibm_datetime\":\"%s.%03ldZ\"", date_buf, now.tv_usec / 1000);
}
cur += snprintf(cur, end-cur, ", \"ibm_processId\":\"%d\"", pid);
cur += snprintf(cur, end-cur, ", \"host\":\"%s\"", hostname);
@@ -146,17 +146,7 @@ void log_printf(const char *source_file, int source_line, const char *level, con
// Important: Just do one file write, to prevent problems with multi-threading.
// This only works if the log message is not too long for the buffer.
fprintf(fp, "%s", buf);
fprintf(fp, buf);
}
}
int trimmed_len(char *s, int max_len)
{
int i;
for (i = max_len - 1; i >= 0; i--)
{
if (s[i] != ' ')
break;
}
return i+1;
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2021, 2022
© Copyright IBM Corporation 2021
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -59,12 +59,5 @@ void log_close();
*/
#define log_debugf(format,...) log_printf(__FILE__, __LINE__, "DEBUG", format, ##__VA_ARGS__)
/**
* Return the length of the string when trimmed of trailing spaces.
* IBM MQ uses fixed length strings, so this function can be used to print
* a trimmed version of a string using the "%.*s" printf format string.
* For example, `log_printf("%.*s", trimmed_len(fw_str, 48), fw_str)`
*/
int trimmed_len(char *s, int);
#endif

View File

@@ -1,120 +0,0 @@
/*
© Copyright IBM Corporation 2022
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
// Headers for multi-threaded tests
#include <pthread.h>
// Start a test and log the function name
#define test_start() printf("=== RUN: %s\n", __func__)
// Indicate test has passed
#define test_pass() printf("--- PASS: %s\n", __func__)
// The length of strings used in the tests
#define STR_LEN 5
// Indicate test has failed
void test_fail(const char *test_name)
{
printf("--- FAIL: %s\n", test_name);
exit(1);
}
// Print a fixed-width string in hexadecimal
void print_hex(char fw_string[STR_LEN])
{
printf("[");
for (int i=0; i<STR_LEN; i++)
{
printf("%02x", fw_string[i]);
if (i < STR_LEN-1)
printf(",");
}
printf("]");
}
// ----------------------------------------------------------------------------
// Tests for string manipulation
// ----------------------------------------------------------------------------
void test_trimmed_len(const char *test_name, char fw_string[STR_LEN], int expected_len)
{
printf("=== RUN: %s\n", test_name);
int len;
// Create a copy of the fixed-width string
char fw_string2[STR_LEN];
memcpy(fw_string2, fw_string, STR_LEN * sizeof(char));
// Call the function under test
len = trimmed_len(fw_string, STR_LEN);
// Check the result is correct
if (len != expected_len)
{
printf("%s: Expected result to be %d; got %d\n", __func__, expected_len, len);
test_fail(test_name);
}
// Check that the original string has not been changed
for (int i=0; i<STR_LEN; i++)
{
if (fw_string[i] != fw_string2[i])
{
printf("%c-%c\n", fw_string[i], fw_string2[i]);
printf("%s: Expected string to be identical to input hex ", __func__);
print_hex(fw_string2);
printf("; got hex ");
print_hex(fw_string);
printf("\n");
test_fail(test_name);
}
}
printf("--- PASS: %s\n", test_name);
}
void test_trimmed_len_normal()
{
char fw_string[STR_LEN] = {'a','b','c',' ',' '};
test_trimmed_len(__func__, fw_string, 3);
}
void test_trimmed_len_full()
{
char fw_string[STR_LEN] = {'a','b','c','d','e'};
test_trimmed_len(__func__, fw_string, 5);
}
void test_trimmed_len_empty()
{
char fw_string[STR_LEN] = {' ',' ',' ',' ',' '};
test_trimmed_len(__func__, fw_string, 0);
}
// ----------------------------------------------------------------------------
int main()
{
// Turn on debugging for the tests
setenv("DEBUG", "true", true);
log_init("log_test.log");
test_trimmed_len_normal();
test_trimmed_len_full();
test_trimmed_len_empty();
log_close();
}

View File

@@ -34,6 +34,8 @@ static MQZ_TERM_AUTHORITY mqhtpass_terminate;
#define HTPASSWD_FILE "/etc/mqm/mq.htpasswd"
#define NAME "MQ Advanced for Developers custom authentication service"
static char *trim(char *s);
/**
* Initialization and entrypoint for the dynamically loaded
* authorization installable service. It registers the addresses of the
@@ -78,7 +80,7 @@ void MQENTRY MQStart(
{
log_infof("Initializing %s", NAME);
}
log_debugf("MQStart options=%s qmgr=%.*s", ((Options == MQZIO_SECONDARY) ? "Secondary" : "Primary"), trimmed_len(QMgrName, MQ_Q_MGR_NAME_LENGTH), QMgrName);
log_debugf("MQStart options=%s qmgr=%s", ((Options == MQZIO_SECONDARY) ? "Secondary" : "Primary"), trim(QMgrName));
if (!htpass_valid_file(HTPASSWD_FILE))
{
@@ -174,14 +176,11 @@ static void MQENTRY mqhtpass_authenticate_user_csp(
// Tell the queue manager to continue trying other authorization services, as they might have the user.
*pContinuation = MQZCI_CONTINUE;
log_debugf(
"User authentication failed due to invalid user. user=%.*s effuser=%.*s applname=%.*s csp_user=%s cc=%d reason=%d",
trimmed_len(pIdentityContext->UserIdentifier, MQ_USER_ID_LENGTH),
pIdentityContext->UserIdentifier,
trimmed_len(pApplicationContext->EffectiveUserID, MQ_USER_ID_LENGTH),
pApplicationContext->EffectiveUserID,
trimmed_len(pApplicationContext->ApplName, MQ_APPL_NAME_LENGTH),
pApplicationContext->ApplName,
csp_user,
"User authentication failed due to invalid user. user=%s effuser=%s applname=%s csp_user=%s cc=%d reason=%d",
trim(pIdentityContext->UserIdentifier),
trim(pApplicationContext->EffectiveUserID),
trim(pApplicationContext->ApplName),
trim(csp_user),
*pCompCode,
*pReason);
}
@@ -193,14 +192,11 @@ static void MQENTRY mqhtpass_authenticate_user_csp(
// Tell the queue manager to stop trying other authorization services.
*pContinuation = MQZCI_STOP;
log_debugf(
"User authentication failed due to invalid password. user=%.*s effuser=%.*s applname=%.*s csp_user=%s cc=%d reason=%d",
trimmed_len(pIdentityContext->UserIdentifier, MQ_USER_ID_LENGTH),
pIdentityContext->UserIdentifier,
trimmed_len(pApplicationContext->EffectiveUserID, MQ_USER_ID_LENGTH),
pApplicationContext->EffectiveUserID,
trimmed_len(pApplicationContext->ApplName, MQ_APPL_NAME_LENGTH),
pApplicationContext->ApplName,
csp_user,
"User authentication failed due to invalid password. user=%s effuser=%s applname=%s csp_user=%s cc=%d reason=%d",
trim(pIdentityContext->UserIdentifier),
trim(pApplicationContext->EffectiveUserID),
trim(pApplicationContext->ApplName),
trim(csp_user),
*pCompCode,
*pReason);
}
@@ -279,14 +275,11 @@ static void MQENTRY mqhtpass_authenticate_user(
else
{
log_debugf(
"User authentication failed user=%.*s effuser=%.*s applname=%.*s cspuser=%s cc=%d reason=%d",
trimmed_len(pIdentityContext->UserIdentifier, MQ_USER_ID_LENGTH),
pIdentityContext->UserIdentifier,
trimmed_len(pApplicationContext->EffectiveUserID, MQ_USER_ID_LENGTH),
pApplicationContext->EffectiveUserID,
trimmed_len(pApplicationContext->ApplName, MQ_APPL_NAME_LENGTH),
pApplicationContext->ApplName,
spuser,
"User authentication failed user=%s effuser=%s applname=%s cspuser=%s cc=%d reason=%d",
trim(pIdentityContext->UserIdentifier),
trim(pApplicationContext->EffectiveUserID),
trim(pApplicationContext->ApplName),
trim(spuser),
*pCompCode,
*pReason);
}
@@ -340,3 +333,18 @@ static void MQENTRY mqhtpass_terminate(
*pReason = MQRC_NONE;
}
/**
* Remove trailing spaces from a string.
*/
static char *trim(char *s)
{
int i;
for (i = strlen(s) - 1; i >= 0; i--)
{
if (s[i] == ' ')
s[i] = 0;
else
break;
}
return s;
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2022
© Copyright IBM Corporation 2017, 2020
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,24 +18,22 @@ limitations under the License.
package main
import (
"context"
"fmt"
"os"
"os/exec"
"os/signal"
"strings"
"github.com/ibm-messaging/mq-container/pkg/name"
)
func queueManagerHealthy(ctx context.Context) (bool, error) {
func queueManagerHealthy() (bool, error) {
name, err := name.GetQueueManagerName()
if err != nil {
return false, err
}
// Specify the queue manager name, just in case someone's created a second queue manager
// #nosec G204
cmd := exec.CommandContext(ctx, "dspmq", "-n", "-m", name)
cmd := exec.Command("dspmq", "-n", "-m", name)
// Run the command and wait for completion
out, err := cmd.CombinedOutput()
fmt.Printf("%s", out)
@@ -49,20 +47,13 @@ func queueManagerHealthy(ctx context.Context) (bool, error) {
return true, nil
}
func doMain() int {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
defer cancel()
healthy, err := queueManagerHealthy(ctx)
func main() {
healthy, err := queueManagerHealthy()
if err != nil {
return 2
os.Exit(2)
}
if !healthy {
return 1
os.Exit(1)
}
return 0
}
func main() {
os.Exit(doMain())
os.Exit(0)
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2023
© Copyright IBM Corporation 2017, 2019
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,59 +18,44 @@ limitations under the License.
package main
import (
"context"
"fmt"
"net"
"os"
"os/signal"
"github.com/ibm-messaging/mq-container/internal/ready"
"github.com/ibm-messaging/mq-container/pkg/name"
)
func doMain() int {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
defer cancel()
func main() {
// Check if runmqserver has indicated that it's finished configuration
r, err := ready.Check()
if !r || err != nil {
return 1
os.Exit(1)
}
name, err := name.GetQueueManagerName()
if err != nil {
fmt.Println(err)
return 1
os.Exit(1)
}
// Check if the queue manager has a running listener
status, err := ready.Status(ctx, name)
if err != nil {
return 1
}
switch status {
case ready.StatusActiveQM:
if active, _ := ready.IsRunningAsActiveQM(name); active {
conn, err := net.Dial("tcp", "127.0.0.1:1414")
if err != nil {
fmt.Println(err)
return 1
os.Exit(1)
}
err = conn.Close()
if err != nil {
fmt.Println(err)
}
return 0
case ready.StatusStandbyQM:
} else if standby, _ := ready.IsRunningAsStandbyQM(name); standby {
fmt.Printf("Detected queue manager running in standby mode")
return 10
case ready.StatusReplicaQM:
os.Exit(10)
} else if replica, _ := ready.IsRunningAsReplicaQM(name); replica {
fmt.Printf("Detected queue manager running in replica mode")
return 20
default:
return 1
os.Exit(20)
} else {
os.Exit(1)
}
}
func main() {
os.Exit(doMain())
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2021, 2022
© Copyright IBM Corporation 2021
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,24 +18,22 @@ limitations under the License.
package main
import (
"context"
"fmt"
"os"
"os/exec"
"os/signal"
"strings"
"github.com/ibm-messaging/mq-container/pkg/name"
)
func queueManagerStarted(ctx context.Context) (bool, error) {
func queueManagerStarted() (bool, error) {
name, err := name.GetQueueManagerName()
if err != nil {
return false, err
}
// Specify the queue manager name, just in case someone's created a second queue manager
// #nosec G204
cmd := exec.CommandContext(ctx, "dspmq", "-n", "-m", name)
cmd := exec.Command("dspmq", "-n", "-m", name)
// Run the command and wait for completion
out, err := cmd.CombinedOutput()
if err != nil {
@@ -48,20 +46,13 @@ func queueManagerStarted(ctx context.Context) (bool, error) {
return true, nil
}
func doMain() int {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
defer cancel()
started, err := queueManagerStarted(ctx)
func main() {
started, err := queueManagerStarted()
if err != nil {
return 2
os.Exit(2)
}
if !started {
return 1
os.Exit(1)
}
return 0
}
func main() {
os.Exit(doMain())
os.Exit(0)
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2023
© Copyright IBM Corporation 2018, 2021
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ import (
"fmt"
"io/ioutil"
"os"
"strings"
"syscall"
"github.com/ibm-messaging/mq-container/internal/htpasswd"
@@ -31,20 +30,7 @@ import (
var log *logger.Logger
func getLogFormat() string {
logFormat := strings.ToLower(strings.TrimSpace(os.Getenv("MQ_LOGGING_CONSOLE_FORMAT")))
//old-style env var is used.
if logFormat == "" {
logFormat = strings.ToLower(strings.TrimSpace(os.Getenv("LOG_FORMAT")))
}
if logFormat != "" && (logFormat == "basic" || logFormat == "json") {
return logFormat
} else {
//this is the case where value is either empty string or set to something other than "basic"/"json"
logFormat = "basic"
}
return logFormat
return os.Getenv("LOG_FORMAT")
}
func getDebug() bool {

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2023
© Copyright IBM Corporation 2017, 2021
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -59,20 +59,7 @@ func logTermination(args ...interface{}) {
}
func getLogFormat() string {
logFormat := strings.ToLower(strings.TrimSpace(os.Getenv("MQ_LOGGING_CONSOLE_FORMAT")))
//old-style env var is used.
if logFormat == "" {
logFormat = strings.ToLower(strings.TrimSpace(os.Getenv("LOG_FORMAT")))
}
if logFormat != "" && (logFormat == "basic" || logFormat == "json") {
return logFormat
} else {
//this is the case where value is either empty string or set to something other than "basic"/"json"
logFormat = "basic"
}
return logFormat
return os.Getenv("LOG_FORMAT")
}
// formatBasic formats a log message parsed from JSON, as "basic" text
@@ -95,94 +82,6 @@ func formatBasic(obj map[string]interface{}) string {
}
// Convert time zone information from some logs (e.g. Liberty) for consistency
obj["ibm_datetime"] = strings.Replace(obj["ibm_datetime"].(string), "+0000", "Z", 1)
// Escape any new-line characters, so that we don't get multi-line messages messing up the output
obj["message"] = strings.ReplaceAll(obj["message"].(string), "\n", "\\n")
if obj["type"] != nil && (obj["type"] == "liberty_trace") {
timeStamp := obj["ibm_datetime"]
threadID := ""
srtModuleName := ""
logLevel := ""
ibmClassName := ""
srtIbmClassName := ""
ibmMethodName := ""
message := ""
if obj["loglevel"] != nil {
//threadID is captured below
if obj["ibm_threadId"] != nil {
threadID = obj["ibm_threadId"].(string)
}
//logLevel character to be mirrored in console web server logging is decided below
logLevelTmp := obj["loglevel"].(string)
switch logLevelTmp {
case "AUDIT":
logLevel = "A"
case "INFO":
logLevel = "I"
case "EVENT":
logLevel = "1"
case "ENTRY":
logLevel = ">"
case "EXIT":
logLevel = "<"
case "FINE":
logLevel = "1"
case "FINER":
logLevel = "2"
case "FINEST":
logLevel = "3"
default:
logLevel = string(logLevelTmp[0])
}
//This is a 13 characters string present in extracted out of module node
if obj["module"] != nil {
srtModuleNameArr := strings.Split(obj["module"].(string), ".")
arrLen := len(srtModuleNameArr)
srtModuleName = srtModuleNameArr[arrLen-1]
if len(srtModuleName) > 13 {
srtModuleName = srtModuleName[0:13]
}
}
if obj["ibm_className"] != nil {
ibmClassName = obj["ibm_className"].(string)
//A 13 character string is extracted from class name. This is required for FINE, FINER & FINEST log lines
ibmClassNameArr := strings.Split(ibmClassName, ".")
arrLen := len(ibmClassNameArr)
srtIbmClassName = ibmClassNameArr[arrLen-1]
if len(srtModuleName) > 13 {
srtIbmClassName = srtIbmClassName[0:13]
}
}
if obj["ibm_methodName"] != nil {
ibmMethodName = obj["ibm_methodName"].(string)
}
if obj["message"] != nil {
message = obj["message"].(string)
}
//For AUDIT & INFO logging
if logLevel == "A" || logLevel == "I" {
return fmt.Sprintf("%s %s %-13s %s %s %s %s\n", timeStamp, threadID, srtModuleName, logLevel, ibmClassName, ibmMethodName, message)
}
//For EVENT logLevel
if logLevelTmp == "EVENT" {
return fmt.Sprintf("%s %s %-13s %s %s\n", timeStamp, threadID, srtModuleName, logLevel, message)
}
//For ENTRY & EXIT
if logLevel == ">" || logLevel == "<" {
return fmt.Sprintf("%s %s %-13s %s %s %s\n", timeStamp, threadID, srtModuleName, logLevel, ibmMethodName, message)
}
//For deeper log levels
if logLevelTmp == "FINE" || logLevel == "2" || logLevel == "3" {
return fmt.Sprintf("%s %s %-13s %s %s %s %s\n", timeStamp, threadID, srtIbmClassName, logLevel, ibmClassName, ibmMethodName, message)
}
}
}
return fmt.Sprintf("%s %s\n", obj["ibm_datetime"], obj["message"])
}
@@ -233,11 +132,6 @@ func configureLogger(name string) (mirrorFunc, error) {
return nil, err
}
return func(msg string, isQMLog bool) bool {
arrLoggingConsoleExcludeIds := strings.Split(strings.ToUpper(os.Getenv("MQ_LOGGING_CONSOLE_EXCLUDE_ID")), ",")
if isExcludedMsgIdPresent(msg, arrLoggingConsoleExcludeIds) {
//If excluded id is present do not mirror it, return back
return false
}
// Check if the message is JSON
if len(msg) > 0 && msg[0] == '{' {
obj, err := processLogMessage(msg)
@@ -262,11 +156,6 @@ func configureLogger(name string) (mirrorFunc, error) {
return nil, err
}
return func(msg string, isQMLog bool) bool {
arrLoggingConsoleExcludeIds := strings.Split(strings.ToUpper(os.Getenv("MQ_LOGGING_CONSOLE_EXCLUDE_ID")), ",")
if isExcludedMsgIdPresent(msg, arrLoggingConsoleExcludeIds) {
//If excluded id is present do not mirror it, return back
return false
}
// Check if the message is JSON
if len(msg) > 0 && msg[0] == '{' {
// Parse the JSON message, and print a simplified version
@@ -277,7 +166,7 @@ func configureLogger(name string) (mirrorFunc, error) {
if err != nil {
log.Printf("Failed to unmarshall JSON in log message - %v", err)
} else {
fmt.Print(formatBasic(obj))
fmt.Printf(formatBasic(obj))
}
} else {
// The log being mirrored isn't JSON, so just print it.
@@ -309,16 +198,6 @@ func filterQMLogMessage(obj map[string]interface{}) bool {
return false
}
// Function to check if ids provided in MQ_LOGGING_CONSOLE_EXCLUDE_ID are present in given log line or not
func isExcludedMsgIdPresent(msg string, envExcludeIds []string) bool {
for _, id := range envExcludeIds {
if id != "" && strings.Contains(msg, strings.TrimSpace(id)) {
return true
}
}
return false
}
func logDiagnostics() {
if getDebug() {
log.Debug("--- Start Diagnostics ---")
@@ -360,73 +239,3 @@ func logDiagnostics() {
log.Debug("--- End Diagnostics ---")
}
}
// Returns the value of MQ_LOGGING_CONSOLE_SOURCE environment variable
func getMQLogConsoleSource() string {
return strings.ToLower(strings.TrimSpace(os.Getenv("MQ_LOGGING_CONSOLE_SOURCE")))
}
// Function to check if valid values are provided for environment variable MQ_LOGGING_CONSOLE_SOURCE. If not valid, main program throws a warning to console
func isLogConsoleSourceValid() bool {
mqLogSource := getMQLogConsoleSource()
retValue := false
//If nothing is set, we will mirror qmgr, so valid
if mqLogSource == "" {
return true
}
logConsoleSource := strings.Split(mqLogSource, ",")
//This will find out if the environment variable contains permitted values and is comma separated
for _, src := range logConsoleSource {
switch strings.TrimSpace(src) {
//If it is a permitted value, it is valid. Keep it as true, but dont return it. We may encounter something junk soon
case "qmgr", "web", "":
retValue = true
//If invalid entry arrives in-between/anywhere, just return false, there is no turning back
default:
return false
}
}
return retValue
}
// To check which all logs have to be mirrored
func checkLogSourceForMirroring(source string) bool {
logsrcs := getMQLogConsoleSource()
//Nothing set, this is when we mirror qmgr
if logsrcs == "" {
if source == "qmgr" {
return true
} else {
return false
}
}
//Split the csv environment value so that we get an accurate comparison instead of a contains() check
logSrcArr := strings.Split(logsrcs, ",")
//Iterate through the array to decide on mirroring
for _, arr := range logSrcArr {
switch strings.TrimSpace(arr) {
case "qmgr":
//If value of source is qmgr and it exists in environment variable, mirror qmgr logs
if source == "qmgr" {
return true
}
case "web":
//If value of source is web and it exists in environment variable, and mirror web logs
if source == "web" {
//If older environment variable is set make sure to print appropriate message
if os.Getenv("MQ_ENABLE_EMBEDDED_WEB_SERVER_LOG") != "" {
log.Println("Environment variable MQ_ENABLE_EMBEDDED_WEB_SERVER_LOG has now been replaced. Use MQ_LOGGING_CONSOLE_SOURCE instead.")
}
return true
}
}
}
return false
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2020, 2023
© Copyright IBM Corporation 2020
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package main
import (
"encoding/json"
"fmt"
"os"
"strings"
"testing"
)
@@ -54,86 +53,3 @@ func TestFormatBasic(t *testing.T) {
})
}
}
// This test covers for functions isLogConsoleSourceValid() & checkLogSourceForMirroring()
var mqLogSourcesTests = []struct {
testNum int
logsrc string
exptValid bool
exptQmgrSrc bool
exptWebSrc bool
}{
{1, "qmgr,web", true, true, true},
{2, "qmgr", true, true, false},
{3, "web,qmgr", true, true, true},
{4, "web", true, false, true},
{5, " ", true, true, false},
{6, "QMGR,WEB", true, true, true},
{7, "qmgr, ", true, true, false},
{8, "qmgr , web", true, true, true},
{9, "qmgr,dummy", false, true, false},
{10, "fake,dummy", false, false, false},
{11, "qmgr,fake,dummy", false, true, false},
{12, "fake,dummy,web", false, false, true},
{13, "true", false, false, false},
{14, "false", false, false, false},
{15, "", true, true, false},
}
func TestLoggingConsoleSourceInputs(t *testing.T) {
for _, mqlogsrctest := range mqLogSourcesTests {
err := os.Setenv("MQ_LOGGING_CONSOLE_SOURCE", mqlogsrctest.logsrc)
if err != nil {
t.Error(err)
}
isValid := isLogConsoleSourceValid()
if isValid != mqlogsrctest.exptValid {
t.Errorf("Expected return value from isLogConsoleSourceValid() is %v for MQ_LOGGING_CONSOLE_SOURCE='%v', got %v\n", mqlogsrctest.exptValid, mqlogsrctest.logsrc, isValid)
}
isLogSrcQmgr := checkLogSourceForMirroring("qmgr")
if isLogSrcQmgr != mqlogsrctest.exptQmgrSrc {
t.Errorf("Expected return value from checkLogSourceForMirroring() is %v for MQ_LOGGING_CONSOLE_SOURCE='%v', got %v\n", mqlogsrctest.exptQmgrSrc, mqlogsrctest.logsrc, isLogSrcQmgr)
}
isLogSrcWeb := checkLogSourceForMirroring("web")
if isLogSrcWeb != mqlogsrctest.exptWebSrc {
t.Errorf("Expected return value from checkLogSourceForMirroring() is %v for MQ_LOGGING_CONSOLE_SOURCE='%v', got %v\n", mqlogsrctest.exptWebSrc, mqlogsrctest.logsrc, isLogSrcWeb)
}
}
}
// This test covers for function isExcludedMsgIdPresent()
var mqExcludeIDTests = []struct {
testNum int
exculdeIDsArr []string
expectedRetVal bool
logEntry string
}{
{
1,
[]string{"AMQ5051I", "AMQ5037I", "AMQ5975I"},
true,
"{\"ibm_messageId\":\"AMQ5051I\",\"ibm_arithInsert1\":0,\"ibm_arithInsert2\":1,\"message\":\"AMQ5051I: The queue manager task 'AUTOCONFIG' has started.\"}",
},
{
2,
[]string{"AMQ5975I", "AMQ5037I"},
false,
"{\"ibm_messageId\":\"AMQ5051I\",\"ibm_arithInsert1\":0,\"ibm_arithInsert2\":1,\"message\":\"AMQ5051I: The queue manager task 'AUTOCONFIG' has started.\"}",
},
{
3,
[]string{""},
false,
"{\"ibm_messageId\":\"AMQ5051I\",\"ibm_arithInsert1\":0,\"ibm_arithInsert2\":1,\"message\":\"AMQ5051I: The queue manager task 'AUTOCONFIG' has started.\"}",
},
}
func TestIsExcludedMsgIDPresent(t *testing.T) {
for _, excludeIDTest := range mqExcludeIDTests {
retVal := isExcludedMsgIdPresent(excludeIDTest.logEntry, excludeIDTest.exculdeIDsArr)
if retVal != excludeIDTest.expectedRetVal {
t.Errorf("%v. Expected return value from isExcludedMsgIdPresent() is %v for MQ_LOGGING_CONSOLE_EXCLUDE_ID='%v', got %v\n",
excludeIDTest.testNum, excludeIDTest.expectedRetVal, excludeIDTest.exculdeIDsArr, retVal)
}
}
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2023
© Copyright IBM Corporation 2017, 2021
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@ import (
"os"
"sync"
"github.com/ibm-messaging/mq-container/internal/fips"
"github.com/ibm-messaging/mq-container/internal/ha"
"github.com/ibm-messaging/mq-container/internal/metrics"
"github.com/ibm-messaging/mq-container/internal/ready"
@@ -145,9 +144,6 @@ func doMain() error {
// Print out versioning information
logVersionInfo()
// Determine FIPS compliance level
fips.ProcessFIPSType(log)
keyLabel, defaultCmsKeystore, defaultP12Truststore, err := tls.ConfigureDefaultTLSKeystores()
if err != nil {
logTermination(err)
@@ -160,11 +156,6 @@ func doMain() error {
return err
}
//Validate MQ_LOG_CONSOLE_SOURCE variable
if !isLogConsoleSourceValid() {
log.Println("One or more invalid value is provided for MQ_LOGGING_CONSOLE_SOURCE. Allowed values are 'qmgr' & 'web' in csv format")
}
err = postInit(name, keyLabel, defaultP12Truststore)
if err != nil {
logTermination(err)
@@ -179,9 +170,6 @@ func doMain() error {
}
}
// Post FIPS initialization processing
fips.PostInit(log)
enableTraceCrtmqm := os.Getenv("MQ_ENABLE_TRACE_CRTMQM")
if enableTraceCrtmqm == "true" || enableTraceCrtmqm == "1" {
err = startMQTrace()
@@ -215,24 +203,17 @@ func doMain() error {
log.Debug("Cancel log mirroring")
cancelMirror()
}()
//For mirroring mq system logs and qm logs, if environment variable is set
if checkLogSourceForMirroring("qmgr") {
//Mirror MQ system logs
_, err = mirrorSystemErrorLogs(ctx, &wg, mf)
if err != nil {
logTermination(err)
return err
}
//Mirror queue manager logs
_, err = mirrorQueueManagerErrorLogs(ctx, &wg, name, newQM, mf)
if err != nil {
logTermination(err)
return err
}
// TODO: Use the error channel
_, err = mirrorSystemErrorLogs(ctx, &wg, mf)
if err != nil {
logTermination(err)
return err
}
_, err = mirrorQueueManagerErrorLogs(ctx, &wg, name, newQM, mf)
if err != nil {
logTermination(err)
return err
}
if *devFlag {
_, err = mirrorHTPasswdLogs(ctx, &wg, name, newQM, mf)
if err != nil {
@@ -240,12 +221,10 @@ func doMain() error {
return err
}
}
//For mirroring web server logs if source variable is set
if checkLogSourceForMirroring("web") {
// Always log from the start of the web server messages.log, as
// Liberty resets it.
_, err = mirrorWebServerLogs(ctx, &wg, name, true, mf)
// Recommended to use this option in conjunction with setting WLP_LOGGING_MESSAGE_FORMAT=JSON
mirrorWebLog := os.Getenv("MQ_ENABLE_EMBEDDED_WEB_SERVER_LOG")
if mirrorWebLog == "true" || mirrorWebLog == "1" {
_, err = mirrorWebServerLogs(ctx, &wg, name, newQM, mf)
if err != nil {
logTermination(err)
return err

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2023
© Copyright IBM Corporation 2018, 2019
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package main
import (
"os"
"github.com/ibm-messaging/mq-container/internal/fips"
"github.com/ibm-messaging/mq-container/internal/tls"
)
@@ -26,15 +25,6 @@ import (
func postInit(name, keyLabel string, p12Truststore tls.KeyStoreData) error {
enableWebServer := os.Getenv("MQ_ENABLE_EMBEDDED_WEB_SERVER")
if enableWebServer == "true" || enableWebServer == "1" {
// Enable FIPS for MQ Web Server if asked for.
if fips.IsFIPSEnabled() {
err := configureFIPSWebServer(p12Truststore)
if err != nil {
return err
}
}
// Configure the web server (if enabled)
webKeystore, err := configureWebServer(keyLabel, p12Truststore)
if err != nil {
@@ -45,7 +35,6 @@ func postInit(name, keyLabel string, p12Truststore tls.KeyStoreData) error {
if len(p12Truststore.TrustedCerts) == 0 {
webTruststoreRef = "MQWebKeyStore"
}
// Start the web server, in the background (if installed)
// WARNING: No error handling or health checking available for the web server
go func() {

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2023
© Copyright IBM Corporation 2017, 2020
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@ limitations under the License.
package main
import (
"context"
"fmt"
"io/ioutil"
"os"
@@ -55,36 +54,23 @@ func createDirStructure() error {
func createQueueManager(name string, devMode bool) (bool, error) {
log.Printf("Creating queue manager %v", name)
// Run 'dspmqinf' to check if 'mqs.ini' configuration file exists
// If command succeeds, the queue manager (or standby queue manager) has already been created
_, _, err := command.Run("dspmqinf", name)
if err == nil {
log.Printf("Detected existing queue manager %v", name)
return false, nil
}
mounts, err := containerruntime.GetMounts()
if err != nil {
log.Printf("Error getting mounts for queue manager")
return false, err
}
dataDir := getQueueManagerDataDir(mounts, name)
// Run 'dspmqinf' to check if 'mqs.ini' configuration file exists
// If command succeeds, the queue manager (or standby queue manager) has already been created
_, _, err = command.Run("dspmqinf", name)
if err == nil {
log.Printf("Detected existing queue manager %v", name)
// Check if MQ_QMGR_LOG_FILE_PAGES matches the value set in qm.ini
lfp := os.Getenv("MQ_QMGR_LOG_FILE_PAGES")
if lfp != "" {
qmIniBytes, err := readQMIni(dataDir)
if err != nil {
log.Printf("Error reading qm.ini : %v", err)
return false, err
}
if !validateLogFilePageSetting(qmIniBytes, lfp) {
log.Println("Warning: the value of MQ_QMGR_LOG_FILE_PAGES does not match the value of 'LogFilePages' in the qm.ini. This setting cannot be altered after Queue Manager creation.")
}
}
return false, nil
}
// Check if 'qm.ini' configuration file exists for the queue manager
// TODO : handle possible race condition - use a file lock?
dataDir := getQueueManagerDataDir(mounts, name)
_, err = os.Stat(filepath.Join(dataDir, "qm.ini"))
if err != nil {
// If 'qm.ini' is not found - run 'crtmqm' to create a new queue manager
@@ -109,25 +95,6 @@ func createQueueManager(name string, devMode bool) (bool, error) {
return true, nil
}
//readQMIni reads the qm.ini file and returns it as a byte array
//This function is specific to comply with the nosec.
func readQMIni(dataDir string) ([]byte, error) {
qmgrDir := filepath.Join(dataDir, "qm.ini")
// #nosec G304 - qmgrDir filepath is derived from dspmqinf
iniFileBytes, err := ioutil.ReadFile(qmgrDir)
if err != nil {
return nil, err
}
return iniFileBytes, err
}
//validateLogFilePageSetting validates if the specified logFilePage number is equal to the existing value in the qm.ini
func validateLogFilePageSetting(iniFileBytes []byte, logFilePages string) bool {
lfpString := "LogFilePages=" + logFilePages
qminiConfigStr := string(iniFileBytes)
return strings.Contains(qminiConfigStr, lfpString)
}
func updateCommandLevel() error {
level, ok := os.LookupEnv("MQ_CMDLEVEL")
if ok && level != "" {
@@ -164,18 +131,17 @@ func startQueueManager(name string) error {
func stopQueueManager(name string) error {
log.Println("Stopping queue manager")
qmGracePeriod := os.Getenv("MQ_GRACE_PERIOD")
status, err := ready.Status(context.Background(), name)
isStandby, err := ready.IsRunningAsStandbyQM(name)
if err != nil {
log.Printf("Error getting status for queue manager %v: %v", name, err.Error())
return err
}
isStandby := status.StandbyQM()
args := []string{"-w", "-r", "-tp", qmGracePeriod, name}
if os.Getenv("MQ_MULTI_INSTANCE") == "true" {
if isStandby {
args = []string{"-x", name}
} else {
args = []string{"-s", "-w", "-tp", qmGracePeriod, name}
args = []string{"-s", "-w", "-r", "-tp", qmGracePeriod, name}
}
}
out, rc, err := command.Run("endmqm", args...)
@@ -271,14 +237,6 @@ func getCreateQueueManagerArgs(mounts map[string]string, name string, devMode bo
if _, ok := mounts["/mnt/mqm-data"]; ok {
args = append(args, "-md", "/mnt/mqm-data/qmgrs")
}
if os.Getenv("MQ_QMGR_LOG_FILE_PAGES") != "" {
_, err = strconv.Atoi(os.Getenv("MQ_QMGR_LOG_FILE_PAGES"))
if err != nil {
log.Printf("Error processing MQ_QMGR_LOG_FILE_PAGES, the default value for LogFilePages will be used. Err: %v", err)
} else {
args = append(args, "-lf", os.Getenv("MQ_QMGR_LOG_FILE_PAGES"))
}
}
args = append(args, name)
return args
}

View File

@@ -1,86 +0,0 @@
/*
© Copyright IBM Corporation 2023
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"io/ioutil"
"testing"
)
func Test_validateLogFilePageSetting(t *testing.T) {
type args struct {
iniFilePath string
isValid bool
logFilePagesValue string
}
tests := []struct {
name string
args args
}{
{
name: "TestLogFilePages1",
args: args{
iniFilePath: "./test-files/testvalidateLogFilePages_1.ini",
isValid: true,
logFilePagesValue: "1235",
},
},
{
name: "TestLogFilePages2",
args: args{
iniFilePath: "./test-files/testvalidateLogFilePages_2.ini",
isValid: true,
logFilePagesValue: "2224",
},
},
{
name: "TestLogFilePages3",
args: args{
iniFilePath: "./test-files/testvalidateLogFilePages_3.ini",
isValid: false,
logFilePagesValue: "1235",
},
},
{
name: "TestLogFilePages4",
args: args{
iniFilePath: "./test-files/testvalidateLogFilePages_4.ini",
isValid: false,
logFilePagesValue: "1235",
},
},
{
name: "TestLogFilePages5",
args: args{
iniFilePath: "./test-files/testvalidateLogFilePages_5.ini",
isValid: false,
logFilePagesValue: "1235",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
iniFileBytes, err := ioutil.ReadFile(tt.args.iniFilePath)
if err != nil {
t.Fatal(err)
}
validate := validateLogFilePageSetting(iniFileBytes, tt.args.logFilePagesValue)
if validate != tt.args.isValid {
t.Fatalf("Expected ini file validation output to be %v got %v", tt.args.isValid, validate)
}
})
}
}

View File

@@ -1,9 +0,0 @@
ExitPath:
ExitsDefaultPath=/mnt/mqm/data/exits
ExitsDefaultPath64=/mnt/mqm/data/exits64
Log:
LogPrimaryFiles=3
LogSecondaryFiles=2
LogFilePages=1235
LogBufferPages=0
LogWriteIntegrity=TripleWrite

View File

@@ -1,9 +0,0 @@
ExitPath:
ExitsDefaultPath=/mnt/mqm/data/exits
ExitsDefaultPath64=/mnt/mqm/data/exits64
Log:
LogPrimaryFiles=3
LogSecondaryFiles=2
LogFilePages=2224
LogBufferPages=0
LogWriteIntegrity=TripleWrite

View File

@@ -1,9 +0,0 @@
ExitPath:
ExitsDefaultPath=/mnt/mqm/data/exits
ExitsDefaultPath64=/mnt/mqm/data/exits64
Log:
LogPrimaryFiles=3
LogSecondaryFiles=2
LogFilePages=6002
LogBufferPages=0
LogWriteIntegrity=TripleWrite

View File

@@ -1,8 +0,0 @@
ExitPath:
ExitsDefaultPath=/mnt/mqm/data/exits
ExitsDefaultPath64=/mnt/mqm/data/exits64
Log:
LogPrimaryFiles=3
LogSecondaryFiles=2
LogBufferPages=0
LogWriteIntegrity=TripleWrite

View File

@@ -1,8 +0,0 @@
ExitPath:
ExitsDefaultPath=/mnt/mqm/data/exits
ExitsDefaultPath64=/mnt/mqm/data/exits64
Log:
LogPrimaryFiles=3
LogSecondaryFiles=2
LogBufferPages=1235
LogWriteIntegrity=TripleWrite

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2022
© Copyright IBM Corporation 2018, 2020
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -197,25 +197,3 @@ func configureWebServer(keyLabel string, p12Truststore tls.KeyStoreData) (string
return webKeystore, err
}
// Configure FIPS mode for MQ Web Server
func configureFIPSWebServer(p12TrustStore tls.KeyStoreData) error {
var errOut error
// Need to update jvm.options file of MQ Web Server. We don't update the jvm.options file
// in /etc/mqm/web/installations/Installation1/servers/mqweb directory. Instead we update
// the one in /etc/mqm/web/installations/Installation1/servers/mqweb/configDropins/defaults.
// During runtime MQ Web Server merges the data from two files.
mqwebJvmOptsDir := "/etc/mqm/web/installations/Installation1/servers/mqweb/configDropins/defaults"
_, errOut = os.Stat(mqwebJvmOptsDir)
if errOut == nil {
// Update the jvm.options file using the data from template file. Tell the MQ Web Server
// use a FIPS provider by setting "-Dcom.ibm.jsse2.usefipsprovider=true" and then tell it
// use a specific FIPS provider by setting "Dcom.ibm.jsse2.usefipsProviderName=IBMJCEPlusFIPS".
errOut = mqtemplate.ProcessTemplateFile(mqwebJvmOptsDir+"/jvm.options.tpl",
mqwebJvmOptsDir+"/jvm.options", map[string]string{
"FipsProvider": "true",
"FipsProviderName": "IBMJCEPlusFIPS",
}, log)
}
return errOut
}

View File

@@ -1,6 +1,6 @@
###########################################################################################################################################################
# MQ_VERSION is the fully qualified MQ version number to build
MQ_VERSION ?= 9.3.2.1
MQ_VERSION ?= 9.3.0.4
###########################################################################################################################################################

7
docs/building.md Executable file → Normal file
View File

@@ -4,7 +4,7 @@
You need to have the following tools installed:
* [Docker](https://www.docker.com/) 17.06.1 or later, or [Podman](https://podman.io) 1.0 or later (Podman 4.1 on macOS).
* [Docker](https://www.docker.com/) 17.06.1 or later, or [Podman](https://podman.io) 1.0 or later (Podman 4.1 on macOS). If using Podman on macOS, the you need to be in "rootful" mode to allow the use of a network during builds. Run `podman machine init --rootful`.
* [GNU make](https://www.gnu.org/software/make/)
If you are working in the Windows Subsystem for Linux, follow [this guide by Microsoft to set up Docker](https://blogs.msdn.microsoft.com/commandline/2017/12/08/cross-post-wsl-interoperability-with-docker/) first.
@@ -34,7 +34,8 @@ MQ_ARCHIVE=mq-1.2.3.4.tar.gz MQ_VERSION=1.2.3.4 make build-advancedserver
**Note**: MQ 9.3 is the latest MQ version with MQ Long Term Support (LTS), as well as being the latest Continuous Delivery (CD) version. Therefore, to build build 9.3.0.X, follow the [instructions above for MQ 9.3](#building-mq-93-long-term-support-lts-and-continuous-delivery-cd).
However, if you wish to build the previous MQ LTS, use the [instructions](https://github.ibm.com/mq-cloudpak/mq-container/blob/v9.2.0.x-eus/docs/building.md#mq-long-term-support-lts) in the `v9.2.0.x-eus` branch.
However, if you wish to build the previous MQ LTS, use the [instructions](/../9.2.0.x/docs/building.md#mq-long-term-support-lts) in the `v9.2.0.x-eus` branch.
## Building a developer image
@@ -44,4 +45,4 @@ You can use the environment variable `MQ_ARCHIVE_DEV` to specify an alternative
## Installed components
This image includes the core MQ server, Java, language packs, GSKit, and web server. This is configured in the `mq-redux` build stage in `Dockerfile-server`.
This image includes the core MQ server, Java, language packs, GSKit, and web server. This is configured in the `Generate MQ package in INSTALLATION_DIR` section [here](../install-mq.sh), with the configured options being picked up at build time.

View File

@@ -34,7 +34,7 @@ Two channels are created, one for administration, the other for normal messaging
## Web Console
By default the MQ Advanced for Developers image will start the IBM MQ Web Console that allows you to administer your Queue Manager running on your container. When the web console has been started, you can access it by opening a web browser and navigating to `https://<Container IP>:9443/ibmmq/console`. Where `<Container IP>` is replaced by the IP address of your running container.
By default the MQ Advanced for Developers image will start the IBM MQ Web Console that allows you to administer your Queue Manager running on your container. When the web console has been started, you can access it by opening a web browser and navigating to https://<Container IP>:9443/ibmmq/console. Where <Container IP> is replaced by the IP address of your running container.
When you navigate to this page you may be presented with a security exception warning. This happens because, by default, the web console creates a self-signed certificate to use for the HTTPS operations. This certificate is not trusted by your browser and has an incorrect distinguished name.

View File

@@ -16,5 +16,5 @@ docker run \
--env LICENSE=accept \
--env MQ_QMGR_NAME=QM1 \
--detach \
ibm-mqadvanced-server:9.3.2.1-amd64
ibm-mqadvanced-server:9.3.0.4-amd64
```

View File

@@ -17,14 +17,14 @@ There are two main sets of tests:
The Docker tests can be run locally on a machine with Docker. For example:
```
make test-devserver
make test-advancedserver
make devserver
make advancedserver
```
You can specify the image to use directly by using the `MQ_IMAGE_ADVANCEDSERVER` or `MQ_IMAGE_DEVSERVER` variables, for example:
```
MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:9.3.2.1-amd64 make test-advancedserver
MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:9.3.0.4-amd64 make test-advancedserver
```
You can pass parameters to `go test` with an environment variable. For example, to run the "TestGoldenPath" test, run the following command:

View File

@@ -112,5 +112,3 @@ For example, if you have an identity certificate you wish to add with the label
This can be achieved by either mounting the directories or files into the container when you run it or by baking the files into the correct location in the image.
If you supply multiple identity certificates then the first label alphabetically will be chosen as the certificate to be used by the MQ Console and the default certificate for the queue manager. If you wish to use a different certificate on the queue manager then you can change the certificate to use at runtime by executing the MQSC command `ALTER QMGR CERTLABL('<newlabel>')`
It must be noted that queue manager certificate with a Subject Distinguished Name (DN) same as it's Issuer certificate (CA) is not supported. Certificates must have a unique Subject Distinguished Name.

View File

@@ -1,4 +1,4 @@
* © Copyright IBM Corporation 2019, 2022
* © Copyright IBM Corporation 2019
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,5 +16,4 @@
* Set the keystore location for the queue manager
ALTER QMGR SSLKEYR('{{ .SSLKeyR }}')
ALTER QMGR CERTLABL('{{ .CertificateLabel }}')
ALTER QMGR SSLFIPS({{ .SSLFips }})
REFRESH SECURITY(*) TYPE(SSL)

View File

@@ -6,9 +6,6 @@ NativeHALocalInstance:
{{ if .CipherSpec }}
CipherSpec={{ .CipherSpec }}
{{- end }}
{{ if .SSLFipsRequired }}
SSLFipsRequired={{ .SSLFipsRequired }}
{{- end }}
{{- end }}
NativeHAInstance:
Name={{ .NativeHAInstance0_Name }}

View File

@@ -1,6 +1,6 @@
#!/bin/bash
# -*- mode: sh -*-
# © Copyright IBM Corporation 2015, 2022
# © Copyright IBM Corporation 2015, 2021
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,7 +22,6 @@ test -f /usr/bin/yum && YUM=true || YUM=false
test -f /usr/bin/microdnf && MICRODNF=true || MICRODNF=false
test -f /usr/bin/rpm && RPM=true || RPM=false
test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false
CPU_ARCH=$(uname -m)
if ($UBUNTU); then
export DEBIAN_FRONTEND=noninteractive
@@ -30,7 +29,8 @@ if ($UBUNTU); then
# This ensures no unsupported code gets installed, and makes the build faster
source /etc/os-release
# Figure out the correct apt URL based on the CPU architecture
if [ "${CPU_ARCH}" == "x86_64" ]; then
CPU_ARCH=$(uname -p)
if [ ${CPU_ARCH} == "x86_64" ]; then
APT_URL="http://archive.ubuntu.com/ubuntu/"
else
APT_URL="http://ports.ubuntu.com/ubuntu-ports/"
@@ -41,22 +41,29 @@ if ($UBUNTU); then
echo "deb ${APT_URL} ${UBUNTU_CODENAME}-updates main restricted" >> /etc/apt/sources.list
echo "deb ${APT_URL} ${UBUNTU_CODENAME}-security main restricted" >> /etc/apt/sources.list
# Install additional packages required by MQ, this install process and the runtime scripts
EXTRA_DEBS="bash bc ca-certificates coreutils curl debianutils file findutils gawk grep libc-bin mount passwd procps sed tar util-linux"
# On ARM CPUs, there is no IBM JRE, so install another one
if [ "${CPU_ARCH}" == "aarch64" ]; then
EXTRA_DEBS="${EXTRA_DEBS} openjdk-8-jre"
fi
apt-get update
apt-get install -y --no-install-recommends ${EXTRA_DEBS}
apt-get install -y --no-install-recommends \
bash \
bc \
ca-certificates \
coreutils \
curl \
debianutils \
file \
findutils \
gawk \
grep \
libc-bin \
mount \
passwd \
procps \
sed \
tar \
util-linux
fi
if ($RPM); then
EXTRA_RPMS="bash bc ca-certificates file findutils gawk glibc-common grep ncurses-compat-libs passwd procps-ng sed shadow-utils tar util-linux which"
# On ARM CPUs, there is no IBM JRE, so install another one
if [ "${CPU_ARCH}" == "aarch64" ]; then
EXTRA_RPMS="${EXTRA_RPMS} java-1.8.0-openjdk-headless"
fi
# Install additional packages required by MQ, this install process and the runtime scripts
$YUM && yum -y install --setopt install_weak_deps=false ${EXTRA_RPMS}
$MICRODNF && microdnf --disableplugin=subscription-manager install ${EXTRA_RPMS}

View File

@@ -1,6 +1,6 @@
#!/bin/bash
# -*- mode: sh -*-
# © Copyright IBM Corporation 2015, 2023
# © Copyright IBM Corporation 2015, 2022
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,8 +21,43 @@ set -ex
test -f /usr/bin/rpm && RPM=true || RPM=false
test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false
# Download and extract the MQ unzippable server
DIR_TMP=/tmp/mq
mkdir -p ${DIR_TMP}
cd ${DIR_TMP}
curl --fail --location $MQ_URL | tar --extract --gunzip
ls -la ${DIR_TMP}
# Generate MQ package in INSTALLATION_DIR
export genmqpkg_inc32=0
export genmqpkg_incadm=1
export genmqpkg_incamqp=0
export genmqpkg_incams=1
export genmqpkg_inccbl=0
export genmqpkg_inccics=0
export genmqpkg_inccpp=0
export genmqpkg_incdnet=0
export genmqpkg_incjava=1
export genmqpkg_incjre=1
export genmqpkg_incman=0
export genmqpkg_incmqbc=0
export genmqpkg_incmqft=0
export genmqpkg_incmqsf=0
export genmqpkg_incmqxr=0
export genmqpkg_incnls=1
export genmqpkg_incras=1
export genmqpkg_incsamp=1
export genmqpkg_incsdk=0
export genmqpkg_inctls=1
export genmqpkg_incunthrd=0
export genmqpkg_incweb=1
export INSTALLATION_DIR=/opt/mqm
${DIR_TMP}/bin/genmqpkg.sh -b ${INSTALLATION_DIR}
ls -la ${INSTALLATION_DIR}
rm -rf ${DIR_TMP}
# Accept the MQ license
/opt/mqm/bin/mqlicense -accept
${INSTALLATION_DIR}/bin/mqlicense -accept
# Optional: Update the command prompt with the MQ version
$UBUNTU && echo "mq:$(dspmqver -b -f 2)" > /etc/debian_chroot

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2022
© Copyright IBM Corporation 2017, 2020
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ limitations under the License.
package command
import (
"context"
"fmt"
"os/exec"
)
@@ -28,13 +27,9 @@ import (
// Do not use this function to run shell built-ins (like "cd"), because
// the error handling works differently
func Run(name string, arg ...string) (string, int, error) {
return RunContext(context.Background(), name, arg...)
}
func RunContext(ctx context.Context, name string, arg ...string) (string, int, error) {
// Run the command and wait for completion
// #nosec G204
cmd := exec.CommandContext(ctx, name, arg...)
cmd := exec.Command(name, arg...)
out, err := cmd.CombinedOutput()
rc := cmd.ProcessState.ExitCode()
if err != nil {

View File

@@ -1,96 +0,0 @@
/*
© Copyright IBM Corporation 2023
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fips
import (
"os"
"strings"
"github.com/ibm-messaging/mq-container/internal/command"
"github.com/ibm-messaging/mq-container/pkg/logger"
)
var (
FIPSEnabledType int
)
// FIPS has been turned off either because OS is not FIPS enabled or
// MQ_ENABLE_FIPS environment variable is set to "false"
const FIPS_ENABLED_OFF = 0
// FIPS is turned ON
const FIPS_ENABLED_ON = 1
// FIPS enabled at operating system level
const FIPS_ENABLED_PLATFORM = 1
// FIPS enabled via environment variable
const FIPS_ENABLED_ENV_VAR = 2
// Get FIPS enabled type.
func ProcessFIPSType(logs *logger.Logger) {
// Run "sysctl crypto.fips_enabled" command to determine if FIPS has been enabled
// on OS.
FIPSEnabledType = FIPS_ENABLED_OFF
out, _, err := command.Run("sysctl", "crypto.fips_enabled")
if err == nil {
// Check the output of the command for expected output
if strings.Contains(out, "crypto.fips_enabled = 1") {
FIPSEnabledType = FIPS_ENABLED_PLATFORM
}
}
// Check if we have been asked to override FIPS cryptography
fipsOverride, fipsOverrideSet := os.LookupEnv("MQ_ENABLE_FIPS")
if fipsOverrideSet {
if strings.EqualFold(fipsOverride, "false") || strings.EqualFold(fipsOverride, "0") {
FIPSEnabledType = FIPS_ENABLED_OFF
} else if strings.EqualFold(fipsOverride, "true") || strings.EqualFold(fipsOverride, "1") {
// This is the case where OS may or may not be FIPS compliant but we have been asked
// to run MQ queue manager, web server and Native HA in FIPS mode. This case can also
// be used when running docker tests. If FIPS is enabled on host, then don't modify
// the original value.
if FIPSEnabledType != FIPS_ENABLED_PLATFORM {
FIPSEnabledType = FIPS_ENABLED_ENV_VAR
}
} else if strings.EqualFold(fipsOverride, "auto") {
// This is the default case. Leave it to the OS default as determined above.
} else {
// We don't recognise the value specified. Log a warning and carry on.
if logs != nil {
logs.Printf("Invalid value '%s' was specified for MQ_ENABLE_FIPS. The value has been ignored.\n", fipsOverride)
}
}
}
}
func IsFIPSEnabled() bool {
return FIPSEnabledType > FIPS_ENABLED_OFF
}
// Log a message on the console to indicate FIPS certified
// cryptography being used.
func PostInit(log *logger.Logger) {
message := "FIPS cryptography is not enabled."
if FIPSEnabledType == FIPS_ENABLED_PLATFORM {
message = "FIPS cryptography is enabled. FIPS cryptography setting on the host is 'true'."
} else if FIPSEnabledType == FIPS_ENABLED_ENV_VAR {
message = "FIPS cryptography is enabled. FIPS cryptography setting on the host is 'false'."
}
log.Println(message)
}

View File

@@ -1,65 +0,0 @@
/*
© Copyright IBM Corporation 2022
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package keystore contains code to create and update keystores
package fips
import (
"fmt"
"os"
"testing"
)
func TestEnableFIPSAuto(t *testing.T) {
ProcessFIPSType(nil)
// Test default "auto"
fipsType := IsFIPSEnabled()
if fipsType {
t.Errorf("Expected FIPS OFF but got %v\n", fipsType)
}
}
func TestEnableFIPSTrue(t *testing.T) {
// Test MQ_ENABLE_FIPS=true
os.Setenv("MQ_ENABLE_FIPS", "true")
fmt.Println(os.Getenv("MQ_ENABLE_FIPS"))
ProcessFIPSType(nil)
fipsType := IsFIPSEnabled()
if !fipsType {
t.Errorf("Expected FIPS ON but got %v\n", fipsType)
}
}
func TestEnableFIPSFalse(t *testing.T) {
// Test MQ_ENABLE_FIPS=false
os.Setenv("MQ_ENABLE_FIPS", "false")
ProcessFIPSType(nil)
fipsType := IsFIPSEnabled()
if fipsType {
t.Errorf("Expected FIPS OFF but got %v\n", fipsType)
}
}
func TestEnableFIPSInvalid(t *testing.T) {
// Test MQ_ENABLE_FIPS with invalid value
os.Setenv("MQ_ENABLE_FIPS", "falseOff")
ProcessFIPSType(nil)
fipsType := IsFIPSEnabled()
if fipsType {
t.Errorf("Expected FIPS OFF but got %v\n", fipsType)
}
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2020, 2023
© Copyright IBM Corporation 2020, 2021
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ package ha
import (
"os"
"github.com/ibm-messaging/mq-container/internal/fips"
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
"github.com/ibm-messaging/mq-container/internal/tls"
"github.com/ibm-messaging/mq-container/pkg/logger"
@@ -58,13 +57,6 @@ func ConfigureNativeHA(log *logger.Logger) error {
if ok {
templateMap["CipherSpec"] = cipherSpec
}
// If FIPS is enabled, then set SSLFipsRequired to Yes
if fips.IsFIPSEnabled() {
templateMap["SSLFipsRequired"] = "Yes"
} else {
templateMap["SSLFipsRequired"] = "No"
}
}
err := mqtemplate.ProcessTemplateFile(templateFile, file, templateMap, log)

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2023
© Copyright IBM Corporation 2018, 2020
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@ import (
"strings"
"github.com/ibm-messaging/mq-container/internal/command"
"github.com/ibm-messaging/mq-container/internal/fips"
)
// KeyStore describes information about a keystore file
@@ -35,46 +34,36 @@ type KeyStore struct {
Password string
keyStoreType string
command string
fipsEnabled bool
}
// NewJKSKeyStore creates a new Java Key Store, managed by the runmqckm command
func NewJKSKeyStore(filename, password string) *KeyStore {
keyStore := &KeyStore{
return &KeyStore{
Filename: filename,
Password: password,
keyStoreType: "jks",
command: "/opt/mqm/bin/runmqckm",
fipsEnabled: fips.IsFIPSEnabled(),
}
return keyStore
}
// NewCMSKeyStore creates a new MQ CMS Key Store, managed by the runmqakm command
func NewCMSKeyStore(filename, password string) *KeyStore {
keyStore := &KeyStore{
return &KeyStore{
Filename: filename,
Password: password,
keyStoreType: "cms",
command: "/opt/mqm/bin/runmqakm",
fipsEnabled: fips.IsFIPSEnabled(),
}
return keyStore
}
// NewPKCS12KeyStore creates a new PKCS12 Key Store, managed by the runmqakm command
func NewPKCS12KeyStore(filename, password string) *KeyStore {
keyStore := &KeyStore{
return &KeyStore{
Filename: filename,
Password: password,
keyStoreType: "p12",
command: "/opt/mqm/bin/runmqakm",
fipsEnabled: fips.IsFIPSEnabled(),
}
return keyStore
}
// Create a key store, if it doesn't already exist
@@ -111,7 +100,7 @@ func (ks *KeyStore) Create() error {
}
// Create the keystore now we're sure it doesn't exist
out, _, err := command.Run(ks.command, "-keydb", "-create", ks.getFipsEnabledFlag(), "-type", ks.keyStoreType, "-db", ks.Filename, "-pw", ks.Password, "-stash")
out, _, err := command.Run(ks.command, "-keydb", "-create", "-type", ks.keyStoreType, "-db", ks.Filename, "-pw", ks.Password, "-stash")
if err != nil {
return fmt.Errorf("error running \"%v -keydb -create\": %v %s", ks.command, err, out)
}
@@ -126,7 +115,7 @@ func (ks *KeyStore) CreateStash() error {
_, err := os.Stat(stashFile)
if err != nil {
if os.IsNotExist(err) {
out, _, err := command.Run(ks.command, "-keydb", ks.getFipsEnabledFlag(), "-stashpw", "-type", ks.keyStoreType, "-db", ks.Filename, "-pw", ks.Password)
out, _, err := command.Run(ks.command, "-keydb", "-stashpw", "-type", ks.keyStoreType, "-db", ks.Filename, "-pw", ks.Password)
if err != nil {
return fmt.Errorf("error running \"%v -keydb -stashpw\": %v %s", ks.command, err, out)
}
@@ -138,7 +127,7 @@ func (ks *KeyStore) CreateStash() error {
// Import imports a certificate file in the keystore
func (ks *KeyStore) Import(inputFile, password string) error {
out, _, err := command.Run(ks.command, "-cert", "-import", ks.getFipsEnabledFlag(), "-file", inputFile, "-pw", password, "-target", ks.Filename, "-target_pw", ks.Password, "-target_type", ks.keyStoreType)
out, _, err := command.Run(ks.command, "-cert", "-import", "-file", inputFile, "-pw", password, "-target", ks.Filename, "-target_pw", ks.Password, "-target_type", ks.keyStoreType)
if err != nil {
return fmt.Errorf("error running \"%v -cert -import\": %v %s", ks.command, err, out)
}
@@ -147,7 +136,7 @@ func (ks *KeyStore) Import(inputFile, password string) error {
// CreateSelfSignedCertificate creates a self-signed certificate in the keystore
func (ks *KeyStore) CreateSelfSignedCertificate(label, dn, hostname string) error {
out, _, err := command.Run(ks.command, "-cert", "-create", ks.getFipsEnabledFlag(), "-db", ks.Filename, "-pw", ks.Password, "-label", label, "-dn", dn, "-san_dnsname", hostname, "-size 2048 -sig_alg sha256 -eku serverAuth")
out, _, err := command.Run(ks.command, "-cert", "-create", "-db", ks.Filename, "-pw", ks.Password, "-label", label, "-dn", dn, "-san_dnsname", hostname, "-size 2048 -sig_alg sha256 -eku serverAuth")
if err != nil {
return fmt.Errorf("error running \"%v -cert -create\": %v %s", ks.command, err, out)
}
@@ -156,7 +145,7 @@ func (ks *KeyStore) CreateSelfSignedCertificate(label, dn, hostname string) erro
// Add adds a CA certificate to the keystore
func (ks *KeyStore) Add(inputFile, label string) error {
out, _, err := command.Run(ks.command, "-cert", "-add", ks.getFipsEnabledFlag(), "-db", ks.Filename, "-type", ks.keyStoreType, "-pw", ks.Password, "-file", inputFile, "-label", label)
out, _, err := command.Run(ks.command, "-cert", "-add", "-db", ks.Filename, "-type", ks.keyStoreType, "-pw", ks.Password, "-file", inputFile, "-label", label)
if err != nil {
return fmt.Errorf("error running \"%v -cert -add\": %v %s", ks.command, err, out)
}
@@ -165,7 +154,7 @@ func (ks *KeyStore) Add(inputFile, label string) error {
// Add adds a CA certificate to the keystore
func (ks *KeyStore) AddNoLabel(inputFile string) error {
out, _, err := command.Run(ks.command, "-cert", "-add", ks.getFipsEnabledFlag(), "-db", ks.Filename, "-type", ks.keyStoreType, "-pw", ks.Password, "-file", inputFile)
out, _, err := command.Run(ks.command, "-cert", "-add", "-db", ks.Filename, "-type", ks.keyStoreType, "-pw", ks.Password, "-file", inputFile)
if err != nil {
return fmt.Errorf("error running \"%v -cert -add\": %v %s", ks.command, err, out)
}
@@ -174,7 +163,7 @@ func (ks *KeyStore) AddNoLabel(inputFile string) error {
// GetCertificateLabels returns the labels of all certificates in the key store
func (ks *KeyStore) GetCertificateLabels() ([]string, error) {
out, _, err := command.Run(ks.command, "-cert", "-list", ks.getFipsEnabledFlag(), "-type", ks.keyStoreType, "-db", ks.Filename, "-pw", ks.Password)
out, _, err := command.Run(ks.command, "-cert", "-list", "-type", ks.keyStoreType, "-db", ks.Filename, "-pw", ks.Password)
if err != nil {
return nil, fmt.Errorf("error running \"%v -cert -list\": %v %s", ks.command, err, out)
}
@@ -218,7 +207,7 @@ func (ks *KeyStore) RenameCertificate(from, to string) error {
// ListAllCertificates Lists all certificates in the keystore
func (ks *KeyStore) ListAllCertificates() ([]string, error) {
out, _, err := command.Run(ks.command, "-cert", "-list", ks.getFipsEnabledFlag(), "-type", ks.keyStoreType, "-db", ks.Filename, "-pw", ks.Password)
out, _, err := command.Run(ks.command, "-cert", "-list", "-type", ks.keyStoreType, "-db", ks.Filename, "-pw", ks.Password)
if err != nil {
return nil, fmt.Errorf("error running \"%v -cert -list\": %v %s", ks.command, err, out)
}
@@ -226,8 +215,6 @@ func (ks *KeyStore) ListAllCertificates() ([]string, error) {
var labels []string
for scanner.Scan() {
s := scanner.Text()
// Check for trusted certficates as well here as this method can
// be called for trusted store as well.
if strings.HasPrefix(s, "-") || strings.HasPrefix(s, "*-") || strings.HasPrefix(s, "!") {
s := strings.TrimLeft(s, "-*!")
labels = append(labels, strings.TrimSpace(s))
@@ -239,22 +226,3 @@ func (ks *KeyStore) ListAllCertificates() ([]string, error) {
}
return labels, nil
}
// Returns the FIPS flag. True if enabled else false
func (ks *KeyStore) IsFIPSEnabled() bool {
return ks.fipsEnabled
}
// Returns -fips option if FIPS is enabled otherwise empty string. Return value is used
// when running runmqakm/runmqckm commands.
func (ks *KeyStore) getFipsEnabledFlag() string {
var fipsEnabled string
if ks.fipsEnabled {
fipsEnabled = "-fips"
} else {
fipsEnabled = ""
}
return fipsEnabled
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2023
© Copyright IBM Corporation 2018, 2019
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -35,8 +35,8 @@ const (
var (
metricsEnabled = false
// #nosec G112 - this code is changing soon to use https.
// for now we will ignore the gosec.
// #nosec G112 - this needs investigation to find reasonable timeout.
// git-issue 233 to cover this..
metricsServer = &http.Server{Addr: ":" + defaultPort}
)
@@ -45,8 +45,8 @@ func GatherMetrics(qmName string, log *logger.Logger) {
// If running in standby mode - wait until the queue manager becomes active
for {
status, _ := ready.Status(context.Background(), qmName)
if status.ActiveQM() {
active, _ := ready.IsRunningAsActiveQM(qmName)
if active {
break
}
time.Sleep(requestTimeout * time.Second)

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2023
© Copyright IBM Corporation 2018, 2019
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ limitations under the License.
package ready
import (
"context"
"io/ioutil"
"os"
"strings"
@@ -68,38 +67,28 @@ func Check() (bool, error) {
return exists, nil
}
// Status returns an enum representing the current running status of the queue manager
func Status(ctx context.Context, name string) (QMStatus, error) {
out, _, err := command.RunContext(ctx, "dspmq", "-n", "-m", name)
if err != nil {
return StatusUnknown, err
}
if strings.Contains(string(out), "(RUNNING)") {
return StatusActiveQM, nil
}
if strings.Contains(string(out), "(RUNNING AS STANDBY)") {
return StatusStandbyQM, nil
}
if strings.Contains(string(out), "(REPLICA)") {
return StatusStandbyQM, nil
}
return StatusUnknown, nil
// IsRunningAsActiveQM returns true if the queue manager is running in active mode
func IsRunningAsActiveQM(name string) (bool, error) {
return isRunningQM(name, "(RUNNING)")
}
type QMStatus int
// IsRunningAsStandbyQM returns true if the queue manager is running in standby mode
func IsRunningAsStandbyQM(name string) (bool, error) {
return isRunningQM(name, "(RUNNING AS STANDBY)")
}
const (
StatusUnknown QMStatus = iota
StatusActiveQM
StatusStandbyQM
StatusReplicaQM
)
// IsRunningAsReplicaQM returns true if the queue manager is running in replica mode
func IsRunningAsReplicaQM(name string) (bool, error) {
return isRunningQM(name, "(REPLICA)")
}
// ActiveQM returns true if the queue manager is running in active mode
func (s QMStatus) ActiveQM() bool { return s == StatusActiveQM }
// StandbyQM returns true if the queue manager is running in standby mode
func (s QMStatus) StandbyQM() bool { return s == StatusStandbyQM }
// ReplicaQM returns true if the queue manager is running in replica mode
func (s QMStatus) ReplicaQM() bool { return s == StatusReplicaQM }
func isRunningQM(name string, status string) (bool, error) {
out, _, err := command.Run("dspmq", "-n", "-m", name)
if err != nil {
return false, err
}
if strings.Contains(string(out), status) {
return true, nil
}
return false, nil
}

View File

@@ -76,20 +76,18 @@ type TLSStore struct {
Truststore KeyStoreData
}
func configureTLSKeystores(keystoreDir, keyDir, trustDir string, p12TruststoreRequired bool, nativeTLSHA bool) (string, KeyStoreData, KeyStoreData, error) {
var keyLabel string
func configureTLSKeystores(keystoreDir, keyDir, trustDir string, p12TruststoreRequired bool) (string, KeyStoreData, KeyStoreData, error) {
// Create the CMS Keystore & PKCS#12 Truststore (if required)
tlsStore, err := generateAllKeystores(keystoreDir, p12TruststoreRequired, nativeTLSHA)
tlsStore, err := generateAllKeystores(keystoreDir, p12TruststoreRequired)
if err != nil {
return "", tlsStore.Keystore, tlsStore.Truststore, err
}
if tlsStore.Keystore.Keystore != nil {
// Process all keys - add them to the CMS KeyStore
keyLabel, err = processKeys(&tlsStore, keystoreDir, keyDir)
if err != nil {
return "", tlsStore.Keystore, tlsStore.Truststore, err
}
// Process all keys - add them to the CMS KeyStore
keyLabel, err := processKeys(&tlsStore, keystoreDir, keyDir)
if err != nil {
return "", tlsStore.Keystore, tlsStore.Truststore, err
}
// Process all trust certificates - add them to the CMS KeyStore & PKCS#12 Truststore (if required)
@@ -103,13 +101,13 @@ func configureTLSKeystores(keystoreDir, keyDir, trustDir string, p12TruststoreRe
// ConfigureDefaultTLSKeystores configures the CMS Keystore & PKCS#12 Truststore
func ConfigureDefaultTLSKeystores() (string, KeyStoreData, KeyStoreData, error) {
return configureTLSKeystores(keystoreDirDefault, keyDirDefault, trustDirDefault, true, false)
return configureTLSKeystores(keystoreDirDefault, keyDirDefault, trustDirDefault, true)
}
// ConfigureHATLSKeystore configures the CMS Keystore & PKCS#12 Truststore
func ConfigureHATLSKeystore() (string, KeyStoreData, KeyStoreData, error) {
// *.crt files mounted to the HA TLS dir keyDirHA will be processed as trusted in the CMS keystore
return configureTLSKeystores(keystoreDirHA, keyDirHA, keyDirHA, false, true)
return configureTLSKeystores(keystoreDirHA, keyDirHA, keyDirHA, false)
}
// ConfigureTLS configures TLS for the queue manager
@@ -117,26 +115,10 @@ func ConfigureTLS(keyLabel string, cmsKeystore KeyStoreData, devMode bool, log *
const mqsc string = "/etc/mqm/15-tls.mqsc"
const mqscTemplate string = mqsc + ".tpl"
sslKeyRing := ""
var fipsEnabled = "NO"
// Don't set SSLKEYR if no keys or crts are not supplied
// Key label will be blank if no private keys were added during processing keys and certs.
if cmsKeystore.Keystore != nil && len(keyLabel) > 0 {
certList, _ := cmsKeystore.Keystore.ListAllCertificates()
if len(certList) > 0 {
sslKeyRing = strings.TrimSuffix(cmsKeystore.Keystore.Filename, ".kdb")
}
if cmsKeystore.Keystore.IsFIPSEnabled() {
fipsEnabled = "YES"
}
}
err := mqtemplate.ProcessTemplateFile(mqscTemplate, mqsc, map[string]string{
"SSLKeyR": sslKeyRing,
"SSLKeyR": strings.TrimSuffix(cmsKeystore.Keystore.Filename, ".kdb"),
"CertificateLabel": keyLabel,
"SSLFips": fipsEnabled,
}, log)
if err != nil {
return err
@@ -177,7 +159,7 @@ func configureTLSDev(log *logger.Logger) error {
}
// generateAllKeystores creates the CMS Keystore & PKCS#12 Truststore (if required)
func generateAllKeystores(keystoreDir string, p12TruststoreRequired bool, nativeTLSHA bool) (TLSStore, error) {
func generateAllKeystores(keystoreDir string, p12TruststoreRequired bool) (TLSStore, error) {
var cmsKeystore, p12Truststore KeyStoreData
@@ -193,19 +175,11 @@ func generateAllKeystores(keystoreDir string, p12TruststoreRequired bool, native
return TLSStore{cmsKeystore, p12Truststore}, fmt.Errorf("Failed to create Keystore directory: %v", err)
}
// Search the default keys directory for any keys/certs.
keysDirectory := keyDirDefault
// Change to default native HA TLS directory if we are configuring nativeHA
if nativeTLSHA {
keysDirectory = keyDirHA
}
// Create the CMS Keystore if we have been provided keys and certificates
if haveKeysAndCerts(keysDirectory) || haveKeysAndCerts(trustDirDefault) {
cmsKeystore.Keystore = keystore.NewCMSKeyStore(filepath.Join(keystoreDir, cmsKeystoreName), cmsKeystore.Password)
err = cmsKeystore.Keystore.Create()
if err != nil {
return TLSStore{cmsKeystore, p12Truststore}, fmt.Errorf("Failed to create CMS Keystore: %v", err)
}
// Create the CMS Keystore
cmsKeystore.Keystore = keystore.NewCMSKeyStore(filepath.Join(keystoreDir, cmsKeystoreName), cmsKeystore.Password)
err = cmsKeystore.Keystore.Create()
if err != nil {
return TLSStore{cmsKeystore, p12Truststore}, fmt.Errorf("Failed to create CMS Keystore: %v", err)
}
// Create the PKCS#12 Truststore (if required)
@@ -229,6 +203,7 @@ func processKeys(tlsStore *TLSStore, keystoreDir string, keyDir string) (string,
// Process all keys
keyList, err := ioutil.ReadDir(keyDir)
if err == nil && len(keyList) > 0 {
// Process each set of keys - each set should contain files: *.key & *.crt
for _, keySet := range keyList {
keys, _ := ioutil.ReadDir(filepath.Join(keyDir, keySet.Name()))
@@ -255,13 +230,6 @@ func processKeys(tlsStore *TLSStore, keystoreDir string, keyDir string) (string,
return "", err
}
// Validate certificates for duplicate Subject DNs
if len(caCertificate) > 0 {
errCertValid := validateCertificates(publicCertificate, caCertificate)
if errCertValid != nil {
return "", errCertValid
}
}
// Create a new PKCS#12 Keystore - containing private key, public certificate & optional CA certificate
file, err := pkcs.Encode(rand.Reader, privateKey, publicCertificate, caCertificate, tlsStore.Keystore.Password)
if err != nil {
@@ -639,39 +607,3 @@ func writeCertificatesToFile(file string, certificates []*pem.Block) error {
}
return nil
}
// Search the specified directory for .key and .crt files.
// Return true if at least one .key or .crt file is found else false
func haveKeysAndCerts(keyDir string) bool {
fileList, err := os.ReadDir(keyDir)
if err == nil && len(fileList) > 0 {
for _, fileInfo := range fileList {
// Keys and certs will be supplied in an user defined subdirectory.
// Do a listing of the subdirectory and then search for .key and .cert files
keys, _ := ioutil.ReadDir(filepath.Join(keyDir, fileInfo.Name()))
for _, key := range keys {
if strings.HasSuffix(key.Name(), ".key") || strings.HasSuffix(key.Name(), ".crt") {
// We found at least one key/crt file.
return true
}
}
}
}
return false
}
// Iterate through the certificates to ensure there are no two certificates with same Subject DN.
// GSKit does not allow two certificates with same Subject DN/Friendly Names
func validateCertificates(personalCert *x509.Certificate, caCertificates []*x509.Certificate) error {
// Check if we have been asked to override certificate validation by setting
// MQ_ENABLE_CERT_VALIDATION to false
enableValidation, enableValidationSet := os.LookupEnv("MQ_ENABLE_CERT_VALIDATION")
if !enableValidationSet || (enableValidationSet && !strings.EqualFold(strings.Trim(enableValidation, ""), "false")) {
for _, caCert := range caCertificates {
if strings.EqualFold(personalCert.Subject.String(), caCert.Subject.String()) {
return fmt.Errorf("Error: The Subject DN of the Issuer Certificate and the Queue Manager are same")
}
}
}
return nil
}

View File

@@ -65,6 +65,7 @@ func ConfigureWebKeystore(p12Truststore KeyStoreData, webKeystore string) (strin
// Check if a new self-signed certificate should be generated
genHostName := os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME")
if genHostName != "" {
// Create the Web Keystore
newWebKeystore := keystore.NewPKCS12KeyStore(webKeystoreFile, p12Truststore.Password)
err := newWebKeystore.Create()
@@ -77,6 +78,7 @@ func ConfigureWebKeystore(p12Truststore KeyStoreData, webKeystore string) (strin
if err != nil {
return "", fmt.Errorf("Failed to generate certificate in Web Keystore %s with DN of 'CN=%s': %v", webKeystoreFile, genHostName, err)
}
} else {
// Check Web Keystore already exists
_, err := os.Stat(webKeystoreFile)

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2023
© Copyright IBM Corporation 2017, 2020
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -102,10 +102,5 @@ func LogContainerDetails(log *logger.Logger) error {
}
}
}
if os.Getenv("MQ_LOGGING_CONSOLE_FORMAT") == "" && os.Getenv("LOG_FORMAT") != "" {
log.Println("Environment variable LOG_FORMAT is deprecated. Use MQ_LOGGING_CONSOLE_FORMAT instead.")
}
return nil
}

View File

@@ -2,6 +2,6 @@
# SOURCE_BRANCH is the repository branch name for this release stream.
# It should be updated when a new release fork is created but not for testing of personal builds or pre-fork updates.
SOURCE_BRANCH ?= v9.3.2
SOURCE_BRANCH ?= v9.3.0.x
###########################################################################################################################################################

View File

@@ -1,4 +1,3 @@
//go:build mqdev
// +build mqdev
/*
@@ -23,8 +22,6 @@ import (
"path/filepath"
"strings"
"testing"
"time"
"crypto/tls"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
@@ -54,16 +51,14 @@ func TestDevGoldenPath(t *testing.T) {
waitForReady(t, cli, id)
waitForWebReady(t, cli, id, insecureTLSConfig)
t.Run("JMS", func(t *testing.T) {
// Run the JMS tests, with no password specified.
// Use OpenJDK JRE for running testing, pass false for 7th parameter.
// Last parameter is blank as the test doesn't use TLS.
runJMSTests(t, cli, id, false, "app", defaultAppPasswordOS, "false", "")
// Run the JMS tests, with no password specified
runJMSTests(t, cli, id, false, "app", defaultAppPasswordOS)
})
t.Run("REST admin", func(t *testing.T) {
testRESTAdmin(t, cli, id, insecureTLSConfig, "")
testRESTAdmin(t, cli, id, insecureTLSConfig)
})
t.Run("REST messaging", func(t *testing.T) {
testRESTMessaging(t, cli, id, insecureTLSConfig, qm, "app", defaultAppPasswordWeb, "")
testRESTMessaging(t, cli, id, insecureTLSConfig, qm, "app", defaultAppPasswordWeb)
})
// Stop the container cleanly
stopContainer(t, cli, id)
@@ -120,15 +115,13 @@ func TestDevSecure(t *testing.T) {
waitForWebReady(t, cli, ctr.ID, createTLSConfig(t, cert, tlsPassPhrase))
t.Run("JMS", func(t *testing.T) {
// OpenJDK is used for running tests, hence pass "false" for 7th parameter.
// Cipher name specified is compliant with non-IBM JRE naming.
runJMSTests(t, cli, ctr.ID, true, "app", appPassword, "false", "TLS_RSA_WITH_AES_256_CBC_SHA256")
runJMSTests(t, cli, ctr.ID, true, "app", appPassword)
})
t.Run("REST admin", func(t *testing.T) {
testRESTAdmin(t, cli, ctr.ID, insecureTLSConfig, "")
testRESTAdmin(t, cli, ctr.ID, insecureTLSConfig)
})
t.Run("REST messaging", func(t *testing.T) {
testRESTMessaging(t, cli, ctr.ID, insecureTLSConfig, qm, "app", appPassword, "")
testRESTMessaging(t, cli, ctr.ID, insecureTLSConfig, qm, "app", appPassword)
})
// Stop the container cleanly
@@ -160,9 +153,7 @@ func TestDevWebDisabled(t *testing.T) {
})
t.Run("JMS", func(t *testing.T) {
// Run the JMS tests, with no password specified
// OpenJDK is used for running tests, hence pass "false" for 7th parameter.
// Last parameter is blank as the test doesn't use TLS.
runJMSTests(t, cli, id, false, "app", defaultAppPasswordOS, "false", "")
runJMSTests(t, cli, id, false, "app", defaultAppPasswordOS)
})
// Stop the container cleanly
stopContainer(t, cli, id)
@@ -193,592 +184,3 @@ func TestDevConfigDisabled(t *testing.T) {
// Stop the container cleanly
stopContainer(t, cli, id)
}
// Test if SSLKEYR and CERTLABL attributes are not set when key and certificate
// are not supplied.
func TestSSLKEYRBlank(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=QM1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=false",
},
}
id := runContainerWithPorts(t, cli, &containerConfig, []int{9443})
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
// execute runmqsc to display qmgr SSLKEYR and CERTLABL attibutes.
// Search the console output for exepcted values
_, sslkeyROutput := execContainer(t, cli, id, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL' | runmqsc"})
if !strings.Contains(sslkeyROutput, "SSLKEYR( )") || !strings.Contains(sslkeyROutput, "CERTLABL( )") {
// Although queue manager is ready, it may be that MQSC scripts have not been applied yet.
// Hence wait for a second and retry few times before giving up.
waitCount := 30
var i int
for i = 0; i < waitCount; i++ {
time.Sleep(1 * time.Second)
_, sslkeyROutput = execContainer(t, cli, id, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL' | runmqsc"})
if strings.Contains(sslkeyROutput, "SSLKEYR( )") && strings.Contains(sslkeyROutput, "CERTLABL( )") {
break
}
}
// Failed to get expected output? dump the contents of mqsc files.
if i == waitCount {
_, tls15mqsc := execContainer(t, cli, id, "", []string{"cat", "/etc/mqm/15-tls.mqsc"})
_, autoMQSC := execContainer(t, cli, id, "", []string{"cat", "/mnt/mqm/data/qmgrs/QM1/autocfg/cached.mqsc"})
t.Errorf("Expected SSLKEYR to be blank but it is not; got \"%v\"\n AutoConfig MQSC file contents %v\n 15-tls: %v", sslkeyROutput, autoMQSC, tls15mqsc)
}
}
// Stop the container cleanly
stopContainer(t, cli, id)
}
// Test if SSLKEYR and CERTLABL attributes are set when key and certificate
// are supplied.
func TestSSLKEYRWithSuppliedKeyAndCert(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=QM1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=false",
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
tlsDir(t, false) + ":/etc/mqm/pki/keys/default",
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
waitForReady(t, cli, ctr.ID)
// execute runmqsc to display qmgr SSLKEYR and CERTLABL attibutes.
// Search the console output for exepcted values
_, sslkeyROutput := execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL' | runmqsc"})
if !strings.Contains(sslkeyROutput, "SSLKEYR(/run/runmqserver/tls/key)") || !strings.Contains(sslkeyROutput, "CERTLABL(default)") {
// Although queue manager is ready, it may be that MQSC scripts have not been applied yet.
// Hence wait for a second and retry few times before giving up.
waitCount := 30
var i int
for i = 0; i < waitCount; i++ {
time.Sleep(1 * time.Second)
_, sslkeyROutput = execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL' | runmqsc"})
if strings.Contains(sslkeyROutput, "SSLKEYR(/run/runmqserver/tls/key)") && strings.Contains(sslkeyROutput, "CERTLABL(default)") {
break
}
}
// Failed to get expected output? dump the contents of mqsc files.
if i == waitCount {
_, tls15mqsc := execContainer(t, cli, ctr.ID, "", []string{"cat", "/etc/mqm/15-tls.mqsc"})
_, autoMQSC := execContainer(t, cli, ctr.ID, "", []string{"cat", "/mnt/mqm/data/qmgrs/QM1/autocfg/cached.mqsc"})
t.Errorf("Expected SSLKEYR to be '/run/runmqserver/tls/key' but it is not; got \"%v\" \n AutoConfig MQSC file contents %v\n 15-tls: %v", sslkeyROutput, autoMQSC, tls15mqsc)
}
}
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}
// Test with CA cert
func TestSSLKEYRWithCACert(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=QM1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=false",
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
tlsDirWithCA(t, false) + ":/etc/mqm/pki/keys/QM1CA",
},
// Assign a random port for the web server on the host
PortBindings: nat.PortMap{
"9443/tcp": []nat.PortBinding{
{
HostIP: "0.0.0.0",
},
},
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
waitForReady(t, cli, ctr.ID)
// execute runmqsc to display qmgr SSLKEYR and CERTLABL attibutes.
// Search the console output for exepcted values
_, sslkeyROutput := execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL' | runmqsc"})
if !strings.Contains(sslkeyROutput, "SSLKEYR(/run/runmqserver/tls/key)") {
// Although queue manager is ready, it may be that MQSC scripts have not been applied yet.
// Hence wait for a second and retry few times before giving up.
waitCount := 30
var i int
for i = 0; i < waitCount; i++ {
time.Sleep(1 * time.Second)
_, sslkeyROutput = execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL' | runmqsc"})
if strings.Contains(sslkeyROutput, "SSLKEYR(/run/runmqserver/tls/key)") {
break
}
}
// Failed to get expected output? dump the contents of mqsc files.
if i == waitCount {
_, tls15mqsc := execContainer(t, cli, ctr.ID, "", []string{"cat", "/etc/mqm/15-tls.mqsc"})
_, autoMQSC := execContainer(t, cli, ctr.ID, "", []string{"cat", "/mnt/mqm/data/qmgrs/QM1/autocfg/cached.mqsc"})
t.Errorf("Expected SSLKEYR to be '/run/runmqserver/tls/key' but it is not; got \"%v\"\n AutoConfig MQSC file contents %v\n 15-tls: %v", sslkeyROutput, autoMQSC, tls15mqsc)
}
}
if !strings.Contains(sslkeyROutput, "CERTLABL(QM1CA)") {
_, autoMQSC := execContainer(t, cli, ctr.ID, "", []string{"cat", "/etc/mqm/15-tls.mqsc"})
t.Errorf("Expected CERTLABL to be 'QM1CA' but it is not; got \"%v\" \n MQSC File contents %v", sslkeyROutput, autoMQSC)
}
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}
// Verifies SSLFIPS is set to NO if MQ_ENABLE_FIPS=false
func TestSSLFIPSNO(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=QM1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=false",
"MQ_ENABLE_FIPS=false",
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
tlsDir(t, false) + ":/etc/mqm/pki/keys/default",
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
waitForReady(t, cli, ctr.ID)
// execute runmqsc to display qmgr SSLKEYR, SSLFIPS and CERTLABL attibutes.
// Search the console output for exepcted values
_, sslFIPSOutput := execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL SSLFIPS' | runmqsc"})
if !strings.Contains(sslFIPSOutput, "SSLKEYR(/run/runmqserver/tls/key)") {
t.Errorf("Expected SSLKEYR to be '/run/runmqserver/tls/key' but it is not; got \"%v\"", sslFIPSOutput)
}
if !strings.Contains(sslFIPSOutput, "CERTLABL(default)") {
t.Errorf("Expected CERTLABL to be 'default' but it is not; got \"%v\"", sslFIPSOutput)
}
if !strings.Contains(sslFIPSOutput, "SSLFIPS(NO)") {
t.Errorf("Expected SSLFIPS to be 'NO' but it is not; got \"%v\"", sslFIPSOutput)
}
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}
// Verifies SSLFIPS is set to YES if certificates for queue manager
// are supplied and MQ_ENABLE_FIPS=true
func TestSSLFIPSYES(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
appPassword := "differentPassw0rd"
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_APP_PASSWORD=" + appPassword,
"MQ_QMGR_NAME=QM1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=false",
"MQ_ENABLE_FIPS=true",
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
tlsDir(t, false) + ":/etc/mqm/pki/keys/default",
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
waitForReady(t, cli, ctr.ID)
// Check for expected message on container log
logs := inspectLogs(t, cli, ctr.ID)
if !strings.Contains(logs, "FIPS cryptography is enabled.") {
t.Errorf("Expected 'FIPS cryptography is enabled.' but got %v\n", logs)
}
// execute runmqsc to display qmgr SSLKEYR, SSLFIPS and CERTLABL attibutes.
// Search the console output for exepcted values
_, sslFIPSOutput := execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL SSLFIPS' | runmqsc"})
if !strings.Contains(sslFIPSOutput, "SSLKEYR(/run/runmqserver/tls/key)") {
t.Errorf("Expected SSLKEYR to be '/run/runmqserver/tls/key' but it is not; got \"%v\"", sslFIPSOutput)
}
if !strings.Contains(sslFIPSOutput, "CERTLABL(default)") {
t.Errorf("Expected CERTLABL to be 'default' but it is not; got \"%v\"", sslFIPSOutput)
}
if !strings.Contains(sslFIPSOutput, "SSLFIPS(YES)") {
t.Errorf("Expected SSLFIPS to be 'YES' but it is not; got \"%v\"", sslFIPSOutput)
}
t.Run("JMS", func(t *testing.T) {
// Run the JMS tests, with no password specified
runJMSTests(t, cli, ctr.ID, true, "app", appPassword, "false", "TLS_RSA_WITH_AES_256_CBC_SHA256")
})
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}
// TestDevSecureFIPSYESWeb verifies if the MQ Web Server is running in FIPS mode
func TestDevSecureFIPSTrueWeb(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
const tlsPassPhrase string = "passw0rd"
qm := "qm1"
appPassword := "differentPassw0rd"
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=" + qm,
"MQ_APP_PASSWORD=" + appPassword,
"DEBUG=1",
"WLP_LOGGING_MESSAGE_FORMAT=JSON",
"MQ_ENABLE_EMBEDDED_WEB_SERVER_LOG=true",
"MQ_ENABLE_FIPS=true",
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
tlsDir(t, false) + ":/etc/mqm/pki/keys/default",
tlsDir(t, false) + ":/etc/mqm/pki/trust/default",
},
// Assign a random port for the web server on the host
// TODO: Don't do this for all tests
PortBindings: nat.PortMap{
"9443/tcp": []nat.PortBinding{
{
HostIP: "0.0.0.0",
},
},
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
waitForReady(t, cli, ctr.ID)
cert := filepath.Join(tlsDir(t, true), "server.crt")
waitForWebReady(t, cli, ctr.ID, createTLSConfig(t, cert, tlsPassPhrase))
// Create a TLS Config with a cipher to use when connecting over HTTPS
var secureTLSConfig *tls.Config = createTLSConfigWithCipher(t, cert, tlsPassPhrase, []uint16{tls.TLS_RSA_WITH_AES_256_GCM_SHA384})
// Put a message to queue
t.Run("REST messaging", func(t *testing.T) {
testRESTMessaging(t, cli, ctr.ID, secureTLSConfig, qm, "app", appPassword, "")
})
// Create a TLS Config with a non-FIPS cipher to use when connecting over HTTPS
var secureNonFIPSCipherConfig *tls.Config = createTLSConfigWithCipher(t, cert, tlsPassPhrase, []uint16{tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA})
// Put a message to queue - the attempt to put message will fail with a EOF return message.
t.Run("REST messaging", func(t *testing.T) {
testRESTMessaging(t, cli, ctr.ID, secureNonFIPSCipherConfig, qm, "app", appPassword, "EOF")
})
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}
// TestDevSecureNOFIPSWeb verifies if the MQ Web Server is not running in FIPS mode
func TestDevSecureFalseFIPSWeb(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
const tlsPassPhrase string = "passw0rd"
qm := "qm1"
appPassword := "differentPassw0rd"
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=" + qm,
"MQ_APP_PASSWORD=" + appPassword,
"DEBUG=1",
"WLP_LOGGING_MESSAGE_FORMAT=JSON",
"MQ_ENABLE_EMBEDDED_WEB_SERVER_LOG=true",
"MQ_ENABLE_FIPS=false",
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
tlsDir(t, false) + ":/etc/mqm/pki/keys/default",
tlsDir(t, false) + ":/etc/mqm/pki/trust/default",
},
// Assign a random port for the web server on the host
PortBindings: nat.PortMap{
"9443/tcp": []nat.PortBinding{
{
HostIP: "0.0.0.0",
},
},
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
waitForReady(t, cli, ctr.ID)
cert := filepath.Join(tlsDir(t, true), "server.crt")
waitForWebReady(t, cli, ctr.ID, createTLSConfig(t, cert, tlsPassPhrase))
// As FIPS is not enabled, the MQ WebServer (actually Java) will choose a JSSE provider from the list
// specified in java.security file. We will need to enable java.net.debug and then parse the web server
// logs to check what JJSE provider is being used. Hence just check the jvm.options file does not contain
// -Dcom.ibm.jsse2.usefipsprovider line.
_, jvmOptionsOutput := execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "cat /var/mqm/web/installations/Installation1/servers/mqweb/configDropins/defaults/jvm.options"})
if strings.Contains(jvmOptionsOutput, "-Dcom.ibm.jsse2.usefipsprovider") {
t.Errorf("Did not expect -Dcom.ibm.jsse2.usefipsprovider but it is not; got \"%v\"", jvmOptionsOutput)
}
// Just do a HTTPS GET as well to query installation details.
var secureTLSConfig *tls.Config = createTLSConfigWithCipher(t, cert, tlsPassPhrase, []uint16{tls.TLS_RSA_WITH_AES_256_GCM_SHA384})
t.Run("REST admin", func(t *testing.T) {
testRESTAdmin(t, cli, ctr.ID, secureTLSConfig, "")
})
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}
// Verify SSLFIPS is set to NO if no certificates were supplied
func TestSSLFIPSTrueNoCerts(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
appPassword := "differentPassw0rd"
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_APP_PASSWORD=" + appPassword,
"MQ_QMGR_NAME=QM1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=false",
"MQ_ENABLE_FIPS=true",
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
waitForReady(t, cli, ctr.ID)
// execute runmqsc to display qmgr SSLKEYR, SSLFIPS and CERTLABL attibutes.
// Search the console output for exepcted values
_, sslFIPSOutput := execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL SSLFIPS' | runmqsc"})
if !strings.Contains(sslFIPSOutput, "SSLKEYR( )") {
t.Errorf("Expected SSLKEYR to be ' ' but it is not; got \"%v\"", sslFIPSOutput)
}
if !strings.Contains(sslFIPSOutput, "CERTLABL( )") {
t.Errorf("Expected CERTLABL to be blank but it is not; got \"%v\"", sslFIPSOutput)
}
if !strings.Contains(sslFIPSOutput, "SSLFIPS(NO)") {
t.Errorf("Expected SSLFIPS to be 'NO' but it is not; got \"%v\"", sslFIPSOutput)
}
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}
// Verifies SSLFIPS is set to NO if MQ_ENABLE_FIPS=tru (invalid value)
func TestSSLFIPSInvalidValue(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=QM1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=false",
"MQ_ENABLE_FIPS=tru",
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
tlsDir(t, false) + ":/etc/mqm/pki/keys/default",
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
waitForReady(t, cli, ctr.ID)
// execute runmqsc to display qmgr SSLKEYR, SSLFIPS and CERTLABL attibutes.
// Search the console output for exepcted values
_, sslFIPSOutput := execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL SSLFIPS' | runmqsc"})
if !strings.Contains(sslFIPSOutput, "SSLKEYR(/run/runmqserver/tls/key)") {
t.Errorf("Expected SSLKEYR to be '/run/runmqserver/tls/key' but it is not; got \"%v\"", sslFIPSOutput)
}
if !strings.Contains(sslFIPSOutput, "CERTLABL(default)") {
t.Errorf("Expected CERTLABL to be 'default' but it is not; got \"%v\"", sslFIPSOutput)
}
if !strings.Contains(sslFIPSOutput, "SSLFIPS(NO)") {
t.Errorf("Expected SSLFIPS to be 'NO' but it is not; got \"%v\"", sslFIPSOutput)
}
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}
// Container creation fails when invalid certs are passed and MQ_ENABLE_FIPS set true
func TestSSLFIPSBadCerts(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=QM1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=false",
"MQ_ENABLE_FIPS=true",
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
tlsDirInvalid(t, false) + ":/etc/mqm/pki/keys/default",
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
rc := waitForContainer(t, cli, ctr.ID, 20*time.Second)
// Expect return code 1 if container failed to create.
if rc == 1 {
// Get container logs and search for specific message.
logs := inspectLogs(t, cli, ctr.ID)
if strings.Contains(logs, "Failed to parse private key") {
t.Logf("Container creating failed because of invalid certifates")
}
} else {
// Some other error occurred.
t.Errorf("Expected rc=0, got rc=%v", rc)
}
// Stop the container cleanly
stopContainer(t, cli, ctr.ID)
}

View File

@@ -1,8 +1,7 @@
//go:build mqdev
// +build mqdev
/*
© Copyright IBM Corporation 2018, 2022
© Copyright IBM Corporation 2018, 2021
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -19,7 +18,6 @@ limitations under the License.
package main
import (
"bufio"
"bytes"
"context"
"crypto/tls"
@@ -28,8 +26,8 @@ import (
"io/ioutil"
"net/http"
"net/http/httputil"
"os"
"path/filepath"
"strconv"
"strings"
"testing"
"time"
@@ -82,23 +80,15 @@ func tlsDir(t *testing.T, unixPath bool) string {
return filepath.Join(getCwd(t, unixPath), "../tls")
}
func tlsDirWithCA(t *testing.T, unixPath bool) string {
return filepath.Join(getCwd(t, unixPath), "../tlscacert")
}
func tlsDirInvalid(t *testing.T, unixPath bool) string {
return filepath.Join(getCwd(t, unixPath), "../tlsinvalidcert")
}
// runJMSTests runs a container with a JMS client, which connects to the queue manager container with the specified ID
func runJMSTests(t *testing.T, cli *client.Client, ID string, tls bool, user, password string, ibmjre string, cipherName string) {
func runJMSTests(t *testing.T, cli *client.Client, ID string, tls bool, user, password string) {
containerConfig := container.Config{
// -e MQ_PORT_1414_TCP_ADDR=9.145.14.173 -e MQ_USERNAME=app -e MQ_PASSWORD=passw0rd -e MQ_CHANNEL=DEV.APP.SVRCONN -e MQ_TLS_TRUSTSTORE=/tls/test.p12 -e MQ_TLS_PASSPHRASE=passw0rd -v /Users/arthurbarr/go/src/github.com/ibm-messaging/mq-container/test/tls:/tls msgtest
Env: []string{
"MQ_PORT_1414_TCP_ADDR=" + getIPAddress(t, cli, ID),
"MQ_USERNAME=" + user,
"MQ_CHANNEL=DEV.APP.SVRCONN",
"IBMJRE=" + ibmjre,
"IBMJRE=" + os.Getenv("IBMJRE"),
},
Image: imageNameDevJMS(),
}
@@ -111,7 +101,6 @@ func runJMSTests(t *testing.T, cli *client.Client, ID string, tls bool, user, pa
containerConfig.Env = append(containerConfig.Env, []string{
"MQ_TLS_TRUSTSTORE=/var/tls/client-trust.jks",
"MQ_TLS_PASSPHRASE=passw0rd",
"MQ_TLS_CIPHER=" + cipherName,
}...)
}
hostConfig := container.HostConfig{
@@ -130,57 +119,9 @@ func runJMSTests(t *testing.T, cli *client.Client, ID string, tls bool, user, pa
if rc != 0 {
t.Errorf("JUnit container failed with rc=%v", rc)
}
// Get console output of the container and process the lines
// to see if we have any failures
scanner := bufio.NewScanner(strings.NewReader(inspectLogs(t, cli, ctr.ID)))
for scanner.Scan() {
s := scanner.Text()
if processJunitLogLine(s) {
t.Errorf("JUnit container tests failed. Reason: %s", s)
}
}
defer cleanContainer(t, cli, ctr.ID)
}
// Parse JUnit log line and return true if line contains failed or aborted tests
func processJunitLogLine(outputLine string) bool {
var failedLine bool
// Sample JUnit test run output
//[ 2 containers found ]
//[ 0 containers skipped ]
//[ 2 containers started ]
//[ 0 containers aborted ]
//[ 2 containers successful ]
//[ 0 containers failed ]
//[ 0 tests found ]
//[ 0 tests skipped ]
//[ 0 tests started ]
//[ 0 tests aborted ]
//[ 0 tests successful ]
//[ 0 tests failed ]
// Consider only those lines that begin with '[' and with ']'
if strings.HasPrefix(outputLine, "[") && strings.HasSuffix(outputLine, "]") {
// Strip off [] and whitespaces
trimmed := strings.Trim(outputLine, "[] ")
if strings.Contains(trimmed, "aborted") || strings.Contains(trimmed, "failed") {
// Tokenize on whitespace
tokens := strings.Split(trimmed, " ")
// Determine the count of aborted or failed tests
count, err := strconv.Atoi(tokens[0])
if err == nil {
if count > 0 {
failedLine = true
}
}
}
}
return failedLine
}
// createTLSConfig creates a tls.Config which trusts the specified certificate
func createTLSConfig(t *testing.T, certFile, password string) *tls.Config {
// Get the SystemCertPool, continue with an empty pool on error
@@ -205,7 +146,7 @@ func createTLSConfig(t *testing.T, certFile, password string) *tls.Config {
}
}
func testRESTAdmin(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config, errorExpected string) {
func testRESTAdmin(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config) {
httpClient := http.Client{
Timeout: time.Duration(30 * time.Second),
Transport: &http.Transport{
@@ -217,15 +158,9 @@ func testRESTAdmin(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.C
req.SetBasicAuth("admin", defaultAdminPassword)
resp, err := httpClient.Do(req)
if err != nil {
if len(errorExpected) > 0 {
if !strings.Contains(err.Error(), errorExpected) {
t.Fatal(err)
}
} else {
t.Fatal(err)
}
t.Fatal(err)
}
if resp != nil && resp.StatusCode != http.StatusOK {
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected HTTP status code %v from 'GET installation'; got %v", http.StatusOK, resp.StatusCode)
}
}
@@ -248,7 +183,7 @@ func logHTTPResponse(t *testing.T, resp *http.Response) {
t.Logf("HTTP response: %v", string(d))
}
func testRESTMessaging(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config, qmName string, user string, password string, errorExpected string) {
func testRESTMessaging(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config, qmName string, user string, password string) {
httpClient := http.Client{
Timeout: time.Duration(30 * time.Second),
Transport: &http.Transport{
@@ -265,19 +200,10 @@ func testRESTMessaging(t *testing.T, cli *client.Client, ID string, tlsConfig *t
logHTTPRequest(t, req)
resp, err := httpClient.Do(req)
if err != nil {
if len(errorExpected) > 0 {
if strings.Contains(err.Error(), errorExpected) {
t.Logf("Error contains expected '%s' value", errorExpected)
return
} else {
t.Fatal(err)
}
} else {
t.Fatal(err)
}
t.Fatal(err)
}
logHTTPResponse(t, resp)
if resp != nil && resp.StatusCode != http.StatusCreated {
if resp.StatusCode != http.StatusCreated {
t.Errorf("Expected HTTP status code %v from 'POST to queue'; got %v", http.StatusOK, resp.StatusCode)
t.Logf("HTTP response: %+v", resp)
t.Fail()
@@ -305,28 +231,3 @@ func testRESTMessaging(t *testing.T, cli *client.Client, ID string, tlsConfig *t
t.Errorf("Expected payload to be \"%s\"; got \"%s\"", putMessage, gotMessage)
}
}
// createTLSConfig creates a tls.Config which trusts the specified certificate
func createTLSConfigWithCipher(t *testing.T, certFile, password string, ciphers []uint16) *tls.Config {
// Get the SystemCertPool, continue with an empty pool on error
certs, err := x509.SystemCertPool()
if err != nil {
t.Fatal(err)
}
// Read in the cert file
cert, err := ioutil.ReadFile(certFile)
if err != nil {
t.Fatal(err)
}
// Append our cert to the system pool
ok := certs.AppendCertsFromPEM(cert)
if !ok {
t.Fatal("No certs appended")
}
// Trust the augmented cert pool in our client
return &tls.Config{
InsecureSkipVerify: false,
RootCAs: certs,
CipherSuites: ciphers,
}
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2023
© Copyright IBM Corporation 2017, 2022
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -52,8 +52,6 @@ func TestLicenseNotSet(t *testing.T) {
expectTerminationMessage(t, cli, id)
}
// Start container with LICENSE environment variable set to view.
// Check that container starts and display license text
func TestLicenseView(t *testing.T) {
t.Parallel()
@@ -77,20 +75,45 @@ func TestLicenseView(t *testing.T) {
}
}
//Start a container with qm grace set to x seconds
//Check that when the container is stopped that the command endmqm has option -tp and x
func TestEndMQMOpts(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{"LICENSE=accept", "MQ_GRACE_PERIOD=27"},
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
killContainer(t, cli, id, "SIGTERM")
_, out := execContainer(t, cli, id, "", []string{"bash", "-c", "ps -ef | grep 'endmqm -w -r -tp 27'"})
t.Log(out)
if !strings.Contains(out, "endmqm -w -r -tp 27") {
t.Errorf("Expected endmqm options endmqm -w -r -tp 27; got \"%v\"", out)
}
}
// TestGoldenPath starts a queue manager successfully when metrics are enabled
func TestGoldenPathWithMetrics(t *testing.T) {
t.Parallel()
goldenPath(t, true)
}
// TestGoldenPath starts a queue manager successfully when metrics are disabled
func TestGoldenPathNoMetrics(t *testing.T) {
t.Parallel()
goldenPath(t, false)
}
// Actual test function for TestGoldenPathNoMetrics & TestGoldenPathWithMetrics
func goldenPath(t *testing.T, metrics bool) {
func goldenPath(t *testing.T, metric bool) {
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
@@ -98,34 +121,54 @@ func goldenPath(t *testing.T, metrics bool) {
containerConfig := container.Config{
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
}
if metrics {
if metric {
containerConfig.Env = append(containerConfig.Env, "MQ_ENABLE_METRICS=true")
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
//By default AMQ5041I,AMQ5052I,AMQ5051I,AMQ5037I,AMQ5975I are excluded
jsonLogs := inspectLogs(t, cli, id)
isMessageFound := scanForExcludedEntries(jsonLogs)
if isMessageFound == true {
t.Errorf("Expected to exclude messageId by default; but messageId \"%v\" is present", jsonLogs)
}
if strings.Contains(jsonLogs, "CWWKF0011I") {
t.Errorf("Web Server is off....CWWKF0011I message id is not expected")
}
t.Run("Validate Default LogFilePages", func(t *testing.T) {
testLogFilePages(t, cli, id, "qm1", "4096")
})
// Stop the container cleanly
stopContainer(t, cli, id)
}
// TestSecurityVulnerabilities checks for any vulnerabilities in the image, as reported
// by Red Hat
func TestSecurityVulnerabilities(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
rc, _ := runContainerOneShot(t, cli, "bash", "-c", "command -v microdnf && test -e /etc/yum.repos.d/ubi.repo")
if rc != 0 {
t.Skip("Skipping test because container is based on ubi-minimal, which doesn't include yum")
}
// id, _, err := command.Run("sudo", "buildah", "from", imageName())
// if err != nil {
// t.Log(id)
// t.Fatal(err)
// }
// id = strings.TrimSpace(id)
// defer command.Run("buildah", "rm", id)
// mnt, _, err := command.Run("sudo", "buildah", "mount", id)
// if err != nil {
// t.Log(mnt)
// t.Fatal(err)
// }
// mnt = strings.TrimSpace(mnt)
// out, _, err := command.Run("bash", "-c", "sudo cp /etc/yum.repos.d/* "+filepath.Join(mnt, "/etc/yum.repos.d/"))
// if err != nil {
// t.Log(out)
// t.Fatal(err)
// }
// out, ret, _ := command.Run("bash", "-c", "yum --installroot="+mnt+" updateinfo list sec | grep /Sec")
// if ret != 1 {
// t.Errorf("Expected no vulnerabilities, found the following:\n%v", out)
// }
}
func utilTestNoQueueManagerName(t *testing.T, hostName string, expectedName string) {
search := "QMNAME(" + expectedName + ")"
cli, err := client.NewClientWithOpts(client.FromEnv)
@@ -144,7 +187,6 @@ func utilTestNoQueueManagerName(t *testing.T, hostName string, expectedName stri
t.Errorf("Expected result of running dspmq to contain name=%v, got name=%v", search, out)
}
}
func TestNoQueueManagerName(t *testing.T) {
t.Parallel()
@@ -1171,6 +1213,28 @@ func jsonLogFormat(t *testing.T, metric bool) {
}
}
func TestBadLogFormat(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"LOG_FORMAT=fake",
},
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
rc := waitForContainer(t, cli, id, 20*time.Second)
if rc != 1 {
t.Errorf("Expected rc=1, got rc=%v", rc)
}
expectTerminationMessage(t, cli, id)
}
// TestMQJSONDisabled tests the case where MQ's JSON logging feature is
// specifically disabled (which will disable log mirroring)
func TestMQJSONDisabled(t *testing.T) {
@@ -1452,450 +1516,3 @@ func TestStartedCheckWithNoNewPrivileges(t *testing.T) {
func TestStartedCheckWithNewPrivileges(t *testing.T) {
utilTestStartedCheck(t, false)
}
// Start a container with qm grace set to x seconds
// Check that when the container is stopped that the command endmqm has option -tp and x
func TestEndMQMOpts(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{"LICENSE=accept", "MQ_GRACE_PERIOD=27"},
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
killContainer(t, cli, id, "SIGTERM")
_, out := execContainer(t, cli, id, "", []string{"bash", "-c", "ps -ef | grep 'endmqm -w -r -tp 27'"})
t.Log(out)
if !strings.Contains(out, "endmqm -w -r -tp 27") {
t.Errorf("Expected endmqm options endmqm -w -r -tp 27; got \"%v\"", out)
}
}
// TestCustomLogFilePages starts a qmgr with a custom number of logfilepages set.
// Check that the number of logfilepages matches.
func TestCustomLogFilePages(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{"LICENSE=accept", "MQ_QMGR_LOG_FILE_PAGES=8192", "MQ_QMGR_NAME=qmlfp"},
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
testLogFilePages(t, cli, id, "qmlfp", "8192")
}
// TestLoggingConsoleSource tests default behavior which is
// MQ_LOGGING_CONSOLE_SOURCE set to qmgr,web
func TestLoggingConsoleSource(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=qm1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=true",
},
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
jsonLogs, errJson := waitForMessageInLog(t, cli, id, "AMQ6206I")
if errJson != nil {
t.Errorf("%v", errJson)
}
isMessageFound := scanForExcludedEntries(jsonLogs)
if isMessageFound == true {
t.Errorf("Expected to exclude messageId by default; but messageId \"%v\" is present", jsonLogs)
}
// Stop the container cleanly
stopContainer(t, cli, id)
}
// TestOldBehaviorWebConsole sets LOG_FORMAT to json and verify logs are indeed in json format
func TestOldBehaviorWebConsole(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=qm1",
"LOG_FORMAT=json",
},
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
jsonLogs := inspectLogs(t, cli, id)
isMessageFound := scanForExcludedEntries(jsonLogs)
if isMessageFound == true {
t.Errorf("Expected to exclude messageId by default; but messageId \"%v\" is present", jsonLogs)
}
if strings.Contains(jsonLogs, "Environment variable LOG_FORMAT is deprecated. Use MQ_LOGGING_CONSOLE_FORMAT instead.") {
t.Logf("Expected Message stating LOG_FORMAT is deprecated is present in the log")
} else {
t.Errorf("Expected Message stating LOG_FORMAT is deprecated is not in the log")
}
isValidJSON := checkLogForValidJSON(jsonLogs)
if !isValidJSON {
t.Fatalf("Expected all log lines to be valid JSON. But got error %v ", err)
}
// Stop the container cleanly
stopContainer(t, cli, id)
}
// TestLoggingConsoleWithContRestart restarts the container and checks
// that setting of env variable persists
func TestLoggingConsoleWithContRestart(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=qm1",
"MQ_LOGGING_CONSOLE_SOURCE=qmgr",
},
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
jsonLogs, errJson := waitForMessageInLog(t, cli, id, "AMQ6206I")
if errJson != nil {
t.Errorf("%v", errJson)
}
isMessageFound := scanForExcludedEntries(jsonLogs)
if isMessageFound == true {
t.Errorf("Expected to exclude messageId by default; but messageId \"%v\" is present", jsonLogs)
}
stopContainer(t, cli, id)
startContainer(t, cli, id)
waitForReady(t, cli, id)
jsonLogs = inspectLogs(t, cli, id)
if !strings.Contains(jsonLogs, "Stopped queue manager") || strings.Contains(jsonLogs, "CWWKF0011I") {
t.Errorf("CWWKF0011I which is not expected is present!!!!!")
}
isMessageFoundAfterRestart := scanForExcludedEntries(jsonLogs)
if isMessageFoundAfterRestart == true {
t.Errorf("Expected to exclude messageId by default; but messageId \"%v\" is present", jsonLogs)
}
// Stop the container cleanly
stopContainer(t, cli, id)
}
// TestLoggingWithQmgrAndExcludeId tests MQ_LOGGING_CONSOLE_SOURCE set to qmgr
// and exclude ID set to amq7230I.
func TestLoggingWithQmgrAndExcludeId(t *testing.T) {
qmgrName := "qm1"
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=qm1",
"MQ_LOGGING_CONSOLE_SOURCE=qmgr",
"MQ_LOGGING_CONSOLE_FORMAT=json",
"MQ_LOGGING_CONSOLE_EXCLUDE_ID=amq7230I",
},
}
dir := "/var/mqm/qmgrs/" + qmgrName + "/errors"
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
jsonLogs, errJson := waitForMessageInLog(t, cli, id, "AMQ6206I")
if errJson != nil {
t.Errorf("%v", errJson)
}
isValidJSON := checkLogForValidJSON(jsonLogs)
if !isValidJSON {
t.Fatalf("Expected all log lines to be valid JSON. But got error %v ", err)
}
if strings.Contains(jsonLogs, "AMQ7230I") || strings.Contains(jsonLogs, "CWWKF0011I") {
t.Errorf("Expected to exclude messageId by default; but messageId \"%v\" is present", jsonLogs)
}
stopContainer(t, cli, id)
//checking that message is only excluded from the console log, but not from the MQ error log
b := copyFromContainer(t, cli, id, filepath.Join(dir, "AMQERR01.json"))
foundInLog := 0
r := bytes.NewReader(b)
scannernew := bufio.NewScanner(r)
for scannernew.Scan() {
textData := scannernew.Text()
if strings.Contains(textData, "AMQ7230I") {
foundInLog = 1
}
}
if foundInLog == 0 {
t.Errorf("mesageID AMQ7230I is not present in MQ LOG!!!!")
}
}
// TestLoggingConsoleSetToWeb tests MQ_LOGGING_CONSOLE_SOURCE set to web
func TestLoggingConsoleSetToWeb(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=qm1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=true",
"MQ_LOGGING_CONSOLE_SOURCE=web",
"MQ_LOGGING_CONSOLE_EXCLUDE_ID=CWWKG0028A,CWWKS4105I",
"MQ_LOGGING_CONSOLE_FORMAT=json",
},
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
jsonLogs, errJson := waitForMessageInLog(t, cli, id, "CWWKF0011I")
if errJson != nil {
t.Errorf("%v", errJson)
}
if strings.Contains(jsonLogs, "AMQ6206I") {
t.Errorf("Logging source is set to web, Qmgr message \"%v\" should be excluded!!!", jsonLogs)
}
if strings.Contains(jsonLogs, "AMQ5041I") || strings.Contains(jsonLogs, "AMQ5052I") ||
strings.Contains(jsonLogs, "AMQ5051I") || strings.Contains(jsonLogs, "AMQ5037I") ||
strings.Contains(jsonLogs, "AMQ5975I") || strings.Contains(jsonLogs, "CWWKG0028A") ||
strings.Contains(jsonLogs, "CWWKS4105I") {
t.Errorf("Expected to exclude messageId by default; but messageId \"%v\" is present", jsonLogs)
}
// Stop the container cleanly
stopContainer(t, cli, id)
}
// TestLoggingConsoleSetToQmgr test sets LOG_FORMAT to BASIC and MQ_LOGGING_CONSOLE_FORMAT to
// json and check that log is in json format
func TestLoggingConsoleSetToQmgr(t *testing.T) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=qm1",
"MQ_ENABLE_EMBEDDED_WEB_SERVER=false",
"MQ_LOGGING_CONSOLE_SOURCE=qmgr",
"LOG_FORMAT=BASIC",
"MQ_LOGGING_CONSOLE_FORMAT=json",
},
}
id := runContainer(t, cli, &containerConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
jsonLogs, errJson := waitForMessageInLog(t, cli, id, "AMQ6206I")
if errJson != nil {
t.Errorf("%v", errJson)
}
isMessageFound := scanForExcludedEntries(jsonLogs)
if isMessageFound == true {
t.Errorf("Expected to exclude messageId by default; but messageId \"%v\" is present", jsonLogs)
}
isValidJSON := checkLogForValidJSON(jsonLogs)
if !isValidJSON {
t.Fatalf("Expected all log lines to be valid JSON. But got error %v ", err)
}
// Stop the container cleanly
stopContainer(t, cli, id)
}
// Test queue manager with both personal and CA certificate having the same DN
func TestSameSubDNError(t *testing.T) {
expectedOutput := "Error: The Subject DN of the Issuer Certificate and the Queue Manager are same"
utilSubDNTest(t, "../tlssamesubdn", "true", expectedOutput, false)
}
// Test queue manager with both personal and CA certificate having the same DN
// but override the changed behavior via environment variable
func TestSameSubDNErrorOverride(t *testing.T) {
expectedOutput := "Failed to relabel certificate for"
utilSubDNTest(t, "../tlssamesubdn", "false", expectedOutput, false)
}
// Test queue manager with root CA certificate
func TestWithCASignedCerts(t *testing.T) {
expectedOutput := "Creating queue manager MQQM"
utilSubDNTest(t, "../tlsdifferentsubdn", "true", expectedOutput, true)
}
// Test queue manager with intermediate CA certificate
func TestWithIntermediateCASignedCerts(t *testing.T) {
expectedOutput := "Creating queue manager MQQM"
utilSubDNTest(t, "../tlsintermediateca", "true", expectedOutput, true)
}
// Scan the console output for required content.
func scanForText(output string, prefix string, findText string) (int, bool) {
var count int
var found bool
scanner := bufio.NewScanner(strings.NewReader(output))
for scanner.Scan() {
s := scanner.Text()
if strings.HasPrefix(s, prefix) {
count++
}
if strings.Contains(s, findText) {
found = true
}
}
return count, found
}
// Utility function to test Certificate relabel issues.
func utilSubDNTest(t *testing.T, certPath string, overrideFlag string, expecteOutPut string, waitLong bool) {
t.Parallel()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=QM1",
"MQ_ENABLE_CERT_VALIDATION=" + overrideFlag,
},
Image: imageName(),
}
hostConfig := container.HostConfig{
Binds: []string{
coverageBind(t),
tlsDirDN(t, false, certPath) + ":/etc/mqm/pki/keys/QM1",
},
}
networkingConfig := network.NetworkingConfig{}
ctr, err := cli.ContainerCreate(context.Background(), &containerConfig, &hostConfig, &networkingConfig, t.Name())
if err != nil {
t.Fatal(err)
}
defer cleanContainer(t, cli, ctr.ID)
startContainer(t, cli, ctr.ID)
if waitLong {
waitForReady(t, cli, ctr.ID)
_, output := execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "echo 'DISPLAY QMGR SSLKEYR CERTLABL SSLFIPS' | runmqsc"})
if !strings.Contains(output, "SSLKEYR(/run/runmqserver/tls/key)") {
t.Errorf("Expected SSLKEYR to be '/run/runmqserver/tls/key' but it is not; got \"%v\"", output)
}
if !strings.Contains(output, "CERTLABL(QM1)") {
t.Errorf("Expected CERTLABL to be 'default' but it is not; got \"%v\"", output)
}
_, output = execContainer(t, cli, ctr.ID, "", []string{"bash", "-c", "runmqakm -cert -list -type cms -db /run/runmqserver/tls/key.kdb -stashed"})
if strings.EqualFold(t.Name(), "TestWithCASignedCerts") {
// There should be one personal certificate and one trusted certificate.
count, found := scanForText(output, "!", "CN=MQMFTQM,OU=ISL,O=IBM,L=BLR,ST=KA,C=IN")
if count != 1 && !found {
t.Errorf("Expected 1 trusted certificate with name containing CN=MQMFTQM. But found %v", output)
}
// One personal certificate that relabeld as QM1
count, found = scanForText(output, "-", "QM1")
if count != 1 && !found {
t.Errorf("Expected 1 personal certificate with name containing QM1. But found %v", output)
}
} else if strings.EqualFold(t.Name(), "TestWithIntermediateCASignedCerts") {
// There should be one personal certificate and two trusted certificates
// an intermediate CA and the root CA.
count, found := scanForText(output, "!", "ST=HANTS,C=GB")
if count != 2 && !found {
t.Errorf("Expected 2 trusted certificate with name containing 'ST=HANTS,C=GB'. But found %v", output)
}
// One personal certificate that is correctly relabeld as QM1
count, found = scanForText(output, "-", "QM1")
if count != 1 && !found {
t.Errorf("Expected 1 personal certificate with name containing QM1. But found %v", output)
}
}
} else {
rc := waitForContainer(t, cli, ctr.ID, 20*time.Second)
// Expect return code 1 if container failed to create.
if rc == 1 {
// Get container logs and search for specific message.
logs := inspectLogs(t, cli, ctr.ID)
if !strings.Contains(logs, expecteOutPut) {
t.Errorf("Container creating failed because of invalid certifates")
}
} else {
// Some other error occurred
t.Errorf("Some other error occurred %v", rc)
}
}
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2023
© Copyright IBM Corporation 2017, 2022
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -745,7 +745,6 @@ func inspectLogs(t *testing.T, cli *client.Client, ID string) string {
t.Fatal(err)
}
buf := new(bytes.Buffer)
// Each output line has a header, which needs to be removed
_, err = stdcopy.StdCopy(buf, buf, reader)
if err != nil {
@@ -890,99 +889,3 @@ func getMQVersion(t *testing.T, cli *client.Client) (string, error) {
version := inspect.ContainerConfig.Labels["version"]
return version, nil
}
// scanForExcludedEntries scans for default excluded messages
func scanForExcludedEntries(msg string) bool {
if strings.Contains(msg, "AMQ5041I") || strings.Contains(msg, "AMQ5052I") ||
strings.Contains(msg, "AMQ5051I") || strings.Contains(msg, "AMQ5037I") ||
strings.Contains(msg, "AMQ5975I") {
return true
}
return false
}
// checkLogForValidJSON checks if the message is in Json format
func checkLogForValidJSON(jsonLogs string) bool {
scanner := bufio.NewScanner(strings.NewReader(jsonLogs))
for scanner.Scan() {
var obj map[string]interface{}
s := scanner.Text()
err := json.Unmarshal([]byte(s), &obj)
if err != nil {
return false
}
}
return true
}
// runContainerWithAllConfig creates and starts a container, using the supplied ContainerConfig, HostConfig,
// NetworkingConfig, and container name (or the value of t.Name if containerName="").
func runContainerWithAllConfigError(t *testing.T, cli *client.Client, containerConfig *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (string, error) {
if containerName == "" {
containerName = t.Name()
}
if containerConfig.Image == "" {
containerConfig.Image = imageName()
}
// Always run as a random user, unless the test has specified otherwise
if containerConfig.User == "" {
containerConfig.User = generateRandomUID()
}
// if coverage
containerConfig.Env = append(containerConfig.Env, "COVERAGE_FILE="+t.Name()+".cov")
containerConfig.Env = append(containerConfig.Env, "EXIT_CODE_FILE="+getExitCodeFilename(t))
t.Logf("Running container (%s)", containerConfig.Image)
ctr, err := cli.ContainerCreate(context.Background(), containerConfig, hostConfig, networkingConfig, containerName)
if err != nil {
return "", err
}
err = startContainerError(t, cli, ctr.ID)
if err != nil {
return "", err
}
return ctr.ID, nil
}
func startContainerError(t *testing.T, cli *client.Client, ID string) error {
t.Logf("Starting container: %v", ID)
startOptions := types.ContainerStartOptions{}
err := cli.ContainerStart(context.Background(), ID, startOptions)
if err != nil {
return err
}
return nil
}
// testLogFilePages validates that the specified number of logFilePages is present in the qm.ini file.
func testLogFilePages(t *testing.T, cli *client.Client, id string, qmName string, expectedLogFilePages string) {
catIniFileCommand := fmt.Sprintf("cat /var/mqm/qmgrs/" + qmName + "/qm.ini")
_, iniContent := execContainer(t, cli, id, "", []string{"bash", "-c", catIniFileCommand})
if !strings.Contains(iniContent, "LogFilePages="+expectedLogFilePages) {
t.Errorf("Expected qm.ini to contain LogFilePages="+expectedLogFilePages+"; got qm.ini \"%v\"", iniContent)
}
}
//waitForMessageInLog will check for a particular message with wait
func waitForMessageInLog(t *testing.T, cli *client.Client, id string, expecteMessageId string) (string, error) {
var jsonLogs string
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
for {
select {
case <-time.After(1 * time.Second):
jsonLogs = inspectLogs(t, cli, id)
if strings.Contains(jsonLogs, expecteMessageId) {
return jsonLogs, nil
}
case <-ctx.Done():
return "", fmt.Errorf("Expected message Id %s was not logged.", expecteMessageId)
}
}
}
// Returns fully qualified path
func tlsDirDN(t *testing.T, unixPath bool, certPath string) string {
return filepath.Join(getCwd(t, unixPath), certPath)
}

View File

@@ -20,7 +20,7 @@ require (
require (
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Microsoft/go-winio v0.5.1 // indirect
github.com/containerd/containerd v1.6.6 // indirect
github.com/containerd/containerd v1.6.3 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect

View File

@@ -18,8 +18,8 @@ github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0=
github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0=
github.com/containerd/containerd v1.6.3 h1:JfgUEIAH07xDWk6kqz0P3ArZt+KJ9YeihSC9uyFtSKg=
github.com/containerd/containerd v1.6.3/go.mod h1:gCVGrYRYFm2E8GmuUIbj/NGD7DLZQLzSJQazjVKDOig=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2019, 2022
© Copyright IBM Corporation 2019, 2020
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@ limitations under the License.
package main
import (
"context"
"strings"
"testing"
"time"
@@ -93,28 +92,15 @@ func TestMultiInstanceContainerStop(t *testing.T) {
waitForReady(t, cli, qm1aId)
waitForReady(t, cli, qm1bId)
err, originalActive, originalStandby := getActiveStandbyQueueManager(t, cli, qm1aId, qm1bId)
err, active, standby := getActiveStandbyQueueManager(t, cli, qm1aId, qm1bId)
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
stopContainer(t, cli, originalActive)
stopContainer(t, cli, active)
for {
status := getQueueManagerStatus(t, cli, originalStandby, "QM1")
select {
case <-time.After(1 * time.Second):
if status == "Running" {
t.Logf("Original standby is now the active")
return
} else if status == "Starting" {
t.Logf("Original standby is starting")
}
case <-ctx.Done():
t.Fatalf("%s Timed out waiting for standby to become the active. Status=%v", time.Now().Format(time.RFC3339), status)
}
if status := getQueueManagerStatus(t, cli, standby, "QM1"); strings.Compare(status, "Running") != 0 {
t.Fatalf("Expected QM1 to be running as active queue manager, dspmq returned status of %v", status)
}
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2019, 2022
© Copyright IBM Corporation 2019
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -77,7 +77,6 @@ func getActiveStandbyQueueManager(t *testing.T, cli *client.Client, qm1aId strin
func getQueueManagerStatus(t *testing.T, cli *client.Client, containerID string, queueManagerName string) string {
_, dspmqOut := execContainer(t, cli, containerID, "", []string{"bash", "-c", "dspmq", "-m", queueManagerName})
t.Logf("dspmq for %v (%v) returned: %v", containerID, queueManagerName, dspmqOut)
regex := regexp.MustCompile(`STATUS\(.*\)`)
status := regex.FindString(dspmqOut)
status = strings.TrimSuffix(strings.TrimPrefix(status, "STATUS("), ")")

View File

@@ -16,9 +16,9 @@ limitations under the License.
package main
import (
"github.com/docker/docker/client"
"strings"
"testing"
"github.com/docker/docker/client"
)
// TestNativeHABasic creates 3 containers in a Native HA queue manager configuration
@@ -217,96 +217,3 @@ func TestNativeHASecureCipherSpec(t *testing.T) {
}
}
// TestNativeHASecure creates 3 containers in a Native HA queue manager configuration
// with HA TLS FIPS enabled, overrides the default CipherSpec, and ensures the queue manger
// and replicas start as expected. This test uses FIPS compliant cipher.
func TestNativeHASecureCipherSpecFIPS(t *testing.T) {
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
version, err := getMQVersion(t, cli)
if err != nil {
t.Fatal(err)
}
if version < "9.2.2.0" {
t.Skipf("Skipping %s as test requires at least MQ 9.2.2.0, but image is version %s", t.Name(), version)
}
containerNames := [3]string{"QM1_1", "QM1_2", "QM1_3"}
qmReplicaIDs := [3]string{}
qmNetwork, err := createBridgeNetwork(cli, t)
if err != nil {
t.Fatal(err)
}
defer removeBridgeNetwork(cli, qmNetwork.ID)
for i := 0; i <= 2; i++ {
containerConfig := getNativeHAContainerConfig(containerNames[i], containerNames, defaultHAPort)
// MQ_NATIVE_HA_CIPHERSPEC is set a FIPS compliant cipherspec.
containerConfig.Env = append(containerConfig.Env, "MQ_NATIVE_HA_TLS=true", "MQ_NATIVE_HA_CIPHERSPEC=TLS_RSA_WITH_AES_128_GCM_SHA256", "MQ_ENABLE_FIPS=true")
hostConfig := getNativeHASecureHostConfig(t)
networkingConfig := getNativeHANetworkConfig(qmNetwork.ID)
ctr := runContainerWithAllConfig(t, cli, &containerConfig, &hostConfig, &networkingConfig, containerNames[i])
defer cleanContainer(t, cli, ctr)
qmReplicaIDs[i] = ctr
}
waitForReadyHA(t, cli, qmReplicaIDs)
// Display the contents of qm.ini
_, qmini := execContainer(t, cli, qmReplicaIDs[0], "", []string{"cat", "/var/mqm/qmgrs/QM1/qm.ini"})
if !strings.Contains(qmini, "SSLFipsRequired=Yes") {
t.Errorf("Expected SSLFipsRequired=Yes but it is not; got \"%v\"", qmini)
}
_, err = getActiveReplicaInstances(t, cli, qmReplicaIDs)
if err != nil {
t.Fatal(err)
}
}
// TestNativeHASecure creates 3 containers in a Native HA queue manager configuration
// with HA TLS FIPS enabled with non-FIPS cipher, overrides the default CipherSpec, and
// ensures the queue manger and replicas don't start as expected
func TestNativeHASecureCipherSpecNonFIPSCipher(t *testing.T) {
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
t.Fatal(err)
}
version, err := getMQVersion(t, cli)
if err != nil {
t.Fatal(err)
}
if version < "9.2.2.0" {
t.Skipf("Skipping %s as test requires at least MQ 9.2.2.0, but image is version %s", t.Name(), version)
}
containerNames := [3]string{"QM1_1", "QM1_2", "QM1_3"}
qmReplicaIDs := [3]string{}
qmNetwork, err := createBridgeNetwork(cli, t)
if err != nil {
t.Fatal(err)
}
defer removeBridgeNetwork(cli, qmNetwork.ID)
for i := 0; i <= 2; i++ {
containerConfig := getNativeHAContainerConfig(containerNames[i], containerNames, defaultHAPort)
// MQ_NATIVE_HA_CIPHERSPEC is set a FIPS non-compliant cipherspec - SSL_ECDHE_ECDSA_WITH_RC4_128_SHA
containerConfig.Env = append(containerConfig.Env, "MQ_NATIVE_HA_TLS=true", "MQ_NATIVE_HA_CIPHERSPEC=TLS_RSA_WITH_AES_128_GCM_SHA256", "MQ_ENABLE_FIPS=true")
hostConfig := getNativeHASecureHostConfig(t)
networkingConfig := getNativeHANetworkConfig(qmNetwork.ID)
ctr, err := runContainerWithAllConfigError(t, cli, &containerConfig, &hostConfig, &networkingConfig, containerNames[i])
defer cleanContainer(t, cli, ctr)
// We expect container to fail in this case because the cipher is non-FIPS and we have asked for FIPS compliance
// by setting MQ_ENABLE_FIPS=true
if err == nil {
t.Logf("Container start expected to fail but did not. %v", err)
}
qmReplicaIDs[i] = ctr
}
}

View File

@@ -106,7 +106,7 @@ func getActiveReplicaInstances(t *testing.T, cli *client.Client, qmReplicaIDs [3
func waitForReadyHA(t *testing.T, cli *client.Client, qmReplicaIDs [3]string) {
ctx, cancel := context.WithTimeout(context.Background(), 4*time.Minute)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
for {

View File

@@ -16,16 +16,16 @@
# Application build environment (Maven)
###############################################################################
FROM registry.access.redhat.com/ubi8/openjdk-8 as builder
COPY pom.xml ./
COPY pom.xml .
#WORKDIR /usr/src/mymaven
# Download dependencies separately, so Docker caches them
RUN mvn dependency:go-offline install
# Copy source
COPY src ./src
COPY src .
# Run the main build
RUN mvn --offline install
# Print a list of all the files (useful for debugging)
RUN find ./
RUN find .
###############################################################################
# Application runtime (JRE only, no build environment)
@@ -35,4 +35,4 @@ FROM registry.access.redhat.com/ubi8/openjdk-8-runtime
COPY --from=builder /home/jboss/target/*.jar /opt/app/
COPY --from=builder /home/jboss/target/lib/*.jar /opt/app/
USER 1001
ENTRYPOINT ["java", "-classpath", "/opt/app/*", "org.junit.platform.console.ConsoleLauncher", "--fail-if-no-tests", "-p", "com.ibm.mqcontainer.test", "--details", "verbose"]
ENTRYPOINT ["java", "-classpath", "/opt/app/*", "org.junit.platform.console.ConsoleLauncher", "-p", "com.ibm.mqcontainer.test", "--details", "verbose"]

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2022
© Copyright IBM Corporation 2018, 2021
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -82,10 +82,11 @@ class JMSTests {
boolean ibmjre = System.getenv("IBMJRE").equals("true");
if (ibmjre){
System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "true");
factory.setSSLCipherSuite("SSL_RSA_WITH_AES_128_CBC_SHA256");
} else {
System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false");
factory.setSSLCipherSuite("TLS_RSA_WITH_AES_128_CBC_SHA256");
}
factory.setSSLCipherSuite(System.getenv("MQ_TLS_CIPHER"));
}
return factory;
}

View File

@@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIUc5EKoPi8cg2M2n+SqCPn44LFjoAwDQYJKoZIhvcNAQEL
BQAwcjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMREwDwYDVQQHDAhOZXcgWW9y
azEMMAoGA1UECgwDSUJNMQwwCgYDVQQLDANJQk0xDDAKBgNVBAMMA0lCTTEZMBcG
CSqGSIb3DQEJARYKbXFAaWJtLmNvbTAeFw0yMjEwMDYxMzA2NTVaFw0zMjEwMDMx
MzA2NTVaMHIxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTERMA8GA1UEBwwITmV3
IFlvcmsxDDAKBgNVBAoMA0lCTTEMMAoGA1UECwwDSUJNMQwwCgYDVQQDDANJQk0x
GTAXBgkqhkiG9w0BCQEWCm1xQGlibS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQCls3oNIDxzKct0NXVsoz1Hng3BcaDPcBRYCNgAEwDOVe3rEEbZ
d2KFliDgCG3hCHMM1Yaabx3iTVsKklubBxr1JFmyDtgb4z9mJpMVYXS+gsKsZOs/
vNSmzpt5VlbEadHKJ/aFf/EWxvoOP80UiEeUJt36aWFUTyjjyArd2xS8fD1DATFB
U2bteaWfkpuLeFiTtwftZhsLv1s5T35+Ex087eX1tkm/TArxZsNl/9RrSWsbJh/t
bjiRKn+fCZdirFsurP3Si5Jd9laCW0RBKAKYEh40XYDgjLhvcazDPTBueTHXQPG5
S0hCOhCJiCWpPCsh8rIOCz0D9YIByZADR1WvAgMBAAGjUzBRMB0GA1UdDgQWBBS5
OsiPqZXlMwpMqGKczUg3qVvy0zAfBgNVHSMEGDAWgBS5OsiPqZXlMwpMqGKczUg3
qVvy0zAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBfwYRcckke
/NzDHlFb8TBlUDqERmlT/qTWamVZO2Zuo4Y0BFOYFEA23F5sQU2s2MFSEZcAKe5v
mJroFE2rr4aY4bJ4Z0UXlOAYyqNxVOTI4MIxwbg3GVr8c8oWBnAmgqI9W9OpgZ52
/bN24XL9s6I3TeOTtYI9z5O70Kl/E3nG8GcfMw0EtNIy0UPUWvJH8FgEsotsRO9v
tPtlZklEK/D+Keozbs2shdNhKgVnDatpdTBqvwLztb1+te5AckuOnJsnG+iIrG2D
Ehoq2O3gktIVdAk4sv2BoONzegLWB+GSxGVZsemfYF4PkN9/w+znz0LK/ATAtabK
rikk0yC+Xg8z
-----END CERTIFICATE-----

View File

@@ -1,34 +0,0 @@
#!/bin/bash -ex
# -*- mode: sh -*-
# © Copyright IBM Corporation 2018, 2022
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
KEY=server.key
CERT=server.crt
CACERT=cacert.crt
CAPEM=rootcakey.pem
# Create a private key and certificate in PEM format, for the server to use
openssl req \
-newkey rsa:2048 -nodes -keyout ${KEY} \
-subj "/CN=localhost" \
-addext "subjectAltName = DNS:localhost" \
-x509 -days 3650 -out ${CERT}
# Generate the private key of the root CA
openssl genrsa -out ${CAPEM} 2048
#Generate the self-signed root CA certificate. Manual input is required when prompted
openssl req -x509 -sha256 -new -nodes -key ${CAPEM} -days 3650 -out ${CACERT}

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEApbN6DSA8cynLdDV1bKM9R54NwXGgz3AUWAjYABMAzlXt6xBG
2XdihZYg4Aht4QhzDNWGmm8d4k1bCpJbmwca9SRZsg7YG+M/ZiaTFWF0voLCrGTr
P7zUps6beVZWxGnRyif2hX/xFsb6Dj/NFIhHlCbd+mlhVE8o48gK3dsUvHw9QwEx
QVNm7Xmln5Kbi3hYk7cH7WYbC79bOU9+fhMdPO3l9bZJv0wK8WbDZf/Ua0lrGyYf
7W44kSp/nwmXYqxbLqz90ouSXfZWgltEQSgCmBIeNF2A4Iy4b3Gswz0wbnkx10Dx
uUtIQjoQiYglqTwrIfKyDgs9A/WCAcmQA0dVrwIDAQABAoIBAQCcL9ZltPMF4mlh
+lnasuu6K+LvafmYTh7+9CcVutPRqfF+1nLR3NRC8sW+JnPb36kCeepMe1yByUR9
bINoV4QzebYKPi+56bQCx21wg9IVGRACi4WrKISRTsIB1z4mGVCj6pNWNsi7HYbq
E31tUx+VKCWoOdiCLbNvMUn84Npk5npK9P9F86qypSJqJv3HORgOa58x7qZiD2fk
TroLuGHKFWGtSiK1vvgax8gBwMi9JvWoPhwHagINh0WwT820+3/4KbqcsvRNSIu8
qA+ltk/Vt0ftwPMpxPYnvRFrSvzYIRE04fbWqA3mxhPr/oP3xXrwyd1hnX6GzPIR
KXeX1i7BAoGBANGV6XtL8cq8tu/4emOYDn4tncMRICQ8uMWZqnIQAvX8PBx1w9E2
Wbkl0oBHJ/gDtU+feDvbHI0JBvXerce2cxj4+793TGLUl980dgq776x2fcxHjvYZ
uZjJd4M95Lh+IhtWGZQ1FviiylDg62w+mrNydX8WiFjLGYPydQqCIAAxAoGBAMpl
m/MDqpgPxiDU1O9DAq8C/0MQUOc/p+67aGsYxmPDdCouBLA/zckQh6Cp9Wo3n7MF
X5UHOqn72q/4ahNEx+3YQoaLqRKTjUHl3r3zj+MsM0hIDp1uOxVzbANxazuLuqqA
C+yJTmRU7uvNPH1AMFJBKRSmhd3MJwoHF/KZAhvfAoGAFaGPU3ZnIjGP//x5RUYw
WL2EhtmBo7vQpjRR7yvP4muCGL3e0/z0DbPloe+2JFbdo7Ylxqe6rqO74Cx3ayFd
h7pK4VwCukCO3C6h8EGtXvNr0GWiT6wgB7DjcNw2ewQpqQCd6zn/gPHsR6SvJ6De
fp7VmaRNtjxgCcpAYjFD9EECgYAhEPaofjnZvAH/jSX4rPb8Rr4TY9AD58d03lNR
4+tNkzogRgJoFRR2u+ecnQfGQa4qnj8eZt7ztHzm8OvLmBodxo4f0yNdMJQMZxS7
7dXdJHSAY51XpRGsEH5eFaKSSOLHRkIsc8ZF6AZcqdwvDlSWq6SdhhMqyFa8cao8
7TiF+wKBgADNZ4HoZDfnuH5jUvf7y+YlxDX3jxWR+BUTLCJmt082uT+8Xg5SALec
B8GP5s6VKglD5Wzj8IhxvpQ5yzH9DRHwEeu3vFLBinIUlWdBiXwtnbmY0E9r3PSb
pZQH5RZ5PyrJicIVBJSqdFu2HDl4heeLJE0LGh7SQnFaexxXn397
-----END RSA PRIVATE KEY-----

View File

@@ -1,19 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDHzCCAgegAwIBAgIUUFCo8fUglrbfDY8ZUDnzAfWeq54wDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIyMTAwNjEzMDYwMloXDTMyMTAw
MzEzMDYwMlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAxcja4TbshPj4tWgbRP73eDs2382j6Km5TNej6To13PJq
Wyezg081ctmgFEMlgbRiowZmecpYOKjDKuVDtfLE6nZMmN+PjXXuOMGIPu67fx/4
tnaMDYw96WIBEFNVZ7dC/pceaTIRbnjma89o1/mTudTAYPLAvKpeBqpJJFWPMDhz
nK3NKeydTdUYc9jmEJWiFCI4bUdyvyUjp+7QrDbdODXo27/nVAV0Ih+OuU4ZnxT5
cf1fzVV1ZqHd8jbLm25ZoAmkk+9DSXFNA2hbSepf70mRVD/Qyn8U6b5A2v+mWIfs
B1+iAlPl7IX88W1Q9q1yu0uT8YWGWpeTbeOnJ4WJ8wIDAQABo2kwZzAdBgNVHQ4E
FgQUEjp6AtPmpuLQyBPeiW4pW+VGb2wwHwYDVR0jBBgwFoAUEjp6AtPmpuLQyBPe
iW4pW+VGb2wwDwYDVR0TAQH/BAUwAwEB/zAUBgNVHREEDTALgglsb2NhbGhvc3Qw
DQYJKoZIhvcNAQELBQADggEBAL2bTWfTqxfN0YbBPjG05sR4nO8mhbNSGHDuGeiO
OP0wPxkgAueScTpyhHWEAJmMQOMUM9KhByZj7LnqW8XY9BBS3zPAyzAdia8/o6Vl
7El+M2JCfqz7hSupRK8M+r+XUq3hyEFjPLt+KO6D5VNzXiTM+36UueeQD3aaxxyo
LpHSPeXFBkOrT/wt6FHi4NHvWls95PllncWZVYjxPMUUF/o30tOxSmgXwjUknrI8
29ADKM1IbFuXd4vKYG9V+ukI6n5F86PYrN2ajPBKIidvTqU8tPzMHuJZ3YiIiv8p
TARE2b5YLWuu+aF2z/V71MmIWr0uyOk6pZVGOCw7fwHx/wg=
-----END CERTIFICATE-----

View File

@@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDFyNrhNuyE+Pi1
aBtE/vd4OzbfzaPoqblM16PpOjXc8mpbJ7ODTzVy2aAUQyWBtGKjBmZ5ylg4qMMq
5UO18sTqdkyY34+Nde44wYg+7rt/H/i2dowNjD3pYgEQU1Vnt0L+lx5pMhFueOZr
z2jX+ZO51MBg8sC8ql4GqkkkVY8wOHOcrc0p7J1N1Rhz2OYQlaIUIjhtR3K/JSOn
7tCsNt04Nejbv+dUBXQiH465ThmfFPlx/V/NVXVmod3yNsubblmgCaST70NJcU0D
aFtJ6l/vSZFUP9DKfxTpvkDa/6ZYh+wHX6ICU+XshfzxbVD2rXK7S5PxhYZal5Nt
46cnhYnzAgMBAAECggEBAKLRsZZbf6QLzbqRBHntJ04b+RWOlVOQfRHMJ4x1Nig4
i+OUsEv1pftxOj3T9QlstRKdzziNociq7VffurkLLJ4TWwUybVu37K9easncABAs
ArQ6rRruC32YB2YoJBOoowcw4oEZDY6TCqVP7nB1be46PVDSJmZqHdOA1YuKv8Ci
FbzLZEKYy6QGmHp9xMzc3usQ+KRNIFcR3NJb0eCbfAXb0tP3F12i4ygnxifkOVQS
hukTJlZVbAO3W9uUEzLh5bkLoPfob6Vrwv1tGQ48uFgzgPXc4bWOUDFXHW5+vQLD
1MKFboozrNhRR+Q5xvbRnaWEv4hMHlUNggc5ErRj6CkCgYEA5m5f1VfhfqSvEF2c
XcIfUDiCzREpllY2ZdBSfUlz/GA6f0QUyFJBCdd4ypipQcggn60de9DoKDcNcq32
rfVfANpsciJq9s4+xLL8MGtUuoi4HK8LHP3tc8aJaAcCVjBFbz0orKXDUOcue6A5
Z5riDjiXOE56XSLSSNSRjWh4psUCgYEA27sfaM4J0YkdFuth/Qu+X9PeroUZyC0T
3glMN/7PU4jZg+2v4Psfe61gj8qOt0catuWvsD0wQTy3jt+svY/KfkbspK6/7CEG
fKx1AB1xeMr4JuQp9POFVhKRn4sBUMbHOkbjzlNpGmUI2arlLRTwT8YpuMDjCK4l
ZuUYB/IHOVcCgYAqexqryCHIKTAlAjz7g/gl3+UtTQavsoEg0AEFG++IDW17XN+/
9noLCHA6WV6KxAxPo6iV1POXxl5yT+P0OhIjpCDuAa5ahbdIp/6aJo9ePCpFD3gr
Bh0qhOV8Ch7CKPAEC/Bds8mINrZ5EBbFJOab3I70UHN6jBrcVmPm/+WOSQKBgQCW
AbBWt1qCnu2qCPWzcAH+n8DFOf645vVKPuS20ZEuwR1l8K2ClU4P+/QRFkLKIpO9
Sx7e3VcFInNZ6Z+fJfwiqz7AysAhbwZjtMSHWJJv2XkB7AAsxtc/RJv/5ED4qUu3
oE/DOrRlHZamKwIb/dB1VZ6ED8Ku2VyVW09FlViTLwKBgEU21xqvP1+TXzsrZNGm
/Hj/RAaA8B6tyo5Dj9glV80oakMSaxBsLP9xHkoZjkHaJnoFosKBQSnCcPnEY4gP
22WEyGshu8sujLibLKWhARqjeubatXv+XBxiDdMbgcd/XTwbI4HTjXy5LF0o47UI
W6itMOg9uCfBJM/i2jrAkmQR
-----END PRIVATE KEY-----

View File

@@ -1,21 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDiTCCAnECFClOtyvBoQXVAGMcX0ObUawZJuYAMA0GCSqGSIb3DQEBCwUAMH0x
CzAJBgNVBAYTAklOMQswCQYDVQQIDAJLQTEMMAoGA1UEBwwDQkxSMQwwCgYDVQQK
DANJQk0xDDAKBgNVBAsMA0lTTDEQMA4GA1UEAwwHTVFNRlRRTTElMCMGCSqGSIb3
DQEJARYWc2hhc2hpa2FudGhAaW4uaWJtLmNvbTAeFw0yMzAxMjUwNjQzMTBaFw0y
NTA0MjkwNjQzMTBaMIGEMQswCQYDVQQGEwJVUzELMAkGA1UECAwCSUwxEDAOBgNV
BAcMB0NISUNBR08xEDAOBgNVBAoMB0J1cnJhZ28xCzAJBgNVBAsMAkJHMRAwDgYD
VQQDDAdNUVFNQ05UMSUwIwYJKoZIhvcNAQkBFhZzaGFzaGlrYW50aEBpbi5pYm0u
Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAys3CaU4vXdZuKyw5
AMkM4onEiJk3/TulWZIrXvFMgYLzAPX5eVUzs+eKfSBVIRiDGtsbmhcztT1GiAU6
l8G9jHSegItJpKjiBEfFEuMmV6Fhx7ZjQdpyGdV+0bcE2IJHmeiaNxouvsV5gBJT
vEamVsw9zU7GGOhhMyBQUUQDNy7yoHn8CBhDdoBskwJtpqPcxzohUDDt5wqSqOUl
jo8yS375k4Q18hWzWIxJIAHoAFk+YyJqLq3mqq438Z9WSgjv9V+eLpNtKlge2IzW
d1uH/siXE8Pp6p3WleG7cw2dzQZap+ekbx+3rRVLs8WYBHeTx08980sv6bBUKwHw
aXXXSQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAMrE0nDBw8wfPR8w7hrUPyG1Ib
/k72yAv9wqaso1pL4IpXE3DFbuoIOQLjNCr+C7h2IzegRZ1z4kZbWh7LeES7M0io
yDgM16Vikr9ek+NCLmF5QAtn/smhfhSEOjJoGkTPUTdWR4VdLeMFGQ9D8LHc0DFP
EyPZy0JZQpRiXAs0ZEDhlFOCxI1aZzJhwGBJd9wOlG/SZKI8izC74mNPU1eE7Js6
1sdU+4zs2wm/QtZ1MLlkKspSQqdNis/wpSSyjTEr9TkfzxVr4f3bALjQydkrcAyv
BkATBYqvJYSHA3PS8VxNTDVef5EgKEWXlCmP/jfMcYNsUxBjaUcqiJJcmI9e
-----END CERTIFICATE-----

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAys3CaU4vXdZuKyw5AMkM4onEiJk3/TulWZIrXvFMgYLzAPX5
eVUzs+eKfSBVIRiDGtsbmhcztT1GiAU6l8G9jHSegItJpKjiBEfFEuMmV6Fhx7Zj
QdpyGdV+0bcE2IJHmeiaNxouvsV5gBJTvEamVsw9zU7GGOhhMyBQUUQDNy7yoHn8
CBhDdoBskwJtpqPcxzohUDDt5wqSqOUljo8yS375k4Q18hWzWIxJIAHoAFk+YyJq
Lq3mqq438Z9WSgjv9V+eLpNtKlge2IzWd1uH/siXE8Pp6p3WleG7cw2dzQZap+ek
bx+3rRVLs8WYBHeTx08980sv6bBUKwHwaXXXSQIDAQABAoIBAQCdbqs7yij1BG/T
ben2VRx+g4ogrCiNmY7bgJ/QfSrx4vC3TztR2DVhtB2K0t2i6n9kCrFbpiVKzX2C
O+TnR8vYS/N7QCV0AHIr9nbjGZh7MFlSiqB0z5oBuf1P2W6WkFP7A1kr61RcXbnb
FN8R6hpYiQZ06XDYhxRldvFClLSWUaZOhM6DoEcfNV5djDWPv4tSlw0ILvgIDfeu
DfW5d6ih51CT+NqtXUZNgWB4WCFrqxLz2H197QtFNbeEnT2kqU81LiSR6ZLU2LAc
SEhWD9xpldPvm6CsYDy9LQazG+F4KA45OGgiHUfB43EvGnDHJEeX4HFMFWYKmefa
VQRD5GKBAoGBAPEQXruYnfYk3B+arl4GWCZd37TQd4ik2HybkhxPK/LXLJhuImun
6gYu0Y5dSpBv0B6LjhTencAjgfZRSiCplxbnnPMg2Tuu1FAjG7W5UlKsT8IlmHR3
3LqublsCQDaww/pBlXMsT7TUe89uH05v5Fn4pwp5Hy6IArhJLecDoYk5AoGBANde
hrLVn0XhFwQWe11vbhclF9KtJHqspXhKX6mRcQ4VSzoGuaji+ISyfoCaU6kVQrq8
WCZIOcTJTDScrk3BYQbY0+I6hBIug3SXhR8pGshQHvGOC/pAUInzWO3xc3lbJAwR
aK70zN8wXFJjc1rOivMY/mRvdJSYlPmr2e5fJg6RAoGAEj97/FVsN7LImvfZlTKD
v7vBcG2LbuOTo7MfF1eC6yoQrSVBI8cdNwSaRl2XhGGCbp1/zuKfLGlDsEKtCtXr
owc7YUguSY9NcReHRHVX3vw+OWMhLEfahKMppWgBNmKhIzONvZ8wFW80RBqA8i4U
Kh9hfbB3hM0074BSojcrJjkCgYEApavzVjJ6WRjzyZM5xwBm4asJDmlefHe+ujAM
MrbNDxZWTgbKXx5qKjnckjUlUhYmxNsJvDknJzfqRTaZ5vpxFwFIzOhSnGHngZLl
Nrk5/wmTJCIvGIzM57GooTFxsNLpgdcKfjuWNcJP4pjaLepgfOynFL+gIIbXYtBN
zs6myeECgYBp2shsVXAo0G2Iw5qSrPmsC0WurVYv5jZSAcnbV468vgGKP+L65nou
c7iuLWFJdsvgZUXWyijsQNmkOpNDkfYxcimFtNWMzt2IcoAEQzk5VO0Ok6EfrVCr
S1Kj0bo7oOyy0eZfQKVs39gE+ZKc8Fn2s4w4l6ZayhTKcfW6lwrJJA==
-----END RSA PRIVATE KEY-----

View File

@@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID2zCCAsOgAwIBAgIUdbPSj6WWhFu2amL9voKbyCMKiB4wDQYJKoZIhvcNAQEL
BQAwfTELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAktBMQwwCgYDVQQHDANCTFIxDDAK
BgNVBAoMA0lCTTEMMAoGA1UECwwDSVNMMRAwDgYDVQQDDAdNUU1GVFFNMSUwIwYJ
KoZIhvcNAQkBFhZzaGFzaGlrYW50aEBpbi5pYm0uY29tMB4XDTIzMDEyNTA1MjEz
NloXDTI4MDEyNDA1MjEzNlowfTELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAktBMQww
CgYDVQQHDANCTFIxDDAKBgNVBAoMA0lCTTEMMAoGA1UECwwDSVNMMRAwDgYDVQQD
DAdNUU1GVFFNMSUwIwYJKoZIhvcNAQkBFhZzaGFzaGlrYW50aEBpbi5pYm0uY29t
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwl9MlmCNG7kzk7qKGuBX
jTONcn2OcifKfwgJlvzTqHcf8X/BIiyOOiwoeznke///LLtt9ygF0iyBMQYM/CG/
rzOR6tbzI4y4Bmx6VqY02CkXi/p66ywQ7B5N2Fdp9Bop3SnthTcT4NoXBSEUhI1O
ob8lDFv1KMRkCULD2sA0FUYCrHtw0M/vEOqsA9VVjyzOXsIlbbR1BSXtlWNneGeL
OAdmQWO3QYCku/YrCyJlscvIisjp4s7guGnQh0Ws8h50R5sqag8RvdHUwExVLUfZ
L1Od0+hCiO5mNfKekT0cs9owplcwgNHw88b8q4/aHDBtQRgsukkMxTpo00ftPJxI
nwIDAQABo1MwUTAdBgNVHQ4EFgQUOyw89AeB0jXb5WCZv/5oDY8oWxkwHwYDVR0j
BBgwFoAUOyw89AeB0jXb5WCZv/5oDY8oWxkwDwYDVR0TAQH/BAUwAwEB/zANBgkq
hkiG9w0BAQsFAAOCAQEAtbybQQ9GpY5gH7xz4EWOUZ7XMmBYtuGXVrqUd+76hvCA
H/SB0nl2bGp7tAKBttmXhfKVac6wFCbXvYe49B+Q9+iL7H9st9VZUPKLQ6K3Uet6
L1ggMm2BhecpuYbwkG7ZidVFo/SuUCbCTnXBgHjvq4IkVCaJe7aKZmejSCh7gsIR
BQkZvz/22Vx/WPTEYp0x/riIvSViBjLCuD25Y+nCtS8c2xGVBjs9Q4GWCOAvEfAr
Tqs42brH1Vs92xS143p2h/wv52tmhfJI6X9QVQBBUoIjPR/VDFqZU5EYhAvuQPBi
UADz9hNYGQ9wBzZGvzbrorpoT+7aW9nGtmUsvvupBA==
-----END CERTIFICATE-----

View File

@@ -1,3 +0,0 @@
This directory contains private key and a certificate that signed by CA.
The directory also contains the CA certificate. The certificate and it's
CA certificate have different Subject DNs.

View File

@@ -1,68 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF5DCCA8ygAwIBAgICEAAwDQYJKoZIhvcNAQENBQAwgYsxCzAJBgNVBAYTAkdC
MQ4wDAYDVQQIDAVIQU5UUzETMBEGA1UEBwwKV2luY2hlc3RlcjEMMAoGA1UECgwD
SUJNMQ8wDQYDVQQLDAZIVVJJQk0xETAPBgNVBAMMCEhVUklCTUdCMSUwIwYJKoZI
hvcNAQkBFhZzaGFzaGlrYW50aEBpbi5pYm0uY29tMB4XDTIzMDEyODAyMjEyNFoX
DTMzMDEyNTAyMjEyNFowdjELMAkGA1UEBhMCR0IxDjAMBgNVBAgMBUhBTlRTMQww
CgYDVQQKDANJQk0xDzANBgNVBAsMBkhVUklCTTERMA8GA1UEAwwISFVSSUJNR0Ix
JTAjBgkqhkiG9w0BCQEWFnNoYXNoaWthbnRoQGluLmlibS5jb20wggIiMA0GCSqG
SIb3DQEBAQUAA4ICDwAwggIKAoICAQDyTaomebXQXMGAs3ux3SSJnJseozpUIWS2
eUMG8U3YK81raVpFsGPcjDi4RdCo72SqwD3LKKJmyfz4NOlKpZJq5rhqaHkECRj/
GUKihl6Fr4OWlcJui/x4xeJmgFHvgnQEH/r8mvVVE8GqKHX9mRVOMaJtG14hm1qI
DoK+x9IwOut/H5FMeici/C11xIDK65/54vztb4wEfyRNK5e8dFwuD9yJo2gYM0GB
csQTq5WbKr0/uMF9rfFEx0lybHEASqgLCUA5lAGFtexefCFNxOxLnP4U2c5J+bcR
rGQ/hpfw02m0UU+fuNba8GPJbXJ6zT+FP0kme0180OKmH1zcNDRJuGY6OQ1nICHc
hf9QF95XQcwkf4MIltxZiNHbhSLuHrNFImv/AxiFchQJ+KPMLHV23x1uVKvRK3Mg
ZOEZmtCZVTRbOF6AWSTMGblu1tuxjSohO9ycqk8yQk/YkHW3zuEiIV+AAZW6qMKI
UZK64AoFb+E79gRpamz3ZOFfzNn/nKT4eMovDUUa8W4sVOVjBP2lT87xt7WBsE2f
mK4vE19hQGMzI3jZcMjIwNp4HjKIAeZb8o21ywogGF0qHctoINnEu7nG2trH02ug
0d+hwCfPRQHB7dicwTZm8ute4cHrwXed5tt1Bwv4Rq45GbwaOCAeZWa9S9GUaY/t
9xeS66HLPQIDAQABo2YwZDAdBgNVHQ4EFgQUMIuRPon0lwjMxi5tLwJYRcagTN0w
HwYDVR0jBBgwFoAUMjCCvlMnTcsiRvpiGPgBUGAA0EwwEgYDVR0TAQH/BAgwBgEB
/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQENBQADggIBACPpl2Im9El6
m7T8cmtgXEW+rcQH/AA3px3+J/RnSWyRUi5fb0lc1RkfxQvuG7/sH3ywOc+uuB2b
3lg6zkNaP4tZYTEjrrkj5qFycoQcvem/5nBKuQ18+ZGulHqE+YzcPTmbNO2VzD5e
RJJpboiJa5TtM4wBeIuWbicWN+2wPeOkiQHxHEWtXOEVmbKzuREI6JHg2CDYMpWb
GWqS3hn9hfQoNhtSdtDFGChlsTpgKB/gRpYEfrlLKYKekJafD+xhEl/ZC2JDOtUr
/dZW4JicC++rUrMt89aFzEAOtcaR4dbL4NQhMRAlF9MdjZvHdcJqYEd3wqOymEnV
4ce1VpraZIh3qywqoOqf54vjd5DugpFoxjye+5ynzfMGX6RjwWnVRiY36kjFiMFR
iGhFT74lbRmw86RUQFjiXWAG9R0cR5s0EyOM3Egp/qRkWxbG6z7JeCdUd7Z/aaR3
iT081PUcQsl+jzCw2J6SDkemzZn/spkViodfzGJ5xEXB0fldIDarbDqOeWjSoKaz
LA7qIfPJptJkwybK/hBqvfR5fXx1VuubJdMfbo5jmP4OVCkNV5I6D5EMkYCxPrOl
9eVjYbndAVAXRF8vopJRqe067c+IwKPTnG4iIoXcR28efCBQ0Tv8DXYmHjSlVLdt
UCqYhFBxgGOUJLmqe7O9TWVk/aIM3Q3M
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF9jCCA96gAwIBAgIBADANBgkqhkiG9w0BAQ0FADCBizELMAkGA1UEBhMCR0Ix
DjAMBgNVBAgMBUhBTlRTMRMwEQYDVQQHDApXaW5jaGVzdGVyMQwwCgYDVQQKDANJ
Qk0xDzANBgNVBAsMBkhVUklCTTERMA8GA1UEAwwISFVSSUJNR0IxJTAjBgkqhkiG
9w0BCQEWFnNoYXNoaWthbnRoQGluLmlibS5jb20wHhcNMjMwMTI4MDIxNjIzWhcN
MzMwMTI1MDIxNjIzWjCBizELMAkGA1UEBhMCR0IxDjAMBgNVBAgMBUhBTlRTMRMw
EQYDVQQHDApXaW5jaGVzdGVyMQwwCgYDVQQKDANJQk0xDzANBgNVBAsMBkhVUklC
TTERMA8GA1UEAwwISFVSSUJNR0IxJTAjBgkqhkiG9w0BCQEWFnNoYXNoaWthbnRo
QGluLmlibS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDjTlg8
0bZ3vzeYLJ1Z4zp/HplJSDzAn22EROJtHNb1pyfWfaO7UyUy5jNt1UJ6hTXy1xOS
r9eGaSu3kAm/R/METYgsMM56ALQ458VlLpZUEJBMgu63W6/FTckl5iUno7n9y3qL
2CKkHuEXG9jd/jPhBX+GLc+h1iwe1URaJSe1CLdSc8SMsGZUC3wMO3EAAqEOHh9j
BQy2qeWpR6oAF8HST5JX6lW+k/4NeNthdse8/Oqv1otPzseXE9jz09tz+4Qd5fdt
J8UcCWPcpAFb/TM6S2Hpr8xSqZr5+Em4JimdNDtEbJZKjzSwvmZ4S3qsUP0xb9ad
NgDjxYjBqNStgjrSzKGebazD6U4EDa8dXS6UxqgnxmtcSQLXIPcwfH9FniKnR7Tu
/cmSDOdWCedyxeDjrLlGuFUtJiSXCqRHU8c5KxTVkyDV1YZPjISktVJQS1/n39Lf
2TtHNTH3qTDfPzcgBqqczF+vlIKspE4YcTFBynOlL4biWZEsddOjpoqzamycMBqj
sEMlvydggS+Z8oZqDFVTU9/BCC2mth9HZr7hjO950IQcgVKexXOqxgPP4rmzEl2k
jEp9PKdDqBv7lOYjYO4taegfCZs5FPwaKtCStmzQLERMwSifqXe0TGV5obA8asRY
pOiZf6d9nVBvIYKotB1mNJTMqBke5hom8uarPQIDAQABo2MwYTAdBgNVHQ4EFgQU
MjCCvlMnTcsiRvpiGPgBUGAA0EwwHwYDVR0jBBgwFoAUMjCCvlMnTcsiRvpiGPgB
UGAA0EwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcN
AQENBQADggIBADYAHeWqQEg+oIC5qy8obEul4Zuk5J9HignrP8ef0+wdJf+Zx9/j
3nZKBrUrgZiBP+RJgNYLRByO9QT/q+P5dLfuLikyP377oLlVUcXQIXbJU60Yxdl5
wrpS9O8nfbwMUdi+1foGmA17zYNiTfBZ0/vem6yrhKdP6pS4h1+291tF3+mac0Q1
sx7RhssZT22YclH9u3U4q7Ef3q5ilqV5fb/Rm2z/iGtOLF2swm/jS1CEpJbyb0EE
yF8hoX8oliJdunmUqGV8bK5D7GFx47tyS5lU4B/Q14xBYUUc4hs83xAs667h0fym
0fbyQGh92bASPEDw6ep8eI6Iv+DSniwEFPG0ayDtnSEM/HkRVML497Rhqks/cP/9
rMJe9hUoetKO+p390R22EQLqGT6nvWV1jsGMHIMjJB7kfBLbgvFz8pQQdo7IxK4N
IirFdEn/atri2Z6baT6eqKt2tnjodQs1F+14rK1cj0QbH/tkHF8S411MclmufthB
U+VlEcjr4pnpVzvE4B78kXtlRH1N7Pj+vIgwpiC+hnWcQdqVF58E+7ERz9U1JqaQ
tX9c6aZW4m1pMcxR3c76NnYJi6rmhoL8xUNDq7HXrkK3DM0/rUvxl5HwfgGC0FGS
QmFgXgNddo2pj/TjnssE9XxFjsU+gEbGudGe0p5HR5qlKzTLc44WxcmW
-----END CERTIFICATE-----

View File

@@ -1,34 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF7jCCA9agAwIBAgICEjQwDQYJKoZIhvcNAQENBQAwdjELMAkGA1UEBhMCR0Ix
DjAMBgNVBAgMBUhBTlRTMQwwCgYDVQQKDANJQk0xDzANBgNVBAsMBkhVUklCTTER
MA8GA1UEAwwISFVSSUJNR0IxJTAjBgkqhkiG9w0BCQEWFnNoYXNoaWthbnRoQGlu
LmlibS5jb20wHhcNMjMwMTI4MDM1NTAxWhcNMzMwNTA1MDM1NTAxWjBHMQswCQYD
VQQGEwJJTjELMAkGA1UECAwCS0ExDDAKBgNVBAcMA0JMUjEMMAoGA1UECgwDSUJN
MQ8wDQYDVQQDDAZJQk1JU0wwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCvn7rGrAzGr1BI688hirHC+P1xcI2dUAc1EZx9bQ1mzSAP+9F5hBzT0Ty6ay0Q
zs8qKOs9YpHy1qCrETlrFJxWmd8IYVhT2QoKPxF6jhfYMf6anabtYSRZe1c3v/zi
DyuLuS2XuDeHnfuJl732YTtteYcG4nAx2Y2GcKLnEfNyrB49+ZGbjnNTqIBsR1tD
U96C1h1z4PGtZDxDGbdjGlaB1AJXH9r2tocaS2WyBKo8w9ogTI5d63NYdVvsPKm8
AKwnVLu1kE/xk8/5fraW3tyX4JmCFk4Tt/rf+Oy0dbFfoC9m6JmHPeEopqE9f/qy
m0WpqM3PHuz2Kke7RQ3GNYFDAgMBAAGjggGzMIIBrzAJBgNVHRMEAjAAMBEGCWCG
SAGG+EIBAQQEAwIGQDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQg
U2VydmVyIENlcnRpZmljYXRlMB0GA1UdDgQWBBTaihsw+XFiyTZXn27Y7qpTFQSD
2DCBuQYDVR0jBIGxMIGugBQwi5E+ifSXCMzGLm0vAlhFxqBM3aGBkaSBjjCBizEL
MAkGA1UEBhMCR0IxDjAMBgNVBAgMBUhBTlRTMRMwEQYDVQQHDApXaW5jaGVzdGVy
MQwwCgYDVQQKDANJQk0xDzANBgNVBAsMBkhVUklCTTERMA8GA1UEAwwISFVSSUJN
R0IxJTAjBgkqhkiG9w0BCQEWFnNoYXNoaWthbnRoQGluLmlibS5jb22CAhAAMA4G
A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATBaBgNVHREEUzBRgh1b
RnVsbHkgUXVhbGlmaWVkIERvbWFpbiBOYW1lXYIXW0FueSB2YXJpYXRpb24gb2Yg
RlFETl2CF1tBbnkgdmFyaWF0aW9uIG9mIEZRRE5dMA0GCSqGSIb3DQEBDQUAA4IC
AQCD3iROwkBiSfJ1jCzUdblYawclZE3kX7remHR77sAuGYHEsHhU4PmXUs+A70JJ
jF8gzc1cqMqy4Kwd1BGbNLp9cdtre4TigQ9UqbqxCENyoq0aTIhHmJ5GP3RKMwC1
jaNmH/MUlFhOKZsTLKymkBGCA9GLhD+quU4AIQHMLGoxMIbRZwZzyuGpa7/Gl2Om
f6taMfBsnmFFC+O+saGvu8TG+Q28bGA7wJQM5WMxyVbVY2Lkbb4u2/gDEY1/6T7g
ZkGuCxVlyQ2+dy5teKe7I2AGkgTbwl39i4YMGdj9ZC7ydRIANnNgCuygUTZ3c+w3
PvA33cX7ICWrmrk0y8Ulox7uj1jNi/npdwPkfjyuh9fJpdV4J/BcsQyZ/j4F5Z4B
5MrQeJ7wEELYDv1OOTntyQoqH1HH3TrZ3PFS0whA6gTT76ci2ra85vLVW4SJrbKj
VvDr5VcHE+IsJBedscbP2fO6imkAB74xdkBx9uy7x4aXJi399DHvw6b7mMsbR0om
6CpI0akjprfhdyv4Ri3vvWpWrzHMUMjzLuj6HYopBlFLErMe6WTY1BAh4ljUFKZ0
141/BCkGzNpH/5g1O1QwdQXzEIgUjG16Dm7gM2WKAeJFBttogX2ygTRnVRCZs/fY
JE3CwtxKczC0XteonH/ylGTQQR/0J8Y/ozLAWQxDyzi2Og==
-----END CERTIFICATE-----

View File

@@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCvn7rGrAzGr1BI
688hirHC+P1xcI2dUAc1EZx9bQ1mzSAP+9F5hBzT0Ty6ay0Qzs8qKOs9YpHy1qCr
ETlrFJxWmd8IYVhT2QoKPxF6jhfYMf6anabtYSRZe1c3v/ziDyuLuS2XuDeHnfuJ
l732YTtteYcG4nAx2Y2GcKLnEfNyrB49+ZGbjnNTqIBsR1tDU96C1h1z4PGtZDxD
GbdjGlaB1AJXH9r2tocaS2WyBKo8w9ogTI5d63NYdVvsPKm8AKwnVLu1kE/xk8/5
fraW3tyX4JmCFk4Tt/rf+Oy0dbFfoC9m6JmHPeEopqE9f/qym0WpqM3PHuz2Kke7
RQ3GNYFDAgMBAAECggEAPeL1eEjsf58LlYazCMjM9z2yYaUd4g9vWr4H/RLOpCko
YTmFiWKKngGfermFueSGj/63VnxDneUP3PhG2Xr71HCIbXWQIIvcw9uRlzQ3JtIH
PAjN59xRaM7T3ytiO27JE4V/kXUy7DE5kDTOleGRhXRLpptomchl3LgYT4C93uw+
Pul/KS4PZrGvTD+QnKNd4aOmlEaVLDRcwMqvg96bofE4Qk8LniQB1xEuYUpJFtPm
dBaGmtkTg8M6ghqOYMMqx8qNjqcv/HxIUFbV6F6fmhDOAAvt0gRzhHsmJieYiWFv
Igj/pmJbo/sfcgiiV4g3lEfqP4i9WpMmpVtEbOrvUQKBgQDio+YfKOwO4Pv0soi6
4qPpAZyYvDeQNFYfm0GP/FBuFHUR7dMA88snPZUY8mSgtfG/zoQdcyI3G7HEsugD
redwGoVvp0s9435xW7KCB3tMP3PhmeMjXihQw5cXyJx+LrHjorme5zQ4OkcB23lF
cjN/Yv0ZxRp2wWpOp3F08CvntQKBgQDGX/h3DTx4IHRjfL6jnL8vKJIsxNFhy/Rz
SMMnwAXLmYv29O+rupqsx/MNbM/VA99HqGQt8p2fVEGafYlolaFjICZM6DH5j30B
t1M4LsPZf+fI5vWI9KHwHT1JxCqfqM5GwwHMrEw8pdicr/+FS6O16Kymln/aAILb
sjvpFyLwFwKBgQCO1m06RjhASFuDJOI3po9XUsS3HiiGofWFhfwUGxk1x37hBdpu
RzhKSu2lA1+YShNKp4VsahuuT64CIh9H8lpitNRUQkORhccy+m/Os5hpvbPzA2G7
8KPIAv0+6Bh5DkTfCreiBmVK6q/F4+TSd98s8d5CV48OOWgemjlPUe7Z4QKBgQCu
MiYP/NqFrhImLquFJqantZuunmIy25NcDJ/6bt9n6vyCLpGrniAm6yneNxfFuTG/
TfoycuLAv48gJ26bHRHr5pZbYGZJ/BtMf3wfUMmAW5Xg0Bb6Xb86B6MC/LRlISmJ
78HLxdzoQMYWyWG63jHzEk9RtcStXVeLrlZ3l26BnwKBgHxMtBHvcaXWzRdm1PZ0
2DVFOP5lm/5t5WC8re8L9oeVLt0+yMBEKXUwX66Z1s5iO24CWsHFN8zDjQhVKfZM
/YOxbfjQWYO1LsgJweAEeEauYI+ncMnQEZf1Ei1P8g2X1GTS+n0r4YANawWczp71
tZURwKJSJwKpGMChxucQDJc9
-----END PRIVATE KEY-----

View File

@@ -1,3 +0,0 @@
This directory contains private key and a certificate that signed by intermediate CA.
The directory also contains the intermediate CA certificate and it's root certificate.
The certificate and it's CA certificate have different Subject DNs.

View File

@@ -1,30 +0,0 @@
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIxuHuzG+WcZACAggA
MBQGCCqGSIb3DQMHBAgMKyhajZd/ewSCBMiCL57/BUvVwtxmhaIqQBSjHLnx+AvG
f+frFkwM52KuAg0Q+vF/1iQXMbZRrHpxNz/1t3cIdwzlc9S3FB+L42q0CEH0c1FW
6gB6csmb1AyhGYffwkeT8bPkELJhpO2taIFTynwDhHaeKeDce3EwQ5xQd4ydq1Ku
t4oJZun51J5qvNs91BiHHVB3/q1Lnh4VK4TTDgXTGfu8qcuOexHQcOgko4oemorv
E1Woy6Lf99bePxedSuMIxPAXysSCBqcrZDbY9K3yaxV6Gr7S9FBVvOx9r8PTaFEY
sXxdtB22qM1PqZIIjK6nzwXb5iu8wcaZFatD6y7RQaS0kz5EcS5kExrEocFV7D1T
dtTf6tt31PbtKfEauRjz3fBXMw+r3Pu/hWRXd3og9hfzFQz49v9RdvgkHy57uCY+
F/fN3BKyTcTqJWKpBDMx/xtD1kXWHf81SFmckuShbgKjDvZraR4RmzO/9upIDCFF
rJ85takmPvZyAdfvZp6RqVja+cphI4nmxVvmOmUiFMmUJ0lv9MhqpxdVFfleWz0w
9XxeL4l+cd/Kbl2ihHwF4oOzWlamyRZjoWiq5s/ika9I1iQ40rGTThqnphonlhUz
HX4NvA+fbugwqyOjqEkg5AqyP5ucUN3Hl0qd7wqAJprDkB938unKo/1sr82PfdO/
5UvzsKz2ieVavEzi/NxYyR+Xjm3YHG1akcftvElcpYepvemt/PtXJH8fX29b1X6C
TYxV03MeA1sJXeM9iqIf/wGQJ657U5ciXUyUtU8s0dDY+jqpZVjxekgCove9FNXz
Mja15yiAy/F8xKX20ZRisg+Ly60UQYbX6Wu6Uy6NMjWkxZOYebCVYLMag6UjS0CS
8n3/DNvuVooGWbgBFs0tyabtlz/Fz5jGktkMBQeEK4PZKZdMt9aXnDfPFGJWrsme
bUzEZLZSWD2Zwr/ujzfBgVeg56AyHJzHuOOLaofZ90ecv69Udl7sYZBelFXxgN8R
JVXyV0kNZYj9LaqRTi54H8YToAIV7GXIcasH3jP54dOba3px2NXbaiMf7Oe8apyW
E7/vKQNoIbWaglRHXVPGoATTUzYNdBO4jca1rTOXjmzsiZl1JGPwQsS03PuTfa8C
F7Uqxj8P9m71G1KuLYA1es55aNXzXSx6uqrRYeu0iug/jE+voGfjbRW3BUY/qxtl
OjR8pCDPLN6/rt//ejvBdA4gPDgjRNH4fO9DULQDqIVHmYlysZqhbPbhzmiBXZVP
zw1/z9amWR00OeN7xUvm9n+65dosoIn2v1dOz8JBh6Uooj63D2cOghBwEXoPg53B
3vLgqy3NKyNZQ/gGfBjXTTeoWzAy8U8hKecNKcsTBquBeBUfS55WwkbD7Mz0Deho
EcMZPZUwAPyJ2kHL74etpoBXuH7Jzo8SVedhE+C5J6F+oUP/JcoXdehdGLI89CHU
cUARt91OiF3WQo51xT21GlGL8RMHVpjTnYZinnQ/fE1y7JfWtYshBya+YLlAk5vb
9jt0tZ9I/KhJ579ZwWBH8V179kBr5Vn+uWlEBBaJu0abdbRSDjt6fAaxi3Q8XK+c
isuVuzN/8JAeRgRpm7hRfIoG6XOsrY72ktz0JiHflZ+90xaPRvpCA9/mFC5qp1zh
yBs=
-----END ENCRYPTED PRIVATE KEY-----

Binary file not shown.

View File

@@ -1,26 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEaTCCAlECAQEwDQYJKoZIhvcNAQEFBQAwgZ8xCzAJBgNVBAYTAlVTMREwDwYD
VQQIDAhOZXcgWW9yazEPMA0GA1UEBwwGQXJtb25rMTQwMgYDVQQKDCtJbnRlcm5h
dGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTYwNAYDVQQDDC1N
USBMaWdodCBFeHBpcmVkIENBIChmb3IgZXhwaXJlZCBzaWduZWQgY2VydCkwHhcN
MTUwMzI4MTMwNDI2WhcNMTUwMzI5MTMwNDI2WjBVMQswCQYDVQQGEwJHQjESMBAG
A1UECAwJSGFtcHNoaXJlMRAwDgYDVQQHDAdIdXJzbGV5MQwwCgYDVQQKDANJQk0x
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAMeNfSaC0XZoi9CHXLUHz7BA8frIlz+gnl1sjaGimsofiMjd8a0c4pOhlusR
kvB4qAQDxmDYhh9QTuqiJZvQxzTI3sNt4W3kcm/bEVawg8HvsWBY40fKkWJYlypV
K4Oizcri7CLaeUwgpJlrSlYiJSzjaaytTDeC1F+RSTrdDg0CxI+pfhxIkc9+HPMC
oSv1ynxktcJPnCLGRIIHYCE4jm1ZsYxAkSV1crja5OQdd3czEMz6wfHdYzTJUEa1
pmnTOa9lhuxlYb8ykt7G2CK66tXaoN0SsAsy6sT2SblI16RDkyOL5XJk56ThhHrn
XjjWr3Zo4/tE/pgn5fd+91oi2+ECAwEAATANBgkqhkiG9w0BAQUFAAOCAgEAZNZn
OJVQ54NLCzCyTiTauG2jJU+3aYEG4hRhpLM6N11vrukIFTeVfbrr1uKp7sLHYB0E
6xLgTxhKF2lDHzCPjA3bOO0tDsxwkOZNP//jmMi+9VKd6Voh/UENOVnBHaXLb5G2
9OXi70W/K8eQU7Qi+tu+snWNLYHb5nsYKnPed3+h/zLV3iNB7cz2DCNCas2cKekx
6hJo+tWoC+jXcpM97pnqY6saYNmKmugIdZ1W77jueoEIIkSMAZvd8sgXzE6Ad8mD
bTMimX9ri0APgxZewaF51YzR2yKqgkpvLVBef0nCbjCDK5zgJVSQHtVJswE4mIcL
J3PbSxtmt3BcIr9jmYZZjmoXSjK0+YQkDYT9/uiE5h+6KXrk4AOTkcO9kuxQcBAD
QYJB8Hr7h9OcWmpOOJDjOz4BspBwQ7Vs2swHBQgWu9mS9I187JFSFm46dp9CnqSV
K5i5amsrJUcRtqlBs4JzqsLivUaet+BtQwlWDfl52TgWpWeIs2EiPFERZxiEggVr
pIhjZ9F2d0pL1Oj5jCWMRGWrz1px5W4r92uzfYvTrT/eyGNGGNdDeAgidJ4SftXu
XMcqgVjAy0kKvQEK9bCqfoOxTllFqLcneaPI6O0hLREph6sti6eDvJeMsUGoYm/7
MxfCaqBU1HStl0HHPaaqHnPP+FW+/xuXhHij1hY=
-----END CERTIFICATE-----

Binary file not shown.

View File

@@ -1,35 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIGEzCCA/ugAwIBAgIJAI+sAC+/ups4MA0GCSqGSIb3DQEBBQUAMIGfMQswCQYD
VQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxDzANBgNVBAcMBkFybW9uazE0MDIG
A1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlv
bjE2MDQGA1UEAwwtTVEgTGlnaHQgRXhwaXJlZCBDQSAoZm9yIGV4cGlyZWQgc2ln
bmVkIGNlcnQpMB4XDTE1MDQwMTExNTkxNloXDTQyMDgxNjExNTkxNlowgZ8xCzAJ
BgNVBAYTAlVTMREwDwYDVQQIDAhOZXcgWW9yazEPMA0GA1UEBwwGQXJtb25rMTQw
MgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0
aW9uMTYwNAYDVQQDDC1NUSBMaWdodCBFeHBpcmVkIENBIChmb3IgZXhwaXJlZCBz
aWduZWQgY2VydCkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDLGn4P
97BZteNO/5zIlGH4F067TPlOjFiLI1TFI/bKp3bx1fHpsQdMX5C9y1s6BqoOzMJV
VHDJH4NlxvnMUGNzYvluynjujejhyDryDrb4uY3JMcewvnHmrWArzbfZw4eBzANr
feBkro4xr6m5HWMxM4GJZeFaEGqbXNE5vAYhZ270qUKqrkSHv4g/LqapITaBPJDC
3tAtV0UD4/HmwB2ogZlXy4DkbBsgcc2rS4xPxx3Qki78DeA9oT6aeLP7KZnoEgo9
Xqb/UfRuZ5MYR17u8yTuJz/JdAs6Saf80t5PLDO/SRKj7Uu1lt+HbkpEghdEdB/V
pPdmlIfo7uNe7rFG/OWif2qwVm2t9o02oIUqlAHggS4WYeOmcB8L9EtmlfZHaoDA
H0a0xlbZ+XlE/EMpphgrzSE5g9h9Vw7vvH5Ygzks8lSXKd5VS8C9y8tWqaMCynAy
5MTIZdXMvouG8vy5Ip+iWck4QSo6eJBryLNt/vzljxo6XntveXRZVvywyjh3NuVu
nVLPe0CFkmRHXK5/zA6H8rZeGb3eK8Y4VcLKj7x4Lnluo47BeGnKH7UcKBA2AREC
VGFVsHcr0HwKgCCSsyv4qRefY/mJWO59BL38shHuzydLxlKHf/uPGdsZ3DU0rb6i
QXMCHC6lzAjJHVCDJ2witiPSjmW2LRZzRqdTqwIDAQABo1AwTjAdBgNVHQ4EFgQU
dv3XdSdsOkZJDWgusfuZqBx/jpMwHwYDVR0jBBgwFoAUdv3XdSdsOkZJDWgusfuZ
qBx/jpMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAgEAR9o32FR4AjTZ
LV5nH5rsQ9OVon1TCv9yemAI4coh08RHWVf7cDyIp8XKy3gTM/lq70wzsXUHwaAS
4xSOjc/fBLP0UTEwCrdyy1guRs9ZjKIhqth1AkB92sF9HV4P811vUNppVfA/BDmb
Ttl6i1Joyl6nhnDxn1HzjcSBB4ZVt/1MRwIaEfRXrqAklYbMOtw8D6Onth6IQ7dS
27ulUPD+AA8H5Ilm2XhPI6ttnR+822+mgB1K9WAjmuIbDJwQJl32UmTUiXPwdlWm
KqyKZGST8wV6Jylha84ETL99IlJsxoAMGmNshMe4t773n0LousAvnbVt9uZcBNUH
d/53EWP7kw1PPhY6jo0gLVK/ZQt8MHBJuT3f5IM9dmkLJmyM9t8tEmvjNEoC2xSW
JHxoWfbMOxxFx+S5CwwcvySpKltio7s5bf/dYexE+Dv/+zMDeMb8GXv811TCqsD2
lm4kTsHjwd+zSGCuvH+R4vWbkSrd65CATmFsVpVPLsIVXDa3DrgFQBmUI/q9UFaG
K25HztaHk8GJkBZdBA7xXxzSJxW37yqPGKqQ/ZoqSz6XFnsgy5AsW0fDM+cPUl7l
tftOlLeSqkaBq9O++76yY2asb0AyqjNs0tajluzxGFZ38DOqA1xkltV/c+KYnEv3
q+K4agMHIKMr7lGJfSBevz3mG+NJ7AU=
-----END CERTIFICATE-----

View File

@@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID2zCCAsOgAwIBAgIUdbPSj6WWhFu2amL9voKbyCMKiB4wDQYJKoZIhvcNAQEL
BQAwfTELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAktBMQwwCgYDVQQHDANCTFIxDDAK
BgNVBAoMA0lCTTEMMAoGA1UECwwDSVNMMRAwDgYDVQQDDAdNUU1GVFFNMSUwIwYJ
KoZIhvcNAQkBFhZzaGFzaGlrYW50aEBpbi5pYm0uY29tMB4XDTIzMDEyNTA1MjEz
NloXDTI4MDEyNDA1MjEzNlowfTELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAktBMQww
CgYDVQQHDANCTFIxDDAKBgNVBAoMA0lCTTEMMAoGA1UECwwDSVNMMRAwDgYDVQQD
DAdNUU1GVFFNMSUwIwYJKoZIhvcNAQkBFhZzaGFzaGlrYW50aEBpbi5pYm0uY29t
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwl9MlmCNG7kzk7qKGuBX
jTONcn2OcifKfwgJlvzTqHcf8X/BIiyOOiwoeznke///LLtt9ygF0iyBMQYM/CG/
rzOR6tbzI4y4Bmx6VqY02CkXi/p66ywQ7B5N2Fdp9Bop3SnthTcT4NoXBSEUhI1O
ob8lDFv1KMRkCULD2sA0FUYCrHtw0M/vEOqsA9VVjyzOXsIlbbR1BSXtlWNneGeL
OAdmQWO3QYCku/YrCyJlscvIisjp4s7guGnQh0Ws8h50R5sqag8RvdHUwExVLUfZ
L1Od0+hCiO5mNfKekT0cs9owplcwgNHw88b8q4/aHDBtQRgsukkMxTpo00ftPJxI
nwIDAQABo1MwUTAdBgNVHQ4EFgQUOyw89AeB0jXb5WCZv/5oDY8oWxkwHwYDVR0j
BBgwFoAUOyw89AeB0jXb5WCZv/5oDY8oWxkwDwYDVR0TAQH/BAUwAwEB/zANBgkq
hkiG9w0BAQsFAAOCAQEAtbybQQ9GpY5gH7xz4EWOUZ7XMmBYtuGXVrqUd+76hvCA
H/SB0nl2bGp7tAKBttmXhfKVac6wFCbXvYe49B+Q9+iL7H9st9VZUPKLQ6K3Uet6
L1ggMm2BhecpuYbwkG7ZidVFo/SuUCbCTnXBgHjvq4IkVCaJe7aKZmejSCh7gsIR
BQkZvz/22Vx/WPTEYp0x/riIvSViBjLCuD25Y+nCtS8c2xGVBjs9Q4GWCOAvEfAr
Tqs42brH1Vs92xS143p2h/wv52tmhfJI6X9QVQBBUoIjPR/VDFqZU5EYhAvuQPBi
UADz9hNYGQ9wBzZGvzbrorpoT+7aW9nGtmUsvvupBA==
-----END CERTIFICATE-----

View File

@@ -1,3 +0,0 @@
This directory contains private key and a certificate that signed by CA.
The directory also contains the CA certificate. The certificate and it's
CA certificate have same Subject DNs.

View File

@@ -1,21 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDgTCCAmkCFClOtyvBoQXVAGMcX0ObUawZJuX/MA0GCSqGSIb3DQEBCwUAMH0x
CzAJBgNVBAYTAklOMQswCQYDVQQIDAJLQTEMMAoGA1UEBwwDQkxSMQwwCgYDVQQK
DANJQk0xDDAKBgNVBAsMA0lTTDEQMA4GA1UEAwwHTVFNRlRRTTElMCMGCSqGSIb3
DQEJARYWc2hhc2hpa2FudGhAaW4uaWJtLmNvbTAeFw0yMzAxMjUwNTM4MzBaFw0y
NTA0MjkwNTM4MzBaMH0xCzAJBgNVBAYTAklOMQswCQYDVQQIDAJLQTEMMAoGA1UE
BwwDQkxSMQwwCgYDVQQKDANJQk0xDDAKBgNVBAsMA0lTTDEQMA4GA1UEAwwHTVFN
RlRRTTElMCMGCSqGSIb3DQEJARYWc2hhc2hpa2FudGhAaW4uaWJtLmNvbTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJNAGirCyLzsHpV2cyso8pc2BOP
4j6lu2ZTsdSE+WVZsqX3YWmV8TCYpJQRD4jmlrYIEdYAGmKPZvbvWjhzZWOJIxfI
MGRwQ4dl8bSDZpcc7OAcHgLaW1OnMy2/1NgVyyXOKTaG4PmzZCzSKnhDF8/+FhUm
rIYi5EU6bn1MuY34HOswAau0G7YVeroBUPs+LUjUpQx4vp5Baz9sWBzWcvsZsoSo
LTMWEqCocqYOhj1ALrwN61NzdRwVtoS41dcjHAiFKEVTKIbqE0ib57Of1sohO9dr
JgjegBNi18lsVUqDnYvydbe1hTEZfoXyN3QHm6QZLYtKB0RqR4HlcufnFWkCAwEA
ATANBgkqhkiG9w0BAQsFAAOCAQEAtgG/2/7q2xPJG+Z0xJIyS9O7h6Igus2LhrAw
tkudX5FZtJclBmDx3KvtJMPzpoGFRF48nXaqNcDSI3+8MiMk+JfpfGtmFbYuaa+l
seqk/3byv/y1ofd8JMk0olY219tI1/BK4AU+fPP1obYV0tFcwIDOqQaS6f/N4RP1
MO0PE+j9dDO6GQjIEUHZVVis70WvGaTc6DfGPVehZzDbNW9nTdkuacZf+XtlLVXq
LzJpGeMxvX7SRRkdyegNigiWHJzOchVcoNnO+rUm9JDjY8pukDC08uZEQVqNpOXD
tO1t4rpBT9HWxPRCLt8IwOhoYAGb5DWwUeIaiY637CSPTJVjCQ==
-----END CERTIFICATE-----

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAsk0AaKsLIvOwelXZzKyjylzYE4/iPqW7ZlOx1IT5ZVmypfdh
aZXxMJiklBEPiOaWtggR1gAaYo9m9u9aOHNlY4kjF8gwZHBDh2XxtINmlxzs4Bwe
AtpbU6czLb/U2BXLJc4pNobg+bNkLNIqeEMXz/4WFSashiLkRTpufUy5jfgc6zAB
q7QbthV6ugFQ+z4tSNSlDHi+nkFrP2xYHNZy+xmyhKgtMxYSoKhypg6GPUAuvA3r
U3N1HBW2hLjV1yMcCIUoRVMohuoTSJvns5/WyiE712smCN6AE2LXyWxVSoOdi/J1
t7WFMRl+hfI3dAebpBkti0oHRGpHgeVy5+cVaQIDAQABAoIBAGlAmVAwQBe24OOm
kDaJZvrLSeZqVnUC4pgqKdy5Tnusso/Uc5WfpMw6H1UkqRX4gNkd9GFumCS8YFy+
uHSAckaKqsOcMizoNITWAhO8SbBEq/QzxOeMPMMp/UUxa5TPcKd1htCgWGgupKDs
w5NQj9sBM8nylX9tU3EmaBjhVNvfsZSeA76s0z+JDDwJLUlH33dwvgidw+baRxYM
U6Tr3Z7YCFZ7+iZbOTHZjkKVtS2EqHtU5OW/pQltbBSovhYQMXjBsCHpTK78+jbV
jKjtDUYWplcAYoN/O8ljYHU6lKQlTfo8KQInLtek/Ycen7uOCT6kFAreWFg08g4x
5IH/pXECgYEA4ivLQjKR1BHiO+6rDZIfQxvbTa2RgT3Yr9W923OpGY1LiuapGFfJ
97PjVKQf6HromQuzveYZR9YFKR4u8YTUn5PCB16v9MEc7nxnwIfE1kH5aEMvMSq9
MvxvYObs3dJu4dx+AF8q8REuviBkQ2br34ukbl8ssaB/7zHPXyNJDt0CgYEAydD3
BNtPRwKorQKOC1VXQxAFtlu/iiia4LEocAODDUX8N0iGxRBpQcfY/OuqV2j8Alfx
n7+Zv/NGEah+WLaApc6wZVvOOuJevam/3ZJReawUtpCcG5em388WSQDuIj3AKhVV
IzRRRFlGrTuHENdsqG5rBzbYWvans4lpVkB6Kf0CgYA0YUQfvqp7XPDyRGIlMHRB
DJCLuuj576LhhjUEQBMnscuPDcCXvK0vyt+ZWLFzHBQGbelgz4uHUY+8aBsjIEpF
8uh64HkLzDWxHerBcjAqFvl2Jiklz+olhsUcwh6VeQjpEjG0UFYXoo0ax1GxMoLq
MOMSFMS7FprKgNSwCfH/mQKBgBLA8lNnNcS5gIcjN6Ph+EvpDz7U48Wo5EuA6usN
yH3RRRC2Ep/5WG6ebZGDLL8WqGRnW7KmkVj++EHn0GXZ/7ZosIeasl1Sb89cGNI0
KJIP5ZTZd0gxHXaqvb1m8roH1vWSKektkWeyjBjI8VIlUpmMOTHgbNZ3GTpbyIgV
UcTZAoGAJp5AX+5u6OhLcCI56dpKYGiIS+8fXd2+oz7uZYf2yNTZONulehh2earM
4soiUF5ArPgc3KbZhorvIXjOUSb5wc7I2nQKxXQt9j2fyZMD8qsyI1kBqLQ53Z0r
agAkX1xMvhvHMQFKmPMXt3pUfXEx/oa32f3ciyPAhyyQNpv5gx4=
-----END RSA PRIVATE KEY-----

View File

@@ -1,6 +1,6 @@
#!/bin/bash
# -*- mode: sh -*-
# © Copyright IBM Corporation 2020, 2023
# © Copyright IBM Corporation 2020
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,6 +41,7 @@ else
make pass
cp bin/build/docker-credential-pass $GOPATH/bin/docker-credential-pass
fi
mkdir -p /home/travis/.docker
echo '{ "credsStore": "pass" }' | tee /home/travis/.docker/config.json
gpg2 --batch --gen-key <<-EOF

View File

@@ -1,5 +0,0 @@
-Djava.util.prefs.userRoot=/tmp
-Djava.util.prefs.systemRoot=/tmp
-Dcom.ibm.jsse2.usefipsprovider={{.FipsProvider}}
-Dcom.ibm.jsse2.usefipsProviderName={{.FipsProviderName}}

View File

@@ -1,2 +0,0 @@
go.collectDependenciesAtRuntime=true
excludes=**/test