<?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: Shuichi Takahashi</title>
    <description>The latest articles on DEV Community by Shuichi Takahashi (@shu85t).</description>
    <link>https://dev.to/shu85t</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%2F326727%2Ff8d43124-229e-41cd-aebb-3d38c54b9a98.jpeg</url>
      <title>DEV Community: Shuichi Takahashi</title>
      <link>https://dev.to/shu85t</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shu85t"/>
    <language>en</language>
    <item>
      <title>Using Permission Boundaries for IAM Role Creation in AWS Organizations Management Account</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Tue, 30 Sep 2025 14:18:06 +0000</pubDate>
      <link>https://dev.to/shu85t/using-permission-boundaries-for-iam-role-creation-in-aws-organizations-management-account-2j0d</link>
      <guid>https://dev.to/shu85t/using-permission-boundaries-for-iam-role-creation-in-aws-organizations-management-account-2j0d</guid>
      <description>&lt;p&gt;In AWS Organizations, the "management account" is a special account.&lt;br&gt;
It owns all organizational settings and has powerful permissions.&lt;br&gt;
By default, it can register and remove accounts from the organization, handle billing, and manage organization-wide settings.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_getting-started_concepts.html#account" rel="noopener noreferrer"&gt;AWS Organizations Management Account&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Therefore, it is a best practice to limit management account access to a small number of people and delegate functions and operations whenever possible.&lt;br&gt;
The functions that can be delegated are listed in the AWS Services integrated with Organizations documentation.&lt;br&gt;
Functions with "Supports delegated administrator" set to "Yes" can be delegated to specified member accounts.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_integrate_services_list.html" rel="noopener noreferrer"&gt;AWS Services Integrated with Organizations&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, the management account is not subject to control policies such as SCPs, making it difficult to restrict.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html" rel="noopener noreferrer"&gt;Service Control Policies (SCP)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For cases where you cannot delegate everything and need to give access to the management account, you can use methods like assigning roles with limited permissions through IAM Identity Center.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html" rel="noopener noreferrer"&gt;AWS IAM Identity Center&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem occurs when developers need to create IAM roles.&lt;br&gt;
For example, they want to deploy a Lambda function or setup serverless infrastructure.&lt;br&gt;
There are several ways to handle this. This article explains one approach: Permission Boundaries.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Challenge: When Allowing iam:CreateRole
&lt;/h2&gt;

&lt;p&gt;When you give someone &lt;code&gt;iam:CreateRole&lt;/code&gt; permission, it looks reasonable.&lt;br&gt;
However, there is a problem: they can create roles with much more permissions than they have.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9qtml2er176k7egwy24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9qtml2er176k7egwy24.png" alt="Diagram showing privilege escalation when users can create IAM roles with more permissions than their own" width="795" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When these IAM roles are used, the intended permission control becomes ineffective.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Permission Boundary Matters in Management Account
&lt;/h2&gt;

&lt;p&gt;Management account has a difficult situation. Developers need to create IAM roles for their applications, but SCPs cannot help - they don't work on management accounts.&lt;/p&gt;

&lt;p&gt;Here is an example: a development team wants to deploy a Lambda that reads from S3. They request &lt;code&gt;iam:CreateRole&lt;/code&gt; permission.&lt;/p&gt;

&lt;p&gt;The escalation pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Developer creates role with &lt;code&gt;s3:GetObject&lt;/code&gt; (intended behavior)&lt;/li&gt;
&lt;li&gt;Developer needs CloudWatch logs, adds &lt;code&gt;logs:CreateLogGroup&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Still getting errors, changes to &lt;code&gt;logs:*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;More problems occur, adds &lt;code&gt;*:*&lt;/code&gt; temporarily&lt;/li&gt;
&lt;li&gt;Six months later, that temporary role with full permissions is still in production&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This escalation pattern happens frequently. Developers focus on making their application work rather than security boundaries.&lt;/p&gt;

&lt;p&gt;Permission Boundary acts like a chain that restricts IAM entities. No matter what permissions you try to attach, you cannot break free from the boundary's constraints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important point&lt;/strong&gt;: Setting the boundary is not enough. If users can remove it, the security is gone. You must block &lt;code&gt;iam:DeleteRolePermissionsBoundary&lt;/code&gt; and &lt;code&gt;iam:PutRolePermissionsBoundary&lt;/code&gt; actions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operational Reality&lt;/strong&gt;: Developers initially resist the additional complexity. However, when they understand it enables self-service IAM role creation without security team approval, adoption improves. Self-service approach is more efficient than ticket-based processes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging Complexity&lt;/strong&gt;: When permissions fail, troubleshooting becomes harder because you must check both identity-based policies AND Permission Boundaries. Invest in logging and documentation upfront.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html" rel="noopener noreferrer"&gt;IAM Permissions Boundaries&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing Permission Boundary Control
&lt;/h2&gt;

&lt;p&gt;When you want to grant IAM role creation permissions but prevent users from creating roles with excessive permissions, you can use Permission Boundaries for control. By setting a policy that explicitly denies unwanted operations as a Permission Boundary and forcing the application of this Permission Boundary when creating IAM roles, you can control the upper limit of permissions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0o5baezocm0j6nhjth21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0o5baezocm0j6nhjth21.png" alt="Diagram illustrating how Permission Boundary controls and limits IAM role creation permissions" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Enforcing Permission Boundary Inheritance
&lt;/h3&gt;

