Compare commits

..

66 Commits

Author SHA1 Message Date
Alec Painter
461dc0e36e Merge pull request #315 from mq-cloudpak/ahp-v9.2.0.6-r3-updates
updated ubi & go versions & increased to r3
2022-09-05 15:15:33 +01:00
Alec-Painter
c0e22e5d59 updated ubi & go versions & increased to r3 2022-09-05 14:05:23 +01:00
Alex Mirski-Fitton
9d9939eaf3 Merge pull request #312 from mq-cloudpak/amf-credential-helper-go-version-920
Pin docker-credential-helpers for old go installs
2022-08-22 13:25:03 +01:00
Alex Mirski-Fitton
b9487921d1 Pin docker-credential-helpers for old go installs 2022-08-22 11:49:14 +01:00
Tom Jefferson
6e158c73f2 Merge pull request #309 from mq-cloudpak/tadj-update-ubi-920x
Update go version and ubi
2022-08-09 13:28:38 +01:00
Tom Jefferson
062c680cf6 Update go version and ubi 2022-08-08 21:30:10 +01:00
Prerna Srivastava
f3e2c34d76 Merge pull request #301 from mq-cloudpak/WS-Fix0808
WS fix
2022-08-08 16:14:36 +05:30
Prerna Srivastava
60bcd27347 WS fix 2022-08-08 15:18:40 +05:30
Tom Jefferson
8cb1dcba50 Merge pull request #295 from mq-cloudpak/tadj-add-august-eus-version
Update release for 9.2.0.6-r2
2022-08-02 14:36:44 +01:00
Tom Jefferson
16fc8640c1 Update release for 9.2.0.6-r2 2022-08-02 11:17:08 +01:00
Simon Hirst
e5b0fd465b Push fake master to different namespace 2022-07-28 11:22:47 +01:00
Simon Hirst
09d1b8d4fb Push fake master to different namespace 2022-07-28 09:57:55 +01:00
Alex Mirski-Fitton
581a510084 Merge pull request #273 from mq-cloudpak/amf-9206
Update to 9.2.0.6 and Go 1.17
2022-07-07 14:05:36 +01:00
Alex Mirski-Fitton
f2a9d75595 Update to Go 1.17
Also pick up latest UBI base image
2022-07-07 13:44:56 +01:00
Alex Mirski-Fitton
b94c26fda3 Update to 9.2.0.6 2022-07-07 11:06:53 +01:00
Alec Painter
090e90ffbc Merge pull request #265 from mq-cloudpak/ahp-9.2.0.x-ubi
Updated ubi
2022-06-15 10:30:49 +01:00
Alec Painter
059058bc26 Updated ubi 2022-06-15 10:07:02 +01:00
David Bell
b1ff7f85b8 Merge pull request #261 from mq-cloudpak/drb-doc-building-920x
[ci skip] doc for building 920x lts
2022-06-10 20:08:17 +01:00
David Bell
23a635ff92 [ci skip] doc for building 920x lts 2022-06-10 16:35:03 +01:00
Alec Painter
c1c098bbe2 Merge pull request #258 from mq-cloudpak/ahp-9.2.0.5-r3-eus
Updated to 9.2.0.5-r3
2022-06-08 08:40:33 +01:00
Alec Painter
2e77779603 Updated to 9.2.0.5-r3 2022-06-07 15:54:57 +01:00
Tom Jefferson
d0bee17f37 Tadj 9205 r2 (#248)
* Update release/ubi/go
2022-05-12 19:12:08 +01:00
Simon Hirst
bc38e758f6 Removing CD builds from Travis
Removing CD builds from Travis
2022-05-11 13:29:26 +01:00
Simon Hirst
4df4841b07 Removing CD builds from Travis 2022-05-10 14:26:37 +01:00
Alec Painter
056b0cac1f Merge pull request #226 from mq-cloudpak/ahp-ubi-eus
Updated UBI
2022-04-12 15:27:28 +01:00
Alec Painter
3a8d1e4c50 Updated UBI 2022-04-12 13:54:24 +01:00
Tom Jefferson
66be620448 Merge pull request #222 from mq-cloudpak/tadj-ubi-update
Go/UBI updates
2022-03-16 13:54:03 +00:00
Tom Jefferson
192ad048af Go/UBI updates 2022-03-16 10:08:08 +00:00
Tom Jefferson
efcd4520a1 Merge pull request #218 from mq-cloudpak/tadj-ubi-updates
Update ubi and go version
2022-03-11 15:55:13 +00:00
Tom Jefferson
c58c08e3ed Update ubi and go version 2022-03-11 15:21:00 +00:00
Tom Jefferson
24dba64144 Merge pull request #206 from mq-cloudpak/tadj-update-ubi
Update UBI and Go
2022-02-07 09:05:15 +00:00
Tom Jefferson
473ba05646 Update UBI and Go 2022-02-04 15:26:06 +00:00
David Bell
cc2c42ff59 Merge pull request #204 from mq-cloudpak/drb-fixmakefile
fix hardcoded version in Makefile
2022-01-28 11:32:32 +00:00
David Bell
7eb0a4cc94 fix hardcoded version in Makefile 2022-01-28 10:45:35 +00:00
David Bell
ae1c16b5fc Merge pull request #203 from mq-cloudpak/ahp-9.2.0.5-eus
Added new 9.2.0.5 MQ version
2022-01-27 19:55:45 +00:00
Alex Mirski-Fitton
9eeab37e32 Handle window between cont. start & port binding 2022-01-27 11:26:18 +00:00
Alex Mirski-Fitton
d324b2b49a Add common name to SAN list for test cert 2022-01-27 11:26:18 +00:00
Alec Painter
0152e5f897 Updated MQ_VERSION variable name for release info 2022-01-27 11:25:41 +00:00
David Bell
1be3c273fc Update ubi and go-toolset 2022-01-26 20:16:15 +00:00
Alec Painter
6a08908425 Added new 9.2.0.5 MQ version 2022-01-26 19:38:17 +00:00
Tom Jefferson
316656d2bf Merge pull request #199 from mq-cloudpak/tadj-1452-container-label
Add MQ build level to the container labels
2022-01-14 14:26:01 +00:00
Tom Jefferson
3800201a7d Add MQ build level to the container labels
* Changes to add MQ build level to the container labels

* Add jq as a dependency
2022-01-14 11:32:28 +00:00
Alex Mirski-Fitton
7ec5133a56 Merge pull request #191 from mq-cloudpak/amf-update-go-920
Update go, go-toolset, and UBI
2021-11-12 17:42:32 +00:00
Alex Mirski-Fitton
09bc87d6d3 Only log in if user defined 2021-11-12 16:24:08 +00:00
Alex Mirski-Fitton
ddfe933f49 Allow longer for webserver to respond 2021-11-12 16:24:03 +00:00
Alex Mirski-Fitton
7d8ce547da Update go-toolset, and UBI 2021-11-12 15:12:50 +00:00
Alex Mirski-Fitton
e11aa50747 Merge pull request #188 from mq-cloudpak/amf-update-go-920
Update go-toolset and ubi levels
2021-11-03 10:15:13 +00:00
Alex Mirski-Fitton
7e4c30e0f7 Update go-toolset and ubi levels 2021-11-03 09:54:01 +00:00
Alex Mirski-Fitton
70419138ce Merge pull request #186 from mq-cloudpak/amf-update-go
Update go
2021-10-28 08:56:42 +01:00
Alex Mirski-Fitton
856adc8467 Update go 2021-10-27 15:51:11 +01:00
Alex Mirski-Fitton
2d4fd9baaa Merge pull request #184 from mq-cloudpak/amf-132-release
Update MQ and UBI levels
2021-10-07 08:39:42 +01:00
Alex Mirski-Fitton
8fa2740fdc Update ubi8 images 2021-10-06 12:11:31 +01:00
Alex Mirski-Fitton
71209def9a Update MQ version to 9.2.0.4 2021-10-06 12:11:26 +01:00
David Bell
088b8c9ab5 Merge pull request #174 from mq-cloudpak/drb-ubigo-9202r2
Use ubi8/openjdk-8 instead of docker.io/maven for JMS tests
2021-07-05 15:15:53 +01:00
David Bell
d4ab93efa7 Use ubi8/openjdk-8 instead of docker.io/maven for JMS tests 2021-07-05 14:32:42 +01:00
David Bell
a0468028c2 Merge pull request #173 from mq-cloudpak/drb-ubigo-9202r2
update ubi and go
2021-07-05 14:04:46 +01:00
David Bell
5e57fa8e3e update ubi and go 2021-07-05 13:26:04 +01:00
Stephen Marshall
bb958abe47 Add 9.2.0.2-r2 2021-06-22 11:31:49 +01:00
Luke Powlett
c6d374f8a2 Update to latest UBI 2021-06-07 10:04:46 +01:00
David Bell
8e67a9cf6a Merge pull request #161 from mq-cloudpak/drb-131-ubigo
update ubi and go
2021-05-20 11:17:54 +01:00
David Bell
1822c45c79 update ubi and go 2021-05-19 20:58:40 +01:00
Amrit Kandola
ccb3af5242 update ubi to latest (#156) 2021-04-22 14:21:05 +01:00
Amrit Kandola
da6a3ce986 new notices.txt (#155) 2021-04-20 14:57:53 +01:00
Amrit Kandola
b427dc0978 9.2.0.2-r1-eus (#154)
* 9202-r1-eus updates, updated golang and ubi version, also added new 9202 driver in travis.yml
2021-04-16 17:00:17 +01:00
David R Bell
7d6c23bb1a resolve docker push (#139) 2021-01-25 16:15:17 +00:00
Nathaniel J. King
996b8facdf [ci skip]: Setup support branch 2020-12-01 10:45:34 +00:00
72 changed files with 14185 additions and 7464 deletions

View File

@@ -1,22 +0,0 @@
name: Close inactive issues and PRs
on:
schedule:
- cron: "30 1 * * *"
jobs:
close-issues:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v3
with:
days-before-stale: 90
days-before-close: 30
stale-issue-label: "stale"
stale-pr-label: "stale"
stale-issue-message: "This issue is stale because it has been open for 90 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 30 days since being marked as stale."
repo-token: ${{ secrets.GITHUB_TOKEN }}
exempt-issue-labels: "bug,enhancement,documentation"

View File

@@ -18,18 +18,18 @@ sudo: required
language: go
go:
- "1.13.15"
- "1.17.12"
services:
- docker
env:
global:
- MAIN_BRANCH=v9.2.3
- MQ_LTS_VERSION=9.2.0.1
- MAIN_BRANCH=v9.2.0.x-eus
- MQ_LTS_VERSION=9.2.0.6
- TAGCACHE_FILE=tagcache
- RELEASE=r1
- RELEASE_LTS=r1
- RELEASE=r2
- RELEASE_LTS=r3
go_import_path: "github.com/ibm-messaging/mq-container"
@@ -40,59 +40,16 @@ go_import_path: "github.com/ibm-messaging/mq-container"
jobs:
include:
- stage: basic-build
if: branch != v9.2.3 AND tag IS blank
if: branch != v9.2.0.x-eus AND tag IS blank
name: "Basic AMD64 build"
os: linux
env:
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_923_ARCHIVE_REPOSITORY_DEV_AMD64
script: bash -e travis-build-scripts/run.sh
# CD Build
- stage: global-tag
if: branch = v9.2.3 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.2.3 OR tag =~ ^release-candidate*
name: "Multi-Arch AMD64 build"
os: linux
env:
- BUILD_ALL=true
- MQ_ARCHIVE_REPOSITORY=$MQ_923_ARCHIVE_REPOSITORY_AMD64
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_923_ARCHIVE_REPOSITORY_DEV_AMD64
script: bash -e travis-build-scripts/run.sh
# - if: branch = v9.2.3 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_923_ARCHIVE_REPOSITORY_PPC64LE
# - MQ_ARCHIVE_REPOSITORY_DEV=$MQ_923_ARCHIVE_REPOSITORY_DEV_PPC64LE
# script: bash -e travis-build-scripts/run.sh
- stage: build
if: branch = v9.2.3 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_923_ARCHIVE_REPOSITORY_S390X
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_923_ARCHIVE_REPOSITORY_DEV_S390X
script: bash -e travis-build-scripts/run.sh
- stage: push-manifest
if: branch = v9.2.3 AND type != pull_request OR tag =~ ^release-candidate*
name: "Push Manifest-list to registry"
env:
- PUSH_MANIFEST_ONLY=true
- MQ_ARCHIVE_REPOSITORY_DEV=$MQ_920_ARCHIVE_REPOSITORY_DEV_AMD64
script: bash -e travis-build-scripts/run.sh
# LTS Build
- stage: global-tag
if: branch = v9.2.3 AND type != pull_request OR tag =~ ^release-candidate*
if: branch = v9.2.0.x-eus AND type != pull_request OR tag =~ ^release-candidate*
name: "Generate Global Tag"
os: linux
env:
@@ -102,18 +59,18 @@ jobs:
- RELEASE=$RELEASE_LTS
script: bash -e travis-build-scripts/global-tag.sh
- stage: build
if: branch = v9.2.3 OR tag =~ ^release-candidate*
if: branch = v9.2.0.x-eus OR tag =~ ^release-candidate*
name: "Multi-Arch AMD64 build"
os: linux
env:
- LTS=true
- TAGCACHE_FILE=tagcache-lts
- MQ_VERSION=$MQ_LTS_VERSION
- MQ_ARCHIVE_REPOSITORY=$MQ_9201_EUS_ARCHIVE_REPOSITORY_AMD64
- MQ_ARCHIVE_REPOSITORY=$MQ_9206_EUS_ARCHIVE_REPOSITORY_AMD64
- RELEASE=$RELEASE_LTS
script: bash -e travis-build-scripts/run.sh
- stage: build
if: branch = v9.2.3 OR tag =~ ^release-candidate*
if: branch = v9.2.0.x-eus OR tag =~ ^release-candidate*
name: "Multi-Arch S390X build"
os: linux-s390
env:
@@ -121,11 +78,11 @@ jobs:
- TAGCACHE_FILE=tagcache-lts
- MQ_VERSION=$MQ_LTS_VERSION
- TEST_OPTS_DOCKER="-run TestGoldenPathWithMetrics"
- MQ_ARCHIVE_REPOSITORY=$MQ_9201_EUS_ARCHIVE_REPOSITORY_S390X
- MQ_ARCHIVE_REPOSITORY=$MQ_9206_EUS_ARCHIVE_REPOSITORY_S390X
- RELEASE=$RELEASE_LTS
script: bash -e travis-build-scripts/run.sh
- stage: push-manifest
if: branch = v9.2.3 AND type != pull_request OR tag =~ ^release-candidate*
if: branch = v9.2.0.x-eus AND type != pull_request OR tag =~ ^release-candidate*
name: "Push Manifest-list to registry"
env:
- LTS=true

View File

@@ -1,17 +1,17 @@
# Change log
## 9.2.3.0 (2021-07-22)
## 9.2.0.6-LTS (2022-07-20)
* Updated to MQ version 9.2.3.0
* Updated to MQ version 9.2.0.6
* Updated to Go version 1.17
## 9.2.2.0 (2021-03-26)
## 9.2.0.5-LTS (2022-01-25)
* Updated to MQ version 9.2.2.0
* Updated to MQ version 9.2.0.5
## 9.2.1.0 (2020-02-18)
* Updated to MQ version 9.2.1.0
## 9.2.0.4-LTS (2021-10-05)
* Updated to MQ version 9.2.0.4
## 9.2.0.1-LTS (2020-12-04)

View File

@@ -1,4 +1,4 @@
# © Copyright IBM Corporation 2015, 2021
# © 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,13 +13,15 @@
# limitations under the License.
ARG BASE_IMAGE=registry.redhat.io/ubi8/ubi-minimal
ARG BASE_TAG=8.4-205
ARG BASE_TAG=8.6-902.1661794353
ARG BUILDER_IMAGE=registry.redhat.io/ubi8/go-toolset
ARG BUILDER_TAG=1.17.12-3.1661377020
ARG GO_WORKDIR=/opt/app-root/src/go/src/github.com/ibm-messaging/mq-container
ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/9.2.3.0-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.2.0.6-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz"
###############################################################################
# Build stage to build Go code
###############################################################################
FROM registry.redhat.io/ubi8/go-toolset:1.15.13-4 as builder
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
@@ -35,6 +37,7 @@ RUN mkdir /opt/mqm \
&& INSTALL_SDK=1 install-mq.sh \
&& chown -R 1001:root /opt/mqm/*
WORKDIR $GO_WORKDIR/
COPY go.mod go.sum ./
COPY cmd/ ./cmd
COPY internal/ ./internal
COPY pkg/ ./pkg
@@ -45,16 +48,16 @@ ENV 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/
RUN go build ./cmd/chkmqready/
RUN go build ./cmd/chkmqhealthy/
RUN go build ./cmd/chkmqstarted/
RUN go build ./cmd/runmqdevserver/
RUN go build -buildmode=c-shared -o amqpasdev.so ./internal/qmgrauth/pas.go
RUN go test -v ./cmd/runmqdevserver/...
RUN go test -v ./cmd/runmqserver/
RUN go test -v ./cmd/chkmqready/
RUN go test -v ./cmd/chkmqhealthy/
RUN go test -v ./cmd/chkmqstarted/
RUN go test -v ./pkg/...
RUN go test -v ./internal/...
RUN go vet ./cmd/... ./internal/...
# go 1.17 sigchanyzer check disabled for EUS stream as fix would introduce change of behaviour
RUN go vet -sigchanyzer=FALSE ./cmd/... ./internal/...
###############################################################################
# Main build stage, to build MQ image
@@ -94,7 +97,6 @@ RUN mkdir -p /run/runmqserver \
COPY --from=builder $GO_WORKDIR/runmqserver /usr/local/bin/
COPY --from=builder $GO_WORKDIR/chkmq* /usr/local/bin/
COPY NOTICES.txt /opt/mqm/licenses/notices-container.txt
COPY ha/native-ha.ini.tpl /etc/mqm/native-ha.ini.tpl
# Copy web XML files
COPY web /etc/mqm/web
COPY etc/mqm/*.tpl /etc/mqm/
@@ -117,27 +119,6 @@ USER 1001
ENV MQ_CONNAUTH_USE_HTP=false
ENTRYPOINT ["runmqserver"]
###############################################################################
# Build stage to build C code for custom authorization service (developer-only)
###############################################################################
FROM registry.redhat.io/rhel8/gcc-toolset-9-toolchain 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 -y install apr-devel apr-util-openssl apr-util-devel
# Install MQ client
COPY install-mq.sh /usr/local/bin/
RUN mkdir /opt/mqm \
&& chmod a+x /usr/local/bin/install-mq.sh \
&& sleep 1 \
&& INSTALL_SDK=1 install-mq.sh \
&& chown -R 1001:root /opt/mqm/*
COPY authservice/ /opt/app-root/src/authservice/
WORKDIR /opt/app-root/src/authservice/mqhtpass
RUN make all
###############################################################################
# Add default developer config
###############################################################################
@@ -159,7 +140,7 @@ LABEL io.k8s.description="Simplify, accelerate and facilitate the reliable excha
LABEL base-image=$BASE_IMAGE
LABEL base-image-release=$BASE_TAG
USER 0
COPY --from=cbuilder /opt/app-root/src/authservice/mqhtpass/build/mqhtpass.so /opt/mqm/lib64/
COPY --from=builder $GO_WORKDIR/amqpas* /opt/mqm/lib64/
COPY etc/mqm/*.ini /etc/mqm/
COPY etc/mqm/mq.htpasswd /etc/mqm/
RUN chmod 0660 /etc/mqm/mq.htpasswd
@@ -181,7 +162,7 @@ RUN chown -R 1001:root /etc/mqm/* \
&& install --directory --mode 2775 --owner 1001 --group root /run/runmqdevserver
ENV MQ_ENABLE_EMBEDDED_WEB_SERVER=1 MQ_GENERATE_CERTIFICATE_HOSTNAME=localhost
ENV LD_LIBRARY_PATH=/opt/mqm/lib64
ENV MQ_CONNAUTH_USE_HTP=true
ENV MQS_PERMIT_UNKNOWN_ID=true
ENV MQ_CONNAUTH_USE_HTP=true
USER 1001
ENTRYPOINT ["runmqdevserver"]

View File

@@ -1,4 +1,4 @@
# © Copyright IBM Corporation 2017, 2021
# © 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,6 +18,7 @@
###############################################################################
include config.env
include source-branch.env
# RELEASE shows what release of the container code has been built
RELEASE ?=
@@ -63,6 +64,10 @@ MQ_DELIVERY_REGISTRY_CREDENTIAL ?=
REGISTRY_USER ?=
# REGISTRY_PASS is the password used to login to the Red Hat registry
REGISTRY_PASS ?=
# DOCKER_USER is the username used to login to docker hub
DOCKER_USER ?=
# DOCKER_PASS is the password used to login to docker hub
DOCKER_PASS ?=
# 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
@@ -71,8 +76,6 @@ LTS ?= false
###############################################################################
# Other variables
###############################################################################
# Build doesn't work if BuildKit is enabled
DOCKER_BUILDKIT=0
GO_PKG_DIRS = ./cmd ./internal ./test
MQ_ARCHIVE_TYPE=LINUX
MQ_ARCHIVE_DEV_TYPE=Linux
@@ -113,6 +116,11 @@ else ifeq "$(ARCH)" "s390x"
MQ_ARCHIVE_ARCH=S390X
endif
# If this is a fake master build, push images to alternative location (pipeline wont consider these images GA candidates)
ifeq ($(shell [ "$(TRAVIS)" = "true" ] && [ -n "$(MAIN_BRANCH)" ] && [ -n "$(SOURCE_BRANCH)" ] && [ "$(MAIN_BRANCH)" != "$(SOURCE_BRANCH)" ] && echo "true"), true)
MQ_DELIVERY_REGISTRY_NAMESPACE="master-fake"
endif
# LTS_TAG is the tag modifier for an LTS container build
LTS_TAG=
ifeq "$(LTS)" "true"
@@ -138,10 +146,16 @@ endif
# image tagging
ifneq "$(RELEASE)" "$(EMPTY)"
EXTRA_LABELS=--label release=$(RELEASE)
EXTRA_LABELS_RELEASE=--label "release=$(RELEASE)"
RELEASE_TAG="-$(RELEASE)"
endif
ifneq "$(MQ_ARCHIVE_LEVEL)" "$(EMPTY)"
EXTRA_LABELS_LEVEL=--label "mq-build=$(MQ_ARCHIVE_LEVEL)"
endif
EXTRA_LABELS=$(EXTRA_LABELS_RELEASE) $(EXTRA_LABELS_LEVEL)
ifeq "$(TIMESTAMPFLAT)" "$(EMPTY)"
TIMESTAMPFLAT=$(shell date "+%Y%m%d%H%M%S")
endif
@@ -206,7 +220,7 @@ downloads/$(MQ_ARCHIVE_DEV):
ifneq "$(BUILD_RSYNC_SERVER)" "$(EMPTY)"
# Use key which is not stored in the repository to fetch the files from the fileserver
curl -L $(BUILD_RSYNC_ENCRYPTED_KEY_URL) -o ./host.key.gpg
@echo $(BUILD_RSYNC_ENCRYPTION_PASSWORD)|gpg --batch --passphrase-fd 0 ./host.key.gpg
@echo $(BUILD_RSYNC_ENCRYPTION_PASSWORD)|gpg --passphrase-fd 0 ./host.key.gpg
chmod 600 ./host.key
rsync -rv -e "ssh -o BatchMode=yes -q -o StrictHostKeyChecking=no -i ./host.key" --include="*/" --include="*.tar.gz" --exclude="*" $(BUILD_RSYNC_USER)@$(BUILD_RSYNC_SERVER):"$(BUILD_RSYNC_PATH)" downloads/$(MQ_ARCHIVE_DEV)
-@rm host.key.gpg host.key
@@ -225,7 +239,7 @@ ifneq "$(BUILD_RSYNC_SERVER)" "$(EMPTY)"
# Use key which is not stored in the repository to fetch the files from the fileserver
-@rm host.key.gpg host.key
curl -L $(BUILD_RSYNC_ENCRYPTED_KEY_URL) -o ./host.key.gpg
@echo $(BUILD_RSYNC_ENCRYPTION_PASSWORD)|gpg --batch --passphrase-fd 0 ./host.key.gpg
@echo $(BUILD_RSYNC_ENCRYPTION_PASSWORD)|gpg --passphrase-fd 0 ./host.key.gpg
chmod 600 ./host.key
rsync -rv -e "ssh -o BatchMode=yes -q -o StrictHostKeyChecking=no -i ./host.key" --include="*/" --include="*.tar.gz" --exclude="*" $(BUILD_RSYNC_USER)@$(BUILD_RSYNC_SERVER):"$(BUILD_RSYNC_PATH)" downloads/$(MQ_ARCHIVE)
-@rm host.key.gpg host.key
@@ -341,7 +355,7 @@ endif
build-advancedserver-host: build-advancedserver
.PHONY: build-advancedserver
build-advancedserver: registry-login log-build-env downloads/$(MQ_ARCHIVE) command-version
build-advancedserver: docker-login registry-login log-build-env downloads/$(MQ_ARCHIVE) command-version
$(info $(SPACER)$(shell printf $(TITLE)"Build $(MQ_IMAGE_ADVANCEDSERVER):$(MQ_TAG)"$(END)))
$(call build-mq,$(MQ_IMAGE_ADVANCEDSERVER),$(MQ_TAG),Dockerfile-server,$(MQ_ARCHIVE),mq-server)
@@ -349,7 +363,7 @@ build-advancedserver: registry-login log-build-env downloads/$(MQ_ARCHIVE) comma
build-devserver-host: build-devserver
.PHONY: build-devserver
build-devserver: registry-login log-build-env downloads/$(MQ_ARCHIVE_DEV) command-version
build-devserver: docker-login registry-login log-build-env downloads/$(MQ_ARCHIVE_DEV) command-version
$(info $(shell printf $(TITLE)"Build $(MQ_IMAGE_DEVSERVER):$(MQ_TAG)"$(END)))
$(call build-mq,$(MQ_IMAGE_DEVSERVER),$(MQ_TAG),Dockerfile-server,$(MQ_ARCHIVE_DEV),mq-dev-server)
@@ -372,6 +386,12 @@ ifneq ($(REGISTRY_USER),)
$(COMMAND) login -u $(REGISTRY_USER) -p $(REGISTRY_PASS) registry.redhat.io
endif
.PHONY: docker-login
docker-login:
ifneq ($(DOCKER_USER),)
docker login -u $(DOCKER_USER) -p $(DOCKER_PASS)
endif
.PHONY: log-build-env
log-build-vars:
$(info $(SPACER)$(shell printf $(TITLE)"Build environment"$(END)))
@@ -402,6 +422,9 @@ pull-mq-archive-dev:
.PHONY: push-advancedserver
push-advancedserver:
@if [ $(MQ_DELIVERY_REGISTRY_NAMESPACE) = "master-fake" ]; then\
echo "Detected fake master build. Note that the push destination is set to the fake master namespace: $(MQ_DELIVERY_REGISTRY_FULL_PATH)";\
fi
$(info $(SPACER)$(shell printf $(TITLE)"Push production image to $(MQ_DELIVERY_REGISTRY_FULL_PATH)"$(END)))
$(COMMAND) login $(MQ_DELIVERY_REGISTRY_HOSTNAME) -u $(MQ_DELIVERY_REGISTRY_USER) -p $(MQ_DELIVERY_REGISTRY_CREDENTIAL)
$(COMMAND) tag $(MQ_IMAGE_ADVANCEDSERVER)\:$(MQ_TAG) $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_FULL_RELEASE_NAME)
@@ -409,6 +432,9 @@ push-advancedserver:
.PHONY: push-devserver
push-devserver:
@if [ $(MQ_DELIVERY_REGISTRY_NAMESPACE) = "master-fake" ]; then\
echo "Detected fake master build. Note that the push destination is set to the fake master namespace: $(MQ_DELIVERY_REGISTRY_FULL_PATH)";\
fi
$(info $(SPACER)$(shell printf $(TITLE)"Push developer image to $(MQ_DELIVERY_REGISTRY_FULL_PATH)"$(END)))
$(COMMAND) login $(MQ_DELIVERY_REGISTRY_HOSTNAME) -u $(MQ_DELIVERY_REGISTRY_USER) -p $(MQ_DELIVERY_REGISTRY_CREDENTIAL)
$(COMMAND) tag $(MQ_IMAGE_DEVSERVER)\:$(MQ_TAG) $(MQ_DELIVERY_REGISTRY_FULL_PATH)/$(MQ_IMAGE_DEV_FULL_RELEASE_NAME)
@@ -449,7 +475,7 @@ endif
echo $(shell ./travis-build-scripts/create-manifest-list.sh -r $(MQ_DELIVERY_REGISTRY_HOSTNAME) -n $(MQ_DELIVERY_REGISTRY_NAMESPACE) -i $(MQ_IMAGE_ADVANCEDSERVER) -t $(MQ_MANIFEST_TAG) -u $(MQ_ARCHIVE_REPOSITORY_USER) -p $(MQ_ARCHIVE_REPOSITORY_CREDENTIAL) -d "$(MQ_IMAGE_ADVANCEDSERVER_AMD64_DIGEST) $(MQ_IMAGE_ADVANCEDSERVER_S390X_DIGEST)" $(END))
.PHONY: build-skopeo-container
build-skopeo-container:
build-skopeo-container: docker-login
$(COMMAND) images | grep -q "skopeo"; if [ $$? != 0 ]; then docker build -t skopeo:latest ./docker-builds/skopeo/; fi
.PHONY: clean
@@ -517,13 +543,14 @@ include formatting.mk
.PHONY: update-release-information
update-release-information:
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
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_LTS_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
sed -i.bak 's/ibm-mqadvanced-server-dev.*-amd64/ibm-mqadvanced-server-dev:$(MQ_VERSION)-amd64/g' docs/security.md && rm docs/security.md.bak
sed -i.bak 's/MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:.*-amd64/MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:$(MQ_VERSION)-amd64/g' docs/testing.md && rm docs/testing.md.bak
$(eval MQ_VERSION_2=$(shell echo '${MQ_VERSION_1}' | rev | cut -c 3- | rev))
sed -i.bak 's/knowledgecenter\/SSFKSJ_.*\/com/knowledgecenter\/SSFKSJ_${MQ_VERSION_2}.0\/com/g' docs/usage.md && rm docs/usage.md.bak
$(eval MQ_VERSION_3=$(shell echo '${MQ_VERSION_1}' | sed "s/\.//g"))
sed -i.bak 's/MQ_..._ARCHIVE_REPOSITORY/MQ_${MQ_VERSION_3}_ARCHIVE_REPOSITORY/g' .travis.yml && rm .travis.yml.bak
sed -i.bak 's/IBM_MQ_.*_LINUX_X86-64_NOINST.tar.gz/IBM_MQ_${MQ_LTS_VERSION}_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_LTS_VERSION)-amd64/g' docs/security.md
sed -i.bak 's/ibm-mqadvanced-server-dev.*-amd64/ibm-mqadvanced-server-dev:$(MQ_LTS_VERSION)-amd64/g' docs/security.md && rm docs/security.md.bak
sed -i.bak 's/MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:.*-amd64/MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:$(MQ_LTS_VERSION)-amd64/g' docs/testing.md && rm docs/testing.md.bak
$(eval MQ_VERSION_2=$(shell echo '${MQ_VERSION_1}' | sed "s/\.//g"))
sed -i.bak 's/MQ_..._ARCHIVE_REPOSITORY/MQ_${MQ_VERSION_2}_ARCHIVE_REPOSITORY/g' .travis.yml && rm .travis.yml.bak
sed -i.bak 's/MQ_LTS_VERSION=[0-9]\.[0-9]\.[0-9]\.[0-9]/MQ_LTS_VERSION=${MQ_LTS_VERSION}/g' .travis.yml && rm .travis.yml.bak
$(eval MQ_LTS_VERSION_1=$(shell echo '${MQ_LTS_VERSION}' | sed "s/\.//g"))
sed -i.bak 's/MQ_...._EUS_ARCHIVE_REPOSITORY/MQ_${MQ_LTS_VERSION_1}_EUS_ARCHIVE_REPOSITORY/g' .travis.yml && rm .travis.yml.bak

18319
NOTICES.txt

File diff suppressed because it is too large Load Diff

View File

@@ -44,12 +44,11 @@ For issues relating specifically to the container image or Helm chart, please us
The Dockerfiles and associated code and scripts are licensed under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html).
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-BYHCL7) (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-APIG-BZDDDY) (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 for Developers](http://www14.software.ibm.com/cgi-bin/weblap/lap.pl?la_formnum=Z125-3301-14&li_formnum=L-APIG-BMKG5H) (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-APIG-BMJJBM) (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, 2021

View File

@@ -1,50 +0,0 @@
# © 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.
# 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.
# This Makefile expects the following to be installed:
# - gcc
# - ldd
# - MQ SDK (mqm_r library, plus header files)
# - Apache Portable Runtime (apr-1 and aprutil-1 libraries, plus header files)
SRC_DIR = src
BUILD_DIR = ./build
# Flags passed to the C compiler. Need to use gnu11 to get POSIX functions needed for file locking.
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.o : $(SRC_DIR)/log.c $(SRC_DIR)/log.h
mkdir -p ${dir $@}
gcc $(CFLAGS) -c $(SRC_DIR)/log.c -o $@
$(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 $@
$(BUILD_DIR)/htpass_test : $(BUILD_DIR)/htpass.o $(BUILD_DIR)/log.o
mkdir -p ${dir $@}
gcc $(CFLAGS) $(LIB_APR) -lpthread $(SRC_DIR)/htpass_test.c $^ -o $@
# Run HTPasswd tests, and print log if they fail
$@ || (cat htpass_test*.log && exit 1)
$(BUILD_DIR)/mqhtpass.so : $(BUILD_DIR)/log.o $(BUILD_DIR)/htpass.o
mkdir -p ${dir $@}
# NOTE: rpath for libapr will be different on Ubuntu
gcc $(CFLAGS) -I/opt/mqm/inc -D_REENTRANT $(LIB_APR) $(LIB_MQ) -Wl,-rpath,/opt/mqm/lib64 -Wl,-rpath,/usr/lib64 -shared $(SRC_DIR)/mqhtpass.c $^ -o $@
ldd $@

View File

@@ -1,145 +0,0 @@
/*
© 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.
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 <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
#include "htpass.h"
#include <linux/limits.h>
#include <apr_general.h>
#include <apr_errno.h>
#include <apr_md5.h>
bool htpass_valid_file(char *filename)
{
bool valid = true;
FILE *fp;
char *huser;
fp = fopen(filename, "r");
if (fp == NULL)
{
log_errorf("Error %d opening htpasswd file '%s'", errno, filename);
}
if (fp)
{
const size_t line_size = 1024;
char *line = malloc(line_size);
while (fgets(line, line_size, fp) != NULL)
{
char *saveptr;
// Need to use strtok_r to be safe for multiple threads
huser = strtok_r(line, ":", &saveptr);
if (strlen(huser) >= 12)
{
log_errorf("Invalid htpasswd file for use with IBM MQ. User '%s' is longer than twelve characters", huser);
valid = false;
break;
}
}
fclose(fp);
if (line)
{
free(line);
}
}
return valid;
}
char *find_hash(char *filename, char *user)
{
bool found = false;
FILE *fp;
char *huser;
char *hash;
fp = fopen(filename, "r");
if (fp == NULL)
{
log_errorf("Error %d opening htpasswd file '%s'", errno, filename);
}
if (fp)
{
const size_t line_size = 1024;
char *line = malloc(line_size);
while (fgets(line, line_size, fp) != NULL)
{
char *saveptr;
// Need to use strtok_r to be safe for multiple threads
huser = strtok_r(line, ":", &saveptr);
if (huser && (strcmp(user, huser) == 0))
{
// Make a duplicate of the string, because we'll be keeping it
hash = strdup(strtok_r(NULL, " \r\n\t", &saveptr));
found = true;
break;
}
}
fclose(fp);
if (line)
{
free(line);
}
}
if (!found)
{
hash = NULL;
}
return hash;
}
int htpass_authenticate_user(char *filename, char *user, char *password)
{
char *hash = find_hash(filename, user);
int result = -1;
if (hash == NULL)
{
result = HTPASS_INVALID_USER;
log_debugf("User does not exist. user=%s", user);
}
else
{
// Use the Apache Portable Runtime utilities to validate the password against the hash.
// Supports multiple hashing algorithms, but we should only be using bcrypt
apr_status_t status = apr_password_validate(password, hash);
// status is usually either APR_SUCCESS or APR_EMISMATCH
if (status == APR_SUCCESS)
{
result = HTPASS_VALID;
log_debugf("Correct password supplied. user=%s", user);
}
else
{
result = HTPASS_INVALID_PASSWORD;
log_debugf("Incorrect password supplied. user=%s", user);
}
}
return result;
}
bool htpass_valid_user(char *filename, char *user)
{
char *hash = find_hash(filename, user);
bool valid = false;
if (hash != NULL)
{
valid = true;
}
return valid;
}

View File

@@ -1,49 +0,0 @@
/*
© 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.
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.
*/
#ifndef _HTPASS_H
#define _HTPASS_H
#define HTPASS_VALID 0
#define HTPASS_INVALID_USER 1
#define HTPASS_INVALID_PASSWORD 2
/**
* Validate an HTPasswd file for use with IBM MQ.
*
* @param filename the HTPasswd file
*/
_Bool htpass_valid_file(char *filename);
/**
* Authenticate a user, based on the supplied file name.
*
* @param filename the HTPasswd file
* @param user the user name to authenticate
* @param password the password of the user
* @return HTPASS_VALID, HTPASS_INVALID_USER or HTPASS_INVALID_PASSWORD
*/
int htpass_authenticate_user(char *filename, char *user, char *password);
/**
* Validate that a user exists in the password file.
*
* @param filename the HTPasswd file
* @param user the user name to validate
*/
_Bool htpass_valid_user(char *filename, char *user);
#endif

View File

@@ -1,223 +0,0 @@
/*
© 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.
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 "log.h"
#include "htpass.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__)
// Indicate test has failed
void test_fail(const char *test_name)
{
printf("--- FAIL: %s\n", test_name);
exit(1);
}
// ----------------------------------------------------------------------------
// Simple tests for file validation
// ----------------------------------------------------------------------------
void test_htpass_valid_file_ok()
{
test_start();
int ok = htpass_valid_file("./src/htpass_test.htpasswd");
if (!ok)
test_fail(__func__);
test_pass();
}
void test_htpass_valid_file_too_long()
{
test_start();
int ok = htpass_valid_file("./src/htpass_test_invalid.htpasswd");
if (ok)
test_fail(__func__);
test_pass();
}
// ----------------------------------------------------------------------------
// Simple tests for authentication
// ----------------------------------------------------------------------------
void test_htpass_authenticate_user_fred_valid()
{
test_start();
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "passw0rd");
printf("%s: fred - %d\n", __func__, rc);
if (rc != HTPASS_VALID)
test_fail(__func__);
test_pass();
}
void test_htpass_authenticate_user_fred_invalid1()
{
test_start();
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "passw0rd ");
printf("%s: fred - %d\n", __func__, rc);
if (rc != HTPASS_INVALID_PASSWORD)
test_fail(__func__);
test_pass();
}
void test_htpass_authenticate_user_fred_invalid2()
{
test_start();
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "");
printf("%s: fred - %d\n", __func__, rc);
if (rc != HTPASS_INVALID_PASSWORD)
test_fail(__func__);
test_pass();
}
void test_htpass_authenticate_user_fred_invalid3()
{
test_start();
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "clearlywrong");
printf("%s: fred - %d\n", __func__, rc);
if (rc != HTPASS_INVALID_PASSWORD)
test_fail(__func__);
test_pass();
}
void test_htpass_authenticate_user_barney_valid()
{
test_start();
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "barney", "s3cret");
printf("%s: barney - %d\n", __func__, rc);
if (rc != HTPASS_VALID)
test_fail(__func__);
test_pass();
}
void test_htpass_authenticate_user_unknown()
{
test_start();
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "george", "s3cret");
printf("%s: barney - %d\n", __func__, rc);
if (rc != HTPASS_INVALID_USER)
test_fail(__func__);
test_pass();
}
// ----------------------------------------------------------------------------
// Multi-threaded test
// ----------------------------------------------------------------------------
#define NUM_THREADS 5
// Number of tests to perform per thread. Higher numbers are more likely to trigger timing issue.
#define NUM_TESTS_PER_THREAD 1000
// Maximum number of JSON errors to report (log can get flooded)
#define MAX_JSON_ERRORS 10
// Authenticate multiple users, multiple times
void *authenticate_many_times(void *p)
{
for (int i = 0; i < NUM_TESTS_PER_THREAD; i++)
{
int rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "barney", "s3cret");
if (rc != HTPASS_VALID)
test_fail(__func__);
rc = htpass_authenticate_user("./src/htpass_test.htpasswd", "fred", "passw0rd");
if (rc != HTPASS_VALID)
test_fail(__func__);
}
pthread_exit(NULL);
}
void check_log_file_valid(char *filename)
{
int errors = 0;
printf("--- Checking log file is valid\n");
// Check that the JSON log file isn't corrupted
FILE *log = fopen(filename, "r");
if (log == NULL)
{
test_fail(__func__);
}
const size_t line_size = 1024;
char *line = malloc(line_size);
while (fgets(line, line_size, log) != NULL)
{
if ((line[0] != '{') && (errors < MAX_JSON_ERRORS))
{
printf("*** Invalid JSON detected: %s\n", line);
errors++;
}
}
if (line)
{
free(line);
}
fclose(log);
}
// Test authenticate_user with multiple threads, each doing many authentications
void test_htpass_authenticate_user_multithreaded(char *logfile)
{
pthread_t threads[NUM_THREADS];
int rc;
test_start();
// Re-initialize the log to use a file for the multi-threaded test
log_init(logfile);
for (int i = 0; i < NUM_THREADS; i++)
{
printf("Creating thread %d\n", i);
rc = pthread_create(&threads[i], NULL, authenticate_many_times, NULL);
if (rc)
{
printf("Error: Unable to create thread, %d\n", rc);
test_fail(__func__);
}
}
// Wait for all the threads to complete
for (int i = 0; i < NUM_THREADS; i++)
{
pthread_join(threads[i], NULL);
}
check_log_file_valid(logfile);
test_pass();
}
// ----------------------------------------------------------------------------
int main()
{
// Turn on debugging for the tests
setenv("DEBUG", "true", true);
log_init("htpass_test.log");
test_htpass_valid_file_ok();
test_htpass_valid_file_too_long();
test_htpass_authenticate_user_fred_valid();
test_htpass_authenticate_user_fred_invalid1();
test_htpass_authenticate_user_fred_invalid2();
test_htpass_authenticate_user_fred_invalid3();
test_htpass_authenticate_user_barney_valid();
test_htpass_authenticate_user_unknown();
log_close();
// Call multi-threaded test last, because it re-initializes the log to use a file
test_htpass_authenticate_user_multithreaded("htpass_test_multithreaded.log");
}

View File

@@ -1,2 +0,0 @@
fred:$2y$05$3Fp9epsqEwWOHdyj9Ngf9.qfX34kzc9zNrdQ7kac0GmcCvQjIkAwy
barney:$2y$05$l8EoyCQ9y2PyfUzIDDfTyu7SSaJEYB1TuHy07xZvN7xt/pR3SIw0a

View File

@@ -1,3 +0,0 @@
fred:$2y$05$3Fp9epsqEwWOHdyj9Ngf9.qfX34kzc9zNrdQ7kac0GmcCvQjIkAwy
barney:$2y$05$l8EoyCQ9y2PyfUzIDDfTyu7SSaJEYB1TuHy07xZvN7xt/pR3SIw0a
namewhichisfartoolongformq:$2y$05$l8EoyCQ9y2PyfUzIDDfTyu7SSaJEYB1TuHy07xZvN7xt/pR3SIw0a

View File

@@ -1,152 +0,0 @@
/*
© 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.
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 <stdarg.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
FILE *fp = NULL;
int pid;
char hostname[255];
bool debug = false;
/**
* Determine whether debugging is enabled or not, using an environment variable.
*/
void init_debug(){
char *debug_env = getenv("DEBUG");
if (debug_env != NULL)
{
// Enable debug logging if the DEBUG environment variable is set
if (strncmp(debug_env, "true", 4) || strncmp(debug_env, "1", 1))
{
debug = true;
}
}
}
/**
* Internal function to initialize the log with the given file mode.
*/
int log_init_internal(char *filename, const char *mode)
{
int result = 0;
pid = getpid();
hostname[254] = '\0';
gethostname(hostname, 254);
if (!fp)
{
fp = fopen(filename, "a");
if (fp)
{
// Disable buffering for this file
setbuf(fp, NULL);
}
else
{
result = 1;
}
}
init_debug();
return result;
}
int log_init_reset(char *filename)
{
// Open the log file for writing (overwrite if it already exists)
return log_init_internal(filename, "w");
}
int log_init(char *filename)
{
// Open the log file file for appending
return log_init_internal(filename, "a");
}
void log_init_file(FILE *f)
{
fp = f;
init_debug();
}
void log_close()
{
if (fp)
{
fclose(fp);
fp = NULL;
}
}
void log_printf(const char *source_file, int source_line, const char *level, const char *format, ...)
{
if (fp)
{
// If this is a DEBUG message, and debugging is off
if ((strncmp(level, "DEBUG", 5) == 0) && !debug)
{
return;
}
char buf[1024] = "";
char *cur = buf;
char* const end = buf + sizeof buf;
char date_buf[70];
struct tm *utc;
time_t t;
struct timeval now;
gettimeofday(&now, NULL);
t = now.tv_sec;
t = time(NULL);
utc = gmtime(&t);
cur += snprintf(cur, end-cur, "{");
cur += snprintf(cur, end-cur, "\"loglevel\":\"%s\"", level);
// Print ISO-8601 time and date
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 / 1000);
}
cur += snprintf(cur, end-cur, ", \"ibm_processId\":\"%d\"", pid);
cur += snprintf(cur, end-cur, ", \"host\":\"%s\"", hostname);
cur += snprintf(cur, end-cur, ", \"module\":\"%s:%d\"", source_file, source_line);
cur += snprintf(cur, end-cur, ", \"message\":\"");
if (strncmp(level, "DEBUG", 5) == 0)
{
// Add a prefix on any debug messages
cur += snprintf(cur, end-cur, "mqhtpass: ");
}
// Print log message, using varargs
va_list args;
va_start(args, format);
cur += vsnprintf(cur, end-cur, format, args);
va_end(args);
cur += snprintf(cur, end-cur, "\"}\n");
// 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, buf);
}
}

View File

@@ -1,63 +0,0 @@
/*
© 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.
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.
*/
#ifndef _LOG_H
#define _LOG_H
/**
* Initialize the log to use the given file name, wiping any existing contents.
*/
int log_init_reset(char *filename);
/**
* Initialize the log to use the given file name.
*/
int log_init(char *filename);
/**
* Initialize the log with an existing file handle.
*/
void log_init_file(FILE *f);
/**
* Write a message to the log file, based on a printf format string.
*
* @param source_file the name of the source code file submitting this log message
* @param source_line the line of code in the source file
* @param level the log level, one of "DEBUG", "INFO" or "ERROR"
* @param format the printf format string for the message
*/
void log_printf(const char *source_file, int source_line, const char *level, const char *format, ...);
void log_close();
/**
* Variadic macro to write an informational message to the log file, based on a printf format string.
*/
#define log_infof(format,...) log_printf(__FILE__, __LINE__, "INFO", format, ##__VA_ARGS__)
/**
* Variadic macro to write an error message to the log file, based on a printf format string.
*/
#define log_errorf(format,...) log_printf(__FILE__, __LINE__, "ERROR", format, ##__VA_ARGS__)
/**
* Variadic macro to write a debug message to the log file, based on a printf format string.
*/
#define log_debugf(format,...) log_printf(__FILE__, __LINE__, "DEBUG", format, ##__VA_ARGS__)
#endif

View File

@@ -1,351 +0,0 @@
/*
© 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.
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.
*/
// This is a developer only configuration and not recommended for production usage.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmqec.h>
#include "log.h"
#include "htpass.h"
// Declare the internal functions that implement the interface
MQZ_INIT_AUTHORITY MQStart;
static MQZ_AUTHENTICATE_USER mqhtpass_authenticate_user;
static MQZ_FREE_USER mqhtpass_free_user;
static MQZ_TERM_AUTHORITY mqhtpass_terminate;
#define LOG_FILE "/var/mqm/errors/mqhtpass.json"
#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
* other functions which are to be called by the queue manager.
*
* This function is called whenever the module is loaded. The Options
* field will show whether it's a PRIMARY (i.e. during qmgr startup) or
* SECONDARY.
*/
void MQENTRY MQStart(
MQHCONFIG hc,
MQLONG Options,
MQCHAR48 QMgrName,
MQLONG ComponentDataLength,
PMQBYTE ComponentData,
PMQLONG Version,
PMQLONG pCompCode,
PMQLONG pReason)
{
MQLONG CC = MQCC_OK;
MQLONG Reason = MQRC_NONE;
int log_rc = 0;
if (Options == MQZIO_PRIMARY)
{
// Reset the log file. The file could still get large if debug is turned on,
// but this is a simpler solution for now.
log_rc = log_init_reset(LOG_FILE);
}
else
{
log_rc = log_init(LOG_FILE);
}
if (log_rc != 0)
{
CC = MQCC_FAILED;
Reason = MQRC_INITIALIZATION_FAILED;
}
if (Options == MQZIO_PRIMARY)
{
log_infof("Initializing %s", NAME);
}
log_debugf("MQStart options=%s qmgr=%s", ((Options == MQZIO_SECONDARY) ? "Secondary" : "Primary"), trim(QMgrName));
if (!htpass_valid_file(HTPASSWD_FILE))
{
CC = MQCC_FAILED;
Reason = MQRC_INITIALIZATION_FAILED;
}
// Initialize the functions to use for each entry point
if (CC == MQCC_OK)
{
hc->MQZEP_Call(hc, MQZID_INIT_AUTHORITY, (PMQFUNC)MQStart, &CC, &Reason);
}
if (CC == MQCC_OK)
{
hc->MQZEP_Call(hc, MQZID_TERM_AUTHORITY, (PMQFUNC)mqhtpass_terminate, &CC, &Reason);
}
if (CC == MQCC_OK)
{
hc->MQZEP_Call(hc, MQZID_AUTHENTICATE_USER, (PMQFUNC)mqhtpass_authenticate_user, &CC, &Reason);
}
if (CC == MQCC_OK)
{
hc->MQZEP_Call(hc, MQZID_FREE_USER, (PMQFUNC)mqhtpass_free_user, &CC, &Reason);
}
*Version = MQZAS_VERSION_5;
*pCompCode = CC;
*pReason = Reason;
return;
}
/**
* Called during the connection of any application which supplies an MQCSP (Connection Security Parameters).
* This is the usual case.
* See https://www.ibm.com/support/knowledgecenter/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q095610_.html
*/
static void MQENTRY mqhtpass_authenticate_user_csp(
PMQCHAR pQMgrName,
PMQCSP pSecurityParms,
PMQZAC pApplicationContext,
PMQZIC pIdentityContext,
PMQPTR pCorrelationPtr,
PMQBYTE pComponentData,
PMQLONG pContinuation,
PMQLONG pCompCode,
PMQLONG pReason)
{
char *csp_user = NULL;
char *csp_pass = NULL;
// Firstly, create null-terminated strings from the user credentials in the MQ CSP object
csp_user = malloc(pSecurityParms->CSPUserIdLength + 1);
if (!csp_user)
{
log_errorf("%s is unable to allocate memory for a user", NAME);
*pCompCode = MQCC_FAILED;
*pReason = MQRC_SERVICE_ERROR;
return;
}
strncpy(csp_user, pSecurityParms->CSPUserIdPtr, pSecurityParms->CSPUserIdLength);
csp_user[pSecurityParms->CSPUserIdLength] = 0;
csp_pass = malloc((pSecurityParms->CSPPasswordLength + 1));
if (!csp_pass)
{
log_errorf("%s is unable to allocate memory for a password", NAME);
*pCompCode = MQCC_FAILED;
*pReason = MQRC_SERVICE_ERROR;
if (csp_user)
{
free(csp_user);
}
return;
}
strncpy(csp_pass, pSecurityParms->CSPPasswordPtr, pSecurityParms->CSPPasswordLength);
csp_pass[pSecurityParms->CSPPasswordLength] = 0;
log_debugf("%s with CSP user set. user=%s", __func__, csp_user);
int auth_result = htpass_authenticate_user(HTPASSWD_FILE, csp_user, csp_pass);
if (auth_result == HTPASS_VALID)
{
// An OK completion code means MQ will accept this user is authenticated
*pCompCode = MQCC_OK;
*pReason = MQRC_NONE;
// Tell the queue manager to stop trying other authorization services.
*pContinuation = MQZCI_STOP;
memcpy(pIdentityContext->UserIdentifier, csp_user, sizeof(pIdentityContext->UserIdentifier));
log_debugf("Authenticated user=%s", pIdentityContext->UserIdentifier);
}
// If the htpasswd file does not have an entry for this user
else if (auth_result == HTPASS_INVALID_USER)
{
*pCompCode = MQCC_WARNING;
*pReason = MQRC_NONE;
// 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",
trim(pIdentityContext->UserIdentifier),
trim(pApplicationContext->EffectiveUserID),
trim(pApplicationContext->ApplName),
trim(csp_user),
*pCompCode,
*pReason);
}
// If the htpasswd file has an entry for this user, but the password supplied is incorrect
else if (auth_result == HTPASS_INVALID_PASSWORD)
{
*pCompCode = MQCC_WARNING;
*pReason = MQRC_NOT_AUTHORIZED;
// 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",
trim(pIdentityContext->UserIdentifier),
trim(pApplicationContext->EffectiveUserID),
trim(pApplicationContext->ApplName),
trim(csp_user),
*pCompCode,
*pReason);
}
if (csp_user)
{
free(csp_user);
}
if (csp_pass)
{
free(csp_pass);
}
return;
}
/**
* Called during the connection of any application.
* For more information on the parameters, see https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_latest/com.ibm.mq.ref.dev.doc/q110090_.html
*/
static void MQENTRY mqhtpass_authenticate_user(
PMQCHAR pQMgrName,
PMQCSP pSecurityParms,
PMQZAC pApplicationContext,
PMQZIC pIdentityContext,
PMQPTR pCorrelationPtr,
PMQBYTE pComponentData,
PMQLONG pContinuation,
PMQLONG pCompCode,
PMQLONG pReason)
{
char *spuser = NULL;
char *sppass = NULL;
// By default, return a warning, which indicates to MQ that this
// authorization service hasn't authenticated the user.
*pCompCode = MQCC_WARNING;
*pReason = MQRC_NONE;
// By default, tell the queue manager to continue trying other
// authorization services.
*pContinuation = MQZCI_CONTINUE;
if ((pSecurityParms->AuthenticationType) == MQCSP_AUTH_USER_ID_AND_PWD)
{
mqhtpass_authenticate_user_csp(pQMgrName, pSecurityParms, pApplicationContext, pIdentityContext, pCorrelationPtr, pComponentData, pContinuation, pCompCode, pReason);
}
else
{
// Password not supplied, so just check that the user ID is valid
spuser = malloc(sizeof(PMQCHAR12) + 1);
if (!spuser)
{
log_errorf("%s is unable to allocate memory to check a user", NAME);
*pCompCode = MQCC_FAILED;
*pReason = MQRC_SERVICE_ERROR;
return;
}
strncpy(spuser, pApplicationContext->EffectiveUserID, strlen(pApplicationContext->EffectiveUserID));
spuser[sizeof(PMQCHAR12)] = 0;
log_debugf("%s without CSP user set. effectiveuid=%s env=%d, callertype=%d, type=%d, accttoken=%d applidentitydata=%d", __func__, spuser, pApplicationContext->Environment, pApplicationContext->CallerType, pApplicationContext->AuthenticationType, pIdentityContext->AccountingToken, pIdentityContext->ApplIdentityData);
if (strncmp(spuser, "mqm", 3) == 0)
{
// Special case: pass the "mqm" user on for validation up the chain
// A warning in the completion code means MQ will pass this to other authorization services
*pCompCode = MQCC_WARNING;
*pReason = MQRC_NONE;
*pContinuation = MQZCI_CONTINUE;
}
else
{
bool valid_user = htpass_valid_user(HTPASSWD_FILE, spuser);
if (valid_user)
{
// An OK completion code means MQ will accept this user is authenticated
*pCompCode = MQCC_OK;
*pReason = MQRC_NONE;
*pContinuation = MQZCI_STOP;
memcpy(pIdentityContext->UserIdentifier, spuser, sizeof(pIdentityContext->UserIdentifier));
}
else
{
log_debugf(
"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);
}
if (spuser)
{
free(spuser);
}
}
}
return;
}
/**
* Called during MQDISC, as the inverse of the call to authenticate.
*/
static void MQENTRY mqhtpass_free_user(
PMQCHAR pQMgrName,
PMQZFP pFreeParms,
PMQBYTE pComponentData,
PMQLONG pContinuation,
PMQLONG pCompCode,
PMQLONG pReason)
{
log_debugf("mqhtpass_freeuser()");
*pCompCode = MQCC_WARNING;
*pReason = MQRC_NONE;
*pContinuation = MQZCI_CONTINUE;
}
/**
* Called when the authorization service is terminated.
*/
static void MQENTRY mqhtpass_terminate(
MQHCONFIG hc,
MQLONG Options,
PMQCHAR pQMgrName,
PMQBYTE pComponentData,
PMQLONG pCompCode,
PMQLONG pReason)
{
if (Options == MQZTO_PRIMARY)
{
log_infof("Terminating %s", NAME);
log_close();
}
else {
log_debugf("Terminating secondary");
}
*pCompCode = MQCC_OK;
*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

@@ -41,7 +41,7 @@ func queueManagerHealthy() (bool, error) {
fmt.Println(err)
return false, err
}
if !strings.Contains(string(out), "(RUNNING)") && !strings.Contains(string(out), "(RUNNING AS STANDBY)") && !strings.Contains(string(out), "(STARTING)") && !strings.Contains(string(out), "(REPLICA)") {
if !strings.Contains(string(out), "(RUNNING)") && !strings.Contains(string(out), "(RUNNING AS STANDBY)") && !strings.Contains(string(out), "(STARTING)") {
return false, nil
}
return true, nil

View File

@@ -39,7 +39,7 @@ func main() {
}
// Check if the queue manager has a running listener
if active, _ := ready.IsRunningAsActiveQM(name); active {
if standby, _ := ready.IsRunningAsStandbyQM(name); !standby {
conn, err := net.Dial("tcp", "127.0.0.1:1414")
if err != nil {
fmt.Println(err)
@@ -49,13 +49,8 @@ func main() {
if err != nil {
fmt.Println(err)
}
} else if standby, _ := ready.IsRunningAsStandbyQM(name); standby {
} else {
fmt.Printf("Detected queue manager running in standby mode")
os.Exit(10)
} else if replica, _ := ready.IsRunningAsReplicaQM(name); replica {
fmt.Printf("Detected queue manager running in replica mode")
os.Exit(20)
} else {
os.Exit(1)
}
}

View File

@@ -1,58 +0,0 @@
/*
© 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.
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.
*/
// chkmqstarted checks that MQ has successfully started, by checking the output of the "dspmq" command
package main
import (
"fmt"
"os"
"os/exec"
"strings"
"github.com/ibm-messaging/mq-container/pkg/name"
)
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.Command("dspmq", "-n", "-m", name)
// Run the command and wait for completion
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(err)
return false, err
}
if !strings.Contains(string(out), "(RUNNING)") && !strings.Contains(string(out), "(RUNNING AS STANDBY)") && !strings.Contains(string(out), "(STARTING)") && !strings.Contains(string(out), "(REPLICA)") {
return false, nil
}
return true, nil
}
func main() {
started, err := queueManagerStarted()
if err != nil {
os.Exit(2)
}
if !started {
os.Exit(1)
}
os.Exit(0)
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2021
© 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.
@@ -19,6 +19,7 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"syscall"
"github.com/ibm-messaging/mq-container/internal/htpasswd"
@@ -29,6 +30,27 @@ import (
var log *logger.Logger
func setPassword(user string, password string) error {
// #nosec G204
cmd := exec.Command("sudo", "chpasswd")
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
fmt.Fprintf(stdin, "%s:%s", user, password)
err = stdin.Close()
if err != nil {
log.Errorf("Error closing password stdin: %v", err)
}
out, err := cmd.CombinedOutput()
if err != nil {
// Include the command output in the error
return fmt.Errorf("%v: %v", err.Error(), out)
}
log.Printf("Set password for \"%v\" user", user)
return nil
}
func getLogFormat() string {
return os.Getenv("LOG_FORMAT")
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2021
© 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.
@@ -79,8 +79,6 @@ func formatBasic(obj map[string]interface{}) string {
if len(inserts) > 0 {
return fmt.Sprintf("%s %s [%v]\n", obj["ibm_datetime"], obj["message"], strings.Join(inserts, ", "))
}
// Convert time zone information from some logs (e.g. Liberty) for consistency
obj["ibm_datetime"] = strings.Replace(obj["ibm_datetime"].(string), "+0000", "Z", 1)
return fmt.Sprintf("%s %s\n", obj["ibm_datetime"], obj["message"])
}
@@ -102,16 +100,6 @@ func mirrorQueueManagerErrorLogs(ctx context.Context, wg *sync.WaitGroup, name s
return mirrorLog(ctx, wg, f, fromStart, mf, true)
}
// mirrorHTPasswdLogs starts a goroutine to mirror the contents of the MQ HTPasswd authorization service's log
func mirrorHTPasswdLogs(ctx context.Context, wg *sync.WaitGroup, name string, fromStart bool, mf mirrorFunc) (chan error, error) {
return mirrorLog(ctx, wg, "/var/mqm/errors/mqhtpass.json", false, mf, true)
}
// mirrorWebServerLogs starts a goroutine to mirror the contents of the Liberty web server messages.log
func mirrorWebServerLogs(ctx context.Context, wg *sync.WaitGroup, name string, fromStart bool, mf mirrorFunc) (chan error, error) {
return mirrorLog(ctx, wg, "/var/mqm/web/installations/Installation1/servers/mqweb/logs/messages.log", false, mf, true)
}
func getDebug() bool {
debug := os.Getenv("DEBUG")
if debug == "true" || debug == "1" {
@@ -131,21 +119,14 @@ func configureLogger(name string) (mirrorFunc, error) {
return nil, err
}
return func(msg string, isQMLog bool) bool {
// Check if the message is JSON
if len(msg) > 0 && msg[0] == '{' {
obj, err := processLogMessage(msg)
if err == nil && isQMLog && filterQMLogMessage(obj) {
return false
}
if err != nil {
log.Printf("Failed to unmarshall JSON in log message - %v", msg)
} else {
fmt.Println(msg)
}
obj, err := processLogMessage(msg)
if err == nil && isQMLog && filterQMLogMessage(obj) {
return false
}
if err != nil {
log.Printf("Failed to unmarshall JSON - %v", msg)
} else {
// The log being mirrored isn't JSON, so wrap it in a simple JSON message
// MQ error logs are usually JSON, but this is useful for Liberty logs - usually expect WLP_LOGGING_MESSAGE_FORMAT=JSON to be set when mirroring Liberty logs.
fmt.Printf("{\"message\":\"%s\"}\n", msg)
fmt.Println(msg)
}
return true
}, nil
@@ -155,22 +136,16 @@ func configureLogger(name string) (mirrorFunc, error) {
return nil, err
}
return func(msg string, isQMLog bool) bool {
// Check if the message is JSON
if len(msg) > 0 && msg[0] == '{' {
// Parse the JSON message, and print a simplified version
obj, err := processLogMessage(msg)
if err == nil && isQMLog && filterQMLogMessage(obj) {
return false
}
if err != nil {
log.Printf("Failed to unmarshall JSON in log message - %v", err)
} else {
fmt.Printf(formatBasic(obj))
}
// Parse the JSON message, and print a simplified version
obj, err := processLogMessage(msg)
if err == nil && isQMLog && filterQMLogMessage(obj) {
return false
}
if err != nil {
log.Printf("Failed to unmarshall JSON - %v", err)
} else {
// The log being mirrored isn't JSON, so just print it.
// MQ error logs are usually JSON, but this is useful for Liberty logs - usually expect WLP_LOGGING_MESSAGE_FORMAT=JSON to be set when mirroring Liberty logs.
fmt.Println(msg)
fmt.Printf(formatBasic(obj))
// fmt.Printf(formatSimple(obj["ibm_datetime"].(string), obj["message"].(string)))
}
return true
}, nil

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2021
© 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.
@@ -24,7 +24,6 @@ import (
"os"
"sync"
"github.com/ibm-messaging/mq-container/internal/ha"
"github.com/ibm-messaging/mq-container/internal/metrics"
"github.com/ibm-messaging/mq-container/internal/ready"
"github.com/ibm-messaging/mq-container/internal/tls"
@@ -144,55 +143,30 @@ func doMain() error {
// Print out versioning information
logVersionInfo()
keyLabel, defaultCmsKeystore, defaultP12Truststore, err := tls.ConfigureDefaultTLSKeystores()
keyLabel, cmsKeystore, p12Truststore, err := tls.ConfigureTLSKeystores()
if err != nil {
logTermination(err)
return err
}
err = tls.ConfigureTLS(keyLabel, defaultCmsKeystore, *devFlag, log)
err = tls.ConfigureTLS(keyLabel, cmsKeystore, *devFlag, log)
if err != nil {
logTermination(err)
return err
}
err = postInit(name, keyLabel, defaultP12Truststore)
err = postInit(name, keyLabel, p12Truststore)
if err != nil {
logTermination(err)
return err
}
if os.Getenv("MQ_NATIVE_HA") == "true" {
err = ha.ConfigureNativeHA(log)
if err != nil {
logTermination(err)
return err
}
}
enableTraceCrtmqm := os.Getenv("MQ_ENABLE_TRACE_CRTMQM")
if enableTraceCrtmqm == "true" || enableTraceCrtmqm == "1" {
err = startMQTrace()
if err != nil {
logTermination(err)
return err
}
}
newQM, err := createQueueManager(name, *devFlag)
if err != nil {
logTermination(err)
return err
}
if enableTraceCrtmqm == "true" || enableTraceCrtmqm == "1" {
err = endMQTrace()
if err != nil {
logTermination(err)
return err
}
}
var wg sync.WaitGroup
defer func() {
log.Debug("Waiting for log mirroring to complete")
@@ -214,23 +188,6 @@ func doMain() error {
logTermination(err)
return err
}
if *devFlag {
_, err = mirrorHTPasswdLogs(ctx, &wg, name, newQM, mf)
if err != nil {
logTermination(err)
return err
}
}
// 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
}
}
err = updateCommandLevel()
if err != nil {
logTermination(err)

View File

@@ -27,7 +27,6 @@ import (
"github.com/ibm-messaging/mq-container/internal/command"
containerruntime "github.com/ibm-messaging/mq-container/internal/containerruntime"
"github.com/ibm-messaging/mq-container/internal/mqscredact"
"github.com/ibm-messaging/mq-container/internal/mqversion"
"github.com/ibm-messaging/mq-container/internal/ready"
)
@@ -113,13 +112,9 @@ func startQueueManager(name string) error {
out, rc, err := command.Run("strmqm", "-x", name)
if err != nil {
// 30=standby queue manager started, which is fine
// 94=native HA replica started, which is fine
if rc == 30 {
log.Printf("Started standby queue manager")
return nil
} else if rc == 94 {
log.Printf("Started replica queue manager")
return nil
}
log.Printf("Error %v starting queue manager: %v", rc, string(out))
return err
@@ -208,28 +203,9 @@ func getQueueManagerDataDir(mounts map[string]string, name string) string {
}
func getCreateQueueManagerArgs(mounts map[string]string, name string, devMode bool) []string {
mqversionBase := "9.2.1.0"
// use "UserExternal" only if we are 9.2.1.0 or above.
oaVal := "user"
mqVersionCheck, err := mqversion.Compare(mqversionBase)
if err != nil {
log.Printf("Error comparing MQ versions for oa,rc: %v", mqVersionCheck)
}
if mqVersionCheck >= 0 {
oaVal = "UserExternal"
}
//build args
args := []string{"-ii", "/etc/mqm/", "-ic", "/etc/mqm/", "-q", "-p", "1414"}
if os.Getenv("MQ_NATIVE_HA") == "true" {
args = append(args, "-lr", os.Getenv("HOSTNAME"))
}
if devMode {
args = append(args, "-oa", oaVal)
args = append(args, "-oa", "user")
}
if _, ok := mounts["/mnt/mqm-log"]; ok {
args = append(args, "-ld", "/mnt/mqm-log/log")

View File

@@ -62,31 +62,15 @@ func startWebServer(webKeystore, webkeystorePW, webTruststoreRef string) error {
}
func configureSSO(p12TrustStore tls.KeyStoreData, webKeystore string) (string, error) {
requiredEnvVars := []string{}
_, set := os.LookupEnv("MQ_ZEN_INTERNAL_ENDPOINT")
if !set {
// Ensure all required environment variables are set for SSO
requiredEnvVars = []string{
"MQ_OIDC_CLIENT_ID",
"MQ_OIDC_CLIENT_SECRET",
"MQ_OIDC_UNIQUE_USER_IDENTIFIER",
"MQ_OIDC_AUTHORIZATION_ENDPOINT",
"MQ_OIDC_TOKEN_ENDPOINT",
"MQ_OIDC_JWK_ENDPOINT",
"MQ_OIDC_ISSUER_IDENTIFIER",
}
} else {
// Ensure all required environment variables are set for Zen SSO
requiredEnvVars = []string{
"MQ_ZEN_UNIQUE_USER_IDENTIFIER",
"MQ_ZEN_INTERNAL_ENDPOINT",
"MQ_ZEN_ISSUER_IDENTIFIER",
"MQ_ZEN_AUDIENCES",
"MQ_ZEN_CONTEXT_NAME",
"MQ_ZEN_BASE_URI",
"MQ_ZEN_CONTEXT_NAMESPACE",
"IAM_URL",
}
// Ensure all required environment variables are set for SSO
requiredEnvVars := []string{
"MQ_OIDC_CLIENT_ID",
"MQ_OIDC_CLIENT_SECRET",
"MQ_OIDC_UNIQUE_USER_IDENTIFIER",
"MQ_OIDC_AUTHORIZATION_ENDPOINT",
"MQ_OIDC_TOKEN_ENDPOINT",
"MQ_OIDC_JWK_ENDPOINT",
"MQ_OIDC_ISSUER_IDENTIFIER",
}
for _, envVar := range requiredEnvVars {
if len(os.Getenv(envVar)) == 0 {

View File

@@ -1,6 +1,8 @@
###########################################################################################################################################################
# MQ_VERSION is the fully qualified MQ version number to build
MQ_VERSION ?= 9.2.3.0
MQ_VERSION ?= 9.2.0.0
MQ_LTS_VERSION ?= 9.2.0.6
###########################################################################################################################################################

View File

@@ -9,7 +9,7 @@ You need to have the following tools installed:
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.
You will also need a [Red Hat Account](https://access.redhat.com) to be able to access the Red Hat Registry.
You will also need a [Red Hat Account](https://access.redhat.com) to be able to access the Red Hat Registry.
## Building a production image
@@ -17,32 +17,19 @@ From MQ 9.2.X, the MQ container adds support for MQ Long Term Support (LTS) **pr
### MQ Continuous Delivery (CD)
This procedure works for building the MQ Continuous Delivery release, on `amd64`, `ppc64le` and `s390x` architectures.
1. Create a `downloads` directory in the root of this repository
2. Download MQ from [IBM Passport Advantage](https://www.ibm.com/software/passportadvantage/) or [IBM Fix Central](https://www.ibm.com/support/fixcentral), and place the downloaded file (for example, `IBM_MQ_9.2.3_LINUX_X86-64_NOINST.tar.gz`) in the `downloads` directory
3. Login to the Red Hat Registry: `docker login registry.redhat.io` using your Customer Portal credentials.
4. Run `make build-advancedserver`
> **Warning**: Note that from MQ 9.2.X CD, the MQ container build uses a 'No-Install' MQ Package, available under `IBM MQ V9.2.x Continuous Delivery Release components eAssembly, part no. CJ7CNML`
If you have an MQ archive file with a different file name, you can specify a particular file (which must be in the `downloads` directory). You should also specify the MQ version, so that the resulting image is tagged correctly, for example:
```bash
MQ_ARCHIVE=mq-1.2.3.4.tar.gz MQ_VERSION=1.2.3.4 make build-advancedserver
```
Note: To build the latest Continuous Delivery (CD) version, follow the latest build [instructions](/../master/docs/building.md#building-a-production-image).
### MQ Long Term Support (LTS)
This procedure works for building the MQ Long Term Support release, on `amd64`, `ppc64le` and `s390x` architectures.
Note: 9.2.0.X is no longer the latest LTS release; MQ 9.3 is the latest MQ version with MQ Long Term Support (LTS). To build MQ 9.3, follow the building [instructions](/../master/docs/building.md#building-a-production-image) for MQ 9.3.
However, if you wish to build the previous 9.2.0.X MQ LTS, follow the procedure below for `amd64` and `s390x` architectures.
1. Create a `downloads` directory in the root of this repository
2. Download MQ from [IBM Passport Advantage](https://www.ibm.com/software/passportadvantage/) or [IBM Fix Central](https://www.ibm.com/support/fixcentral), and place the downloaded file (for example, `9.2.0.1-IBM-MQ-Advanced-Non-Install-LinuxX86.tar.gz`) in the `downloads` directory
3. Login to the Red Hat Registry: `docker login registry.redhat.io` using your Customer Portal credentials.
2. Download MQ from [IBM Passport Advantage](https://www.ibm.com/software/passportadvantage/). Identify the correct 'Long Term Support for containers' eImage part number for your architecture from the appropriate 9.2.0.X LTS tab at https://www.ibm.com/support/pages/downloading-ibm-mq-92.
3. Ensure the `tar.gz` file is in the `downloads` directory
4. Run `LTS=true make build-advancedserver`
> **Warning**: Note that from MQ 9.2 LTS, the MQ container build uses a 'No-Install' MQ Package, available under `IBM MQ V9.2 Long Term Support Release components eAssembly, part no. CXXXXXX`
If you have an MQ archive file with a different file name, you can specify a particular file (which must be in the `downloads` directory). You should also specify the MQ version, so that the resulting image is tagged correctly, for example:
```bash

View File

@@ -11,7 +11,6 @@ The resulting Docker image contains the following:
- `runmqdevserver` - The main process for MQ Advanced for Developers
- `chkmqhealthy` - Checks the health of the queue manager. This can be used by (say) a Kubernetes liveness probe.
- `chkmqready` - Checks if the queue manager is ready for work. This can be used by (say) a Kubernetes readiness probe.
- `chkmqstarted` - Checks if the queue manager has successfully started. This can be used by (say) a Kubernetes startup probe.
## runmqserver
The `runmqserver` command has the following responsibilities:

View File

@@ -24,6 +24,6 @@ Use an administrative tool or your application to connect to queue manager using
#### Troubleshooting
A log file named `mqhtpass.log` is generated under `/var/mqm/errors` directory path of the container. This file will contain all the failed connection authentication requests. Additional information is logged to this file if the environment variable `DEBUG` is set to `true`.
A log file named `amqpasdev.log` is generated under `/var/mqm/errors` directory path of the container. This file will contain all the failed connection authentication requests.
**Please note**: This log file will be wiped when the queue manager is next started.
**Please note**: This log file is based on circular logging and the maximum size is restricted to 1MB.

View File

@@ -16,5 +16,20 @@ docker run \
--env LICENSE=accept \
--env MQ_QMGR_NAME=QM1 \
--detach \
ibm-mqadvanced-server:9.2.3.0-amd64
ibm-mqadvanced-server:9.2.0.6-amd64
```
The MQ Advanced for Developers image does require the "chown", "setuid", "setgid" and "audit_write" capabilities (plus "dac_override" if you're using an image based on Red Hat Enterprise Linux). This is because it uses the "sudo" command to change passwords inside the container. For example, in Docker, you could do the following:
```sh
docker run \
--cap-drop=ALL \
--cap-add=CHOWN \
--cap-add=SETUID \
--cap-add=SETGID \
--cap-add=AUDIT_WRITE \
--env LICENSE=accept \
--env MQ_QMGR_NAME=QM1 \
--detach \
ibm-mqadvanced-server-dev:9.2.0.6-amd64
```

View File

@@ -14,7 +14,7 @@ There are two main sets of tests:
2. Docker tests, which test a complete Docker image, using the Docker API
### Running the Docker tests
The Docker tests can be run locally on a machine with Docker. For example:
```
@@ -25,7 +25,7 @@ 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.2.3.0-amd64 make test-advancedserver
MQ_IMAGE_ADVANCEDSERVER=ibm-mqadvanced-server:9.2.0.6-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

@@ -60,7 +60,7 @@ You can customize the configuration in several ways:
1. For getting started, you can use the [default developer configuration](developer-config.md), which is available out-of-the-box for the MQ Advanced for Developers image
2. By creating your own image and adding your own MQSC file into the `/etc/mqm` directory on the image. This file will be run when your queue manager is created.
3. By using [remote MQ administration](https://www.ibm.com/support/knowledgecenter/SSFKSJ_9.2.0/com.ibm.mq.adm.doc/q021090_.htm), via an MQ command server, the MQ HTTP APIs, or using a tool such as the MQ web console or MQ Explorer.
3. By using [remote MQ administration](https://www.ibm.com/docs/en/ibm-mq/9.2?topic=administering-working-remote-mq-objects), via an MQ command server, the MQ HTTP APIs, or using a tool such as the MQ web console or MQ Explorer.
Note that a listener is always created on port 1414 inside the container. This port can be mapped to any port on the Docker host.

View File

@@ -1,7 +1,7 @@
ServiceComponent:
Service=AuthorizationService
Name=Dev.HtpAuth.Service
Module=/opt/mqm/lib64/mqhtpass.so
Module=/opt/mqm/lib64/amqpasdev.so
ComponentDataSize=0
ServiceComponent:
Service=AuthorizationService

5
go.mod
View File

@@ -4,14 +4,13 @@ go 1.15
require (
github.com/genuinetools/amicontained v0.4.0
github.com/genuinetools/pkg v0.0.0-20181022210355-2fcf164d37cb // indirect
github.com/ibm-messaging/mq-golang v2.0.0+incompatible
github.com/prometheus/client_golang v1.7.1
github.com/prometheus/client_model v0.2.0
github.com/prometheus/common v0.14.0 // indirect
github.com/prometheus/procfs v0.2.0 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1
software.sslmate.com/src/go-pkcs12 v0.0.0-20200830195227-52f69702a001
)

32
go.sum
View File

@@ -56,11 +56,6 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/genuinetools/amicontained v0.4.0 h1:J70LMWTebQqQJQaQx9uAW82A6QQqe5ux9GMFgo3NAGY=
github.com/genuinetools/amicontained v0.4.0/go.mod h1:PAMZkg9CcUTa6gNyULQ6tOMTMEb2HTKJufvKeFqDw+o=
github.com/genuinetools/amicontained v0.4.3 h1:cqq9XiAHfWWY3dk8VU8bSJFu9yh8Il5coEdeTAPq72o=
github.com/genuinetools/amicontained v0.4.3/go.mod h1:PAMZkg9CcUTa6gNyULQ6tOMTMEb2HTKJufvKeFqDw+o=
github.com/genuinetools/amicontained v0.4.9 h1:/LvLdgD7iO3IPk7neqfcwB7ufoH7tG77u1pERXBIj7w=
github.com/genuinetools/pkg v0.0.0-20181022210355-2fcf164d37cb h1:9MQ4N7zyYTtdjLGqE5McDbgjIjqR5TAPc6lytEOdndc=
github.com/genuinetools/pkg v0.0.0-20181022210355-2fcf164d37cb/go.mod h1:XTcrCYlXPxnxL2UpnwuRn7tcaTn9HAhxFoFJucootk8=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
@@ -78,7 +73,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -130,15 +124,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/ibm-messaging/mq-golang v1.0.0 h1:NZHBQlJzAuNsVv09sooYgxBWPvRUX4L6wZIuOSumiKE=
github.com/ibm-messaging/mq-golang v2.0.0+incompatible h1:xAufRPYSzoRGaME2+x7LcW5+uvy/G3xL/3Sn3u+G/lY=
github.com/ibm-messaging/mq-golang v2.0.0+incompatible/go.mod h1:qjsZDb7m1oKnbPeDma2JVJTKgyCA91I4bcJ1qHY+gcA=
github.com/ibm-messaging/mq-golang v3.0.0+incompatible h1:Yc3c8emAyveT54uNDRMkgvS+EBAHeLNWHkc3hk5x+IY=
github.com/ibm-messaging/mq-golang v3.0.0+incompatible/go.mod h1:qjsZDb7m1oKnbPeDma2JVJTKgyCA91I4bcJ1qHY+gcA=
github.com/ibm-messaging/mq-golang/v5 v5.0.0-alpha h1:Bw2c+k+o9VTMXpiVBmX6PKOm/vPuihx6dO2knPAhkKc=
github.com/ibm-messaging/mq-golang/v5 v5.0.0-alpha/go.mod h1:ywCwmYbJOU/E0rl+z4GiNoxVMty68O+LVO39a1VMXrE=
github.com/ibm-messaging/mq-golang/v5 v5.1.2 h1:u0e1Vce2TNqJpH088vF77rDMsnMRWnGaOIlxZo4DMZc=
github.com/ibm-messaging/mq-golang/v5 v5.1.2/go.mod h1:ywCwmYbJOU/E0rl+z4GiNoxVMty68O+LVO39a1VMXrE=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -153,7 +140,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -217,8 +203,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@@ -235,7 +219,6 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4=
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
@@ -243,7 +226,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
@@ -256,7 +238,6 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -298,8 +279,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae h1:duLSQW+DZ5MsXKX7kc4rXlq6/mmxz4G6ewJuBPlhRe0=
golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -325,6 +306,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -352,10 +334,14 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -1,18 +0,0 @@
NativeHALocalInstance:
Name={{ .Name }}
{{ if .CertificateLabel }}
CertificateLabel={{ .CertificateLabel }}
KeyRepository={{ .KeyRepository }}
{{ if .CipherSpec }}
CipherSpec={{ .CipherSpec }}
{{- end }}
{{- end }}
NativeHAInstance:
Name={{ .NativeHAInstance0_Name }}
ReplicationAddress={{ .NativeHAInstance0_ReplicationAddress }}
NativeHAInstance:
Name={{ .NativeHAInstance1_Name }}
ReplicationAddress={{ .NativeHAInstance1_ReplicationAddress }}
NativeHAInstance:
Name={{ .NativeHAInstance2_Name }}
ReplicationAddress={{ .NativeHAInstance2_ReplicationAddress }}

View File

@@ -1,6 +1,6 @@
#!/bin/bash
# -*- mode: sh -*-
# © Copyright IBM Corporation 2019, 2021
# © Copyright IBM Corporation 2019
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,17 +25,17 @@ test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false
if ($UBUNTU); then
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y --no-install-recommends libaprutil1
apt-get install -y --no-install-recommends sudo
rm -rf /var/lib/apt/lists/*
fi
if ($YUM); then
yum -y install apr-util-openssl
yum -y install sudo
yum -y clean all
rm -rf /var/cache/yum/*
fi
if ($MICRODNF); then
microdnf --disableplugin=subscription-manager install apr-util-openssl
microdnf --disableplugin=subscription-manager clean all
microdnf install sudo
microdnf clean all
fi

View File

@@ -36,8 +36,5 @@
</basicRegistry>
<variable name="httpHost" value="*"/>
<variable name="managementMode" value="externallyprovisioned"/>
<variable name="mqConsoleEnableUnsafeInline" value="true"/>
<jndiEntry jndiName="mqConsoleDefaultCCDTHostname" value="${env.MQ_CONSOLE_DEFAULT_CCDT_HOSTNAME}"/>
<jndiEntry jndiName="mqConsoleDefaultCCDTPort" value="${env.MQ_CONSOLE_DEFAULT_CCDT_PORT}"/>
<include location="tls.xml"/>
</server>

View File

@@ -21,6 +21,11 @@ set -ex
sudo curl -Lo /usr/local/bin/dep https://github.com/golang/dep/releases/download/v0.5.1/dep-linux-$ARCH
sudo chmod +x /usr/local/bin/dep
sudo apt-get update || :
sudo apt-get install -y jq
go get -u golang.org/x/lint/golint
(
cd "$(mktemp -d)"
go get -u golang.org/x/lint/golint
)
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $GOPATH/bin 2.0.0 || echo "Gosec not installed. Platform may not be supported."

View File

@@ -1,6 +1,6 @@
#!/bin/bash
# -*- mode: sh -*-
# © Copyright IBM Corporation 2015, 2021
# © Copyright IBM Corporation 2015, 2020
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -66,7 +66,7 @@ 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"
# 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}
$MICRODNF && microdnf install ${EXTRA_RPMS}
fi
# Apply any bug fixes not included in base Ubuntu or MQ image.
@@ -78,4 +78,4 @@ $UBUNTU && apt-get install -y libapparmor1 libsystemd0 systemd systemd-sysv libu
$UBUNTU && rm -rf /var/lib/apt/lists/*
$YUM && yum -y clean all
$YUM && rm -rf /var/cache/yum/*
$MICRODNF && microdnf --disableplugin=subscription-manager clean all
$MICRODNF && microdnf clean all

View File

@@ -1,68 +0,0 @@
/*
© 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.
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 ha contains code for high availability
package ha
import (
"os"
"github.com/ibm-messaging/mq-container/internal/mqtemplate"
"github.com/ibm-messaging/mq-container/internal/tls"
"github.com/ibm-messaging/mq-container/pkg/logger"
)
// ConfigureNativeHA configures native high availability
func ConfigureNativeHA(log *logger.Logger) error {
file := "/etc/mqm/native-ha.ini"
templateFile := file + ".tpl"
templateMap := map[string]string{}
templateMap["Name"] = os.Getenv("HOSTNAME")
templateMap["NativeHAInstance0_Name"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_0_NAME")
templateMap["NativeHAInstance1_Name"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_1_NAME")
templateMap["NativeHAInstance2_Name"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_2_NAME")
templateMap["NativeHAInstance0_ReplicationAddress"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS")
templateMap["NativeHAInstance1_ReplicationAddress"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS")
templateMap["NativeHAInstance2_ReplicationAddress"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS")
if os.Getenv("MQ_NATIVE_HA_TLS") == "true" {
keyLabel, _, _, err := tls.ConfigureHATLSKeystore()
if err != nil {
return err
}
templateMap["CertificateLabel"] = keyLabel
keyRepository, ok := os.LookupEnv("MQ_NATIVE_HA_KEY_REPOSITORY")
if !ok {
keyRepository = "/run/runmqserver/ha/tls/key"
}
templateMap["KeyRepository"] = keyRepository
cipherSpec, ok := os.LookupEnv("MQ_NATIVE_HA_CIPHERSPEC")
if ok {
templateMap["CipherSpec"] = cipherSpec
}
}
err := mqtemplate.ProcessTemplateFile(templateFile, file, templateMap, log)
if err != nil {
return err
}
return nil
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2020, 2021
© 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.
@@ -110,3 +110,44 @@ func (htpfile mapHtPasswd) updateHtPasswordFile(isTest bool) error {
}
return ioutil.WriteFile(file, htpfile.GetBytes(), 0660)
}
// AuthenticateUser verifies if the given user password match with htpasswrd
func AuthenticateUser(user string, password string, isTest bool) (bool, bool, error) {
passwords := mapHtPasswd(map[string]string{})
if len(strings.TrimSpace(user)) == 0 || len(strings.TrimSpace(password)) == 0 {
return false, false, fmt.Errorf("UserId or Password are empty")
}
err := passwords.ReadHtPasswordFile(isTest)
if err != nil {
return false, false, err
}
ok := false
value, found := passwords[user]
if !found {
return found, ok, fmt.Errorf("User not found in the mq.htpasswd file")
}
err = bcrypt.CompareHashAndPassword([]byte(value), []byte(password))
return found, err == nil, err
}
// ValidateUser validates the given user
func ValidateUser(user string, isTest bool) (bool, error) {
passwords := mapHtPasswd(map[string]string{})
if len(strings.TrimSpace(user)) == 0 {
return false, fmt.Errorf("Userid is empty for AuthenticateUser")
}
err := passwords.ReadHtPasswordFile(isTest)
if err != nil {
return false, err
}
_, found := passwords[strings.TrimSpace(user)]
return found, nil
}

View File

@@ -0,0 +1,62 @@
/*
© 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.
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 htpasswd
import (
"testing"
)
// TestCheckUser verifies Htpassword's use
func TestCheckUser(t *testing.T) {
err := SetPassword("guest", "guestpw", true)
if err != nil {
t.Fatalf("htpassword test failed due to error:%s\n", err.Error())
}
found, ok, err := AuthenticateUser("guest", "guestpw", true)
if err != nil {
t.Fatalf("htpassword test1 failed as user could not be found:%s\n", err.Error())
}
if found == false || ok == false {
t.Fatalf("htpassword test1 failed as user could not be found:%v, ok:%v\n", found, ok)
}
found, ok, err = AuthenticateUser("myguest", "guestpw", true)
if err == nil {
t.Fatalf("htpassword test2 failed as no error received for non-existing user\n")
}
if found == true || ok == true {
t.Fatalf("htpassword test2 failed for non-existing user found :%v, ok:%v\n", found, ok)
}
found, ok, err = AuthenticateUser("guest", "guest", true)
if err == nil {
t.Fatalf("htpassword test3 failed as incorrect password of user did not return error\n")
}
if found == false || ok == true {
t.Fatalf("htpassword test3 failed for existing user with incorrect passwored found :%v, ok:%v\n", found, ok)
}
found, err = ValidateUser("guest", true)
if err != nil || found == false {
t.Fatalf("htpassword test4 failed as user could not be found:%v, ok:%v\n", found, ok)
}
found, err = ValidateUser("myguest", true)
if err != nil || found == true {
t.Fatalf("htpassword test5 failed as non-existing user returned to be found:%v, ok:%v\n", found, ok)
}
}

View File

@@ -0,0 +1 @@
guest:$2y$05$ifFP0nCmFed6.m4iB9CHRuHFps2YeeuwopmOvszWt0GRnN59p8qxW

299
internal/qmgrauth/pas.go Normal file
View File

@@ -0,0 +1,299 @@
/*
© 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.
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.
*/
//This is a developer only configuration and not recommended for production usage.
package main
/*
#cgo !windows CFLAGS: -I/opt/mqm/lib64 -D_REENTRANT
#cgo !windows,!darwin LDFLAGS: -L/opt/mqm/lib64 -lmqm_r -Wl,-rpath,/opt/mqm/lib64 -Wl,-rpath,/usr/lib64
#cgo darwin LDFLAGS: -L/opt/mqm/lib64 -lmqm_r -Wl,-rpath,/opt/mqm/lib64 -Wl,-rpath,/usr/lib64
#cgo windows CFLAGS: -I"C:/Program Files/IBM/MQ/Tools/c/include"
#cgo windows LDFLAGS: -L "C:/Program Files/IBM/MQ/bin64" -lmqm
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmqc.h>
#include <cmqxc.h>
#include <cmqzc.h>
#include <cmqec.h>
#include <time.h>
static MQZ_INIT_AUTHORITY PASStart;
static MQZ_AUTHENTICATE_USER OAAuthUser;
static MQZ_FREE_USER OAFreeUser;
static MQZ_TERM_AUTHORITY OATermAuth;
extern int Authenticate(char *, char *);
extern int CheckAuthority(char *);
static char *OAEnvStr(MQLONG);
static void FindSize();
static void PrintDateTime();
static FILE *fp = NULL;
static int primary_process = 0;
static void MQENTRY PASStart(
MQHCONFIG hc,
MQLONG Options,
MQCHAR48 QMgrName,
MQLONG ComponentDataLength,
PMQBYTE ComponentData,
PMQLONG Version,
PMQLONG pCompCode,
PMQLONG pReason) {
MQLONG CC = MQCC_OK;
MQLONG Reason = MQRC_NONE;
if ((Options & MQZIO_PRIMARY) == MQZIO_PRIMARY)
primary_process = 1;
fp=fopen("/var/mqm/errors/amqpasdev.log","a");
if (CC == MQCC_OK)
hc->MQZEP_Call(hc, MQZID_INIT_AUTHORITY,(PMQFUNC)PASStart,&CC,&Reason);
if (CC == MQCC_OK)
hc->MQZEP_Call(hc,MQZID_TERM_AUTHORITY,(PMQFUNC)OATermAuth,&CC,&Reason);
if (CC == MQCC_OK)
hc->MQZEP_Call(hc,MQZID_AUTHENTICATE_USER,(PMQFUNC)OAAuthUser,&CC,&Reason);
if (CC == MQCC_OK)
hc->MQZEP_Call(hc,MQZID_FREE_USER,(PMQFUNC)OAFreeUser,&CC,&Reason);
*Version = MQZAS_VERSION_5;
*pCompCode = CC;
*pReason = Reason;
PrintDateTime();
fprintf(fp, "Pluggable OAM Initialized.\n");
fprintf(fp, "THIS IS A DEVELOPER ONLY CONFIGURATION AND NOT RECOMMENDED FOR PRODUCTION USAGE");
return;
}
static char *authuserfmt =
"\tUser : \"%12.12s\"\n"\
"\tEffUser : \"%12.12s\"\n"\
"\tAppName : \"%28.28s\"\n"\
"\tApIdDt : \"%32.32s\"\n"\
"\tEnv : \"%s\"\n"\
"\tApp Pid : %d\n"\
"\tApp Tid : %d\n"\
;
static void MQENTRY OAAuthUser (
PMQCHAR pQMgrName,
PMQCSP pSecurityParms,
PMQZAC pApplicationContext,
PMQZIC pIdentityContext,
PMQPTR pCorrelationPtr,
PMQBYTE pComponentData,
PMQLONG pContinuation,
PMQLONG pCompCode,
PMQLONG pReason)
{
char *spuser = NULL;
char *sppass = NULL;
int gorc = MQRC_NOT_AUTHORIZED;
if ((pSecurityParms->CSPUserIdLength) > 0) {
//Grab the user creds from csp.
spuser = malloc(pSecurityParms->CSPUserIdLength+1);
strncpy(spuser,pSecurityParms->CSPUserIdPtr,pSecurityParms->CSPUserIdLength);
spuser[pSecurityParms->CSPUserIdLength]=0;
sppass = malloc(pSecurityParms->CSPPasswordLength+1);
strncpy(sppass,pSecurityParms->CSPPasswordPtr,pSecurityParms->CSPPasswordLength);
sppass[pSecurityParms->CSPPasswordLength]=0;
gorc = Authenticate(spuser,sppass);
if (gorc == MQRC_NONE) {
*pCompCode = MQCC_OK;
*pReason = MQRC_NONE;
*pContinuation = MQZCI_CONTINUE;
memcpy( pIdentityContext->UserIdentifier
, spuser
, sizeof(pIdentityContext->UserIdentifier) );
} else {
*pCompCode = MQCC_WARNING;
*pReason = MQRC_NONE;
*pContinuation = MQZCI_CONTINUE;
//we print to error file only if error'd
PrintDateTime();
if (fp) {
fprintf(fp, authuserfmt,
pIdentityContext->UserIdentifier,
pApplicationContext->EffectiveUserID,
pApplicationContext->ApplName,
pIdentityContext->ApplIdentityData,
OAEnvStr(pApplicationContext->Environment),
pApplicationContext->ProcessId,
pApplicationContext->ThreadId);
fprintf(fp,"\tCSP UserId : %s\n", spuser);
fprintf(fp,"\tCSP Password : %s\n", "****..");
fprintf(fp,"\tPAS-Compcode:%d\n",*pCompCode);
fprintf(fp,"\tPAS-Reasoncode:%d\n",*pReason);
}
}
free(spuser);
free(sppass);
} else {
//this is only a normal UID authentication.
spuser = malloc(sizeof(PMQCHAR12));
strncpy(spuser,pApplicationContext->EffectiveUserID,strlen(pApplicationContext->EffectiveUserID));
spuser[sizeof(PMQCHAR12)]=0;
gorc = CheckAuthority(spuser);
if (gorc == MQRC_NONE){
*pCompCode = MQCC_OK;
*pReason = MQRC_NONE;
*pContinuation = MQZCI_CONTINUE;
memcpy( pIdentityContext->UserIdentifier
, spuser
, sizeof(pIdentityContext->UserIdentifier) );
} else {
*pCompCode = MQCC_WARNING;
*pReason = MQRC_NONE;
*pContinuation = MQZCI_CONTINUE;
//we print only if error'd
PrintDateTime();
if (fp)
{
fprintf(fp, authuserfmt,
pIdentityContext->UserIdentifier,
pApplicationContext->EffectiveUserID,
pApplicationContext->ApplName,
pIdentityContext->ApplIdentityData,
OAEnvStr(pApplicationContext->Environment),
pApplicationContext->ProcessId,
pApplicationContext->ThreadId
);
fprintf(fp,"\tUID : %s\n", spuser);
fprintf(fp,"\tPAS-Compcode:%d\n",*pCompCode);
fprintf(fp,"\tPAS-Reasoncode:%d\n",*pReason);
}
}
}
return;
}
static void MQENTRY OAFreeUser (
PMQCHAR pQMgrName,
PMQZFP pFreeParms,
PMQBYTE pComponentData,
PMQLONG pContinuation,
PMQLONG pCompCode,
PMQLONG pReason)
{
*pCompCode = MQCC_WARNING;
*pReason = MQRC_NONE;
*pContinuation = MQZCI_CONTINUE;
return;
}
static void MQENTRY OATermAuth(
MQHCONFIG hc,
MQLONG Options,
PMQCHAR pQMgrName,
PMQBYTE pComponentData,
PMQLONG pCompCode,
PMQLONG pReason)
{
if ((primary_process) && ((Options & MQZTO_PRIMARY) == MQZTO_PRIMARY) ||
((Options & MQZTO_SECONDARY) == MQZTO_SECONDARY))
{
if (fp)
{
fclose(fp);
fp = NULL;
}
}
*pCompCode = MQCC_OK;
*pReason = MQRC_NONE;
}
static void PrintDateTime() {
FindSize();
struct tm *local;
time_t t;
t = time(NULL);
local = localtime(&t);
if (fp) {
fprintf(fp, "-------------------------------------------------\n");
fprintf(fp, "Local time: %s", asctime(local));
local = gmtime(&t);
fprintf(fp, "UTC time: %s", asctime(local));
}
return;
}
static char *OAEnvStr(MQLONG x)
{
switch (x)
{
case MQXE_OTHER: return "Application";
case MQXE_MCA: return "Channel";
case MQXE_MCA_SVRCONN: return "Channel SvrConn";
case MQXE_COMMAND_SERVER: return "Command Server";
case MQXE_MQSC: return "MQSC";
default: return "Invalid Environment";
}
}
static void FindSize()
{
int sz = 0;
int prev=ftell(fp);
fseek(fp, 0L, SEEK_END);
sz=ftell(fp);
//if log file size goes over 1mb, rewind it.
if (sz > 1000000) {
rewind(fp);
} else {
fseek(fp, prev, SEEK_SET);
}
}
*/
import "C"
import "github.com/ibm-messaging/mq-container/internal/htpasswd"
//export MQStart
func MQStart(hc C.MQHCONFIG, Options C.MQLONG, QMgrName C.PMQCHAR, ComponentDataLength C.MQLONG, ComponentData C.PMQBYTE, Version C.PMQLONG, pCompCode C.PMQLONG, pReason C.PMQLONG) {
C.PASStart(hc, Options, QMgrName, ComponentDataLength, ComponentData, Version, pCompCode, pReason)
}
//export Authenticate
func Authenticate(x *C.char, y *C.char) C.int {
user := C.GoString(x)
pwd := C.GoString(y)
found, ok, err := htpasswd.AuthenticateUser(user, pwd, false)
if !found || !ok || err != nil {
return C.MQRC_UNKNOWN_OBJECT_NAME
}
return C.MQRC_NONE
}
//export CheckAuthority
func CheckAuthority(x *C.char) C.int {
user := C.GoString(x)
found, err := htpasswd.ValidateUser(user, false)
if !found || err != nil {
return C.MQRC_UNKNOWN_OBJECT_NAME
}
return C.MQRC_NONE
}
func main() {}

View File

@@ -76,11 +76,6 @@ func IsRunningAsStandbyQM(name string) (bool, error) {
return isRunningQM(name, "(RUNNING AS STANDBY)")
}
// IsRunningAsReplicaQM returns true if the queue manager is running in replica mode
func IsRunningAsReplicaQM(name string) (bool, error) {
return isRunningQM(name, "(REPLICA)")
}
func isRunningQM(name string, status string) (bool, error) {
out, _, err := command.Run("dspmq", "-n", "-m", name)
if err != nil {

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2019, 2021
© 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.
@@ -43,20 +43,14 @@ const cmsKeystoreName = "key.kdb"
// p12TruststoreName is the name of the PKCS#12 Truststore
const p12TruststoreName = "trust.p12"
// keystoreDirDefault is the location for the default CMS Keystore & PKCS#12 Truststore
const keystoreDirDefault = "/run/runmqserver/tls/"
// keystoreDir is the location for the CMS Keystore & PKCS#12 Truststore
const keystoreDir = "/run/runmqserver/tls/"
// keystoreDirHA is the location for the HA CMS Keystore
const keystoreDirHA = "/run/runmqserver/ha/tls/"
// keyDir is the location of the keys to import
const keyDir = "/etc/mqm/pki/keys"
// keyDirDefault is the location of the default keys to import
const keyDirDefault = "/etc/mqm/pki/keys"
// keyDirHA is the location of the HA keys to import
const keyDirHA = "/etc/mqm/ha/pki/keys"
// trustDirDefault is the location of the trust certificates to import
const trustDirDefault = "/etc/mqm/pki/trust"
// trustDir is the location of the trust certificates to import
const trustDir = "/etc/mqm/pki/trust"
type KeyStoreData struct {
Keystore *keystore.KeyStore
@@ -71,43 +65,28 @@ type P12KeyFiles struct {
Password string
}
type TLSStore struct {
Keystore KeyStoreData
Truststore KeyStoreData
}
// ConfigureTLSKeystores configures the CMS Keystore & PKCS#12 Truststore
func ConfigureTLSKeystores() (string, KeyStoreData, KeyStoreData, error) {
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)
// Create the CMS Keystore & PKCS#12 Truststore
cmsKeystore, p12Truststore, err := generateAllKeystores()
if err != nil {
return "", tlsStore.Keystore, tlsStore.Truststore, err
return "", cmsKeystore, p12Truststore, err
}
// Process all keys - add them to the CMS KeyStore
keyLabel, err := processKeys(&tlsStore, keystoreDir, keyDir)
keyLabel, err := processKeys(&cmsKeystore, &p12Truststore)
if err != nil {
return "", tlsStore.Keystore, tlsStore.Truststore, err
return "", cmsKeystore, p12Truststore, err
}
// Process all trust certificates - add them to the CMS KeyStore & PKCS#12 Truststore (if required)
err = processTrustCertificates(&tlsStore, trustDir)
// Process all trust certificates - add them to the CMS KeyStore & PKCS#12 Truststore
err = processTrustCertificates(&cmsKeystore, &p12Truststore)
if err != nil {
return "", tlsStore.Keystore, tlsStore.Truststore, err
return "", cmsKeystore, p12Truststore, err
}
return keyLabel, tlsStore.Keystore, tlsStore.Truststore, err
}
// ConfigureDefaultTLSKeystores configures the CMS Keystore & PKCS#12 Truststore
func ConfigureDefaultTLSKeystores() (string, KeyStoreData, KeyStoreData, error) {
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)
return keyLabel, cmsKeystore, p12Truststore, err
}
// ConfigureTLS configures TLS for the queue manager
@@ -158,9 +137,8 @@ func configureTLSDev(log *logger.Logger) error {
return nil
}
// generateAllKeystores creates the CMS Keystore & PKCS#12 Truststore (if required)
func generateAllKeystores(keystoreDir string, p12TruststoreRequired bool) (TLSStore, error) {
// generateAllKeystores creates the CMS Keystore & PKCS#12 Truststore
func generateAllKeystores() (KeyStoreData, KeyStoreData, error) {
var cmsKeystore, p12Truststore KeyStoreData
// Generate a pasword for use with both the CMS Keystore & PKCS#12 Truststore
@@ -172,30 +150,28 @@ func generateAllKeystores(keystoreDir string, p12TruststoreRequired bool) (TLSSt
// #nosec G301 - write group permissions are required
err := os.MkdirAll(keystoreDir, 0770)
if err != nil {
return TLSStore{cmsKeystore, p12Truststore}, fmt.Errorf("Failed to create Keystore directory: %v", err)
return cmsKeystore, p12Truststore, fmt.Errorf("Failed to create Keystore directory: %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)
return cmsKeystore, p12Truststore, fmt.Errorf("Failed to create CMS Keystore: %v", err)
}
// Create the PKCS#12 Truststore (if required)
if p12TruststoreRequired {
p12Truststore.Keystore = keystore.NewPKCS12KeyStore(filepath.Join(keystoreDir, p12TruststoreName), p12Truststore.Password)
err = p12Truststore.Keystore.Create()
if err != nil {
return TLSStore{cmsKeystore, p12Truststore}, fmt.Errorf("Failed to create PKCS#12 Truststore: %v", err)
}
// Create the PKCS#12 Truststore
p12Truststore.Keystore = keystore.NewPKCS12KeyStore(filepath.Join(keystoreDir, p12TruststoreName), p12Truststore.Password)
err = p12Truststore.Keystore.Create()
if err != nil {
return cmsKeystore, p12Truststore, fmt.Errorf("Failed to create PKCS#12 Truststore: %v", err)
}
return TLSStore{cmsKeystore, p12Truststore}, nil
return cmsKeystore, p12Truststore, nil
}
// processKeys processes all keys - adding them to the CMS KeyStore
func processKeys(tlsStore *TLSStore, keystoreDir string, keyDir string) (string, error) {
func processKeys(cmsKeystore, p12Truststore *KeyStoreData) (string, error) {
// Key label - will be set to the label of the first set of keys
keyLabel := ""
@@ -214,7 +190,7 @@ func processKeys(tlsStore *TLSStore, keystoreDir string, keyDir string) (string,
}
// Process private key (*.key)
privateKey, keyPrefix, err := processPrivateKey(keyDir, keySet.Name(), keys)
privateKey, keyPrefix, err := processPrivateKey(keySet.Name(), keys)
if err != nil {
return "", err
}
@@ -225,13 +201,13 @@ func processKeys(tlsStore *TLSStore, keystoreDir string, keyDir string) (string,
}
// Process certificates (*.crt) - public certificate & optional CA certificate
publicCertificate, caCertificate, err := processCertificates(keyDir, keySet.Name(), keyPrefix, keys, &tlsStore.Keystore, &tlsStore.Truststore)
publicCertificate, caCertificate, err := processCertificates(keySet.Name(), keyPrefix, keys, cmsKeystore, p12Truststore)
if err != nil {
return "", err
}
// 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)
file, err := pkcs.Encode(rand.Reader, privateKey, publicCertificate, caCertificate, cmsKeystore.Password)
if err != nil {
return "", fmt.Errorf("Failed to encode PKCS#12 Keystore %s: %v", keySet.Name()+".p12", err)
}
@@ -241,13 +217,13 @@ func processKeys(tlsStore *TLSStore, keystoreDir string, keyDir string) (string,
}
// Import the new PKCS#12 Keystore into the CMS Keystore
err = tlsStore.Keystore.Keystore.Import(filepath.Join(keystoreDir, keySet.Name()+".p12"), tlsStore.Keystore.Password)
err = cmsKeystore.Keystore.Import(filepath.Join(keystoreDir, keySet.Name()+".p12"), cmsKeystore.Password)
if err != nil {
return "", fmt.Errorf("Failed to import keys from %s into CMS Keystore: %v", filepath.Join(keystoreDir, keySet.Name()+".p12"), err)
return "", fmt.Errorf("Failed tp import keys from %s into CMS Keystore: %v", filepath.Join(keystoreDir, keySet.Name()+".p12"), err)
}
// Relabel the certificate in the CMS Keystore
err = relabelCertificate(keySet.Name(), &tlsStore.Keystore)
err = relabelCertificate(keySet.Name(), cmsKeystore)
if err != nil {
return "", err
}
@@ -262,8 +238,8 @@ func processKeys(tlsStore *TLSStore, keystoreDir string, keyDir string) (string,
return keyLabel, nil
}
// processTrustCertificates processes all trust certificates - adding them to the CMS KeyStore & PKCS#12 Truststore (if required)
func processTrustCertificates(tlsStore *TLSStore, trustDir string) error {
// processTrustCertificates processes all trust certificates - adding them to the CMS KeyStore & PKCS#12 Truststore
func processTrustCertificates(cmsKeystore, p12Truststore *KeyStoreData) error {
// Process all trust certiifcates
trustList, err := ioutil.ReadDir(trustDir)
@@ -289,17 +265,15 @@ func processTrustCertificates(tlsStore *TLSStore, trustDir string) error {
}
// Add to known certificates for the CMS Keystore
err = addToKnownCertificates(block, &tlsStore.Keystore, true)
err = addToKnownCertificates(block, cmsKeystore, true)
if err != nil {
return fmt.Errorf("Failed to add to know certificates for CMS Keystore")
}
if tlsStore.Truststore.Keystore != nil {
// Add to known certificates for the PKCS#12 Truststore
err = addToKnownCertificates(block, &tlsStore.Truststore, true)
if err != nil {
return fmt.Errorf("Failed to add to know certificates for PKCS#12 Truststore")
}
// Add to known certificates for the PKCS#12 Truststore
err = addToKnownCertificates(block, p12Truststore, true)
if err != nil {
return fmt.Errorf("Failed to add to know certificates for PKCS#12 Truststore")
}
}
}
@@ -307,17 +281,17 @@ func processTrustCertificates(tlsStore *TLSStore, trustDir string) error {
}
}
// Add all trust certificates to PKCS#12 Truststore (if required)
if tlsStore.Truststore.Keystore != nil && len(tlsStore.Truststore.TrustedCerts) > 0 {
err = addCertificatesToTruststore(&tlsStore.Truststore)
// Add all trust certificates to PKCS#12 Truststore
if len(p12Truststore.TrustedCerts) > 0 {
err = addCertificatesToTruststore(p12Truststore)
if err != nil {
return err
}
}
// Add all trust certificates to CMS Keystore
if len(tlsStore.Keystore.TrustedCerts) > 0 {
err = addCertificatesToCMSKeystore(&tlsStore.Keystore)
if len(cmsKeystore.TrustedCerts) > 0 {
err = addCertificatesToCMSKeystore(cmsKeystore)
if err != nil {
return err
}
@@ -327,7 +301,7 @@ func processTrustCertificates(tlsStore *TLSStore, trustDir string) error {
}
// processPrivateKey processes the private key (*.key) from a set of keys
func processPrivateKey(keyDir string, keySetName string, keys []os.FileInfo) (interface{}, string, error) {
func processPrivateKey(keySetName string, keys []os.FileInfo) (interface{}, string, error) {
var privateKey interface{}
keyPrefix := ""
@@ -362,7 +336,7 @@ func processPrivateKey(keyDir string, keySetName string, keys []os.FileInfo) (in
}
// processCertificates processes the certificates (*.crt) from a set of keys
func processCertificates(keyDir string, keySetName, keyPrefix string, keys []os.FileInfo, cmsKeystore, p12Truststore *KeyStoreData) (*x509.Certificate, []*x509.Certificate, error) {
func processCertificates(keySetName, keyPrefix string, keys []os.FileInfo, cmsKeystore, p12Truststore *KeyStoreData) (*x509.Certificate, []*x509.Certificate, error) {
var publicCertificate *x509.Certificate
var caCertificate []*x509.Certificate
@@ -410,12 +384,10 @@ func processCertificates(keyDir string, keySetName, keyPrefix string, keys []os.
return nil, nil, fmt.Errorf("Failed to add to know certificates for CMS Keystore")
}
if p12Truststore.Keystore != nil {
// Add to known certificates for the PKCS#12 Truststore
err = addToKnownCertificates(block, p12Truststore, true)
if err != nil {
return nil, nil, fmt.Errorf("Failed to add to know certificates for PKCS#12 Truststore")
}
// Add to known certificates for the PKCS#12 Truststore
err = addToKnownCertificates(block, p12Truststore, true)
if err != nil {
return nil, nil, fmt.Errorf("Failed to add to know certificates for PKCS#12 Truststore")
}
certificate, err := x509.ParseCertificate(block.Bytes)

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2019, 2021
© 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.
@@ -60,7 +60,7 @@ func ConfigureWebKeystore(p12Truststore KeyStoreData, webKeystore string) (strin
if webKeystore == "" {
webKeystore = webKeystoreDefault
}
webKeystoreFile := filepath.Join(keystoreDirDefault, webKeystore)
webKeystoreFile := filepath.Join(keystoreDir, webKeystore)
// Check if a new self-signed certificate should be generated
genHostName := os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME")

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2021
© 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.
@@ -117,22 +117,14 @@ func (l *Logger) log(level string, msg string) {
// Debug logs a line as debug
func (l *Logger) Debug(args ...interface{}) {
if l.debug {
if l.json {
l.log(debugLevel, fmt.Sprint(args...))
} else {
l.log(debugLevel, "DEBUG: "+fmt.Sprint(args...))
}
l.log(debugLevel, fmt.Sprint(args...))
}
}
// Debugf logs a line as debug using format specifiers
func (l *Logger) Debugf(format string, args ...interface{}) {
if l.debug {
if l.json {
l.log(debugLevel, fmt.Sprintf(format, args...))
} else {
l.log(debugLevel, fmt.Sprintf("DEBUG: "+format, args...))
}
l.log(debugLevel, fmt.Sprintf(format, args...))
}
}

7
source-branch.env Normal file
View File

@@ -0,0 +1,7 @@
###########################################################################################################################################################
# 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.2.0.x-eus
###########################################################################################################################################################

View File

@@ -1,7 +1,7 @@
// +build mqdev
/*
© Copyright IBM Corporation 2018, 2021
© 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.
@@ -43,7 +43,6 @@ func TestDevGoldenPath(t *testing.T) {
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=" + qm,
"DEBUG=true",
},
}
id := runContainerWithPorts(t, cli, &containerConfig, []int{9443})
@@ -83,8 +82,6 @@ func TestDevSecure(t *testing.T) {
"MQ_QMGR_NAME=" + qm,
"MQ_APP_PASSWORD=" + appPassword,
"DEBUG=1",
"WLP_LOGGING_MESSAGE_FORMAT=JSON",
"MQ_ENABLE_EMBEDDED_WEB_SERVER_LOG=true",
},
Image: imageName(),
}

View File

@@ -1,3 +1,4 @@
//go:build mqdev
// +build mqdev
/*
@@ -48,7 +49,6 @@ var insecureTLSConfig *tls.Config = &tls.Config{
}
func waitForWebReady(t *testing.T, cli *client.Client, ID string, tlsConfig *tls.Config) {
t.Logf("%s Waiting for web server to be ready", time.Now().Format(time.RFC3339))
httpClient := http.Client{
Timeout: time.Duration(10 * time.Second),
Transport: &http.Transport{
@@ -64,13 +64,13 @@ func waitForWebReady(t *testing.T, cli *client.Client, ID string, tlsConfig *tls
case <-time.After(1 * time.Second):
req, err := http.NewRequest("GET", url, nil)
req.SetBasicAuth("admin", defaultAdminPassword)
resp, err := httpClient.Do(req)
resp, err := httpClient.Do(req.WithContext(ctx))
if err == nil && resp.StatusCode == http.StatusOK {
t.Logf("%s MQ web server is ready", time.Now().Format(time.RFC3339))
t.Log("MQ web server is ready")
return
}
case <-ctx.Done():
t.Fatalf("%s Timed out waiting for web server to become ready", time.Now().Format(time.RFC3339))
t.Fatal("Timed out waiting for web server to become ready")
}
}
}

View File

@@ -1475,44 +1475,3 @@ func TestHealthCheckWithNoNewPrivileges(t *testing.T) {
func TestHealthCheckWithNewPrivileges(t *testing.T) {
utilTestHealthCheck(t, false)
}
// utilTestStartedCheck is used by TestStartedCheck* to run a container with
// privileges enabled or disabled. Otherwise the same as the golden path tests.
func utilTestStartedCheck(t *testing.T, nonewpriv bool) {
t.Parallel()
cli, err := client.NewEnvClient()
if err != nil {
t.Fatal(err)
}
containerConfig := container.Config{
Env: []string{"LICENSE=accept", "MQ_QMGR_NAME=qm1"},
}
hostConfig := getDefaultHostConfig(t, cli)
hostConfig.SecurityOpt = append(hostConfig.SecurityOpt, fmt.Sprintf("no-new-privileges:%v", nonewpriv))
id := runContainerWithHostConfig(t, cli, &containerConfig, hostConfig)
defer cleanContainer(t, cli, id)
waitForReady(t, cli, id)
rc, out := execContainer(t, cli, id, "", []string{"chkmqstarted"})
t.Log(out)
if rc != 0 {
t.Errorf("Expected chkmqstarted to return with exit code 0; got \"%v\"", rc)
t.Logf("Output from chkmqstarted:\n%v", out)
}
// Stop the container cleanly
stopContainer(t, cli, id)
}
// TestStartedCheckWithNoNewPrivileges tests golden path start/stop plus
// chkmqstarted, when running in a container where no new privileges are
// allowed (i.e. setuid is disabled)
func TestStartedCheckWithNoNewPrivileges(t *testing.T) {
utilTestStartedCheck(t, true)
}
// TestStartedCheckWithNoNewPrivileges tests golden path start/stop plus
// chkmqstarted when running in a container where new privileges are
// allowed (i.e. setuid is allowed)
// See https://github.com/ibm-messaging/mq-container/issues/428
func TestStartedCheckWithNewPrivileges(t *testing.T) {
utilTestStartedCheck(t, false)
}

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2017, 2021
© 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.
@@ -313,31 +313,6 @@ func runContainerWithHostConfig(t *testing.T, cli *client.Client, containerConfi
return ctr.ID
}
// runContainerWithAllConfig creates and starts a container, using the supplied ContainerConfig, HostConfig,
// NetworkingConfig, and container name (or the value of t.Name if containerName="").
func runContainerWithAllConfig(t *testing.T, cli *client.Client, containerConfig *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) string {
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 {
t.Fatal(err)
}
startContainer(t, cli, ctr.ID)
return ctr.ID
}
// runContainerWithPorts creates and starts a container, exposing the specified ports on the host.
// If no image is specified in the container config, then the image name is retrieved from the TEST_IMAGE
// environment variable.
@@ -647,9 +622,6 @@ func waitForReady(t *testing.T, cli *client.Client, ID string) {
} else if rc == 10 {
t.Log("MQ Readiness: Queue Manager Running as Standby")
return
} else if rc == 20 {
t.Log("MQ Readiness: Queue Manager Running as Replica")
return
}
case <-ctx.Done():
t.Fatal("Timed out waiting for container to become ready")
@@ -826,12 +798,23 @@ func copyFromContainer(t *testing.T, cli *client.Client, id string, file string)
}
func getPort(t *testing.T, cli *client.Client, ID string, port int) string {
i, err := cli.ContainerInspect(context.Background(), ID)
if err != nil {
t.Fatal(err)
var inspectInfo types.ContainerJSON
var err error
for attemptsRemaining := 3; attemptsRemaining > 0; attemptsRemaining-- {
inspectInfo, err = cli.ContainerInspect(context.Background(), ID)
if err != nil {
t.Fatal(err)
}
portNat := nat.Port(fmt.Sprintf("%d/tcp", port))
if inspectInfo.NetworkSettings.Ports[portNat] == nil || len(inspectInfo.NetworkSettings.Ports[portNat]) == 0 {
t.Log("Container port not yet bound")
time.Sleep(1 * time.Second)
continue
}
return inspectInfo.NetworkSettings.Ports[portNat][0].HostPort
}
portNat := nat.Port(fmt.Sprintf("%d/tcp", port))
return i.NetworkSettings.Ports[portNat][0].HostPort
t.Fatal("Failed to get port")
return ""
}
func countLines(t *testing.T, r io.Reader) int {
@@ -864,12 +847,3 @@ func countTarLines(t *testing.T, b []byte) int {
}
return total
}
func getMQVersion(t *testing.T, cli *client.Client) (string, error) {
inspect, _, err := cli.ImageInspectWithRaw(context.Background(), imageName())
if err != nil {
return "", err
}
version := inspect.ContainerConfig.Labels["version"]
return version, nil
}

View File

@@ -14,7 +14,6 @@ require (
github.com/onsi/gomega v1.10.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/cobra v1.1.1 // indirect
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
)

View File

@@ -1,76 +1,23 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Sirupsen/logrus v1.0.5 h1:447dy9LxSj+Iaa2uN3yoFHOzU9yJcJYiQPtNz8OXtv0=
github.com/Sirupsen/logrus v1.0.5/go.mod h1:rmk17hk6i8ZSAJkSDa7nOxamrG+SP4P0mm+DAvExv4U=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v1.13.2-0.20170601211448-f5ec1e2936dc h1:y4nIGNQUH6JtUV3pd6HjnzdnHq+96wMDVXhkfZ6jc4E=
github.com/docker/docker v1.13.2-0.20170601211448-f5ec1e2936dc/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.2+incompatible h1:vFgEHPqWBTp4pTjdLwjAA4bSo3gvIGOYwuJTlEjVBCw=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
@@ -78,78 +25,15 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
@@ -160,125 +44,27 @@ github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -286,52 +72,11 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -341,26 +86,13 @@ google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyz
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@@ -1,219 +0,0 @@
/*
© 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.
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 (
"testing"
"github.com/docker/docker/client"
)
// TestNativeHABasic creates 3 containers in a Native HA queue manager configuration
// and ensures the queue manger and replicas start as expected
func TestNativeHABasic(t *testing.T) {
cli, err := client.NewEnvClient()
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{}
qmVolumes := []string{}
qmNetwork, err := createBridgeNetwork(cli, t)
if err != nil {
t.Fatal(err)
}
defer removeBridgeNetwork(cli, qmNetwork.ID)
for i := 0; i <= 2; i++ {
vol := createVolume(t, cli, containerNames[i])
defer removeVolume(t, cli, vol.Name)
qmVolumes = append(qmVolumes, vol.Name)
containerConfig := getNativeHAContainerConfig(containerNames[i], containerNames, defaultHAPort)
hostConfig := getHostConfig(t, 1, "", "", vol.Name)
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)
_, err = getActiveReplicaInstances(t, cli, qmReplicaIDs)
if err != nil {
t.Fatal(err)
}
}
// TestNativeHAFailover creates 3 containers in a Native HA queue manager configuration,
// stops the active queue manager, checks a replica becomes active, and ensures the stopped
// queue manager comes back as a replica
func TestNativeHAFailover(t *testing.T) {
cli, err := client.NewEnvClient()
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{}
qmVolumes := []string{}
qmNetwork, err := createBridgeNetwork(cli, t)
if err != nil {
t.Fatal(err)
}
defer removeBridgeNetwork(cli, qmNetwork.ID)
for i := 0; i <= 2; i++ {
vol := createVolume(t, cli, containerNames[i])
defer removeVolume(t, cli, vol.Name)
qmVolumes = append(qmVolumes, vol.Name)
containerConfig := getNativeHAContainerConfig(containerNames[i], containerNames, defaultHAPort)
hostConfig := getHostConfig(t, 1, "", "", vol.Name)
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)
haStatus, err := getActiveReplicaInstances(t, cli, qmReplicaIDs)
if err != nil {
t.Fatal(err)
}
stopContainer(t, cli, haStatus.Active)
waitForFailoverHA(t, cli, haStatus.Replica)
startContainer(t, cli, haStatus.Active)
waitForReady(t, cli, haStatus.Active)
_, 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 enabled, and ensures the queue manger and replicas start as expected
func TestNativeHASecure(t *testing.T) {
cli, err := client.NewEnvClient()
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)
containerConfig.Env = append(containerConfig.Env, "MQ_NATIVE_HA_TLS=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)
_, 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 enabled, overrides the default CipherSpec, and ensures the queue manger
// and replicas start as expected
func TestNativeHASecureCipherSpec(t *testing.T) {
cli, err := client.NewEnvClient()
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)
containerConfig.Env = append(containerConfig.Env, "MQ_NATIVE_HA_TLS=true", "MQ_NATIVE_HA_CIPHERSPEC=TLS_AES_256_GCM_SHA384")
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)
_, err = getActiveReplicaInstances(t, cli, qmReplicaIDs)
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,149 +0,0 @@
/*
© 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.
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 (
"context"
"fmt"
"path/filepath"
"testing"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
)
const defaultHAPort = 9414
// HAReplicaStatus represents the Active/Replica/Replica container status of the queue manager
type HAReplicaStatus struct {
Active string
Replica [2]string
}
func createBridgeNetwork(cli *client.Client, t *testing.T) (types.NetworkCreateResponse, error) {
return cli.NetworkCreate(context.Background(), t.Name(), types.NetworkCreate{})
}
func removeBridgeNetwork(cli *client.Client, networkID string) error {
return cli.NetworkRemove(context.Background(), networkID)
}
func getNativeHAContainerConfig(containerName string, replicaNames [3]string, haPort int) container.Config {
return container.Config{
Env: []string{
"LICENSE=accept",
"MQ_QMGR_NAME=QM1",
"AMQ_CLOUD_PAK=true",
"MQ_NATIVE_HA=true",
fmt.Sprintf("HOSTNAME=%s", containerName),
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_0_NAME=%s", replicaNames[0]),
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_1_NAME=%s", replicaNames[1]),
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_2_NAME=%s", replicaNames[2]),
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_0_REPLICATION_ADDRESS=%s(%d)", replicaNames[0], haPort),
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_1_REPLICATION_ADDRESS=%s(%d)", replicaNames[1], haPort),
fmt.Sprintf("MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS=%s(%d)", replicaNames[2], haPort),
},
}
}
func getNativeHASecureHostConfig(t *testing.T) container.HostConfig {
return container.HostConfig{
Binds: []string{
coverageBind(t),
filepath.Join(getCwd(t, true), "../tls") + ":/etc/mqm/ha/pki/keys/ha",
},
}
}
func getNativeHANetworkConfig(networkID string) network.NetworkingConfig {
return network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
networkID: &network.EndpointSettings{},
},
}
}
func getActiveReplicaInstances(t *testing.T, cli *client.Client, qmReplicaIDs [3]string) (HAReplicaStatus, error) {
var actives []string
var replicas []string
for _, id := range qmReplicaIDs {
qmReplicaStatus := getQueueManagerStatus(t, cli, id, "QM1")
if qmReplicaStatus == "Running" {
actives = append(actives, id)
} else if qmReplicaStatus == "Replica" {
replicas = append(replicas, id)
} else {
err := fmt.Errorf("Expected status to be Running or Replica, got status: %s", qmReplicaStatus)
return HAReplicaStatus{}, err
}
}
if len(actives) != 1 || len(replicas) != 2 {
err := fmt.Errorf("Expected 1 Active and 2 Replicas, got: %d Active and %d Replica", len(actives), len(replicas))
return HAReplicaStatus{}, err
}
return HAReplicaStatus{actives[0], [2]string{replicas[0], replicas[1]}}, nil
}
func waitForReadyHA(t *testing.T, cli *client.Client, qmReplicaIDs [3]string) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
for {
select {
case <-time.After(1 * time.Second):
for _, id := range qmReplicaIDs {
rc, _ := execContainer(t, cli, id, "", []string{"chkmqready"})
if rc == 0 {
t.Log("MQ is ready")
rc, _ := execContainer(t, cli, id, "", []string{"chkmqstarted"})
if rc == 0 {
t.Log("MQ has started")
return
}
}
}
case <-ctx.Done():
t.Fatal("Timed out waiting for HA Queue Manager to become ready")
}
}
}
func waitForFailoverHA(t *testing.T, cli *client.Client, replicas [2]string) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
for {
select {
case <-time.After(1 * time.Second):
for _, id := range replicas {
if status := getQueueManagerStatus(t, cli, id, "QM1"); status == "Running" {
return
}
}
case <-ctx.Done():
t.Fatal("Timed out waiting for Native HA Queue Manager to failover to an available replica")
}
}
}

View File

@@ -1,4 +1,4 @@
# © Copyright IBM Corporation 2018, 2021
# © 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.

View File

@@ -1,5 +1,5 @@
<!--
© Copyright IBM Corporation 2018, 2021
© Copyright IBM Corporation 2018
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,7 @@ limitations under the License.
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>com.ibm.mq.allclient</artifactId>
<version>9.2.0.0</version>
<version>9.3.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -65,9 +65,5 @@ limitations under the License.
</executions>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
</build>
</project>

View File

@@ -1,5 +1,5 @@
/*
© Copyright IBM Corporation 2018, 2021
© Copyright IBM Corporation 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@ limitations under the License.
*/
package com.ibm.mqcontainer.test;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.FileInputStream;
import java.io.IOException;
@@ -32,12 +32,9 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import com.ibm.mq.MQException;
import com.ibm.mq.constants.MQConstants;
import com.ibm.mq.jms.MQConnectionFactory;
import com.ibm.mq.jms.MQQueue;
import com.ibm.msg.client.wmq.WMQConstants;
import com.ibm.msg.client.jms.DetailedJMSSecurityRuntimeException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
@@ -60,18 +57,27 @@ class JMSTests {
static SSLSocketFactory createSSLSocketFactory() throws IOException, GeneralSecurityException {
KeyStore ts=KeyStore.getInstance("jks");
ts.load(new FileInputStream(TRUSTSTORE), PASSPHRASE.toCharArray());
// KeyManagerFactory kmf=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
TrustManagerFactory tmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ts);
// tmf.init();
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
// Security.setProperty("crypto.policy", "unlimited");
ctx.init(null, tmf.getTrustManagers(), null);
return ctx.getSocketFactory();
}
static MQConnectionFactory createMQConnectionFactory(String channel, String addr) throws JMSException, IOException, GeneralSecurityException {
static JMSContext create(String channel, String addr, String user, String password) throws JMSException, IOException, GeneralSecurityException {
LOGGER.info(String.format("Connecting to %s/TCP/%s(1414) as %s", channel, addr, user));
MQConnectionFactory factory = new MQConnectionFactory();
factory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
factory.setChannel(channel);
factory.setConnectionNameList(String.format("%s(1414)", addr));
// If a password is set, make sure it gets sent to the queue manager for authentication
if (password != null) {
factory.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
}
// factory.setClientReconnectOptions(WMQConstants.WMQ_CLIENT_RECONNECT);
if (TRUSTSTORE == null) {
LOGGER.info("Not using TLS");
}
@@ -88,33 +94,12 @@ class JMSTests {
factory.setSSLCipherSuite("TLS_RSA_WITH_AES_128_CBC_SHA256");
}
}
return factory;
}
/**
* Create a JMSContext with the supplied user and password.
*/
static JMSContext create(String channel, String addr, String user, String password) throws JMSException, IOException, GeneralSecurityException {
LOGGER.info(String.format("Connecting to %s/TCP/%s(1414) as %s", channel, addr, user));
MQConnectionFactory factory = createMQConnectionFactory(channel, addr);
// If a password is set, make sure it gets sent to the queue manager for authentication
if (password != null) {
factory.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
}
LOGGER.info(String.format("CSP authentication: %s", factory.getBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP)));
// Give up if unable to reconnect for 10 minutes
// factory.setClientReconnectTimeout(600);
// LOGGER.info(String.format("user=%s pw=%s", user, password));
return factory.createContext(user, password);
}
/**
* Create a JMSContext with the default user identity (from the OS)
*/
static JMSContext create(String channel, String addr) throws JMSException, IOException, GeneralSecurityException {
LOGGER.info(String.format("Connecting to %s/TCP/%s(1414) as OS user '%s'", channel, addr, System.getProperty("user.name")));
MQConnectionFactory factory = createMQConnectionFactory(channel, addr);
LOGGER.info(String.format("CSP authentication: %s", factory.getBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP)));
return factory.createContext();
}
@BeforeAll
private static void waitForQueueManager() {
for (int i = 0; i < 20; i++) {
@@ -131,34 +116,28 @@ class JMSTests {
}
}
@Test
void putGetTest(TestInfo t) throws Exception {
@BeforeEach
void connect() throws Exception {
context = create(CHANNEL, ADDR, USER, PASSWORD);
}
@Test
void succeedingTest(TestInfo t) throws JMSException {
Queue queue = new MQQueue("DEV.QUEUE.1");
context.createProducer().send(queue, t.getDisplayName());
Message m = context.createConsumer(queue).receive();
assertNotNull(m.getBody(String.class));
}
// @Test
// void failingTest() {
// fail("a failing test");
// }
@Test
void defaultIdentityTest(TestInfo t) throws Exception {
LOGGER.info(String.format("Password='%s'", PASSWORD));
try {
// Don't pass a user/password, which should cause the default identity to be used
context = create(CHANNEL, ADDR);
} catch (DetailedJMSSecurityRuntimeException ex) {
Throwable cause = ex.getCause();
assertNotNull(cause);
assertTrue(cause instanceof MQException);
assertEquals(MQConstants.MQRC_NOT_AUTHORIZED, ((MQException)cause).getReason());
return;
}
// The default developer config allows any user to appear as "app", and use a blank password. This is done with the MCAUSER on the channel.
// If this test is run on a queue manager without a password set, then it should be possible to connect without exception.
// If this test is run on a queue manager with a password set, then an exception should be thrown, because this test doesn't send a password.
if ((PASSWORD != null) && (PASSWORD != "")) {
fail("Exception not thrown");
}
@Disabled("for demonstration purposes")
void skippedTest() {
// not executed
}
@AfterEach
@@ -167,4 +146,9 @@ class JMSTests {
context.close();
}
}
@AfterAll
static void tearDownAll() {
}
}

Binary file not shown.

View File

@@ -1,6 +1,6 @@
#!/bin/bash
#!/bin/bash -ex
# -*- mode: sh -*-
# © Copyright IBM Corporation 2018
# © 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.
@@ -23,6 +23,7 @@ PASSWORD=passw0rd
openssl req \
-newkey rsa:2048 -nodes -keyout ${KEY} \
-subj "/CN=localhost" \
-addext "subjectAltName = DNS:localhost" \
-x509 -days 3650 -out ${CERT}
# Add the key and certificate to a PKCS #12 key store, for the server to use

View File

@@ -1,17 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICpDCCAYwCCQC6vpJFnfYO6TANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAls
b2NhbGhvc3QwHhcNMTkwMzIxMTYxMzUxWhcNMjkwMzE4MTYxMzUxWjAUMRIwEAYD
VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCu
48qtIDwmihFqj2HY3dZjPfROA1MJ+D0c6aEA08ooOczthLB7XdZBQDapj8LFldyt
4ZMbTkqtF5QtPXmJY0wi39foLYlcGXPL1b7y3mypaFou88BcSM3VmfILKXhNeAlt
rXevnuT5kDU7sLVgKGhGwas20T1MU7d0I3bQ5z5c7egL76Hk9fYucjN6RkbwlrJ3
TrCXrGIziofn3Zq1t51ygv21c80JD3XJ44YmuCrede4rhOS/4NpwRuZyiwpJ6tlv
0L0QSDGCmt2JT3ty28UAsGznFzC5Qu9KyaR+9Gk4aftiyKxrYWZkgtJmMRU+C1X2
kFLOHsucGmJswjwubSR7AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEdlmXVGy86P
XIX5a4ZmHQ5Ns4wm7rY8vzUxlymEQ86En1PN1zAO9gV94tLyNeMptjsFEEo/uJhC
Yvg3l5TIr/WCiY2+2XsSHvnbXrlbF3S0fRHa9VaCMRKjzRT68uq2Y891906YGtUE
m6fCjHqVzX8qaplDf79aVkPydYaYOIZ1a/mCfQcD9XMZ/v5zI9IUDhdoq97bgPhB
gBOzWLI+hkzyU8jxKAFw1Hwi9lD/P6RXL5arNb/+arOgA3vTW+xGWGevgjVK1Ay9
81beWiQmn0KbeLZxj+WJ9Nntlf1M4EqPYgsSYs/IlJTYS8W1B0mDJEoovPdFTryY
GyIuQEVcjUE=
MIICwzCCAaugAwIBAgIJAKnwG0VGiDelMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
BAMMCWxvY2FsaG9zdDAeFw0yMTA5MDYxNTIyMDlaFw0zMTA5MDQxNTIyMDlaMBQx
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBALLmDX3OB/4DlzJzKz/Edc5qVdjdIN/u8pApSQPevT0mAsSK1uw2MObeOo4C
DCBmabYeuvGzZ4t3SiejdsHK+qAYMFW51lxTbulv5kUPvTBOY2JCENkVDFjqcK8S
9ItI/UzTmnBolvZmUKzROHzA/pFb/jkhlzqJO+TqIBXKLF5gdFFTiHHcqfoUyVOV
n+49V8z6W2rokz4QIWa5Dlh6VS1B6VXdihJv5P9HV8P8FOtefhA85yaSVKlFS/AC
XRb5FmtmYHBnghLktHS71s/KcPeX27Q1NcKhmZMvHRH95hqEcP25S6SGu69eiCLk
xpbJKqG3fntfooLUDfR2PHQUJ7UCAwEAAaMYMBYwFAYDVR0RBA0wC4IJbG9jYWxo
b3N0MA0GCSqGSIb3DQEBCwUAA4IBAQBamIH23oDh1XxOeMPUEyPLHm5M8LM8FNhT
GEpf1ICy4TSLipSFhIs3hGzVt22zBBzU59apQ8rXUME5SK+9PLag/t/48rG1SfUA
VyYvaeu/cA5NQMWwuyCLqZL1MWn+BLsdAiNtbNHANesnl0i+vUb0GPzSP8soe3PP
N7Fh8SO3Qq6e9zT3iE2tP2OFxzcpg538Xn3qoVPJwmLIfBtvsiK07zqAWdqBWtt6
cBXyagnmgKvOyv6sKAlTpwP9HqVem3XxZVrhm1KiPHs4Dnks6e79txmB8lqzvWu5
tu4h2ePGJjqUy5JkkoDY0j6hALwEe3ZXBvJ6XUQDi9Hou2k+MaQd
-----END CERTIFICATE-----

View File

@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCu48qtIDwmihFq
j2HY3dZjPfROA1MJ+D0c6aEA08ooOczthLB7XdZBQDapj8LFldyt4ZMbTkqtF5Qt
PXmJY0wi39foLYlcGXPL1b7y3mypaFou88BcSM3VmfILKXhNeAltrXevnuT5kDU7
sLVgKGhGwas20T1MU7d0I3bQ5z5c7egL76Hk9fYucjN6RkbwlrJ3TrCXrGIziofn
3Zq1t51ygv21c80JD3XJ44YmuCrede4rhOS/4NpwRuZyiwpJ6tlv0L0QSDGCmt2J
T3ty28UAsGznFzC5Qu9KyaR+9Gk4aftiyKxrYWZkgtJmMRU+C1X2kFLOHsucGmJs
wjwubSR7AgMBAAECggEAH9t6teKjUlngJksMBdcTEGzerb9JRw2jBDtCisYJkx5E
SBfdlftX5fbufiCj2B4eXsYyZ8zxKWqcIUmLdA1Udx3TVIXG+bHhOAYtjEwb+xf5
JYhdR/IzHG+4eXQKaAIvpXztyl3lU9iC+eaMg4GYzRrGN2wSAG9XgZ5cLF2TLJYU
jPxp7goz9X6V57aL2G/EFlbFsMaI/6cW7+XoRdo0I4N2Z766gz7GgyxtTVwR5Peq
LjOpqSNS0W57KJxReURfySok9CP1DfyigopsYW8O4jGVDDRLdiN3I8+JhWya2E0j
96hHpN04Oz6HnMm7bdZDVtkZCOiu6xIzLJJxZ4o+kQKBgQDYqOA/hSod7s7w4LBE
A6Mp+e0//PYH6/N9SKmSIgQNec9bMGI4yanoblMbg4GM1g7pkvjlC0nTdjnUbLkB
vIvtVh3XwTIlrZ/4lc7VB23/hmKU+lRc+NJP5fgasAQu0W3+qp2cXo0pnHVwBEku
Z7FwDPX0JNDIi/Or2I7dt8JojQKBgQDOpU1AnIXv1/cToYK4nz8BWLxRxwLTxy5A
ucafNKacPlxb5luZRCExiPZwAM8Z3zI9o99rYXOPQmsnknZWJV66Zx0Vo0yTD1CT
DWMUj0ugI1wORNMhwZP6YBYWjAeupyU9a7FyU1Geg4sdQt5rMyAEQOoECc8x8foP
rySHuO/TJwKBgBjMM2ZxymFErQDa5rHSLMGoLmRtgodjlSnYwDfOluIn9/i67/MJ
+d11iyOSCKji8y/+t2gXw6plVLcgfohZWTaf7ah9H006sx2Tn+m4APoHGo9sm21M
uV2Vt7DuRnxJUiqcwo9cLxH9K1/Xzbx299MYWKpJ8G+TvR8FGUz9NE4dAoGAM5gs
KKSsAE1QwFMEG2qPRZvNMTHaL9w8XSbFQ7zWmI4tazihyCutifujZCWfj9sdZSyE
PQBQ5QT1UiUMbMfZ1fqm1V83YERjnsOp6Fk6zZnmgx2GBZiahNn2ydxekqni72nz
HRNWfphjZIPsmqFiLg2zIBz+4X6EK+RT35s6LeMCgYEAwF/9jX8kONW5KKZdoNHa
opkLpa9qkwTGQ9M3AZiRUjM4rtvggYt8FBEP+3BLDLHqfUOkPq82MCRXm+6Cz+sT
gyPnsPlAh/sr3Pys3olJbUDE9H24k1LU0CI/sSwAFkka0+Q7PVTTe/Dcavitrcrm
+fyiT2oSPZeHSjQE9iIW3OY=
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCy5g19zgf+A5cy
cys/xHXOalXY3SDf7vKQKUkD3r09JgLEitbsNjDm3jqOAgwgZmm2Hrrxs2eLd0on
o3bByvqgGDBVudZcU27pb+ZFD70wTmNiQhDZFQxY6nCvEvSLSP1M05pwaJb2ZlCs
0Th8wP6RW/45IZc6iTvk6iAVyixeYHRRU4hx3Kn6FMlTlZ/uPVfM+ltq6JM+ECFm
uQ5YelUtQelV3YoSb+T/R1fD/BTrXn4QPOcmklSpRUvwAl0W+RZrZmBwZ4IS5LR0
u9bPynD3l9u0NTXCoZmTLx0R/eYahHD9uUukhruvXogi5MaWySqht357X6KC1A30
djx0FCe1AgMBAAECggEAagD5A49+mtwjzigB+4H80Def8KVuomIi5psgAaQM+9u3
DiC6ozKlHVeW2KiL6PLmNpzU5v0IINKpZP1uE/yjLxPGKDW6t/BUKww8JLXjw2jf
aMx+0TKwo0sfRA32S0YPmWNVAsBmm1AbA5vhXcK51QXuiInH406H5+d25ZJrYevF
liKWSjx9CM/0XO7t20j18mCa8RjBEdsZoHxHsoWNvFJ6DCR25cFShAhR7s4OtkUk
yELm1tYYrFOffUM0Q/Fp9uSlCHWMSqPtf/6NEfnszfFEtzDh/N+YqC1Bexv0XPsD
dBPOkUZjWA2Sc8Se1t2GLfrRURzj3GvWH1+GssjsAQKBgQDeIdyzQSqce4Kn0opa
vdS5moCiv3pyfNd0nYe0awgVos4kHY7/nBq0eyMZAatRHeD3DunVsw3LmvWyEw53
app7MTTjVrYaadoBlB6jy2elyF5RcW2jGchZExoNh+0ZQWUiMbYEozPLQTy9ZxMz
t0OcZ1hHPngGgmj5TELZKkwEtQKBgQDOLLh7pdKrdudtim+o4H20jl5yYKl25Iq/
DKVodwUd94cM7xAIOQJrx2XK/YPCfRkKRN1wxzAhYdIVkaaKDVhI8Jeu+H18QOa6
5OlzzZcqJCtACpbVqLaDcmq8pRrAYekiwMIKwC95llvktjilvLfoUnQoXAaX8E8B
yCSUvDh3AQKBgQCxa0h04DLho4Da/D3HdmHHERF3bAqoEPCh0wTF5MsjRNLzY6yI
mq11w/hni77C3mOF0SKRrh7xpcZiQfhHBx12EfpVLjfq5uraYe0LFHanol87G6bf
I8Oy6Z/geNW2W1YktqHUGGpRCL0z5nUe1FyrOpv2431Ibbbcj73A6JipFQKBgHdl
vJyWpk73+AQe1JUnFIU4oYd5ZQpeRd9n8m5x5ru4+jPKSi2I3lcOTWvlrqU2Dwc8
ZEUIhV3/qUsmYxy1p7ft5NnGO912NGhtYqjWmcEk2wsmVr17C99JpniC4OAik4G1
wWm6bIPsSGFGCb4pcROQlIY+7O6WkxqEDnM4ITcBAoGAHXBKmadFpupUeGSkCwEo
/VjeI4QoKKcWj9K8z8ifCVPz1FiQ1AJ91WMTM7PAmpEDX058Hor9xxJ2bEtQFwUS
QKvjeU+/Ig0TWjsJBgBPvc0xYLaJptAbjvG4a5nBn7hwbRzLTcKx2OVTmdAkz00H
1lq8cwizfwNgt8ldFFDDRvw=
-----END PRIVATE KEY-----

Binary file not shown.

View File

@@ -56,14 +56,16 @@ FILE_NAME=
BUILD_ID=
REGISTRY_HOSTNAME=
FILE_LOCATION=
PROPERTY_NAME=
CHECK=false
UPLOAD=false
GET=false
GET_PROPERTY=false
DELETE=false
DELETE_NAMESPACE=false
num_commands_selected=0
while getopts "f:u:p:c:l:-:" flag
while getopts "f:u:p:c:l:n:-:" flag
do
case "${flag}" in
f) FILE_NAME=${OPTARG};;
@@ -71,6 +73,7 @@ do
p) CREDENTIAL=${OPTARG};;
c) CACHE_PATH=${OPTARG};;
l) FILE_LOCATION=${OPTARG};;
n) PROPERTY_NAME=${OPTARG};;
-)
case "${OPTARG}" in
check)
@@ -85,6 +88,10 @@ do
GET=true
num_commands_selected=$((num_commands_selected+1))
;;
get-property)
GET_PROPERTY=true
num_commands_selected=$((num_commands_selected+1))
;;
delete)
DELETE=true
num_commands_selected=$((num_commands_selected+1))
@@ -167,6 +174,43 @@ if [ "$GET" == "true" ]; then
fi
fi
if [ "$GET_PROPERTY" == "true" ]; then
if [[ -z $PROPERTY_NAME ]]; then
printf "${REDCROSS} Property name to retrieve from '${FILE_NAME}' was not supplied please do so\n"
printf $SPACER
printf "${ERROR}$usage${END}\n"
exit 1
fi
if [[ -z $FILE_LOCATION ]]; then
printf "${REDCROSS} File location to store property value in was not supplied please do so\n"
printf $SPACER
printf "${ERROR}$usage${END}\n"
exit 1
fi
printf "${GREENRIGHTARROW} Attempting to retrieve ${PROPERTY_NAME} of ${FILE_NAME} from repository ${REMOTE_PATH} and store it in ${FILE_LOCATION}\n"
query_url="${FILE_NAME}"
query_url="${query_url/\/artifactory\//\/artifactory\/api\/storage\//}?properties=${PROPERTY_NAME}"
request_result="$(curl -s -u ${USER}:${CREDENTIAL} "${query_url}")"
if [ $? != 0 ]; then
printf "Unable to retrieve properties from ${query_url}"
exit 1
else
printf "${GREENTICK} Properties retrieved from ${query_url}"
fi
jq -r '.properties.snapshot|first' <<<"$request_result" > ${FILE_LOCATION}
if [ $? != 0 ]; then
printf "Unable to write snapshot property to ${FILE_LOCATION}"
exit 1
else
printf "${GREENTICK} Property written to ${FILE_LOCATION}"
fi
fi
if [ "$DELETE" == "true" ]; then
printf "${GREENRIGHTARROW} Checking to see if file ${FILE_NAME} exists in repository ${REMOTE_PATH} before delete\n"
FILE_FOUND=`curl -u ${USER}:${CREDENTIAL} -X GET "${REMOTE_PATH}/${FILE_NAME}" -o /dev/null -w "%{http_code}" -s`

View File

@@ -16,6 +16,30 @@
set -e
archive_level_cache_dir="$(mktemp -d)"
get_archive_level() {
local level_path
local archive_variable
archive_variable="$1"
MQ_ARCHIVE_LEVEL=""
level_path="${archive_level_cache_dir}/${archive_variable}.level"
if [[ ! -f "$level_path" ]]; then
if [[ -z "${REPOSITORY_USER}" || -z "${REPOSITORY_CREDENTIAL}" ]]; then
echo 'Skipping level lookup as repository credentials not set'
return
fi
if [[ -z "${!archive_variable}" ]]; then
echo "Skipping level lookup as '\$${archive_variable}' is not set"
return
fi
./travis-build-scripts/artifact-util.sh -f "${!archive_variable}" -u "${REPOSITORY_USER}" -p "${REPOSITORY_CREDENTIAL}" -l "$level_path" -n snapshot --get-property
fi
read -r MQ_ARCHIVE_LEVEL < "$level_path"
export MQ_ARCHIVE_LEVEL
}
if [ "$TRAVIS_BRANCH" = "$MAIN_BRANCH" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
echo 'Retrieving global tagcache' && echo -en 'travis_fold:start:tag-cache-retrieve\\r'
./travis-build-scripts/artifact-util.sh -c ${CACHE_PATH} -u ${REPOSITORY_USER} -p ${REPOSITORY_CREDENTIAL} -f cache/${TAGCACHE_FILE} -l ./.tagcache --check
@@ -28,12 +52,14 @@ if [ -z "$BUILD_INTERNAL_LEVEL" ] ; then
make build-devjmstest
echo -en 'travis_fold:end:build-devjmstest\\r'
echo 'Building Developer image...' && echo -en 'travis_fold:start:build-devserver\\r'
get_archive_level MQ_ARCHIVE_REPOSITORY_DEV
make build-devserver
echo -en 'travis_fold:end:build-devserver\\r'
fi
if [ "$BUILD_ALL" = true ] || [ "$LTS" = true ] ; then
if [[ "$ARCH" = "amd64" || "$ARCH" = "s390x" ]] ; then
echo 'Building Production image...' && echo -en 'travis_fold:start:build-advancedserver\\r'
get_archive_level MQ_ARCHIVE_REPOSITORY
make build-advancedserver
echo -en 'travis_fold:end:build-advancedserver\\r'
fi
@@ -45,10 +71,12 @@ else
if [[ "$BUILD_INTERNAL_LEVEL" == *".DE"* ]]; then
echo 'Building Developer image...' && echo -en 'travis_fold:start:build-devserver\\r'
get_archive_level MQ_ARCHIVE_REPOSITORY_DEV
make build-devserver
echo -en 'travis_fold:end:build-devserver\\r'
else
echo 'Building Production image...' && echo -en 'travis_fold:start:build-advancedserver\\r'
get_archive_level MQ_ARCHIVE_REPOSITORY
make build-advancedserver
echo -en 'travis_fold:end:build-advancedserver\\r'
fi

View File

@@ -26,7 +26,18 @@ mkdir -p $GOPATH/src/github.com/docker
cd $GOPATH/src/github.com/docker
git clone https://github.com/docker/docker-credential-helpers
cd docker-credential-helpers
make pass
# After https://github.com/docker/docker-credential-helpers/commit/fd0197473f0ecb29e73ccef9028057194ff463bc go 1.18 is required... Pin commit if earlier go installed
go_version="$(go version | cut -f3 -d' ')"
IFS=. read -a go_version_parts <<<"$go_version"
go_major="${go_version_parts[0]##go}"
go_minor="${go_version_parts[1]}"
if [[ "$go_major" -eq 1 && "$go_minor" -lt 18 ]]; then
echo "Go version ${go_major}.${go_minor} < 1.18... Pinning credential-helper commit"
git checkout ab7fd12c67d83193072fa91e5648b036547f6323
fi
make pass
cp bin/docker-credential-pass $GOPATH/bin/docker-credential-pass
mkdir -p /home/travis/.docker
echo '{ "credsStore": "pass" }' | tee /home/travis/.docker/config.json

View File

@@ -18,9 +18,6 @@ set -e
if [ "$(uname -m)" = "x86_64" ] ; then export ARCH="amd64" ; else export ARCH=$(uname -m) ; fi
# if DOCKER_USER is set, authenticate with docker.io to mitigate rate limit (https://www.docker.com/increase-rate-limits)
if [ -n "$DOCKER_USER" ] ; then echo 'Authenticating with docker.io...' && docker login -u $DOCKER_USER -p $DOCKER_PASS docker.io ; fi
if [ "$PUSH_MANIFEST_ONLY" = true ] ; then
echo 'Retrieving remote tagcache' && echo -en 'travis_fold:start:retrieve-tag-cache\\r'
./travis-build-scripts/artifact-util.sh -c ${CACHE_PATH} -u ${REPOSITORY_USER} -p ${REPOSITORY_CREDENTIAL} -f cache/${TAGCACHE_FILE} -l ./.tagcache --get

4
vendor/modules.txt vendored
View File

@@ -40,12 +40,12 @@ github.com/prometheus/procfs/internal/util
# github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
## explicit
github.com/syndtr/gocapability/capability
# golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae
# golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
## explicit
golang.org/x/crypto/bcrypt
golang.org/x/crypto/blowfish
golang.org/x/crypto/pbkdf2
# golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f
# golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1
## explicit
golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix

View File

@@ -21,8 +21,5 @@
</application-bnd>
</enterpriseApplication>
<variable name="httpHost" value="*"/>
<variable name="mqConsoleEnableUnsafeInline" value="true"/>
<jndiEntry jndiName="mqConsoleDefaultCCDTHostname" value="${env.MQ_CONSOLE_DEFAULT_CCDT_HOSTNAME}"/>
<jndiEntry jndiName="mqConsoleDefaultCCDTPort" value="${env.MQ_CONSOLE_DEFAULT_CCDT_PORT}"/>
<include location="tls.xml"/>
</server>

View File

@@ -38,9 +38,6 @@
</openidConnectClient>
<variable name="httpHost" value="*"/>
<variable name="managementMode" value="externallyprovisioned"/>
<variable name="mqConsoleEnableUnsafeInline" value="true"/>
<jndiEntry jndiName="mqConsoleDefaultCCDTHostname" value="${env.MQ_CONSOLE_DEFAULT_CCDT_HOSTNAME}"/>
<jndiEntry jndiName="mqConsoleDefaultCCDTPort" value="${env.MQ_CONSOLE_DEFAULT_CCDT_PORT}"/>
<httpDispatcher enableWelcomePage="false" appOrContextRootMissingMessage='&lt;script&gt;document.location.href="/ibmmq/console";&lt;/script&gt;' />
<include location="tls.xml"/>
</server>