private toOriginProperty()

in packages/aws-cdk-lib/aws-cloudfront/lib/web-distribution.ts [1081:1202]


  private toOriginProperty(originConfig: SourceConfigurationRender, originId: string): CfnDistribution.OriginProperty {
    if (
      !originConfig.s3OriginSource &&
      !originConfig.customOriginSource
    ) {
      throw new cdk.ValidationError(
        'There must be at least one origin source - either an s3OriginSource, a customOriginSource',
        this,
      );
    }
    if (originConfig.customOriginSource && originConfig.s3OriginSource) {
      throw new cdk.ValidationError(
        'There cannot be both an s3OriginSource and a customOriginSource in the same SourceConfiguration.',
        this,
      );
    }

    if ([
      originConfig.originHeaders,
      originConfig.s3OriginSource?.originHeaders,
      originConfig.customOriginSource?.originHeaders,
    ].filter(x => x).length > 1) {
      throw new cdk.ValidationError('Only one originHeaders field allowed across origin and failover origins', this);
    }

    if ([
      originConfig.originPath,
      originConfig.s3OriginSource?.originPath,
      originConfig.customOriginSource?.originPath,
    ].filter(x => x).length > 1) {
      throw new cdk.ValidationError('Only one originPath field allowed across origin and failover origins', this);
    }

    if ([
      originConfig.originShieldRegion,
      originConfig.s3OriginSource?.originShieldRegion,
      originConfig.customOriginSource?.originShieldRegion,
    ].filter(x => x).length > 1) {
      throw new cdk.ValidationError('Only one originShieldRegion field allowed across origin and failover origins', this);
    }

    const headers = originConfig.originHeaders ?? originConfig.s3OriginSource?.originHeaders ?? originConfig.customOriginSource?.originHeaders;

    const originHeaders: CfnDistribution.OriginCustomHeaderProperty[] = [];
    if (headers) {
      Object.keys(headers).forEach((key) => {
        const oHeader: CfnDistribution.OriginCustomHeaderProperty = {
          headerName: key,
          headerValue: headers[key],
        };
        originHeaders.push(oHeader);
      });
    }

    let s3OriginConfig: CfnDistribution.S3OriginConfigProperty | undefined;
    if (originConfig.s3OriginSource) {
      // first case for backwards compatibility
      if (originConfig.s3OriginSource.originAccessIdentity) {
        // grant CloudFront OriginAccessIdentity read access to S3 bucket
        // Used rather than `grantRead` because `grantRead` will grant overly-permissive policies.
        // Only GetObject is needed to retrieve objects for the distribution.
        // This also excludes KMS permissions; currently, OAI only supports SSE-S3 for buckets.
        // Source: https://aws.amazon.com/blogs/networking-and-content-delivery/serving-sse-kms-encrypted-content-from-s3-using-cloudfront/
        originConfig.s3OriginSource.s3BucketSource.addToResourcePolicy(new iam.PolicyStatement({
          resources: [originConfig.s3OriginSource.s3BucketSource.arnForObjects('*')],
          actions: ['s3:GetObject'],
          principals: [originConfig.s3OriginSource.originAccessIdentity.grantPrincipal],
        }));

        s3OriginConfig = {
          originAccessIdentity: `origin-access-identity/cloudfront/${originConfig.s3OriginSource.originAccessIdentity.originAccessIdentityId}`,
        };
      } else {
        s3OriginConfig = {};
      }
    }

    const connectionAttempts = originConfig.connectionAttempts ?? 3;
    if (connectionAttempts < 1 || 3 < connectionAttempts || !Number.isInteger(connectionAttempts)) {
      throw new cdk.ValidationError('connectionAttempts: You can specify 1, 2, or 3 as the number of attempts.', this);
    }

    const connectionTimeout = (originConfig.connectionTimeout || cdk.Duration.seconds(10)).toSeconds();
    if (connectionTimeout < 1 || 10 < connectionTimeout || !Number.isInteger(connectionTimeout)) {
      throw new cdk.ValidationError('connectionTimeout: You can specify a number of seconds between 1 and 10 (inclusive).', this);
    }

    const originProperty: CfnDistribution.OriginProperty = {
      id: originId,
      domainName: originConfig.s3OriginSource
        ? originConfig.s3OriginSource.s3BucketSource.bucketRegionalDomainName
        : originConfig.customOriginSource!.domainName,
      originPath: originConfig.originPath ?? originConfig.customOriginSource?.originPath ?? originConfig.s3OriginSource?.originPath,
      originCustomHeaders:
        originHeaders.length > 0 ? originHeaders : undefined,
      s3OriginConfig,
      originShield: this.toOriginShieldProperty(originConfig),
      customOriginConfig: originConfig.customOriginSource
        ? {
          httpPort: originConfig.customOriginSource.httpPort || 80,
          httpsPort: originConfig.customOriginSource.httpsPort || 443,
          originKeepaliveTimeout:
            (originConfig.customOriginSource.originKeepaliveTimeout &&
              originConfig.customOriginSource.originKeepaliveTimeout.toSeconds()) ||
            5,
          originReadTimeout:
            (originConfig.customOriginSource.originReadTimeout &&
              originConfig.customOriginSource.originReadTimeout.toSeconds()) ||
            30,
          originProtocolPolicy:
            originConfig.customOriginSource.originProtocolPolicy ||
            OriginProtocolPolicy.HTTPS_ONLY,
          originSslProtocols: originConfig.customOriginSource
            .allowedOriginSSLVersions || [OriginSslPolicy.TLS_V1_2],
        }
        : undefined,
      connectionAttempts,
      connectionTimeout,
    };

    return originProperty;
  }