ceph key的创建
来源:互联网 发布:淘宝试衣服软件 编辑:程序博客网 时间:2024/06/07 22:27
ceph中提供了cephx认证机制,客户端到服务端的访问,服务段之间的互访等都提供了认证过程,当然这些都是可配的。本文主要介绍ceph中key的常见过程。
ceph中有两个要弄清的概念:
key和keyring: key标识一个密钥,一串字符;keyring用来存放密钥,也可以理解为一个文件。
创建keyring的过程:
下面这部分代码,从ceph_osd.cc的main方法中提取的。
if (mkkey) { common_init_finish(g_ceph_context); //创建KeyRing实例 KeyRing *keyring = KeyRing::create_empty(); if (!keyring) { derr << "Unable to get a Ceph keyring." << dendl; return 1; } EntityName ename(g_conf->name); EntityAuth eauth; //从keyring文件中加载KeyRing信息 int ret = keyring->load(g_ceph_context, g_conf->keyring); if (ret == 0 && keyring->get_auth(ename, eauth)) { derr << "already have key in keyring " << g_conf->keyring << dendl; } else { //创建Key eauth.key.create(g_ceph_context, CEPH_CRYPTO_AES); keyring->add(ename, eauth); bufferlist bl; //将KeyRing信息序列化到bl中(以普通文本的形式) keyring->encode_plaintext(bl); //保存到keyring文件中 int r = bl.write_file(g_conf->keyring.c_str(), 0600); if (r) derr << TEXT_RED << " ** ERROR: writing new keyring to " << g_conf->keyring << ": " << cpp_strerror(r) << TEXT_NORMAL << dendl; else derr << "created new key in keyring " << g_conf->keyring << dendl; } }
这段代码主要实现创建key的过程,首先它试图从给定的keyring文件中去加载,如果没有再去创建,创建成功之后,又以普通文本的形式保持到keyring文件中。
其中涉及的一些抽象结构:
1.KeyRing继承与KeyStore,KeyRing类中包含一个keys(map < EntityName, EntityAuth >)属性。
2.EntityAuth中包含auid(uint64_t)key(CryptoKey) caps(map< string, bufferlist >)
3.CryptoKey中有type(__u16) created(utime_t) secret(bufferptr) ckh(mutable ceph::shared_ptr < CryptoKeyHandler >)
4.CryptoAES 继承于CryptoHandler
创建Key的过程实现
加载keyring
从keyring文件中读取信息,然后反序列化到KeyRing实例中。
int KeyRing::load(CephContext *cct, const std::string &filename){ if (filename.empty()) ¦ return -EINVAL; bufferlist bl; std::string err; //从keyring文件中读取key int ret = bl.read_file(filename.c_str(), &err); if (ret < 0) { ¦ lderr(cct) << "error reading file: " << filename << ": " << err << dendl; ¦ return ret; }//将读取到的信息,反序列化到keys中 try { ¦ bufferlist::iterator iter = bl.begin(); ¦ decode(iter); } catch (const buffer::error& err) { ¦ lderr(cct) << "error parsing file " << filename << dendl; ¦ return -EIO; } ldout(cct, 2) << "KeyRing::load: loaded key file " << filename << dendl; return 0;}
void KeyRing::decode(bufferlist::iterator& bl) { __u8 struct_v; bufferlist::iterator start_pos = bl; try { ¦ ::decode(struct_v, bl); ¦ ::decode(keys, bl); } catch (buffer::error& err) { ¦ keys.clear(); ¦ decode_plaintext(start_pos); } }
上面如果发现keyring中没有,或者加载失败,则进入创建新key的过程。
创建key
int CryptoKey::create(CephContext *cct, int t) { CryptoHandler *ch = CryptoHandler::create(t); if (!ch) { ¦ if (cct) ¦ ¦ lderr(cct) << "ERROR: cct->get_crypto_handler(type=" << t << ") returned NULL" << dendl; ¦ return -EOPNOTSUPP; } bufferptr s; int r = ch->create(s); delete ch; if (r < 0) ¦ return r; r = _set_secret(t, s); if (r < 0) ¦ return r; created = ceph_clock_now(); return r; }
该法方法中创建了CryptoHandler来完成key的创建,深入到create方法中会发现该方法返回的是CryptoHandler的子类,由它来创建key。
创建CryptoAES实例。
CryptoHandler *CryptoHandler::create(int type) { switch (type) { case CEPH_CRYPTO_NONE: ¦ return new CryptoNone; case CEPH_CRYPTO_AES: ¦ return new CryptoAES; default: ¦ return NULL; } }
创建一串字符来作为key
int CryptoAES::create(bufferptr& secret) { bufferlist bl; int r = get_random_bytes(AES_KEY_LEN, bl); if (r < 0) ¦ return r; secret = buffer::ptr(bl.c_str(), bl.length()); return 0; } int get_random_bytes(char *buf, int len){ int fd = TEMP_FAILURE_RETRY(::open("/dev/urandom", O_RDONLY)); if (fd < 0) return -errno; int ret = safe_read_exact(fd, buf, len); VOID_TEMP_FAILURE_RETRY(::close(fd)); return ret;}
由以上代码可以知道key是由linux系统的/dev/urandom,随机生成。
设置key
int CryptoKey::_set_secret(int t, const bufferptr& s) { if (s.length() == 0) { ¦ secret = s; ¦ ckh.reset(); ¦ return 0; } CryptoHandler *ch = CryptoHandler::create(t); if (ch) { ¦ int ret = ch->validate_secret(s); ¦ if (ret < 0) { ¦ ¦ delete ch; ¦ ¦ return ret; ¦ } ¦ string error; ¦ ckh.reset(ch->get_key_handler(s, error)); ¦ delete ch; ¦ if (error.length()) { ¦ ¦ return -EIO; ¦ } } else { ¦ ¦ return -EOPNOTSUPP; } type = t; secret = s; return 0; }
验证key的长度,创建CryptoAESKeyHandler,并生成对secret加密后的字符串。
int CryptoAES::validate_secret(const bufferptr& secret){ if (secret.length() < (size_t)AES_KEY_LEN) { ¦ return -EINVAL; } return 0;} CryptoKeyHandler *CryptoAES::get_key_handler(const bufferptr& secret, string& error) { CryptoAESKeyHandler *ckh = new CryptoAESKeyHandler; ostringstream oss; if (ckh->init(secret, oss) < 0) { ¦ error = oss.str(); ¦ delete ckh; ¦ return NULL; } return ckh; }
创建secret的加密后的key。
int CryptoAESKeyHandler::init(const bufferptr& s, ostringstream& err) { ¦ secret = s; ¦ enc_key = new CryptoPP::AES::Encryption( ¦ ¦ (byte*)secret.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH); ¦ dec_key = new CryptoPP::AES::Decryption( ¦ ¦ (byte*)secret.c_str(), CryptoPP::AES::DEFAULT_KEYLENGTH); ¦ return 0; }
到这里key就创建完成了,下面是将内存中的key导入的文件中(普通文本形式)。
将内存中的key序列化之后导出到keyring中
//将KeyRing实例中的信息,以普通文本的形式写入到bl中。void KeyRing::encode_plaintext(bufferlist& bl) { std::ostringstream os; print(os); string str = os.str(); bl.append(str); }
//将KeyRing实例中的信息,输出到out流中。void KeyRing::print(ostream& out) { for (map<EntityName, EntityAuth>::iterator p = keys.begin(); ¦ ¦ ¦p != keys.end(); ¦ ¦ ¦++p) { ¦ out << "[" << p->first << "]" << std::endl; ¦ out << "\tkey = " << p->second.key << std::endl; ¦ if (p->second.auid != CEPH_AUTH_UID_DEFAULT) ¦ ¦ out << "\tauid = " << p->second.auid << std::endl; ¦ for (map<string, bufferlist>::iterator q = p->second.caps.begin(); ¦q != p->second.caps.end(); ¦++q) { ¦ ¦ bufferlist::iterator dataiter = q->second.begin(); ¦ ¦ string caps; ¦ ¦ ::decode(caps, dataiter); ¦ ¦ out << "\tcaps " << q->first << " = \"" << caps << '"' << std::endl; ¦ } } }
这个方法就导出了平常在keyring文件中看到的key的形式。
- ceph key的创建
- ceph的pool创建流程--代码分析
- 【实践】Ceph:创建RGW
- docker创建ceph集群
- Centos搭建ceph+++五、创建ceph集群
- ceph后端rbd,active的实例创建快照报错
- 关于ceph client创建RBD报错的解决方法
- Entity创建Primary Key的方法
- OutputCache 缓存key的创建 CreateOutputCachedItemKey
- GitHub SSH key的创建添加
- Android Studio创建key-store的方法
- Git SSH 创建Key的步骤
- CEPH pool 创建使用监控
- ceph存储 "ceph集群浅析三"Ceph的设计思想
- ceph存储 "ceph集群浅析四"Ceph的结构
- ceph存储 ceph中PG的意义
- ceph存储 ceph-Architecture的Cognize
- ceph存储 ceph Bluestore的架构
- java之yield(),sleep(),wait()区别详解
- React Native中样式表中的一些样式属性
- 2017最新在linux上搭建hustOJ(ubuntu系统)
- 【Ex.】打印出菱形图案的简易方法
- 列表页 删除操作(单选/多选)
- ceph key的创建
- MySql官方建议:Innodb表最佳实践
- 清除select自带小三角
- 智能投票合约
- Effective c++之Item 28: 避免返回对象内部构件的“句柄”
- C#188课的主要内容
- POJ 3065 Stargates 笔记
- 静态变量
- python中range和xrange的区别