rm $tmp.bazar.keyring $tmp.foo.keyring $tmp.bar.keyring
+# invalid caps health warning
+cat <<EOF | ceph auth import -i -
+[client.bad]
+ caps mon = this is wrong
+ caps osd = does not parse
+ caps mds = also does not parse
+EOF
+ceph health | grep AUTH_BAD_CAP
+ceph health detail | grep client.bad
+ceph auth rm client.bad
+expect "ceph auth health | grep AUTH_BAD_CAP" 1
+
echo OK
void AuthMonitor::update_from_paxos(bool *need_bootstrap)
{
dout(10) << __func__ << dendl;
+ load_health();
+
version_t version = get_last_committed();
version_t keys_ver = mon->key_server.get_ver();
if (version == keys_ver)
version_t version = get_last_committed() + 1;
put_version(t, version, bl);
put_last_committed(t, version);
+
+ // health
+ health_check_map_t next;
+ map<string,list<string>> bad_detail; // entity -> details
+ for (auto i = mon->key_server.secrets_begin();
+ i != mon->key_server.secrets_end();
+ ++i) {
+ for (auto& p : i->second.caps) {
+ ostringstream ss;
+ if (!valid_caps(p.first, p.second, &ss)) {
+ ostringstream ss2;
+ ss2 << i->first << " " << ss.str();
+ bad_detail[i->first.to_str()].push_back(ss2.str());
+ }
+ }
+ }
+ for (auto& inc : pending_auth) {
+ if (inc.inc_type == AUTH_DATA) {
+ KeyServerData::Incremental auth_inc;
+ auto iter = inc.auth_data.cbegin();
+ decode(auth_inc, iter);
+ if (auth_inc.op == KeyServerData::AUTH_INC_DEL) {
+ bad_detail.erase(auth_inc.name.to_str());
+ } else if (auth_inc.op == KeyServerData::AUTH_INC_ADD) {
+ for (auto& p : auth_inc.auth.caps) {
+ ostringstream ss;
+ if (!valid_caps(p.first, p.second, &ss)) {
+ ostringstream ss2;
+ ss2 << auth_inc.name << " " << ss.str();
+ bad_detail[auth_inc.name.to_str()].push_back(ss2.str());
+ }
+ }
+ }
+ }
+ }
+ if (bad_detail.size()) {
+ ostringstream ss;
+ ss << bad_detail.size() << " auth entities have invalid capabilities";
+ health_check_t *check = &next.add("AUTH_BAD_CAPS", HEALTH_ERR, ss.str());
+ for (auto& i : bad_detail) {
+ for (auto& j : i.second) {
+ check->detail.push_back(j);
+ }
+ }
+ }
+ encode_health(next, t);
}
void AuthMonitor::encode_full(MonitorDBStore::TransactionRef t)
/* validate mon/osd/mds caps; fail on unrecognized service/type */
bool valid_caps(const string& type, const string& caps, ostream *out);
+ bool valid_caps(const string& type, const bufferlist& bl, ostream *out) {
+ auto p = bl.begin();
+ string v;
+ try {
+ decode(v, p);
+ } catch (buffer::error& e) {
+ *out << "corrupt capability encoding";
+ return false;
+ }
+ return valid_caps(type, v, out);
+ }
bool valid_caps(const vector<string>& caps, ostream *out);
void on_active() override;