Cloudfront предоставляет ответ «Отказано в доступе», созданный с помощью AWS CDK Python для источника корзины S3 без публикации c Доступ - PullRequest
1 голос
/ 28 марта 2020

Создан веб-дистрибутив Cloud Front с AWS CDK для корзины S3 без открытого доступа c. Возможность создания идентификатора доступа Origin и развертывания, но при успешном развертывании я получаю ответ об отказе в доступе в браузере.

Предоставление разрешений на чтение для корзины из настроек Origin будет установлено на Нет, для этого установлено значение Да, вручную все будет работать нормально, но эту настройку необходимо выполнить с помощью AWS CDK и python. Ниже приведен мой код.

from aws_cdk import aws_cloudfront as front, aws_s3 as s3

class CloudFrontStack(core.Stack):        
    def __init__(self, scope: core.Construct, idx: str, **kwargs) -> None:
        super().__init__(scope, idx, **kwargs)

        bucket = s3.Bucket.from_bucket_name(self, 'CloudFront',bucket_name="bucket_name")

        oia = aws_cloudfront.OriginAccessIdentity(self, 'OIA', comment="Created By CDK")
        bucket.grant_read(oia)

        s3_origin_source = aws_cloudfront.S3OriginConfig(s3_bucket_source=bucket, origin_access_identity=oia)

        source_config = aws_cloudfront.SourceConfiguration(s3_origin_source=s3_origin_source,
                                                           origin_path="bucket_path",
                                                           behaviors=[aws_cloudfront.Behavior(is_default_behavior=True)])

        aws_cloudfront.CloudFrontWebDistribution(self, "cloud_front_name",
                                                 origin_configs=[source_config],
                                                 comment='Cloud Formation created',
                                                 default_root_object='index.html')

Я также попытался добавить разрешения к приведенному ниже, но все равно не повезло.

policyStatement = aws_iam.PolicyStatement()
policyStatement.add_resources()

policyStatement.add_actions('s3:GetBucket*');
policyStatement.add_actions('s3:GetObject*');
policyStatement.add_actions('s3:List*');
policyStatement.add_resources(bucket.bucket_arn);
policyStatement.add_canonical_user_principal(oia.cloud_front_origin_access_identity_s3_canonical_user_id);
code_bucket.add_to_resource_policy(policyStatement);

1 Ответ

1 голос
/ 29 марта 2020

Я попытался имитировать c это и смог успешно интегрировать дистрибутив Cloudfront в частную корзину S3. Тем не менее, я использовал TS для своего стека. Я уверен, что будет легко соотнести приведенный ниже код с Python версией. Предположим, есть файл index.html в dist

aws -cdk v1.31.0 (последний по состоянию на 29 марта 2020 г.)

import { App, Stack, StackProps } from '@aws-cdk/core';
import { BucketDeployment, Source } from '@aws-cdk/aws-s3-deployment';
import { CloudFrontWebDistribution, OriginAccessIdentity } from '@aws-cdk/aws-cloudfront';
import { BlockPublicAccess, Bucket, BucketEncryption } from '@aws-cdk/aws-s3';

export class HelloCdkStack extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props);

    const myFirstBucket = new Bucket(this, 'MyFirstBucket', {
      versioned: true,
      encryption: BucketEncryption.S3_MANAGED,
      bucketName: 'cdk-example-bucket-for-test',
      websiteIndexDocument: 'index.html',
      blockPublicAccess: BlockPublicAccess.BLOCK_ALL
    });

    new BucketDeployment(this, 'DeployWebsite', {
      sources: [Source.asset('dist')],
      destinationBucket: myFirstBucket
    });

    const oia = new OriginAccessIdentity(this, 'OIA', {
      comment: "Created by CDK"
    });
    myFirstBucket.grantRead(oia);

    new CloudFrontWebDistribution(this, 'cdk-example-distribution', {
      originConfigs: [
        {
          s3OriginSource: {
            s3BucketSource: myFirstBucket,
            originAccessIdentity: oia
          },
          behaviors: [
            { isDefaultBehavior: true }
          ]
        }
      ]
    });
  }
}

== Обновление == [корзина S3 без веб-хостинга]

Вот пример, где S3 используется в качестве источника без веб-хостинга. Работает как положено.

import { App, Stack, StackProps } from '@aws-cdk/core';
import { BucketDeployment, Source } from '@aws-cdk/aws-s3-deployment';
import { CloudFrontWebDistribution, OriginAccessIdentity } from '@aws-cdk/aws-cloudfront';
import { BlockPublicAccess, Bucket, BucketEncryption } from '@aws-cdk/aws-s3';

