<?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: lordz-md</title>
    <description>The latest articles on DEV Community by lordz-md (@lordzmd).</description>
    <link>https://dev.to/lordzmd</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%2F761749%2F66a49ecc-6a79-407f-99c2-808174a757e8.jpeg</url>
      <title>DEV Community: lordz-md</title>
      <link>https://dev.to/lordzmd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lordzmd"/>
    <language>en</language>
    <item>
      <title>Deploying a Cloudfront Lambda Image Optimization stack with Terraform Part 1 - Cloudfront</title>
      <dc:creator>lordz-md</dc:creator>
      <pubDate>Sun, 09 Feb 2025 14:06:52 +0000</pubDate>
      <link>https://dev.to/aws-builders/deploying-a-cloudfront-lambda-image-optimization-stack-with-terraform-part-1-cloudfront-3ocf</link>
      <guid>https://dev.to/aws-builders/deploying-a-cloudfront-lambda-image-optimization-stack-with-terraform-part-1-cloudfront-3ocf</guid>
      <description>&lt;p&gt;Ever since AWS announced CloudFront supporting Origin Access Control (OAC) for Lambda function URL origins I was thinking of improving the  image optimization system used by one of my projects that was based on the infrastructure described &lt;a href="https://aws.amazon.com/blogs/networking-and-content-delivery/image-optimization-using-amazon-cloudfront-and-aws-lambda/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
The problem with this approach was that it's security was based on a secret key in a Custom origin header, which is validated in the Lambda function before processing the image. This approach was triggering the AWS Security rules to flag the Lambda Public Access rule. At the moment of publishing this post this has been already been fixed by the team maintaining the &lt;a href="https://github.com/aws-samples/image-optimization.git" rel="noopener noreferrer"&gt;aws-samples&lt;/a&gt; although the official blog post still mentions the Custom origin header.&lt;/p&gt;

&lt;p&gt;Anyway, as I was not much into CDK and JavaScript I also decided to rewrite the CDK code used to deploy the stack with Terraform and make it available to the public via Githbub &lt;a href="https://github.com/lordz-ei/terraform-cloudfront-image-optimization/" rel="noopener noreferrer"&gt;terraform-cloudfront-image-optimizatio&lt;/a&gt; repository.&lt;/p&gt;

&lt;p&gt;This is the sample architecture the image-optimization stack creates.&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%2F01r0wklikxx15m6q5hkt.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%2F01r0wklikxx15m6q5hkt.png" alt="Sample image-optimization architecture" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;
Image from AWS Networking &amp;amp; Content Delivery blog



&lt;p&gt;So let's start.&lt;/p&gt;

&lt;p&gt;We have a couple of components in this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Original images S3 bucket&lt;/li&gt;
&lt;li&gt;Transformed images S3 bucket&lt;/li&gt;
&lt;li&gt;Cloudfront&lt;/li&gt;
&lt;li&gt;Cloudfront funtion&lt;/li&gt;
&lt;li&gt;Image optimization Lambda function&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Setting up AWS Terraform provider
&lt;/h2&gt;

&lt;p&gt;Let's set up the AWS Terraform provider first. I ussualy do it by creating a file called versions.tf but I have seen also configurations using providers.tf&lt;/p&gt;

&lt;p&gt;It is done using the following block&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&amp;gt; 5.0"  #Allow only the right-most version component to increment 
    }
  }

}

provider "aws" {
  region = var.aws_region
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining necessary Terraform variables
&lt;/h2&gt;

&lt;p&gt;Let's define the required variables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "aws_region" {
  description = "The AWS region to deploy resources."
  default     = "eu-west-1"
}

variable "create_origin_bucket" {
  description = "Create an S3 bucket for original images"
  type        = bool
  default     = false #Assume there is already a bucket used to serve images
}

variable "original_image_bucket_name" {
  description = "Name of the original image bucket"
  type        = string
}

variable "transformed_image_bucket_name" {
  description = "Name of the transformed image bucket"
  type        = string
}

variable "cloudfront_log_bucket_name" {
  description = "S3 bucket for CloudFront logs"
  type        = string
}

variable "min_ttl" {
  description = "Minimum TTL for CloudFront cache"
  type        = number
  default     = 86400
}

variable "default_ttl" {
  description = "Default TTL for CloudFront cache"
  type        = number
  default     = 604800
}

variable "max_ttl" {
  description = "Maximum TTL for CloudFront cache"
  type        = number
  default     = 2592000
}

variable "max_image_size" {
  description = "Maximum image size in bytes"
  type        = number
  default     = 4700000
}

