<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Petri Kallberg</title>
    <description>The latest articles on DEV Community by Petri Kallberg (@kallu).</description>
    <link>https://dev.to/kallu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F728163%2F582decb5-d92c-4d9e-9999-521fb7dfc57a.png</url>
      <title>DEV Community: Petri Kallberg</title>
      <link>https://dev.to/kallu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kallu"/>
    <language>en</language>
    <item>
      <title>Rerouting legacy server IP address</title>
      <dc:creator>Petri Kallberg</dc:creator>
      <pubDate>Tue, 02 Nov 2021 18:38:58 +0000</pubDate>
      <link>https://dev.to/kallu/rerouting-legacy-server-ip-address-4am</link>
      <guid>https://dev.to/kallu/rerouting-legacy-server-ip-address-4am</guid>
      <description>&lt;p&gt;This is second repost in series that covers various details of migrating services from traditional data center to AWS. You can find this and other post from my personal blog &lt;a href="https://carriagereturn.nl/"&gt;https://carriagereturn.nl/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;I’ve been working on lift-and-shift -migrations from on-premises data center to AWS. In these projects you often find workloads that have been running for a fairly long time with minimal changes and not all “modern IT” practices can not be taken for granted.&lt;/p&gt;

&lt;p&gt;One such practice is using DNS to find server IP address. It is not that uncommon to find an application with clients connecting to server with IP address. And when moving the server from data center to AWS VPC, IP address is going to change because typically it is not possible to move the whole network in one big bang and reuse data center CIDRs for AWS VPC.&lt;/p&gt;

&lt;p&gt;So how could clients keep connecting to the old IP address, until they have been reconfigured?&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Sometimes an old idea can be repurposed for a new use-case. I was thinking the problem of rerouting the legacy server IP to EC2, when I remembered the post of &lt;a href="https://carriagereturn.nl/aws/vpc/ha/standby/cloudnative/2019/04/28/warmstandbyha.html"&gt;Thinking outside of the VPC&lt;/a&gt; where I described a pattern of using IP address outside of VPC CIDR. The Goal at the time was to implement a virtual IP that could be “assigned” to EC2 instances across multiple subnets and AZs. Could the same technic be used for routing data center IPs to EC2s? It turns out it could!&lt;/p&gt;

&lt;p&gt;Here is how to reroute a single IP address from data center network to an EC2 instance in VPC.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In the on-prem router, route the legacy server IP 1.2.3.4/32 to AWS Direct Connect or VPN.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next is the Transit Gateway attached to target VPC. In the diagram it is drawn on the same account and region as the target VPC but it would work also across AWS &lt;a href="https://docs.aws.amazon.com/vpc/latest/tgw/transit-gateway-share.html"&gt;accounts&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/vpc/latest/tgw/transit-gateway-peering-scenario.html"&gt;regions&lt;/a&gt;. In &lt;a href="https://docs.aws.amazon.com/vpc/latest/tgw/tgw-route-tables.html"&gt;Transit Gateway route table&lt;/a&gt; add a static route for 1.2.3.4/32 to attachment of target VPC.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Route_Tables.html"&gt;VPC Subnet route table&lt;/a&gt; add a static route for 1.2.3.4/32 to the new server instance ID.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On EC2 instance OS level, define the secondary IP address 1.2.3.4/32 for the network interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disable EC2 instance &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#change_source_dest_check"&gt;Source/Destination Check&lt;/a&gt; to so packets to 1.2.3.4/32 can reach it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VIyTk90N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdgkh2bn6i7on8m0689j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VIyTk90N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdgkh2bn6i7on8m0689j.png" alt="Architecture diagram of routing a single IP outside of VPC CIDR to the interface within VPC" width="880" height="1083"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and side effects
&lt;/h2&gt;

&lt;p&gt;Nice side effect of above is that the EC2 instance will answer on both old and new IP address. This means the clients can be reconfigured to new IP address (or maybe even start using DNS) one by one. When all of them are using the new IP address, static routes for legacy IP address can be removed from Transit Gateway and VPC route tables.&lt;/p&gt;

&lt;p&gt;Obviously this isn’t the solution for rerouting IPs in large scale. Route tables can easily grow very complex and pretty soon hit the default limit of &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/amazon-vpc-limits.html"&gt;50 routes in VPC route table&lt;/a&gt;. While the limit can be increased up to 1000 routes, it will have a negative impact on VPC network performance.&lt;/p&gt;

