From 89f58c8e24abd36bf3098da28321dad15a54de9c Mon Sep 17 00:00:00 2001 From: alessandrocapanna Date: Tue, 13 Feb 2024 01:03:25 +0100 Subject: [PATCH] refactor(util): Move maskProxyPassword to pkg/util, update references & tests, introduced MaskProxyPasswordWithKey refactor(util): Move maskProxyPassword to pkg/util, update references & tests, introduced MaskProxyPasswordWithKey --- pkg/minikube/node/config.go | 36 +---------- pkg/minikube/node/config_test.go | 72 ---------------------- pkg/minikube/node/start.go | 4 +- pkg/util/utils.go | 40 ++++++++++++ pkg/util/utils_test.go | 102 +++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 109 deletions(-) delete mode 100644 pkg/minikube/node/config_test.go diff --git a/pkg/minikube/node/config.go b/pkg/minikube/node/config.go index e7f271a6584a..0ef66c916083 100644 --- a/pkg/minikube/node/config.go +++ b/pkg/minikube/node/config.go @@ -21,9 +21,7 @@ import ( "os" "os/exec" "path/filepath" - "regexp" "strconv" - "strings" "sync" "github.com/spf13/viper" @@ -38,46 +36,16 @@ import ( "k8s.io/minikube/pkg/minikube/out/register" "k8s.io/minikube/pkg/minikube/reason" "k8s.io/minikube/pkg/minikube/style" + "k8s.io/minikube/pkg/util" "k8s.io/minikube/pkg/util/lock" ) -func maskProxyPassword(v string) string { - parts := strings.Split(v, "=") - // Is it an attribution variable? - if len(parts) == 2 { - key := strings.ToUpper(parts[0]) - // Is it a proxy setting? - if key == "HTTP_PROXY" || key == "HTTPS_PROXY" { - proxyValue := parts[1] - // Proxy variable values SHOULD have a value like - // https(s):// - proxyAddressParts := strings.Split(proxyValue, "://") - if len(proxyAddressParts) == 2 { - proxyURL := "" - proxyURL = proxyAddressParts[1] - // Let's store the username, the URL and and optional port address - pattern := `([^:]+):.+(@[\w\.]+)(:\d+)?` - regexpPattern := regexp.MustCompile(pattern) - matches := regexpPattern.FindStringSubmatch(proxyURL) - mask := "*****" - if len(matches) == 4 { - proxyValue = fmt.Sprintf("%s://%s:%s%s%s", proxyAddressParts[0], matches[1], mask, matches[2], matches[3]) - } else if len(matches) == 3 { - proxyValue = fmt.Sprintf("%s//%s:%s@%s", proxyAddressParts[0], matches[1], mask, matches[2]) - } - } - v = key + "=" + proxyValue - } - } - return v -} - func showVersionInfo(k8sVersion string, cr cruntime.Manager) { version, _ := cr.Version() register.Reg.SetStep(register.PreparingKubernetes) out.Step(cr.Style(), "Preparing Kubernetes {{.k8sVersion}} on {{.runtime}} {{.runtimeVersion}} ...", out.V{"k8sVersion": k8sVersion, "runtime": cr.Name(), "runtimeVersion": version}) for _, v := range config.DockerOpt { - v = maskProxyPassword(v) + v = util.MaskProxyPasswordWithKey(v) out.Infof("opt {{.docker_option}}", out.V{"docker_option": v}) } for _, v := range config.DockerEnv { diff --git a/pkg/minikube/node/config_test.go b/pkg/minikube/node/config_test.go deleted file mode 100644 index c40df55b50a9..000000000000 --- a/pkg/minikube/node/config_test.go +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package node - -import ( - "testing" -) - -func Test_maskProxyPassword(t *testing.T) { - type dockerOptTest struct { - input string - output string - } - var tests = []dockerOptTest{ - { - input: "cats", - output: "cats", - }, - { - input: "myDockerOption=value", - output: "myDockerOption=value", - }, - { - input: "http_proxy=http://minikube.sigs.k8s.io", - output: "HTTP_PROXY=http://minikube.sigs.k8s.io", - }, - { - input: "https_proxy=http://jdoe@minikube.sigs.k8s.io:8080", - output: "HTTPS_PROXY=http://jdoe@minikube.sigs.k8s.io:8080", - }, - { - input: "https_proxy=https://mary:iam$Fake!password@minikube.sigs.k8s.io:8080", - output: "HTTPS_PROXY=https://mary:*****@minikube.sigs.k8s.io:8080", - }, - { - input: "http_proxy=http://jdoe:%n0tRe@al:Password!@minikube.sigs.k8s.io:8080", - output: "HTTP_PROXY=http://jdoe:*****@minikube.sigs.k8s.io:8080", - }, - { - input: "http_proxy=http://jo@han:n0tRe@al:&Password!@minikube.sigs.k8s.io:8080", - output: "HTTP_PROXY=http://jo@han:*****@minikube.sigs.k8s.io:8080", - }, - { - input: "http_proxy=http://k@r3n!:an0th3erF@akeP@55word@minikube.sigs.k8s.io", - output: "HTTP_PROXY=http://k@r3n!:*****@minikube.sigs.k8s.io", - }, - { - input: "https_proxy=https://fr@ank5t3in:an0th3erF@akeP@55word@minikube.sigs.k8s.io", - output: "HTTPS_PROXY=https://fr@ank5t3in:*****@minikube.sigs.k8s.io", - }, - } - for _, test := range tests { - got := maskProxyPassword(test.input) - if got != test.output { - t.Errorf("maskProxyPassword(\"%v\"): got %v, expected %v", test.input, got, test.output) - } - } -} diff --git a/pkg/minikube/node/start.go b/pkg/minikube/node/start.go index baebf81b9baa..41f9993e4d9f 100755 --- a/pkg/minikube/node/start.go +++ b/pkg/minikube/node/start.go @@ -748,9 +748,7 @@ func validateNetwork(h *host.Host, r command.Runner, imageRepository string) (st k = strings.ToUpper(k) // let's get the key right away to mask password from output // If http(s)_proxy contains password, let's not splatter on the screen if k == "HTTP_PROXY" || k == "HTTPS_PROXY" { - pattern := `//(\w+):\w+@` - regexpPattern := regexp.MustCompile(pattern) - v = regexpPattern.ReplaceAllString(v, "//$1:*****@") + v = util.MaskProxyPassword(v) } out.Infof("{{.key}}={{.value}}", out.V{"key": k, "value": v}) ipExcluded := proxy.IsIPExcluded(ip) // Skip warning if minikube ip is already in NO_PROXY diff --git a/pkg/util/utils.go b/pkg/util/utils.go index a30b9e08e555..21ee798924db 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -21,7 +21,9 @@ import ( "os" "os/user" "path/filepath" + "regexp" "strconv" + "strings" "github.com/blang/semver/v4" units "github.com/docker/go-units" @@ -123,3 +125,41 @@ func RemoveDuplicateStrings(initial []string) []string { } return result } + +// MaskProxyPassword masks the password in a proxy URL +func MaskProxyPassword(proxyURL string) string { + // Proxy variable values SHOULD have a value like + // https(s):// + parts := strings.Split(proxyURL, "://") + if len(parts) == 2 { + proxyAddress := parts[1] + // Let's store the username, the URL and an optional port address + pattern := `([^:]+):.+(@[\w\.]+)(:\d+)?` + re := regexp.MustCompile(pattern) + matches := re.FindStringSubmatch(proxyAddress) + mask := "*****" + switch len(matches) { + case 4: + return fmt.Sprintf("%s://%s:%s%s%s", parts[0], matches[1], mask, matches[2], matches[3]) + case 3: + return fmt.Sprintf("%s//%s:%s@%s", parts[0], matches[1], mask, matches[2]) + } + } + return proxyURL +} + +// MaskProxyPasswordWithKey masks the password in a proxy URL specified by a key-value pair +func MaskProxyPasswordWithKey(v string) string { + parts := strings.Split(v, "=") + // Is it an attribution variable? + if len(parts) == 2 { + key := strings.ToUpper(parts[0]) + // Is it a proxy setting? + if key == "HTTP_PROXY" || key == "HTTPS_PROXY" { + proxyValue := parts[1] + maskedProxyValue := MaskProxyPassword(proxyValue) + return key + "=" + maskedProxyValue + } + } + return v +} diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go index 195a64d258cb..8c8a96faa3dc 100644 --- a/pkg/util/utils_test.go +++ b/pkg/util/utils_test.go @@ -208,3 +208,105 @@ func TestRemoveDuplicateStrings(t *testing.T) { }) } } + +func TestMaskProxyPassword(t *testing.T) { + type dockerOptTest struct { + input string + output string + } + var tests = []dockerOptTest{ + { + input: "cats", + output: "cats", + }, + { + input: "myDockerOption=value", + output: "myDockerOption=value", + }, + { + input: "http://minikube.sigs.k8s.io", + output: "http://minikube.sigs.k8s.io", + }, + { + input: "http://jdoe@minikube.sigs.k8s.io:8080", + output: "http://jdoe@minikube.sigs.k8s.io:8080", + }, + { + input: "https://mary:iam$Fake!password@minikube.sigs.k8s.io:8080", + output: "https://mary:*****@minikube.sigs.k8s.io:8080", + }, + { + input: "http://jdoe:%n0tRe@al:Password!@minikube.sigs.k8s.io:8080", + output: "http://jdoe:*****@minikube.sigs.k8s.io:8080", + }, + { + input: "http://jo@han:n0tRe@al:&Password!@minikube.sigs.k8s.io:8080", + output: "http://jo@han:*****@minikube.sigs.k8s.io:8080", + }, + { + input: "http://k@r3n!:an0th3erF@akeP@55word@minikube.sigs.k8s.io", + output: "http://k@r3n!:*****@minikube.sigs.k8s.io", + }, + { + input: "https://fr@ank5t3in:an0th3erF@akeP@55word@minikube.sigs.k8s.io", + output: "https://fr@ank5t3in:*****@minikube.sigs.k8s.io", + }, + } + for _, test := range tests { + got := MaskProxyPassword(test.input) + if got != test.output { + t.Errorf("MaskProxyPassword(\"%v\"): got %v, expected %v", test.input, got, test.output) + } + } +} + +func TestMaskProxyPasswordWithKey(t *testing.T) { + type dockerOptTest struct { + input string + output string + } + var tests = []dockerOptTest{ + { + input: "cats", + output: "cats", + }, + { + input: "myDockerOption=value", + output: "myDockerOption=value", + }, + { + input: "http_proxy=http://minikube.sigs.k8s.io", + output: "HTTP_PROXY=http://minikube.sigs.k8s.io", + }, + { + input: "https_proxy=http://jdoe@minikube.sigs.k8s.io:8080", + output: "HTTPS_PROXY=http://jdoe@minikube.sigs.k8s.io:8080", + }, + { + input: "https_proxy=https://mary:iam$Fake!password@minikube.sigs.k8s.io:8080", + output: "HTTPS_PROXY=https://mary:*****@minikube.sigs.k8s.io:8080", + }, + { + input: "http_proxy=http://jdoe:%n0tRe@al:Password!@minikube.sigs.k8s.io:8080", + output: "HTTP_PROXY=http://jdoe:*****@minikube.sigs.k8s.io:8080", + }, + { + input: "http_proxy=http://jo@han:n0tRe@al:&Password!@minikube.sigs.k8s.io:8080", + output: "HTTP_PROXY=http://jo@han:*****@minikube.sigs.k8s.io:8080", + }, + { + input: "http_proxy=http://k@r3n!:an0th3erF@akeP@55word@minikube.sigs.k8s.io", + output: "HTTP_PROXY=http://k@r3n!:*****@minikube.sigs.k8s.io", + }, + { + input: "https_proxy=https://fr@ank5t3in:an0th3erF@akeP@55word@minikube.sigs.k8s.io", + output: "HTTPS_PROXY=https://fr@ank5t3in:*****@minikube.sigs.k8s.io", + }, + } + for _, test := range tests { + got := MaskProxyPasswordWithKey(test.input) + if got != test.output { + t.Errorf("MaskProxyPasswordWithKey(\"%v\"): got %v, expected %v", test.input, got, test.output) + } + } +}