Skip to content

Commit

Permalink
fix: if provided, apply permissions boundary to all roles created wit…
Browse files Browse the repository at this point in the history
…hin a stack
  • Loading branch information
anayeaye committed Sep 28, 2023
1 parent 9aa3311 commit 7db6adc
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 4 deletions.
10 changes: 6 additions & 4 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#!/usr/bin/env python3
""" CDK Configuration for the veda-backend stack."""

from aws_cdk import App, Stack, Tags, aws_iam
from aws_cdk import App, Aspects, Stack, Tags, aws_iam
from constructs import Construct

from config import veda_app_settings
from database.infrastructure.construct import RdsConstruct
from domain.infrastructure.construct import DomainConstruct
from network.infrastructure.construct import VpcConstruct
from permissions_boundary.infrastructure.construct import PermissionsBoundaryAspect
from raster_api.infrastructure.construct import RasterApiLambdaConstruct
from stac_api.infrastructure.construct import StacApiLambdaConstruct

Expand All @@ -22,12 +23,13 @@ def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)

if veda_app_settings.permissions_boundary_policy_name:
permission_boundary_policy = aws_iam.Policy.from_policy_name(
permissions_boundary_policy = aws_iam.Policy.from_policy_name(
self,
"permission-boundary",
"permissions-boundary",
veda_app_settings.permissions_boundary_policy_name,
)
aws_iam.PermissionsBoundary.of(self).apply(permission_boundary_policy)
aws_iam.PermissionsBoundary.of(self).apply(permissions_boundary_policy)
Aspects.of(self).add(PermissionsBoundaryAspect(permissions_boundary_policy))


veda_stack = VedaStack(
Expand Down
56 changes: 56 additions & 0 deletions permissions_boundary/infrastructure/construct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Class that applies permissions boundary to all the roles created within a Stack"""
from typing import Union

import jsii
from aws_cdk import IAspect, aws_iam
from constructs import IConstruct
from jsii._reference_map import _refs
from jsii._utils import Singleton


@jsii.implements(IAspect)
class PermissionsBoundaryAspect:
"""
This aspect finds all aws_iam.Role objects in a node (ie. CDK stack) and sets permissions boundary to the given ARN.
"""

def __init__(self, permissions_boundary: Union[aws_iam.ManagedPolicy, str]) -> None:
"""
:param permissions_boundary: Either aws_iam.ManagedPolicy object or managed policy's ARN string
"""
self.permissions_boundary = permissions_boundary

def visit(self, construct_ref: IConstruct) -> None:
"""
construct_ref only contains a string reference to an object. To get the actual object, we need to resolve it using JSII mapping.
:param construct_ref: ObjRef object with string reference to the actual object.
:return: None
"""
if isinstance(construct_ref, jsii._kernel.ObjRef) and hasattr(
construct_ref, "ref"
):
kernel = Singleton._instances[
jsii._kernel.Kernel
] # The same object is available as: jsii.kernel
resolve = _refs.resolve(kernel, construct_ref)
else:
resolve = construct_ref

def _walk(obj):
if isinstance(obj, aws_iam.Role):
cfn_role = obj.node.find_child("Resource")
policy_arn = (
self.permissions_boundary
if isinstance(self.permissions_boundary, str)
else self.permissions_boundary.managed_policy_arn
)
cfn_role.add_property_override("PermissionsBoundary", policy_arn)
else:
if hasattr(obj, "permissions_node"):
for c in obj.permissions_node.children:
_walk(c)
if hasattr(obj, "node") and obj.node.children:
for c in obj.node.children:
_walk(c)

_walk(resolve)

0 comments on commit 7db6adc

Please sign in to comment.