<?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: DNX Labs</title>
    <description>The latest articles on DEV Community by DNX Labs (@dnx).</description>
    <link>https://dev.to/dnx</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%2Forganization%2Fprofile_image%2F714%2Ff18802fc-8f63-48a3-a942-b27b498e12ca.png</url>
      <title>DEV Community: DNX Labs</title>
      <link>https://dev.to/dnx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dnx"/>
    <language>en</language>
    <item>
      <title>Protecting URLs with AWS ALBs and OIDC in 6 minutes</title>
      <dc:creator>Allan Denot</dc:creator>
      <pubDate>Mon, 15 Nov 2021 23:11:19 +0000</pubDate>
      <link>https://dev.to/dnx/protecting-urls-with-aws-albs-and-oidc-in-6-minutes-32jo</link>
      <guid>https://dev.to/dnx/protecting-urls-with-aws-albs-and-oidc-in-6-minutes-32jo</guid>
      <description>&lt;h2&gt;
  
  
  00:00:00
&lt;/h2&gt;

&lt;p&gt;Problem: You have a web app with an administration page that should be restricted to internal users.&lt;/p&gt;

&lt;p&gt;Here's some of the options that would solve this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Program authentication into your app, which would be different from your main user login as it's targeted to internal users and not your customers.&lt;/li&gt;
&lt;li&gt;Deploy the app privately (like an internal load balancer) and require VPN access&lt;/li&gt;
&lt;li&gt;Use some third-party service like Cloudflare Access.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We would like to propose a solution that could be implemented very quickly if you already using AWS Application Load Balancer (ALB).&lt;/p&gt;

&lt;h2&gt;
  
  
  00:01:00
&lt;/h2&gt;

&lt;p&gt;This example we will authenticate internal users in Google Workspace, but this works with any Identity Provider that supports OIDC/OAuth2.&lt;/p&gt;

&lt;p&gt;Go to your Google Cloud Console (linked to your Google Workspace account) as Admin and under "APIs &amp;amp; Services", create a new OAuth2 Client, as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F73nwi2p9scgoqoz7olwk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F73nwi2p9scgoqoz7olwk.png" alt="Google Cloud creating OAuth client"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More details here: &lt;a href="https://support.google.com/cloud/answer/6158849?hl=en" rel="noopener noreferrer"&gt;https://support.google.com/cloud/answer/6158849?hl=en&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fl9poqbhda8yg54wx4ltw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fl9poqbhda8yg54wx4ltw.png" alt="Google Cloud Setup OAuth client URLs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In "Authorized JavaScript origins", enter the main URL of your web application (without the &lt;code&gt;/admin&lt;/code&gt; path). And in "Authorized redirect URIs" enter the same as before, but adding &lt;code&gt;oauth2/idpresponse&lt;/code&gt; to the path.&lt;/p&gt;

&lt;p&gt;After creation, copy the Client ID and Client Secret generated to a secure location.&lt;/p&gt;

&lt;p&gt;Also make sure your Google project's OAuth Consent is set to Internal, if you want to authenticate only internal users. If your goal is to authenticate anyone with a Google Account, you can leave it External.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fg105v6w0g8ury4g2uk6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fg105v6w0g8ury4g2uk6p.png" alt="Google Cloud OAuth consent screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  00:03:00
&lt;/h2&gt;

&lt;p&gt;Login to your AWS Console, under EC2 select Load Balancers, choose your load balance and edit the Listener Rules, as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F10vvwpow3yjq49zr3guf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F10vvwpow3yjq49zr3guf.png" alt="AWS Console edit ALBs Listener Rules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the "+" icon to add a new rule.&lt;/p&gt;

&lt;p&gt;Click "Insert rule" above the normal URL for your web app (which could be the default action).&lt;/p&gt;

&lt;p&gt;In the left side, enter the conditions for the rule. As this example is for path-based, we will enter all paths we want to protect with an OAuth login screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fu89xkrl83y96l60n8ujn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fu89xkrl83y96l60n8ujn.png" alt="AWS ALB rule condition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter all paths ending with a &lt;code&gt;*&lt;/code&gt; (remove the trailing slash from the path).&lt;/p&gt;

