Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anonymize the host in case of HTTP failure (RabbitMQ Scaler) #2041

Merged
merged 6 commits into from Aug 27, 2021

Conversation

JorTurFer
Copy link
Member

@JorTurFer JorTurFer commented Aug 19, 2021

Signed-off-by: jorturfer jorge_turrado@hotmail.es

This PR replaces the user and the password before log the host in case of failure (RabbitMQ Scaler) in KEDA metrics server

Checklist

  • Commits are signed with Developer Certificate of Origin (DCO - learn more)
  • Tests have been added
  • A PR is opened to update our Helm chart (repo) (if applicable, ie. when deployment manifests are modified)
  • A PR is opened to update the documentation on (repo) (if applicable)
  • Changelog has been updated

Fixes #2040

Signed-off-by: jorturfer <jorge_turrado@hotmail.es>
Signed-off-by: jorturfer <jorge_turrado@hotmail.es>
Copy link
Contributor

@coderanger coderanger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable. We should also probably reach out to the upstream about not including passwords in errors?

// Mask host for log porpouses
func (s *rabbitMQScaler) anonimizeRabbitMQError(err error) error {
errorMessage := fmt.Sprintf("error inspecting rabbitMQ: %s", err)
m1 := regexp.MustCompile(`([^ \/:]+):([^\/:]+)\@`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can move this out into a package level variable + init()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which exactly are you talking about? The regex pattern?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes:

var anonymizePattern *regexp.Regexp

func init() {
  anonymizePattern = regex.MustCompile(...)
}

That means it only compiles the pattern once at startup.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice improvement!!!
I thought that golang cache several regex like other languages do (but I could do it wrong too, I'm learning golang right now)
I will update this with your suggestion asap :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, that explains why you're using a regex :) You could also do this with net/url Parse since it's a URI.

Copy link
Member Author

@JorTurFer JorTurFer Aug 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, I got it! you are proposing to use something like this, right?

parsedURL, _ := url.Parse(s.metadata.host)
errorMessage := strings.ReplaceAllString(fmt.Sprintf("error inspecting rabbitMQ: %s", err),parsedURL.User.Password, "xxxx")

Don't take care about the exact code, I did manually in Github and surely it wrongs, but as idea

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you have is probably better, just do the static precompile of the pattern and I think that's okay give or take if we want to ignore the username.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look when you can please :)
I have applied your proposal :)

@JorTurFer
Copy link
Member Author

JorTurFer commented Aug 19, 2021

Looks reasonable. We should also probably reach out to the upstream about not including passwords in errors?

I'm not total sure if we can avoid it globally or we need to fix it scaler by scaler, I mean, each scaler has its own method to uses the password, in this specific case it inside the host variable, but others could have a password field

@coderanger
Copy link
Contributor

I'm not total sure if we can avoid it globally or we need to fix it scaler by scaler, I mean, each scaler has its own method to uses the password, in this specific case it inside the host variable, but others could have a password field

I mean upstream as in the RabbitMQ library.

@zroubalik zroubalik added this to the v2.5.0 milestone Aug 20, 2021
Signed-off-by: jorturfer <jorge_turrado@hotmail.es>
@@ -21,6 +21,12 @@ import (
kedautil "github.com/kedacore/keda/v2/pkg/util"
)

var anonymizePattern *regexp.Regexp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var anonymizePattern *regexp.Regexp
var rabbitMQAnonymizePattern *regexp.Regexp

Nit, since this is set on a package level.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right :)

Jorge Turrado and others added 2 commits August 23, 2021 18:46
Co-authored-by: Zbynek Roubalik <726523+zroubalik@users.noreply.github.com>

Signed-off-by: Jorge Turrado <jorge.turrado@docplanner.com>
Copy link
Contributor

@arschles arschles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a typo and comment on tests from me

@@ -498,3 +505,9 @@ func getMaximum(q []queueInfo) (int, float64) {
}
return maxMessages, maxRate
}

// Mask host for log porpouses
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Mask host for log porpouses
// Mask host for log purposes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

Comment on lines 417 to 418
meta, _ := parseRabbitMQMetadata(&ScalerConfig{ResolvedEnv: sampleRabbitMqResolvedEnv, TriggerMetadata: metadata, AuthParams: nil})

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
meta, _ := parseRabbitMQMetadata(&ScalerConfig{ResolvedEnv: sampleRabbitMqResolvedEnv, TriggerMetadata: metadata, AuthParams: nil})
meta, err := parseRabbitMQMetadata(&ScalerConfig{ResolvedEnv: sampleRabbitMqResolvedEnv, TriggerMetadata: metadata, AuthParams: nil})
if err != nil {
t.Fatalf("Error parsing metadata (%s)", err)
}

