Назначение политики S3Bucket для использования только дистрибутивом CloudFront.

В этом сценарии показано, как я создаю идентификатор доступа к источнику CloudFront, корзину, в которой будет храниться мое веб-приложение, и как я назначаю политику корзины, чтобы разрешить доступ к корзине только из раздачи CloudFront.

Что действительно удивительно (и раздражает) при таком сценарии, так это тот факт, что этот код работает, если я отлаживаю его построчно в Eclipse, но если я пытаюсь запустить его, не переходя построчно (т.е. установка точки останова сразу после назначения политики), то появляется приведенное ниже исключение...

Надеюсь, кто-то может помочь!

String myBucket = transferManager.getAmazonS3Client().createBucket(new CreateBucketRequest("my-bucket-name")).getName();

CloudFrontOriginAccessIdentity myOAI = cloudFrontClient.createCloudFrontOriginAccessIdentity(
                        new CreateCloudFrontOriginAccessIdentityRequest().withCloudFrontOriginAccessIdentityConfig(
                                new CloudFrontOriginAccessIdentityConfig().withCallerReference(UUID.randomUUID().toString()).withComment("myOAI"))).getCloudFrontOriginAccessIdentity();

//*ATTEMPT 1: Using canonical user Id*
transferManager.getAmazonS3Client().setBucketPolicy(myBucketName, new Policy().
withId("MyPolicyForCloudFrontPrivateContent").
withStatements(new Statement(Effect.Allow).
withId("Grant CloudFront Origin Identity access to support private content").
withActions(S3Actions.GetObject).
withPrincipals(new Principal("CanonicalUser:" + myOAI.getS3CanonicalUserId())).
withResources(new S3ObjectResource(myBucketName,"*"))).toJson());

//*ATTEMPT 2: Using OAI id*
transferManager.getAmazonS3Client().setBucketPolicy(myBucketName, new Policy().
withId("MyPolicyForCloudFrontPrivateContent").
withStatements(new Statement(Effect.Allow).
withActions(S3Actions.GetObject).
withPrincipals(new Principal("arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity " + myOAI.getId())).
withResources(new S3ObjectResource(myBucketName,"*"))).toJson());

//*ATTEMP 3: HARDCODING THE POLICY*
String myPolicy = "{\"Version\":\"2012-10-17\",\"Id\":\"PolicyForCloudFrontPrivateContent\",\"Statement\":[{\"Sid\":\" Grant a CloudFront Origin Identity access to support private content\",\"Effect\":\"Allow\",\"Principal\":{\"CanonicalUser\":\"" + myOAI.getS3CanonicalUserId() + "\"},\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::" + myBucketName + "/*\"}]}";
transferManager.getAmazonS3Client().setBucketPolicy(myBucketName, myPolicy);


//*ERROR MESSAGE*

Exception in thread "main" com.amazonaws.services.s3.model.AmazonS3Exception: Invalid principal in policy (Service: Amazon S3; Status Code: 400; Error Code: MalformedPolicy; Request ID: XXXXXXXXXXXXX), S3 Extended Request ID: YYYYYYYYYYYYYYYYYYYYYY+XXXXXXXXXXXXXXXXXXXXXXX=
    at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1088)
    at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:735)
    at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:461)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:296)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3737)
    at com.amazonaws.services.s3.AmazonS3Client.setBucketPolicy(AmazonS3Client.java:2372)
    at com.myapp.services.DeploymentService.applyVersion(DeploymentService.java:234)
    at com.myapp.services.DeploymentService.launch(DeploymentService.java:3553)
    at com.myapp.EntryPoint.main(EntryPoint.java:35)

person Antonio Acevedo    schedule 20.04.2015    source источник


Ответы (1)


Нашел проблему...

Похоже, что когда вы создаете идентификатор Cloudfront Origin Access Identity (OAI) и пытаетесь сразу назначить его политике корзины, появляется ошибка, потому что это новое изменение OAI не распространяется немедленно.

Допустимым обходным путем является реализация политики условия повторной попытки:

class CloudFrontRetryCondition implements RetryCondition {
    @Override
    public boolean shouldRetry(AmazonWebServiceRequest originalRequest, AmazonClientException exception, int retriesAttempted) {
        if(exception instanceof AmazonS3Exception) {
            final AmazonS3Exception s3Exception = (AmazonS3Exception) exception;
            return  s3Exception.getStatusCode() == 400 &&
                    s3Exception.getErrorCode().equals("MalformedPolicy") &&
                    s3Exception.getErrorMessage().equals("Invalid principal in policy") &&
                s3Exception.getAdditionalDetails().get("Detail").contains("arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity");
        } else {
            return false;
        }
    }
}
person Antonio Acevedo    schedule 06.05.2015