&lt;p&gt;In the right side, enter Add Action &amp;gt; Authenticate, and select OIDC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fpigl7s5855qergbnayxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fpigl7s5855qergbnayxg.png" alt="AWS ALB rule action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And setup Google Workspace OIDC with the following parameters:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Issuer&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://accounts.google.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authorization endpoint&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://accounts.google.com/o/oauth2/v2/auth&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token endpoint&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://oauth2.googleapis.com/token&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User info endpoint&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://openidconnect.googleapis.com/v1/userinfo&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And under Advanced Settings, set the &lt;strong&gt;Session Timeout&lt;/strong&gt; to a small value, like &lt;code&gt;43200&lt;/code&gt; (12 hours), otherwise the authentication will last for 7 days by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fvwmuuuu25i5h7yqsqvap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fvwmuuuu25i5h7yqsqvap.png" alt="AWS ALB OIDC action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just below the OIDC action, you now have to add the Forward action to reach your web app.&lt;/p&gt;

&lt;p&gt;Copy the same action as the rule used at the moment to reach your web app. In this example, we were using a Default Action, Forwarding to a Target Group called "Laravel", so we will mimic this action into our OIDC rule, as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F24png4qjqngnhh2qsati.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F24png4qjqngnhh2qsati.png" alt="AWS ALB rule action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the Save button above to save the new rule.&lt;/p&gt;

&lt;h1&gt;
  
  
  00:05:00
&lt;/h1&gt;

&lt;p&gt;That's it, now access your web app under the URL protected and you should be redirected to a Google authentication page.&lt;/p&gt;

&lt;p&gt;After authenticated, ALB will add a cookie that lasts for 12 hours (or the Session Timeout set before).&lt;/p&gt;

&lt;p&gt;If you like this post, you will love our 100+ open source repositories with moslty Terraform modules that help you achieve stuff like this.&lt;/p&gt;

&lt;p&gt;Check out our repos at &lt;a href="https://github.com/DNXLabs" rel="noopener noreferrer"&gt;https://github.com/DNXLabs&lt;/a&gt;, specially &lt;a href="https://github.com/DNXLabs/terraform-aws-ecs-app" rel="noopener noreferrer"&gt;https://github.com/DNXLabs/terraform-aws-ecs-app&lt;/a&gt; that comes with this feature built in.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>oauth2</category>
    </item>
    <item>
      <title>Launching Amazon FSx for Windows File Server and Joining a Self-managed Domain using Terraform</title>
      <dc:creator>maiconrocha</dc:creator>
      <pubDate>Tue, 19 Oct 2021 03:02:28 +0000</pubDate>
      <link>https://dev.to/dnx/launching-amazon-fsx-for-windows-file-server-and-joining-a-self-managed-domain-using-terraform-2oid</link>
      <guid>https://dev.to/dnx/launching-amazon-fsx-for-windows-file-server-and-joining-a-self-managed-domain-using-terraform-2oid</guid>
      <description>&lt;p&gt;TL;DR:&lt;/p&gt;

&lt;p&gt;The github repo with all scripts are &lt;a href="https://github.com/DNXLabs/blog-post-terraform-fsx-self-managed-domain" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because of specific requirements, reasons, or preferences, some customers need to self-manage a Microsoft AD directory on-premises or in the cloud.&lt;/p&gt;

&lt;p&gt;AWS offers options to have their fully managed Microsoft Windows file servers (&lt;a href="https://aws.amazon.com/fsx/windows/" rel="noopener noreferrer"&gt;Amazon FSx for Windows File Server&lt;/a&gt;) join a self-managed Microsoft Active Directory.&lt;/p&gt;

&lt;p&gt;In this post, I will provide an example of launching an FSx for Windows File Server and joining a self-managed domain using Terraform.&lt;/p&gt;

&lt;p&gt;This article won’t go into details on the following items as they are presumed to already be created.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/fsx/latest/WindowsGuide/self-manage-prereqs.html" rel="noopener noreferrer"&gt;self-managed Microsoft AD directory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;the fully qualified, distinguished name (FQDN) of the organisational unit (OU) within your self-managed AD directory that the Windows File Server instance will join; and&lt;/li&gt;
&lt;li&gt;valid DNS servers and networking configuration (VPC/Subnets) that allows traffic from the file system to the domain controller.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, I recommend to go through the steps “&lt;a href="https://docs.aws.amazon.com/fsx/latest/WindowsGuide/validate-ad-config.html" rel="noopener noreferrer"&gt;Validating your Active Directory configuration&lt;/a&gt;” from AWS Documentation at the following link to validate self-managed AD configuration before starting creation of the FSx filesystem:&lt;/p&gt;

