From 6929a5512f008a6c1ed7861a7cffb67b3c8c4ff2 Mon Sep 17 00:00:00 2001 From: Dario Meloni Date: Thu, 6 Mar 2025 15:12:41 +0100 Subject: [PATCH] Reset RC DB in case an agent changes the RC url In case a database is configured from data from a different datacenter (or url to be completely generic) the agent is forced to reset the database like if the version of the agent changed or the API Key changed. This allows users to change the site without having to manually delete the cached configurations. --- pkg/config/remote/service/service.go | 4 +-- pkg/config/remote/service/util.go | 24 ++++++++-------- pkg/config/remote/service/util_test.go | 38 +++++++++++++++++++++----- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/pkg/config/remote/service/service.go b/pkg/config/remote/service/service.go index d4d27278e39e3..6358257bb2af5 100644 --- a/pkg/config/remote/service/service.go +++ b/pkg/config/remote/service/service.go @@ -415,7 +415,7 @@ func NewService(cfg model.Reader, rcType, baseRawURL, hostname string, tagsGette databaseFilePath = options.databaseFilePath } dbPath := path.Join(databaseFilePath, options.databaseFileName) - db, err := openCacheDB(dbPath, agentVersion, authKeys.apiKey) + db, err := openCacheDB(dbPath, agentVersion, authKeys.apiKey, baseURL.String()) if err != nil { return nil, err } @@ -1053,7 +1053,7 @@ type HTTPClient struct { // An HTTPClient must be closed via HTTPClient.Close() before creating a new one. func NewHTTPClient(runPath, site, apiKey, agentVersion string) (*HTTPClient, error) { dbPath := path.Join(runPath, "remote-config-cdn.db") - db, err := openCacheDB(dbPath, agentVersion, apiKey) + db, err := openCacheDB(dbPath, agentVersion, apiKey, site) if err != nil { return nil, err } diff --git a/pkg/config/remote/service/util.go b/pkg/config/remote/service/util.go index cfffdd2505e13..abe4ae5659153 100644 --- a/pkg/config/remote/service/util.go +++ b/pkg/config/remote/service/util.go @@ -37,6 +37,7 @@ type AgentMetadata struct { Version string `json:"version"` APIKeyHash string `json:"api-key-hash"` CreationTime time.Time `json:"creation-time"` + URL string `json:"url"` } // hashAPIKey hashes the API key to avoid storing it in plain text using SHA256 @@ -44,7 +45,7 @@ func hashAPIKey(apiKey string) string { return fmt.Sprintf("%x", sha256.Sum256([]byte(apiKey))) } -func recreate(path string, agentVersion string, apiKeyHash string) (*bbolt.DB, error) { +func recreate(path string, agentVersion string, apiKeyHash string, url string) (*bbolt.DB, error) { log.Infof("Clear remote configuration database") _, err := os.Stat(path) if err != nil && !os.IsNotExist(err) { @@ -69,10 +70,10 @@ func recreate(path string, agentVersion string, apiKeyHash string) (*bbolt.DB, e } return nil, err } - return db, addMetadata(db, agentVersion, apiKeyHash) + return db, addMetadata(db, agentVersion, apiKeyHash, url) } -func addMetadata(db *bbolt.DB, agentVersion string, apiKeyHash string) error { +func addMetadata(db *bbolt.DB, agentVersion string, apiKeyHash string, url string) error { return db.Update(func(tx *bbolt.Tx) error { bucket, err := tx.CreateBucketIfNotExists([]byte(metaBucket)) if err != nil { @@ -82,6 +83,7 @@ func addMetadata(db *bbolt.DB, agentVersion string, apiKeyHash string) error { Version: agentVersion, APIKeyHash: apiKeyHash, CreationTime: time.Now(), + URL: url, }) if err != nil { return err @@ -90,7 +92,7 @@ func addMetadata(db *bbolt.DB, agentVersion string, apiKeyHash string) error { }) } -func openCacheDB(path string, agentVersion string, apiKey string) (*bbolt.DB, error) { +func openCacheDB(path string, agentVersion string, apiKey string, url string) (*bbolt.DB, error) { apiKeyHash := hashAPIKey(apiKey) db, err := bbolt.Open(path, 0600, &bbolt.Options{ @@ -101,10 +103,10 @@ func openCacheDB(path string, agentVersion string, apiKey string) (*bbolt.DB, er return nil, fmt.Errorf("rc db is locked. Please check if another instance of the agent is running and using the same `run_path` parameter") } log.Infof("Failed to open remote configuration database %s", err) - return recreate(path, agentVersion, apiKeyHash) + return recreate(path, agentVersion, apiKeyHash, url) } - metadata := new(AgentMetadata) + var metadata AgentMetadata err = db.View(func(tx *bbolt.Tx) error { bucket := tx.Bucket([]byte(metaBucket)) if bucket == nil { @@ -116,7 +118,7 @@ func openCacheDB(path string, agentVersion string, apiKey string) (*bbolt.DB, er log.Infof("Missing meta file in meta bucket") return err } - err = json.Unmarshal(metadataBytes, metadata) + err = json.Unmarshal(metadataBytes, &metadata) if err != nil { log.Infof("Invalid metadata") return err @@ -126,13 +128,13 @@ func openCacheDB(path string, agentVersion string, apiKey string) (*bbolt.DB, er if err != nil { _ = db.Close() log.Infof("Failed to validate remote configuration database %s", err) - return recreate(path, agentVersion, apiKeyHash) + return recreate(path, agentVersion, apiKeyHash, url) } - if metadata.Version != agentVersion || metadata.APIKeyHash != apiKeyHash { - log.Infof("Different agent version or API Key detected") + if metadata.Version != agentVersion || metadata.APIKeyHash != apiKeyHash || metadata.URL != url { + log.Infof("Different agent version, API Key or URL detected") _ = db.Close() - return recreate(path, agentVersion, apiKeyHash) + return recreate(path, agentVersion, apiKeyHash, url) } return db, nil diff --git a/pkg/config/remote/service/util_test.go b/pkg/config/remote/service/util_test.go index 7b2883f134974..b4197e0dca227 100644 --- a/pkg/config/remote/service/util_test.go +++ b/pkg/config/remote/service/util_test.go @@ -22,6 +22,7 @@ import ( ) const apiKey = "37d58c60b8ac337293ce2ca6b28b19eb" +const rcURL = "dd-rc-url" func TestAuthKeys(t *testing.T) { tests := []struct { @@ -128,7 +129,7 @@ func TestRemoteConfigNewDB(t *testing.T) { defer os.RemoveAll(dir) // should add the version to newly created databases - db, err := openCacheDB(filepath.Join(dir, "remote-config.db"), "9.9.9", apiKey) + db, err := openCacheDB(filepath.Join(dir, "remote-config.db"), "9.9.9", apiKey, rcURL) require.NoError(t, err) defer db.Close() @@ -144,14 +145,14 @@ func TestRemoteConfigChangedAPIKey(t *testing.T) { defer os.RemoveAll(dir) // should add the version to newly created databases - db0, err := openCacheDB(filepath.Join(dir, "remote-config.db"), "9.9.9", apiKey) + db0, err := openCacheDB(filepath.Join(dir, "remote-config.db"), "9.9.9", apiKey, rcURL) require.NoError(t, err) defer db0.Close() metadata0, err := getMetadata(db0) require.NoError(t, err) db0.Close() - db1, err := openCacheDB(filepath.Join(dir, "remote-config.db"), "9.9.9", apiKey+"-new") + db1, err := openCacheDB(filepath.Join(dir, "remote-config.db"), "9.9.9", apiKey+"-new", rcURL) require.NoError(t, err) defer db1.Close() metadata1, err := getMetadata(db1) @@ -167,7 +168,7 @@ func TestRemoteConfigReopenNoVersionChange(t *testing.T) { defer os.RemoveAll(dir) // should add the version to newly created databases - db, err := openCacheDB(filepath.Join(dir, "remote-config.db"), agentVersion, apiKey) + db, err := openCacheDB(filepath.Join(dir, "remote-config.db"), agentVersion, apiKey, rcURL) require.NoError(t, err) metadata, err := getMetadata(db) @@ -177,7 +178,7 @@ func TestRemoteConfigReopenNoVersionChange(t *testing.T) { require.NoError(t, addData(db)) require.NoError(t, db.Close()) - db, err = openCacheDB(filepath.Join(dir, "remote-config.db"), agentVersion, apiKey) + db, err = openCacheDB(filepath.Join(dir, "remote-config.db"), agentVersion, apiKey, rcURL) require.NoError(t, err) defer db.Close() require.NoError(t, checkData(db)) @@ -191,7 +192,7 @@ func TestRemoteConfigOldDB(t *testing.T) { dbPath := filepath.Join(dir, "remote-config.db") // create database with current version - db, err := openCacheDB(dbPath, agentVersion, apiKey) + db, err := openCacheDB(dbPath, agentVersion, apiKey, rcURL) require.NoError(t, err) require.NoError(t, addData(db)) @@ -207,7 +208,7 @@ func TestRemoteConfigOldDB(t *testing.T) { require.NoError(t, db.Close()) // reopen database - db, err = openCacheDB(dbPath, agentVersion, apiKey) + db, err = openCacheDB(dbPath, agentVersion, apiKey, rcURL) require.NoError(t, err) // check version after the database opens @@ -217,3 +218,26 @@ func TestRemoteConfigOldDB(t *testing.T) { assert.Equal(t, agentVersion, parsedMeta.Version) assert.Error(t, checkData(db)) } + +func TestRemoteConfigChangedURL(t *testing.T) { + dir, err := os.MkdirTemp("", "remote-config-test") + require.NoError(t, err) + defer os.RemoveAll(dir) + + // should add the version to newly created databases + db0, err := openCacheDB(filepath.Join(dir, "remote-config.db"), "9.9.9", apiKey, rcURL) + require.NoError(t, err) + defer db0.Close() + metadata0, err := getMetadata(db0) + require.NoError(t, err) + db0.Close() + + db1, err := openCacheDB(filepath.Join(dir, "remote-config.db"), "9.9.9", apiKey, rcURL+"-new") + require.NoError(t, err) + defer db1.Close() + metadata1, err := getMetadata(db1) + require.NoError(t, err) + + require.NotEqual(t, metadata0.URL, metadata1.URL) + require.NotEqual(t, metadata0.CreationTime, metadata1.CreationTime) +}