Skip to content

PMM-13748 gssapi support #1042

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a9a2fea
build with gssapi tag
idoqo Feb 25, 2025
beb936b
set up kerberos test env
idoqo Feb 25, 2025
f6f9c0e
improve setup
idoqo Mar 3, 2025
3828945
create separate exporter keytab
idoqo Mar 5, 2025
429a4aa
prepare test environment
idoqo Mar 5, 2025
a3b4f5d
include test tags
idoqo Mar 5, 2025
260cbd0
create conf file before starting containers
idoqo Mar 5, 2025
49cd21c
use tmp dir for config
idoqo Mar 5, 2025
8dc0a42
re-run script
idoqo Mar 5, 2025
7de17fb
add logrus reporter
idoqo Mar 5, 2025
68b28c4
Merge branch 'main' into PMM-13748-gssapi-support
idoqo Mar 5, 2025
78546b8
install libkrb5-dev in runner
idoqo Mar 5, 2025
c43f06f
drop installation
idoqo Mar 5, 2025
df39b91
do not mount tmp directly
idoqo Mar 5, 2025
e49d071
install krb5 libraries
idoqo Mar 5, 2025
2e5902f
use one liners for mongo commands
idoqo Mar 5, 2025
433720a
fix permissions
idoqo Mar 5, 2025
4168b9b
fix up linter
idoqo Mar 5, 2025
b4fffed
split test function to satisfy linter
idoqo Mar 5, 2025
5f131b2
fix formatting
idoqo Mar 5, 2025
436e068
remove unused changes
idoqo Mar 5, 2025
9b2b81f
Merge branch 'main' into PMM-13748-gssapi-support
idoqo Mar 10, 2025
41b4475
use prebuilt docker image and volume
idoqo Mar 10, 2025
87b1206
rename 'docker' folder to 'test-setup'
idoqo Mar 10, 2025
e59c50a
fix image in use
idoqo Mar 10, 2025
8568537
build docker image
idoqo Mar 11, 2025
5da2a9d
enable CGO in goreleaser
idoqo Mar 11, 2025
813c7ba
fix releaser tags
idoqo Mar 11, 2025
859c765
force cgo during build
idoqo Mar 11, 2025
b44322b
add timeout to script
idoqo Mar 13, 2025
25f71ce
Merge branch 'main' into PMM-13748-gssapi-support
idoqo Mar 18, 2025
315a6d9
Merge branch 'main' into PMM-13748-gssapi-support
idoqo Apr 9, 2025
26db3b2
Merge branch 'main' into PMM-13748-gssapi-support
idoqo Apr 16, 2025
aa2ce3f
Merge branch 'main' into PMM-13748-gssapi-support
idoqo Apr 24, 2025
811436a
remove logrus
idoqo Apr 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ jobs:
with:
go-version-file: ${{ github.workspace }}/go.mod

- name: Install kerberos development libraries
run: |
sudo apt-get update
sudo apt-get install libkrb5-dev

- name: Run tests with code coverage
run: |
TEST_MONGODB_IMAGE=${{ matrix.image }} make test-cluster
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ dist
cover.out
mongodb_exporter
.DS_Store

3 changes: 2 additions & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 2
builds:
- binary: mongodb_exporter
env:
- CGO_ENABLED=0
- CGO_ENABLED=1
goos:
- linux
- darwin
Expand All @@ -19,6 +19,7 @@ builds:
goarch: arm
flags:
- -v
- -tags=gssapi
ldflags:
- -s -w -X main.version=v{{.Version}} -X main.commit={{.ShortCommit}} -X main.buildDate={{.Date}}
archives:
Expand Down
11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ init: ## Install linters
cd tools && go generate -x -tags=tools

build: ## Compile using plain go build
go build -ldflags="$(GO_BUILD_LDFLAGS)" -o $(PMM_RELEASE_PATH)/mongodb_exporter
CGO_ENABLED=1 go build -ldflags="$(GO_BUILD_LDFLAGS)" -o $(PMM_RELEASE_PATH)/mongodb_exporter -tags gssapi

release: ## Build the binaries using goreleaser
docker run --rm --privileged \
Expand Down Expand Up @@ -99,17 +99,18 @@ help: ## Display this help message
awk -F ':.*?## ' 'NF==2 {printf " %-26s%s\n", $$1, $$2}'

test: env ## Run all tests
go test -v -count 1 -timeout 30s ./...
go test -tags gssapi -v -count 1 -timeout 30s ./...

