文档简介:
配置KMS多用户访问控制
概述
多用户访问控制,主要用于帮助用户管理云账户下资源的访问权限,适用于企业内的不同角色,可以对不同的工作人员赋予使用产品的不同权限,当您的企业存在多用户协同操作资源时,推荐您使用多用户访问控制。 适用于下列使用场景:
- 中大型企业客户:对公司内多个员工授权管理;
- 偏技术型 vendor 或 SaaS 的平台商:对代理客户进行资源和权限管理;
- 中小开发者或小企业:添加项目成员或协作者,进行资源管理。
配置多用户访问控制包含创建用户、配置策略、用户授权及子用户登录共4个步骤。
创建子用户
- 主账号用户登录后在控制台选择“多用户访问控制”进入用户管理页面。
- 在左侧导航栏点击“用户管理”,在“用户管理 > 子用户”列表页,点击“创建子用户”。
- 在弹出的“创建子用户”对话框中,完成填写“用户名”和确认,返回“子用户管理列表”区可以查看到刚刚创建的子用户。
配置策略
KMS支持用户自定义策略。自定义策略是由用户自己创建,更细化的管理资源的权限集,可以针对单个实例配置权限,更加灵活的满足账户对不同用户的差异化权限管理。
子用户可以通过点击“创建策略”,填写策略名称并选择服务类型为(“密钥管理服务KMS”)添加自定义策略来进行自定义权限添加,用户可以根据具体的权限设置修改策略内容。
策略创建流程
点击创建策略
页面左侧选择"策略管理",在新的页面中点击"创建策略",选择"按策略生成器创建.
填写策略基本信息
在创建策略的页面中,填写需要创建的策略的名称,并在说明中填写该策略的备注信息,如该策略应用的实例,希望赋予的子用户或者策略的使用场景,以免将该策略和其他策略混淆。
填写策略权限配置
填写完策略的基本信息后,您需要填写该策略中包含的使用权限。
- 您需要进一步该权限对应的效力为允许还是拒绝。若您选择允许,则该策略中选择的权限将允许被授权的用户操作;若您选择拒绝,则该策略中选择的权限将禁止被授权用户操作;
- 选择权限,您需要选择该策略中包含的权限为仅加密、仅解密、加解密、查看、管理;
- 您还可以选择该策略针对的资源。在 KMS服务中,您可以指定该策略能够生效的具体密钥。
- 最后,您可以选择该策略在生效时间上的限制条件。您可以指定该策略在某一时刻后或者某一时刻前生效。
权限说明
分类 | API |
---|---|
查看权限 |
POST /?aciton=ListKeys POST /?aciton=ConsoleListKeys POST /?aciton=DescribeKey |
加密权限 |
POST /?aciton=ListKeys POST /?aciton=ConsoleListKeys POST /?aciton=DescribeKey POST /?aciton=Encrypt POST /?aciton=GenerateDataKey |
解密权限 |
POST /?aciton=ListKeys POST /?aciton=ConsoleListKeys POST /?aciton=DescribeKey POST /?aciton=Decrypt POST /?aciton=GenerateDataKey |
加解密权限 |
POST /?aciton=ListKeys POST /?aciton=ConsoleListKeys POST /?aciton=DescribeKey POST /?aciton=Encrypt POST /?aciton=Decrypt POST /?aciton=GenerateDataKey |
运维权限 |
POST /?aciton=ListKeys POST /?aciton=ConsoleListKeys POST /?aciton=DescribeKey POST /?action=CreateKey POST /?action=EnableKey POST /?action=DisableKey POST /?aciton=ScheduleKeyDeletion POST /?aciton=CancelKeyDeletion POST /?action=ImportKey POST /?action=ImportAsymmetricKey |
使用BCT记录操作事件
KMS已经与云审计(BCT)服务进行了集成。您可以在云审计中查看所有用户对您的资源所进行的操作记录。
使用对称密钥
对称加密是最常用的数据加密保护方式,KMS提供了简单易用的接口,方便您在云上轻松实现数据加解密的功能。KMS支持的对称密钥算法有以下几类:
BAIDU_AES_256/AES_128/AES_256
创建KMS生成的对称密码
首先点击创建密钥,然后选择你想要生成的对称密钥类型,选择影像名称("KMS生成"),并填写对密钥的描述。
创建外部导入的对称密钥
首先点击创建密钥,然后选择你想要生成的对称密钥类型,选择影像名称("外部导入"),并填写对密钥的描述
点击获取密钥参数
获取加密公钥和令牌后,对需要导入的对称密钥进行加密,通过点击导入密钥进行导入.
导入 AES_256密钥 过程示例
1.在控制台或者通过接口创建一个AES_256 的待导入的对称密钥:
- 创建完毕后点击获取密钥材料或者利用接口(/?action=GetParametersForImport)来获取密钥材料(加密公钥和令牌)
- 加密自己的对称密钥 openssl方式
#以aes256的导入为例
#使用openssl生成一个256位的对称密钥
openssl rand -out KeyMaterial.bin 32
#将加密公钥从16进制转成二进制文本
cat public_key_xxxxx.txt |xxd -ps -r > PublicKey.bin
#PKCS#1 v1.5 加密 待导入密钥二进制文本KeyMaterial.bin
openssl rsautl -encrypt -in KeyMaterial.bin -pkcs -inkey PublicKey.bin -keyform DER -pubin -out EncryptedKeyMaterial.bin
#将加密后的结果进行base64加密
openssl enc -e -base64 -A -in EncryptedKeyMaterial.bin -out EncryptedKeyMaterial_base64.txt
#最后将加密后的结果和令牌密钥填入。即可成功导入
java sdk方式
import com.baidubce.BceClientException;
import com.baidubce.BceServiceException;
import com.baidubce.Protocol;
import com.baidubce.auth.DefaultBceCredentials;
import com.baidubce.services.kms.KmsClient;
import com.baidubce.services.kms.KmsClientConfiguration;
import com.baidubce.services.kms.model.*;
import javax.crypto.Cipher;
import javax.xml.bind.DatatypeConverter;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Random;
public class testImportSymmetricKey {
public static void main(String[] args){
//String ACCESS_KEY_ID = ""; // 用户的Access Key ID
//String SECRET_ACCESS_KEY = ""; // 用户的Secret Access Key
String ENDPOINT = "https://bkm.bj.baidubce.com"; // kms域名
// 初始化一个KmsClient
KmsClientConfiguration config = new KmsClientConfiguration();
config.setCredentials(new DefaultBceCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY));
config.setEndpoint(ENDPOINT);
config.setProtocol(Protocol.HTTPS); // 设置https协议
KmsClient client = new KmsClient(config);
try {
//产生一个32字节随机数
byte[] keyMaterial = new byte[32];
new Random().nextBytes(keyMaterial);
//创建一个AES_256待导入密钥
CreateKeyRequest createReq = new CreateKeyRequest();
createReq.setKeySpec("AES_256");
createReq.setKeyUsage("ENCRYPT_DECRYPT");
createReq.setOrigin("EXTERNAL");
createReq.setProtectedBy("HSM");
CreateKeyResponse createRes = client.createKey(createReq);
String keyId = createRes.getKeyMetadata().getKeyId();
//获取导入密钥参数
GetParametersForImportResponse getParametersRes = client
.getParametersForImport(new GetParametersForImportRequest(keyId,"BASE64"));
String pubKey = getParametersRes.getPublicKey();
String token = getParametersRes.getImportToken();
byte[] publicKeyDer = DatatypeConverter.parseBase64Binary(pubKey);
//解析成RSA的公钥
KeyFactory keyFact = KeyFactory.getInstance("RSA");
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyDer);
PublicKey publicKey = keyFact.generatePublic(spec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherDer = cipher.doFinal(keyMaterial);
//加密后的密钥材料,需要进行base64编码
String encryptedKeyMaterial = DatatypeConverter.printBase64Binary(cipherDer);
ImportKeyRequest importReq = new ImportKeyRequest();
importReq.setEncryptedKey(encryptedKeyMaterial);
importReq.setImportToken(token);
importReq.setKeyId(keyId);
importReq.setKeySpec("AES_256");
importReq.setKeyUsage("ENCRYPT_DECRYPT");
KmsResponse importRes = client.importKey(importReq);
System.out.println(importRes.toString());
}catch (BceServiceException e) {
System.out.println(e.getMessage());
} catch (BceClientException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
使用非对称密钥
相比对称加密,非对称密钥通常用于在信任程度不对等的系统之间,实现数字签名验签或者加密传递敏感信息的目的。KMS支持的非对称密钥算法有以下几类:
RSA_1024/RSA_2048/RSA_4096
创建KMS生成的非对称密钥
该步骤与对称密钥的kms生成过程相似,密钥类型选择您需要创建的非对称密钥类型即可。
创建外部导入的非对称密钥
创建过程与对称密钥的外部导入过程相似
RSA密钥的导入
您使用正确的加密密钥材料加密您的信封密钥,形成信封密钥密文。并将公钥材料和通过信封密钥加密的私钥材料以及获取的令牌正确填入,点击确认即可导入。
注意,您需要使用aes128算法ecb加密模式来加密您的私钥各二进制分量。并且填入的信息需要base64加密。
控制台导入RSA密钥示例
- 准备一个aes128的对称密钥(KEK密钥),用来加密非对称密钥
例:11223344556677881122334455667788 (16进制形式,请注意是128位bytes)
- 准备一个待导入的RSA密钥
例:
名称 | 内容(16进制表示) |
---|---|
公钥(PKCS#1, ASN.1 DER form) |
30818902818100b985d0d957e8c17c3d2ed1a0e6d522dbf3a5812429aacaf1a0cc517112d9927d58166bc06 ce14481a443d0545751065f4220f2a3d03c553ebb4fd5f7849a2a574d0f92a3518a6ccc96f41092deca64dcf 8101edaefdf8597bcb30f74a93f82c203ac3d571a7073101c3b2fc7bd27060ef90245d5fe54356524a72ae 13bac91470203010001 |
D分量 |
43b683b3d05233cc94c831daf8657283b53a03189fdca695ea8aa86f0ce23c8563514ba2c01ab856590e27 4ba15301706342834d2703de593724bc83caf239e1643663fcb5490d623fa8fb325aefb5a6a954625af99e bc05c72c58f613bc0e822d77ee061223bc66d95a0d977a17a60eae8d4520fc8f335b2648f40400540c01 |
P分量 |
dc7dd1239889ca4f702f46563611b4495c643538b5136f064b834e865902513804f90c46903001bf23 5a1cc847a347609d7dbcb0b6a064a8d7180fe931b3bae1 |
Q分量 |
d766585371b4bf7a717ab2ffa20565d95009a02e00a4d07bd4fec73da1b9a8bd3cec173aa9a7 8b0f53a019d4bd19eb229411c46995f4b71c439554b5618f3927 |
DP分量 |
653e8ca2e8af14aba75abdd4665d78c85ad954aae652b71f4fdb4a5a5c52b9129d0df2ba10094 b34063aa18ec17e530f2522105ba07043e85764202237054d61 |
DQ分量 |
9f8425a9362ddb17bc6e579d44c9a69176da8a0b4762c71acdb418ad25d5ae86e6551926d27 9475c845bae8583bd6c0ae188fee20ab17de1aa932e765cd78a45 |
Qinv分量 |
25f1e8ea900548e3b9664e5c3719a2ba34155fdafb4b2f70cebcffddc6bcdd4815515694b91 6b2234314bd6be97edee735afef8e535461b608f6e4427a052381 |
- 在控制台创建一个待导入的RSA1024密钥
选择你需要导入的 RSA密钥类型。选择外部导入,并添加描述,点击确定即可创建一个RSA1024的外部导入密钥,此时密钥的状态处于待导入状态。
- 获取密钥参数文件 点击获取密钥参数
如果第一次创建,加密公钥和令牌为空,点击确认,获取导入密钥参数。
- 使用导入密钥参数处理待导入密钥
- 使用步骤1准备的 KEK密钥 来对 待导入的RSA1024密钥 除公钥以外的各分量二进制 进行加密,并转化为base64加密的字符串
名称 | 处理方法 |
---|---|
公钥材料密文 | 仅对公钥Der编码的二进制进行base64加密 |
密钥材料-D密文 | 使用KEK密钥(aes128 ECB)对D分量二进制进行加密 然后进行base64加密 |
密钥材料-P密文 | 使用KEK密钥(aes128 ECB)对P分量二进制进行加密 然后进行base64加密 |
密钥材料-Q密文 | 使用KEK密钥(aes128 ECB)对Q分量二进制进行加密 然后进行base64加密 |
密钥材料-Dp密文 | 使用KEK密钥(aes128 ECB)对Dp分量二进制进行加密 然后进行base64加密 |
密钥材料-Dq密文 | 使用KEK密钥(aes128 ECB)对Dq分量二进制进行加密 然后进行base64加密 |
密钥材料-Qinv密文 | 使用KEK密钥(aes128 ECB)对Qinv分量二进制进行加密 然后进行base64加密 |
- 使用密钥参数中的公钥对步骤一中准备的KEK密钥进行加密。得到信封密钥密文
echo "11223344556677881122334455667788"|xxd -ps -r > KeyMaterial.bin
cat public_key_xxxxxxx.txt |xxd -ps -r > PublicKey.bin
openssl rsautl -encrypt -in KeyMaterial.bin -pkcs -inkey PublicKey.bin -keyform DER -pubin -out EncryptedKeyMaterial.bin
openssl enc -e -base64 -A -in EncryptedKeyMaterial.bin -out EncryptedKeyMaterial_base64.txt
- 密钥导入
点击确认,导入密钥即完成
java sdk方式
import com.baidubce.BceClientException; import com.baidubce.BceServiceException; import com.baidubce.Protocol; import com.baidubce.auth.DefaultBceCredentials; import com.baidubce.services.kms.KmsClient; import com.baidubce.services.kms.KmsClientConfiguration; import com.baidubce.services.kms.model.*; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; import java.security.Key; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; import java.util.Random; public class testImportRSA1024 { public static void main(String[] args){ String ACCESS_KEY_ID = ""; String SECRET_ACCESS_KEY = ""; String ENDPOINT = "https://bkm.bj.baidubce.com"; // kms域名 // 初始化一个KmsClient KmsClientConfiguration config = new KmsClientConfiguration(); config.setCredentials(new DefaultBceCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY)); config.setEndpoint(ENDPOINT); config.setProtocol(Protocol.HTTPS); // 设置https协议 KmsClient client = new KmsClient(config); try { //产生一个16字节随机数作为信封密钥 byte[] keyMaterial = new byte[16]; new Random().nextBytes(keyMaterial); //创建一个RSA_1024待导入密钥 CreateKeyRequest createReq = new CreateKeyRequest(); createReq.setKeySpec("RSA_1024"); createReq.setKeyUsage("ENCRYPT_DECRYPT"); createReq.setOrigin("EXTERNAL"); createReq.setProtectedBy("HSM"); CreateKeyResponse createRes = client.createKey(createReq); String keyId = createRes.getKeyMetadata().getKeyId(); GetParametersForImportResponse getParametersRes = client .getParametersForImport
(new GetParametersForImportRequest(keyId,"BASE64")); String pubKey = getParametersRes.getPublicKey(); String token = getParametersRes.getImportToken(); byte[] publicKeyDer = DatatypeConverter.parseBase64Binary(pubKey); //解析成RSA的公钥 KeyFactory keyFact = KeyFactory.getInstance("RSA"); X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyDer); PublicKey publicKey = keyFact.generatePublic(spec); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] cipherDer = cipher.doFinal(keyMaterial); //加密后的信封密钥,需要进行base64编码 String encryptedKeyMaterial = DatatypeConverter.printBase64Binary(cipherDer); cipher = Cipher.getInstance("AES/ECB/NoPadding"); Key key = new SecretKeySpec(keyMaterial, "AES"); cipher.init(Cipher.ENCRYPT_MODE, key); //待导入的RSA密钥各分量(16进制表示) String publickDerHex = "30818902818100b985d0d957e8c17c3d2ed1a0e6d522dbf3a5812429aacaf1a0cc5171" +"12d9927d58166bc06ce14481a443d0545751065f4220f2a3d03c553ebb4fd5f7849a2a574d0f92a3518a6ccc96f41092deca64dcf" +"8101edaefdf8597bcb30f74a93f82c203ac3d571a7073101c3b2fc7bd27060ef90245d5fe54356524a72ae13bac91470203010001"; String D = "43b683b3d05233cc94c831daf8657283b53a03189fdca695ea8aa86f0ce
23c8563514ba2c01ab856590e274ba15301706342834d2" +"703de593724bc83caf239e1643663fcb5490d623fa8fb325aefb5a6a954625af99ebc05c72c58f613bc0e822d77
ee061223bc66d95a0d977a17a60eae8d4520f" +"c8f335b2648f40400540c01"; String P = "dc7dd1239889ca4f702f46563611b4495c643538b5136f064b834e865902513804f90c46903001bf23" +"5a1cc847a347609d7dbcb0b6a064a8d7180fe931b3bae1"; String Q = "d766585371b4bf7a717ab2ffa20565d95009a02e00a4d07bd4fec73da1b9a8bd3cec173aa9a78b0f53a" +"019d4bd19eb229411c46995f4b71c439554b5618f3927"; String DP = "653e8ca2e8af14aba75abdd4665d78c85ad954aae652b71f4fdb4a5a5c52b9129d0df2ba10094b3406" +"3aa18ec17e530f2522105ba07043e85764202237054d61"; String DQ = "9f8425a9362ddb17bc6e579d44c9a69176da8a0b4762c71acdb418ad25d5ae86e6551926d279475c845" +"bae8583bd6c0ae188fee20ab17de1aa932e765cd78a45"; String Qinv = "25f1e8ea900548e3b9664e5c3719a2ba34155fdafb4b2f70cebcffddc6bcdd4815515694b916b2234" +"314bd6be97edee735afef8e535461b608f6e4427a052381"; String publicDerBase64 = DatatypeConverter.printBase64Binary(DatatypeConverter
.parseHexBinary(publickDerHex)); System.out.println("publicDerBase64:"+publicDerBase64); String DBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal
(DatatypeConverter.parseHexBinary(D))); System.out.println("DBase64:"+DBase64); String PBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal
(DatatypeConverter.parseHexBinary(P))); System.out.println("DBase64:"+DBase64); String QBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal
(DatatypeConverter.parseHexBinary(Q))); System.out.println("DBase64:"+QBase64); String DPBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal
(DatatypeConverter.parseHexBinary(DP))); System.out.println("DBase64:"+DPBase64); String DQBase64 = DatatypeConverter.printBase64Binary(cipher.doFinal
(DatatypeConverter.parseHexBinary(DQ))); System.out.println("DBase64:"+DQBase64); String QinvBase64 = DatatypeConverter.printBase64Binary
(cipher.doFinal(DatatypeConverter.parseHexBinary(Qinv))); System.out.println("DBase64:"+QinvBase64); //初始化RSA导入密钥请求 ImportAsymmetricKeyRequest importReq = new ImportAsymmetricKeyRequest(); importReq.setKeyId(keyId); importReq.setImportToken(token); importReq.setAsymmetricKeySpec("RSA_1024"); importReq.setEncryptedKeyEncryptionKey(encryptedKeyMaterial); importReq.setAsymmetricKeyUsage("ENCRYPT_DECRYPT"); EncryptedRsaKey rsaKey = new EncryptedRsaKey(); rsaKey.setPublicKeyDer(publicDerBase64); rsaKey.setEncryptedD(DBase64); rsaKey.setEncryptedP(PBase64); rsaKey.setEncryptedQ(QBase64); rsaKey.setEncryptedDp(DPBase64); rsaKey.setEncryptedDq(DQBase64); rsaKey.setEncryptedQinv(QinvBase64); importReq.setEncryptedRsaKey(rsaKey); //导入RSA密钥 KmsResponse res = client.importAsymmetricKey(importReq); }catch (BceServiceException e) { System.out.println(e.getMessage()); } catch (BceClientException e) { System.out.println(e.getMessage()); } catch (Exception e) { System.out.println(e.getMessage()); } } }