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" # 清单所存储桶
    }
  ]
}
最后修改:2023 年 06 月 26 日
如果觉得我的文章对你有用,请随意赞赏