From 93a73cbc14788d0863bda717dc8ab42498731a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Sabat=C3=A9=20Sol=C3=A0?= Date: Thu, 3 Oct 2024 09:40:23 +0200 Subject: [PATCH 1/3] internal: Add a ServerType to the configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows the internal configuration of SUSEConnect to understand on which kind of server it's trying to connect. This is relevant in case we want to perform some operations on SCC and some others on RMT. Signed-off-by: Miquel Sabaté Solà --- cmd/suseconnect/suseconnect.go | 6 +++--- internal/connect/config.go | 31 +++++++++++++++++++++++++++---- internal/connect/config_test.go | 2 ++ internal/connect/connection.go | 12 ++++++++++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/cmd/suseconnect/suseconnect.go b/cmd/suseconnect/suseconnect.go index 04016ff1..a1b9537b 100644 --- a/cmd/suseconnect/suseconnect.go +++ b/cmd/suseconnect/suseconnect.go @@ -261,11 +261,11 @@ func main() { fmt.Print(string(out)) } else { - if instanceDataFile != "" && connect.URLDefault() { + if instanceDataFile != "" && connect.CFG.IsScc() { fmt.Print("Please use --instance-data only in combination ") fmt.Print("with --url pointing to your RMT or SMT server\n") os.Exit(1) - } else if connect.URLDefault() && token == "" && product.value == "" { + } else if connect.CFG.IsScc() && token == "" && product.value == "" { flag.Usage() os.Exit(1) } else if isSumaManaged() { @@ -316,7 +316,7 @@ func main() { } func maybeBrokenSMTError() error { - if !connect.URLDefault() && !connect.UpToDate() { + if !connect.CFG.IsScc() && !connect.UpToDate() { return fmt.Errorf("Your Registration Proxy server doesn't support this function. " + "Please update it and try again.") } diff --git a/internal/connect/config.go b/internal/connect/config.go index 53517039..9cafb257 100644 --- a/internal/connect/config.go +++ b/internal/connect/config.go @@ -26,6 +26,15 @@ const ( defaultEnableSystemUptimeTracking = false ) +// Kinds of servers which are supported by SUSEConnect. +type ServerType uint64 + +const ( + Unknown ServerType = iota + Scc + Rmt +) + // Config holds the config! type Config struct { Path string @@ -40,10 +49,10 @@ type Config struct { Email string `json:"email"` AutoAgreeEULA bool EnableSystemUptimeTracking bool - - NoZypperRefresh bool - AutoImportRepoKeys bool - SkipServiceInstall bool + ServerType ServerType + NoZypperRefresh bool + AutoImportRepoKeys bool + SkipServiceInstall bool } // NewConfig returns a Config with defaults @@ -123,6 +132,11 @@ func parseConfig(r io.Reader, c *Config) { util.Debug.Printf("Cannot parse line \"%s\" from %s", line, c.Path) } } + + // Set the server type depending on what we parsed from the configuration. + if c.BaseURL == defaultBaseURL { + c.ServerType = Scc + } } // MergeJSON merges attributes of jsn that match Config fields @@ -131,3 +145,12 @@ func (c *Config) MergeJSON(jsn string) error { util.Debug.Printf("Merged options: %+v", c) return err } + +// Returns true if we detected that the configuration points to SCC. +// +// NOTE: this will be reliable if the configuration file already pointed to SCC, +// but it might need to be filled in upon HTTP requests to further guess if it's +// a Glue instance running on localhost or similar developer-only scenarios. +func (c *Config) IsScc() bool { + return c.ServerType == Scc +} diff --git a/internal/connect/config_test.go b/internal/connect/config_test.go index a01ddcf5..ae91fd86 100644 --- a/internal/connect/config_test.go +++ b/internal/connect/config_test.go @@ -57,12 +57,14 @@ func TestSaveLoad(t *testing.T) { c1 := NewConfig() c1.Path = path c1.AutoAgreeEULA = true + c1.ServerType = Unknown if err := c1.Save(); err != nil { t.Fatalf("Unable to write config: %s", err) } c2 := NewConfig() c2.Path = path c2.Load() + c2.ServerType = Unknown if !reflect.DeepEqual(c1, c2) { t.Errorf("got %+v, expected %+v", c2, c1) } diff --git a/internal/connect/connection.go b/internal/connect/connection.go index 615158a0..188288e3 100644 --- a/internal/connect/connection.go +++ b/internal/connect/connection.go @@ -155,6 +155,18 @@ func callHTTP(verb, path string, body []byte, query map[string]string, auth auth } defer resp.Body.Close() + // If we failed to detect which server type was being used when loading the + // configuration, we can actually further inspect it via some of the headers + // that are returned by Glue vs RMT. Hence, if the server type is unknown, + // make an educated guess now. + if CFG.ServerType == Unknown { + if api := resp.Header.Get("Scc-Api-Version"); api == sccAPIVersion { + CFG.ServerType = Scc + } else { + CFG.ServerType = Rmt + } + } + // For each request SCC might update the System token for a given system. // This will be given through the `System-Token` header, so we have to grab // this here and store it for the next request. From 77d734fa4693bf68580e0087b252f8ba9f0605d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Sabat=C3=A9=20Sol=C3=A0?= Date: Thu, 3 Oct 2024 09:41:32 +0200 Subject: [PATCH 2/3] internal: Skip the docker auth generation on RMT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes bsc#1231185 Signed-off-by: Miquel Sabaté Solà --- cmd/suseconnect/suseconnect.go | 2 +- internal/connect/client.go | 17 +++++++++-------- internal/connect/config.go | 32 +++++++++++++++++++++++++++----- internal/connect/config_test.go | 4 ++-- internal/connect/connection.go | 6 +++--- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/cmd/suseconnect/suseconnect.go b/cmd/suseconnect/suseconnect.go index a1b9537b..537b291d 100644 --- a/cmd/suseconnect/suseconnect.go +++ b/cmd/suseconnect/suseconnect.go @@ -135,7 +135,7 @@ func main() { fmt.Printf("URL \"%s\" not valid: %s\n", baseURL, err) os.Exit(1) } - connect.CFG.BaseURL = baseURL + connect.CFG.ChangeBaseURL(baseURL) writeConfig = true } if fsRoot != "" { diff --git a/internal/connect/client.go b/internal/connect/client.go index 356c7e20..eb1ea2bb 100644 --- a/internal/connect/client.go +++ b/internal/connect/client.go @@ -387,8 +387,14 @@ func announceOrUpdate(quiet bool) error { } if err = cred.CreateCredentials(login, password, "", cred.SystemCredentialsPath(CFG.FsRoot)); err == nil { - util.Debug.Print("\nAdding SUSE registry system authentication configuration ...") - setupRegistryAuthentication(login, password) + // If the user is authenticated against the SCC, then setup the Docker + // Registry configuration for the system. Otherwise, if the system is + // behind a proxy (e.g. RMT), this step might fail and it's best to + // avoid it (see bsc#1231185). + if CFG.IsScc() { + util.Debug.Print("\nAdding SUSE registry system authentication configuration ...") + setupRegistryAuthentication(login, password) + } } return err } @@ -405,14 +411,9 @@ func UpToDate() bool { return upToDate() } -// URLDefault returns true if using https://scc.suse.com -func URLDefault() bool { - return CFG.BaseURL == defaultBaseURL -} - func printInformation(action string, jsonOutput bool) { var server string - if URLDefault() { + if CFG.IsScc() { server = "SUSE Customer Center" } else { server = "registration proxy " + CFG.BaseURL diff --git a/internal/connect/config.go b/internal/connect/config.go index 9cafb257..0840e896 100644 --- a/internal/connect/config.go +++ b/internal/connect/config.go @@ -30,9 +30,9 @@ const ( type ServerType uint64 const ( - Unknown ServerType = iota - Scc - Rmt + UnknownProvider ServerType = iota + SccProvider + RmtProvider ) // Config holds the config! @@ -93,6 +93,12 @@ func (c Config) Save() error { func (c *Config) Load() { f, err := os.Open(c.Path) if err != nil { + // If we failed at parsing the configuration, we can make further + // assumptions based on the base URL being used. + if c.BaseURL == defaultBaseURL { + c.ServerType = SccProvider + } + util.Debug.Println(err) return } @@ -101,6 +107,22 @@ func (c *Config) Load() { util.Debug.Printf("Config after parsing: %+v", c) } +// Change the base url to be used when talking to the server to the one being +// provided. +func (c *Config) ChangeBaseURL(baseUrl string) { + c.BaseURL = baseUrl + + // When making an explicit change of the URL, we can further detect which + // kind of server we are dealing with. For now, let's keep it simple, and if + // it's the defaultBaseURL then we assume it to be SccProvider, otherwise + // RmtProvider. + if c.BaseURL == defaultBaseURL { + c.ServerType = SccProvider + } else { + c.ServerType = RmtProvider + } +} + func parseConfig(r io.Reader, c *Config) { scanner := bufio.NewScanner(r) for scanner.Scan() { @@ -135,7 +157,7 @@ func parseConfig(r io.Reader, c *Config) { // Set the server type depending on what we parsed from the configuration. if c.BaseURL == defaultBaseURL { - c.ServerType = Scc + c.ServerType = SccProvider } } @@ -152,5 +174,5 @@ func (c *Config) MergeJSON(jsn string) error { // but it might need to be filled in upon HTTP requests to further guess if it's // a Glue instance running on localhost or similar developer-only scenarios. func (c *Config) IsScc() bool { - return c.ServerType == Scc + return c.ServerType == SccProvider } diff --git a/internal/connect/config_test.go b/internal/connect/config_test.go index ae91fd86..4a311fe5 100644 --- a/internal/connect/config_test.go +++ b/internal/connect/config_test.go @@ -57,14 +57,14 @@ func TestSaveLoad(t *testing.T) { c1 := NewConfig() c1.Path = path c1.AutoAgreeEULA = true - c1.ServerType = Unknown + c1.ServerType = UnknownProvider if err := c1.Save(); err != nil { t.Fatalf("Unable to write config: %s", err) } c2 := NewConfig() c2.Path = path c2.Load() - c2.ServerType = Unknown + c2.ServerType = UnknownProvider if !reflect.DeepEqual(c1, c2) { t.Errorf("got %+v, expected %+v", c2, c1) } diff --git a/internal/connect/connection.go b/internal/connect/connection.go index 188288e3..03ad0231 100644 --- a/internal/connect/connection.go +++ b/internal/connect/connection.go @@ -159,11 +159,11 @@ func callHTTP(verb, path string, body []byte, query map[string]string, auth auth // configuration, we can actually further inspect it via some of the headers // that are returned by Glue vs RMT. Hence, if the server type is unknown, // make an educated guess now. - if CFG.ServerType == Unknown { + if CFG.ServerType == UnknownProvider { if api := resp.Header.Get("Scc-Api-Version"); api == sccAPIVersion { - CFG.ServerType = Scc + CFG.ServerType = SccProvider } else { - CFG.ServerType = Rmt + CFG.ServerType = RmtProvider } } From 21e14d007a264cf60ec9a9f3fbbf1438571ec668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miquel=20Sabat=C3=A9=20Sol=C3=A0?= Date: Mon, 28 Oct 2024 09:55:37 +0100 Subject: [PATCH 3/3] Only send labels if targetting SCC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miquel Sabaté Solà --- cmd/suseconnect/suseconnect.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/suseconnect/suseconnect.go b/cmd/suseconnect/suseconnect.go index 537b291d..0d21157e 100644 --- a/cmd/suseconnect/suseconnect.go +++ b/cmd/suseconnect/suseconnect.go @@ -298,8 +298,9 @@ func main() { } } - // After successful registration we try to set labels - if len(labels) > 0 { + // After successful registration we try to set labels if we are + // targetting SCC. + if connect.CFG.IsScc() && len(labels) > 0 { err := connect.AssignAndCreateLabels(strings.Split(labels, ",")) if err != nil && !jsonFlag { fmt.Printf("Problem setting labels for this system: %s\n", err)