&lt;p&gt;If the instance ID will change, static route in the subnet route table must be updated. When using Auto Scaling group of 1 instance, to ensure server will stay running, it will become a bit more complex as code for route table update must be included in server start-up routine. This is also limited to routing to EC2s and ENIs. That is ok for most lift-and-shift workloads, but not suitable for cloud-native architectures.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>vpc</category>
      <category>routing</category>
      <category>ip</category>
    </item>
    <item>
      <title>Delegating IAM access with permission boundary</title>
      <dc:creator>Petri Kallberg</dc:creator>
      <pubDate>Sun, 17 Oct 2021 14:08:24 +0000</pubDate>
      <link>https://dev.to/kallu/delegating-iam-access-with-permission-boundary-1ehe</link>
      <guid>https://dev.to/kallu/delegating-iam-access-with-permission-boundary-1ehe</guid>
      <description>&lt;p&gt;This is first repost in series that covers various details of migrating services from traditional data center to AWS. You can find this and other post from my personal blog &lt;a href="https://carriagereturn.nl/"&gt;https://carriagereturn.nl/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Brief history of shared AWS accounts
&lt;/h2&gt;

&lt;p&gt;Back in the days, when creating an AWS account was a lot of overhead, common pattern was to have multiple teams sharing a single account. This created a demand to isolate teams from each other by assigning them an IAM policy that would grant access only to their part of the account. While it might have been possible (in theory) to create complex IAM policies to containerize resources by application or team, one fundamental problem did remain. Once you granted a right to create an IAM policy or role, you effectively granted admin level access to everything on the account. IAM has very granular controls for actions, it can not limit what policies you attach to a role, or content of policy documents.&lt;/p&gt;

&lt;p&gt;To solve this problem, AWS introduced in July 2018 feature called &lt;a href="https://aws.amazon.com/blogs/security/delegate-permission-management-to-developers-using-iam-permissions-boundaries/"&gt;IAM permission boundary&lt;/a&gt;. If this went unnoticed, don't feel back about yourself. If you have been working in modern environments, it has been the best practice to use AWS account as boundary and create accounts dedicated to a single team, application or environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  IAM permission boundary
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RtgYa7ZB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://carriagereturn.nl/img/iambound/permissions.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RtgYa7ZB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://carriagereturn.nl/img/iambound/permissions.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are 3 types of IAM polices that control your access to AWS APIs. First and the most common is normal identity-based policies that are attached to roles and users. Second type is organization service control policies (SCP) that are attached to AWS accounts or OUs. These can limit what the local admins can do on the account and as they are not part the account, they can not be modified by local admins. Typical use-case for SCPs would be limiting regions or services you are allowed to use within given account.&lt;/p&gt;

&lt;p&gt;The Third type is permission boundary policy. It is similar to regular IAM policies inside of an account, but the use-case is similar to SCPs, limiting what can be granted in normal policies.&lt;/p&gt;

&lt;p&gt;Policy evaluation logic works so, that you are only allowed for an actions if all three policy types allow it. You may remember that single &lt;code&gt;deny&lt;/code&gt; will always overwrite any number of &lt;code&gt;allow&lt;/code&gt; statements, but another thing to note is that all policy types must also have &lt;code&gt;allow&lt;/code&gt; your actions, ie. the effective permissions are the intersection of all policies applied. This is why you typically want to have &lt;code&gt;allow-all&lt;/code&gt; -statement in permission boundary or SCP policies, and then deny the parts you don't want to be granted via normal IAM policies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting boundaries for a team
&lt;/h2&gt;

&lt;p&gt;The Goal is to allow users to manage IAM policies, roles, users, groups and instance-profiles so they can work idependently. But at the same time, protect their resources from others sharing the same AWS account. Ownership of an resource is claimed using a tag with unique value to user, team or role. Ie. something that wasn't possible before &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html"&gt;permission boundaries&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dissecting the boundary policy
&lt;/h2&gt;

&lt;p&gt;As a demonstration of how IAM permission boundary works, I wrote a &lt;a href="https://carriagereturn.nl/files/iambound/iambound.yaml"&gt;cloudformation template&lt;/a&gt; that creates an IAM user with &lt;code&gt;AdministratorAccess&lt;/code&gt; and permission boundary attached. I've dissected the boundary policy statements below.&lt;/p&gt;

&lt;p&gt;First there is normal IAM policy header stuff. Only interesting piece here is &lt;code&gt;ManagedPolicyName&lt;/code&gt;. This is going to be restricted in following statements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  IAMBoundary:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      ManagedPolicyName: !Sub "${AWS::StackName}-boundary"
      Description: IAM permission boundary to force boundary inheritance
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  AllowUnlessOwnedBySomeoneElse
&lt;/h4&gt;

&lt;p&gt;This statement will allow all actions, on all resources, unless there is an &lt;code&gt;owner&lt;/code&gt; -tag that has different value than the IAM role or user &lt;code&gt;owner&lt;/code&gt; -tag has. Ie. if some resource is missing the &lt;code&gt;owner&lt;/code&gt; -tag, they are considered as common property. This is something you have to accept, as it is not possible to tag all resources at creation but create and tagging are 2 separate API calls. It is also assuming that when role or user is created, it will be tagged with team or application specific owner -tag value as &lt;code&gt;StringEqualsIfExists&lt;/code&gt; won't apply when &lt;code&gt;aws:PrincipalTag/owner&lt;/code&gt; is not present.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          - Sid: 'AllowUnlessOwnedBySomeoneElse'
            Effect: Allow 
            Action: '*'
            Resource: '*'
            Condition:
              StringEqualsIfExists:
                'aws:RequestTag/owner': ${aws:PrincipalTag/owner}
                'aws:ResourceTag/owner': ${aws:PrincipalTag/owner}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  DenyBoundaryModification