export class CloudfrontS3Stack extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props);

    // Create bucket (which is not a static website host), encrypted AES-256 and block all public access
    // Only Cloudfront access to S3 bucket
    const testBucket = new Bucket(this, 'TestS3Bucket', {
      encryption: BucketEncryption.S3_MANAGED,
      bucketName: 'cdk-static-asset-dmahapatro',
      blockPublicAccess: BlockPublicAccess.BLOCK_ALL
    });

    // Create Origin Access Identity to be use Canonical User Id in S3 bucket policy
    const originAccessIdentity = new OriginAccessIdentity(this, 'OAI', {
      comment: "Created_by_dmahapatro"
    });
    testBucket.grantRead(originAccessIdentity);

    // Create Cloudfront distribution with S3 as Origin
    const distribution = new CloudFrontWebDistribution(this, 'cdk-example-distribution', {
      originConfigs: [
        {
          s3OriginSource: {
            s3BucketSource: testBucket,
            originAccessIdentity: originAccessIdentity
          },
          behaviors: [
            { isDefaultBehavior: true }
          ]
        }
      ]
    });

    // Upload items in bucket and provide distribution to create invalidations
    new BucketDeployment(this, 'DeployWebsite', {
      sources: [Source.asset('dist')],
      destinationBucket: testBucket,
      distribution,
      distributionPaths: ['/images/*.png']
    });
  }
}

== ОБНОВЛЕНИЕ == [S3 Bucket импортируется вместо создания в том же стеке]

Когда мы ссылаемся на существующую корзину S3, проблему можно воссоздать.

Причина :
Причина проблемы root находится здесь, в этой строке кода . autoCreatePolicy всегда будет false для импортированной корзины S3 . Чтобы заставить addResourcePolicy работать, либо импортированный сегмент должен уже иметь существующую политику Bucket, чтобы можно было добавлять новые операторы политики, либо вручную создавать новый BucketPolicy и добавлять операторы политики. В приведенном ниже коде я вручную создал политику сегмента и добавил необходимые инструкции политики. Это очень близко к проблеме github # 941 , но тонкое различие между созданием сегмента в стеке и импортом уже созданного сегмента.

import { App, Stack, StackProps } from '@aws-cdk/core';
import { CloudFrontWebDistribution, OriginAccessIdentity } from '@aws-cdk/aws-cloudfront';
import { Bucket, BucketPolicy } from '@aws-cdk/aws-s3';
import { PolicyStatement } from '@aws-cdk/aws-iam';

export class CloudfrontS3Stack extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props);

    const testBucket = Bucket.fromBucketName(this, 'TestBucket', 'dmahapatro-personal-bucket');

    // Create Origin Access Identity to be use Canonical User Id in S3 bucket policy
    const originAccessIdentity = new OriginAccessIdentity(this, 'OAI', {
      comment: "Created_by_dmahapatro"
    });

    // This does not seem to work if Bucket.fromBucketName is used
    // It works for S3 buckets which are created as part of this stack
    // testBucket.grantRead(originAccessIdentity);

    // Explicitly add Bucket Policy 
    const policyStatement = new PolicyStatement();
    policyStatement.addActions('s3:GetBucket*');
    policyStatement.addActions('s3:GetObject*');
    policyStatement.addActions('s3:List*');
    policyStatement.addResources(testBucket.bucketArn);
    policyStatement.addResources(`${testBucket.bucketArn}/*`);
    policyStatement.addCanonicalUserPrincipal(originAccessIdentity.cloudFrontOriginAccessIdentityS3CanonicalUserId);

    // testBucket.addToResourcePolicy(policyStatement);

    // Manually create or update bucket policy
    if( !testBucket.policy ) {
      new BucketPolicy(this, 'Policy', { bucket: testBucket }).document.addStatements(policyStatement);
    } else {
      testBucket.policy.document.addStatements(policyStatement);
    }

    // Create Cloudfront distribution with S3 as Origin
    const distribution = new CloudFrontWebDistribution(this, 'cdk-example-distribution', {
      originConfigs: [
        {
          s3OriginSource: {
            s3BucketSource: testBucket,
            originAccessIdentity: originAccessIdentity
          },
          behaviors: [
            { isDefaultBehavior: true }
          ]
        }
      ]
    });
  }
}
...