@JorTurFer this is not using assert.NoError(...) because I'm assuming the test should fail immediately on error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test shouldn't fail there never because this part is totally outside from this specific test's scope. That's why the data should be always valid, but I agree, check it is free and can be used in case of failure :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

Co-authored-by: Aaron Schlesinger <aaron@ecomaz.net>

Signed-off-by: jorturfer <jorge_turrado@hotmail.es>
Copy link
Contributor

@arschles arschles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JorTurFer looks great 👍

@JorTurFer
Copy link
Member Author

I'm checking this error (maybe it's an error during any merge because I didn't change anything related with it)
https://github.com/kedacore/keda/runs/3435379660#step:10:43

@arschles
Copy link
Contributor

@JorTurFer odd that the stack trace doesn't include any test code. I haven't tried running this branch locally, so as a pure guess, you could try setting the httpClient in the test rabbitMQ client to something not nil (e.g. the http.DefaultClient)

@JorTurFer
Copy link
Member Author

I'm using dev containers so maybe anything is missing in it :(

root@75bac589934e:/workspaces/keda# make test
/go/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
/go/bin/controller-gen crd:crdVersions=v1 rbac:roleName=keda-operator paths="./..." output:crd:artifacts:config=config/crd/bases
# withTriggers is only used for duck typing so we only need the deepcopy methods
# However operator-sdk generate doesn't appear to have an option for that
# until this issue is fixed: https://github.com/kubernetes-sigs/controller-tools/issues/398
rm config/crd/bases/keda.sh_withtriggers.yaml
gofmt -l -w -s .
go vet ./...
mkdir -p /workspaces/keda/testbin
test -f /workspaces/keda/testbin/setup-envtest.sh || curl -sSLo /workspaces/keda/testbin/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.6.5/hack/setup-envtest.sh
source /workspaces/keda/testbin/setup-envtest.sh; fetch_envtest_tools /workspaces/keda/testbin; setup_envtest_env /workspaces/keda/testbin; go test ./... -covermode=atomic -coverprofile cover.out
/bin/sh: 1: source: not found
/bin/sh: 1: fetch_envtest_tools: not found
/bin/sh: 1: setup_envtest_env: not found
?       github.com/kedacore/keda/v2     [no test files]
?       github.com/kedacore/keda/v2/adapter     [no test files]
?       github.com/kedacore/keda/v2/adapter/generated/openapi   [no test files]
?       github.com/kedacore/keda/v2/api/v1alpha1        [no test files]
Running Suite: Controller Suite
===============================
Random Seed: 1630002544
Will run 10 of 10 specs

STEP: bootstrapping test environment
2021-08-26T18:29:04.085Z        DEBUG   controller-runtime.test-env     starting control plane  {"api server flags": []}
2021-08-26T18:29:04.086Z        ERROR   controller-runtime.test-env     unable to start the controlplane        {"tries": 0, "error": "fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory"}
sigs.k8s.io/controller-runtime/pkg/envtest.(*Environment).Start
        /go/pkg/mod/sigs.k8s.io/controller-runtime@v0.6.5/pkg/envtest/server.go:241
github.com/kedacore/keda/v2/controllers.glob..func3
        /workspaces/keda/controllers/suite_test.go:65
reflect.Value.call
        /usr/local/go/src/reflect/value.go:476
reflect.Value.Call
        /usr/local/go/src/reflect/value.go:337
github.com/onsi/ginkgo/internal/leafnodes.newRunner.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:49
github.com/onsi/ginkgo/internal/leafnodes.(*runner).runAsync.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:86
2021-08-26T18:29:04.095Z        ERROR   controller-runtime.test-env     unable to start the controlplane        {"tries": 1, "error": "fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory"}
sigs.k8s.io/controller-runtime/pkg/envtest.(*Environment).Start
        /go/pkg/mod/sigs.k8s.io/controller-runtime@v0.6.5/pkg/envtest/server.go:241
github.com/kedacore/keda/v2/controllers.glob..func3
        /workspaces/keda/controllers/suite_test.go:65
reflect.Value.call
        /usr/local/go/src/reflect/value.go:476
reflect.Value.Call
        /usr/local/go/src/reflect/value.go:337
github.com/onsi/ginkgo/internal/leafnodes.newRunner.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:49
github.com/onsi/ginkgo/internal/leafnodes.(*runner).runAsync.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:86
2021-08-26T18:29:04.100Z        ERROR   controller-runtime.test-env     unable to start the controlplane        {"tries": 2, "error": "fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory"}
sigs.k8s.io/controller-runtime/pkg/envtest.(*Environment).Start
        /go/pkg/mod/sigs.k8s.io/controller-runtime@v0.6.5/pkg/envtest/server.go:241
