2015-04-20 60 views
1

此腳本顯示了我如何創建CloudFront原始訪問標識,一個可容納我的Web應用的存儲桶以及如何分配存儲桶策略以僅允許訪問來自CloudFront分配的存儲桶。將策略分配給S3Bucket以便僅供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) 

回答

0

發現問題...

它看起來當您創建的Cloudfront原產地訪問標識(OAI)像,並嘗試將其分配到一個水桶政策inmediately出現的錯誤,因爲新的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; 
     } 
    } 
}