&lt;p&gt;On the file _variables.tf, we will provide the details for the self-managed AD, including IPs, DNS Name, Organisational Unit, and Domain Username and Password:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;_variables.tf&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;variable "ad_directory_name" {
 type    = string
 default = "example.com"
}

variable "ad_directory_ip1" {
 type    = string
 default = "XXX.XXX.XXX.XXX"
}

variable "ad_directory_ip2" {
 type    = string
 default = "XXX.XXX.XXX.XXX"
}

variable "fsx_name" {
 type    = string
 default = "fsxblogpost"
}

variable "domain_ou_path" {
 type    = string
 default = "OU=Domain Controllers,DC=example,DC=com"
}

variable "domain_fsx_username" {
 type    = string
 default = "fsx"
}

variable "domain_fsx_password" {
 type    = string
 default = "placeholder"
}

variable "fsx_deployment_type" {
 type    = string
 default = "SINGLE_AZ_1"
}

variable "fsx_subnet_ids" {
 type    = list(string)
 default = ["subnet-XXXXXXXXXXXX"]
}

variable "vpc_id" {
 type    = string
 default = "vpc-XXXXXXXXXXXX"
}


variable "fsx_deployment_type" {
 type    = string
 default = "SINGLE_AZ_1"
}

variable "fsx_subnet_ids" {
 type    = list(string)
 default = ["subnet-XXXXXXXXXXXX"]
}

