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

monclient: avoid key renew storm on clock skew #8258

Merged
merged 1 commit into from Mar 31, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 22 additions & 4 deletions src/mon/MonClient.cc
Expand Up @@ -534,6 +534,7 @@ void MonClient::handle_auth(MAuthReply *m)
if (ret == 0) {
if (state != MC_STATE_HAVE_SESSION) {
state = MC_STATE_HAVE_SESSION;
last_rotating_renew_sent = utime_t();
while (!waiting_for_session.empty()) {
_send_mon_message(waiting_for_session.front());
waiting_for_session.pop_front();
Expand Down Expand Up @@ -831,18 +832,34 @@ int MonClient::_check_auth_rotating()
return 0;
}

utime_t cutoff = ceph_clock_now(cct);
utime_t now = ceph_clock_now(cct);
utime_t cutoff = now;
cutoff -= MIN(30.0, cct->_conf->auth_service_ticket_ttl / 4.0);
utime_t issued_at_lower_bound = now;
issued_at_lower_bound -= cct->_conf->auth_service_ticket_ttl;
if (!rotating_secrets->need_new_secrets(cutoff)) {
ldout(cct, 10) << "_check_auth_rotating have uptodate secrets (they expire after " << cutoff << ")" << dendl;
rotating_secrets->dump_rotating();
return 0;
}

ldout(cct, 10) << "_check_auth_rotating renewing rotating keys (they expired before " << cutoff << ")" << dendl;
if (!rotating_secrets->need_new_secrets() &&
rotating_secrets->need_new_secrets(issued_at_lower_bound)) {
Copy link
Member

Choose a reason for hiding this comment

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

need_new_secrets is

bool need_new_secrets(utime_t now) const {
return secrets.size() < KEY_ROTATE_NUM || current().expiration <= now;
}

and issued_at_lower_bound is before now.. when will this ever be true?

Copy link
Author

Choose a reason for hiding this comment

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

If the client (OSD) system clock is off by a few hours (in the future) with respect to monitor.

// the key has expired before it has been issued?
lderr(cct) << __func__ << " possible clock skew, rotating keys expired way too early"
<< " (before " << issued_at_lower_bound << ")" << dendl;
}
if ((now > last_rotating_renew_sent) &&
double(now - last_rotating_renew_sent) < 1) {
ldout(cct, 10) << __func__ << " called too often (last: "
<< last_rotating_renew_sent << "), skipping refresh" << dendl;
return 0;
}
MAuth *m = new MAuth;
m->protocol = auth->get_protocol();
if (auth->build_rotating_request(m->auth_payload)) {
last_rotating_renew_sent = now;
_send_mon_message(m);
} else {
m->put();
Expand All @@ -853,7 +870,8 @@ int MonClient::_check_auth_rotating()
int MonClient::wait_auth_rotating(double timeout)
{
Mutex::Locker l(monc_lock);
utime_t until = ceph_clock_now(cct);
utime_t now = ceph_clock_now(cct);
utime_t until = now;
until += timeout;

if (auth->get_protocol() == CEPH_AUTH_NONE)
Expand All @@ -863,14 +881,14 @@ int MonClient::wait_auth_rotating(double timeout)
return 0;

while (auth_principal_needs_rotating_keys(entity_name) &&
rotating_secrets->need_new_secrets()) {
utime_t now = ceph_clock_now(cct);
rotating_secrets->need_new_secrets(now)) {
if (now >= until) {
ldout(cct, 0) << "wait_auth_rotating timed out after " << timeout << dendl;
return -ETIMEDOUT;
}
ldout(cct, 10) << "wait_auth_rotating waiting (until " << until << ")" << dendl;
auth_cond.WaitUntil(monc_lock, until);
now = ceph_clock_now(cct);
}
ldout(cct, 10) << "wait_auth_rotating done" << dendl;
return 0;
Expand Down
1 change: 1 addition & 0 deletions src/mon/MonClient.h
Expand Up @@ -179,6 +179,7 @@ class MonClient : public Dispatcher {
int authenticate_err;

list<Message*> waiting_for_session;
utime_t last_rotating_renew_sent;
Context *session_established_context;
bool had_a_connection;
double reopen_interval_multiplier;
Expand Down
11 changes: 11 additions & 0 deletions src/osd/OSD.cc
Expand Up @@ -2028,6 +2028,9 @@ int OSD::init()
daily_loadavg = 1.0;
}

int rotating_auth_attempts = 0;
const int max_rotating_auth_attempts = 10;

// read superblock
r = read_superblock();
if (r < 0) {
Expand Down Expand Up @@ -2177,6 +2180,14 @@ int OSD::init()

while (monc->wait_auth_rotating(30.0) < 0) {
derr << "unable to obtain rotating service keys; retrying" << dendl;
++rotating_auth_attempts;
if (rotating_auth_attempts > max_rotating_auth_attempts) {
osd_lock.Lock(); // make locker happy
if (!is_stopping()) {
r = - ETIMEDOUT;
}
goto monout;
}
}

osd_lock.Lock();
Expand Down