-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cloudfront: Support Origin Access Control #21771
cloudfront: Support Origin Access Control #21771
Comments
We should have L1 support soon, any higher level abstractions for this new feature may take a bit to be implemented as we see how customers use the L1 construct |
Hey, Is the L1 support out? Is it for now we can only use OAI with CDK? Thanks
|
Okay, so while it's true that updates haven't happen, the required type has not made it into the resource specification yet. So this is still basically waiting on CloudFormation Resource Specification to update. |
I just had a look and do actually see the OAC in the resource specification listed as:
|
Oh nice! Yeah, so it looks like now this actually is blocked by #21957 (or the underlying tracked issue) since OAC was added in spec v88.0.0! |
Looks like once this PR is merged and released we should have L1 constructs :) |
I've started poking at implementing this (based off the branch created by #22026) and the real pain is going to be from the fact that the principal of the OAC is the CloudFront service principal with a condition of This can possibly be solved with some lazy evaluation but it will probably require a bit more than that. A somewhat obvious (and equally obviously suboptimal) solution would be to not specify the Another thing is that while the examples in the docs always show a 1:1 OAC:Origin mapping, the CloudFormation resource structure seems to imply that it could be many:many (whether the underlying service allows this is a different matter). Even if a Distribution "silently" created an OAC, that would need to be passed to the Origin constructs (for the distribution ARN and the OAC ID). But some good news is that at least if passing this data around is solved, adding the statement(s) the KMS key's (if present) resource policy should be trivial (since it'd be a mirror of the S3 bucket). So with this situation, it will be a little harder to implement than I had assumed in the opening message before seeing the L1 constructs irl. I am not going to open a PR based on by branch because I fear it'd generate quite a bit of noise. But the following links should be sufficient to understand where it's at:
|
This issue has received a significant amount of attention so we are automatically upgrading its priority. A member of the community will see the re-prioritization and provide an update on the issue. |
I think the CloudFormation team may have pulled the rug out from under the feature flag effort. It looks like the Origin Access Identity is not supported in CloudFormation and now the L2 CloudFront classes won't work at all in terms of S3 access control. I have a demonstration here #22451 A note for those working around this via L1 cfn classes. The Route53 CfnRecordSet Alias has a hosted zone Id attribute that is different from the hosted zone Id attribute on the RecordSet itself. You will probably just want to set it to the static
|
Did someone manage to make it work for use cases like:
I have a piece of WIP code related to 1st point in the list but no I continue to get forbidden when I try to access the content inside the S3 origin. oac = cf.CfnOriginAccessControl(
self,
'OAC',
origin_access_control_config=cf.CfnOriginAccessControl.
OriginAccessControlConfigProperty(
name=f'{cdk.Stack.of(self).stack_name}_OAC',
description=f'[{environment}] OAC to access buckets',
origin_access_control_origin_type='s3',
signing_behavior='always',
signing_protocol='sigv4',
),
)
cf_distro = t.cast(
cf.CfnDistribution,
distro.node.default_child,
)
cf_distro.add_property_override(
'DistributionConfig.Origins.0.OriginAccessControlId',
oac.get_att('Id'),
)
cf_distro.add_property_override(
'DistributionConfig.Origins.0.S3OriginConfig.OriginAccessIdentity',
'',
)
bucket.add_to_resource_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
's3:GetObject',
],
principals=[iam.ServicePrincipal('cloudfront')],
resources=[bucket.arn_for_objects('*')],
conditions={
'StringEquals': {
'AWS:SourceArn': cdk.Stack.of(self).format_arn(
service='cloudfront',
region='',
resource='distribution',
resource_name=distro.distribution_id,
arn_format=cdk.ArnFormat.SLASH_RESOURCE_NAME,
),
},
},
),
) |
I got it working for the first case, here's the snippet. const oac = new cloudfront.CfnOriginAccessControl(this, 'AOC', {
originAccessControlConfig: {
name: 'AOC',
originAccessControlOriginType: 's3',
signingBehavior: 'always',
signingProtocol: 'sigv4',
},
})
const cloudFrontWebDistribution = new cloudfront.CloudFrontWebDistribution(this, 'CDN', {
originConfigs: [
{
s3OriginSource: {
s3BucketSource: this.s3Bucket,
},
behaviors: [
{
isDefaultBehavior: true,
allowedMethods: cloudfront.CloudFrontAllowedMethods.GET_HEAD,
compress: true,
cachedMethods: cloudfront.CloudFrontAllowedCachedMethods.GET_HEAD,
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
minTtl: cdk.Duration.seconds(0),
maxTtl: cdk.Duration.seconds(86400),
defaultTtl: cdk.Duration.seconds(3600),
},
],
},
],
})
const cfnDistribution = cloudFrontWebDistribution.node.defaultChild as CfnDistribution
cfnDistribution.addPropertyOverride('DistributionConfig.Origins.0.OriginAccessControlId', oac.getAtt('Id')) |
@hfgbarrigas Hasn't that left OAI somewhere around? I think I have been trying something similar but it hasn't worked until I have removed OAI reference. |
@kornicameister What does the |
@scottbisker I was referring to OAI cloudformation resource. As for the origins, it actually looks fine. Anyway, what I feel I need to point out as a separate thing is that I wanted to have a single stack that's domain is storage (buckets, efs, whatnot) and another stack just for CDN. Needless to say that design is circular dependency all around. @kylelaker do you plan to address that somehow or is it just me organizing stacks in wrong way? |
FYI: I am also observing this issue when trying to create CDN + buckets inside a single stack. The key aspect of the setup is having the bucket encrypted with customer KMS key. Here's a short repro: import aws_cdk as cdk
from aws_cdk import (
aws_cloudfront as cf,
aws_cloudfront_origins as cf_origins,
aws_iam as iam,
aws_kms as kms,
aws_s3 as s3,
aws_sns as sns,
)
class OACCircularIssueStack(cdk.Stack):
def __init__(
self,
scope: Construct,
construct_id: str,
**kwargs: t.Any,
) -> None:
super().__init__(
scope,
construct_id,
description='Demonstrates circular issue when using OAC',
termination_protection=False,
analytics_reporting=False,
**kwargs,
)
encryption_key = kms.Key(
self,
'Key',
description='Some key to just have bucket encrypted',
removal_policy=cdk.RemovalPolicy.DESTROY,
)
bucket = s3.Bucket(
self,
'Bucket',
enforce_ssl=True,
public_read_access=False,
removal_policy=cdk.RemovalPolicy.DESTROY,
auto_delete_objects=True,
encryption_key=encryption_key,
encryption=s3.BucketEncryption.KMS,
bucket_key_enabled=True,
block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
object_ownership=s3.ObjectOwnership.BUCKET_OWNER_ENFORCED,
)
oac = cf.CfnOriginAccessControl(
self,
'OAC',
origin_access_control_config=(
cf.CfnOriginAccessControl.OriginAccessControlConfigProperty(
name=f'{cdk.Stack.of(self).stack_name}_OAC',
description='OAC to access buckets',
origin_access_control_origin_type='s3',
signing_behavior='always',
signing_protocol='sigv4',
)
),
)
distro = cf.Distribution(
self,
'Distribution',
comment='Distribution using OAC',
enable_ipv6=False,
http_version=cf.HttpVersion.HTTP2_AND_3,
price_class=cf.PriceClass.PRICE_CLASS_100,
default_behavior=cf.BehaviorOptions(
origin=cf_origins.S3Origin(
bucket,
origin_path='/',
),
allowed_methods=cf.AllowedMethods.ALLOW_GET_HEAD,
cached_methods=cf.CachedMethods.CACHE_GET_HEAD,
viewer_protocol_policy=cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
origin_request_policy=cf.OriginRequestPolicy.CORS_S3_ORIGIN,
cache_policy=cf.CachePolicy.CACHING_OPTIMIZED,
),
)
cf_distro = t.cast(
cf.CfnDistribution,
distro.node.default_child,
)
cf_distro.add_property_override(
'DistributionConfig.Origins.0.OriginAccessControlId',
oac.get_att('Id'),
)
cf_distro.add_property_override(
'DistributionConfig.Origins.0.S3OriginConfig.OriginAccessIdentity',
'',
)
distribution_arn = cdk.Stack.of(self).format_arn(
service='cloudfront',
region='',
resource='distribution',
resource_name=distro.distribution_id,
arn_format=cdk.ArnFormat.SLASH_RESOURCE_NAME,
)
cloudfront = iam.ServicePrincipal('cloudfront')
bucket.add_to_resource_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
's3:GetObject',
],
principals=[cloudfront],
resources=[bucket.arn_for_objects('*')],
conditions={
'ArnEquals': {
'AWS:SourceArn': distribution_arn,
},
},
),
)
encryption_key.add_to_resource_policy(
iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
'kms:Decrypt',
'kms:Encrypt',
'kms:GenerateDataKey*',
],
principals=[cloudfront],
resources=['*'],
conditions={
'ArnEquals': {
'AWS:SourceArn': distribution_arn,
},
},
),
allow_no_op=False,
)
app = cdk.App()
OACCircularIssueStack(app, 'oac-circular-issue')
app.synth()
So the problem lies well below CDK. It's CloudFormation issue. |
@@ -21,9 +21,11 @@ def __init__(
description='Some key to just have bucket encrypted',
removal_policy=cdk.RemovalPolicy.DESTROY,
)
+ bucket_name = f'{self.stack_name}.oac-bucket'
bucket = s3.Bucket(
self,
'Bucket',
+ bucket_name=bucket_name,
enforce_ssl=True,
public_read_access=False,
removal_policy=cdk.RemovalPolicy.DESTROY,
@@ -57,7 +59,11 @@ def __init__(
price_class=cf.PriceClass.PRICE_CLASS_100,
default_behavior=cf.BehaviorOptions(
origin=cf_origins.S3Origin(
- bucket,
+ s3.Bucket.from_bucket_name(
+ self,
+ 'BucketOrigin',
+ bucket_name,
+ ),
origin_path='/',
),
allowed_methods=cf.AllowedMethods.ALLOW_GET_HEAD, Seems like a way to break the circular dependency is to:
|
@kylelaker is there any progress here? |
I'm curious where this stands, too. I'm standing up a brand new project, and I am doing it with OriginAccessIdentity but then I see that marked as "Legacy." I tried to follow the workaround above but I don't follow which worked / didn't work. My thought here is to continue using OAI until this is all sorted out. |
Hey, I am probably not suited to continue moving forward with making this change. I have now unchecked the box in the original message to indicate I'm not planning to work on this. It does look like this issue has also gotten enough 👍🏻s to be put onto the "CDK Ownership" board by the bot; however, it hasn't moved from the "Incoming" state. I think that because the API around this needs a really healthy amount of consideration, because OAI and OAC can't be used together, and because the OAC to Distribution to Source relationship isn't 1:1, this should probably be created as an RFC and handled over there; that way a bar raiser can be found and there can be more back and forth with the core CDK team around the design. |
@wz2b you can pick my last two code examples if you want. They key is to set the bucket name and reimport the bucket. This is what made it work for me. It is a workaround but that compared to deploying us-east-1 stack with Lambda@edge sounded like a reasonable tradeoff. |
I have just opened: aws/aws-pdk#660 which is for the aws-pdk, however it is completely generic and my preference would be to contribute it to the |
The AWS Solutions Constructs library has addressed this issue in its aws-cloudfront-s3 construct. This construct will create a CloudFront distribution in front of a new or existing S3 bucket, and implement an OAC instead of the default OAI. As an additional benefit, it includes a custom resource that addresses the circular dependency issue when the bucket is encrypted by a CMK, allowing the policies to specify a the CMK rather than just use an '*'. The Solutions Constructs library is available in npm, PyPi and Maven. |
Hey Folks! AWS announced support for Origin Access Control for Lambda Function URLs and AWS Elemental MediaPackage Origin yesterday. Please can we get some movement on an OAC L2 construct. This is getting beyond embarrassing and now actively making workloads less secure. @colifran @scanlonp @evgenyka please escalate to get some movement on this RFC |
Hi everyone,
An example, for what is worth is available here: https://github.com/aws-abaschen/example-cdk-cloudfront-s3-static-sites |
I have a feeling the Lambda Function URL OAC protection is going to be very painful to implement with infra-as-code as there seems to be some challenging state / ordering required:
I've been trying to set it up with some CDK hacks but without success so far. |
I'm doing it without the construct, using the method described in a previous comment You can see my code here:
I believe both of these are solved with a Cloudfront Function doing URL rewrites... you probably don't need multiple behaviors if they're all in the same bucket (but you definitely do if the subsites are in their own buckets). I don't have a public-facing example of this code, but I am doing this in production at work. |
Well coming back to Lambda Function URLs & OAC regarding my #21771 (comment): I managed to get it working in the end: For anyone looking a workaround, here's an example setup with Lambda Function URL and CloudFront Origin Access Control (OAC). Caution Just note that if you define Lambda function and CloudFront distribution in different stacks, you'll most probably end up with a CloudFormation cyclic reference. For simplicity, here's a single stack solution: import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";
import * as iam from "aws-cdk-lib/aws-iam";
export class DemoStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Just a basic "Hello world" Lambda function
const fn = new lambda.Function(this, "MyFunction", {
code: lambda.Code.fromInline(`
def handler(event, context):
return {
"statusCode": 200,
"headers": {
"Content-Type": "text/plain"
},
"body": "Hello from Lambda Function Url!"
}`),
runtime: lambda.Runtime.PYTHON_3_12,
handler: "index.handler",
});
// Define the function URL
const fnUrl = fn.addFunctionUrl({
authType: lambda.FunctionUrlAuthType.AWS_IAM, // Note the IAM auth type
});
// Output the "raw" FN URL so you can verify that it doesn't work without Sigv4/IAM auth
new cdk.CfnOutput(this, "FunctionUrl", { value: fnUrl.url });
// Create an Origin Access Control using Cfn construct
const oac = new cloudfront.CfnOriginAccessControl(this, "OAC", {
originAccessControlConfig: {
name: "MyFunctionOAC",
originAccessControlOriginType: "lambda",
signingBehavior: "always",
signingProtocol: "sigv4",
},
});
// Basic CloudFront setup
const distribution = new cloudfront.Distribution(this, "MyDistribution", {
priceClass: cloudfront.PriceClass.PRICE_CLASS_100,
defaultBehavior: {
origin: new origins.FunctionUrlOrigin(fnUrl),
cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
});
// Get reference to the underlying CloudFormation construct of the distribution
const cfnDistribution = distribution.node
.defaultChild as cloudfront.CfnDistribution;
// Override the OAC ID into the CloudFormation distribution CFN construct
cfnDistribution.addPropertyOverride(
"DistributionConfig.Origins.0.OriginAccessControlId",
oac.getAtt("Id")
);
// Grant the CloudFront service principal permission to invoke the Lambda function URL
fn.grantInvokeUrl(
new iam.ServicePrincipal("cloudfront.amazonaws.com", {
conditions: {
ArnLike: {
// Note if you do Lambda Function and CloudFront Distribution in different stacks
// you'll most-likely end up with a circular dependency.
// Important, don't specify region as CloudFront needs to access the function from all regions
"aws:SourceArn": `arn:aws:cloudfront::${
cdk.Stack.of(this).account
}:distribution/${distribution.distributionId}`,
},
},
})
);
// Output the CloudFront URL, this should now work and respond with "Hello from Lambda Function Url!"
new cdk.CfnOutput(this, "DistributionUrl", {
value: `https://${distribution.distributionDomainName}`,
});
}
} |
I got it working with this snippet below: import { Reference } from 'aws-cdk-lib';
import { S3Origin, S3OriginProps } from 'aws-cdk-lib/aws-cloudfront-origins';
// other imports
type S3OriginWithOACPatchProps = S3OriginProps & {
oacId: Reference;
};
class S3OriginWithOACPatch extends S3Origin {
private readonly oacId: Reference;
constructor(bucket: IBucket, props: S3OriginWithOACPatchProps) {
super(bucket, props);
this.oacId = props.oacId;
}
public bind(scope: Construct, options: OriginBindOptions): OriginBindConfig {
const originConfig = super.bind(scope, options);
if (!originConfig.originProperty) throw new Error('originProperty is required');
return {
...originConfig,
originProperty: {
...originConfig.originProperty,
originAccessControlId: this.oacId.toString(), // Adds OAC to S3 origin config
s3OriginConfig: {
...originConfig.originProperty.s3OriginConfig,
originAccessIdentity: '', // removes OAI from S3 origin config
},
},
};
}
} Usage: const s3BucketOAC = new CfnOriginAccessControl(this, 's3-bucket-OAC', {
originAccessControlConfig: {
name: "s3-bucket-OAC",
originAccessControlOriginType: 's3',
signingBehavior: 'always',
signingProtocol: 'sigv4',
},
});
const s3BucketOrigin = new S3OriginWithOACPatch(s3Bucket, { originAccessIdentity: cloudfrontOAI });
// Reuse s3BucketOrigin as cloudfront default behaviour or other behaviours This snippet also works if your S3 origin is not at index 0 like my use case as well as @s-nt-s . |
In addition to the OAC Patch Construct posted by @Darasimi-Ajewole , you can prevent the OAI from being added to your BucketPolicy by doing a de-tour by reconstructing the new S3OriginWithOAC(
// prevent CF from adding its OriginAccessIdentity to the BucketPolicy since we're using OriginAccessControl (see below)
Bucket.fromBucketName(this, 'UIResourcesBucketCopy', props.uiResourcesBucket.bucketName),
{ oacId: uiResourcesOAC.getAtt('Id') },
), |
You could also inherit from import { OriginBase } from 'aws-cdk-lib/aws-cloudfront';
class S3OriginWithOACPatch extends OriginBase {
...
constructor(bucket: IBucket, props: S3OriginWithOACPatchProps) {
const { bucketRegionalDomainName } = bucket
super(bucketRegionalDomainName, props);
... |
Hey y’all, As part of our goal to improve service coverage with CDK constructs, we are actively working on this feature! While we can’t commit to specific dates, we’re making progress and will keep you updated along the way. Your feedback and support are helping us shape the roadmap, so thank you! |
It works! https://d2p2e6v3qepvh3.cloudfront.net/great-news-everyone.jpg Created CloudFront distribution manually because there's a dependency issue. CloudFront distributions rely on S3 Buckets (origin). But the S3 Bucket and KMS Key policy relies on the CloudFront distribution id. So a circular dependency, though it looks like there may be a workaround: aws/aws-cdk#21771
Worked! Thank you! |
Comments on closed issues and PRs are hard for our team to see. |
1 similar comment
Comments on closed issues and PRs are hard for our team to see. |
### Issue # (if applicable) Closes aws#21771 . ### Reason for this change L2 support for setting up OAC for S3 origins. See [RFC 617](https://github.com/aws/aws-cdk-rfcs/blob/main/text/0617-cloudfront-oac-l2.md) for more details. ### Description of changes - New L2 construct `OriginAccessControl` - Deprecation of `CloudFrontWebDistribution` — replaced by existing `Distribution` construct - Deprecation of `S3Origin` — replaced by new constructs `S3BucketOrigin` and `S3StaticWebsiteOrigin` - README updates ### Description of how you validated changes Added unit tests and integration tests Internal tracking: V1491594161 ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
### Issue # (if applicable) Closes aws#21771 . ### Reason for this change L2 support for setting up OAC for S3 origins. See [RFC 617](https://github.com/aws/aws-cdk-rfcs/blob/main/text/0617-cloudfront-oac-l2.md) for more details. ### Description of changes - New L2 construct `OriginAccessControl` - Deprecation of `CloudFrontWebDistribution` — replaced by existing `Distribution` construct - Deprecation of `S3Origin` — replaced by new constructs `S3BucketOrigin` and `S3StaticWebsiteOrigin` - README updates ### Description of how you validated changes Added unit tests and integration tests Internal tracking: V1491594161 ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
### Issue # (if applicable) Closes #21771 . ### Reason for this change L2 support for setting up OAC for S3 origins. See [RFC 617](https://github.com/aws/aws-cdk-rfcs/blob/main/text/0617-cloudfront-oac-l2.md) for more details. ### Description of changes - New L2 construct `OriginAccessControl` - Deprecation of `CloudFrontWebDistribution` — replaced by existing `Distribution` construct - Deprecation of `S3Origin` — replaced by new constructs `S3BucketOrigin` and `S3StaticWebsiteOrigin` - README updates ### Description of how you validated changes Added unit tests and integration tests Internal tracking: V1491594161 ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Describe the feature
Amazon CloudFront now supports Origin Access Control, an improved method for accessing S3 Origins over Origin Access Identity.
It seems that the CloudFormation documentation (and resource specification) has not yet been updated but the OAC docs contain an example of deploying using CloudFormation.
I am opening an issue to discuss this because the
S3Origin
class currently only supports OAI and creates one by default; migrating to do so would likelyUse Case
The release announcement and documentation describe OAC as an improvement over OAI. OAC supports requests other than
GET
as well asSSE-KMS
, and all AWS regions. Documentation already refers to OAI as "legacy".Proposed Solution
I propose doing all of the following:
@aws-cdk/aws-cloudfront:useOriginAccessControl
. When this istrue
, by default an OAC will be used instead of an OAI.enum
forSigningBehavior
andSigningType
. Maybe forOriginAccessControlOriginType
too.originAccessControl
prop toS3OriginProps
of typecloudfront.IOriginAccessControl
. When truthy, this is used and an OAI is not created. When not specified, an OAI is created and usedS3Origin
add the necessary statements to the S3 bucket resource policyFeature flag behavior
S3Props.originAccessIdentity
providedS3Props.originAccessControl
providedtrue
true
true
true
false
false
false
false
To migrate, a user would enable the feature flag. If they were already passing an OAI, they'd run with both side-by-side (a supported configuration), if not they'd use only an OAC. To migrate to OAC-only, they can then use a custom-created OAC or the default one.
Other Information
The
CreateOriginAccessControl
action seems like it's pretty likely to map 1:1 to the CloudFormation resource https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateOriginAccessControl.html. The example in the docs is:Implementation requires a new CloudFormation Resource Specification but since an example is given in the CloudFront docs, hopefully that won't take and since this may require other changes, having a conversation may be helpful.
This felt smaller than an RFC but I'm happy to open one if needed.
Acknowledgements
CDK version used
2.39.0
Environment details (OS name and version, etc.)
The text was updated successfully, but these errors were encountered: