1 Amazon S3 简介
Amazon Simple Storage Service(Amazon S3)是一种对象存储服务,具有行业领先的可扩展性、数据可用性、安全性和性能。各种规模和行业的客户都可以使用 Amazon S3 存储和保护任意数量的数据,用于数据湖、网站、移动应用程序、备份和恢复、归档、企业应用程序、IoT 设备和大数据分析。Amazon S3 还提供了管理功能,使用户可以优化、组织和配置对数据的访问,以满足用户的特定业务、组织和合规性要求。
S3 理论上是一个全球存储区域网络 (SAN),它表现为一个超大的硬盘,用户可以在其中存储和检索数字资产。但是,从技术上讲,Amazon 的架构有一些不同。用户通过 S3 存储和检索的资产被称为对象。对象存储在存储段(bucket)中。这可以用硬盘进行类比:对象就像是文件,存储段就像是文件夹(或目录)。与硬盘一样,对象和存储段也可以通过统一资源标识符(Uniform Resource Identifier,URI)查找。
2 JAVA API
2.1 定义登陆信息
@Data
@Component
@ConfigurationProperties(prefix = "s3a")
public class S3Entiy {
private String impl;
private String accessKey;
private String secretKey;
private String endpoint;
private String bucket;
}
2.2 初始化S3连接
public AmazonS3 initAmazonS3() {
AmazonS3 s3 = new AmazonS3Client(new BasicAWSCredentials(entiy.getAccessKey(), entiy.getSecretKey()));
s3.setRegion(Region.getRegion(Regions.CN_NORTH_1));
s3.setEndpoint(entiy.getEndpoint());
s3.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build());
return s3;
}
2.3 获取 Account 信息
public String getAccount() {
return initAmazonS3().getS3AccountOwner().getId();
}
2.4 桶存在
public boolean isExistBucket(String bucketName) {
try {
HeadBucketRequest request = new HeadBucketRequest(bucketName);
initAmazonS3().headBucket(request);
} catch (Exception e) {
return false;
}
return true;
}
2.5 桶列表
public List<Bucket> listBuckets() {
ListBucketsRequest request = new ListBucketsRequest();
assert initAmazonS3() != null;
return initAmazonS3().listBuckets(request);
}
2.6 建桶
public void creatBucket(String bucketName) {
boolean existBucket = isExistBucket(bucketName);
if (!existBucket) {
try {
CreateBucketRequest request = new CreateBucketRequest(bucketName);
initAmazonS3().createBucket(request);
} catch (Exception e) {
System.out.printf("s3Client error " + e.getMessage());
}
}
}
2.7 删桶
public void deleteBucket(String bucketName) {
try {
DeleteBucketRequest request = new DeleteBucketRequest(bucketName);
initAmazonS3().deleteBucket(request);
} catch (Exception e) {
System.out.println("s3Client error {} "+ e.getMessage());
}
}
2.8 根据桶名称获取文件集合
public List<S3ObjectSummary> getFileMsgByBucketName(String bucketName) {
ObjectListing objectListing = initAmazonS3().listObjects(bucketName);
List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
return objectSummaries;
}
2.9 获取桶文件总大小
public long getFolderSize(String bucketName) {
ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName(bucketName);
ObjectListing objectListing;
long totalSize = 0;
do {
objectListing = initAmazonS3().listObjects(listObjectsRequest);
for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
totalSize += objectSummary.getSize();
}
listObjectsRequest.setMarker(objectListing.getNextMarker());
} while (objectListing.isTruncated());
return totalSize;
}
2.10 获取文件信息
public HashMap<String, Object> getFileInfo(String bucketName, String fileName) {
S3Object file = initAmazonS3().getObject(bucketName, fileName);
ObjectMetadata metadata = initAmazonS3().getObjectMetadata(bucketName, fileName);
HashMap<String, Object> fileInfoMap = new HashMap<>();
fileInfoMap.put("BucketName", file.getBucketName());
fileInfoMap.put("Key", file.getKey());
fileInfoMap.put("Size", metadata.getContentLength());
fileInfoMap.put("StorageClass", metadata.getStorageClass());
fileInfoMap.put("ETag", metadata.getETag());
fileInfoMap.put("UserMetadata", metadata.getUserMetadata());
return fileInfoMap;
}
2.11 上传
public String uploadFile(File file, String bucketName) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(file.length());
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, file.getName(), inputStream, objectMetadata);
initAmazonS3().putObject(putObjectRequest);
return bucketName + "/" + file.getName();
} catch (Exception e) {
return "uploadFile error " + e.getMessage();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
return "inputStream close error " + e.getMessage();
}
}
}
}
2.12 下载
public InputStream downloadFile(String bucketName, String fileName) {
GetObjectRequest request = new GetObjectRequest(bucketName, fileName);
S3Object response = initAmazonS3().getObject(request);
return response.getObjectContent();
}
2.13 删文件
public void deleteFile(String bucketName, String fileKey) {
try {
DeleteObjectRequest request = new DeleteObjectRequest(bucketName, fileKey);
initAmazonS3().deleteObject(request);
} catch (Exception e) {
System.out.println("s3Client error {} "+ e.getMessage());
}
}
2.14 查看桶策略
public BucketPolicy getPolicy(String bucketName) {
BucketPolicy bucketPolicy = initAmazonS3().getBucketPolicy(bucketName);
return bucketPolicy;
}
2.15 设置桶策略
public void setPolicy(String bucketName, String policyText) {
SetBucketPolicyRequest request = new SetBucketPolicyRequest(bucketName, policyText);
initAmazonS3().setBucketPolicy(request);
}
3 桶策略
S3 桶策略是一种控制对 S3 Bucket 的访问权限的方法,可以让用户授权或拒绝访问请求,以及控制谁可以访问用户的 Bucket 和 Bucket 中的对象。S3 桶策略使用 JSON 格式编写,可以定义一组规则,以便控制对 Bucket 和对象的访问权限。S3 桶策略可以与 AWS Identity and Access Management (IAM) 策略结合使用,以提供更精细的访问控制。
桶策略的配置可以帮助用户指定哪些 AWS 实体可以访问 Bucket 和对象,以及可以执行哪些操作,例如上传、下载、删除等;限制访问权限和启用加密等安全措施,限制特定的 IP 地址范围访问 Bucket 和对象,防止未经授权的访问和数据泄露;控制访问 Bucket 和 Bucket 中的对象的成本;限制访问权限和使用生命周期规则等。
3.1 使用 SSE-KMS
要求写入桶的每个对象都通过使用 AWS Key Management Service(AWS KMS)密钥的服务器端加密(SSE-KMS)进行加密。如果对象未使用 SSE-KMS 进行加密,则请求将被拒绝。
{
"Version": "2012-10-17",
"Id": "PutObjPolicy",
"Statement": [{
"Sid": "DenyObjectsThatAreNotSSEKMS",
"Principal": "*",
"Effect": "Deny",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
"Condition": {
"Null": {
"s3:x-amz-server-side-encryption-aws-kms-key-id": "true"
}
}
}]
}
3.2 仅允许访问组织
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowGetObject",
"Principal": {
"AWS": "*"
},
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": ["o-aa111bb222"]
}
}
}]
}
3.3 限定访问 IP
{
"Version": "2012-10-17",
"Id": "S3PolicyId1",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET",
"arn:aws:s3:::DOC-EXAMPLE-BUCKET1/*"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "192.0.2.0/24"
}
}
}
]
}
3.4 对特定文件夹的访问权限
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowRootAndHomeListingOfCompanyBucket",
"Principal": {
"AWS": [
"arn:aws:iam::You-Account:user/JohnDoe"
]
},
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET"],
"Condition": {
"StringEquals": {
"s3:prefix": ["", "home/", "home/JohnDoe"],
"s3:delimiter": ["/"]
}
}
},
{
"Sid": "AllowListingOfUserFolder",
"Principal": {
"AWS": [
"arn:aws:iam::You-Account:user/JohnDoe"
]
},
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET"],
"Condition": {
"StringLike": {
"s3:prefix": ["home/JohnDoe/*"]
}
}
},
{
"Sid": "AllowAllS3ActionsInUserFolder",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::You-Account:user/JohnDoe"
]
},
"Action": ["s3:*"],
"Resource": ["arn:aws:s3:::DOC-EXAMPLE-BUCKET/home/JohnDoe/*"]
}
]
}
3.5 删除权限设置
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:DeleteObject",
"s3:DeleteObjectVersion"
],
"Resource": [
"arn:aws:s3:::test0523-file/*"
]
}
]
}
本例表示不允许删除所有文件。
Statement:
其值是一个列表,包含一个或多个策略规则。本例只有一个策略规则。Effect": "Deny" :
指定策略规则的效果为拒绝(Deny)访问,如果需要允许访问而不是拒绝访问,则可以将其设置为 "Allow"。*"Principal": "":**
指定此策略规则适用的 AWS 账户或 IAM 用户/角色。在此示例中,所有人都将受到此策略规则的影响。如果需要限制此规则适用的用户或角色,则可以将此值设置为相应的 ARN。"Action": ["s3:DeleteObject","s3:DeleteObjectVersion"]
指定此策略规则将禁止的 S3 操作,包含在一个 JSON 数组中。在此示例中,策略规则将阻止删除对象和对象版本。如果需要禁止其他操作,则可以将此值更改为相应的操作。*"Resource": ["arn:aws:s3:::test0523-file/"]**
指定此策略规则适用的 S3 存储桶和其下的所有对象,包含在一个 JSON 数组中。在此示例中,策略规则将适用于名为 "test0523-file" 的存储桶和其下的所有对象。如果需要将策略规则应用于其他存储桶或特定的对象,则可以更改此值为相应的 ARN。
3.6 启用日志
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3ServerAccessLogsPolicy",
"Effect": "Allow",
"Principal": {
"Service": "logging.s3.amazonaws.com"
},
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::test0523-file/*",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:s3:::test0523-inventory"
},
"StringEquals": {
"aws:SourceAccount": "testuser"
}
}
}
]
}
"Resource" 指定了生成日志的桶
"Condition" 中 "ArnLike" 指定了存储文件桶位置。
"StringEquals" 中 "aws:SourceAccount" 指定了被允许的 AWS 账户。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::test0523-inventory",
"Condition": {
"ArnLike": {
"aws:SourceArn": "arn:aws:s3:::test0523"
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::testuser:root"
},
"Action": [
"s3:GetBucketInventoryConfiguration",
"s3:DeleteBucketInventoryConfiguration"
],
"Resource": "arn:aws:s3:::test0523-inventory" # 清单所存储桶
}
]
}