test-race: env ## Run all tests with race flag
go test -race -v -timeout 30s ./...
go test -tags gssapi -race -v -timeout 30s ./...

test-cover: env ## Run tests and collect cross-package coverage information
go test -race -timeout 30s -coverprofile=cover.out -covermode=atomic -coverpkg=./... ./...
go test -tags gssapi -race -timeout 30s -coverprofile=cover.out -covermode=atomic -coverpkg=./... ./...

test-cluster: env ## Starts MongoDB test cluster. Use env var TEST_MONGODB_IMAGE to set flavor and version. Example: TEST_MONGODB_IMAGE=mongo:3.6 make test-cluster
docker compose up --build -d
./docker/scripts/setup-pbm.sh
./test-setup/scripts/init-psmdb-kerberos.sh
./test-setup/scripts/init-pbm.sh

test-cluster-clean: env ## Stops MongoDB test cluster.
docker compose down --remove-orphans --volumes
78 changes: 61 additions & 17 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ services:
- "mongo-1-3"
- "mongo-1-arbiter"
volumes:
- ./docker/scripts:/scripts
- ./test-setup/scripts:/scripts
environment:
- MONGO1=mongo-1-1
- MONGO2=mongo-1-2
Expand All @@ -63,7 +63,7 @@ services:
mongo-2-2:
container_name: "mongo-2-2"
build:
dockerfile: ./docker/mongodb-auth.dockerfile
dockerfile: test-setup/mongodb-auth.dockerfile
environment:
- MONGO_INITDB_ROOT_USERNAME=${TEST_MONGODB_USERNAME:-admin}
- MONGO_INITDB_ROOT_PASSWORD=${TEST_MONGODB_PASSWORD:-admin}
Expand All @@ -76,7 +76,7 @@ services:
mongo-2-3:
container_name: "mongo-2-3"
build:
dockerfile: ./docker/mongodb-auth.dockerfile
dockerfile: test-setup/mongodb-auth.dockerfile
ports:
- "${TEST_MONGODB_S2_SECONDARY1_PORT:-17005}:27017"
command: mongod --replSet rs2 --port 27017 --oplogSize 16 --auth --keyFile=/opt/keyfile
Expand All @@ -86,7 +86,7 @@ services:
mongo-2-1:
container_name: "mongo-2-1"
build:
dockerfile: ./docker/mongodb-auth.dockerfile
dockerfile: test-setup/mongodb-auth.dockerfile
ports:
- "${TEST_MONGODB_S2_SECONDARY2_PORT:-17006}:27017"
command: mongod --replSet rs2 --port 27017 --oplogSize 16 --auth --keyFile=/opt/keyfile
Expand All @@ -96,7 +96,7 @@ services:
mongo-2-arbiter:
container_name: "mongo-2-arbiter"
build:
dockerfile: ./docker/mongodb-auth.dockerfile
dockerfile: test-setup/mongodb-auth.dockerfile
ports:
- "${TEST_MONGODB_S2_ARBITER:-17012}:27017"
command: mongod --replSet rs2 --port 27017 --oplogSize 16 --auth --keyFile=/opt/keyfile
Expand All @@ -112,8 +112,8 @@ services:
environment:
- PBM_MONGODB_URI=mongodb://admin:admin@mongo-2-1:27017
volumes:
- ./docker/pbm/config:/etc/config
- ./docker/scripts:/scripts
- ./test-setup/pbm/config:/etc/config
- ./test-setup/scripts:/scripts
- pbm-backups:/opt/backups
networks:
- rs2
Expand All @@ -127,8 +127,8 @@ services:
environment:
- PBM_MONGODB_URI=mongodb://admin:admin@mongo-2-2:27017
volumes:
- ./docker/pbm/config:/etc/config
- ./docker/scripts:/scripts
- ./test-setup/pbm/config:/etc/config
- ./test-setup/scripts:/scripts
- pbm-backups:/opt/backups
networks:
- rs2
Expand All @@ -142,8 +142,8 @@ services:
environment:
- PBM_MONGODB_URI=mongodb://admin:admin@mongo-2-3:27017
volumes:
- ./docker/pbm/config:/etc/config
- ./docker/scripts:/scripts
- ./test-setup/pbm/config:/etc/config
- ./test-setup/scripts:/scripts
- pbm-backups:/opt/backups
networks:
- rs2
Expand All @@ -157,7 +157,7 @@ services:
- "mongo-2-3"
- "mongo-2-arbiter"
volumes:
- ./docker/scripts:/scripts
- ./test-setup/scripts:/scripts
environment:
- MONGO1=mongo-2-2
- MONGO2=mongo-2-1
Expand Down Expand Up @@ -210,7 +210,7 @@ services:
- "mongo-cnf-2"
- "mongo-cnf-3"
volumes:
- ./docker/scripts:/scripts
- ./test-setup/scripts:/scripts
environment:
- MONGO1=mongo-cnf-1
- MONGO2=mongo-cnf-2
Expand Down Expand Up @@ -249,7 +249,7 @@ services:
- rs2
- cnf-serv
volumes:
- ./docker/scripts:/scripts
- ./test-setup/scripts:/scripts
environment:
- MONGOS=mongos
- MONGO11=mongo-1-1
Expand All @@ -265,7 +265,7 @@ services:
- PORT2=27017
- PORT3=27017
- VERSION=${TEST_MONGODB_IMAGE}
entrypoint: [ "/scripts/init-shard.sh" ]
entrypoint: [ "/scripts/setup-shard.sh" ]
restart: on-failure:20

