feat: explicitly log if each authentication method is enabled (#3599)

feat: explicitly log if each autentication methods is enabled

When the server starts or when the config is reloaded.
See the discussion in: https://github.com/project-zot/zot/pull/3577#issuecomment-3568505810

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
This commit is contained in:
Andrei Aaron
2025-11-27 11:30:14 +02:00
committed by GitHub
parent e068b8dc9f
commit 69c3a0b99b
3 changed files with 179 additions and 2 deletions
+92
View File
@@ -94,6 +94,20 @@ func TestConfigReloader(t *testing.T) {
test.WaitTillServerReady(baseURL)
// verify initial startup authentication logs
initialData, err := os.ReadFile(logFile.Name())
So(err, ShouldBeNil)
So(string(initialData), ShouldContainSubstring, "configuration settings")
// verify authentication methods status messages are present in initial startup
verifyAuthenticationLogs(initialData, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": true,
"basic authentication (LDAP)": false,
"basic authentication (API key)": false,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
content = fmt.Sprintf(`{
"distSpecVersion": "1.1.1",
"storage": {
@@ -156,6 +170,15 @@ func TestConfigReloader(t *testing.T) {
So(string(data), ShouldContainSubstring, "loaded new configuration settings")
So(string(data), ShouldContainSubstring, "\"Users\":[\"alice\"]")
So(string(data), ShouldContainSubstring, "\"Actions\":[\"read\",\"create\",\"update\",\"delete\"]")
// verify authentication methods status messages are present
verifyAuthenticationLogs(data, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": true,
"basic authentication (LDAP)": false,
"basic authentication (API key)": false,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
})
Convey("reload gc config", t, func(c C) {
@@ -211,6 +234,20 @@ func TestConfigReloader(t *testing.T) {
test.WaitTillServerReady(baseURL)
// verify initial startup authentication logs (no auth configured)
initialData, err := os.ReadFile(logFile.Name())
So(err, ShouldBeNil)
So(string(initialData), ShouldContainSubstring, "configuration settings")
// verify authentication methods status messages are present in initial startup
verifyAuthenticationLogs(initialData, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": false,
"basic authentication (LDAP)": false,
"basic authentication (API key)": false,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
content = fmt.Sprintf(`{
"distSpecVersion": "1.1.1",
"storage": {
@@ -263,6 +300,15 @@ func TestConfigReloader(t *testing.T) {
So(string(data), ShouldContainSubstring, "\"Dedupe\":true")
So(string(data), ShouldNotContainSubstring, "\"GC\":false")
So(string(data), ShouldNotContainSubstring, "\"Dedupe\":false")
// verify authentication methods status messages are present
verifyAuthenticationLogs(data, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": false,
"basic authentication (LDAP)": false,
"basic authentication (API key)": false,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
})
Convey("reload sync config", t, func(c C) {
@@ -330,6 +376,20 @@ func TestConfigReloader(t *testing.T) {
test.WaitTillServerReady(baseURL)
// verify initial startup authentication logs (no auth configured)
initialData, err := os.ReadFile(logFile.Name())
So(err, ShouldBeNil)
So(string(initialData), ShouldContainSubstring, "configuration settings")
// verify authentication methods status messages are present in initial startup
verifyAuthenticationLogs(initialData, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": false,
"basic authentication (LDAP)": false,
"basic authentication (API key)": false,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
content = fmt.Sprintf(`{
"distSpecVersion": "1.1.1",
"storage": {
@@ -396,6 +456,15 @@ func TestConfigReloader(t *testing.T) {
So(string(data), ShouldContainSubstring, "\"Prefix\":\"zot-cve-test\"")
So(string(data), ShouldContainSubstring, "\"Regex\":\"tag\"")
So(string(data), ShouldContainSubstring, "\"Semver\":false")
// verify authentication methods status messages are present
verifyAuthenticationLogs(data, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": false,
"basic authentication (LDAP)": false,
"basic authentication (API key)": false,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
})
Convey("reload scrub and CVE config", t, func(c C) {
@@ -453,6 +522,20 @@ func TestConfigReloader(t *testing.T) {
test.WaitTillServerReady(baseURL)
// verify initial startup authentication logs (no auth configured)
initialData, err := os.ReadFile(logFile.Name())
So(err, ShouldBeNil)
So(string(initialData), ShouldContainSubstring, "configuration settings")
// verify authentication methods status messages are present in initial startup
verifyAuthenticationLogs(initialData, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": false,
"basic authentication (LDAP)": false,
"basic authentication (API key)": false,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
content = fmt.Sprintf(`{
"distSpecVersion": "1.1.1",
"storage": {
@@ -509,6 +592,15 @@ func TestConfigReloader(t *testing.T) {
So(string(data), ShouldContainSubstring, "\"UpdateInterval\":18000000000000")
So(string(data), ShouldContainSubstring, "\"Scrub\":null")
So(string(data), ShouldContainSubstring, "\"DBRepository\":\"another/unreachable/trivy/url2\"")
// verify authentication methods status messages are present
verifyAuthenticationLogs(data, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": false,
"basic authentication (LDAP)": false,
"basic authentication (API key)": false,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
// Just verify the new URL appears in the logs to confirm config reload worked and ignore
// the order of json message formatting that can change independent of this functional
+70
View File
@@ -6,6 +6,7 @@ import (
"os"
"path"
"path/filepath"
"strings"
"testing"
"time"
@@ -19,6 +20,53 @@ import (
. "zotregistry.dev/zot/v2/pkg/test/common"
)
// checkAuthLogEntry checks if a log entry with the given message has the expected enabled value.
func checkAuthLogEntry(logData []byte, message string, expectedEnabled bool) bool {
//nolint:modernize // strings.Split is compatible with older Go versions
for _, line := range strings.Split(string(logData), "\n") {
if line == "" {
continue
}
var logEntry map[string]any
if err := json.Unmarshal([]byte(line), &logEntry); err != nil {
continue
}
if msg, ok := logEntry["message"].(string); ok && msg == message {
if enabled, ok := logEntry["enabled"].(bool); ok {
return enabled == expectedEnabled
}
}
}
return false
}
// verifyAuthenticationLogs verifies that all authentication method log messages are present
// and that each method has the expected enabled status.
// expectedAuth maps authentication method names to their expected enabled status (true/false).
func verifyAuthenticationLogs(data []byte, expectedAuth map[string]bool) {
authMethods := []string{
"bearer authentication",
"basic authentication (htpasswd)",
"basic authentication (LDAP)",
"basic authentication (API key)",
"OpenID authentication",
"mutual TLS authentication",
}
// Verify all authentication method messages are present
for _, method := range authMethods {
So(string(data), ShouldContainSubstring, method)
}
// Verify each authentication method has the expected enabled status
for method, expectedEnabled := range expectedAuth {
So(checkAuthLogEntry(data, method, expectedEnabled), ShouldBeTrue)
}
}
func TestServerUsage(t *testing.T) {
oldArgs := os.Args
@@ -2031,6 +2079,17 @@ func TestServeAPIKey(t *testing.T) {
defer os.Remove(logPath) // clean up
So(string(data), ShouldContainSubstring, "\"APIKey\":true")
// verify configuration settings message is present
So(string(data), ShouldContainSubstring, "configuration settings")
// verify authentication methods status messages are present
verifyAuthenticationLogs(data, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": false,
"basic authentication (LDAP)": false,
"basic authentication (API key)": true,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
})
Convey("apikey disabled", t, func(c C) {
@@ -2058,6 +2117,17 @@ func TestServeAPIKey(t *testing.T) {
defer os.Remove(logPath) // clean up
So(string(data), ShouldContainSubstring, "\"APIKey\":false")
// verify configuration settings message is present
So(string(data), ShouldContainSubstring, "configuration settings")
// verify authentication methods status messages are present
verifyAuthenticationLogs(data, map[string]bool{
"bearer authentication": false,
"basic authentication (htpasswd)": false,
"basic authentication (LDAP)": false,
"basic authentication (API key)": false,
"OpenID authentication": false,
"mutual TLS authentication": false,
})
})
}