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

[CORE-8020] tls: Watch for IN_MOVED_TO #150

Open
wants to merge 1 commit into
base: v24.3.x
Choose a base branch
from

Conversation

BenPope
Copy link
Member

@BenPope BenPope commented Oct 31, 2024

Fixes CORE-8020

A common pattern for updating certificates is to do:

mv new.crt existing.crt

So configure the watch to detect IN_MOVED_TO

Signed-off-by: Ben Pope <[email protected]>
@BenPope BenPope self-assigned this Oct 31, 2024
@BenPope BenPope requested review from a team, oleiman and IoannisRP and removed request for a team October 31, 2024 08:18
@@ -537,7 +537,7 @@ class tls::reloadable_credentials_base {
}
}
}
future<fsnotifier::watch_token> add_watch(const sstring& filename, fsnotifier::flags flags = fsnotifier::flags::close_write|fsnotifier::flags::delete_self) {
future<fsnotifier::watch_token> add_watch(const sstring& filename, fsnotifier::flags flags = fsnotifier::flags::close_write|fsnotifier::flags::delete_self|fsnotifier::flags::move_to) {

Choose a reason for hiding this comment

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

Interesting. The man page made me think that move_to is generated for the containing directory rather than the file and that move_self is more appropriate.

What happens if someone does mv existing.crt existing.crt.bkp as a way of deleting certificates? I'm wondering if that would trigger a delete_self or if we should be watching move_from as well.

https://man7.org/linux/man-pages/man7/inotify.7.html

Copy link
Member

Choose a reason for hiding this comment

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

fwiw, I don't think mv existing.crt existing.crt.bkp will reliably invalidate the inode corresponding to existing.crt.

@@ -537,7 +537,7 @@ class tls::reloadable_credentials_base {
}
}
}
future<fsnotifier::watch_token> add_watch(const sstring& filename, fsnotifier::flags flags = fsnotifier::flags::close_write|fsnotifier::flags::delete_self) {
future<fsnotifier::watch_token> add_watch(const sstring& filename, fsnotifier::flags flags = fsnotifier::flags::close_write|fsnotifier::flags::delete_self|fsnotifier::flags::move_to) {

Choose a reason for hiding this comment

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

When executing

mv existing.crt.bak existing.crt

existing.crt should trigger a delete_self, which is already watched for, and the parent dir should issue a move_to.

I do not understand why adding move_to to the file watcher fixes the issue. What am I missing here?

The add_dir_watch function seems to be there to cater for moving files around, but for some reason it is only applied on rebuild and not on init.

Copy link
Member

Choose a reason for hiding this comment

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

Testing this naively at the command line, it doesn't seem like this type of mv generates a delete event, or at least not guaranteed right away.

which makes sense I think because inotify monitors the state of the inodes pointed to by the directory entry, rather than the name->inode mapping itself?

Copy link
Member

Choose a reason for hiding this comment

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

Ah, never mind, this is a file watch. Now I'm confused too!

Choose a reason for hiding this comment

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

Apologies, you are right. i should have been more careful in the description.
I was referring to the case where existing.crt already exists and we are trying to overwrite it with a move.

Copy link
Member

@oleiman oleiman Oct 31, 2024

Choose a reason for hiding this comment

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

well, that type of move does not immediately notify delete on the directory watch, but it does notify delete_self on the file watch. Anyway, your original question is apt I think.

Copy link
Member

@oleiman oleiman left a comment

Choose a reason for hiding this comment

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

ok, i think i get it. from reading

seastar/src/net/tls-impl.cc

Lines 445 to 464 in 7820b86

// #756
// first, add a watch to nearest parent dir we
// can find. If user deleted folders, we could end
// up looking at modifications to root.
// The idea is that should adding a watch to actual file
// fail (deleted file/folder), we wait for changes to closest
// parent. When this happens, we will retry all files
// that have not been successfully replaced (and maybe more),
// repeating the process. At some point, we hopefully
// get new, current data.
add_dir_watch(filename);
// #756 add watch _first_. File could change while we are
// reading this.
try {
add_watch(filename).get();
} catch (...) {
// let's just assume if this happens, it's because the file or folder was deleted.
// just ignore for now, and hope the dir watch will tell us when it is back...
return;
}

so we're sort of extending the parent-dir fallback watcher to hopefully pick this up?

I don't really understand why mv new existing doesn't generate a delete_self event sometimes (ever?). Seems like it should also trigger this watcher though.

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.

4 participants