variable "vpc_id" {
 type    = string
 default = "vpc-XXXXXXXXXXXX"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file fsx.tf is where we will effectively create FSx filesystem, and also KMS encryption key and KMS Key policy. The KMS key is optional, however I strongly recommend having the filesystem encrypted.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;fsx.tf&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data "aws_iam_policy_document" "fsx_kms" {
 statement {
   sid       = "Allow FSx to encrypt storage"
   actions   = ["kms:GenerateDataKey"]
   resources = ["*"]
   principals {
     type        = "Service"
     identifiers = ["fsx.amazonaws.com"]
   }
 }
 statement {
   sid       = "Allow account to manage key"
   actions   = ["kms:*"]
   resources = ["arn:aws:kms:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:key/*"]
   principals {
     type        = "AWS"
     identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
   }
 }
}

resource "aws_kms_key" "fsx" {
 description             = "FSx Key"
 deletion_window_in_days = 7
 policy                  = data.aws_iam_policy_document.fsx_kms.json
}

resource "aws_fsx_windows_file_system" "fsx" {
 kms_key_id          = aws_kms_key.fsx.arn
 storage_capacity    = 100
 subnet_ids          = var.fsx_subnet_ids
 throughput_capacity = 32
 security_group_ids  = [aws_security_group.fsx_sg.id]
 deployment_type     = var.fsx_deployment_type

 self_managed_active_directory {
   dns_ips                                = [var.ad_directory_ip1, var.ad_directory_ip2]
   domain_name                            = var.ad_directory_name
   username                               = var.domain_fsx_username
   password                               = var.domain_fsx_password
   organizational_unit_distinguished_name = var.domain_ou_path
 }
}

resource "aws_security_group" "fsx_sg" {
 name        = "${var.fsx_name}-fsx-sg"
 description = "SG for FSx"
 vpc_id      = data.aws_vpc.selected.id

 tags = {
   Name = "${var.fsx_name}-fsx-sg"
 }
}

resource "aws_security_group_rule" "fsx_default_egress" {
 description       = "Traffic to internet"
 type              = "egress"
 from_port         = 0
 to_port           = 0
 protocol          = "-1"
 security_group_id = aws_security_group.fsx_sg.id
 cidr_blocks       = ["0.0.0.0/0"]
}

resource "aws_security_group_rule" "fsx_access_from_vpc" {
 type              = "ingress"data "aws_iam_policy_document" "fsx_kms" {
  statement {
    sid       = "Allow FSx to encrypt storage"
    actions   = ["kms:GenerateDataKey"]
    resources = ["*"]
    principals {
      type        = "Service"
      identifiers = ["fsx.amazonaws.com"]
    }
  }
  statement {
    sid       = "Allow account to manage key"
    actions   = ["kms:*"]
    resources = ["arn:aws:kms:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:key/*"]
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
    }
  }
}

resource "aws_kms_key" "fsx" {
  description             = "FSx Key"
  deletion_window_in_days = 7
  policy                  = data.aws_iam_policy_document.fsx_kms.json
}

resource "aws_fsx_windows_file_system" "fsx" {
  kms_key_id          = aws_kms_key.fsx.arn
  storage_capacity    = 100
  subnet_ids          = var.fsx_subnet_ids
  throughput_capacity = 32
  security_group_ids  = [aws_security_group.fsx_sg.id]
  deployment_type     = var.fsx_deployment_type

  self_managed_active_directory {
    dns_ips                                = [var.ad_directory_ip1, var.ad_directory_ip2]
    domain_name                            = var.ad_directory_name
    username                               = var.domain_fsx_username
    password                               = var.domain_fsx_password
    organizational_unit_distinguished_name = var.domain_ou_path
  }
}

resource "aws_security_group" "fsx_sg" {
  name        = "${var.fsx_name}-fsx-sg"
  description = "SG for FSx"
  vpc_id      = data.aws_vpc.selected.id

  tags = {
    Name = "-${var.fsx_name}-fsx-sg"
  }
}

resource "aws_security_group_rule" "fsx_default_egress" {
  description       = "Traffic to internet"
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  security_group_id = aws_security_group.fsx_sg.id
  cidr_blocks       = ["0.0.0.0/0"]
}

resource "aws_security_group_rule" "fsx_access_from_vpc" {
  type              = "ingress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  security_group_id = aws_security_group.fsx_sg.id
  cidr_blocks       = [data.aws_vpc.selected.cidr_block]
}

 from_port         = 0
 to_port           = 0
 protocol          = "-1"
 security_group_id = aws_security_group.fsx_sg.id
 cidr_blocks       = [data.aws_vpc.selected.cidr_block]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you apply the scripts on Terraform, it should take around 15 minutes for the resources to be created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws_fsx_windows_file_system.fsx: Creation complete after 15m54s [id=fs-05701e8e6ad3fbe24]

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the FSx created and in Available state on AWS Console, which means FSx was able to join the self-managed domain:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fu3ieuj8ol693oqksceqb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fu3ieuj8ol693oqksceqb.jpeg" alt="AWS Console"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I hope the instructions and terraform scripts provided can make your life easier when launching FSx for Windows File Server and joining a self-managed domain using Terraform.&lt;/p&gt;

&lt;p&gt;When recently working on a project, I noticed there weren’t many examples online, so I decided to write this blog post to help others.&lt;/p&gt;

&lt;p&gt;I would encourage you to open an issue or feature request on the &lt;a href="https://github.com/DNXLabs/blog-post-terraform-fsx-self-managed-domain" rel="noopener noreferrer"&gt;github repo&lt;/a&gt; in case you need any additional help when using the scripts.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>fsx</category>
      <category>windows</category>
      <category>terraform</category>
    </item>
    <item>
      <title>ARM vs Intel - A real-world comparison using EC2</title>
      <dc:creator>Allan Denot</dc:creator>
      <pubDate>Wed, 02 Dec 2020 11:38:32 +0000</pubDate>
      <link>https://dev.to/dnx/arm-vs-intel-a-real-world-comparison-using-ec2-2kme</link>
      <guid>https://dev.to/dnx/arm-vs-intel-a-real-world-comparison-using-ec2-2kme</guid>
      <description>&lt;p&gt;With the recent move from Apple to ARM-based CPUs, everyone seems to be in awe of the performance of the ARM-based Apple M1s. &lt;/p&gt;

&lt;p&gt;As a cloud engineer, I couldn't avoid asking if this performance translates to cloud computing too.&lt;/p&gt;

&lt;p&gt;AWS has their line of ARM CPUs called &lt;a href="https://aws.amazon.com/ec2/graviton/" rel="noopener noreferrer"&gt;Graviton&lt;/a&gt;, available in their second generation as the &lt;code&gt;m6g&lt;/code&gt; family in EC2. Those CPUs are on average 20% cheaper for the same amount of vCPUs and RAM, but how do they compare in terms of real-world performance, against traditional Intel CPUs? That's what we are here to find out.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Intel&lt;/th&gt;
&lt;th&gt;ARM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Instance Count&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instance Type&lt;/td&gt;
&lt;td&gt;m5.large&lt;/td&gt;
&lt;td&gt;m6g.large&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU Tested&lt;/td&gt;
&lt;td&gt;Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz&lt;/td&gt;
&lt;td&gt;Custom built AWS Graviton2 Processor with 64-bit Arm Neoverse cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU Count&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clock (MHz)&lt;/td&gt;
&lt;td&gt;3397.426&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Region/AZ&lt;/td&gt;
&lt;td&gt;ap-southeast-2c&lt;/td&gt;
&lt;td&gt;ap-southeast-2c&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price (Sydney)&lt;/td&gt;
&lt;td&gt;$0.120 per Hour&lt;/td&gt;
&lt;td&gt;$0.096 per Hour&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;cat /proc/cpuinfo&lt;/code&gt; didn't show much information for the Graviton CPUs, I guess AWS wants to be secretive about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Platform
&lt;/h2&gt;

&lt;p&gt;The goal is to simulate a workload close to a real-world scenario, so we chose to use a Laravel API connecting to a MySQL database, which is a popular stack today.&lt;/p&gt;

&lt;p&gt;The infrastructure used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS ECS running in EC2&lt;/li&gt;
&lt;li&gt;2 Docker containers (ECS tasks) running the same App in one instance&lt;/li&gt;
&lt;li&gt;Containers limited to 1GB RAM (soft and hard limit), but no limit on CPU usage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Application
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/gothinkster/laravel-realworld-example-app" rel="noopener noreferrer"&gt;RealWorld Example API, Laravel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PHP 7.1&lt;/li&gt;
&lt;li&gt;Apache/2.4.38 (Debian)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Container
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intel: &lt;code&gt;FROM php:7.1-apache&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;ARM: &lt;code&gt;FROM arm64v8/php:7.1-apache&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Test Tool
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ab -n 1000 -c 20 https://${HOST}/api/articles/test-post
^      ^      ^
⎮      |      ⎩ 20 concurrency
⎮      ⎩ 1000 requests
⎩ Apache Benchmark
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Results
&lt;/h1&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Graviton2 processors (m6g.large) are on average 25% faster than Intel on an m5.large instance. &lt;/p&gt;

&lt;p&gt;Given that m6g.large is 20% cheaper, we get a total of 40% gain in price/performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data (higher is better)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmql0qitqnzlaugmcunk8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmql0qitqnzlaugmcunk8.png" alt="single container, same database"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Graviton2 is almost 29% faster when shooting requests to a single container and the database behind is exactly the same.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6dmvbbgc2xz5j4dkp011.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6dmvbbgc2xz5j4dkp011.png" alt="2 containers, same database"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When adding a second container to answer requests, interestingly Gravitons didn't see any improvement, while Intel did. The difference fell to 8% only&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjw16q9490x0zhxx9lut3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjw16q9490x0zhxx9lut3.png" alt="2 containers, no database access"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Testing with requests that do not require database access, the number of requests per second were higher for both, and Graviton kept a good margin against Intel of 26%.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fv1ikjz1nafvtjy5x6e25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fv1ikjz1nafvtjy5x6e25.png" alt="2 containers, database with the same instance type"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a bonus, we decided to match the same instance type in the database. That means that now the &lt;code&gt;m5.large&lt;/code&gt; EC2 instance is connected to a &lt;code&gt;db.m5.large&lt;/code&gt; RDS instance and the &lt;code&gt;m6g.large&lt;/code&gt; to a &lt;code&gt;db.m6g.large&lt;/code&gt; RDS instance.&lt;/p&gt;

&lt;p&gt;Results were pretty similar to before, with a 22% advantage to Gravitons, meaning that for this specific test, the database was not a bottleneck.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;A simple change in your Dockerfile could mean a 40% cost reduction in your compute costs.&lt;/p&gt;

&lt;p&gt;As M1 Macs become more popular, dev teams will be multi-platform, requiring environments (both local and cloud) to support different architectures. &lt;/p&gt;

&lt;p&gt;Docker also is working on better support for multi-platform images with &lt;a href="https://docs.docker.com/buildx/working-with-buildx/" rel="noopener noreferrer"&gt;docker buildx&lt;/a&gt;, making it more portable and easier to use the most cost-effective computing platform, independent of architecture.&lt;/p&gt;

</description>
      <category>ec2</category>
      <category>aws</category>
      <category>performance</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
