<?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: Fady</title>
    <description>The latest articles on DEV Community by Fady (@fadyio).</description>
    <link>https://dev.to/fadyio</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%2F751249%2F66d299a9-36bf-4e1b-958f-5da6d6edf274.png</url>
      <title>DEV Community: Fady</title>
      <link>https://dev.to/fadyio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fadyio"/>
    <language>en</language>
    <item>
      <title>Securely Accessing Private AWS Resources from GitHub Actions with TailScale</title>
      <dc:creator>Fady</dc:creator>
      <pubDate>Thu, 14 Dec 2023 09:49:49 +0000</pubDate>
      <link>https://dev.to/aws-builders/securely-accessing-private-aws-resources-from-github-actions-with-tailscale-7ol</link>
      <guid>https://dev.to/aws-builders/securely-accessing-private-aws-resources-from-github-actions-with-tailscale-7ol</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;One of the common problems of CI/CD automation is how to handle private resources without exposing these resources directly to the public or relying on complex VPN setups may not be the ideal solution.&lt;/p&gt;

&lt;p&gt;Typically, you go with something like OpenVPN, but OpenVPN can be complicated, with something like OpenVPN,you have to set up your own server, and configure, maintain, etc. On the other hand, it takes less than 2 minutes to set up TailScale, Another thing, if you live in a country where OpenVPN is blocked, you don't have many options.&lt;/p&gt;

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

&lt;p&gt;Here is the diagram that we are going to be implanted in this blog, the blog post will guide you with step-by-step through its implementation. The initial steps involve setting up a GitHub Actions workflow that installs the TailScale client and authorizes it into a TailScale network. Subsequently, the blog post will cover the creation and configuration of the TailScale router, ensuring proper traffic routing and security group settings on AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting GitHub Actions to the Tailscale Network
&lt;/h2&gt;

&lt;p&gt;Before starting this guide, you'll need to have a Tailscale network set up and configured with at least one existing device, If you do not know how, follow this &lt;a href="https://tailscale.com/kb/1017/install/" rel="noopener noreferrer"&gt;guide&lt;/a&gt; and of course you're going to need an AWS account as well.&lt;/p&gt;

&lt;p&gt;Now the next thing that I'm going to do is go out to GitHub and create a new repository,You can find the code for the end result in this &lt;a href="https://github.com/Fadyio/Accessing-Private-AWS-Resources" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You will then need to create an OAuth client to use with the Github action via this &lt;a href="https://login.tailscale.com/admin/settings/oauth" rel="noopener noreferrer"&gt;link&lt;/a&gt;, copy the Client ID and Client Secret to a safe place for now.&lt;/p&gt;

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

&lt;p&gt;Go to the GitHub repo you created earlier and go to Settings &amp;gt; in the Security section of the sidebar, select Secrets and Variables, then click Actions, Create a GitHub secret with the name &lt;code&gt;TS_OAUTH_CLIENT_ID&lt;/code&gt; and assign your OAuth client ID as the secret value and name &lt;code&gt;TS_OAUTH_SECRET&lt;/code&gt; and assign your OAuth client secret as the secret value.&lt;/p&gt;

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

&lt;p&gt;You will then need to create a server role account using ACL tags in Tailscale, basically ACL tags allow you to assign an identity to a device that is separate from human users, and use that identity as part of an ACL to restrict access. This should be used when adding servers to your Tailscale network, to learn more about ACL tags, &lt;a href="https://tailscale.com/kb/1068/acl-tags/" rel="noopener noreferrer"&gt;click here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open your favorite editor and create a .github directory and underneath .github we'll create a Workflows directory, this is the special directory that GitHub Actions is going to look for workflow files in, create a new workflow, I'm going to call it tailscale.yaml.&lt;/p&gt;

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

&lt;p&gt;And inside of this file, we're going to go ahead and set up our basic workflow structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy-via-tailscale&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tailscale&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tailscale/github-action@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;oauth-client-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TS_OAUTH_CLIENT_ID }}&lt;/span&gt;
        &lt;span class="na"&gt;oauth-secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TS_OAUTH_SECRET }}&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tag:ci&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me break it down for you. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the workflow dispatch event. Allows us to trigger workflows manually, which is great for debugging.&lt;/li&gt;
&lt;li&gt;The push event means that whenever we push a change, it goes ahead and triggers a build.&lt;/li&gt;
&lt;li&gt;Define the job and name it deploy-via-tailscale. It will run on the latest release of Ubuntu.&lt;/li&gt;
&lt;li&gt;connect to your tailnet by using the &lt;a href="https://github.com/tailscale/github-action" rel="noopener noreferrer"&gt;Tailscale GitHub Action&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go ahead and push the code to Github, you should see an ephemeral node. The node can access nodes in your Tailnet, subject to the access rules that apply to the specified ACL tag(s).&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Set Up Amazon VPC and Tailscale Router
&lt;/h2&gt;

