diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/tools/ceph_authtool.cc | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/ceph_authtool.cc')
-rw-r--r-- | src/tools/ceph_authtool.cc | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/src/tools/ceph_authtool.cc b/src/tools/ceph_authtool.cc new file mode 100644 index 000000000..c650cc880 --- /dev/null +++ b/src/tools/ceph_authtool.cc @@ -0,0 +1,314 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net> + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include "common/ConfUtils.h" +#include "common/ceph_argparse.h" +#include "common/config_proxy.h" +#include "global/global_context.h" +#include "global/global_init.h" + +#include "auth/Crypto.h" +#include "auth/Auth.h" +#include "auth/KeyRing.h" + +void usage() +{ + cout << "usage: ceph-authtool keyringfile [OPTIONS]...\n" + << "where the options are:\n" + << " -l, --list will list all keys and capabilities present in\n" + << " the keyring\n" + << " -p, --print-key will print an encoded key for the specified\n" + << " entityname. This is suitable for the\n" + << " 'mount -o secret=..' argument\n" + << " -C, --create-keyring will create a new keyring, overwriting any\n" + << " existing keyringfile\n" + << " -g, --gen-key will generate a new secret key for the\n" + << " specified entityname\n" + << " --gen-print-key will generate a new secret key without set it\n" + << " to the keyringfile, prints the secret to stdout\n" + << " --import-keyring FILE will import the content of a given keyring\n" + << " into the keyringfile\n" + << " -n NAME, --name NAME specify entityname to operate on\n" + << " -a BASE64, --add-key BASE64 will add an encoded key to the keyring\n" + << " --cap SUBSYSTEM CAPABILITY will set the capability for given subsystem\n" + << " --caps CAPSFILE will set all of capabilities associated with a\n" + << " given key, for all subsystems\n" + << " --mode MODE will set the desired file mode to the keyring\n" + << " e.g: '0644', defaults to '0600'" + << std::endl; + exit(1); +} + +int main(int argc, const char **argv) +{ + vector<const char*> args; + argv_to_vec(argc, argv, args); + + std::string add_key; + std::string caps_fn; + std::string import_keyring; + map<string,bufferlist> caps; + std::string fn; + + if (args.empty()) { + cerr << argv[0] << ": -h or --help for usage" << std::endl; + exit(1); + } + if (ceph_argparse_need_usage(args)) { + usage(); + exit(0); + } + + auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, + CODE_ENVIRONMENT_UTILITY, + CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); + + bool gen_key = false; + bool gen_print_key = false; + bool list = false; + bool print_key = false; + bool create_keyring = false; + int mode = 0600; // keyring file mode + std::vector<const char*>::iterator i; + + /* Handle options unique to ceph-authtool + * -n NAME, --name NAME is handled by global_init + * */ + for (i = args.begin(); i != args.end(); ) { + std::string val; + if (ceph_argparse_double_dash(args, i)) { + break; + } else if (ceph_argparse_flag(args, i, "-g", "--gen-key", (char*)NULL)) { + gen_key = true; + } else if (ceph_argparse_flag(args, i, "--gen-print-key", (char*)NULL)) { + gen_print_key = true; + } else if (ceph_argparse_witharg(args, i, &val, "-a", "--add-key", (char*)NULL)) { + if (val.empty()) { + cerr << "Option --add-key requires an argument" << std::endl; + exit(1); + } + add_key = val; + } else if (ceph_argparse_flag(args, i, "-l", "--list", (char*)NULL)) { + list = true; + } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) { + caps_fn = val; + } else if (ceph_argparse_witharg(args, i, &val, "--cap", (char*)NULL)) { + std::string my_key = val; + if (i == args.end()) { + cerr << "must give two arguments to --cap: key and val." << std::endl; + exit(1); + } + std::string my_val = *i; + ++i; + encode(my_val, caps[my_key]); + } else if (ceph_argparse_flag(args, i, "-p", "--print-key", (char*)NULL)) { + print_key = true; + } else if (ceph_argparse_flag(args, i, "-C", "--create-keyring", (char*)NULL)) { + create_keyring = true; + } else if (ceph_argparse_witharg(args, i, &val, "--import-keyring", (char*)NULL)) { + import_keyring = val; + } else if (ceph_argparse_witharg(args, i, &val, "--mode", (char*)NULL)) { + std::string err; + mode = strict_strtoll(val.c_str(), 8, &err); + if (!err.empty()) { + cerr << "Option --mode requires an argument" << std::endl; + exit(1); + } + } else if (fn.empty()) { + fn = *i++; + } else { + cerr << argv[0] << ": unexpected '" << *i << "'" << std::endl; + usage(); + } + } + + if (fn.empty() && !gen_print_key) { + cerr << argv[0] << ": must specify filename" << std::endl; + usage(); + } + if (!(gen_key || + gen_print_key || + !add_key.empty() || + list || + !caps_fn.empty() || + !caps.empty() || + print_key || + create_keyring || + !import_keyring.empty())) { + cerr << "no command specified" << std::endl; + usage(); + } + if (gen_key && (!add_key.empty())) { + cerr << "can't both gen-key and add-key" << std::endl; + usage(); + } + + common_init_finish(g_ceph_context); + EntityName ename(g_conf()->name); + + // Enforce the use of gen-key or add-key when creating to avoid ending up + // with an "empty" key (key = AAAAAAAAAAAAAAAA) + if (create_keyring && !gen_key && add_key.empty() && !caps.empty()) { + cerr << "must specify either gen-key or add-key when creating" << std::endl; + usage(); + } + + if (gen_print_key) { + CryptoKey key; + key.create(g_ceph_context, CEPH_CRYPTO_AES); + cout << key << std::endl; + return 0; + } + + // keyring -------- + bool modified = false; + bool added_entity = false; + KeyRing keyring; + + bufferlist bl; + int r = 0; + if (create_keyring) { + cout << "creating " << fn << std::endl; + modified = true; + } else { + std::string err; + r = bl.read_file(fn.c_str(), &err); + if (r >= 0) { + try { + auto iter = bl.cbegin(); + decode(keyring, iter); + } catch (const buffer::error &err) { + cerr << "error reading file " << fn << std::endl; + exit(1); + } + } else { + cerr << "can't open " << fn << ": " << err << std::endl; + exit(1); + } + } + + // Validate that "name" actually has an existing key in this keyring if we + // have not given gen-key or add-key options + if (!gen_key && add_key.empty() && !caps.empty()) { + CryptoKey key; + if (!keyring.get_secret(ename, key)) { + cerr << "can't find existing key for " << ename + << " and neither gen-key nor add-key specified" << std::endl; + exit(1); + } + } + + // write commands + if (!import_keyring.empty()) { + KeyRing other; + bufferlist obl; + std::string err; + int r = obl.read_file(import_keyring.c_str(), &err); + if (r >= 0) { + try { + auto iter = obl.cbegin(); + decode(other, iter); + } catch (const buffer::error &err) { + cerr << "error reading file " << import_keyring << std::endl; + exit(1); + } + + cout << "importing contents of " << import_keyring << " into " << fn << std::endl; + //other.print(cout); + keyring.import(g_ceph_context, other); + modified = true; + } else { + cerr << "can't open " << import_keyring << ": " << err << std::endl; + exit(1); + } + } + if (gen_key) { + EntityAuth eauth; + eauth.key.create(g_ceph_context, CEPH_CRYPTO_AES); + keyring.add(ename, eauth); + modified = true; + } + if (!add_key.empty()) { + EntityAuth eauth; + try { + eauth.key.decode_base64(add_key); + } catch (const buffer::error &err) { + cerr << "can't decode key '" << add_key << "'" << std::endl; + exit(1); + } + keyring.add(ename, eauth); + modified = true; + cout << "added entity " << ename << " " << eauth << std::endl; + added_entity = true; + } + if (!caps_fn.empty()) { + ConfFile cf; + if (cf.parse_file(caps_fn, &cerr) != 0) { + cerr << "could not parse caps file " << caps_fn << std::endl; + exit(1); + } + map<string, bufferlist> caps; + const char *key_names[] = { "mon", "osd", "mds", "mgr", NULL }; + for (int i=0; key_names[i]; i++) { + std::string val; + if (cf.read("global", key_names[i], val) == 0) { + bufferlist bl; + encode(val, bl); + string s(key_names[i]); + caps[s] = bl; + } + } + keyring.set_caps(ename, caps); + modified = true; + } + if (!caps.empty()) { + keyring.set_caps(ename, caps); + modified = true; + } + if (added_entity && caps.size() > 0) { + cout << "added " << caps.size() << " caps to entity " << ename << std::endl; + } + + // read commands + if (list) { + try { + keyring.print(cout); + } catch (ceph::buffer::end_of_buffer &eob) { + cout << "Exception (end_of_buffer) in print(), exit." << std::endl; + exit(1); + } + } + if (print_key) { + CryptoKey key; + if (keyring.get_secret(ename, key)) { + cout << key << std::endl; + } else { + cerr << "entity " << ename << " not found" << std::endl; + exit(1); + } + } + + // write result? + if (modified) { + bufferlist bl; + keyring.encode_plaintext(bl); + r = bl.write_file(fn.c_str(), mode); + if (r < 0) { + cerr << "could not write " << fn << std::endl; + exit(1); + } + //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl; + } + return 0; +} |