standalone:
Expand All @@ -282,12 +282,56 @@ services:
ports:
- "${TEST_MONGODB_STANDALONE_ENCRYPTED_PORT:-27027}:27017"
volumes:
- ./docker/secret/mongodb_secrets.txt:/secret/mongodb_secrets.txt
- ./docker/scripts:/scripts
- ./test-setup/secret/mongodb_secrets.txt:/secret/mongodb_secrets.txt
- ./test-setup/scripts:/scripts
command: /scripts/run-mongodb-encrypted.sh

kerberos:
build:
dockerfile: test-setup/kerberos.dockerfile
container_name: kerberos
hostname: kerberos
environment:
- KRB5_TRACE=/dev/stderr
- MONGO_HOST=psmdb-kerberos
- KERBEROS_HOST=kerberos
- KRB5_CONFIG=/krb5/krb5.conf
- MONGO_KERBEROS_USERNAME=pmm-test
- MONGO_KERBEROS_PASSWORD=password1
depends_on:
- psmdb-kerberos
volumes:
- kerberos-config:/krb5
- ./test-setup/scripts:/scripts
ports:
- "88:88/udp"
entrypoint: [ "sh", "/scripts/setup-krb5-server.sh" ]
healthcheck:
test: [ "CMD", "kadmin.local", "-q", "listprincs" ]
interval: 5s
timeout: 5s
retries: 5

psmdb-kerberos:
image: percona/percona-server-mongodb:8.0
container_name: psmdb-kerberos
hostname: psmdb-kerberos
ports:
- 29017:27017
environment:
- KRB5_KTNAME=/krb5/mongodb.keytab
- KRB5CCNAME=/krb5/krb5cc_0
- KRB5_CONFIG=/krb5/krb5.conf
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=adminpassword
volumes:
- ./test-setup/scripts:/scripts
- kerberos-config:/krb5
command: >
mongod --bind_ip_all --auth --setParameter authenticationMechanisms=GSSAPI,SCRAM-SHA-256
volumes:
pbm-backups:
kerberos-config:

networks:
rs1:
Expand Down
88 changes: 88 additions & 0 deletions exporter/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"net"
"net/http"
"net/http/httptest"
"os"
"strconv"
"strings"
"sync"
Expand All @@ -30,6 +31,7 @@
"github.com/prometheus/client_golang/prometheus/testutil"
"github.com/prometheus/common/promslog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/percona/mongodb_exporter/internal/tu"
)
Expand Down Expand Up @@ -197,6 +199,92 @@
}
}

func generateKerberosConfigFile(t *testing.T) *os.File {
t.Helper()
kerberosHost, err := tu.IPForContainer("kerberos")
require.NoError(t, err)

config := fmt.Sprintf(`
[libdefaults]
default_realm = PERCONATEST.COM
forwardable = true
dns_lookup_realm = false
dns_lookup_kdc = false
ignore_acceptor_hostname = true
rdns = false
[realms]
PERCONATEST.COM = {
kdc_ports = 88
kdc = %s
}
[domain_realm]
.perconatest.com = PERCONATEST.COM
perconatest.com = PERCONATEST.COM
%s = PERCONATEST.COM
`, kerberosHost, kerberosHost)
configFile, err := os.Create(t.TempDir() + "/krb5.conf")
require.NoError(t, err)

_, err = configFile.WriteString(config)
require.NoError(t, err)

return configFile
}

