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

[WIP] storage/remote: use YAML data instead of JSON for MD5 hash #6456

Closed

Conversation

simonpasquier
Copy link
Member

The configuration structs don't have JSON field tags so there's no guarantee that different configurations produce different JSON data. This isn't the case for YAML.

This is similar to #6455.

@brian-brazil
Copy link
Contributor

Huh? I don't see how that could be an issue.

That we're not considering secrets is an issue.

@simonpasquier simonpasquier force-pushed the fix-md5-remote-write branch 2 times, most recently from 3896e4a to b99d365 Compare December 12, 2019 15:15
@simonpasquier
Copy link
Member Author

Huh? I don't see how that could be an issue.

relabel.Regexp are always marshaled to {}.

That we're not considering secrets is an issue.

True. I've added a unit test to catch this.

testutil.Equals(t, 3, len(s.queues))

testutil.Assert(t, q0 == s.queues[0], "Pointer of unchanged queue should have remained the same")
testutil.Assert(t, q1 != s.queues[1], "If the index changed, the queue should be stopped and recreated.")
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't the message here be around changing the bearer token should restart the queue?

@brian-brazil
Copy link
Contributor

relabel.Regexp are always marshaled to {}.

I don't see what that has to do with field tags.

Copy link
Member

@cstyan cstyan left a comment

Choose a reason for hiding this comment

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

I don't have opinions on the yaml vs. json

testutil.Equals(t, 3, len(s.queues))

testutil.Assert(t, q == s.queues[1], "Pointer of unchanged queue should have remained the same")
testutil.Assert(t, q0 != s.queues[0], "If the index changed, the queue should be stopped and recreated.")
Copy link
Member

Choose a reason for hiding this comment

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

The message here isn't helpful in my opinion. What index are you referring to? The index of the queue's config in the overall RemoteWriteConfigs array? Rearranging those should no longer result in queue restarts. So I think this (and similar lines) should mention which part of the config was changed, and that when changing that field we expect to see a queue restart.

storage/remote/write_test.go Outdated Show resolved Hide resolved
@johncming
Copy link
Contributor

@simonpasquier

the master branch has updated which use hash instead of index. #6043

@simonpasquier
Copy link
Member Author

As @johncming pointed out, I need to rebase the change but from a quick look, the issues should still exist.

@cstyan
Copy link
Member

cstyan commented Dec 17, 2019

As @johncming pointed out, I need to rebase the change but from a quick look, the issues should still exist.

My bad, I pointed out that the test failure messages should be updated but that PR had only been merged a few hours earlier. It had been open long enough that I just had it in my head that the index to hash change was already merged.

@jutley
Copy link

jutley commented Jan 3, 2020

I've run into this bug in two ways, both with regards to write_relabel_configs:

  1. When the only difference between two remote_write configs is a regex, they produce the same hash, and Prometheus refuses to start. This is new in 2.15.
  2. When a remote_write is updated and the only change is in its regex, the new rules never take effect. This was an issue before 2.15.

I'd really like to see this PR merged. We can create hacky workarounds, but would prefer not to.

@csmarchbanks
Copy link
Member

@simonpasquier Do you think you will have an opportunity to rebase this soon?

@simonpasquier simonpasquier changed the title storage/remote: use YAML data instead of JSON for MD5 hash [WIP] storage/remote: use YAML data instead of JSON for MD5 hash Jan 15, 2020
@simonpasquier
Copy link
Member Author

I've rebased my change but it only includes the test that demonstrates the issue. I don't have an immediate solution though.

@csmarchbanks
Copy link
Member

I thought just changing the hashes to use YAML instead of JSON fixed it? Did those changes disappear?

@simonpasquier
Copy link
Member Author

It does fix the issue in a way but it breaks in another. More precisely secret fields (bearer tokens for instance) are marshaled as <secret> in YAML so this test won't pass if we switch from JSON to YAML.

@jutley
Copy link

jutley commented Jan 31, 2020

Would it make sense to update the yaml marshaller to include a hash of the secret? That should fix the toHash function for regexes and secrets without exposing the secret. Not sure if it will break anything.

@roidelapluie
Copy link
Member

roidelapluie commented Feb 1, 2020 via email

@jutley
Copy link

jutley commented Feb 4, 2020

@roidelapluie To be clear, what would be the concern with a user-visible hash? I suppose it would allow a user to identify secret re-use. Are there any other concerns?

@roidelapluie
Copy link
Member

Hash should not be used to hide secrets. They are not meant for security.

@brian-brazil
Copy link
Contributor

It depends on the hash, but even with a proper cryptographic hash you could e.g. notice that two secrets were the same.

@jutley
Copy link

jutley commented Feb 4, 2020

So, it seems like there are 2 requirements here:

  1. Configuration marshaling exposes nothing about a secret's value
  2. Configuration hashing reflects changes to any field (including regexes and secrets)

In order for these to not conflict, I think we must either 1) salt and hash the secrets when marshaling, or 2) not implement hashing using YAML marshaling.

I already implemented the second option with my original solution in #6546, which uses the JSON marshaler and provides an implementation for Regexp. However, this really feels like an abuse of the fact that there are multiple marshalers available, especially given that the JSON marshalers are never intentionally implemented in this project.

Signed-off-by: Simon Pasquier <spasquie@redhat.com>
But it doesn't work either because of secret fields.

Signed-off-by: Simon Pasquier <spasquie@redhat.com>
@csmarchbanks
Copy link
Member

Would it be reasonable to keep the yaml marshaling for the hash, thus having redacted secrets, and specifically update a queue whenever one of the secrets changes? Or else have a way to update the http client on a remote.Client so we wouldn't even have to restart the whole queue if the auth changes?

@roidelapluie
Copy link
Member

What prevents us to use reflects.Deepequal?

@csmarchbanks
Copy link
Member

Closing as I took this over in #7073

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.

7 participants