&lt;p&gt;What we're going to do is we're going to create a VPC, and then we're going to have this public subnet, and we're going to put an EC2 instance on that public subnet, and we're going to have that EC2 instance connect out to our Tailscale network as well, and then we're going to set that EC2 instance up as a router.&lt;/p&gt;

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

&lt;p&gt;Let's go to the AWS Management Console. First, we'll create  an elastic IP and EC2 instance on the public subnet, which will act as a subnet router.&lt;/p&gt;

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

&lt;p&gt;After the instance has passed the checks we need to download and install Tailscale onto your subnet router machine.&lt;/p&gt;

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

&lt;p&gt;Step 1: Install the Tailscale client&lt;/p&gt;

&lt;p&gt;ssh into the instance and follow the instructions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -fsSL https://tailscale.com/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Step 2: Enable IP forwarding and Advertise subnet routes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoyyq612mnac8f8p6e6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoyyq612mnac8f8p6e6c.png" alt="Image10" width="800" height="129"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo tailscale up --advertise-routes==10.0.16.0/20 --accept-dns=false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the subnets in the example above with the correct ones for your network, it will give you a link that you will need to go to in order to authenticate.&lt;/p&gt;

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

&lt;p&gt;The EC2 instance should appear in the Tailscale console.&lt;/p&gt;

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

&lt;p&gt;Step 3: Enable subnet routes from the tailscale console&lt;/p&gt;

&lt;p&gt;Locate the device that advertised subnet routes, from the ellipsis menu at the bottom of the table, select Edit Route Settings. This opens the Edit Route Settings panel.&lt;/p&gt;

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

&lt;p&gt;Everything should be working to test connectivity, we will add test connectivity to the Github action, commit and push the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy-via-tailscale&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tailscale&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tailscale/github-action@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;oauth-client-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TS_OAUTH_CLIENT_ID }}&lt;/span&gt;
        &lt;span class="na"&gt;oauth-secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TS_OAUTH_SECRET }}&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tag:ci&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test-connectivity&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;ping -c 10 100.73.32.96&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the IP address with the IP address of the subnet router.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Create Private Amazon RDS Instance and Test Connectivity
&lt;/h2&gt;

&lt;p&gt;After reviewing and verifying, we will provision an Amazon RDS instance in our VPC and test connectivity from our GitHub Actions workflow.&lt;/p&gt;

&lt;p&gt;First, we will create a security group that will allow connection from the subnet router, I'm going to call it the database security group.&lt;/p&gt;

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

&lt;p&gt;In a production environment, it is bad practice to allow all connections from a security group, Only allow access from trusted sources for specific ports and protocols, following the principle of least privilege.&lt;/p&gt;

&lt;p&gt;I will not cover how to create an RDS database here. I assume you have already created an RDS database, please refer to the &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CreateDBInstance.html" rel="noopener noreferrer"&gt;AWS documentation&lt;/a&gt; if you don't know how to create one.&lt;/p&gt;

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

&lt;p&gt;If you want to test connectivity between your machine and the private Amazon RDS instance type the following command. This action allows you to connect to the MySQL DB instance using the MySQL client, Replace endpoint with the DB instance endpoint (DNS name) and replace admin with the master username you used. Enter the master password that you used when prompted for a password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql -h endpoint -P 3306 -u admin -p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;If everything is configured correctly, you should be able to see this massage.&lt;/p&gt;

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

&lt;p&gt;We will return to the Github action workflow to test connectivity, we will create three secrets for the database endpoint, password, and username.&lt;/p&gt;

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

&lt;p&gt;Update the workflow with this to test connectivity. We can now connect to RDS from any node in the Tailnet, using the same DNS name used inside AWS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy-via-tailscale&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tailscale&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tailscale/github-action@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;oauth-client-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TS_OAUTH_CLIENT_ID }}&lt;/span&gt;
        &lt;span class="na"&gt;oauth-secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TS_OAUTH_SECRET }}&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tag:ci&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test-Connectivity-to-AWS-RDS&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;mysql -h ${{ secrets.ENDPOINT }} -u ${{ secrets.USER }} -p"${{ secrets.PASSWORD }}" -e "show databases;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;p&gt;In this blog, we've demonstrated how to create a secure and seamless connection between GitHub Actions workflows and private AWS resources. This approach not only improves the overall security of your CI/CD pipeline, but also ensures that sensitive data and interactions remain within your network, TailScale is easy to use, and has robust encryption mechanisms.&lt;/p&gt;

&lt;p&gt;This is not sponsored or endorsed by TailScale, I use the TailScale at work and in my home lab, I am just a happy customer.&lt;/p&gt;