func TestGSSAPIAuth(t *testing.T) {
logger := promslog.New(&promslog.Config{})

mongoHost, err := tu.IPForContainer("psmdb-kerberos")
require.NoError(t, err)

configFile := generateKerberosConfigFile(t)
require.NoError(t, err)
defer func() {
_ = configFile.Close()
_ = os.Setenv("KRB5_CONFIG", "")

Check failure on line 244 in exporter/exporter_test.go

View workflow job for this annotation

GitHub Actions / Lint Check

os.Setenv() could be replaced by t.Setenv() in TestGSSAPIAuth (usetesting)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci-lint] reported by reviewdog 🐶
os.Setenv() could be replaced by t.Setenv() in TestGSSAPIAuth (usetesting)

}()

t.Setenv("KRB5_CONFIG", configFile.Name())
ctx := context.Background()

username := "pmm-test%40PERCONATEST.COM"
password := "password1"
uri := fmt.Sprintf("mongodb://%s:%s@%s/?authSource=$external&authMechanism=GSSAPI",
username,
password,
net.JoinHostPort(mongoHost, "27017"),
)
exporterOpts := &Opts{
URI: uri,
Logger: logger,
CollectAll: true,
GlobalConnPool: false,
DirectConnect: true,
}

client, err := connect(ctx, exporterOpts)
assert.NoError(t, err)

e := New(exporterOpts)
nodeType, _ := getNodeType(ctx, client)
gc := newGeneralCollector(ctx, client, nodeType, e.opts.Logger)
r := e.makeRegistry(ctx, client, new(labelsGetterMock), *e.opts)

expected := strings.NewReader(`
# HELP mongodb_up Whether MongoDB is up.
# TYPE mongodb_up gauge
mongodb_up {cluster_role="mongod"} 1` + "\n")

filter := []string{
"mongodb_up",
}
err = testutil.CollectAndCompare(gc, expected, filter...)
require.NoError(t, err, "mongodb_up metric should be 1")

res := r.Unregister(gc)
assert.True(t, res)
}

func TestMongoUpMetric(t *testing.T) {
ctx := context.Background()

Expand Down
14 changes: 14 additions & 0 deletions internal/tu/testutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,20 @@ func PortForContainer(name string) (string, error) {
return ports[0].HostPort, nil
}

// IPForContainer returns the IP address of a running container.
func IPForContainer(name string) (string, error) {
di, err := InspectContainer(name)
if err != nil {
return "", errors.Wrapf(err, "cannot get error for container %q", name)
}

if len(di) == 0 {
return "", errors.Wrapf(err, "cannot get error for container %q (empty array)", name)
}

return di[0].NetworkSettings.Networks.MongodbExporterDefault.IPAddress, nil
}

// SetupFakeResolver sets up Fake DNS server to resolve SRV records.
func SetupFakeResolver() *mockdns.Server {
p1, err1 := strconv.ParseInt(GetenvDefault("TEST_MONGODB_S1_PRIMARY_PORT", "17001"), 10, 64)
Expand Down
3 changes: 3 additions & 0 deletions test-setup/kerberos.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM alpine
RUN apk add --no-cache bash krb5 krb5-server krb5-pkinit
EXPOSE 88/udp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG TEST_MONGODB_IMAGE=mongo:4.4
FROM ${TEST_MONGODB_IMAGE}
USER root
COPY docker/secret/keyfile /opt/keyfile
COPY test-setup/secret/keyfile /opt/keyfile
RUN chown mongodb /opt/keyfile && chmod 400 /opt/keyfile && mkdir -p /home/mongodb/ && chown mongodb /home/mongodb
RUN mkdir /opt/backups && touch /opt/backups/.gitkeep && chown mongodb /opt/backups
USER mongodb
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions test-setup/scripts/init-psmdb-kerberos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

docker exec --user root psmdb-kerberos bash -c 'chown mongodb:root /krb5/mongodb.keytab'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
docker exec --user root psmdb-kerberos bash -c 'chown mongodb:root /krb5/mongodb.keytab'
docker exec --user root psmdb-kerberos bash -c 'chown mongodb:mongodb /krb5/mongodb.keytab'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's no mongodb group, only the user.

docker exec psmdb-kerberos bash -c '/scripts/setup-krb5-mongo.sh'
Loading
Loading