Skip to content

Commit

Permalink
ECS Policies (#264)
Browse files Browse the repository at this point in the history
* Policies for ecs_service, ecs_cluster, ecs_taskdefinition, ecs_task

Signed-off-by: Alina Buzachis <[email protected]>

* Abstract List and Describe operations

Signed-off-by: Alina Buzachis <[email protected]>

* Add extra black line

Signed-off-by: Alina Buzachis <[email protected]>

* Update resources

Signed-off-by: Alina Buzachis <[email protected]>

* Remove bracket

Signed-off-by: Alina Buzachis <[email protected]>

* Update for dependant resources

Signed-off-by: Alina Buzachis <[email protected]>

* Refactor

Signed-off-by: Alina Buzachis <[email protected]>

* Remove extra space

Signed-off-by: Alina Buzachis <[email protected]>

* apply suggestion

Signed-off-by: Alina Buzachis <[email protected]>

* Linting

Signed-off-by: Alina Buzachis <[email protected]>

* Move ecs policies and terminator classes into paas files

Signed-off-by: Alina Buzachis <[email protected]>

* Apply suggestion

Signed-off-by: Alina Buzachis <[email protected]>

* Apply suggestion

Signed-off-by: Alina Buzachis <[email protected]>

* Fix rebase

Signed-off-by: Alina Buzachis <[email protected]>

* remove trailing spaces

Signed-off-by: Alina Buzachis <[email protected]>

* More ECS related permissions

* requested changes

---------

Signed-off-by: Alina Buzachis <[email protected]>
Co-authored-by: Alina Buzachis <[email protected]>
  • Loading branch information
tremble and alinabuzachis authored Feb 23, 2023
1 parent f5bbeff commit 339cbe3
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 26 deletions.
35 changes: 35 additions & 0 deletions aws/policy/paas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,38 @@ Statement:
StringLike:
lambda:FunctionArn:
- arn:aws:lambda:{{ aws_region }}:{{ aws_account_id }}:function:*

- Sid: AllowGlobalUnrestrictedResourceActionsWhichIncurFees
Effect: Allow
Action:
- ecs:CreateCluster
Resource: "*"

- Sid: AllowGlobalUnrestrictedResourceActionsWhichIncurNoFees
Effect: Allow
Action:
- ecs:Describe*
- ecs:List*
- ecs:TagResource
- ecs:UntagResource
- ecs:PutAccountSetting
- ecs:RegisterTaskDefinition
- ecs:DeregisterTaskDefinition
Resource:
- "*"

- Sid: AllowGlobalRestrictedResourceActionsWhichIncurFees
Effect: Allow
Action:
- ecs:RunTask
- ecs:StartTask
- ecs:StopTask
- ecs:DeleteCluster
- ecs:CreateService
- ecs:DeleteService
- ecs:UpdateService
- ecs:UpdateCluster
- ecs:*CapacityProvider
- ecs:PutClusterCapacityProviders
Resource:
- 'arn:aws:ecs:{{ aws_region }}:{{ aws_account_id }}:*'
32 changes: 7 additions & 25 deletions aws/policy/security-services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,11 @@ Statement:
- 'arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole'
- 'arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole'
- 'arn:aws:iam::aws:policy/service-role/AWSServiceRoleForVPCTransitGateway'

# Legacy - We need to backport ansible-collections/community.aws/63 or
# wait until community.aws drops CI support for Ansible 2.9
- Sid: AllowPassRole
Effect: Allow
Action:
- iam:PassRole
Resource:
- 'arn:aws:iam::{{ aws_account_id }}:role/ansible_lambda_role'
- 'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy'

- Sid: AllowRegionalUnrestrictedResourceActionsWhichIncurNoFees
Effect: Allow
Action:
- iam:ListAccountAliases
- iam:ListPolicies
- iam:ListInstanceProfiles
- iam:GetUser
- acm:ListCertificates
- acm:ListTagsForCertificate
Expand All @@ -73,12 +62,7 @@ Statement:
Action:
- access-analyzer:ValidatePolicy
- iam:GetRole
- iam:ListAttachedRolePolicies
- iam:ListRoles
- iam:ListRolePolicies
- iam:ListRoleTags
- iam:ListSAMLProviders
- iam:ListServerCertificates
- iam:List*
- iam:TagRole
- iam:UntagRole
- kms:CreateAlias
Expand All @@ -92,12 +76,7 @@ Statement:
- kms:GetKeyPolicy
- kms:GetKeyRotationStatus
- kms:GetPublicKey
- kms:ListAliases
- kms:ListGrants
- kms:ListKeyPolicies
- kms:ListKeys
- kms:ListResourceTags
- kms:ListRetirableGrants
- kms:List*
- kms:PutKeyPolicy
- kms:RetireGrant
- kms:ScheduleKeyDeletion
Expand Down Expand Up @@ -152,7 +131,6 @@ Statement:
- iam:GetInstanceProfile
- iam:GetSAMLProvider
- iam:GetServerCertificate
- iam:ListInstanceProfilesForRole
- iam:PassRole
- iam:RemoveRoleFromInstanceProfile
- iam:UpdateSAMLProvider
Expand Down Expand Up @@ -181,6 +159,7 @@ Statement:
- 'arn:aws:iam::{{ aws_account_id }}:role/rds_export_task'
- 'arn:aws:logs:{{ aws_region }}:{{ aws_account_id }}:log-group:*'
- 'arn:aws:logs:{{ aws_region }}:{{ aws_account_id }}:log-group:ansible-test*'
- 'arn:aws:iam::{{ aws_account_id }}:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS'

# This allows AWS Services to autmatically create their Default Service Linked Roles
# These have fixed policies and can only be assumed by the service itself.
Expand All @@ -195,6 +174,7 @@ Statement:
- 'arn:aws:iam::{{ aws_account_id }}:role/aws-service-role/eks-nodegroup.amazonaws.com/*'
- 'arn:aws:iam::{{ aws_account_id }}:role/aws-service-role/transitgateway.amazonaws.com/*'
- 'arn:aws:iam::{{ aws_account_id }}:role/aws-service-role/network-firewall.amazonaws.com/*'
- 'arn:aws:iam::{{ aws_account_id }}:role/aws-service-role/ecs.amazonaws.com/*'
Condition:
ForAnyValue:StringEquals:
iam:AWSServiceName:
Expand All @@ -204,3 +184,5 @@ Statement:
- 'eks-nodegroup.amazonaws.com'
- 'transitgateway.amazonaws.com'
- 'network-firewall.amazonaws.com'
- 'ecs.amazonaws.com'
- 'ecs-test.amazonaws.com'
130 changes: 129 additions & 1 deletion aws/terminator/paas.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timedelta

from . import DbTerminator, Terminator

Expand Down Expand Up @@ -117,3 +117,131 @@ def terminate(self):
else:
# delete streaming distribution
self.client.delete_streaming_distribution(Id=self.Id, IfMatch=ETag)


class Ecs(DbTerminator):
@property
def age_limit(self):
return datetime.timedelta(minutes=20)

@property
def name(self):
return self.instance['clusterName']

@staticmethod
def create(credentials):
def _paginate_cluster_results(client):
names = client.get_paginator('list_clusters').paginate(
PaginationConfig={
'PageSize': 100,
}
).build_full_result()['clusterArns']

if not names:
return []

return client.describe_clusters(clusters=names)['clusters']

return Terminator._create(credentials, Ecs, 'ecs', _paginate_cluster_results)

def terminate(self):
def _paginate_task_results(container_instance=None):
params = {
'cluster': self.name,
'PaginationConfig': {
'PageSize': 100,
}
}

if container_instance:
params['containerInstance'] = container_instance

names = self.client.get_paginator('list_tasks').paginate(
**params
).build_full_result()['taskArns']

return [] if not names else names

def _paginate_task_definition_results():
names = self.client.get_paginator('list_task_definitions').paginate(
PaginationConfig={
'PageSize': 100,
}
).build_full_result()['taskDefinitionArns']

return [] if not names else names

def _paginate_container_instance_results():
names = self.client.get_paginator('list_container_instances').paginate(
cluster=self.name,
PaginationConfig={
'PageSize': 100,
}
).build_full_result()['containerInstanceArns']

return [] if not names else names

def _paginate_service_results():
names = self.client.get_paginator('list_services').paginate(
cluster=self.name,
PaginationConfig={
'PageSize': 100,
}
).build_full_result()['serviceArns']

return [] if not names else names

# If there are running services, delete them first
services = _paginate_service_results()
for each in services:
self.client.delete_service(cluster=self.name, service=each, force=True)

# Deregister container instances and stop any running task
container_instances = _paginate_container_instance_results()
for each in container_instances:
self.client.deregister_container_instance(containerInstance=each['containerInstanceArn'], force=True)

# Deregister task definitions
task_definitions = _paginate_task_definition_results()
for each in task_definitions:
self.client.deregister_task_definition(taskDefinition=each)

# Stop all the tasks
tasks = _paginate_task_results()
for each in tasks:
self.client.stop_task(cluster=self.name, task=each)

# Delete cluster
try:
self.client.delete_cluster(cluster=self.name)
except (self.client.exceptions.ClusterContainsServicesException, self.client.exceptions.ClusterContainsTasksException):
pass


class EcsCluster(DbTerminator):
@property
def age_limit(self):
return timedelta(minutes=30)

@property
def name(self):
return self.instance['clusterName']

@staticmethod
def create(credentials):
def _paginate_cluster_results(client):
names = client.get_paginator('list_clusters').paginate(
PaginationConfig={
'PageSize': 100,
}
).build_full_result()['clusterArns']

if not names:
return []

return client.describe_clusters(clusters=names)['clusters']

return Terminator._create(credentials, EcsCluster, 'ecs', _paginate_cluster_results)

def terminate(self):
self.client.delete_cluster(cluster=self.name)

0 comments on commit 339cbe3

Please sign in to comment.