代码之家  ›  专栏  ›  技术社区  ›  Alex

为什么只有root用户才能从EC2实例上传到运行Java程序的S3 bucket?

  •  3
  • Alex  · 技术社区  · 7 年前

    我们的应用程序在将数据上传到S3 bucket crystal dyn时遇到了问题。这种上传在Centos-6实例上可以很好地使用相同的程序,但在RHEL7实例上失败。

    {
    "RoleName": "crystal-role", 
    "PolicyDocument": {
        "Version": "2012-10-17", 
        "Statement": [
            {
                "Action": [
                    "ec2:DescribeInstances"
                ], 
                "Resource": "*", 
                "Effect": "Allow", 
                "Sid": "AllowDescribeInstances"
            }, 
            {
                "Action": [
                    "s3:ListBucket", 
                    "s3:GetBucketLocation"
                ], 
                "Resource": [
                    "arn:aws:s3:::crystal-dyn" 
                ], 
                "Effect": "Allow", 
                "Sid": "AllowSeeLogBucket"
            }, 
            {
                "Action": [
                    "s3:PutObject"
                ], 
                "Resource": [
                    "arn:aws:s3:::crystal-dyn/*" 
                ], 
                "Effect": "Allow", 
                "Sid": "AllowPutLogs"
            }, 
            {
                "Action": [
                    "kms:Encrypt", 
                    "kms:GenerateDataKey"
                ], 
                "Resource": [
                    "arn:aws:kms:us-east-1:566:key/a15912a107bb", 
                    "arn:aws:kms:us-east-1:566201213358:key/158d81e9467a"
                ], 
                "Effect": "Allow", 
                "Sid": "AllowEncrypt"
            }, 
            {
                "Action": "sts:AssumeRole", 
                "Resource": "arn:aws:iam::389203956472:role/allow-cross-account-exec-api-qa2", 
                "Effect": "Allow", 
                "Sid": "AllowApiAccess"
            }
        ]
    }, 
    "PolicyName": "crystal-policy"
    }
    

    此策略应允许在实例上运行的Java应用程序将数据上载到S3存储桶。

    java -cp ".:lib/*" org.examples.UploadObject
    

    在lib中,我有以下jar:

    aws-java-sdk-1.10.10.jar        aws-java-sdk-s3-1.11.339.jar  httpclient-4.5.5.jar  jackson-annotations-2.9.5.jar  jackson-databind-2.9.5.jar
    aws-java-sdk-core-1.11.423.jar  commons-logging-1.1.3.jar     httpcore-4.4.9.jar    jackson-core-2.9.5.jar         joda-time-2.9.9.jar
    

    Java代码:

       String clientRegion = "us-east-1";
        String bucketName = "crystal-dyn";
        String stringObjKeyName = "stringToUploadTest";
        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(DefaultAWSCredentialsProviderChain.getInstance()).withRegion(clientRegion).build();
            System.out.println("s3Client=" + s3Client);
            s3Client.putObject(bucketName, stringObjKeyName, "Uploaded String Object");
            System.out.println("Uploading String  is done");
        }
        catch(AmazonServiceException e) {
            e.printStackTrace();
        }
        catch(SdkClientException e) {
            e.printStackTrace();
        }
    try {
            System.out.println("Uploading to S3 bucket=" + bucketName + " string=" + stringObjKeyName  + " Building with No Creds");
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion(clientRegion).build();
            System.out.println("s3Client=" + s3Client);
            s3Client.putObject(bucketName, stringObjKeyName, "Uploaded String Object");
            System.out.println("Uploading String  is done");
        }
        catch(AmazonServiceException e) {
            e.printStackTrace();
        }
        catch(SdkClientException e) {
            e.printStackTrace();
        }
        try {
            System.out.println("Uploading to S3 bucket=" + bucketName + " string=" + stringObjKeyName  + " Building with No Creds and No region");
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard().build();
            System.out.println("s3Client=" + s3Client);
            s3Client.putObject(bucketName, stringObjKeyName, "Uploaded String Object");
            System.out.println("Uploading String  is done");
        }
        catch(AmazonServiceException e) {
            e.printStackTrace();
        }
        catch(SdkClientException e) {
            e.printStackTrace();
        }
    

    s3Client=com.amazonaws.services.s3.AmazonS3Client@682b2fa
    com.amazonaws.SdkClientException: Unable to load AWS credentials from 
    any provider in the chain: [EnvironmentVariableCredentialsProvider: 
    Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY)), SystemPropertiesCredentialsProvider: Unable to load AWS credentials from Java system properties (aws.accessKeyId and aws.secretKey), com.amazonaws.auth.profile.ProfileCredentialsProvider@20d525: profile file cannot be null, com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@3f56875e: Unable to load credentials from service endpoint]
    at com.amazonaws.auth.AWSCredentialsProviderChain.getCredentials(AWSCredentialsProviderChain.java:136)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.getCredentialsFromContext(AmazonHttpClient.java:1186)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:776)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:726)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:719)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:701) 
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:669)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:651)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:515)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4365)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4312)
    at com.amazonaws.services.s3.AmazonS3Client.putObject(AmazonS3Client.java:1755)
    at com.amazonaws.services.s3.AmazonS3Client.putObject(AmazonS3Client.java:3448)
    at org.examples.UploadObject.main(UploadObject.java:20)
    Uploading to S3 bucket=dynarch-ac-logs-malachite-dyn 
    string=stringToUploadTest Building with No Creds
    s3Client=com.amazonaws.services.s3.AmazonS3Client@740773a3
    com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: AF2735F42CCB60D0; S3 Extended Request ID: 7VyScO6XOs00oB/g0k8bqG3X3Ib01n4uT1xg8/2U72TCOKg8YKNIVgQrjjnF6XzUAfoB24wcYZY=), S3 Extended Request ID: 7VyScO6XOs00oB/g0k8bqG3X3Ib01n4uT1xg8/2U72TCOKg8YKNIVgQrjjnF6XzUAfoB24wcYZY=
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1660)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1324)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1074)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:745)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:719)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:701)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:669)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:651)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:515)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4365)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4312)
    at com.amazonaws.services.s3.AmazonS3Client.putObject(AmazonS3Client.java:1755)
    at com.amazonaws.services.s3.AmazonS3Client.putObject(AmazonS3Client.java:3448)
    at org.examples.UploadObject.main(UploadObject.java:33)
    Uploading to S3 bucket=dynarch-ac-logs-malachite-dyn 
    string=stringToUploadTest Building with No Creds and No region
    com.amazonaws.SdkClientException: Unable to find a region via the region provider chain. Must provide an explicit region in the builder or setup environment to supply a region.
    at com.amazonaws.client.builder.AwsClientBuilder.setRegion(AwsClientBuilder.java:436)
    at com.amazonaws.client.builder.AwsClientBuilder.configureMutableProperties(AwsClientBuilder.java:402)
    at com.amazonaws.client.builder.AwsSyncClientBuilder.build(AwsSyncClientBuilder.java:46)
    at org.examples.UploadObject.main(UploadObject.java:44)
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   Imran    7 年前

    https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-install.html

    sudo sh -c "echo 'net.ipv4.conf.all.route_localnet = 1' >> /etc/sysctl.conf"
    sudo sysctl -p /etc/sysctl.conf
    
    sudo iptables -t nat -A PREROUTING -p tcp -d 169.254.170.2 --dport 80 -j DNAT --to-destination 127.0.0.1:51679
    sudo iptables -t nat -A OUTPUT -d 169.254.170.2 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 51679
    
    sudo sh -c 'iptables-save > /etc/iptables/rules.v4'
    //OR
    sudo sh -c 'iptables-save > /etc/sysconfig/iptables'
    
        2
  •  2
  •   Alex    7 年前

    问题似乎出在iptables规则中,该规则只允许访问根目录。

    iptables -L | grep root
    DROP       all  --  anywhere             instance-data.ec2.internal  ! owner UID match root