github.com/kedacore/keda/v2/controllers.glob..func3
        /workspaces/keda/controllers/suite_test.go:65
reflect.Value.call
        /usr/local/go/src/reflect/value.go:476
reflect.Value.Call
        /usr/local/go/src/reflect/value.go:337
github.com/onsi/ginkgo/internal/leafnodes.newRunner.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:49
github.com/onsi/ginkgo/internal/leafnodes.(*runner).runAsync.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:86
2021-08-26T18:29:04.101Z        ERROR   controller-runtime.test-env     unable to start the controlplane        {"tries": 3, "error": "fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory"}
sigs.k8s.io/controller-runtime/pkg/envtest.(*Environment).Start
        /go/pkg/mod/sigs.k8s.io/controller-runtime@v0.6.5/pkg/envtest/server.go:241
github.com/kedacore/keda/v2/controllers.glob..func3
        /workspaces/keda/controllers/suite_test.go:65
reflect.Value.call
        /usr/local/go/src/reflect/value.go:476
reflect.Value.Call
        /usr/local/go/src/reflect/value.go:337
github.com/onsi/ginkgo/internal/leafnodes.newRunner.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:49
github.com/onsi/ginkgo/internal/leafnodes.(*runner).runAsync.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:86
2021-08-26T18:29:04.113Z        ERROR   controller-runtime.test-env     unable to start the controlplane        {"tries": 4, "error": "fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory"}
sigs.k8s.io/controller-runtime/pkg/envtest.(*Environment).Start
        /go/pkg/mod/sigs.k8s.io/controller-runtime@v0.6.5/pkg/envtest/server.go:241
github.com/kedacore/keda/v2/controllers.glob..func3
        /workspaces/keda/controllers/suite_test.go:65
reflect.Value.call
        /usr/local/go/src/reflect/value.go:476
reflect.Value.Call
        /usr/local/go/src/reflect/value.go:337
github.com/onsi/ginkgo/internal/leafnodes.newRunner.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:49
github.com/onsi/ginkgo/internal/leafnodes.(*runner).runAsync.func1
        /go/pkg/mod/github.com/onsi/ginkgo@v1.16.4/internal/leafnodes/runner.go:86
Failure [0.028 seconds]
[BeforeSuite] BeforeSuite 
/workspaces/keda/controllers/suite_test.go:56

  Unexpected error:
      <*fmt.wrapError | 0xc0004343e0>: {
          msg: "failed to start the controlplane. retried 5 times: fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory",
          err: <*os.PathError | 0xc000b44480>{
              Op: "fork/exec",
              Path: "/usr/local/kubebuilder/bin/etcd",
              Err: <syscall.Errno>0x2,
          },
      }
      failed to start the controlplane. retried 5 times: fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory
  occurred

  /workspaces/keda/controllers/suite_test.go:66
------------------------------


Ran 10 of 0 Specs in 0.029 seconds
FAIL! -- 0 Passed | 10 Failed | 0 Pending | 0 Skipped
You're using deprecated Ginkgo functionality:
=============================================
Ginkgo 2.0 is under active development and will introduce (a small number of) breaking changes.
To learn more, view the migration guide at https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md
To comment, chime in at https://github.com/onsi/ginkgo/issues/711

  You are using a custom reporter.  Support for custom reporters will likely be removed in V2.  Most users were using them to generate junit or teamcity reports and this functionality will be merged into the core reporter.  In addition, Ginkgo 2.0 will support emitting a JSON-formatted report that users can then manipulate to generate custom reports.

  If this change will be impactful to you please leave a comment on https://github.com/onsi/ginkgo/issues/711
  Learn more at: https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md#removed-custom-reporters
  You are passing a Done channel to a test node to test asynchronous behavior.  This is deprecated in Ginkgo V2.  Your test will run synchronously and the timeout will be ignored.
  Learn more at: https://github.com/onsi/ginkgo/blob/v2/docs/MIGRATING_TO_V2.md#removed-async-testing
    /workspaces/keda/controllers/suite_test.go:56

To silence deprecations that can be silenced set the following environment variable:
  ACK_GINKGO_DEPRECATIONS=1.16.4

