So it's possible to test with various key-types.
Signed-off-by: Patrick Donnelly <pdonnell@ibm.com>
{
auto l = s;
std::transform(l.begin(), l.end(), l.begin(), ::tolower);
+ if (l == "recommended") {
+ return CEPH_CRYPTO_AES256KRB5;
+ }
if (l == "aes") {
return CEPH_CRYPTO_AES;
}
return -ENOENT;
}
+const std::set<int>& CryptoManager::get_secure_key_types()
+{
+ static const std::set<int> secure_keys{CEPH_CRYPTO_AES256KRB5};
+ return secure_keys;
+}
+
bool CryptoManager::crypto_type_supported(int type) const
{
return supported_crypto_types.find(type) != supported_crypto_types.end();
}
static int get_key_type(const std::string& s);
+ static const std::set<int>& get_secure_key_types();
bool crypto_type_supported(int type) const;
std::shared_ptr<CryptoHandler> get_handler(int type);
services:
- mon
with_legacy: true
+- name: mon_auth_allow_insecure_key
+ type: bool
+ level: advanced
+ desc: Allow the creation of keys with insecure type.
+ long_desc: >
+ By default, the Monitors will allow creation of keys with a cipher type
+ known to be insecure so long as the Monitors also allow that cipher to
+ authenticate. When that cipher type is removed from the authentication
+ list, the Monitors will also disable the default value of this
+ configuration. When disabled, ceph commands can no longer create keys with
+ an insecure cipher type.
+ default: false
+ services:
+ - mon
+ flags:
+ - runtime
- name: mon_auth_validate_all_caps
type: bool
level: advanced
#include "auth/AuthServiceHandler.h"
#include "auth/KeyRing.h"
+#include "auth/Crypto.h"
#include "include/stringify.h"
#include "include/ceph_assert.h"
#include "mgr/MgrCap.h"
#include "osd/OSDCap.h"
+#include <string>
+#include <string_view>
+using namespace std::literals::string_view_literals;
+using namespace std::literals::string_literals;
+
#define dout_subsys ceph_subsys_mon
#undef dout_prefix
#define dout_prefix _prefix(_dout, mon, get_last_committed())
return true;
}
+int AuthMonitor::get_cipher_type(const cmdmap_t& cmdmap, std::ostream& ss) const
+{
+ std::string key_string_type;
+ cmd_getval_or<std::string>(cmdmap, "key_type"sv, key_string_type, "recommended"s);
+ auto key_type = CryptoManager::get_key_type(key_string_type);
+ auto&& secure_key_types = CryptoManager::get_secure_key_types();
+ if (!secure_key_types.contains(key_type)) {
+ if (!cct->_conf.get_val<bool>("mon_auth_allow_insecure_key")) {
+ ss << "creating key with insecure key type (\"" << key_string_type << "\") not allowed";
+ return -EPERM;
+ }
+ }
+ return key_type;
+}
+
+
bool AuthMonitor::prepare_command(MonOpRequestRef op)
{
auto m = op->get_req<MMonCommand>();
bufferlist bl = m->get_data();
bool has_keyring = (bl.length() > 0);
+ int key_type = get_cipher_type(cmdmap, ss);
+ if (key_type < 0) {
+ goto done;
+ }
+
KeyRing new_keyring;
if (has_keyring) {
auto iter = bl.cbegin();
if (!has_keyring) {
dout(10) << "AuthMonitor::prepare_command generating random key for "
<< auth_inc.name << dendl;
- new_inc.key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+ new_inc.key.create(g_ceph_context, key_type);
}
new_inc.caps = encoded_caps;
goto done;
}
+ int key_type = get_cipher_type(cmdmap, ss);
+ if (key_type < 0) {
+ goto done;
+ }
+
// is there an uncommitted pending_key? (or any change for this entity)
for (auto& p : pending_auth) {
if (p.inc_type == AUTH_DATA) {
auth_inc.op = KeyServerData::AUTH_INC_ADD;
auth_inc.name = entity;
auth_inc.auth = entity_auth;
- auth_inc.auth.pending_key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+ auth_inc.auth.pending_key.create(g_ceph_context, key_type);
push_cephx_inc(auth_inc);
kr.add(entity, auth_inc.auth.key, auth_inc.auth.pending_key);
push_cephx_inc(auth_inc);
goto done;
}
+ int key_type = get_cipher_type(cmdmap, ss);
+ if (key_type < 0) {
+ goto done;
+ }
+
// do we have it?
EntityAuth entity_auth;
if (mon.key_server.get_auth(entity, entity_auth)) {
KeyServerData::Incremental auth_inc;
auth_inc.op = KeyServerData::AUTH_INC_ADD;
auth_inc.name = entity;
- auth_inc.auth.key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+ auth_inc.auth.key.create(g_ceph_context, key_type);
auth_inc.auth.caps = wanted_caps;
push_cephx_inc(auth_inc);
string mds_cap_string, osd_cap_string;
string osd_cap_wanted = "r";
+ int key_type = get_cipher_type(cmdmap, ss);
+ if (key_type < 0) {
+ goto done;
+ }
+
const Filesystem* fs = nullptr;
if (filesystem != "*" && filesystem != "all") {
const auto& fsmap = mon.mdsmon()->get_fsmap();
dout(20) << it.first << " cap = \"" << it.second << "\"" << dendl;
}
- err = _update_caps(entity, newcaps, op, ss, ds, &rdata, f.get());
+ err = _update_caps(entity, key_type, newcaps, op, ss, ds, &rdata, f.get());
if (err == 0) {
return true;
} else {
}
}
- err = _create_entity(entity, newcaps, op, ss, ds, &rdata, f.get());
+ err = _create_entity(entity, key_type, newcaps, op, ss, ds, &rdata, f.get());
if (err == 0) {
return true;
} else {
goto done;
}
} else if (prefix == "auth caps" && !entity_name.empty()) {
- err = _update_caps(entity, ceph_caps, op, ss, ds, &rdata, f.get());
+ err = _update_caps(entity, CEPH_CRYPTO_AES256KRB5, ceph_caps, op, ss, ds, &rdata, f.get());
if (err == 0) {
return true;
} else {
goto done;
}
+ int key_type = get_cipher_type(cmdmap, ss);
+ if (key_type < 0) {
+ goto done;
+ }
+
EntityAuth entity_auth;
if (!mon.key_server.get_auth(entity, entity_auth)) {
ss << "entity does not exist";
goto done;
}
- entity_auth.key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+ entity_auth.key.create(g_ceph_context, key_type);
KeyServerData::Incremental auth_inc;
auth_inc.op = KeyServerData::AUTH_INC_ADD;
// Pass both, rdata as well as fmtr, to enable printing of the key after
// update
int AuthMonitor::_update_or_create_entity(const EntityName& entity,
+ int key_type,
const map<string, string>& caps, MonOpRequestRef op, stringstream& ss,
stringstream& ds, bufferlist* rdata, Formatter* fmtr, bool create_entity)
{
auth_inc.op = KeyServerData::AUTH_INC_ADD;
auth_inc.auth.caps = encoded_caps;
if (create_entity) {
- auth_inc.auth.key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+ auth_inc.auth.key.create(g_ceph_context, key_type);
}
push_cephx_inc(auth_inc);
return 0;
}
-int AuthMonitor::_update_caps(const EntityName& entity,
+int AuthMonitor::_update_caps(const EntityName& entity, int key_type,
const map<string, string>& caps, MonOpRequestRef op, stringstream& ss,
stringstream& ds, bufferlist* rdata, Formatter* fmtr)
{
- return _update_or_create_entity(entity, caps, op, ss, ds, rdata, fmtr,
- false);
+ return _update_or_create_entity(entity, key_type, caps, op, ss,
+ ds, rdata, fmtr, false);
}
-int AuthMonitor::_create_entity(const EntityName& entity,
+int AuthMonitor::_create_entity(const EntityName& entity, int key_type,
const map<string, string>& caps, MonOpRequestRef op, stringstream& ss,
stringstream& ds, bufferlist* rdata, Formatter* fmtr)
{
- return _update_or_create_entity(entity, caps, op, ss, ds, rdata, fmtr,
- true);
+ return _update_or_create_entity(entity, key_type, caps, op, ss,
+ ds, rdata, fmtr, true);
}
bool AuthMonitor::prepare_global_id(MonOpRequestRef op)
private:
std::vector<Incremental> pending_auth;
- uint64_t max_global_id;
- uint64_t last_allocated_id;
+ uint64_t max_global_id = 0;
+ uint64_t last_allocated_id = 0;
+ boost::intrusive_ptr<CephContext> cct;
// these are protected by mon->auth_lock
int mon_num = 0, mon_rank = 0;
bool prep_auth(MonOpRequestRef op, bool paxos_writable);
bool preprocess_command(MonOpRequestRef op);
+
+ int get_cipher_type(const cmdmap_t& cmdmap, std::ostream& ss) const;
bool prepare_command(MonOpRequestRef op);
void _encode_keyring(KeyRing& kr, const EntityName& entity,
int _check_and_encode_caps(const std::map<std::string, std::string>& caps,
std::map<std::string, bufferlist>& encoded_caps, std::stringstream& ss);
- int _update_or_create_entity(const EntityName& entity,
+ int _update_or_create_entity(const EntityName& entity, int key_type,
const std::map<std::string, std::string>& caps, MonOpRequestRef op,
std::stringstream& ss, std::stringstream& ds, bufferlist* rdata=nullptr,
Formatter* fmtr=nullptr, bool create_entity=false);
- int _create_entity(const EntityName& entity,
+ int _create_entity(const EntityName& entity, int key_type,
const std::map<std::string, std::string>& caps, MonOpRequestRef op,
std::stringstream& ss, std::stringstream& ds, bufferlist* rdata,
Formatter* fmtr);
- int _update_caps(const EntityName& entity,
+ int _update_caps(const EntityName& entity, int key_type,
const std::map<std::string, std::string>& caps, MonOpRequestRef op,
std::stringstream& ss, std::stringstream& ds, bufferlist* rdata,
Formatter* fmtr);
const EntityAuth& auth);
public:
- AuthMonitor(Monitor &mn, Paxos &p, const std::string& service_name)
- : PaxosService(mn, p, service_name),
- max_global_id(0),
- last_allocated_id(0)
+ AuthMonitor(CephContext* cct, Monitor &mn, Paxos &p, const std::string& service_name)
+ : PaxosService(mn, p, service_name), cct(cct)
{}
void pre_auth(MAuth *m);
COMMAND("auth ls", "list authentication state", "auth", "rx")
COMMAND("auth import", "auth import: read keyring file from -i <file>",
"auth", "rwx")
-COMMAND("auth add "
- "name=entity,type=CephString "
- "name=caps,type=CephString,n=N,req=false",
+COMMAND("auth add"
+ " name=entity,type=CephString"
+ " name=caps,type=CephString,n=N,req=false"
+ " --"
+ " name=key_type,type=CephString,req=false"
+ ,
"add auth info for <entity> from input file, or random key if no "
"input is given, and/or any caps specified in the command",
"auth", "rwx")
-COMMAND("auth rotate "
- "name=entity,type=CephString",
+COMMAND("auth rotate"
+ " name=entity,type=CephString"
+ " --"
+ " name=key_type,type=CephString,req=false"
+ ,
"rotate entity key",
"auth", "rwx")
-COMMAND("auth get-or-create-key "
- "name=entity,type=CephString "
- "name=caps,type=CephString,n=N,req=false",
+COMMAND("auth get-or-create-key"
+ " name=entity,type=CephString"
+ " name=caps,type=CephString,n=N,req=false"
+ " --"
+ " name=key_type,type=CephString,req=false"
+ ,
"get, or add, key for <name> from system/caps pairs specified in the command. If key already exists, any given caps must match the existing caps for that key.",
"auth", "rwx")
-COMMAND("auth get-or-create "
- "name=entity,type=CephString "
- "name=caps,type=CephString,n=N,req=false",
+COMMAND("auth get-or-create"
+ " name=entity,type=CephString"
+ " name=caps,type=CephString,n=N,req=false"
+ " --"
+ " name=key_type,type=CephString,req=false"
+ ,
"add auth info for <entity> from input file, or random key if no input given, and/or any caps specified in the command",
"auth", "rwx")
COMMAND("auth get-or-create-pending "
"name=entity,type=CephString",
"rotate pending key into active position",
"auth", "rwx")
-COMMAND("fs authorize "
- "name=filesystem,type=CephString "
- "name=entity,type=CephString "
- "name=caps,type=CephString,n=N",
+COMMAND("fs authorize"
+ " name=filesystem,type=CephString"
+ " name=entity,type=CephString"
+ " name=caps,type=CephString,n=N"
+ " --"
+ " name=key_type,type=CephString,req=false"
+ ,
"add auth for <entity> to access file system <filesystem> based on following directory and permissions pairs",
"auth", "rwx")
COMMAND("auth caps "
paxos_service[PAXOS_MONMAP].reset(new MonmapMonitor(*this, *paxos, "monmap"));
paxos_service[PAXOS_OSDMAP].reset(new OSDMonitor(cct, *this, *paxos, "osdmap"));
paxos_service[PAXOS_LOG].reset(new LogMonitor(*this, *paxos, "logm"));
- paxos_service[PAXOS_AUTH].reset(new AuthMonitor(*this, *paxos, "auth"));
+ paxos_service[PAXOS_AUTH].reset(new AuthMonitor(cct, *this, *paxos, "auth"));
paxos_service[PAXOS_MGR].reset(new MgrMonitor(*this, *paxos, "mgr"));
paxos_service[PAXOS_MGRSTAT].reset(new MgrStatMonitor(*this, *paxos, "mgrstat"));
paxos_service[PAXOS_HEALTH].reset(new HealthMonitor(*this, *paxos, "health"));
map<string,bufferlist> caps;
std::string fn;
- int key_type = CEPH_CRYPTO_AES256KRB5;
+ int key_type = CryptoManager::get_key_type("recommended");
if (args.empty()) {
cerr << argv[0] << ": -h or --help for usage" << std::endl;