variable "image_cache_ttl" {
  description = "TTL for transformed images in seconds"
  type        = string
  default     = "max-age=31622400"
}

variable "lambda_layer_arn" {
  description = "ARN of the Lambda layer" #used for adding the Pillow library layer
  type        = string
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating Cloudfront distribution
&lt;/h2&gt;

&lt;p&gt;To create the Cloudfront distribution we use the &lt;a href="https://registry.terraform.io/modules/terraform-aws-modules/cloudfront/aws/latest" rel="noopener noreferrer"&gt;terraform-aws-modules/cloudfront/aws&lt;/a&gt; from AWS Hero Anton Babenko. &lt;/p&gt;

&lt;p&gt;For an easy distinction of the distribution let's set &lt;code&gt;comment = "Image Optimization CloudFront with Failover"&lt;/code&gt;, obviously this can be changed to the description of your wish.&lt;/p&gt;

&lt;p&gt;As we will use Cloudfront Origin Access Control (OAC) we will enable it using following configuration block&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;origin_access_control = {
    s3_oac = {
      description      = "CloudFront access to S3"
      origin_type      = "s3"
      signing_behavior = "always"
      signing_protocol = "sigv4"
    }

    lambda_oac = {
      description      = "CloudFront access to Lambda"
      origin_type      = "lambda"
      signing_behavior = "always"
      signing_protocol = "sigv4"
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the cloudfront module doesn't have the posibility to create the cache policy and response header policy we will use Terraform resources&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_cloudfront_cache_policy" "image_optimization_cache_policy" {
  name        = "image-optimization-cache-policy"
  comment     = "Cache policy for image optimization"
  default_ttl = var.default_ttl
  min_ttl     = var.min_ttl
  max_ttl     = var.max_ttl
  parameters_in_cache_key_and_forwarded_to_origin {
    cookies_config {
      cookie_behavior = "none"
    }
    headers_config {
      header_behavior = "none"
    }
    query_strings_config {
      query_string_behavior = "none"
    }
  }
}

resource "aws_cloudfront_response_headers_policy" "image_optimization_response_header_policy" {
  name    = "image-optimization-response-header-policy"
  comment = "Response header policy for image optimization"

  cors_config {
    access_control_allow_credentials = false

    access_control_allow_headers {
      items = ["*"]
    }

    access_control_allow_methods {
      items = ["GET"]
    }

    access_control_allow_origins {
      items = ["*"]
    }
    access_control_expose_headers {
      items = ["-"]
    }

    access_control_max_age_sec = 600
    origin_override            = true
  }

  custom_headers_config {
    items {
      header   = "x-aws-image-optimization"
      override = true
      value    = "v1.0"
    }

    items {
      header   = "vary"
      override = true
      value    = "accept"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's return to the cloudfront module and add the origins and the origin group&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;origin = {
    s3 = {
      domain_name           = module.transformed_s3_bucket.s3_bucket_bucket_regional_domain_name
      origin_access_control = "s3_oac"
      origin_shield = {
        enabled              = true
        origin_shield_region = var.aws_region
      }
    }

    lambda = {
      domain_name           = "${module.image_optimization_lambda.lambda_function_url_id}.lambda-url.${data.aws_region.current.name}.on.aws"
      origin_access_control = "lambda_oac"
      custom_origin_config = {
        http_port              = 80
        https_port             = 443
        origin_protocol_policy = "https-only"
        origin_ssl_protocols   = ["TLSv1.2"]
      }
      origin_shield = {
        enabled              = true
        origin_shield_region = var.aws_region
      }
    }
  }

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

&lt;/div&gt;



&lt;p&gt;To make this work we will also need the default cache behavior and the Cloudfront function association&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;default_cache_behavior = {
    target_origin_id       = "lambda_failover"
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]

    use_forwarded_values       = false
    cache_policy_id            = aws_cloudfront_cache_policy.image_optimization_cache_policy.id
    response_headers_policy_id = aws_cloudfront_response_headers_policy.image_optimization_response_header_policy.id

    function_association = {
      # Valid keys: viewer-request, viewer-response
      viewer-request = {
        function_arn = aws_cloudfront_function.cloudfront_url_rewrite.arn
      }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last pieces of Cloudfront configurations are logging and viewer certificate which we will use the default and also we don't need any geo restrictions and will setup a dependency on the lambda function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;logging_config = {
      include_cookies = false
      bucket          = module.cloudfront_logs.s3_bucket_bucket_domain_name
      prefix          = "cloudfront-logs/"
    }


    geo_restriction = {
      restriction_type = "none"
    }


    viewer_certificate = {
      cloudfront_default_certificate = true
    }
  }

  depends_on = [module.image_optimization_lambda]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next part we will deploy the Cloudfront function and Lambda&lt;/p&gt;

</description>
      <category>cloudfront</category>
      <category>security</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Operation Fire Valley</title>
      <dc:creator>lordz-md</dc:creator>
      <pubDate>Fri, 15 Dec 2023 21:44:45 +0000</pubDate>
      <link>https://dev.to/aws-builders/operation-fire-valley-3b7h</link>
      <guid>https://dev.to/aws-builders/operation-fire-valley-3b7h</guid>
      <description>&lt;p&gt;&lt;strong&gt;Ho ho ho!!!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's that time of the year again!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Welcome to Operation “FireValleyRocks”!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Many thanks to Jason Dunn, Lily Kerns, and the other wonderful AWS Community managers.&lt;br&gt;
It's been a wonderful year and you guys made it even greater. Have wonderful holidays and thanks for everything you are doing for us the community!!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qTPaFFpx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/utoc8a5kfm13dxkbo41p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qTPaFFpx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/utoc8a5kfm13dxkbo41p.png" alt="step function tree" width="800" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>communitybuilders</category>
      <category>stepfunctions</category>
      <category>thankfulforest2024</category>
      <category>firevalleyrocks</category>
    </item>
    <item>
      <title>Operation Ho Ho Ho, or how AWS Community Builders saved the holidays!</title>
      <dc:creator>lordz-md</dc:creator>
      <pubDate>Tue, 20 Dec 2022 06:00:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/operation-ho-ho-ho-or-how-aws-community-builders-saved-christmas-52e5</link>
      <guid>https://dev.to/aws-builders/operation-ho-ho-ho-or-how-aws-community-builders-saved-christmas-52e5</guid>
      <description>&lt;h2&gt;
  
  
  What surprises you most about the community builders program?
&lt;/h2&gt;

&lt;p&gt;I love learning new things, but mostly I like socializing with builders around the world and I am very surprised on how builders help each other, doesn't matter if it's a problem with an AWS service or a Vegas hotel not accepting your card when you arrived for re:Invent.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s your background and your experience with AWS?
&lt;/h2&gt;

&lt;p&gt;I come from a sysadmin/networking background which I did for about 10 years before finding out about AWS. I enjoy AWS because it gives me the freedom to build things and tear them down fast. I also enjoy sharing knowledge about AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the biggest benefit you see from the program?
&lt;/h2&gt;

&lt;p&gt;This year was my second in person re:Invent, and thanks to the builders I didn't feel lonely in Vegas. I think networking and knowledge sharing is the best benefit of the AWS Community Builders.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the next swag item that you would like to get?
&lt;/h2&gt;

&lt;p&gt;My apartment is full of swag items, so I donated a lot of swag I received this year, except the hoodie and the oversized coffee mug ( which is good also for self-defense and I don't have to justify why I carry a coffee mug in my car :D :D :D ). I even gave my claw won Kindle to a builder that needed it more than me. I would love access to books, maybe an Audible yearly subscription and access to Cloud Academy that can be donated to someone who needs it more.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are you eating for dinner today? Share the recipe!
&lt;/h2&gt;

&lt;p&gt;Borscht (Beet Soup )&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---qwhziAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oshyze0x9fzg744b9ws3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---qwhziAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oshyze0x9fzg744b9ws3.jpg" alt="Image description" width="880" height="479"&gt;&lt;/a&gt;&lt;br&gt;
(Not actual image of my borscht)&lt;/p&gt;

&lt;p&gt;According to Wikipedia, Borscht is neither Ukrainian or Russian. It is national Slavic dish that has a history of centuries. Borsch is traditional beet soup cooked in every household of any former republic that belonged to USSR – Ukraine, Russia, Moldova, Belorussia etc. Not to mention all over Eastern Europe&lt;/p&gt;

&lt;p&gt;The iconic red beet soup is made with beef ribs, cabbage, potatoes, carrots, garlic and dill, and then served with a dollop of sour cream and rye bread, but I replaced the beef ribs with pork ones. So let's go.&lt;/p&gt;

&lt;p&gt;You will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Red beets&lt;/li&gt;
&lt;li&gt;Cabbage&lt;/li&gt;
&lt;li&gt;Potatoes&lt;/li&gt;
&lt;li&gt;Carrots&lt;/li&gt;
&lt;li&gt;Onion&lt;/li&gt;
&lt;li&gt;Garlic&lt;/li&gt;
&lt;li&gt;Dill&lt;/li&gt;
&lt;li&gt;Beef or Pork ribs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Step 1. Put the ribs in boiling water and let them boil for 30-40 minutes.&lt;br&gt;
Step 2. Add cabbage in broth with bay leaves and peppercorns for 20 minutes after bringing to a boil.&lt;br&gt;
Meanwhile you can chop the rest of the vegetables.&lt;br&gt;
Step 3. Sauté the onion and carrots in a bit of olive oil until translucent, about 5 minutes. This makes onion flavorful making entire borscht recipe more delicious. &lt;strong&gt;Do not skip.&lt;/strong&gt;&lt;br&gt;
Step 4. Add beets and a bit more oil, cook for another 5 minutes.&lt;br&gt;
Step 5. Put the sautéed veggies to the pot along with potatoes, tomato paste and salt. Cook covered for 20 minutes. In the meantime, prep garlic, dill and other seasonings.&lt;/p&gt;

&lt;p&gt;Season borscht with white vinegar, garlic, sugar and pepper. Red wine vinegar, apple cider vinegar, white wine vinegar or lemon juice can also be used. Traditional choice is borsch for sour soup - a liquid created with fermented wheat or barley brans, giving the dish a distinctively sour and slightly pungent taste ( can be bought in US and Western Europe at traditional eastern european shops ) but if not the best choice is white vinegar though.&lt;/p&gt;

&lt;p&gt;Stir, turn off heat and let borscht soup stand for 10 minutes covered to allow flavors to “marry” each other. Add dill and your borscht is ready to serve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is there anything else you would like to say about the community builders program in 2022?
&lt;/h2&gt;

&lt;p&gt;This year was amazing, the CB mixer at re:Invent, the people I met gave me a lot of inspiration for 2023. So I will be launching a local AWS UG in Moldova and will work more on trainings and labs with local students who want to learn more about cloud and AWS.&lt;br&gt;
Thanks to all the AWS CB managers, developer advocates and to all the CB around the world for a wonderful experience. Wish you Happy Holidays! Let's us all have a wonderful 2023!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>communitybuilder</category>
      <category>cbchristmas2022</category>
    </item>
    <item>
      <title>What I learned from “failing” to teach my first AWS course</title>
      <dc:creator>lordz-md</dc:creator>
      <pubDate>Fri, 11 Nov 2022 09:56:08 +0000</pubDate>
      <link>https://dev.to/aws-builders/what-i-learned-from-failing-to-teach-my-first-aws-course-1085</link>
      <guid>https://dev.to/aws-builders/what-i-learned-from-failing-to-teach-my-first-aws-course-1085</guid>
      <description>&lt;p&gt;I have been working with AWS for more than 5 years already and this spring I was selected by AWS to become an AWS Community Builder in Republic of Moldova. I have teamed up with Tekwill Academy who already has a lot of amazing IT courses and organize a lot of events for the local community, to give an AWS course to a local bank and in the future have courses to students and people that wish to transition into cloud and DevOps. I have started to teach my AWS course at the end of August 2022 and finished it a couple of days ago mid-November (initially it was planned to finish it end of October, but I needed to postpone some lessons because of personal issues).&lt;/p&gt;

&lt;p&gt;This are the lessons I learned from this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Being an AWS Certified Cloud Engineer and having lots of years of experience, doesn’t make you a great teacher — no matter how many projects you have done in the past, it doesn’t mean you can teach, it gives you the weight of having experience but every small mistake in the way of your students gives them the benefit of doubt of your qualifications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Great trainers prepare the courses well in advance — never leave preparing the slides for the last moment, this course came unexpected, so I had literally been preparing slides and material in the day of the lesson or the day before. This combined with working on real projects made me do them as fast as possible, so I am sure I have omitted important thing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nether underestimate your audience — on-line training and off-line differ a lot, if you are off-line, you can expect questions of situations that you have never encountered, and you are expected to answer immediately, thus on-line you have some time to prepare and give an answer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On-line video courses are totally different from a course with a trainer — this actually relates to the point above, I have taken many on-line courses for my work and sometimes I wish I could have asked the trainer a question that related to a real issue I had at the moment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Community matters — AWS Community Builders and folks at AWS helped me a lot in getting answers on issues I have never faced but students asked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improvement nether stops — after the lessons learned from this attempt I will improve, I have already ideas on making the slides more fun, the labs and the hands-on task much interactive.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You may have noticed that the title had failing in quotes, though I feel I have could done better, I consider this a learning experience and actually I have learned a lot from preparing this course so it’s not a failure at all. I know what can be done better and in 3 months I will have a better course and will be prepared to share the knowledge with other.&lt;/p&gt;

</description>
      <category>awscommunity</category>
      <category>teaching</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