--- FAIL: TestAPIs (0.03s)
FAIL
coverage: 0.2% of statements
FAIL    github.com/kedacore/keda/v2/controllers 0.106s
?       github.com/kedacore/keda/v2/controllers/util    [no test files]
?       github.com/kedacore/keda/v2/pkg/eventreason     [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/clientset/versioned   [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/clientset/versioned/fake      [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/clientset/versioned/scheme    [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/clientset/versioned/typed/keda/v1alpha1       [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/clientset/versioned/typed/keda/v1alpha1/fake  [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/informers/externalversions    [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/informers/externalversions/internalinterfaces [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/informers/externalversions/keda       [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/informers/externalversions/keda/v1alpha1      [no test files]
?       github.com/kedacore/keda/v2/pkg/generated/listers/keda/v1alpha1 [no test files]
?       github.com/kedacore/keda/v2/pkg/metrics [no test files]
?       github.com/kedacore/keda/v2/pkg/mock/mock_client        [no test files]
?       github.com/kedacore/keda/v2/pkg/mock/mock_scale [no test files]
?       github.com/kedacore/keda/v2/pkg/mock/mock_scaler        [no test files]
?       github.com/kedacore/keda/v2/pkg/mock/mock_scaling       [no test files]
ok      github.com/kedacore/keda/v2/pkg/provider        0.063s  coverage: 48.1% of statements
ok      github.com/kedacore/keda/v2/pkg/scalers 1.200s  coverage: 47.6% of statements
?       github.com/kedacore/keda/v2/pkg/scalers/authentication  [no test files]
ok      github.com/kedacore/keda/v2/pkg/scalers/azure   0.166s  coverage: 36.7% of statements
?       github.com/kedacore/keda/v2/pkg/scalers/externalscaler  [no test files]
?       github.com/kedacore/keda/v2/pkg/scalers/liiklus [no test files]
?       github.com/kedacore/keda/v2/pkg/scalers/liiklus/mocks   [no test files]
?       github.com/kedacore/keda/v2/pkg/scalers/openstack       [no test files]
?       github.com/kedacore/keda/v2/pkg/scalers/openstack/utils [no test files]
ok      github.com/kedacore/keda/v2/pkg/scaling 0.084s  coverage: 13.6% of statements
ok      github.com/kedacore/keda/v2/pkg/scaling/executor        0.128s  coverage: 59.9% of statements
ok      github.com/kedacore/keda/v2/pkg/scaling/resolver        0.110s  coverage: 31.2% of statements
ok      github.com/kedacore/keda/v2/pkg/util    0.024s  coverage: 18.7% of statements
?       github.com/kedacore/keda/v2/version     [no test files]
FAIL
make: *** [Makefile:47: test] Error 1
root@75bac589934e:/workspaces/keda# 

@arschles
Copy link
Contributor

it looks like there are more problems than just a nil ptr panic in that run - it's trying to start up a local cluster from scratch and can't start etcd. you could try installing that, or more likely installing all of kubebuilder first and then re-running maybe

@JorTurFer
Copy link
Member Author

I'm trying again with kubebuilder installed, :) Thanks for the tip
I will update the dev container Dockerfile to add this dependency after this problem is solved

@ahmelsayed
Copy link
Contributor

So it seems that rerunning it passed. I was pretty confused by the panic too, but not sure why it happened.

@arschles
Copy link
Contributor

that's a weird flake. glad the re-run passed @ahmelsayed

@ahmelsayed ahmelsayed enabled auto-merge (squash) August 27, 2021 17:08
@ahmelsayed ahmelsayed merged commit ff19979 into kedacore:main Aug 27, 2021
@JorTurFer JorTurFer deleted the fix/rabbitmq_logger branch August 27, 2021 17:32
nilayasiktoprak pushed a commit to nilayasiktoprak/keda that referenced this pull request Oct 23, 2021
…e#2041)

* Anonimize the host in case of HTTP failure

Signed-off-by: jorturfer <jorge_turrado@hotmail.es>

* Update CHANGELOG and add one extra test case

Signed-off-by: jorturfer <jorge_turrado@hotmail.es>

* Move the regex from the method to a static var

Signed-off-by: jorturfer <jorge_turrado@hotmail.es>

* Update regex var name
Co-authored-by: Zbynek Roubalik <726523+zroubalik@users.noreply.github.com>

Signed-off-by: Jorge Turrado <jorge.turrado@docplanner.com>

* Fix typo and improve test
Co-authored-by: Aaron Schlesinger <aaron@ecomaz.net>

Signed-off-by: jorturfer <jorge_turrado@hotmail.es>

Co-authored-by: Ahmed ElSayed <ahmels@microsoft.com>
Signed-off-by: nilayasiktoprak <nilayasiktoprak@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RabbitMQ Scaler exposes sensible information (HTTP Host) in logs in case of failure
6 participants