&lt;p&gt;A critical challenge emerges when roles create other roles: how do you ensure that "child" and "grandchild" roles maintain the same constraints? Permission Boundaries don't automatically inherit, but you can enforce inheritance through policy design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution: Self-Referencing Permission Boundary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The key insight is to make the Permission Boundary policy reference itself. Include this condition in your &lt;code&gt;baseline_policy&lt;/code&gt; Permission Boundary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"iam:CreateUser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"iam:CreateRole"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"StringNotEquals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"iam:PermissionsBoundary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::ACCOUNT-ID:policy/baseline_policy"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Self-Reference Works:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;baseline_policy&lt;/code&gt; enforces that new roles must have the same Permission Boundary attached. This creates a chain where all created roles inherit the same constraints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Self-Reference Creates the Chain:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parent Role&lt;/strong&gt; has &lt;code&gt;baseline_policy&lt;/code&gt; as its Permission Boundary&lt;/li&gt;
&lt;li&gt;Parent Role attempts to create a new role&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;baseline_policy&lt;/code&gt; &lt;strong&gt;denies&lt;/strong&gt; the creation unless the new role also gets &lt;code&gt;baseline_policy&lt;/code&gt; as its Permission Boundary&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Child Role&lt;/strong&gt; is created with the identical Permission Boundary (&lt;code&gt;baseline_policy&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;When Child Role creates another role, the &lt;strong&gt;same self-referencing constraint applies&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grandchild Role&lt;/strong&gt; and all subsequent generations must also have &lt;code&gt;baseline_policy&lt;/code&gt; as their Permission Boundary&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Chain of Enforcement:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent Role (Boundary: baseline_policy)
  ↓ iam:CreateRole (must specify same boundary)
Child Role (Boundary: baseline_policy)
  ↓ iam:CreateRole (must specify same boundary)
Grandchild Role (Boundary: baseline_policy)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Additional Protection:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To prevent boundary removal, also deny these actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"iam:DeleteRolePermissionsBoundary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"iam:PutRolePermissionsBoundary"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach ensures that regardless of how many generations of roles are created, they all maintain the same constraints. This prevents privilege escalation problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative Approaches
&lt;/h2&gt;

&lt;p&gt;For permission control in management account, there are other methods besides Permission Boundary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Migration&lt;/strong&gt;: When data in the management account is needed, share or copy only the necessary parts of that data to member accounts and build solutions in the member accounts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Work Separation&lt;/strong&gt;: Have administrators or CI/CD pipelines handle IAM role creation and deployment work, and give general users only execution permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Considerations for Permission Boundary Usage
&lt;/h2&gt;

&lt;p&gt;Permission Boundaries can be used not only in management account but also in member accounts. However, they add operational complexity. Before implementation, evaluate whether the security benefits justify the operational overhead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Operational Complexity&lt;/strong&gt;: Permission Boundaries add an additional layer of policy evaluation, which can make troubleshooting permission issues more complex&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development Velocity&lt;/strong&gt;: Strict boundaries may slow down development workflows, especially in environments requiring frequent role modifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance Overhead&lt;/strong&gt;: Permission Boundary policies need to be maintained and updated as business requirements evolve&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Experience&lt;/strong&gt;: Developers may encounter unexpected permission denials, requiring additional training and documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before implementing Permission Boundaries, ensure your team can manage the additional complexity and that the security benefits are significant for your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference Links
&lt;/h2&gt;

&lt;h3&gt;
  
  
  AWS Organizations and IAM Related
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_best-practices.html" rel="noopener noreferrer"&gt;AWS Organizations Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html" rel="noopener noreferrer"&gt;IAM Permissions Boundaries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_integrate_services_list.html" rel="noopener noreferrer"&gt;AWS Services Integrated with Organizations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AWS Well-Architected Related
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/wellarchitected/2025-02-25/framework/sec_permissions_least_privileges.html" rel="noopener noreferrer"&gt;SEC03-BP02: Grant Least Privilege Access&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&amp;gt;For example, you can allow your workload teams to create their own IAM policies for systems they build, but only if they apply a Permission Boundary to limit the maximum permissions they can grant.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/aws-account-management-and-separation.html" rel="noopener noreferrer"&gt;SEC01-BP01: Separate Workloads Using Accounts&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/welcome.html" rel="noopener noreferrer"&gt;Security Pillar - AWS Well-Architected Framework&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>AWS Cost Categories with OU Structure</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Sat, 29 Mar 2025 20:48:31 +0000</pubDate>
      <link>https://dev.to/shu85t/aws-cost-categories-with-ou-structure-61n</link>
      <guid>https://dev.to/shu85t/aws-cost-categories-with-ou-structure-61n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;AWS Cost Categories help organize cloud spending by mapping costs to your business structure using rules. You can define rules based on accounts, tags, services, and more. See the &lt;a href="https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/manage-cost-categories.html" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;This article explores an approach to automatically align AWS Cost Categories with your AWS Organizations Organizational Unit (OU) structure. We'll look at the reasoning behind this method and demonstrate how to implement it using a sample Python script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Also available in Japanese&lt;/strong&gt;: An enhanced Japanese version of this article with additional content is available &lt;a href="https://iret.media/169416" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Important Security Note&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;This script is a &lt;strong&gt;sample&lt;/strong&gt;. Test thoroughly before use in production.&lt;/li&gt;
&lt;li&gt;It requires execution in the &lt;strong&gt;Management Account&lt;/strong&gt; to access necessary Organizations and Cost Explorer APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Least Privilege:&lt;/strong&gt; The Management Account is critical. &lt;strong&gt;Do not run scripts with administrative privileges.&lt;/strong&gt; Create a dedicated IAM role with &lt;em&gt;only&lt;/em&gt; the minimum required permissions (see &lt;a href="https://dev.toYOUR_GITHUB_REPO_URL_HERE#iam-permissions"&gt;README&lt;/a&gt;) and use that role for execution (e.g., in CloudShell, EC2, Lambda).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Approach Details
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automation Need:&lt;/strong&gt; OU structures change. Manual Cost Category updates are impractical. This script automates synchronization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementation:&lt;/strong&gt; Cost Category rules cannot directly target OUs. This script uses the following logic:

&lt;ol&gt;
&lt;li&gt; List all accounts via &lt;code&gt;ListAccounts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; For each account, find its OU path using &lt;code&gt;ListParents&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Assign the account to a category name derived from its OU path up to a specified &lt;code&gt;depth&lt;/code&gt; (e.g., &lt;code&gt;OU1-OU1A&lt;/code&gt;). Each account belongs only to its deepest relevant category.&lt;/li&gt;
&lt;li&gt; Generate Cost Category rules mapping the category name (&lt;code&gt;Value&lt;/code&gt;) to the list of associated account IDs (&lt;code&gt;Dimensions&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution:&lt;/strong&gt; Uses Python3.x/&lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/index.html" rel="noopener noreferrer"&gt;Boto3&lt;/a&gt; Assumes execution from an environment like AWS CloudShell. Can be adapted for scheduled Lambda execution (requires changes for parameter input and considering execution limits).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Script Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hierarchical Categories:&lt;/strong&gt; Creates names like &lt;code&gt;Level1OU-Level2OU-...&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Depth Control:&lt;/strong&gt; A &lt;code&gt;depth&lt;/code&gt; argument sets the granularity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Script
&lt;/h2&gt;

&lt;p&gt;The complete Python script is available on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/shu85t/PutOuCostCategory" rel="noopener noreferrer"&gt;https://github.com/shu85t/PutOuCostCategory&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python:&lt;/strong&gt; Version 3.9 or later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boto3:&lt;/strong&gt; AWS SDK for Python (&lt;code&gt;pip install boto3&lt;/code&gt;). Ensure you are using a recent version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Account:&lt;/strong&gt; Access to the &lt;strong&gt;Management Account&lt;/strong&gt; of your AWS Organization.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Execution Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This script needs to run in an environment with credentials for the &lt;strong&gt;Management Account&lt;/strong&gt; of your AWS Organization, possessing the necessary IAM permissions (see below).&lt;/li&gt;
&lt;li&gt;A primary intended environment is &lt;strong&gt;AWS CloudShell&lt;/strong&gt; accessed while logged into the Management Account.&lt;/li&gt;
&lt;li&gt;It can also run on an EC2 instance or in an AWS Lambda function within the Management Account, provided the execution role has the required permissions.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Command Line Execution
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 put_ou_cost_category.py &amp;lt;CostCategoryName&amp;gt; &amp;lt;EffectiveStartMonth&amp;gt; &amp;lt;Depth&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Arguments
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;&lt;code&gt;&amp;lt;CostCategoryName&amp;gt;&lt;/code&gt;&lt;/strong&gt; (Required): The name of the Cost Category to create or update (e.g., &lt;code&gt;OrganizationStructure&lt;/code&gt;, &lt;code&gt;OUHierarchy&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;&lt;code&gt;&amp;lt;EffectiveStartMonth&amp;gt;&lt;/code&gt;&lt;/strong&gt; (Required): The effective start month in &lt;code&gt;YYYY-MM&lt;/code&gt; format (e.g., &lt;code&gt;2025-04&lt;/code&gt;). The script uses the first day of this month (UTC midnight) for the API call.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;&lt;code&gt;&amp;lt;Depth&amp;gt;&lt;/code&gt;&lt;/strong&gt; (Required): An integer (1 or greater) specifying the maximum depth of the OU hierarchy to create categories for.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;1&lt;/code&gt;: Creates categories for &lt;code&gt;Root&lt;/code&gt; and first-level OUs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;2&lt;/code&gt;: Creates categories for &lt;code&gt;Root&lt;/code&gt;, first-level OUs, and second-level OUs (e.g., &lt;code&gt;OU1-OU1A&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Accounts are always assigned to their deepest category up to the specified depth.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Log Level Configuration
&lt;/h3&gt;

&lt;p&gt;Control logging verbosity using the &lt;code&gt;LOG_LEVEL&lt;/code&gt; environment variable. Default is &lt;code&gt;INFO&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example: Run with DEBUG logs&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LOG_LEVEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DEBUG
python3 put_ou_cost_category.py MyOUCategory 2025-04 2

&lt;span class="c"&gt;# Or temporarily for one command&lt;/span&gt;
&lt;span class="nv"&gt;LOG_LEVEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DEBUG python3 put_ou_cost_category.py MyOUCategory 2025-04 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  IAM Permissions
&lt;/h2&gt;

&lt;p&gt;The IAM principal (user or role) running this script needs the following permissions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Required Actions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;organizations:ListAccounts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;organizations:ListParents&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;organizations:DescribeOrganizationalUnit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;organizations:ListRoots&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ce:ListCostCategoryDefinitions&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ce:CreateCostCategoryDefinition&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ce:UpdateCostCategoryDefinition&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example Results
&lt;/h2&gt;

&lt;p&gt;Here's how it works with a sample OU structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample OU Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Root
├── Management Account
│
├── Management OU
│   ├── Management Tool Account1
│   └── Management Tool Account2
│
├── Sandbox OU (No direct accounts)
│
├── Security OU
│   ├── Audit Account
│   └── Log Archive Account
│
└── SDLC OU
    ├── Dev OU
    │   └── Workload Dev Account
    └── Stg OU
        └── Workload Staging Account
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Result with &lt;code&gt;depth=1&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 put_ou_cost_category.py OUStructure 2025-01 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmnabk1xcw8c2mg94swq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmnabk1xcw8c2mg94swq3.png" alt="Result with depth1" width="645" height="565"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Result with &lt;code&gt;depth=2&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 put_ou_cost_category.py OUStructure 2025-01 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo88krza71n7lca1zmoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo88krza71n7lca1zmoa.png" alt="Result with depth1" width="629" height="578"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How the Script Works
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Get organization structure
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/shu85t/PutOuCostCategory/blob/1d1189ddf8db469ecc4ac99a24c5ae31b88a9464/put_ou_cost_category.py#L82-L136" rel="noopener noreferrer"&gt;https://github.com/shu85t/PutOuCostCategory/blob/1d1189ddf8db469ecc4ac99a24c5ae31b88a9464/put_ou_cost_category.py#L82-L136&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# --- Core Functions ---
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_organization_structure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_depth&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt; Retrieves Org structure assigning accounts to deepest category up to max_depth. Returns dict or None. Propagates exceptions. &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Fetching organization structure (assigning accounts to deepest path up to depth &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;max_depth&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; It starts by listing all accounts using &lt;code&gt;list_accounts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; For each account, it traces the full path of parent OUs back to the Root using the &lt;code&gt;list_parents&lt;/code&gt; API.&lt;/li&gt;
&lt;li&gt; It retrieves OU names using &lt;code&gt;describe_organizational_unit&lt;/code&gt; (names are cached locally via &lt;code&gt;get_ou_name&lt;/code&gt; to improve efficiency).&lt;/li&gt;
&lt;li&gt; Based on the OU path and the provided &lt;code&gt;max_depth&lt;/code&gt;, it constructs the final category name (e.g., &lt;code&gt;L1OU-L2OU&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; Crucially, each account is assigned &lt;strong&gt;uniquely&lt;/strong&gt; to the single category representing its deepest OU placement within the depth limit.&lt;/li&gt;
&lt;li&gt; Finally, it returns a Python dictionary where keys are the generated category names and values are lists of the corresponding account IDs.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Build cost category rules
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/shu85t/PutOuCostCategory/blob/1d1189ddf8db469ecc4ac99a24c5ae31b88a9464/put_ou_cost_category.py#L138-L155" rel="noopener noreferrer"&gt;https://github.com/shu85t/PutOuCostCategory/blob/1d1189ddf8db469ecc4ac99a24c5ae31b88a9464/put_ou_cost_category.py#L138-L155&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_cost_category_rules&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;org_structure&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt; Builds rule list. Skips categories with empty accounts. Propagates exceptions. &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Building Cost Category rules...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; It takes the input dictionary (mapping category names to account lists) and translates each category with accounts into a rule object formatted for the API.&lt;/li&gt;
&lt;li&gt; Returns a list containing only the rules generated for categories that actually have assigned accounts.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Put cost category
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/shu85t/PutOuCostCategory/blob/1d1189ddf8db469ecc4ac99a24c5ae31b88a9464/put_ou_cost_category.py#L181-L227" rel="noopener noreferrer"&gt;https://github.com/shu85t/PutOuCostCategory/blob/1d1189ddf8db469ecc4ac99a24c5ae31b88a9464/put_ou_cost_category.py#L181-L227&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;put_cost_category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cost_category_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;effective_start_iso_str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt; Creates/Updates Cost Category. Returns True on success. Raises exceptions on failure. Logs raw parameters. &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; It first checks if a Cost Category with the specified &lt;code&gt;cost_category_name&lt;/code&gt; already exists using &lt;code&gt;find_cost_category_arn&lt;/code&gt;. Based on the result, it prepares the necessary parameters for either the &lt;code&gt;create_cost_category_definition&lt;/code&gt; or &lt;code&gt;update_cost_category_definition&lt;/code&gt; API call.&lt;/li&gt;
&lt;li&gt; Before calling the API, it performs pre-checks on the number of rules and accounts per rule against documented limits. &lt;/li&gt;
&lt;li&gt;If validation passes, it executes the appropriate API call (create or update) to apply the changes in AWS.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Refelence
&lt;/h3&gt;

&lt;p&gt;This time, I wrote the code in Python and am using boto3. Since APIs are defined for each service [within boto3], I'm including a link to the SDK documentation for reference.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Boto3(Python SDK)

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/organizations.html" rel="noopener noreferrer"&gt;Organizations Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ce.html" rel="noopener noreferrer"&gt;CostExplorer Client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;As a side note, taking the time to carefully read through the API's defined arguments and responses – even the ones you don't end up using – is very helpful for understanding the AWS service itself, its behavior, and its various options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This script offers a method to automatically align AWS Cost Categories with your AWS Organizations OU structure. &lt;/p&gt;

&lt;p&gt;This provides a useful perspective for cost analysis, allowing you to understand costs based on the OU level categorization of accounts.&lt;/p&gt;

&lt;p&gt;Using this OU structure categorization, I noticed some unexpected costs in one area. After investigating, I identified an OpenSearch instance that could likely be optimized to reduce costs.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awsorganizations</category>
      <category>cloudfinops</category>
      <category>python</category>
    </item>
    <item>
      <title>Sharing an AWS Well-Architected workload</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Mon, 30 Sep 2024 14:23:56 +0000</pubDate>
      <link>https://dev.to/shu85t/sharing-a-aws-well-architected-workload-3h70</link>
      <guid>https://dev.to/shu85t/sharing-a-aws-well-architected-workload-3h70</guid>
      <description>&lt;p&gt;The Well-Architected Tool provides a feature to share resources. &lt;br&gt;
You can share "Workloads," "Lenses," "Profiles," and "Templates."&lt;br&gt;
You can specify "IAM users," "AWS accounts," "Organizations," or "Organizational Units (OUs)" as the recipients of the share.&lt;/p&gt;

&lt;p&gt;This post will examine the behavior and limitations of sharing workloads.&lt;/p&gt;

&lt;p&gt;Can you share with a different organization? Can you restrict permissions for sharing? Let's investigate these questions.&lt;/p&gt;
&lt;h1&gt;
  
  
  How to Share
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Management Console
&lt;/h2&gt;

&lt;p&gt;You can share from the Workloads tab by selecting "Create" under the Shares section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1lwuqq4vpyc9henvk2ip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1lwuqq4vpyc9henvk2ip.png" alt="Management Console" width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  AWS CLI
&lt;/h2&gt;

&lt;p&gt;You can share using the &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/wellarchitected/create-workload-share.html" rel="noopener noreferrer"&gt;wellarchitected create-workload-share&lt;/a&gt;. &lt;br&gt;
API specifications are &lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/APIReference/API_CreateWorkloadShare.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws wellarchitected create-workload-share &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--workload-id&lt;/span&gt; &amp;lt;value&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--shared-with&lt;/span&gt; &amp;lt;value&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--permission-type&lt;/span&gt; &amp;lt;value&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Share Recipients
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Sharing with IAM Users
&lt;/h2&gt;

&lt;p&gt;The shared workload can be accessed, and the invitation is accepted only when the specified user is logged in. The specified user can belong to a different organization from the sharing source.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing via Management Console
&lt;/h3&gt;

&lt;p&gt;Enter the IAM user ARN in the Principal field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvsmjcl5750n1mrz6ngm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvsmjcl5750n1mrz6ngm.png" alt="Management Console" width="635" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing via AWS CLI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws wellarchitected create-workload-share  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--workload-id&lt;/span&gt; 0123456789abcdef0123456789abcdef  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--shared-with&lt;/span&gt; arn:aws:iam::123456789012:user/username  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--permission-type&lt;/span&gt; READONLY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specify the workload-id as the 32-character ID following workload/ in the workload's ARN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sharing with an AWS Account
&lt;/h2&gt;

&lt;p&gt;Users with the appropriate permissions in the specified account can accept the invitation and access the shared workload. The specified account can belong to a different organization from the sharing source.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing via Management Console
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzq8ugl6e4o9sj4x1ll7n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzq8ugl6e4o9sj4x1ll7n.png" alt="Management Console" width="641" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the 12-digit AWS account ID.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing via AWS CLI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws wellarchitected create-workload-share  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--workload-id&lt;/span&gt; 0123456789abcdef0123456789abcdef  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--shared-with&lt;/span&gt; 123456789012  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--permission-type&lt;/span&gt; READONLY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sharing with an Organization
&lt;/h2&gt;

&lt;p&gt;You can share within the Organization to which the sharing source belongs.&lt;br&gt;
No invitation approval is required. Once shared, workloads can be accessed from accounts within the Organization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing via Management Console
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwf0lexn66ibk1yl2vy0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwf0lexn66ibk1yl2vy0s.png" alt="Management Console" width="658" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ID of the Organization to which the sharing source belongs is pre-filled and cannot be changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing via AWS CLI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws wellarchitected create-workload-share  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--workload-id&lt;/span&gt; 0123456789abcdef0123456789abcdef  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--shared-with&lt;/span&gt; o-123456789a  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--permission-type&lt;/span&gt; READONLY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose you specify an Organization ID other than the one you belong to. In that case, the operation will fail with the error message: "The shared with principal can only be shared to an organization that you belong to."&lt;/p&gt;

&lt;h2&gt;
  
  
  Sharing with an Organizational Unit (OU)
&lt;/h2&gt;

&lt;p&gt;You can share with an Organizational Unit (OU) within the Organization to which the sharing source belongs.&lt;br&gt;
No invitation approval is required. Once shared, workloads can be accessed from accounts within the specified OU.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing via Management Console
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeaeq82en4u1tscydl2q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeaeq82en4u1tscydl2q.png" alt="Image description" width="643" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the ID of the OU.&lt;/p&gt;

&lt;p&gt;If you enter the ID of an OU that belongs to a different Organization, the share will fail with the message: "Failed: Unable to fetch organization details."&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing via AWS CLI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws wellarchitected create-workload-share  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--workload-id&lt;/span&gt; 0123456789abcdef0123456789abcdef  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--shared-with&lt;/span&gt; ou-1234-abcdefgh  &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--permission-type&lt;/span&gt; READONLY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Permissions
&lt;/h1&gt;

&lt;p&gt;The permission required to share a workload is "wellarchitected:CreateWorkloadShare".&lt;/p&gt;

&lt;p&gt;Workloads may contain sensitive information such as the workload name, description, and review notes. In certain scenarios, you may not want to accidentally share this information outside the organization, or even within the organization to unintended OUs or accounts. &lt;/p&gt;

&lt;h3&gt;
  
  
  Can you restrict the recipients of the share?
&lt;/h3&gt;

&lt;p&gt;No, you cannot. The Principal refers to the requester, so conditions such as &lt;code&gt;aws:PrincipalOrgID&lt;/code&gt; or &lt;code&gt;aws:PrincipalOrgPaths&lt;/code&gt; cannot restrict recipients. To implement such a control, you may need to create custom rules in AWS Config to detect these settings.&lt;/p&gt;

&lt;h1&gt;
  
  
  Use Case
&lt;/h1&gt;

&lt;p&gt;Establishing mechanisms, standardization, culture, and rules at the organizational level, not just for individual projects, is often necessary to adhere to AWS Well-Architected best practices. By viewing, aggregating, and analyzing workload review reports across the Organization, you can identify areas where standardization and mechanisms are lacking and weaknesses in the Organization.&lt;/p&gt;

&lt;p&gt;Check Include workloads shared with me on the &lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/userguide/dashboard.html" rel="noopener noreferrer"&gt;dashboard&lt;/a&gt; to include shared workloads in the analysis.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>wellarchitectedframework</category>
    </item>
    <item>
      <title>Our Approach to AWS Well-Architected Best Practices</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Sun, 30 Jun 2024 14:08:37 +0000</pubDate>
      <link>https://dev.to/shu85t/our-approach-to-aws-well-architected-best-practices-3edg</link>
      <guid>https://dev.to/shu85t/our-approach-to-aws-well-architected-best-practices-3edg</guid>
      <description>&lt;h2&gt;
  
  
  What is Well-Architected?
&lt;/h2&gt;

&lt;p&gt;The Well-Architected framework, a comprehensive compilation of 'best practices' for cloud architecture, is created by AWS.&lt;br&gt;
&lt;a href="https://aws.amazon.com/architecture/well-architected" rel="noopener noreferrer"&gt;https://aws.amazon.com/architecture/well-architected&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on this review, you can identify risks that are not in line with best practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impressions from Conducting Reviews
&lt;/h2&gt;

&lt;p&gt;Meeting best practices involves not only workload-specific design, implementation, and operation but also organizational structure, rules, and training.&lt;/p&gt;

&lt;p&gt;We have been working with a cross-departmental team called the "Well-Architected Working Group" for several years, and I have compiled a rough diagram of our activities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diagram of AWS Well-Architected Utilization Status Across Our Company
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv91uccpvghttwuncuads.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv91uccpvghttwuncuads.png" alt="Diagram of AWS Well-Architected Utilization Status Across Our Company" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will pick a few examples from the diagram and introduce them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Well-Architected Working Group
&lt;/h3&gt;

&lt;p&gt;The working group comprises one or more members selected from each target department.&lt;/p&gt;

&lt;p&gt;Having members from various departments helps us understand the different circumstances and situations during our meetings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading and Discussing Best Practices
&lt;/h3&gt;

&lt;p&gt;The descriptions of best practices become more transparent and easier to understand each year. Still, some items are difficult to interpret in concrete terms. Establish internal guidelines to determine the acceptable extent and interpretation of best practices.&lt;/p&gt;

&lt;p&gt;These discussions also provide feedback on cheat sheets, internal standards and templates, internal training, and internal systems as necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mini BootCamp
&lt;/h3&gt;

&lt;p&gt;The Well-Architected BootCamp is a workshop where you can learn to apply best practices.&lt;/p&gt;

&lt;p&gt;Teams will discuss and present their results on applying best practices to virtual systems and business situations.&lt;/p&gt;

&lt;p&gt;The Mini BootCamp is our in-house version of this workshop. Below is a participation report from one of these sessions.&lt;br&gt;
&lt;a href="https://iret.media/tag/aws-well-architected-mini-bootcamp" rel="noopener noreferrer"&gt;https://iret.media/tag/aws-well-architected-mini-bootcamp&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;If reviewing becomes the main objective, it can distract from the essence. Therefore, I would like to use the AWS best practices positively to ensure quality and improve efficiency!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>wellarchitectedframework</category>
    </item>
    <item>
      <title>Easy Chaos Engineering with AWS Organizations SCP</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Thu, 28 Mar 2024 04:16:15 +0000</pubDate>
      <link>https://dev.to/shu85t/easy-chaos-engineering-with-aws-organizations-scp-8gl</link>
      <guid>https://dev.to/shu85t/easy-chaos-engineering-with-aws-organizations-scp-8gl</guid>
      <description>&lt;p&gt;I have attached a permission-robbing &lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html" rel="noopener noreferrer"&gt;SCP&lt;/a&gt; to an experiment OU, moved the target account to that OU, and observed its behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is &lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_introduction.html" rel="noopener noreferrer"&gt;AWS Organizations&lt;/a&gt;?
&lt;/h2&gt;

&lt;p&gt;AWS Organizations is an account management service that enables you to consolidate multiple AWS accounts into an "organization."AWS Organizations makes it very useful for managing multiple accounts.&lt;br&gt;
You can integrate and control &lt;a href="https://docs.aws.amazon.com/organizations/latest/userguide/orgs_integrate_services_list.html" rel="noopener noreferrer"&gt;supported AWS services&lt;/a&gt; to accounts that are members of an organization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4ejqq5tgn7n9zdxp5mc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4ejqq5tgn7n9zdxp5mc.png" alt="AWS Organizations" width="534" height="253"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Chaos with SCP
&lt;/h2&gt;

&lt;p&gt;Simulate the behavior of AWS services failure on a target workload.&lt;br&gt;
Attach a permission-robbing SCP to an experimental OU, move accounts into it, and observe workload behavior.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6nxm5cssr4iut52ya9a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6nxm5cssr4iut52ya9a.png" alt="Chaos with SCP" width="563" height="383"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Target workload
&lt;/h2&gt;

&lt;p&gt;I set the &lt;a href="https://cloudpack.jp/casestudy/209.html" rel="noopener noreferrer"&gt;In-house email notification integrated system&lt;/a&gt; as the target workload this time.&lt;/p&gt;

&lt;p&gt;The rough architecture.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8r12uo1se0c8bzyznva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8r12uo1se0c8bzyznva.png" alt="Target workload" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  permission-robbing SCP
&lt;/h2&gt;

&lt;p&gt;Set the following policies for SCP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Statement1",
      "Effect": "Deny",
      "Action": [
        "SNS:*",
        "SES:*",
        "S3:*",
        "Lambda:*",
        "Dynamodb:*",
        "SQS:*"
      ],
      "Resource": "*"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let's take a guess
&lt;/h2&gt;

&lt;p&gt;What would be the behavior if I moved a workload account to an OU with a permission-robbing SCP attached?&lt;/p&gt;

&lt;p&gt;What part of the architecture would fail?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fquaajdkexbqj2492bc4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fquaajdkexbqj2492bc4b.png" alt="What part of the architecture would fail?" width="800" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Experimental outcome
&lt;/h2&gt;

&lt;p&gt;I sent an email that this workload should notify Slack.&lt;br&gt;
However, the email has not been sent to Slack.&lt;/p&gt;

&lt;p&gt;I found that the (3)Converter failed when it was going to read the email data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ERROR] ClientError: An error occurred (AccessDenied) when calling the GetObject operation: Access Denied Traceback (most recent call last):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(1) SES -&amp;gt; (2) SNS -&amp;gt; (3) Lambda calls are connected by events and do not use IAM role access, so they worked correctly.&lt;/p&gt;

&lt;p&gt;After that, the Lambda in (3) read email data from S3 using IAM role access, so it failed here. (Got failed by Deny "S3:*")&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3zshi9sqzv3helodiu6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3zshi9sqzv3helodiu6.png" alt="outcome" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Incidentally, I checked the Lambda function from the management console, but it displayed "~with an explicit deny in a service control policy," I could not see the function. It is because "Lambda:*" is denied.&lt;/p&gt;

&lt;p&gt;It reminded me that if the service fails, I may not be able to check the status of that service resource either.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I have tried easy chaos engineering with AWS Organizations SCP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Good points of this method
&lt;/h3&gt;

&lt;p&gt;Easy to start, easy to clean up&lt;/p&gt;

&lt;p&gt;If it is through an IAM role, you can simulate, to some extent, the failure to be able to access a specific service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bad points of this method
&lt;/h3&gt;

&lt;p&gt;SCP with strong restrictions will be attached,  and a mistake can cause an accident.&lt;br&gt;
However, limiting the account IDs allowed by the "Organizations:MoveAccount" permission may reduce the incident risk.&lt;/p&gt;

&lt;p&gt;Only IAM users and IAM roles can be deny by SCP, so the situations that can be simulated are limited.&lt;/p&gt;

&lt;h3&gt;
  
  
  At the end
&lt;/h3&gt;

&lt;p&gt;Can I detect the failure? Can I identify the cause? &lt;br&gt;
I thought "Easy Chaos Engineering with AWS Organizations SCP" would be a good starting point for checking.&lt;/p&gt;

&lt;p&gt;This post is an English rewrite of &lt;a href="https://iret.media/74946" rel="noopener noreferrer"&gt;a post I wrote in Japanese&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awsorganizations</category>
    </item>
    <item>
      <title>Visualize CloudWatch Logs ingestion lag with Logs Insights</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Sun, 25 Jun 2023 18:35:14 +0000</pubDate>
      <link>https://dev.to/shu85t/visualize-cloudwatch-logs-ingestion-lag-with-logs-insights-hkl</link>
      <guid>https://dev.to/shu85t/visualize-cloudwatch-logs-ingestion-lag-with-logs-insights-hkl</guid>
      <description>&lt;p&gt;I have visualized the lag time it takes to ingest logs to CloudWatch Logs and compared it by source service!&lt;/p&gt;

&lt;h1&gt;
  
  
  0. "timestamp" and "ingestionTime"
&lt;/h1&gt;

&lt;p&gt;CloudWatch Logs event includes the following two times.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(i) &lt;a href="https://docs.aws.amazon.com/ja_jp/AmazonCloudWatchLogs/latest/APIReference/API_OutputLogEvent.html#CWL-Type-%20OutputLogEvent-timestamp" rel="noopener noreferrer"&gt;timestamp&lt;/a&gt; = The time the event occurred
&lt;/li&gt;
&lt;li&gt;(ii) &lt;a href="https://docs.aws.amazon.com/ja_jp/AmazonCloudWatchLogs/latest/APIReference/API_OutputLogEvent.html#CWL%20-Type-OutputLogEvent-ingestionTime" rel="noopener noreferrer"&gt;ingestionTime&lt;/a&gt; =The time the event was ingested into CloudWatch Logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a lag between "timestamp" and "ingestionTime".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ghvjpxv0eujqgpkjlbq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ghvjpxv0eujqgpkjlbq.png" alt="sequence" width="783" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "timestamp" (=event occurrence time) is passed by the parameter &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_InputLogEvent.html" rel="noopener noreferrer"&gt;InputLogEvent&lt;/a&gt; of &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html" rel="noopener noreferrer"&gt;PutLogEvents&lt;/a&gt;.&lt;br&gt;
This is something we're rarely aware of if we're using an integrated service or CloudWatch agent&lt;/p&gt;
&lt;h1&gt;
  
  
  1. Visualize CloudWatch Logs ingestion lag
&lt;/h1&gt;

&lt;p&gt;We can get both from the log data in Logs Insights, so we will aggregate them using the &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax-Stats.html" rel="noopener noreferrer"&gt;stats command&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  1-1. Query the "timestamp" and "ingestionTime"
&lt;/h2&gt;

&lt;p&gt;The initial query of Logs Insights only displays &lt;strong&gt;timestamp&lt;/strong&gt;, but let's display &lt;strong&gt;ingestionTime&lt;/strong&gt; as well&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="nv"&gt;fields&lt;/span&gt; &lt;span class="nv"&gt;@timestamp,&lt;/span&gt; &lt;span class="nv"&gt;@ingestionTime,&lt;/span&gt; &lt;span class="nv"&gt;@message,&lt;/span&gt; &lt;span class="nv"&gt;@logStream,&lt;/span&gt; &lt;span class="nv"&gt;@log&lt;/span&gt;
&lt;span class="nv"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;sort&lt;/span&gt; &lt;span class="nv"&gt;@timestamp&lt;/span&gt; &lt;span class="nv"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Result
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuaokfkg8jwurog87q229.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuaokfkg8jwurog87q229.png" alt="logs" width="800" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that there is a time lag of several seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  1-2. Query the time difference(=lag)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scheme"&gt;&lt;code&gt;&lt;span class="nv"&gt;fields&lt;/span&gt; &lt;span class="nv"&gt;@timestamp,&lt;/span&gt; &lt;span class="nv"&gt;@ingestionTime,&lt;/span&gt; &lt;span class="nv"&gt;toMillis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;@ingestionTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;toMillis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;@timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;diff&lt;/span&gt;
&lt;span class="nv"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;sort&lt;/span&gt; &lt;span class="nv"&gt;@timestamp&lt;/span&gt; &lt;span class="nv"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Result
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feax2ksv73s9jzicmv6rl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feax2ksv73s9jzicmv6rl.png" alt="logs" width="623" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;toMillis(@ingestionTime) - toMillis(@timestamp) as diff&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax-datetime.html" rel="noopener noreferrer"&gt;"toMillis" function&lt;/a&gt; converts the timestamp found in the named field into a number representing the milliseconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  1-3. Visualize the time difference(=lag) with stats
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fields @timestamp, @ingestionTime, toMillis(@ingestionTime) - toMillis(@timestamp) as diff
| sort @timestamp desc
| stats max(diff), pct(diff,50), avg(diff) by bin(30min)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The maximum, median (50th percentile), and mean of the difference are output at 30-minute intervals. The period is specified as 2 weeks.&lt;br&gt;
The maximum number of log fields that Logs Insights can output is 1,000, so the interval and period must be adjusted accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7fcetd8eiqc9l80y9pc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7fcetd8eiqc9l80y9pc.png" alt="visualization" width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  2 Comparison of lag by source service
&lt;/h1&gt;

&lt;p&gt;Let's run a visualization query to see if the time difference differs depending on the log source!&lt;/p&gt;

&lt;h2&gt;
  
  
  2-1. AWS Lambda
&lt;/h2&gt;

&lt;p&gt;AWS Lambda is integrated with CloudWatch and automatically outputs logs with appropriate permissions, so we query the group. (/aws/lambda/{function name})&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2iydsfoiqof0srkuj49a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2iydsfoiqof0srkuj49a.png" alt="aws lambda" width="800" height="219"&gt;&lt;/a&gt;&lt;br&gt;
The median time is about less than 9 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  2-2. EC2 + CloudWatch Agent
&lt;/h2&gt;

&lt;p&gt;Query the log group that EC2 is outputting via CloudWatch Agent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgbjtc50x0h737w4be8v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgbjtc50x0h737w4be8v.png" alt="ec2" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The median is a little over 5 seconds, but the maximum is around 16 seconds.&lt;br&gt;
It may depend on the contents of the agent configuration file (per force_flush_interval?) &lt;/p&gt;

&lt;h2&gt;
  
  
  2-3. API Gateway
&lt;/h2&gt;

&lt;p&gt;Query the log group that is output when log output is enabled on API Gateway.&lt;br&gt;
(API-Gateway-Execution-Logs_{stage ID})&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny6vm2qrv5hbobb38qvn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny6vm2qrv5hbobb38qvn.png" alt="api gateway" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The median time is over 20 seconds, the longest among those compared.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;There were differences in lagging tendencies among the services. It would be fun to try to guess the cause.&lt;/p&gt;

&lt;p&gt;I used Logs Insights to visualize the data, and found it easy and useful.&lt;/p&gt;

&lt;p&gt;This post is an English rewrite of &lt;a href="https://iret.media/71989" rel="noopener noreferrer"&gt;an post I wrote in Japanese&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudwatchlogs</category>
      <category>cloudwatchlogsinsights</category>
    </item>
    <item>
      <title>Python script to list unused IP addresses in AWS VPC Subnet</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Thu, 31 Mar 2022 14:19:23 +0000</pubDate>
      <link>https://dev.to/shu85t/python-script-to-list-unused-ip-addresses-in-aws-vpc-subnet-jai</link>
      <guid>https://dev.to/shu85t/python-script-to-list-unused-ip-addresses-in-aws-vpc-subnet-jai</guid>
      <description>&lt;p&gt;I wrote a Python script to list unused IP addresses (IPv4) in a subnet.&lt;/p&gt;

&lt;p&gt;I have used &lt;a href="https://blog.ilearnaws.com/2020/10/08/how-do-i-know-the-unused-ip-addresses/" rel="noopener noreferrer"&gt;Henry's post&lt;/a&gt; as a reference, thanks.&lt;/p&gt;

&lt;h1&gt;
  
  
  Mechanism
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Get the CIDR of specified subnet by &lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Client.describe_subnets" rel="noopener noreferrer"&gt;DescribeSubnets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Get the used private IP addresses in specified subnet by  &lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Client.describe_network_interfaces" rel="noopener noreferrer"&gt;DescribeNetworkInterfaces&lt;/a&gt; = Used IP addresses&lt;/li&gt;
&lt;li&gt;Calculate the Unused IP addresses = "CIDR IP addresses" - "Used IP addresses" - "Reserved IP Addresses"&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  note
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I used &lt;a href="https://docs.python.org/3/library/ipaddress.html" rel="noopener noreferrer"&gt;ipaddress module&lt;/a&gt; to calculate IP addresses within the CIDR.&lt;/li&gt;
&lt;li&gt;I used "PrivateIpAddresses array" instead of "PrivateIpAddress" to extract both primary and secondary addresses from the NetworkInterface response.&lt;/li&gt;
&lt;li&gt;Reserved IP addresses are described in &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html#subnet-sizing" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;For example, if you create a VPC with CIDR block 10.0.0.0/24, it supports 256 IP addresses. You can break this CIDR block into two subnets, each supporting 128 IP addresses. One subnet uses CIDR block 10.0.0.0/25 (for addresses 10.0.0.0 - 10.0.0.127) and the other uses CIDR block 10.0.0.128/25 (for addresses 10.0.0.128 - 10.0.0.255).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Python script
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/shu85t/aws_describe_unused_ips" rel="noopener noreferrer"&gt;https://github.com/shu85t/aws_describe_unused_ips&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&amp;gt;Python3.8&lt;/li&gt;
&lt;li&gt;boto3&lt;/li&gt;
&lt;li&gt;AWS Permissions

&lt;ul&gt;
&lt;li&gt;ec2:DescribeSubnets&lt;/li&gt;
&lt;li&gt;ec2:DescribeNetworkInterfaces&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export AWS_DEFAULT_REGION={region name}
export AWS_DEFAULT_PROFILE={aws profile name}
python describe_unused_ips.py {subnet-id}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export AWS_DEFAULT_REGION=ap-northeast-1
export AWS_DEFAULT_PROFILE=my_aws_account
python describe_unused_ips.py subnet-000000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;subnet_id='subnet-000000000000' mode='normal'
cidr='10.1.0.0/24'
cidr_ips=['10.1.0.0', '10.1.0.1', '10.1.0.2', '10.1.0.3', '10.1.0.4', ...]
-----------
reserved_ips=['10.1.0.0', '10.1.0.1', '10.1.0.2', '10.1.0.3', '10.1.0.255']
-----------
used_ips=['10.1.0.39']
-----------
unused_ips=['10.1.0.4', '10.1.0.5', '10.1.0.6', ...]
-----------
cidr=10.1.0.0/24 cidr_ips=256 reserved=5 used=1 unused=250
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This post is an English rewrite of &lt;a href="https://iret.media/61691" rel="noopener noreferrer"&gt;an post I wrote in Japanese&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>vpc</category>
      <category>network</category>
    </item>
    <item>
      <title>How long is your Maximum Line Length for PEP 8?</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Mon, 06 Sep 2021 01:52:33 +0000</pubDate>
      <link>https://dev.to/shu85t/how-long-is-your-maximum-line-length-for-pep8-g2m</link>
      <guid>https://dev.to/shu85t/how-long-is-your-maximum-line-length-for-pep8-g2m</guid>
      <description>&lt;h1&gt;
  
  
  Style Guide
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.python.org/dev/peps/pep-0008/#maximum-line-length" rel="noopener noreferrer"&gt;PEP 8 Maximum Line Length&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Limit all lines to a maximum of 79 characters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I used to follow this guide and set the default value to 79 characters in Lint.&lt;br&gt;
However, the readability was sometimes compromised to comply with this, so I decided to reread the guide and tune the setting values.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Some teams strongly prefer a longer line length. For code maintained exclusively or primarily by a team that can reach agreement on this issue, it is okay to increase the line length limit up to 99 characters, provided that comments and docstrings are still wrapped at 72 characters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The rationale for the 79 characters is described as follows.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Limiting the required editor window width makes it possible to have several files open side by side, and works well when using code review tools that present the two versions in adjacent columns.&lt;br&gt;
The default wrapping in most tools disrupts the visual structure of the code, making it more difficult to understand. The limits are chosen to avoid wrapping in editors with the window width set to 80, even if the tool places a marker glyph in the final column when wrapping lines. Some web based tools may not offer dynamic line wrapping at all.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I see.&lt;/p&gt;

&lt;p&gt;Also, in &lt;a href="https://www.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds" rel="noopener noreferrer"&gt;A Foolish Consistency is the Hobgoblin of Little Minds&lt;/a&gt; there is a section that says&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;However, know when to be inconsistent -- sometimes style guide recommendations just aren't applicable. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don't hesitate to ask!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Note
&lt;/h1&gt;

&lt;h2&gt;
  
  
  IDE defaults
&lt;/h2&gt;

&lt;p&gt;VisualStudioCode and PyCharm defaulted to 120 characters per line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Languages
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Characters_per_line" rel="noopener noreferrer"&gt;Characters per line - Wikipedia&lt;/a&gt;  has a good summary.&lt;br&gt;
There are many languages with 80 characters.&lt;/p&gt;

&lt;p&gt;Interestingly, they seem to be derived from typewriters and punch cards.&lt;/p&gt;

&lt;h1&gt;
  
  
  How long is my Maximum Line Length for PEP 8?
&lt;/h1&gt;

&lt;p&gt;So, I changed the Maximum Line Length to 90 for the time being because, in our team's standard editors, about 90 characters can be displayed in the one tree tab + two editor tabs.&lt;/p&gt;

&lt;p&gt;It's been a couple of months now, and I'm glad I changed it.&lt;/p&gt;

&lt;p&gt;I'm thinking of changing it to 99 characters after seeing how it goes.&lt;/p&gt;

</description>
      <category>python</category>
      <category>pep8</category>
      <category>programming</category>
    </item>
    <item>
      <title>Listing of AWS Lambda Python 2.7 functions that will be EOL(across all regions)</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Mon, 19 Apr 2021 11:29:08 +0000</pubDate>
      <link>https://dev.to/shu85t/listing-of-aws-lambda-python-2-7-functions-that-will-be-eol-across-all-regions-2khd</link>
      <guid>https://dev.to/shu85t/listing-of-aws-lambda-python-2-7-functions-that-will-be-eol-across-all-regions-2khd</guid>
      <description>&lt;p&gt;The official AWS blog posted An announcement titled &lt;a href="https://aws.amazon.com/blogs/compute/announcing-end-of-support-for-python-2-7-in-aws-lambda/" rel="noopener noreferrer"&gt;Announcing end of support for Python 2.7 in AWS Lambda&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the post, there is an AWS CLI command that lists Python 2.7 Lambda functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda list-functions &lt;span class="nt"&gt;--function-version&lt;/span&gt; ALL &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"Functions[?Runtime=='python2.7'].FunctionArn"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Across all regions
&lt;/h1&gt;

&lt;p&gt;Here is a shell to run its command across all regions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Script(list-py27functions.sh)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;region &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;aws ec2 describe-regions &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"Regions[].RegionName"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-west-1 &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;region&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]"&lt;/span&gt;
    aws lambda list-functions &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;region&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"Functions[?Runtime=='python2.7'].{ARN:FunctionArn, Runtime:Runtime}"&lt;/span&gt;
&lt;span class="k"&gt;done
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"finished"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xxxx &lt;span class="c"&gt;# Not necessary if you always set the default profile.&lt;/span&gt;
sh list-py27functions.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[eu-north-1]
[ap-south-1]
[eu-west-3]
[eu-west-2]
[eu-west-1]
[ap-northeast-3]
[ap-northeast-2]
[ap-northeast-1]
arn:aws:lambda:ap-northeast-1:111111111111:function:xxxxx   python2.7
arn:aws:lambda:ap-northeast-1:111111111111:function:yyyyy   python2.7
[ca-central-1]
[ap-east-1]
[ap-southeast-1]
[ap-southeast-2]
[eu-central-1]
[us-east-1]
arn:aws:lambda:us-east-1:111111111111:function:test python2.7
[us-east-2]
[us-west-1]
[us-west-2]
arn:aws:lambda:us-west-2:111111111111:function:zzzz python2.7
finished
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also run it from within CloudShell without specifying a profile.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reference
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/blogs/compute/announcing-end-of-support-for-python-2-7-in-aws-lambda/" rel="noopener noreferrer"&gt;Announcing end of support for Python 2.7 in AWS Lambda&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/lambda/list-functions.html" rel="noopener noreferrer"&gt;AWS CLI::list-functions&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-regions.html" rel="noopener noreferrer"&gt;AWS CLI::describe-regions&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-filter.html" rel="noopener noreferrer"&gt;AWS CLI::Filtering&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>python</category>
      <category>shell</category>
    </item>
    <item>
      <title>Search for a keyword across all AWS Lambda functions with zipgrep</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Wed, 30 Dec 2020 18:09:51 +0000</pubDate>
      <link>https://dev.to/shu85t/search-for-a-keyword-across-all-aws-lambda-functions-with-zipgrep-52ah</link>
      <guid>https://dev.to/shu85t/search-for-a-keyword-across-all-aws-lambda-functions-with-zipgrep-52ah</guid>
      <description>&lt;p&gt;Liquid syntax error: 'raw' tag was never closed&lt;/p&gt;
</description>
      <category>aws</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Listing of all resources in all AWS regions (shell script)</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Tue, 20 Oct 2020 10:39:42 +0000</pubDate>
      <link>https://dev.to/shu85t/listing-of-all-resources-in-all-aws-regions-shell-script-2bia</link>
      <guid>https://dev.to/shu85t/listing-of-all-resources-in-all-aws-regions-shell-script-2bia</guid>
      <description>&lt;p&gt;This allows you to see the overall resources without having to check for each region and each service.&lt;/p&gt;

&lt;p&gt;When you &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/close-aws-account/?nc1=h_ls" rel="noopener noreferrer"&gt;close your AWS Account&lt;/a&gt;, it also helps you to see if there are any active resources left over.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;if you have any active resources and terminate them before you close your account&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Script
&lt;/h1&gt;

&lt;p&gt;get-resources.sh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;region &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;aws ec2 describe-regions &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Regions[].RegionName'&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-west-1 &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"region = &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;region&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    aws resourcegroupstaggingapi get-resources &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;region&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'ResourceTagMappingList[].ResourceARN'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;For each region fetched by describe-regions, I use resourcegroupstaggingapi get-resources.&lt;/li&gt;
&lt;li&gt;It's OK to do describe-regions at any region, so I've set it to us-west-1.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/jp/cli/" rel="noopener noreferrer"&gt;aws cli&lt;/a&gt; is installed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Usage
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Run
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xxxx &lt;span class="c"&gt;# Not necessary if you always set the default profile.&lt;/span&gt;
sh get-resources.sh 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Output
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;region &lt;span class="o"&gt;=&lt;/span&gt; eu-north-1
&lt;span class="o"&gt;[]&lt;/span&gt;
region &lt;span class="o"&gt;=&lt;/span&gt; ap-south-1
&lt;span class="o"&gt;[]&lt;/span&gt;
region &lt;span class="o"&gt;=&lt;/span&gt; eu-west-3
&lt;span class="o"&gt;[]&lt;/span&gt;
region &lt;span class="o"&gt;=&lt;/span&gt; eu-west-2
&lt;span class="o"&gt;[]&lt;/span&gt;
region &lt;span class="o"&gt;=&lt;/span&gt; eu-west-1
&lt;span class="o"&gt;[]&lt;/span&gt;
region &lt;span class="o"&gt;=&lt;/span&gt; ap-northeast-2
&lt;span class="o"&gt;[]&lt;/span&gt;
region &lt;span class="o"&gt;=&lt;/span&gt; ap-northeast-1
&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"arn:aws:apigateway:ap-northeast-1::/restapis/〜/stages/devA"&lt;/span&gt;,
    &lt;span class="s2"&gt;"arn:aws:apigateway:ap-northeast-1::/restapis/〜/stages/devB"&lt;/span&gt;,
〜
    &lt;span class="s2"&gt;"arn:aws:ec2:ap-northeast-1:111111111111:vpc/vpc-1111111a"&lt;/span&gt;,
    &lt;span class="s2"&gt;"arn:aws:ec2:ap-northeast-1:111111111111:vpc/vpc-1111111b"&lt;/span&gt;,
〜
    &lt;span class="s2"&gt;"arn:aws:lambda:ap-northeast-1:111111111111:function:xxxx-checker"&lt;/span&gt;,
    &lt;span class="s2"&gt;"arn:aws:lambda:ap-northeast-1:111111111111:function:xxxx-deleter"&lt;/span&gt;,
〜
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Notes
&lt;/h1&gt;

&lt;p&gt;If there is a service that is not supported by the resourcegroupstaggingapi, it will not be listed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reference
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ec2/describe-regions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-regions.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-regions.html&lt;/a&gt;&lt;br&gt;
Used for listing regions&lt;/p&gt;

&lt;h2&gt;
  
  
  resourcegroupstaggingapi/get-resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/resourcegroupstaggingapi/get-resources.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cli/latest/reference/resourcegroupstaggingapi/get-resources.html&lt;/a&gt;&lt;br&gt;
Used for listing resources&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I close my AWS account?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/close-aws-account/?nc1=h_ls" rel="noopener noreferrer"&gt;https://aws.amazon.com/premiumsupport/knowledge-center/close-aws-account/?nc1=h_ls&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>Using Secrets Manager or SSM Parameters by both ECS and local machine</title>
      <dc:creator>Shuichi Takahashi</dc:creator>
      <pubDate>Wed, 05 Feb 2020 11:34:54 +0000</pubDate>
      <link>https://dev.to/shu85t/using-secrets-manager-or-ssm-parameters-by-both-ecs-and-local-machine-2o1m</link>
      <guid>https://dev.to/shu85t/using-secrets-manager-or-ssm-parameters-by-both-ecs-and-local-machine-2o1m</guid>
      <description>&lt;h1&gt;
  
  
  Goal
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Amazon ECS enables you to inject sensitive data into your containers by storing your sensitive data in either AWS Secrets Manager secrets or AWS Systems Manager Parameter Store parameters and then referencing them in your container definition. This feature is supported by tasks using both the EC2 and Fargate launch types.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is useful to inject parameters into containers on ECS.&lt;br&gt;
I also want to use this method for containers on a local machine too.&lt;br&gt;
Because I am often running containers on a local machine when debugging.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Inject parameter named ServiceSettings Into a container on a local machine from Secret Manager or SSM Parameter Store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Precondition
&lt;/h2&gt;

&lt;p&gt;AWS CLI is installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shell
&lt;/h2&gt;

&lt;h3&gt;
  
  
  When using Secret Manager.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;setting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;aws secretsmanager get-secret-value &lt;span class="nt"&gt;--secret-id&lt;/span&gt; ServiceSetting &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'SecretString'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-e&lt;/span&gt;  &lt;span class="nv"&gt;SERVICE_SETTING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$setting&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The point is to use the "--output text" option.&lt;/p&gt;

&lt;h3&gt;
  
  
  When using SSM Parameter Store
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;setting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;aws ssm get-parameter &lt;span class="nt"&gt;--name&lt;/span&gt; ServiceSetting &lt;span class="nt"&gt;--with-decryption&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="nt"&gt;--query&lt;/span&gt; Parameter.Value | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;' \n'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-e&lt;/span&gt;  &lt;span class="nv"&gt;SERVICE_SETTING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$setting&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The point is to use the "tr" to delete spaces and newlines.&lt;br&gt;
And use the "--with-decryption" option when parameters are encrypted.&lt;/p&gt;

&lt;h1&gt;
  
  
  Result
&lt;/h1&gt;

&lt;p&gt;ECS and a local machine no longer need to change the way environment variables are captured in the application code.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ecs</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
