<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Yahya Mohamed on Medium]]></title>
        <description><![CDATA[Stories by Yahya Mohamed on Medium]]></description>
        <link>https://medium.com/@yahmo?source=rss-37293dc400a0------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*dmbNkD5D-u45r44go_cf0g.png</url>
            <title>Stories by Yahya Mohamed on Medium</title>
            <link>https://medium.com/@yahmo?source=rss-37293dc400a0------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 04 Jun 2026 21:51:05 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@yahmo/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[How to Improve the Security of Your Terraform Resources Using Checkov]]></title>
            <link>https://medium.com/@yahmo/how-to-improve-the-security-of-your-terraform-resources-using-checkov-dd6a1333ba13?source=rss-37293dc400a0------2</link>
            <guid isPermaLink="false">https://medium.com/p/dd6a1333ba13</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[terraform]]></category>
            <category><![CDATA[security]]></category>
            <category><![CDATA[infrastructure-as-code]]></category>
            <category><![CDATA[checkov]]></category>
            <dc:creator><![CDATA[Yahya Mohamed]]></dc:creator>
            <pubDate>Tue, 12 Aug 2025 15:44:17 GMT</pubDate>
            <atom:updated>2025-08-12T15:44:17.113Z</atom:updated>
            <content:encoded><![CDATA[<p>You’ve created well-structured Terraform modules, following the DRY principle.</p><p>Your code is clean; main.tf, variables.tf, outputs.tf, everything is in place.</p><p>Terraform apply runs successfully, and your resources are provisioned exactly as planned.</p><p>But there’s a catch: <strong>your Terraform configurations might not be secure enough</strong>.</p><p>So how do we tighten the security of our infrastructure?</p><p>This is where <strong>Checkov</strong> comes in.</p><h3>What is Checkov?</h3><p>Checkov is an <strong>open-source static analysis tool</strong> for IaC (Infrastructure-as-Code) that scans Terraform, CloudFormation, Kubernetes, and other IaC files for misconfigurations and security issues.</p><p>When run, it:</p><ul><li>Performs multiple security and compliance checks on your Terraform code.</li><li>Flags any misconfigurations, vulnerabilities, or best practice violations.</li><li>Guides on how to fix each failed check.</li></ul><p>In short: <strong>Checkov helps you find and fix security issues before they make it into production</strong>.</p><h3>Let’s Try It Out</h3><h4>Step 1 — Install Checkov</h4><p>You can install Checkov locally:</p><p><strong>macOS (Homebrew)</strong></p><pre>brew install checkov</pre><p><strong>Python (Cross-platform)</strong></p><pre>pip install checkov</pre><h4>Step 2 — Navigate to Your Terraform Code</h4><p>Move into the folder containing your Terraform configuration files:</p><pre>cd path/to/terraform/code</pre><h4>Step 3 — Run Checkov</h4><p>Run the following command to scan your entire directory:</p><pre>checkov -d . --quiet</pre><p>Here’s an example output from my run:</p><blockquote><em>I had </em><strong><em>10 failed security checks</em></strong><em> in my Terraform code.</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nlATrHV2aLIyMpANZUVXSg.png" /><figcaption>Checkov failed checks (Before)</figcaption></figure><h3>Fixing a Failed Check Example</h3><p>Let’s fix one of these failed checks for demonstration purposes.</p><p>One of my failed checks was:<br> <strong>CKV_AWS_130</strong> – This warns if a public subnet automatically assigns public IP addresses to instances on launch.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*C8X6zrlNGmTbacxrPPLEGw.png" /><figcaption>CKV_AWS_130: Map Public IP assigned to true</figcaption></figure><h4>Finding the Root Cause</h4><p>Upon checking the Checkov documentation, I found the cause:<br>My Terraform code had map_public_ip_on_launch = true, meaning any EC2 instance launched in this subnet would be publicly accessible by default.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*A73AB1XcJdVknEJ4vVaHag.png" /><figcaption>Documentation showcasing the solution (and describing the reason it failed)</figcaption></figure><p><strong>Security best practice:</strong><br> Set map_public_ip_on_launch to false unless explicitly needed.</p><h4>Before:</h4><pre>resource &quot;aws_subnet&quot; &quot;public&quot; {<br>  vpc_id                  = var.vpc_id<br>  cidr_block              = var.public_subnets_cidr_blocks[count.index]<br>  availability_zone       = var.azs[count.index]<br>  map_public_ip_on_launch = true<br>}</pre><h4>After (Fixed):</h4><pre>resource &quot;aws_subnet&quot; &quot;public&quot; {<br>  vpc_id                  = var.vpc_id<br>  cidr_block              = var.public_subnets_cidr_blocks[count.index]<br>  availability_zone       = var.azs[count.index]<br>  map_public_ip_on_launch = false<br>}</pre><h4>Step 4 — Re-run Checkov</h4><pre>checkov -d . --quiet</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-pfwdt9Zbs9hEWMK9AmSsg.png" /><figcaption>Checkov failed checks (after)</figcaption></figure><p>As you can see, the number of failed checks dropped from <strong>10 → 7</strong>.<br>(The other failed checks can be fixed in a similar way.)</p><h3>Skipping Specific Checks</h3><p>Sometimes you might want to skip certain checks — for example, in non-production environments or known exceptions.</p><p>To skip a specific check, pass the --skip-check flag:</p><pre>checkov -d . --skip-check CKV_AWS_289,CKV_AWS_129</pre><p>This will exclude those checks from the scan results.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1Q21WfiL3YXku-6p7YF3qw.png" /><figcaption>Checkov scan results after using the — skip-check flag</figcaption></figure><h3>Summary</h3><p>In this tutorial, we:</p><ul><li>Installed and ran <strong>Checkov</strong> to scan Terraform code for security issues.</li><li>Identified a failed check (CKV_AWS_130) and fixed it by updating the subnet configuration.</li><li>Learnt how to skip certain checks when necessary.</li></ul><p><strong>Key Takeaway:</strong><br>Checkov is a powerful tool to integrate into your IaC workflow, ensuring your Terraform code follows security best practices before it ever reaches production.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dd6a1333ba13" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Connect GitHub Actions with AWS Without Storing Long-Lived Secrets]]></title>
            <link>https://medium.com/@yahmo/how-to-connect-github-actions-with-aws-without-storing-long-lived-secrets-dcef33a17c1e?source=rss-37293dc400a0------2</link>
            <guid isPermaLink="false">https://medium.com/p/dcef33a17c1e</guid>
            <category><![CDATA[oidc]]></category>
            <category><![CDATA[github]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[ami]]></category>
            <category><![CDATA[github-actions]]></category>
            <dc:creator><![CDATA[Yahya Mohamed]]></dc:creator>
            <pubDate>Mon, 11 Aug 2025 15:51:54 GMT</pubDate>
            <atom:updated>2025-08-11T15:51:54.945Z</atom:updated>
            <content:encoded><![CDATA[<p>When connecting GitHub Actions workflows to AWS services, there are two main authentication approaches:</p><h3>1. Using Long-Lived AWS IAM User Credentials (Secrets)</h3><ul><li>Create an IAM user in AWS and generate an <strong>Access Key ID</strong> and <strong>Secret Access Key</strong>.</li><li>Store these keys in GitHub under <strong>Settings → Secrets and variables</strong> (at the repository or environment level).</li><li>The GitHub Actions workflow retrieves these secrets and uses them to authenticate to AWS.</li><li><strong>Drawback:</strong> Long-lived credentials must be rotated manually and are at risk if exposed.</li></ul><h3>2. Using OpenID Connect (OIDC) — The More Secure Way</h3><ul><li>Instead of long-lived credentials, your workflow requests a short-lived token from GitHub’s OIDC provider at runtime.</li><li>This token is exchanged with AWS Security Token Service (STS) for temporary credentials.</li><li>No AWS keys are stored in GitHub.</li></ul><h3>Example Scenario</h3><p>We have a workflow that builds a Docker image and pushes it to <strong>Amazon Elastic Container Registry (ECR)</strong>.</p><ul><li><strong>Before (Secrets-Based Authentication):</strong><br> The workflow retrieves AWS credentials from AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY stored in GitHub Secrets.</li><li><strong>After (OIDC-Based Authentication):</strong><br> The workflow assumes a temporary AWS role at runtime — <strong>no secrets needed</strong>.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cDSf4JAUGxGKRdYQhsh5vQ.png" /><figcaption>Our current workflow yaml file that uses secrets based authentication (Before)</figcaption></figure><h3>How OIDC Authentication Works with AWS and GitHub Actions</h3><ol><li><strong>Token Request</strong> — The workflow requests an OIDC token from GitHub’s OIDC provider.</li><li><strong>Role Assumption</strong> — AWS STS is called with AssumeRoleWithWebIdentity using that token.</li><li><strong>Validation</strong> — AWS verifies the token against the IAM role’s trust policy (which can be restricted to specific repos/branches).</li><li><strong>Temporary Credentials</strong> — AWS issues short-lived credentials (up to 1 hour).</li><li><strong>Access AWS Services</strong> — The workflow uses these temporary credentials to interact with AWS, limited by the role’s permissions.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QWRbRfg5EzG00YKY8ggoaw.png" /><figcaption>Architecture diagram showcasing the OIDC Authentication Workflow</figcaption></figure><h3>Setting Up OIDC with AWS and GitHub Actions</h3><h3>Step 1 — Add GitHub as an Identity Provider in AWS</h3><ol><li>Go to <strong>AWS IAM</strong> → <strong>Identity Providers</strong> → <strong>Add Provider</strong>.</li><li>Provider type: <strong>OpenID Connect</strong>.</li><li>Pass in the Provider URL and Audience as shown below</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NYP52l8RQbqIb-gpTNxl6w.png" /><figcaption>Image demonstrating how to add the identity provider</figcaption></figure><h3>Step 2 — Create an IAM Role for GitHub Actions</h3><ol><li>Go to <strong>AWS IAM → Roles → Create role</strong>.</li><li>Choose <strong>Web identity</strong> and select the OIDC provider you created.</li><li>Set audience to sts.amazonaws.com.</li><li>Attach an IAM policy (for testing, you can use AdministratorAccess, but in production, follow the <strong>principle of least privilege</strong>).</li><li>Add a <strong>trust policy condition</strong> to restrict access, e.g.,</li></ol><pre>&quot;Condition&quot;: {<br>  &quot;StringEquals&quot;: {<br>    &quot;token.actions.githubusercontent.com:sub&quot;: &quot;repo:your-username/your-repo:ref:refs/heads/main&quot;<br>  }<br>}</pre><p>6. Create the role and <strong>copy the Role ARN</strong>.</p><h3>Step 3 — Update Your GitHub Actions Workflow</h3><p>At the top of your workflow, allow the job to request the OIDC token:</p><pre>permissions:<br>  contents: read<br>  id-token: write</pre><p>and replace the old secrets-based step with:</p><pre>- name: Configure AWS Credentials using OIDC<br>  uses: aws-actions/configure-aws-credentials@v4<br>  with:<br>    aws-region: ${{ env.AWS_REGION }}<br>    role-to-assume: arn:aws:iam::123456789012:role/GitHubOIDCRole<br>    audience: sts.amazonaws.com</pre><p>Optional: You can also create a secret for the AWS IAM Role ARN and reference it within the step.</p><h3>Step 4 — Test the Workflow</h3><p>Push your changes to the branch specified in the IAM role’s trust policy.<br> If successful, your build will proceed without any long-lived secrets.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aI0yV14bmFx_SikBL4HYcw.png" /></figure><p><strong>Summary</strong><br> In this guide, we explored how to replace long-lived AWS credentials in GitHub Actions with a secure, short-lived authentication method using OpenID Connect (OIDC). By configuring AWS to trust GitHub’s OIDC provider, your workflows can assume IAM roles at runtime without storing secrets in your repository. This approach reduces security risks, automates credential rotation, and allows fine-grained access control, making it a best practice for connecting GitHub Actions to AWS.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dcef33a17c1e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Create and Delete an S3 Bucket using the AWS CLI (Command line Interface)]]></title>
            <link>https://medium.com/@yahmo/how-to-create-and-delete-an-s3-bucket-using-the-aws-cli-command-line-interface-ca9dd9bb4337?source=rss-37293dc400a0------2</link>
            <guid isPermaLink="false">https://medium.com/p/ca9dd9bb4337</guid>
            <dc:creator><![CDATA[Yahya Mohamed]]></dc:creator>
            <pubDate>Thu, 03 Oct 2024 18:31:33 GMT</pubDate>
            <atom:updated>2024-10-03T18:31:33.541Z</atom:updated>
            <content:encoded><![CDATA[<p>An S3 bucket is an online storage container from Amazon Web Services where you can store and manage files and data. Just like the AWS Portal, we are also able to create an S3 bucket using the CLI. Here is how:</p><h4><strong>1. Install the AWS CLI</strong>:</h4><p>You can refer to the documentation to install the AWS CLI here → <a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"><strong>https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html</strong></a></p><h4>2. AWS CLI Configuration:</h4><p>Make sure you have configured the AWS CLI with your credentials (Access Key and Secret Key). To create these, go to the AWS portal, click on your <strong>username/profile</strong> in the top right corner, select <strong>Security Credentials</strong>, then scroll down to <strong>Access Keys</strong>. From there, create new access keys, and you’ll have the credentials needed for AWS CLI configuration.</p><p>To configure the AWS CLI, run the `<strong>aws configure</strong>` command, input your Access Key and Secret Key, and either accept the default options for the following prompts or customise them as needed.</p><h4>3. Using the S3 API:</h4><p>You can use the aws s3api help command to display a list of all the available commands that you can execute. These commands represent requests made to the S3 bucket API for performing various CRUD (Create, Read, Update, Delete) operations. Essentially, the s3api interface allows you to directly interact with the S3 service at a more granular level, giving you control over actions like creating buckets, uploading files, retrieving objects, managing permissions, and more. Here&#39;s a more detailed breakdown of the types of commands you should expect to see when using s3api.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/880/1*k9GKIfDxSl_3CdMZdAiEIw.png" /><figcaption>S3api help command output</figcaption></figure><p>4. Use the create-bucket command. Make sure the bucket name is both unique and valid, and specify the region where you&#39;d like the bucket to be located. Additionally, there are several optional arguments you can provide when setting up the S3 bucket to customise its configuration further.</p><pre>aws s3api create-bucket --bucket test-bucket-98928124  --region us-east-1</pre><p>You should then be able to see an output:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*WinexrZXd4oou-cB6ZMloA.png" /><figcaption>Successful creation of the s3 bucket</figcaption></figure><p>And Voila! You have successfully created an S3 Bucket. To confirm your newly created resource, Use the command:</p><pre>aws s3 ls </pre><p>You should see the <strong>date/time</strong> and the s3 bucket <strong>name</strong> as the output</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/622/1*wOIhMssbjKSM-ucKrhI37A.png" /><figcaption>aws s3 ls output</figcaption></figure><p>To now <strong>delete</strong> your newly created s3 bucket. Use the command:</p><pre>aws s3api delete-bucket --bucket test-bucket-98928124  --region us-east-1</pre><p>Then use the command:</p><pre>aws s3 ls </pre><p>You should see that you no longer get the s3 bucket as an output, indicating that the s3 bucket no longer exists. To confirm, you can also view the AWS UI (Portal) to see if the changes made on the CLI are reflected on the console.</p><p>And that’s it! That is how you create and delete an S3 Bucket.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ca9dd9bb4337" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>