1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "common/ConfUtils.h"
16 #include "common/ceph_argparse.h"
17 #include "common/config.h"
18 #include "global/global_context.h"
19 #include "global/global_init.h"
21 #include "auth/Crypto.h"
22 #include "auth/Auth.h"
23 #include "auth/KeyRing.h"
27 cout << "usage: ceph-authtool keyringfile [OPTIONS]...\n"
28 << "where the options are:\n"
29 << " -l, --list will list all keys and capabilities present in\n"
31 << " -p, --print-key will print an encoded key for the specified\n"
32 << " entityname. This is suitable for the\n"
33 << " 'mount -o secret=..' argument\n"
34 << " -C, --create-keyring will create a new keyring, overwriting any\n"
35 << " existing keyringfile\n"
36 << " -g, --gen-key will generate a new secret key for the\n"
37 << " specified entityname\n"
38 << " --gen-print-key will generate a new secret key without set it\n"
39 << " to the keyringfile, prints the secret to stdout\n"
40 << " --import-keyring FILE will import the content of a given keyring\n"
41 << " into the keyringfile\n"
42 << " -n NAME, --name NAME specify entityname to operate on\n"
43 << " -u AUID, --set-uid AUID sets the auid (authenticated user id) for the\n"
44 << " specified entityname\n"
45 << " -a BASE64, --add-key BASE64 will add an encoded key to the keyring\n"
46 << " --cap SUBSYSTEM CAPABILITY will set the capability for given subsystem\n"
47 << " --caps CAPSFILE will set all of capabilities associated with a\n"
48 << " given key, for all subsystems"
53 int main(int argc, const char **argv)
55 vector<const char*> args;
56 argv_to_vec(argc, argv, args);
61 std::string import_keyring;
62 uint64_t auid = CEPH_AUTH_UID_DEFAULT;
63 map<string,bufferlist> caps;
66 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
67 CODE_ENVIRONMENT_UTILITY,
68 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
71 bool gen_print_key = false;
73 bool print_key = false;
74 bool create_keyring = false;
75 bool set_auid = false;
76 std::vector<const char*>::iterator i;
78 /* Handle options unique to ceph-authtool
79 * -n NAME, --name NAME is handled by global_init
81 for (i = args.begin(); i != args.end(); ) {
83 if (ceph_argparse_double_dash(args, i)) {
85 } else if (ceph_argparse_flag(args, i, "-g", "--gen-key", (char*)NULL)) {
87 } else if (ceph_argparse_flag(args, i, "--gen-print-key", (char*)NULL)) {
89 } else if (ceph_argparse_witharg(args, i, &val, "-a", "--add-key", (char*)NULL)) {
91 cerr << "Option --add-key requires an argument" << std::endl;
95 } else if (ceph_argparse_flag(args, i, "-l", "--list", (char*)NULL)) {
97 } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) {
99 } else if (ceph_argparse_witharg(args, i, &val, "--cap", (char*)NULL)) {
100 std::string my_key = val;
101 if (i == args.end()) {
102 cerr << "must give two arguments to --cap: key and val." << std::endl;
105 std::string my_val = *i;
107 ::encode(my_val, caps[my_key]);
108 } else if (ceph_argparse_flag(args, i, "-p", "--print-key", (char*)NULL)) {
110 } else if (ceph_argparse_flag(args, i, "-C", "--create-keyring", (char*)NULL)) {
111 create_keyring = true;
112 } else if (ceph_argparse_witharg(args, i, &val, "--import-keyring", (char*)NULL)) {
113 import_keyring = val;
114 } else if (ceph_argparse_witharg(args, i, &val, "-u", "--set-uid", (char*)NULL)) {
116 auid = strict_strtoll(val.c_str(), 10, &err);
118 cerr << "error parsing UID: " << err << std::endl;
122 } else if (fn.empty()) {
125 cerr << argv[0] << ": unexpected '" << *i << "'" << std::endl;
130 if (fn.empty() && !gen_print_key) {
131 cerr << argv[0] << ": must specify filename" << std::endl;
143 !import_keyring.empty())) {
144 cerr << "no command specified" << std::endl;
147 if (gen_key && (!add_key.empty())) {
148 cerr << "can't both gen-key and add-key" << std::endl;
152 common_init_finish(g_ceph_context);
153 EntityName ename(g_conf->name);
155 // Enforce the use of gen-key or add-key when creating to avoid ending up
156 // with an "empty" key (key = AAAAAAAAAAAAAAAA)
157 if (create_keyring && !gen_key && add_key.empty() && !caps.empty()) {
158 cerr << "must specify either gen-key or add-key when creating" << std::endl;
164 key.create(g_ceph_context, CEPH_CRYPTO_AES);
165 cout << key << std::endl;
170 bool modified = false;
175 if (create_keyring) {
176 cout << "creating " << fn << std::endl;
180 r = bl.read_file(fn.c_str(), &err);
183 bufferlist::iterator iter = bl.begin();
184 ::decode(keyring, iter);
185 } catch (const buffer::error &err) {
186 cerr << "error reading file " << fn << std::endl;
190 cerr << "can't open " << fn << ": " << err << std::endl;
195 // Validate that "name" actually has an existing key in this keyring if we
196 // have not given gen-key or add-key options
197 if (!gen_key && add_key.empty() && !caps.empty()) {
199 if (!keyring.get_secret(ename, key)) {
200 cerr << "can't find existing key for " << ename
201 << " and neither gen-key nor add-key specified" << std::endl;
207 if (!import_keyring.empty()) {
211 int r = obl.read_file(import_keyring.c_str(), &err);
214 bufferlist::iterator iter = obl.begin();
215 ::decode(other, iter);
216 } catch (const buffer::error &err) {
217 cerr << "error reading file " << import_keyring << std::endl;
221 cout << "importing contents of " << import_keyring << " into " << fn << std::endl;
223 keyring.import(g_ceph_context, other);
226 cerr << "can't open " << import_keyring << ": " << err << std::endl;
232 eauth.key.create(g_ceph_context, CEPH_CRYPTO_AES);
233 keyring.add(ename, eauth);
236 if (!add_key.empty()) {
239 eauth.key.decode_base64(add_key);
240 } catch (const buffer::error &err) {
241 cerr << "can't decode key '" << add_key << "'" << std::endl;
244 keyring.add(ename, eauth);
246 cout << "added entity " << ename << " auth " << eauth << std::endl;
248 if (!caps_fn.empty()) {
250 std::deque<std::string> parse_errors;
251 if (cf.parse_file(caps_fn, &parse_errors, &cerr) != 0) {
252 cerr << "could not parse caps file " << caps_fn << std::endl;
255 complain_about_parse_errors(g_ceph_context, &parse_errors);
256 map<string, bufferlist> caps;
257 const char *key_names[] = { "mon", "osd", "mds", "mgr", NULL };
258 for (int i=0; key_names[i]; i++) {
260 if (cf.read("global", key_names[i], val) == 0) {
263 string s(key_names[i]);
267 keyring.set_caps(ename, caps);
271 keyring.set_caps(ename, caps);
275 keyring.set_uid(ename, auid);
283 } catch (ceph::buffer::end_of_buffer &eob) {
284 cout << "Exception (end_of_buffer) in print(), exit." << std::endl;
290 if (keyring.get_secret(ename, key)) {
291 cout << key << std::endl;
293 cerr << "entity " << ename << " not found" << std::endl;
301 keyring.encode_plaintext(bl);
302 r = bl.write_file(fn.c_str(), 0600);
304 cerr << "could not write " << fn << std::endl;
307 //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl;