mirror of
https://github.com/project-zot/zot.git
synced 2026-06-18 05:28:07 +08:00
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:
+17
-2
@@ -283,6 +283,15 @@ func (c *Controller) Init() error {
|
||||
// print the current configuration, but strip secrets
|
||||
c.Log.Info().Interface("params", c.Config.Sanitize()).Msg("configuration settings")
|
||||
|
||||
// log authentication methods status
|
||||
authConfig := c.Config.CopyAuthConfig()
|
||||
c.Log.Info().Bool("enabled", authConfig.IsBearerAuthEnabled()).Msg("bearer authentication")
|
||||
c.Log.Info().Bool("enabled", authConfig.IsHtpasswdAuthEnabled()).Msg("basic authentication (htpasswd)")
|
||||
c.Log.Info().Bool("enabled", authConfig.IsLdapAuthEnabled()).Msg("basic authentication (LDAP)")
|
||||
c.Log.Info().Bool("enabled", authConfig.IsAPIKeyEnabled()).Msg("basic authentication (API key)")
|
||||
c.Log.Info().Bool("enabled", authConfig.IsOpenIDAuthEnabled()).Msg("OpenID authentication")
|
||||
c.Log.Info().Bool("enabled", c.Config.IsMTLSAuthEnabled()).Msg("mutual TLS authentication")
|
||||
|
||||
// print the current runtime environment
|
||||
DumpRuntimeParams(c.Log)
|
||||
|
||||
@@ -310,8 +319,6 @@ func (c *Controller) Init() error {
|
||||
c.InitCVEInfo()
|
||||
c.Healthz.Started()
|
||||
|
||||
// Get auth config safely
|
||||
authConfig := c.Config.CopyAuthConfig()
|
||||
if authConfig.IsHtpasswdAuthEnabled() {
|
||||
err := c.HTPasswdWatcher.ChangeFile(authConfig.HTPasswd.Path)
|
||||
if err != nil {
|
||||
@@ -435,6 +442,14 @@ func (c *Controller) LoadNewConfig(newConfig *config.Config) {
|
||||
|
||||
c.Log.Info().Interface("reloaded params", c.Config.Sanitize()).
|
||||
Msg("loaded new configuration settings")
|
||||
|
||||
// log authentication methods status
|
||||
c.Log.Info().Bool("enabled", authConfig.IsBearerAuthEnabled()).Msg("bearer authentication")
|
||||
c.Log.Info().Bool("enabled", authConfig.IsHtpasswdAuthEnabled()).Msg("basic authentication (htpasswd)")
|
||||
c.Log.Info().Bool("enabled", authConfig.IsLdapAuthEnabled()).Msg("basic authentication (LDAP)")
|
||||
c.Log.Info().Bool("enabled", authConfig.IsAPIKeyEnabled()).Msg("basic authentication (API key)")
|
||||
c.Log.Info().Bool("enabled", authConfig.IsOpenIDAuthEnabled()).Msg("OpenID authentication")
|
||||
c.Log.Info().Bool("enabled", c.Config.IsMTLSAuthEnabled()).Msg("mutual TLS authentication")
|
||||
}
|
||||
|
||||
func (c *Controller) Shutdown() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user