# Copyright 2023 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. Parameters: AllPackagesBucketsArn: Type: String Description: ARN that matches all buckets used for storing packages (prod and canary) ConstraintDescription: ARN is required AllowedPattern: ".+" Default: "arn:aws:s3:::*-cdn-packages-k8s-io-*" ProdPackagesBucketArn: Type: String Description: ARN that matches buckets only used for production ConstraintDescription: ARN is required AllowedPattern: ".+" Default: "arn:aws:s3:::prod-cdn-packages-k8s-io-eu-central-1" CloudFrontDistributionArn: Type: String Description: ARN that matches production CloudFront distribution used for serving packages ConstraintDescription: ARN is required AllowedPattern: ".+" Default: "arn:aws:cloudfront::309501585971:distribution/E2W1P23FX44BGD" Resources: ######################################### # Terraform State # ######################################### # TFStateBucket (packages-k8s-io-tfstate) is S3 bucket for storing Terraform # state TFStateBucket: Type: AWS::S3::Bucket # We retain the bucket to ensure that accidental deletion of the stack # doesn't destroy Terraform state DeletionPolicy: Retain Properties: BucketName: cdn-packages-k8s-io-tfstate VersioningConfiguration: Status: Enabled ######################################### # IAM user for Terraform # ######################################### # ProvisionerUser (provisioner) is an IAM user used for running Terraform. # This is a shared user used by Kubernetes Release Managers to run Terraform # and manage this AWS account. # We need to use a shared IAM user because we can only run Terraform locally. # In the future, we will intorduce some changes that will allow us to phase # out this IAM user: # - GitOps workflow that's going to automatically apply Terraform changes # - Integration such as Okta so we have personalized AWS users # Credentials for this IAM user are located in 1Password vault accessible # by Kubernetes Release Managers. ProvisionerUser: Type: 'AWS::IAM::User' Properties: Path: / UserName: provisioner Policies: - PolicyName: ProvisionerUserAccess PolicyDocument: Version: 2012-10-17 Statement: - Action: 'sts:AssumeRole' Effect: Allow Resource: !Sub 'arn:aws:iam::${AWS::AccountId}:role/Provisioner' # ProvisionerRole is an IAM role assumed by provisioner IAM user to run Terraform ProvisionerRole: Type: 'AWS::IAM::Role' Properties: RoleName: Provisioner AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Action: 'sts:AssumeRole' Effect: Allow Principal: AWS: !GetAtt ProvisionerUser.Arn TerraformStateAccessPolicy: Type: 'AWS::IAM::ManagedPolicy' Properties: ManagedPolicyName: TerraformStateAccess PolicyDocument: Version: 2012-10-17 Statement: # Permissions needed for S3 bucket used for Terraform state are documented here: # https://developer.hashicorp.com/terraform/language/settings/backends/s3#s3-bucket-permissions - Effect: 'Allow' Action: - 's3:ListBucket' Resource: !GetAtt TFStateBucket.Arn - Effect: 'Allow' Action: - 's3:GetObject' - 's3:PutObject' - 's3:DeleteObject' Resource: !Sub '${TFStateBucket.Arn}/*' # Attach the policy to the Provisioner IAM role Roles: - Ref: ProvisionerRole # ProvisionerPlanAccessPolicy is an IAM policy that grants permissions to run `terraform plan` ProvisionerPlanAccessPolicy: Type: 'AWS::IAM::ManagedPolicy' Properties: ManagedPolicyName: ProvisionerPlanAccess PolicyDocument: Version: 2012-10-17 Statement: # CloudFront requires the ACM certificate objects to be located in # the us-east-1 region. That's why we only give `acm:` permissions in # that region. - Effect: 'Allow' Action: - 'acm:DescribeCertificate' - 'acm:ListTagsForCertificate' Resource: !Sub 'arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/*' - Effect: 'Allow' Action: - 'cloudfront:GetCachePolicy' - 'cloudfront:GetDistribution' - 'cloudfront:GetOriginAccessControl' - 'cloudfront:ListCachePolicies' - 'cloudfront:ListTagsForResource' Resource: - !Sub 'arn:aws:cloudfront::${AWS::AccountId}:distribution/*' - !Sub 'arn:aws:cloudfront::${AWS::AccountId}:cache-policy/*' - !Sub 'arn:aws:cloudfront::${AWS::AccountId}:origin-access-control/*' - Effect: 'Allow' Action: - 's3:GetAccelerateConfiguration' - 's3:GetBucketAcl' - 's3:GetBucketCORS' - 's3:GetBucketLogging' - 's3:GetBucketObjectLockConfiguration' - 's3:GetBucketOwnershipControls' - 's3:GetBucketPolicy' - 's3:GetBucketRequestPayment' - 's3:GetBucketTagging' - 's3:GetBucketVersioning' - 's3:GetBucketWebsite' - 's3:GetEncryptionConfiguration' - 's3:GetLifecycleConfiguration' - 's3:GetReplicationConfiguration' - 's3:ListBucket' Resource: !Ref AllPackagesBucketsArn # CloudFront requires the WAF Web ACL objects to be located in # the us-east-1 region. That's why we only give `wafv2:` permissions in # that region. - Effect: 'Allow' Action: - 'wafv2:GetWebACL' - 'wafv2:ListTagsForResource' Resource: !Sub 'arn:aws:wafv2:us-east-1:${AWS::AccountId}:global/webacl/*-PackagesCloudFrontWebACL/*' # Attach the policy to the Provisioner IAM role Roles: - Ref: ProvisionerRole # ProvisionerApplyAccessPolicy is an IAM policy that grants permissions to run `terraform apply` ProvisionerApplyAccessPolicy: Type: 'AWS::IAM::ManagedPolicy' Properties: ManagedPolicyName: ProvisionerApplyAccess PolicyDocument: Version: 2012-10-17 Statement: - Effect: 'Allow' Action: - 'acm:AddTagsToCertificate' - 'acm:RequestCertificate' Resource: !Sub 'arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/*' - Effect: 'Allow' Action: - 'cloudfront:CreateDistribution' - 'cloudfront:CreateOriginAccessControl' - 'cloudfront:UpdateDistribution' - 'cloudfront:TagResource' Resource: - !Sub 'arn:aws:cloudfront::${AWS::AccountId}:distribution/*' - !Sub 'arn:aws:cloudfront::${AWS::AccountId}:cache-policy/*' - !Sub 'arn:aws:cloudfront::${AWS::AccountId}:origin-access-control/*' - Effect: 'Allow' Action: - 's3:CreateBucket' - 's3:PutBucketOwnershipControls' - 's3:PutBucketPolicy' - 's3:PutBucketTagging' Resource: !Ref AllPackagesBucketsArn - Effect: 'Allow' Action: - 'wafv2:CreateWebACL' - 'wafv2:UpdateWebACL' Resource: - !Sub 'arn:aws:wafv2:us-east-1:${AWS::AccountId}:global/managedruleset/*/*' - !Sub 'arn:aws:wafv2:us-east-1:${AWS::AccountId}:global/webacl/*-PackagesCloudFrontWebACL/*' - Effect: 'Allow' Action: - 'wafv2:TagResource' Resource: !Sub 'arn:aws:wafv2:us-east-1:${AWS::AccountId}:global/webacl/*-PackagesCloudFrontWebACL/*' # Attach the policy to the Provisioner IAM role Roles: - Ref: ProvisionerRole # ProvisionerDestroyAccessPolicy is an IAM policy that grants permissions to run `terraform destroy` ProvisionerDestroyAccessPolicy: Type: 'AWS::IAM::ManagedPolicy' Properties: ManagedPolicyName: ProvisionerDestroyAccess PolicyDocument: Version: 2012-10-17 Statement: - Effect: 'Allow' Action: - 'acm:DeleteCertificate' Resource: !Sub 'arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/*' - Effect: 'Allow' Action: - 'cloudfront:DeleteDistribution' - 'cloudfront:DeleteOriginAccessControl' Resource: - !Sub 'arn:aws:cloudfront::${AWS::AccountId}:distribution/*' - !Sub 'arn:aws:cloudfront::${AWS::AccountId}:cache-policy/*' - !Sub 'arn:aws:cloudfront::${AWS::AccountId}:origin-access-control/*' - Effect: 'Allow' Action: - 's3:DeleteBucket' - 's3:DeleteBucketPolicy' Resource: !Ref AllPackagesBucketsArn - Effect: 'Allow' Action: - 'wafv2:DeleteWebACL' Resource: !Sub 'arn:aws:wafv2:us-east-1:${AWS::AccountId}:global/webacl/*-PackagesCloudFrontWebACL/*' # Attach the policy to the Provisioner IAM role Roles: - Ref: ProvisionerRole ######################################### # IAM user for OpenBuildService (OBS) # ######################################### # OBSAdminUser (obs-admin) is an IAM user used by the OBS platform to perform # needed operation on the S3 bucket (e.g. publish packages) OBSAdminUser: Type: 'AWS::IAM::User' Properties: Path: / UserName: obs-admin # OBSAdminAccessPolicy gives the permissions needed to run rclone on the S3 bucket. # Permissions needed for rclone are documented here: # https://rclone.org/s3/#s3-permissions OBSAdminAccessPolicy: Type: 'AWS::IAM::ManagedPolicy' Properties: ManagedPolicyName: OBSAdminAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: 'Allow' Action: # Needed because of https://github.com/rclone/rclone/issues/5119 # We can remove this once the issue is fixed. # This should be safe because the bucket is already created, so # this is a no-op call, but it doesn't fail rclone. - 's3:CreateBucket' - 's3:ListBucket' - 's3:DeleteObject' - 's3:GetObject' - 's3:PutObject' Resource: - !Ref ProdPackagesBucketArn - !Sub '${ProdPackagesBucketArn}/*' - Effect: 'Allow' Action: 's3:ListAllMyBuckets' # ListAllMyBuckets can't be scoped down to specific buckets Resource: '*' - Effect: 'Allow' Action: 'cloudfront:CreateInvalidation' Resource: !Ref CloudFrontDistributionArn Users: - Ref: OBSAdminUser