&lt;/h4&gt;

&lt;p&gt;Next thing is to deny modification of this boundary policy. Deny rule applies only this single policy. You can still grant access to all other IAM policies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          - Sid: 'DenyBoundaryModification'
            Effect: Deny
            Action:
              - iam:CreatePolicyVersion
              - iam:DeletePolicy
              - iam:DeletePolicyVersion
              - iam:SetDefaultPolicyVersion
            Resource: !Sub "arn:aws:iam::${AWS::AccountId}:policy/${AWS::StackName}-boundary"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ForceBoundaryInheritance
&lt;/h4&gt;

&lt;p&gt;This is the beef of permission boundary. You are allowed to create a role or user only if that has the same permission boundary attached as you have.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          - Sid: 'ForceBoundaryInheritance'
            Effect: Deny 
            Action:
              - iam:CreateUser
              - iam:CreateRole
              - iam:PutUserPermissionsBoundary
              - iam:PutRolePermissionsBoundary
            Resource: '*'
            Condition:
              StringNotEquals:
                'iam:PermissionsBoundary': !Sub "arn:aws:iam::${AWS::AccountId}:policy/${AWS::StackName}-boundary"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  DenyBoundaryRemoval
&lt;/h4&gt;

&lt;p&gt;Inheritance isn't enough, but it is also necessary to deny removal of permission boundary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          - Sid: 'DenyBoundaryRemoval'
            Effect: Deny
            Action:
              - iam:DeleteUserPermissionsBoundary
              - iam:DeleteRolePermissionsBoundary
            Resource: '*'
            Condition:
              StringEquals:
                'iam:PermissionsBoundary': !Sub "arn:aws:iam::${AWS::AccountId}:policy/${AWS::StackName}-boundary"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  DenyIAMChangesWithoutPrefix
&lt;/h4&gt;

&lt;p&gt;Final statement of the boundary policy, restricts the IAM resources; users, groups, roles, policies and instance-profiles, to have a prefix of your IAM pricipals &lt;code&gt;owner&lt;/code&gt; -tag value. This is ensuring you won't be able to modify or attach other than your own IAM resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          - Sid: 'DenyIAMChangesWithoutPrefix'
            Effect: Deny
            Action:
              - iam:Add*
              - iam:Attach*
              - iam:Create*
              - iam:Delete*
              - iam:Detach*
              - iam:Pass*
            NotResource:
              - !Sub "arn:*:iam::${AWS::AccountId}:group/${!aws:PrincipalTag/owner}-*"
              - !Sub "arn:*:iam::${AWS::AccountId}:policy/${!aws:PrincipalTag/owner}-*"
              - !Sub "arn:*:iam::${AWS::AccountId}:role/${!aws:PrincipalTag/owner}-*"
              - !Sub "arn:*:iam::${AWS::AccountId}:user/${!aws:PrincipalTag/owner}-*"
              - !Sub "arn:*:iam::${AWS::AccountId}:instance-profile/${!aws:PrincipalTag/owner}-*"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! Now you have isolated multiple teams within a single account using IAM permission boundary. You can tag now the IAM user with &lt;code&gt;owner&lt;/code&gt; -tag and some value. Then using a different user, create resources, some tagged with the same value as the IAM user created, some with different values, and see how access is only granted to resources matching your tag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; There is no need to create team specific boundary policies but the same policy can be attached to all roles and users that need to be isolated. This is thanks to &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html"&gt;IAM policy variable&lt;/a&gt; &lt;code&gt;aws:PrincipalTag&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Too little, too late?
&lt;/h2&gt;

&lt;p&gt;But is this "too little, too late", as now it is also easy to create new accounts using organizations?&lt;/p&gt;

&lt;p&gt;If there is an option to have dedicated AWS account, that would be the ultimate boundary. But there are also many large migrations from data center to AWS, where it isn't feasible to create own account for every workload. This is where shared accounts with permission boundaries can become helpful. And not to forget those shared "legacy" accounts that many of us have created in past, and are not quite yet split into single tenancy model ;-)&lt;/p&gt;

&lt;p&gt;So, there actually might be more use for IAM boundaries than ever!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; I'd love to hear if you found holes in the boundary that I missed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.P.S.&lt;/strong&gt; &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/permissions-boundary.html"&gt;Lambda applies automatic permission boundary&lt;/a&gt; to application&lt;br&gt;
IAM roles it creates. You can use auto created boundary policy or define your own in SAM template &lt;code&gt;Globals&lt;/code&gt; -section.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
