Skip to content

Commit 1a5bd7e

Browse files
brent-anyscalehongchaodeng
authored andcommitted
feat: Add support for CloudKeeper Anyscale services (#69)
* feat: Add support for CloudKeeper Anyscale services - Moved Anyscale Services V2 policy to a new template - Added support for CloudKeeper Anyscale services - Added flag to enable/disable the creation of the ELB Service Linked Role On branch brent/upd-iam-serv-perm Changes to be committed: modified: CHANGELOG.md modified: README.md modified: getting-started.md modified: main.tf modified: modules/aws-anyscale-iam/README.md new file: modules/aws-anyscale-iam/anyscale-control_plane-services-v2.tmpl modified: modules/aws-anyscale-iam/iam-policies-data.tf modified: modules/aws-anyscale-iam/variables.tf modified: variables.tf * upd: IAM Role descriptions Remove the region from the IAM Role descriptions. With the new AWS provider, the call to the data source to return the region introduced a deprecation warning. As this is rarely required, it is being removed and the region will not be part of the IAM Role descriptions. Changes to be committed: modified: modules/aws-anyscale-iam/README.md modified: modules/aws-anyscale-iam/eks-iam-main.tf modified: modules/aws-anyscale-iam/main.tf * upd: add tflint rule to skip tmpl files Changes to be committed: modified: .tflint.hcl
1 parent e5e3a24 commit 1a5bd7e

File tree

12 files changed

+357
-216
lines changed

12 files changed

+357
-216
lines changed

.tflint.hcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ plugin "aws" {
77
config {
88
call_module_type = "local"
99
force = false
10+
exclude = ["**/*.tmpl"]
1011
}
1112

1213
rule "terraform_required_providers" {

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
## (NEXT)
2+
NOTES:
3+
14
FEATURES:
25
- Removed null provider and updated validation of required variables to variables.tf
6+
- Added additional IAM policies for CloudKeeper deployments of Anyscale Services
7+
- Anyscale Services v2 originally managed the deployment and load balancers via Cloudformation. This had inherrent limitations.
8+
- Anyscale Services will now be fully managed via the Control Plane via AWS APIs. This requires small adjustments to the IAM policies in use.
9+
- A future version will remove the Cloudformation IAM policies.
310

411
BUG FIXES:
512
- When passing in an organization id as well as the external id, if a cloud ID was also provided, it would not prioritize the correct local value for the external ID.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ We use GitHub [Issues] to track community reported issues and missing features.
233233
| <a name="input_anyscale_s3_server_side_encryption"></a> [anyscale\_s3\_server\_side\_encryption](#input\_anyscale\_s3\_server\_side\_encryption) | (Optional) S3 Bucket Server Side Encryption.<br/><br/>Configuration to enforce server side encryption (KMS or AES256).<br/>If you are using KMS, you must proivde the KMS Key ID.<br/><br/>ex using KMS:<pre>anyscale_s3_server_side_encryption = {<br/> kms_master_key_id = "1234abcd-12ab-34cd-56ef-1234567890ab"<br/> sse_algorithm = "aws:kms"<br/>}</pre>ex using AES256:<pre>anyscale_s3_server_side_encryption = {<br/> sse_algorithm = "AES256"<br/>}</pre> | `map(string)` | <pre>{<br/> "sse_algorithm": "AES256"<br/>}</pre> | no |
234234
| <a name="input_anyscale_s3_tags"></a> [anyscale\_s3\_tags](#input\_anyscale\_s3\_tags) | (Optional) A map of tags for S3 resources.<br/><br/>Duplicate tags found in the "tags" variable will get duplicated on the resource.<br/><br/>ex:<pre>anyscale_iam_tags = {<br/> "purpose" : "storage",<br/> "criticality" : "critical"<br/>}</pre> | `map(string)` | `{}` | no |
235235
| <a name="input_anyscale_securitygroup_tags"></a> [anyscale\_securitygroup\_tags](#input\_anyscale\_securitygroup\_tags) | (Optional) A map of tags for Security Group resources.<br/><br/>Duplicate tags found in the "tags" variable will get duplicated on the resource.<br/><br/>ex:<pre>anyscale_securitygroup_tags = {<br/> "purpose" : "security",<br/> "criticality" : "critical"<br/>}</pre>Default is an empty map. | `map(string)` | `{}` | no |
236+
| <a name="input_anyscale_servicesv2_create_elb_service_linked_role"></a> [anyscale\_servicesv2\_create\_elb\_service\_linked\_role](#input\_anyscale\_servicesv2\_create\_elb\_service\_linked\_role) | (Optional) Determines if the ELB service linked role is created.<br/><br/>ex:<pre>anyscale_servicesv2_create_elb_service_linked_role = true</pre> | `bool` | `true` | no |
236237
| <a name="input_anyscale_vpc_cidr_block"></a> [anyscale\_vpc\_cidr\_block](#input\_anyscale\_vpc\_cidr\_block) | (Optional) The IPv4 CIDR block for the VPC.<br/>The CIDR block can be explicitly set or it can be derived from IPAM using `ipv4_netmask_length` & `ipv4_ipam_pool_id`.<br/><br/>ex:<pre>anyscale_vpc_cidr_block = "10.0.0.0/16"</pre> | `string` | `"10.0.0.0/16"` | no |
237238
| <a name="input_anyscale_vpc_name"></a> [anyscale\_vpc\_name](#input\_anyscale\_vpc\_name) | (Optional) VPC name.<br/><br/>If provided, will create a VPC with this name.<br/>Defaults to `vpc_<anyscale_cloud_id>` in a local variable if not provided.<br/><br/>ex:<pre>anyscale_vpc_name = "anyscale-vpc"</pre> | `string` | `null` | no |
238239
| <a name="input_anyscale_vpc_private_subnet_tags"></a> [anyscale\_vpc\_private\_subnet\_tags](#input\_anyscale\_vpc\_private\_subnet\_tags) | (Optional) A map of tags for private subnets.<br/><br/>Duplicate tags found in the `tags` or `anyscale_vpc_tags` variables will get duplicated on the resource.<br/><br/>ex:<pre>anyscale_vpc_private_subnet_tags = {<br/> "purpose" : "networking",<br/> "criticality" : "critical"<br/>}</pre> | `map(string)` | `{}` | no |

getting-started.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,14 @@ anyscale cloud register --provider aws \
119119
--s3-bucket-id anyscale-tf-test-1-fw \
120120
--external-id org_1234567890abcdef-example_id
121121
```
122-
123-
### 12. Clean up resources (optional):
122+
### 12. Re-run the Terraform Module with Anyscale cloud ID (optional):
123+
To enable consistent tagging for billing or to support tag-based conditions in the
124+
IAM policies for the control plane, set the `anyscale_cloud_id` variable and re-run the Terraform modules.
125+
This will:
126+
- Apply consistent tags to all newly created resources
127+
- Add tag-based conditions and restrictions to IAM policies
128+
129+
### Clean up resources (optional):
124130
Once you are done, you can destroy the resources created by Terraform:
125131
```
126132
terraform destroy -var-file="terraform.tfvars"

main.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ module "aws_anyscale_iam" {
102102
anyscale_access_servicesv2_policy_name = local.iam_servicesv2_policy_name
103103
anyscale_access_servicesv2_policy_prefix = local.iam_servicesv2_policy_prefix
104104
anyscale_access_servicesv2_policy_description = var.anyscale_access_servicesv2_policy_description
105+
create_elb_service_linked_role = var.anyscale_servicesv2_create_elb_service_linked_role
105106

106107
anyscale_trusted_role_arns = var.anyscale_access_role_trusted_role_arns
107108

modules/aws-anyscale-iam/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ No modules.
7777
| [aws_iam_policy_document.iam_anyscale_s3_bucket_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
7878
| [aws_iam_policy_document.iam_anyscale_services_v2](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
7979
| [aws_iam_policy_document.iam_anyscale_steadystate_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
80-
| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
8180

8281
## Inputs
8382

@@ -157,6 +156,7 @@ No modules.
157156
| <a name="input_create_cluster_node_instance_profile"></a> [create\_cluster\_node\_instance\_profile](#input\_create\_cluster\_node\_instance\_profile) | (Optional) Determines whether to create an instance profile role.<br/><br/>ex:<pre>create_cluster_node_instance_profile = true</pre> | `bool` | `true` | no |
158157
| <a name="input_create_eks_ebs_csi_driver_role"></a> [create\_eks\_ebs\_csi\_driver\_role](#input\_create\_eks\_ebs\_csi\_driver\_role) | (Optional) Determines whether to create the EKS EBS CSI driver role.<br/><br/>ex:<pre>create_eks_ebs_csi_driver_role = true</pre> | `bool` | `false` | no |
159158
| <a name="input_create_eks_efs_csi_driver_role"></a> [create\_eks\_efs\_csi\_driver\_role](#input\_create\_eks\_efs\_csi\_driver\_role) | (Optional) Determines whether to create the EKS EFS CSI driver role.<br/><br/>ex:<pre>create_eks_efs_csi_driver_role = true</pre> | `bool` | `false` | no |
159+
| <a name="input_create_elb_service_linked_role"></a> [create\_elb\_service\_linked\_role](#input\_create\_elb\_service\_linked\_role) | (Optional) Determines if the ELB service linked role is created.<br/><br/>ex:<pre>create_elb_service_linked_role = true</pre> | `bool` | `true` | no |
160160
| <a name="input_create_iam_s3_policy"></a> [create\_iam\_s3\_policy](#input\_create\_iam\_s3\_policy) | (Optional) Determines whether to create the S3 Access Policy for IAM roles.<br/>Requires anyscale\_s3\_bucket\_arn (below).<br/><br/>ex:<pre>create_iam_s3_policy = true</pre> | `bool` | `true` | no |
161161
| <a name="input_efs_file_system_arn"></a> [efs\_file\_system\_arn](#input\_efs\_file\_system\_arn) | (Optional) The EFS File System ARN that the IAM Roles need access to.<br/><br/>Required if `create_eks_efs_csi_driver_role` is set to `true`.<br/><br/>ex:<pre>efs_file_system_arn = "arn:aws:efs:us-east-1:123456789012:file-system/fs-12345678"</pre> | `string` | `null` | no |
162162
| <a name="input_eks_ebs_csi_role_description"></a> [eks\_ebs\_csi\_role\_description](#input\_eks\_ebs\_csi\_role\_description) | (Optional) IAM Role description.<br/><br/>If left `null`, will default to `Anyscale EKS EBS CSI Role`.<br/><br/>ex:<pre>eks_ebs_csi_role_description = "Anyscale EKS EBS CSI Role"</pre> | `string` | `null` | no |
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
{
2+
"Version": "2012-10-17",
3+
"Statement": [
4+
{
5+
"Sid": "CloudformationDescribeGet",
6+
"Effect": "Allow",
7+
"Action": [
8+
"cloudformation:CreateStack",
9+
"cloudformation:DescribeStackEvents",
10+
"cloudformation:DescribeStackResources",
11+
"cloudformation:DescribeStacks",
12+
"cloudformation:GetTemplate"
13+
],
14+
"Resource": [
15+
"arn:aws:cloudformation:*:${account_id}:stack/*"
16+
]
17+
},
18+
{
19+
"Sid": "EC2Describe",
20+
"Effect": "Allow",
21+
"Action": [
22+
"ec2:DescribeVpcs",
23+
"ec2:DescribeInternetGateways"
24+
],
25+
"Resource": ["*"]
26+
},
27+
%{ if cloud_id_provided == false ~}
28+
{
29+
"Sid": "CloudformationWrite",
30+
"Effect": "Allow",
31+
"Action": [
32+
"cloudformation:TagResource",
33+
"cloudformation:UntagResource",
34+
"cloudformation:UpdateStack"
35+
],
36+
"Resource": [
37+
"arn:aws:cloudformation:*:${account_id}:stack/*"
38+
]
39+
},
40+
%{ endif ~}
41+
%{ if cloud_id_provided == true ~}
42+
{
43+
"Sid": "CloudformationWrite",
44+
"Effect": "Allow",
45+
"Action": [
46+
"cloudformation:TagResource",
47+
"cloudformation:UntagResource",
48+
"cloudformation:UpdateStack",
49+
"cloudformation:DeleteStack"
50+
],
51+
"Resource": [
52+
"arn:aws:cloudformation:*:${account_id}:stack/*"
53+
],
54+
"Condition": {
55+
"StringEquals": {
56+
"aws:ResourceTag/anyscale-cloud-id": "${anyscale_cloud_id}"
57+
}
58+
}
59+
},
60+
%{ endif ~}
61+
%{ if cloud_id_provided == false ~}
62+
{
63+
"Sid": "CloudformationDelete",
64+
"Effect": "Allow",
65+
"Action": [
66+
"cloudformation:DeleteStack"
67+
],
68+
"Resource": [
69+
"arn:aws:cloudformation:*:${account_id}:stack/anyscale*"
70+
]
71+
},
72+
%{ endif ~}
73+
%{ if create_elb_service_linked_role == true ~}
74+
{
75+
"Sid": "CreateELBServiceLinkedRole",
76+
"Effect": "Allow",
77+
"Action": [
78+
"iam:CreateServiceLinkedRole"
79+
],
80+
"Resource": [
81+
"arn:aws:iam::${account_id}:role/aws-service-role/elasticloadbalancing.amazonaws.com/AWSServiceRoleForElasticLoadBalancing"
82+
],
83+
"Condition": {
84+
"StringLike": {
85+
"iam:AWSServiceName": ["elasticloadbalancing.amazonaws.com"]
86+
}
87+
}
88+
},
89+
%{ endif ~}
90+
{
91+
"Sid": "ELBRead",
92+
"Effect": "Allow",
93+
"Action": [
94+
"elasticloadbalancing:DescribeListeners",
95+
"elasticloadbalancing:DescribeLoadBalancers",
96+
"elasticloadbalancing:DescribeLoadBalancerAttributes",
97+
"elasticloadbalancing:DescribeRules",
98+
"elasticloadbalancing:DescribeTargetGroups",
99+
"elasticloadbalancing:DescribeTargetGroupAttributes",
100+
"elasticloadbalancing:DescribeTargetHealth",
101+
"elasticloadbalancing:DescribeListenerCertificates",
102+
"elasticloadbalancing:DescribeTags"
103+
],
104+
"Resource": "*"
105+
},
106+
{
107+
"Sid": "ACMAllResources",
108+
"Effect": "Allow",
109+
"Action": [
110+
"acm:ListCertificates",
111+
"acm:RequestCertificate",
112+
"acm:DescribeCertificate"
113+
],
114+
"Resource": "*"
115+
},
116+
%{ if cloud_id_provided == false ~}
117+
{
118+
"Sid": "ACMWrite",
119+
"Effect": "Allow",
120+
"Action": [
121+
"acm:DeleteCertificate",
122+
"acm:RenewCertificate",
123+
"acm:AddTagsToCertificate",
124+
"acm:GetCertificate",
125+
"acm:ListTagsForCertificate"
126+
],
127+
"Resource": ["arn:aws:acm:*:${account_id}:certificate/*"]
128+
},
129+
%{ endif ~}
130+
%{ if cloud_id_provided == true ~}
131+
{
132+
"Sid": "ACMWrite",
133+
"Effect": "Allow",
134+
"Action": [
135+
"acm:DeleteCertificate",
136+
"acm:RenewCertificate",
137+
"acm:AddTagsToCertificate",
138+
"acm:GetCertificate",
139+
"acm:ListTagsForCertificate"
140+
],
141+
"Resource": ["arn:aws:acm:*:${account_id}:certificate/*"],
142+
"Condition": {
143+
"StringEquals": {
144+
"aws:RequestTag/anyscale-cloud-id": "${anyscale_cloud_id}"
145+
},
146+
"ForAnyValue:StringEquals": {
147+
"aws:TagKeys": ["anyscale-cloud-id"]
148+
}
149+
}
150+
},
151+
%{ endif ~}
152+
{
153+
"Sid": "ELBWrite",
154+
"Effect": "Allow",
155+
"Action": [
156+
"elasticloadbalancing:AddTags",
157+
"elasticloadbalancing:RemoveTags",
158+
"elasticloadbalancing:CreateRule",
159+
"elasticloadbalancing:ModifyRule",
160+
"elasticloadbalancing:DeleteRule",
161+
"elasticloadbalancing:SetRulePriorities",
162+
"elasticloadbalancing:CreateListener",
163+
"elasticloadbalancing:ModifyListener",
164+
"elasticloadbalancing:DeleteListener",
165+
"elasticloadbalancing:CreateLoadBalancer",
166+
"elasticloadbalancing:DeleteLoadBalancer",
167+
"elasticloadbalancing:ModifyLoadBalancerAttributes",
168+
"elasticloadbalancing:CreateTargetGroup",
169+
"elasticloadbalancing:ModifyTargetGroup",
170+
"elasticloadbalancing:DeleteTargetGroup",
171+
"elasticloadbalancing:ModifyTargetGroupAttributes",
172+
"elasticloadbalancing:AddListenerCertificates",
173+
"elasticloadbalancing:RemoveListenerCertificates",
174+
"elasticloadbalancing:SetIpAddressType",
175+
"elasticloadbalancing:SetSecurityGroups",
176+
"elasticloadbalancing:SetSubnets"
177+
],
178+
"Resource": [
179+
"arn:aws:elasticloadbalancing:*:${account_id}:loadbalancer/app/Anyscale*",
180+
"arn:aws:elasticloadbalancing:*:${account_id}:listener/app/Anyscale*",
181+
"arn:aws:elasticloadbalancing:*:${account_id}:listener-rule/app/Anyscale*",
182+
"arn:aws:elasticloadbalancing:*:${account_id}:targetgroup/AnyscaleTarget*"
183+
],
184+
"Condition": {
185+
"StringEquals": {
186+
"aws:CalledViaFirst": ["cloudformation.amazonaws.com"]
187+
}
188+
}
189+
},
190+
{
191+
"Sid": "ELBTargetRegistration",
192+
"Effect": "Allow",
193+
"Action": [
194+
"elasticloadbalancing:RegisterTargets",
195+
"elasticloadbalancing:DeregisterTargets"
196+
],
197+
"Resource": [
198+
"arn:aws:elasticloadbalancing:*:${account_id}:targetgroup/AnyscaleTarget*",
199+
"arn:aws:elasticloadbalancing:*:${account_id}:targetgroup/anyscale*"
200+
]
201+
},
202+
{
203+
"Sid": "ELBDirectCreate",
204+
"Effect": "Allow",
205+
"Action": [
206+
"elasticloadbalancing:CreateRule",
207+
"elasticloadbalancing:CreateListener",
208+
"elasticloadbalancing:CreateLoadBalancer",
209+
"elasticloadbalancing:CreateTargetGroup"
210+
],
211+
"Resource": [
212+
"arn:aws:elasticloadbalancing:*:${account_id}:loadbalancer/app/anyscale*",
213+
"arn:aws:elasticloadbalancing:*:${account_id}:listener/app/anyscale*",
214+
"arn:aws:elasticloadbalancing:*:${account_id}:listener-rule/app/anyscale*",
215+
"arn:aws:elasticloadbalancing:*:${account_id}:targetgroup/anyscale*"
216+
]
217+
},
218+
%{ if cloud_id_provided == false ~}
219+
{
220+
"Sid": "ELBDirectWrite",
221+
"Effect": "Allow",
222+
"Action": [
223+
"elasticloadbalancing:AddTags",
224+
"elasticloadbalancing:RemoveTags",
225+
"elasticloadbalancing:ModifyRule",
226+
"elasticloadbalancing:DeleteRule",
227+
"elasticloadbalancing:SetRulePriorities",
228+
"elasticloadbalancing:ModifyListener",
229+
"elasticloadbalancing:DeleteListener",
230+
"elasticloadbalancing:DeleteLoadBalancer",
231+
"elasticloadbalancing:ModifyLoadBalancerAttributes",
232+
"elasticloadbalancing:ModifyTargetGroup",
233+
"elasticloadbalancing:DeleteTargetGroup",
234+
"elasticloadbalancing:ModifyTargetGroupAttributes",
235+
"elasticloadbalancing:AddListenerCertificates",
236+
"elasticloadbalancing:RemoveListenerCertificates",
237+
"elasticloadbalancing:SetIpAddressType",
238+
"elasticloadbalancing:SetSecurityGroups",
239+
"elasticloadbalancing:SetSubnets"
240+
],
241+
"Resource": [
242+
"arn:aws:elasticloadbalancing:*:${account_id}:loadbalancer/app/anyscale*",
243+
"arn:aws:elasticloadbalancing:*:${account_id}:listener/app/anyscale*",
244+
"arn:aws:elasticloadbalancing:*:${account_id}:listener-rule/app/anyscale*",
245+
"arn:aws:elasticloadbalancing:*:${account_id}:targetgroup/anyscale*"
246+
]
247+
}
248+
%{ endif ~}
249+
%{ if cloud_id_provided == true ~}
250+
251+
{
252+
"Sid": "ELBDirectModifyDelete",
253+
"Effect": "Allow",
254+
"Action": [
255+
"elasticloadbalancing:AddTags",
256+
"elasticloadbalancing:RemoveTags",
257+
"elasticloadbalancing:ModifyRule",
258+
"elasticloadbalancing:DeleteRule",
259+
"elasticloadbalancing:SetRulePriorities",
260+
"elasticloadbalancing:ModifyListener",
261+
"elasticloadbalancing:DeleteListener",
262+
"elasticloadbalancing:DeleteLoadBalancer",
263+
"elasticloadbalancing:ModifyLoadBalancerAttributes",
264+
"elasticloadbalancing:ModifyTargetGroup",
265+
"elasticloadbalancing:DeleteTargetGroup",
266+
"elasticloadbalancing:ModifyTargetGroupAttributes",
267+
"elasticloadbalancing:AddListenerCertificates",
268+
"elasticloadbalancing:RemoveListenerCertificates",
269+
"elasticloadbalancing:SetIpAddressType",
270+
"elasticloadbalancing:SetSecurityGroups",
271+
"elasticloadbalancing:SetSubnets"
272+
],
273+
"Resource": [
274+
"arn:aws:elasticloadbalancing:*:${account_id}:loadbalancer/app/anyscale*",
275+
"arn:aws:elasticloadbalancing:*:${account_id}:listener/app/anyscale*",
276+
"arn:aws:elasticloadbalancing:*:${account_id}:listener-rule/app/anyscale*",
277+
"arn:aws:elasticloadbalancing:*:${account_id}:targetgroup/anyscale*"
278+
],
279+
"Condition": {
280+
"StringEquals": {
281+
"aws:ResourceTag/anyscale-cloud-id": "${anyscale_cloud_id}"
282+
}
283+
}
284+
}
285+
%{ endif ~}
286+
]
287+
}

0 commit comments

Comments
 (0)