&lt;p&gt;One more thing, you can host &lt;a href="https://github.com/juanfont/headscale" rel="noopener noreferrer"&gt;Tailscale Control Server&lt;/a&gt; yourself if you want, which is a plus.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cicd</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Protect your Web Apps Against DDoS Attacks by Using AWS Shield</title>
      <dc:creator>Fady</dc:creator>
      <pubDate>Mon, 24 Apr 2023 09:52:09 +0000</pubDate>
      <link>https://dev.to/aws-builders/protect-your-web-apps-against-ddos-attacks-by-using-aws-shield-1gle</link>
      <guid>https://dev.to/aws-builders/protect-your-web-apps-against-ddos-attacks-by-using-aws-shield-1gle</guid>
      <description>&lt;p&gt;AWS offers really great tools to protect you from threats and ensure security in the cloud, one of these tools is AWS shield which is essential tools to safeguard your web apps or websites from Distributed Denial of Service (DDoS) attacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  what is DDoS attacks?
&lt;/h2&gt;

&lt;p&gt;DDoS attacks have become increasingly common in today's digital world, &lt;a href="https://blog.cloudflare.com/ddos-threat-report-2022-q4/" rel="noopener noreferrer"&gt;with the number of attacks are rising&lt;/a&gt;, DDoS stands for “Distributed Denial-of-Service” attack, DDoS attacks are a type of Cyberattacks in which the attacker (Often, it's not just one person who is responsible for this attack; sometimes, the attacker is a nation) floods a server with internet traffic by botnets (A botnet is a network of computers infected by malware that are under the control of the attacker), rendering connected online services and sites inaccessible to legitimate users. These attacks are sophisticated and designed to overwhelm the network with unwanted traffic. As a result, network performance is either degraded or critical infrastructure experiences a service outage.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS Shield
&lt;/h2&gt;

&lt;p&gt;AWS Shield is a managed DDoS protection service offered by AWS, It works in partnership with ELB, Amazon CloudFront, and Amazon Route 53 to protects you from DDoS attacks of many types of DDoS Attacks.&lt;br&gt;
AWS Shield protects against three different types&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network volumetric attacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are designed to simply overwhelm the system being attacked. &lt;br&gt;
So to direct as much raw network data at a target as possible&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network protocol attacks or TCP SYN floods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are various types of protocol attack, but one common one is to generate a huge number of connections from a spoofed IP address (computers infected by malware) and then just leave these connections open and never terminating them, the server will be impacted by the huge volume of fake connections.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application layer attacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine you have a part of your web app which allows searches, think of something like Facebook or Twitter Search which lets you search for new friends or people to follow, Attackers can use web app searches to launch DDoS attacks by sending a large number of requests to a web application that has a search feature. The attacker sends requests that are designed to consume as much server resources as possible. And it can be done hundreds, thousands, or millions of times per second. Some parts of the application are cheap to request, but expensive to deliver the result.&lt;/p&gt;

&lt;p&gt;So those are the types of things which Shield protects against.&lt;/p&gt;

&lt;p&gt;AWS Shield comes in two forms, Shield Standard and Shield Advanced. While both offer protection against DDoS attacks, there are significant differences between the two.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shield Standard
&lt;/h3&gt;

&lt;p&gt;Shield Standard is a free service that comes with all AWS accounts, you benefit from its protection automatically without you having to do anything.&lt;/p&gt;

&lt;p&gt;AWS Shield Standard doesn’t provide much in the way of proactive capability or any form of explicit configurable protection. It’s just there working away in the background&lt;/p&gt;

&lt;p&gt;Shield Standard is designed for applications that require basic protection against DDoS attacks but have a low risk tolerance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shield Advanced
&lt;/h3&gt;

&lt;p&gt;Shield Advanced, which comes with additional costs (&lt;a href="https://aws.amazon.com/shield/pricing/" rel="noopener noreferrer"&gt;it costs $3,000 US dollars per month,per organization&lt;/a&gt;) and benefits, is a commercial extra product that offers additional detection and mitigation against large and sophisticated DDoS attacks, near real-time visibility into attacks, and integration with AWS WAF, a web application firewall.&lt;br&gt;
Shield Advanced provides a 24/7 to &lt;a href="https://docs.aws.amazon.com/waf/latest/developerguide/ddos-srt-support.html" rel="noopener noreferrer"&gt;AWS Shield Response Team (SRT)&lt;/a&gt;, advanced attack mitigation techniques, and protection against attacks at the application layer. &lt;br&gt;
It also includes features such as traffic logging and metrics, which allow customers to monitor their traffic and identify potential attacks. &lt;/p&gt;

&lt;p&gt;Shield Advanced is designed for applications that require a higher level of protection against DDoS attacks and have a higher risk tolerance.&lt;/p&gt;

&lt;p&gt;If you have feedback about this blog post, submit comments in the Comments section below.&lt;/p&gt;

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