AWS KMS 实现跨租户的安全数据加密(二)

阅读数:5 2019 年 12 月 26 日 13:47

AWS KMS 实现跨租户的安全数据加密(二)

3 配置 Cognito identity pool 及 IAM 角色

3.1 创建 Identity pool 及 IAM role

AWS KMS 实现跨租户的安全数据加密(二)

3.2 配置 Developer provider name

AWS KMS 实现跨租户的安全数据加密(二)

3.3 创建 IAM 角色

利用 identity pool 生成的 身份证书管理 CMK(权限已在 CMK 管理中指定),删除其他的权限

AWS KMS 实现跨租户的安全数据加密(二)

4 实现 Cognito Developer provider

Java

复制代码
/*
*
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
* in compliance with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.amazon.saas.idp;
import java.util.Collections;
import java.util.Map;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentity;
import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClientBuilder;
import com.amazonaws.services.cognitoidentity.model.GetCredentialsForIdentityRequest;
import com.amazonaws.services.cognitoidentity.model.GetCredentialsForIdentityResult;
import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenForDeveloperIdentityRequest;
import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenForDeveloperIdentityResult;
public class CognitoDeveloperIdentityProvider {
private String region = "cn-north-1";
//cognito 对于 sts 的 provider id 中国区选择 "cognito-identity.cn-north-1.amazonaws.com.cn"
private String cognitoProviderId= "cognito-identity.cn-north-1.amazonaws.com.cn"
// 前面配置的 Developer Identity Provider Name
private String developerIdentityProviderName = "developerIdentityProviderName";
// indentity pool id 如 cn-north-1:cc310c44-de78-4661-8e6e-8cc21d974058
private String identityPoolId="cn-north-1:cc310c44-de78-4661-8e6e-8cc21d974058";
private AmazonCognitoIdentity amazonCognitoIdentity;
// 构建 AmazonCognitoIdentityClient
public void init() {
AmazonCognitoIdentityClientBuilder cidBuilder = AmazonCognitoIdentityClientBuilder.standard();
cidBuilder.setRegion(region);
cidBuilder.setCredentials(DefaultAWSCredentialsProviderChain.getInstance());
amazonCognitoIdentity = cidBuilder.build();
}
// 获取 cognito OpenIdToken
public GetOpenIdTokenForDeveloperIdentityResult getOpenIdTokenFromCognito(String tenantid, String userid) {
GetOpenIdTokenForDeveloperIdentityRequest request = new GetOpenIdTokenForDeveloperIdentityRequest();
request.setIdentityPoolId(identityPoolId);
Map<String, String> logins = Collections.singletonMap(developerIdentityProviderName, tenantid + ":" + userid);
request.setLogins(logins);
GetOpenIdTokenForDeveloperIdentityResult result = amazonCognitoIdentity
.getOpenIdTokenForDeveloperIdentity(request);
return result;
}
// 获取 aws credentials 用于调用 KMS
public GetCredentialsForIdentityResult getCredentialsForIdentity(String identityid, String token, TenantUserInfo userinfo) {
GetCredentialsForIdentityRequest request = new GetCredentialsForIdentityRequest();
request.setIdentityId(identityid);
request.setLogins(Collections.singletonMap(cognitoProviderId, token));
GetCredentialsForIdentityResult result = amazonCognitoIdentity.getCredentialsForIdentity(request);
return result;
}
}

5 实现数据加密解密

5.1 AWS 证书与 data key 缓存

Java

复制代码
/*
*
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
* in compliance with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.amazon.saas.tes;
import java.util.concurrent.TimeUnit;
import com.amazon.saas.tes.TenantCryptoMaterialsManagerHolder.Cachekey;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.encryptionsdk.CryptoMaterialsManager;
import com.amazonaws.encryptionsdk.MasterKeyProvider;
import com.amazonaws.encryptionsdk.caching.CachingCryptoMaterialsManager;
import com.amazonaws.encryptionsdk.caching.CryptoMaterialsCache;
import com.amazonaws.encryptionsdk.caching.LocalCryptoMaterialsCache;
import com.amazonaws.encryptionsdk.kms.KmsMasterKey;
import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
public class TenantCryptoMaterialsManagerHolder extends CacheLoader<Cachekey, CryptoMaterialsManager> {
@Getter
@Setter
@AllArgsConstructor
public static class Cachekey {
private String tenantID;
private String userid;
}
@Data
public static class Config {
private String keyArn;
private int maxCacheSize;
private int maxEntryAge;
private int credentialsDuration;
}
private LoadingCache<Cachekey, CryptoMaterialsManager> cache;
private Config config;
public void init() {
// 配置缓存参数
config=new Config();
cache = CacheBuilder.newBuilder().maximumSize(10000)
.expireAfterWrite(config.getCredentialsDuration(), TimeUnit.MINUTES).build(this);
}
public CryptoMaterialsManager createMaterialsManager(Cachekey key) {
Credentials credentialsForIdentity = cognitoDeveloperIdentityProviderClient;
MasterKeyProvider<KmsMasterKey> keyProvider = KmsMasterKeyProvider.builder()
.withKeysForEncryption(config.getKeyArn())
.withCredentials(new BasicSessionCredentials(credentialsForIdentity.getAccessKeyId(),
credentialsForIdentity.getSecretKey(), credentialsForIdentity.getSessionToken()))
.build();
int MAX_CACHE_SIZE = config.getMaxCacheSize();
CryptoMaterialsCache cache = new LocalCryptoMaterialsCache(MAX_CACHE_SIZE);
int MAX_ENTRY_AGE_SECONDS = config.getMaxEntryAge();
int MAX_ENTRY_MSGS = config.getMaxCacheSize();
CryptoMaterialsManager cachingCmm = CachingCryptoMaterialsManager.newBuilder()
.withMasterKeyProvider(keyProvider).withCache(cache).withMaxAge(MAX_ENTRY_AGE_SECONDS, TimeUnit.SECONDS)
.withMessageUseLimit(MAX_ENTRY_MSGS).build();
return cachingCmm;
}
public CryptoMaterialsManager getMaterialsManager(TenantUserInfo userinfo) {
return cache.get(new Cachekey(userinfo.getTenantID(), userinfo.getUserid()));
}
@Override
public CryptoMaterialsManager load(Cachekey key) throws Exception {
return createMaterialsManager(key);
}
}

5.2 数据加密解密

Java

复制代码
/*
*
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
* in compliance with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
*/
package com.amazon.saas.tes;
import java.util.Collections;
import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CryptoMaterialsManager;
import com.amazonaws.encryptionsdk.CryptoResult;
import org.springframework.beans.factory.annotation.Autowired;
public class EncDecService {
private final AwsCrypto crypto = new AwsCrypto();
@Autowired
TenantCryptoMaterialsManagerHolder tenantCryptoMaterialsManagerHolder;
public TESEncryptedMessage encrypt(String plaintext, String authorizationHeader, TenantUserInfo userinfo) {
CryptoMaterialsManager cmm = tenantCryptoMaterialsManagerHolder.getMaterialsManager(authorizationHeader,
userinfo);
String message = crypto.encryptString(cmm, plaintext,
Collections.singletonMap("tenantid.userid", userinfo.getTenantID() + "." + userinfo.getUserid()))
.getResult();
TESEncryptedMessage re = new TESEncryptedMessage();
re.setEncyptedMsg(message);
return re;
}
public TesPlainText dectypt(String encryptMessage, String authorizationHeader, TenantUserInfo userinfo) {
CryptoMaterialsManager cmm = tenantCryptoMaterialsManagerHolder.getMaterialsManager(authorizationHeader,
userinfo);
CryptoResult<String, ?> decryptResult = crypto.decryptString(cmm, encryptMessage);
TesPlainText re = new TesPlainText();
re.setText(decryptResult.getResult());
return re;
}

作者介绍:
*

!
复制代码
AWS 解决方案架构师,负责企业客户应用在 AWS 的架构咨询和 设计。在微服务架构设计、数据库等领域有丰富的经验

本文转载自 AWS 技术博客。

原文链接: https://amazonaws-china.com/cn/blogs/china/aws-kms-enables-secure-data-encryption-across-tenants/

欲了解 AWS 的更多信息,请访问【AWS 技术专区】

评论

发布