<?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"><channel><title><![CDATA[Personal Blog of Mahesh Chandra Regmi ]]></title><description><![CDATA[Personal blog of Mahesh Chandra Regmi includes all the article written by him on python, nodejs, rust, git, and many other  tools and techniques which need to be followed by a genuine programmer.]]></description><link>https://maheshchandraregmi.com.np</link><generator>RSS for Node</generator><lastBuildDate>Sun, 17 May 2026 14:45:14 GMT</lastBuildDate><atom:link href="https://maheshchandraregmi.com.np/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Is your code really good?]]></title><description><![CDATA[When working on a project, I find myself repeatedly asking the question: "Is this the best way to do this?" This is the constant refrain that runs through my mind as I navigate the process of creating abstractions, API contracts, generics, mixins, ad...]]></description><link>https://maheshchandraregmi.com.np/is-your-code-really-good</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/is-your-code-really-good</guid><category><![CDATA[Software Engineering]]></category><category><![CDATA[architecture]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[Terraform]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Mon, 29 Jul 2024 18:56:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722279347724/3caf0ca7-da14-4915-bd38-9b89324cfaca.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When working on a project, I find myself repeatedly asking the question: "Is this the best way to do this?" This is the constant refrain that runs through my mind as I navigate the process of creating abstractions, API contracts, generics, mixins, adapters, and other architectural elements.</p>
<p>Just yesterday, I was working on some Terraform infrastructure code and doing a code review with a senior member of the team. During the review, they posed a simple question that gave me pause:</p>
<blockquote>
<p>"Do you understand the difference between 'looks good' and 'is good'?"</p>
</blockquote>
<p>At first, I thought this was their way of telling me that my code wasn't good enough. However, after reflecting on it for a while, I began to discern a deeper meaning in their question.</p>
<h2 id="heading-looks-good">Looks good.</h2>
<p><img src="https://static01.nyt.com/images/2021/04/30/multimedia/30xp-meme/29xp-meme-superJumbo-v3.jpg" alt /></p>
<p>Making a code look good is easy.</p>
<pre><code class="lang-go">module <span class="hljs-string">"label"</span> {
  source = <span class="hljs-string">"./modules/label"</span>

  tags       = <span class="hljs-keyword">var</span>.tags
  namespace  = <span class="hljs-keyword">var</span>.namespace
  name       = <span class="hljs-keyword">var</span>.name
  stage      = <span class="hljs-keyword">var</span>.stage
  delimiter  = <span class="hljs-keyword">var</span>.delimiter
  attributes = compact(concat(<span class="hljs-keyword">var</span>.attributes, [<span class="hljs-string">"cluster"</span>]))
}

module <span class="hljs-string">"vpc"</span> {
  source = <span class="hljs-string">"./modules/vpc/"</span>

  tags       = local.tags
  namespace  = module.label.namespace
  name       = module.label.name
  stage      = module.label.stage
  cidr_block = <span class="hljs-keyword">var</span>.cidr_block
}
</code></pre>
<p>This code may appear neat and visually appealing. Someone who stumbles upon this Terraform code might say it is beautifully written and likely copied from a template provided by a popular Terraform module provider, such as CloudPosse.</p>
<p>However, this does not necessarily mean the code is "good." At least, not on the inside. One could argue that the only thing that truly matters is the exported interface of the module, and the underlying complexity of the implementation may be irrelevant.</p>
<p>While the code may look clean and organized on the surface, the actual quality and maintainability of the codebase depend on factors beyond just its aesthetics. The complexity of the logic, the efficiency of the implementations, the robustness of the error handling, and the overall alignment with the project's requirements are all important considerations that cannot be fully assessed based on the appearances alone.</p>
<p>In software development, it is important to strike a balance between the visual appeal and the underlying quality of the codebase. Code that looks "beautiful" on the outside but is convoluted or difficult to understand on the inside may still pose challenges for long-term maintenance and future enhancements. The true measure of "good" code should encompass both its external presentation and its internal structure and implementation.</p>
<pre><code class="lang-go">locals {

  defaults = {
    label_order = [<span class="hljs-string">"namespace"</span>, <span class="hljs-string">"stage"</span>, <span class="hljs-string">"environment"</span>, <span class="hljs-string">"name"</span>, <span class="hljs-string">"attributes"</span>]
    delimiter   = <span class="hljs-string">"-"</span>
    replacement = <span class="hljs-string">""</span>
    # The <span class="hljs-string">`sentinel`</span> should match the <span class="hljs-string">`regex_replace_chars`</span>, so it will be replaced with the <span class="hljs-string">`replacement`</span> value
    sentinel   = <span class="hljs-string">"~"</span>
    attributes = [<span class="hljs-string">""</span>]
  }

  # The values provided by variables superceed the values inherited from the context

  enabled             = <span class="hljs-keyword">var</span>.enabled
  regex_replace_chars = coalesce(<span class="hljs-keyword">var</span>.regex_replace_chars, <span class="hljs-keyword">var</span>.context.regex_replace_chars)

  name               = lower(replace(coalesce(<span class="hljs-keyword">var</span>.name, <span class="hljs-keyword">var</span>.context.name, local.defaults.sentinel), local.regex_replace_chars, local.defaults.replacement))
  namespace          = lower(replace(coalesce(<span class="hljs-keyword">var</span>.namespace, <span class="hljs-keyword">var</span>.context.namespace, local.defaults.sentinel), local.regex_replace_chars, local.defaults.replacement))
  environment        = lower(replace(coalesce(<span class="hljs-keyword">var</span>.environment, <span class="hljs-keyword">var</span>.context.environment, local.defaults.sentinel), local.regex_replace_chars, local.defaults.replacement))
  stage              = lower(replace(coalesce(<span class="hljs-keyword">var</span>.stage, <span class="hljs-keyword">var</span>.context.stage, local.defaults.sentinel), local.regex_replace_chars, local.defaults.replacement))
  delimiter          = coalesce(<span class="hljs-keyword">var</span>.delimiter, <span class="hljs-keyword">var</span>.context.delimiter, local.defaults.delimiter)
  label_order        = length(<span class="hljs-keyword">var</span>.label_order) &gt; <span class="hljs-number">0</span> ? <span class="hljs-keyword">var</span>.label_order : (length(<span class="hljs-keyword">var</span>.context.label_order) &gt; <span class="hljs-number">0</span> ? <span class="hljs-keyword">var</span>.context.label_order : local.defaults.label_order)
  additional_tag_map = merge(<span class="hljs-keyword">var</span>.context.additional_tag_map, <span class="hljs-keyword">var</span>.additional_tag_map)

  # Merge attributes
  attributes = compact(distinct(concat(<span class="hljs-keyword">var</span>.attributes, <span class="hljs-keyword">var</span>.context.attributes, local.defaults.attributes)))

 # code removed <span class="hljs-keyword">for</span> clarity
}
</code></pre>
<p>This is what the label module code looks like on the inside. It's a real mess of Terraform code that would be very challenging to maintain. Although I understand the purpose of each function and local variable here, trying to make edits after being away from this codebase for a month would likely require several minutes to reorient myself and figure out the implementation.</p>
<p>But can this code truly be made "good"?</p>
<p>To improve this, we must first focus on simplifying it. Before proceeding, I'd like to reference the "Zen of Python" principle:</p>
<blockquote>
<p>Simple is better than complex.<br />Complex is better than complicated.</p>
</blockquote>
<p>The key distinction here is that complexity, while not ideal, can be justified if it is necessary to accomplish a task. Complication, on the other hand, simply means the code is disorderly and difficult to understand without necessity.</p>
<p>In the case of this label module, the current implementation appears to be overly complicated, rather than appropriately complex. To make this code "good," the focus should be on reducing the complication and unnecessary complexity, breaking down the logic into more modular and understandable components.</p>
<h2 id="heading-complex-vs-complicated">Complex vs Complicated</h2>
<p>Complexity means that something is hard to understand for a reason, because it requires you to study the complexity, and there is no pragmatic way to avoid it. Compilers might be complex for a programmer because they accomplish a complex job. The nature of compilers is inherently hard to understand, so it cannot be reduced to simpler elements.</p>
<p>Complication means something is difficult to understand and disorderly. In other words, it's a mess. Although this is subjective, one could argue that Helm templates are complicated. However, complicated things can be simplified into simpler and more maintainable components using tools like Kustomize or domain-specific languages (DSLs) like Jsonnet.</p>
<p>The key difference is that complexity arises from the inherent nature of a system, while complication is more about the disorder and difficulty in understanding something. Complexity cannot be easily reduced, while complicated things can often be simplified through the use of appropriate tools and techniques.</p>
<h1 id="heading-is-good">Is Good</h1>
<p>For something to become good, it must possess a good internal mechanisms and external interface. The code must be maintainable.</p>
<p>In the above example: The sheer number of variables and the nested conditional logic can make the code complex and potentially difficult to maintain or extend in the future, especially for larger or more complex software projects.</p>
<p>In summary, while the code "looks good" in terms of its structure, readability, and adherence to coding best practices, the statement "is good" requires a more in-depth evaluation of the code's actual functionality, performance, and overall quality, which cannot be determined solely from the provided code snippet. A comprehensive assessment of the code's suitability, robustness, and alignment with the software's requirements would be necessary to determine whether the code "is good" or not.</p>
]]></content:encoded></item><item><title><![CDATA[From Dumb and Boring YAML to Dumb and Boring YAML; IaC Experience]]></title><description><![CDATA[For more than 3 years I've been doing DevOps and involved myself in multiple projects ranging from simple static web applications deployed to some CDNs to multi-tenant systems with event-driven architectures. I've always found some ways to make my bo...]]></description><link>https://maheshchandraregmi.com.np/from-dumb-and-boring-yaml-to-dumb-and-boring-yaml-iac-experience</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/from-dumb-and-boring-yaml-to-dumb-and-boring-yaml-iac-experience</guid><category><![CDATA[cloudformation]]></category><category><![CDATA[Devops]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Wed, 10 Jul 2024 16:12:00 GMT</pubDate><content:encoded><![CDATA[<p>For more than 3 years I've been doing DevOps and involved myself in multiple projects ranging from simple static web applications deployed to some CDNs to multi-tenant systems with event-driven architectures. I've always found some ways to make my boring job fun. Sometimes, I experiment with new DevOps tools other times I try to write automation over some repetitive tasks. One of the major thing that is in every DevOps toolbox in IaC (Infrastructure as a Code) tool.</p>
<p>The experience I've shared in this article is personal and might not be the same for you. Hey, remember as long as it works for you, don't complain.</p>
<h2 id="heading-infrastructure-as-a-code">Infrastructure-as-a-Code</h2>
<p>Remember the last time you tried to spin up a virtual machine in some cloud? Think, there are multiple virtual machines involved each having different configurations. How do you make this process repeatable, observable, managed, and testable? This is where IaC tools come in. IaC tools let you to define your infrastructure in code declaratively and have some sort of tooling to apply, preview, and destroy the changes in your cloud. There are multiple tools and technologies involved to define and manage your IaC code. Terraform is a popular example.</p>
<blockquote>
<p>Infrastructure as code (IaC) is the ability to provision and support your computing infrastructure using code instead of manual processes and settings. Any application environment requires many infrastructure components like operating systems, database connections, and storage. Developers have to regularly set up, update, and maintain the infrastructure to develop, test, and deploy applications.</p>
<p>- Amazon Web Services (AWS)</p>
</blockquote>
<h2 id="heading-square-1-aws-cloudformation">Square 1: AWS Cloudformation</h2>
<p>In the beginning, I started with AWS Cloudformation. So, AWS Cloudformation is the IaC tool that lets you define your infrastructure in YAML / JSON code and deploy it in AWS.</p>
<blockquote>
<p>AWS CloudFormation is a service that helps you model and set up your AWS resources so that you can spend less time managing those resources and more time focusing on your applications that run in AWS. You create a template that describes all the AWS resources that you want (like Amazon EC2 instances or Amazon RDS DB instances), and CloudFormation takes care of provisioning and configuring those resources for you. You don't need to individually create and configure AWS resources and figure out what's dependent on what; CloudFormation handles that. The following scenarios demonstrate how CloudFormation can help.</p>
<p>- Amazon Web Services (AWS)</p>
</blockquote>
<p>Cloudformation template looks like this when written in YAML.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">AWSTemplateFormatVersion:</span> <span class="hljs-string">'2010-09-09'</span>
<span class="hljs-attr">Description:</span> <span class="hljs-string">Create</span> <span class="hljs-string">an</span> <span class="hljs-string">S3</span> <span class="hljs-string">Bucket</span>

<span class="hljs-attr">Resources:</span>
  <span class="hljs-attr">S3Bucket:</span>
    <span class="hljs-attr">Type:</span> <span class="hljs-string">AWS::S3::Bucket</span>
    <span class="hljs-attr">Properties:</span>
      <span class="hljs-attr">BucketName:</span> <span class="hljs-string">my-example-s3-bucket</span>
      <span class="hljs-attr">PublicAccessBlockConfiguration:</span>
        <span class="hljs-attr">BlockPublicAcls:</span> <span class="hljs-literal">true</span>
        <span class="hljs-attr">BlockPublicPolicy:</span> <span class="hljs-literal">true</span>
        <span class="hljs-attr">IgnorePublicAcls:</span> <span class="hljs-literal">true</span>
        <span class="hljs-attr">RestrictPublicBuckets:</span> <span class="hljs-literal">true</span>

<span class="hljs-attr">Outputs:</span>
  <span class="hljs-attr">BucketName:</span>
    <span class="hljs-attr">Description:</span> <span class="hljs-string">Name</span> <span class="hljs-string">of</span> <span class="hljs-string">the</span> <span class="hljs-string">S3</span> <span class="hljs-string">bucket</span>
    <span class="hljs-attr">Value:</span> <span class="hljs-type">!Ref</span> <span class="hljs-string">S3Bucket</span>
</code></pre>
<p>The first project I worked on was a legacy AWS Cloudformation project. It was a relatively simple 3-tier application with some ETL processing involved. The codebase was a single 3000+ LOC YAML document. Changing it felt tough and cumbersome. I think these are the major reasons why I felt it was so lacking.</p>
<p>I didn't use <code>cfn-lint</code> at that time and making sure the YAML change is valid required deploying it. There were a lot of repetitive patterns in the code which I thought should be composable. The configuration was too static and it felt too boring. Although some variables and stuff were involved I didn't like the static nature of the YAML file. Like not being able to calculate CIDR ranges, string manipulations etc.</p>
<h2 id="heading-square-2-terraform">Square 2: Terraform</h2>
<p>Then, I heard of HashiCorp Terraform. Terraform is written in a language called HCL (Hashicorp Configuration Language). HCL is a DSL created by Hashicorp, the creator company of Terraform. Terraform felt great. It felt like I was programming the infrastructure at the time. And hearing all the great benefits like I can deploy AWS, Azure or any other resources with the same codebase felt like a clear winner to me.</p>
<p>This is how the above code looks like in terraform.</p>
<pre><code class="lang-bash">provider <span class="hljs-string">"aws"</span> {
  region = <span class="hljs-string">"us-west-2"</span>
}

resource <span class="hljs-string">"aws_s3_bucket"</span> <span class="hljs-string">"example"</span> {
  bucket = <span class="hljs-string">"my-example-s3-bucket"</span>
  acl    = <span class="hljs-string">"private"</span>

  block_public_acls       = <span class="hljs-literal">true</span>
  block_public_policy     = <span class="hljs-literal">true</span>
  ignore_public_acls      = <span class="hljs-literal">true</span>
  restrict_public_buckets = <span class="hljs-literal">true</span>
}

output <span class="hljs-string">"bucket_name"</span> {
  description = <span class="hljs-string">"Name of the S3 bucket"</span>
  value       = aws_s3_bucket.example.id
}
</code></pre>
<p>The language is great. You can manipulate strings using a wide variety of functions, there are multiple providers and the plugin system is really extensible. You can write a clean and neat IaC with it. This really overcome the challenges I felt previously.</p>
<p>The tooling is extremely good. For example: there are LSPs which can help you in writing the code. There are many sane functions provided by the terraform itself. It feels like programming to some sense. The modules system is a great abstraction mechanism. I can create a module called static-website and provision all CDNs, Storage Buckets there and reuse that module in multiple places. The configuration is dynamic now to some extent.</p>
<p>Terraform started providing me the correct amount of abstraction, <strong>until it didn't</strong>. I started abusing the programmability nature of the terraform to start making everything dynamic. I wanted to write the master terraform code which I can plug into any project and just change some variables and have it work.</p>
<p>This is a code snippet of the <code>label</code> module from my template repository for terraform codebases.</p>
<pre><code class="lang-bash"> name               = lower(replace(coalesce(var.name, var.context.name, local.defaults.sentinel), local.regex_replace_chars, local.defaults.replacement))
  namespace          = lower(replace(coalesce(var.namespace, var.context.namespace, local.defaults.sentinel), local.regex_replace_chars, local.defaults.replacement))
  environment        = lower(replace(coalesce(var.environment, var.context.environment, local.defaults.sentinel), local.regex_replace_chars, local.defaults.replacement))
  stage              = lower(replace(coalesce(var.stage, var.context.stage, local.defaults.sentinel), local.regex_replace_chars, local.defaults.replacement))
  delimiter          = coalesce(var.delimiter, var.context.delimiter, local.defaults.delimiter)
  label_order        = length(var.label_order) &gt; 0 ? var.label_order : (length(var.context.label_order) &gt; 0 ? var.context.label_order : local.defaults.label_order)
  additional_tag_map = merge(var.context.additional_tag_map, var.additional_tag_map)
</code></pre>
<p>Github: <a target="_blank" href="https://github.com/regmicmahesh/infrastructure-backend/tree/main">regmicmahesh/infrastructure-backend (</a><a target="_blank" href="http://github.com">github.com</a><a target="_blank" href="https://github.com/regmicmahesh/infrastructure-backend/tree/main">)</a></p>
<p>Slowly, terraform started feeling limited. Although the new DSL provided some level of dynamic nature in the codebase, it's DSL in the end. It's not a programming language. There are limitations to it. I don't think the problems I faced on Cloudformation were solved by Terraform.</p>
<p>You can create multiple resources by using <code>count</code> terraform but it introduces its own sort of issues. So, the usage of <code>count</code> introduces a list data structure in the scene which manages the count of the resources. Like if you remove an item of some index in the list, all of the elements of the list following the item will be redeployed. There is a drift between terraform modules and official AWS APIs, some stuffs are implemented in the aws-provider in their own way. There is not any good proper concept of conditional resources in terraform, like how <code>Conditions:</code> block work in Cloudformation.</p>
<h2 id="heading-square-3-pulumi">Square 3: Pulumi</h2>
<p>Then, I heard of this new IaC tool called Pulumi and decided to invest some time on it. Pulumi felt great. You can write your IaC in any of the supported programming languages and have it deployed in the cloud. I enjoyed writing Pulumi code in Go. Pulumi is also the language in which it itself is written, so the support was great!</p>
<p>I wrote custom stacks, experimented with different architecture patterns, and wrote custom components and stuff.</p>
<p>There's this automation API of Pulumi which lets you not even use the Pulumi tooling and just have your infrastructure code as a single binary. Doesn't it sound cool to have a binary that you can store in some artifact store and deploy it and your infrastructure will be in the desired state?</p>
<p>This is how the above code looks like in Pulumi.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/s3"</span>
    <span class="hljs-string">"github.com/pulumi/pulumi/sdk/v3/go/pulumi"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    pulumi.Run(<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(ctx *pulumi.Context)</span> <span class="hljs-title">error</span></span> {
        bucket, err := s3.NewBucket(ctx, <span class="hljs-string">"example-bucket"</span>, &amp;s3.BucketArgs{
            BucketName: pulumi.String(<span class="hljs-string">"my-example-s3-bucket"</span>),
            AcceleratedConfigurati on: &amp;s3.BucketAcceleratedConfigurationArgs{
                Enabled: pulumi.Bool(<span class="hljs-literal">false</span>),
            },
            AclInput: pulumi.String(<span class="hljs-string">"private"</span>),
            PublicAccessBlockConfiguration: &amp;s3.BucketPublicAccessBlockConfigurationArgs{
                BlockPublicAcls:       pulumi.Bool(<span class="hljs-literal">true</span>),
                BlockPublicPolicy:     pulumi.Bool(<span class="hljs-literal">true</span>),
                IgnorePublicAcls:      pulumi.Bool(<span class="hljs-literal">true</span>),
                RestrictPublicBuckets: pulumi.Bool(<span class="hljs-literal">true</span>),
            },
        })
        <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
            <span class="hljs-keyword">return</span> err
        }

        ctx.Export(<span class="hljs-string">"bucketName"</span>, bucket.ID())
        <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span>
    })
}
</code></pre>
<p>You can find a blog about my Pulumi architecture here as well.</p>
<p><a target="_blank" href="https://maheshchandraregmi.com.np/structuring-infrastructure-as-code-with-a-layered-approach">Structuring Infrastructure as Code with a Layered Approach (maheshchandraregmi.com.np)</a></p>
<p>I thought developers would also be involved in managing the IaC if it's in the programming language that they use. But, it didn't quite work like that. They had no interest in writing infrastructure code and even if they did, it was just too risky for them to deploy.</p>
<p>Then, I didn't touch the pulumi code for a month. I opened the pulumi codebase next month and it all started breaking apart. The dependencies were outdated, there were vulnerabilities introduced in the packages that I used.</p>
<p>The code felt too magic to me and required few hours to quickly wrap my head around how I had done things. The dynamic nature of the code quickly became the downside because there were just too many moving pieces and changing something had unintended consequences.</p>
<h2 id="heading-back-to-square-1-aws-cloudformation">Back to Square 1: AWS Cloudformation</h2>
<p>And, now I'm back in AWS CloudFormation. I think the configuration and DevOps processes should be as dumb as possible. It should be clear to the eyes on one look and involve no magic. It should be lean and every extra line of code or tool involved is a tech debt.</p>
<p>I started using nested stacks and custom resources of CloudFormation as well. I don't need to use loops because I don't need to make the infrastructure dynamic. Do I need to add a new subnet in future? Ok, I will modify the code to have a new subnet. For me or any other DevOps who will join in the future it is easier to see than to wrap a head around the looping logic.</p>
<p>We can also leverage features like Stacksets, Drift Detection, Automated Rollbacks with cloudformation. The code can also be viewed as a diagram in the application manager and can be entirely managed through AWS.</p>
<p>I use these templates in the projects nowadays.</p>
<p><a target="_blank" href="https://github.com/regmicmahesh/cloudformation-stack-templates">regmicmahesh/cloudformation-stack-templates (github.com)</a></p>
<p>Thank you for reading!</p>
]]></content:encoded></item><item><title><![CDATA[Structuring Infrastructure as Code with a Layered Approach]]></title><description><![CDATA[One of the problems that I face frequently when writing Infrastructure as a Code is how you structure it. To answer this question, I think there are a few indicators that decide how we want to structure.

One resource will have less change compared t...]]></description><link>https://maheshchandraregmi.com.np/structuring-infrastructure-as-code-with-a-layered-approach</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/structuring-infrastructure-as-code-with-a-layered-approach</guid><category><![CDATA[Pulumi]]></category><category><![CDATA[golang]]></category><category><![CDATA[Infrastructure as code]]></category><category><![CDATA[Terraform]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[cloud architecture]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Tue, 30 Jan 2024 06:55:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706597644521/cf2e263d-1de3-4b39-a34b-cadfbe9e67b4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the problems that I face frequently when writing Infrastructure as a Code is <strong>how you structure it.</strong> To answer this question, I think there are a few indicators that decide how we want to structure.</p>
<ol>
<li><p>One resource will have less change compared to another resource. For example: your VPC resource may not change for the lifespan of the project but the application resource may change every day. How can I structure it in a way that I can make sure the changes in application don't have any relationship with the change in VPC?</p>
</li>
<li><p>Changes in some resources are significant. Such as IAM Roles, Accounts, Billing, etc. They may bring down the whole system. How to make sure it's properly encapsulated? So that the code responsible for the application is guaranteed to have read-only access to the IAM Roles.</p>
</li>
</ol>
<h2 id="heading-layered-approach">Layered Approach</h2>
<p>Then, I read this fantastic write-up I've included in the references section of this blog. We can think differently. What if we can distinguish every resource in different layers based on the two principles:</p>
<ol>
<li><p><strong>Rate of Change:</strong> The resources with a similar rate of change should go in the same layer.</p>
</li>
<li><p><strong>Encapsulation:</strong> A layer should encapsulate all the necessary resources which change with it.</p>
</li>
</ol>
<p>If you think of these layers, they resemble somewhat like the OSI layer model in computer networking. Each layer encapsulates the data passing only the required data to the lower layer. The rate of change and the effect of change increases drastically as you go up the layer chain.</p>
<h2 id="heading-layer-representation">Layer Representation</h2>
<p>This is the diagram of different layers as presented in the blog by <a target="_blank" href="https://leebriggs.co.uk/">Lee Briggs</a><strong>.</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Layer</td><td>Name</td><td>Example Resources</td></tr>
</thead>
<tbody>
<tr>
<td>0</td><td>Billing</td><td>AWS Organization/Azure Account/Google Cloud Account</td></tr>
<tr>
<td>1</td><td>Privilege</td><td>AWS Account/Azure Subscription/Google Cloud Project</td></tr>
<tr>
<td>2</td><td>Network</td><td>AWS VPC/Google Cloud VPC/Azure Virtual Network</td></tr>
<tr>
<td>3</td><td>Permissions</td><td>AWS IAM/Azure Managed Identity/Google Cloud Service Account</td></tr>
<tr>
<td>4</td><td>Data</td><td>AWS RDS/Azure Cosmos DB/Google Cloud SQL</td></tr>
<tr>
<td>5</td><td>Compute</td><td>AWS EC2/Azure Container Instances/GKE</td></tr>
<tr>
<td>6</td><td>Ingress</td><td>AWS ELB/Azure Load Balancer/Google Cloud Load Balancer</td></tr>
<tr>
<td>7</td><td>Application</td><td>Kubernetes Manifests/Azure Functions/ECS Taks/Google Cloud Functions</td></tr>
</tbody>
</table>
</div><p>We can discard the upper two layers. It's best if we manage those layers manually because the lifespan of those resources is generally equivalent to the lifespan of your whole IaC project. And, we have this sweet problem always existing of "if IaC manages state using a resource which can't be managed by that IaC, what manages that resource? For example s3 bucket". For this kind of resource, it's best to have some scripts that do it.</p>
<p>So, the approach that I'd like to take is the following.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Layer</td><td>Name</td><td>Example Resources</td></tr>
</thead>
<tbody>
<tr>
<td>0</td><td>IAM</td><td>IAM Users, IAM Roles etc.</td></tr>
<tr>
<td>1</td><td>Network</td><td>AWS VPC / Security Groups / NAT / IGW / Route Tables / Subnets</td></tr>
<tr>
<td>2</td><td>Certificates</td><td>AWS Certificate Manager, Route53 Records for Certificates</td></tr>
<tr>
<td>3</td><td>Data</td><td>AWS RDS, AWS DocumentDB, DynamoDB</td></tr>
<tr>
<td>4</td><td>Assets</td><td>S3 Buckets, ECR Repositories</td></tr>
<tr>
<td>5</td><td>Ingress</td><td>AWS ELB, Target Groups, Cloudfront Distributions, DNS Records for Route53</td></tr>
<tr>
<td>6</td><td>Compute</td><td>ECS, EKS, EC2 Instances, Autoscaling Groups, Lambda Functions</td></tr>
<tr>
<td>7</td><td>Application</td><td>ECS Services, EKS Resource, Lambda Functions</td></tr>
</tbody>
</table>
</div><p>If you prefer a tree view, this is how I've structured the codebase written using Pulumi SDK in Golang.</p>
<pre><code class="lang-bash">./layers/
├── application
│   ├── main.go
│   ├── Pulumi.dev.yaml
│   └── Pulumi.yaml
├── assets
│   ├── main.go
│   ├── Pulumi.dev.yaml
│   └── Pulumi.yaml
├── certs
│   ├── main.go
│   ├── Pulumi.dev.yaml
│   └── Pulumi.yaml
├── compute
│   ├── main.go
│   ├── Pulumi.dev.yaml
│   └── Pulumi.yaml
├── data
│   ├── main.go
│   ├── Pulumi.dev.yaml
│   └── Pulumi.yaml
├── ingress
│   ├── main.go
│   ├── Pulumi.dev.yaml
│   └── Pulumi.yaml
└── network
    ├── main.go
    ├── Pulumi.dev.yaml
    └── Pulumi.yaml
</code></pre>
<h2 id="heading-complete-project-structure">Complete Project Structure</h2>
<p>If you look at the complete project structure, it resembles something like this.</p>
<pre><code class="lang-bash">.
├── assets
├── base
│   ├── Dockerfile.infras-builder
│   └── Makefile
├── env
│   └── override.mk
├── go.mod
├── go.sum
├── internal
│   └── file
│       └── main.go
├── layers
│   ├── application
│   │   ├── main.go
│   │   ├── Pulumi.dev.yaml
│   │   └── Pulumi.yaml
│   ├── assets
│   │   ├── main.go
│   │   ├── Pulumi.dev.yaml
│   │   └── Pulumi.yaml
│   ├── certs
│   │   ├── main.go
│   │   ├── Pulumi.dev.yaml
│   │   └── Pulumi.yaml
│   ├── compute
│   │   ├── main.go
│   │   ├── Pulumi.dev.yaml
│   │   └── Pulumi.yaml
│   ├── data
│   │   ├── main.go
│   │   ├── Pulumi.dev.yaml
│   │   └── Pulumi.yaml
│   ├── ingress
│   │   ├── main.go
│   │   ├── Pulumi.dev.yaml
│   │   └── Pulumi.yaml
│   └── network
│       ├── main.go
│       ├── Pulumi.dev.yaml
│       └── Pulumi.yaml
├── main.go
├── Makefile
├── pkg
│   ├── acm-certificate
│   │   └── main.go
│   ├── ecr-repository
│   │   └── main.go
│   ├── ecs-cluster
│   │   └── main.go
│   ├── ecs-service-v2
│   │   ├── main.go
│   │   └── types.go
│   ├── label
│   │   └── main.go
│   ├── load-balancer
│   │   ├── main.go
│   │   └── target_group.go
│   ├── mongo-database
│   │   └── main.go
│   ├── postgres-database
│   │   └── main.go
│   ├── s3-cloudfront-website
│   │   └── main.go
│   ├── security-group
│   │   ├── main.go
│   │   └── rule.go
│   └── ssm-parameters
│       └── main.go
├── policies
│   └── ssm-parameter.access.json
└── targets
    ├── docker.mk
    ├── go.mk
    └── pulumi.mk
</code></pre>
<h2 id="heading-explanation">Explanation</h2>
<p>I've heavily used Makefile for this architecture.</p>
<h3 id="heading-targets">targets</h3>
<p>Everything that needs to be run from automation is grouped into the CLI it invokes. For example: dockerized commands, go into the docker.mk, go building/ linting/ vendoring commands go int othe go.mk file</p>
<h3 id="heading-pkg">pkg</h3>
<p>This folder contains the Pulumi components that I've created to abstract all the resources required for one logical component. For example: the <em>ecs-service-v2</em> creates EBS volumes, ECS task definitions, and ECS service itself.</p>
<h3 id="heading-layers">layers</h3>
<p>Every layer of the above diagram resides in a respective folder inside of the layers folder. Each of those packages produces a binary which is then passed with <code>LAYER_NAME</code> to the make command to operate on a single layer at a time.</p>
<h3 id="heading-env">env</h3>
<p>This folder contains the environment variables required for the whole deployment to function. It also sets some handy variables like GOCACHE, GOPATH, and PULUMI_HOME to ensure I have a caching mechanism and a pretty fast build cycle in local environment.</p>
<p>These things will be directly set when running the IaC in CI/CD platform.</p>
<h2 id="heading-reference">Reference</h2>
<p><a target="_blank" href="https://leebriggs.co.uk/blog/2023/08/17/structuring-iac">Structuring your Infrastructure as Code | lbr. (leebriggs.co.uk)</a></p>
]]></content:encoded></item><item><title><![CDATA[Hands-On: I wrote my auth logic with JS in Nginx; Will you?]]></title><description><![CDATA[This may come as a surprise to you. How can someone use nginx configuration with Javascript? Fortunately, nginx supports a language called njs which is a strict subset of ECMA5. This can be used to further extend your routing logic, but don't be that...]]></description><link>https://maheshchandraregmi.com.np/hands-on-i-wrote-my-auth-logic-with-js-in-nginx-will-you</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/hands-on-i-wrote-my-auth-logic-with-js-in-nginx-will-you</guid><category><![CDATA[nginx]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Sun, 17 Sep 2023 16:02:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1694966492443/90a0dbf6-7f87-4b29-a34f-396b1aa57ad5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This may come as a surprise to you. <strong>How can someone use nginx configuration with Javascript?</strong> Fortunately, nginx supports a language called <code>njs</code> which is a strict subset of ECMA5. This can be used to further extend your routing logic, but don't be that happy because the feature you get with <code>njs</code> is very limited.</p>
<p>Lots of syntax doesn't work out of the box and I couldn't make it work with third-party npm modules such as jsonwebtoken etc. I couldn't even use <code>esbuild</code> to generate a single file build.</p>
<p>From the documentation of nginx:</p>
<blockquote>
<p>njs is a subset of the JavaScript language that allows extending nginx functionality. njs is created in compliance with <a target="_blank" href="http://www.ecma-international.org/ecma-262/5.1/">ECMAScript 5.1</a> (strict mode) with some <a target="_blank" href="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</a> and later extensions. The compliance is still <a target="_blank" href="https://nginx.org/en/docs/njs/compatibility.html">evolving</a>.</p>
</blockquote>
<p>I won't go with the installation process because you can get it easily in the documentation <a target="_blank" href="https://nginx.org/en/docs/njs/install.html">here</a>. Also, you'd have to add the following repositories to have nginx packages available if you're also using Ubuntu.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># NGINX Repository</span>
deb http://nginx.org/packages/mainline/ubuntu/ jammy nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ jammy nginx
</code></pre>
<h3 id="heading-running-hello-world">Running Hello World</h3>
<p>After, we've installed the njs module. Let's go ahead and write the js code for straight-up firing the hello world.</p>
<pre><code class="lang-javascript">
@machine:<span class="hljs-regexp">/etc/</span>nginx sudo cat &gt; index.js &lt;&lt; EOF
&gt; <span class="hljs-keyword">var</span> hello = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">r</span>) </span>{
    r.return(<span class="hljs-number">200</span>, <span class="hljs-string">"Hello world!"</span>);
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> { <span class="hljs-attr">hello</span>: hello };
&gt; EOF
root@machine:<span class="hljs-regexp">/etc/</span>nginx
</code></pre>
<p>This is a very simple handler, which will return the string "Hello world!" with status code 200.</p>
<p>Let's plug it into the nginx.conf file.</p>
<pre><code class="lang-apache"><span class="hljs-attribute">user</span>  nginx;
<span class="hljs-attribute">worker_processes</span>  auto;

<span class="hljs-attribute">load_module</span> modules/ngx_http_js_module.so;

<span class="hljs-attribute">http</span> {
  <span class="hljs-attribute">js_import</span> index.js;
  <span class="hljs-attribute">server</span> {
      <span class="hljs-attribute">location</span> / {
          <span class="hljs-attribute">js_content</span> index.hello;
      }
  }
}
</code></pre>
<p>Now, when I send GET request to localhost with curl, I get the expected response.</p>
<pre><code class="lang-javascript">root@machine:<span class="hljs-regexp">/etc/</span>nginx# curl localhost
Hello world!
root@machine:<span class="hljs-regexp">/etc/</span>nginx#
</code></pre>
<p>This is already very cool. But, we can do even more.</p>
<h3 id="heading-implementing-dummy-auth-and-user-service">Implementing Dummy Auth and User Service</h3>
<p>Let's create two simple services; one auth service and one for consuming the auth service.</p>
<p>Auth Service: <a target="_blank" href="https://pastebin.com/uZG7Bx1e">Code</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694965133302/8fc536cb-07ec-4912-984e-00ae2f25fa08.png" alt="Auth Service" /></p>
<p>This is a fairly simple API. The <code>login</code> handler takes a POST request with <code>username</code> JSON key and generates a JWT token. The <code>verify</code> handler verifies the JWT token passed as a bearer token.</p>
<p>Let's test our auth service if it's working as intended.</p>
<pre><code class="lang-bash">regmicmahesh@machine:/etc/nginx$ curl -s localhost:8080/login -XPOST -d <span class="hljs-string">'{"username":"mahesh"}'</span>
{<span class="hljs-string">"token"</span>:<span class="hljs-string">"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTUyMjUzMjMsInVzZXJuYW1lIjoibWFoZXNoIn0.y7kOx9dScMwg0XjRj1AAa9xh3rZp0GzEzR0FC1f3x-w"</span>}
regmicmahesh@machine:/etc/nginx$ curl -s localhost:8080/login -XPOST -d <span class="hljs-string">'{"username":"mahesh"}'</span> | jq -r <span class="hljs-string">".token"</span>
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTUyMjUzMjYsInVzZXJuYW1lIjoibWFoZXNoIn0.XXkLCwspeYYy8kCONSSPve1T7AYX94GgzNB1rrdOygk
regmicmahesh@machine:/etc/nginx$ k^C
regmicmahesh@machine:/etc/nginx$ curl localhost:8080/verify -H <span class="hljs-string">'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTUyMjI5NTksInVzZXJuYW1lIjoibWFoZXNoIn0.GXnnmLuXRr8tu1Sx08DXcgs7N6au4huku-S62sR0JCU'</span>
{<span class="hljs-string">"exp"</span>:1695222959,<span class="hljs-string">"username"</span>:<span class="hljs-string">"mahesh"</span>}
</code></pre>
<p>User Service: <a target="_blank" href="https://pastebin.com/vm04if6Y">Code</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694965227895/a6ee4ee2-0de0-44d3-a80d-8d57100807ab.png" alt /></p>
<p>The <code>user-service</code> simply prints out the value of the header <code>X-User-Id</code> .</p>
<p><strong>Now, we need to configure our nginx such that, every request first goes through the auth service, decodes the token if possible, and passes the username to</strong> <code>user-service</code></p>
<h3 id="heading-writing-nginx-config">Writing Nginx Config</h3>
<p>First of all, let's configure the <code>/verify</code> .</p>
<pre><code class="lang-nginx"> <span class="hljs-attribute">location</span> = /verify {
   internal;
   <span class="hljs-attribute">proxy_pass</span> http://localhost:8080/verify;
}
</code></pre>
<p>This is okay enough. The auth-service is running on port 8080. This should pass the request to that endpoint whenever requested.</p>
<p>Now, we can simply use <code>auth_request /verify</code> . But, where's the fun in that? We want to set the username in the header dynamically.</p>
<p>Let's write a simple njs script to send a request to this endpoint.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">verify</span>(<span class="hljs-params">originalR</span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">callback</span>(<span class="hljs-params">r</span>) </span>{
    originalR.return(r.status);
  }

  originalR.subrequest(<span class="hljs-string">"/verify"</span>, { <span class="hljs-attr">method</span>: <span class="hljs-string">"GET"</span>, <span class="hljs-attr">body</span>: <span class="hljs-string">""</span> }, callback);
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> { verify };
</code></pre>
<p>The NJS script above simply sends the request to <code>/verify</code> but doesn't send the request body. It sends only the headers.</p>
<p>Let's add one more block in nginx to use this js function.</p>
<pre><code class="lang-nginx"> <span class="hljs-attribute">location</span> = /auth {
   internal;
   <span class="hljs-attribute">js_content</span> index.verify;
}
</code></pre>
<p>Now, we need to use this <code>/auth</code> endpoint as the authentication endpoint and everything should be good. We just wrapped our actual verification endpoint with a proxy. Why? Because now we can add our JS logic to set the header.</p>
<p>Let's define a variable to hold the value of the username.</p>
<pre><code class="lang-nginx"><span class="hljs-section">server</span> {
    <span class="hljs-attribute">set</span> <span class="hljs-variable">$username</span> <span class="hljs-string">""</span>;
<span class="hljs-comment"># other code</span>
}
</code></pre>
<p>Now, we can set this variable from the NJS script.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">verify</span>(<span class="hljs-params">originalR</span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">callback</span>(<span class="hljs-params">r</span>) </span>{
    <span class="hljs-keyword">if</span> (r.status === <span class="hljs-number">200</span>) {
      <span class="hljs-keyword">const</span> body = <span class="hljs-built_in">JSON</span>.parse(r.responseText);
      originalR.variables.username = body.username; 
      originalR.return(<span class="hljs-number">200</span>);
    } <span class="hljs-keyword">else</span> {
      originalR.return(<span class="hljs-number">401</span>);
    }
  }

  originalR.subrequest(<span class="hljs-string">"/verify"</span>, { <span class="hljs-attr">method</span>: <span class="hljs-string">"GET"</span>, <span class="hljs-attr">body</span>: <span class="hljs-string">""</span> }, callback);
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> { verify };
</code></pre>
<p>Now, we can send this variable as a header to the actual user service.</p>
<p>Adding it in the location, block it comes as follows:</p>
<pre><code class="lang-nginx"><span class="hljs-attribute">location</span> / {
    <span class="hljs-attribute">auth_request</span> /auth;
    <span class="hljs-attribute">proxy_set_header</span> <span class="hljs-string">"X-User-Id"</span> <span class="hljs-variable">$username</span>;
    <span class="hljs-attribute">proxy_pass</span> http://localhost:8081;
}
</code></pre>
<p>Let's take it for a test-run. It works!</p>
<pre><code class="lang-bash">regmicmahesh@machine:/etc/nginx$ curl  localhost -H <span class="hljs-string">"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTUyMjI5NTksInVzZXJuYW1lIjoibWFoZXNoIn0.GXnnmLuXRr8tu1Sx08DXcgs7N6au4huku-S62sR0JCU"</span>
Request Received From: mahesh
regmicmahesh@machine:/etc/nginx$
</code></pre>
<p>Thanks for reading my blog. I don't think this is the best way, but just wanted to share what's possible with NJS scripting.</p>
]]></content:encoded></item><item><title><![CDATA[Dev Blog 1; Scratching the Kube API Server to get TTY]]></title><description><![CDATA[This is my first blog of multiple blogs on developing a pod troubleshooter turned into a compiler as a service. What do you call it CaaS? COMPaaS is cooler though, lol. I've been learning a lot of things in this journey, so I decided to share about i...]]></description><link>https://maheshchandraregmi.com.np/dev-blog-1-scratching-the-kube-api-server-to-get-tty</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/dev-blog-1-scratching-the-kube-api-server-to-get-tty</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Devops]]></category><category><![CDATA[development]]></category><category><![CDATA[websockets]]></category><category><![CDATA[custom-controller]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Sat, 16 Sep 2023 06:50:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1694846829082/3b2fe060-d6c1-4a23-af9a-9ef1dcd0edf1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is my first blog of multiple blogs on developing a pod troubleshooter turned into a compiler as a service. What do you call it CaaS? COMPaaS is cooler though, lol. I've been learning a lot of things in this journey, so I decided to share about it with you all.</p>
<p>Let me start this blog with how it started, I wanted to make a super simple pod troubleshooter to provide for developers. Developers were having a hard time running migrations, checking application logs, and everything. I thought, okay, I'll create a simple tool which will do one simple thing; provide live tty session inside a running pod.</p>
<p>Although I used Weavescope for the project need, I thought it was always exciting to learn how these tools work and how can I develop one myself. So, I decided I'll build one live tty API for the pod myself.</p>
<h3 id="heading-rest-api-of-kube-api-server">REST API of Kube-API Server</h3>
<p>Let me give you a little bit of background on what is this <a target="_blank" href="https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/">kube-apiserver</a> thing.</p>
<p><img src="https://avinetworks.com/wp-content/uploads/2021/01/kubernetes-architecture-diagram-1.png" alt="What is Kubernetes Architecture?" class="image--center mx-auto" /></p>
<p>Kube-API Server is one of the major services in the control plane which provides a REST API to change/configure the cluster's state. All the things (kubelets, controller manager) need to communicate with the API Server to perform any change in the cluster.</p>
<p>Now, it was clear. If I want a shell in the pod, I need to go through the kube-api server. But how? I wanted the REST API documentation or any reference on how can I send requests to the kube-API server.</p>
<p><strong>Let me teach you a nice hack to find out what requests are you making when you're using</strong> <a target="_blank" href="https://kubernetes.io/docs/reference/kubectl/kubectl/"><strong>kubectl</strong></a><strong>. You can change the verbosity to level 10 to get the exact curl request you're making with the API Server.</strong></p>
<pre><code class="lang-bash">kubectl get pods --v=10
...
curl -v -XGET -H <span class="hljs-string">"User-Agent: kubectl/v1.25.4 (linux/amd64) kubernetes/872a965"</span> \
 <span class="hljs-string">'https://[redacted].com/api/v1/namespaces/default/pods?limit=500'</span>
...
</code></pre>
<p>It's that simple to understand what request is kubectl making to fetch the list of pods in your cluster.</p>
<p>You can also get the <a target="_blank" href="https://swagger.io/specification/">OpenAPI schema</a> of the REST API of Kubernetes.</p>
<pre><code class="lang-bash">curl --insecure -L <span class="hljs-string">"https://<span class="hljs-variable">$API_URL</span>/openapi/v2"</span> \
    -H <span class="hljs-string">"Authorization: Bearer <span class="hljs-variable">$TOKEN</span>"</span>
</code></pre>
<p>This will provide you with the complete open API schema of the kube-api server. You can then visualize this with tools like <a target="_blank" href="https://redocly.com/"><em>redoc</em></a>, <a target="_blank" href="https://swagger.io/"><em>swagger</em></a><em>,</em> etc., and get a proper hold of the API.</p>
<h3 id="heading-rest-endpoint-for-podexec">REST Endpoint for pod/exec</h3>
<p>Our goal is to extract the endpoint of exec-ing inside of the pod. You can either get it using the kubectl as I showed you or just explore through the schema. Either way, the endpoint is this.</p>
<pre><code class="lang-bash"><span class="hljs-variable">${this.config.url}</span>/api/v1/namespaces/<span class="hljs-variable">${namespace}</span>/pods/<span class="hljs-variable">${podName}</span>/<span class="hljs-built_in">exec</span>?<span class="hljs-built_in">command</span>=<span class="hljs-variable">${cmd}</span>&amp;stdin=<span class="hljs-literal">true</span>&amp;stdout=<span class="hljs-literal">true</span>&amp;stderr=<span class="hljs-literal">true</span>&amp;tty=<span class="hljs-literal">true</span>
</code></pre>
<p>But the catch is, that this endpoint doesn't work on HTTP, it upgrades your request to WebSockets. You can't do something like okay, I'll fire up an HTTP request with the command I wanna execute and show the stdout. <strong>The response to this endpoint is always a WebSocket upgrade, and the stdout/stderr is sent as a WebSocket message.</strong></p>
<pre><code class="lang-bash">curl -XPOST -H <span class="hljs-string">"X-Stream-Protocol-Version: v4.channel.k8s.io"</span> \
 -H <span class="hljs-string">"X-Stream-Protocol-Version: v3.channel.k8s.io"</span> \
 -H <span class="hljs-string">"X-Stream-Protocol-Version: v2.channel.k8s.io"</span> \
 -H <span class="hljs-string">"X-Stream-Protocol-Version: channel.k8s.io"</span> \
 -H <span class="hljs-string">"User-Agent: kubectl/v1.25.4 (linux/amd64) kubernetes/872a965"</span> \
 <span class="hljs-string">"https://<span class="hljs-variable">$API_URL</span>/api/v1/namespaces/default/pods/nginx-deployment-cbdccf466-qjfvw/exec?command=python&amp;container=nginx&amp;stdin=true&amp;stdout=true&amp;tty=true"</span>
</code></pre>
<p>The response will contain the header <code>Connection: Upgrade</code> and <code>Upgrade: SPDY/3.1</code> This means the connection is upgraded to WebSocket.</p>
<p>curl won't be able to take you long enough with WebSockets, we can use another tool similar to curl <code>wscurl</code> to send WebSockets requests with curl-like API.</p>
<p>If you're using curl, make sure to specify the subprotocol (i.e. <code>X-Stream-Protocol-Version</code>) with the flag <code>-s</code> .</p>
<pre><code class="lang-bash">wscat -H <span class="hljs-string">"Authorization: Bearer <span class="hljs-variable">$TOKEN</span>"</span> \
   -c <span class="hljs-string">"<span class="hljs-variable">$URL</span>"</span> \
   -s <span class="hljs-string">"v4.channel.k8s.io"</span>
</code></pre>
<h3 id="heading-message-format-from-kube-api-server">Message Format from Kube-API Server.</h3>
<p>The message you receive from kube-api server over WebSockets is in a specific format. The first byte contains the messageType and the remaining bytes are the actual message from the TTY.</p>
<p>There can be three types of messages: <code>stdin, stdout, stderr</code> .</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Message Type</td><td>Byte</td></tr>
</thead>
<tbody>
<tr>
<td>stdin</td><td>0x00</td></tr>
<tr>
<td>stdout</td><td>0x01</td></tr>
<tr>
<td>stderr</td><td>0x02</td></tr>
</tbody>
</table>
</div><p>In this way, you need to filter out the messages whether they're in stdin, stdout, or stderr.</p>
<p>For example: if you establish a connection with websocket, <code>wscat</code> will print something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694846590052/acb42b5b-4e4f-4168-ab0d-3acbb1098d32.png" alt class="image--center mx-auto" /></p>
<p>You see the first byte in the message received from the server. It's 0x01 because it's sent in stdout by the pod when you open a shell. And, your terminal doesn't know how to render that.</p>
<p>Will continue in Part 2.</p>
]]></content:encoded></item><item><title><![CDATA[My bad; But it's too late to rewrite.]]></title><description><![CDATA[It's been around 5 years in the software space as a software engineer. In this journey, I started with the backend, jumped around between different full-stack technologies and currently settling down as the DevOps Engineer, occasionally handling diff...]]></description><link>https://maheshchandraregmi.com.np/my-bad-but-its-too-late-to-rewrite</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/my-bad-but-its-too-late-to-rewrite</guid><category><![CDATA[Devops]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Mon, 11 Sep 2023 14:32:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1694442590799/14081b6b-b502-40e6-ab60-62e5928113ce.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It's been around 5 years in the software space as a software engineer. In this journey, I started with the backend, jumped around between different full-stack technologies and currently settling down as the DevOps Engineer, occasionally handling difficult and complex parts of the system development.</p>
<p>Throughout my career, I've worked with numerous frontend frameworks, backend frameworks and operational strategies and technologies. This brings back a lot of painful and happy memories. <strong>In this blog, I've written about my views from my experience which may or may not be correct.</strong></p>
<p>One problem I've always faced in the majority of the projects is as the projects grow it gets increasingly difficult to change things, observe things and gain a better understanding of the system. When we aren't able to have a good sense of the system, we can't properly architect the new change.</p>
<p>One recent example; I was leading in moving the auth-module of a system from self-backend implementation to Google provider. When I started the project it was really simple, I had implemented the auth module as a separate testable entity that could be plugged into other modules and easily modified. As the project grew with other developers, they started plugging in middlewares, modifying attributes of the auth module and injecting unneeded things to the auth state just because it was properly designed to hold the state in the request-response lifecycle.</p>
<p>Now, I thought to change the internal implementation of the auth module, and sweet hell Mary, everything was a mess. Our middleware broke, and authorization didn't work. Most of the modules that depended on the auth module broke.</p>
<p>Another example; I was leading the development of a data labeling system. We envisioned this system would be complex, so we chose to separate systems into 3 different components. This time, I had bootstrapped the projects and the code was in proper shape in the initial commit. But, soon after from Day 2, there were blockers. Separate components had separate developers working on them. The interaction between components was over HTTP, and communication issues between these components ate up a lot of the development time. By a lot, I mean the development time was extended significantly. Now, when I think about it, it boils down to "premature optimization is the root of all evil".</p>
<p>Another example; This was a streaming site built with a claimed "Super Fast" NodeJS framework at the time. I thought, okay streaming is a tough job. Let's write this service with NodeJS and a custom ffmpeg wrapper in NodeJS. The super-fast framework was so slow to develop, that it had no community plugins. I wrote a lot of things myself which I could have got for free. If I'd sacrificed 1% speed and used a slower framework, my productivity would be 100x.</p>
<h2 id="heading-what-did-i-learn-from-it">What did I learn from it?</h2>
<p>I learned two key things from it:</p>
<ol>
<li><p>Developers often fail to understand the intention behind the code.</p>
</li>
<li><p>You don't need to think about scaling to 10 million when you're writing your first line of code.</p>
</li>
<li><p>There is no such thing as "It worked for X corp, it should surely work for us."</p>
</li>
<li><p>Don't go with "Yeah, I've worked with X framework between these choices, and I think it's a good fit."</p>
</li>
<li><p>Performance isn't always the top priority.</p>
</li>
</ol>
<h2 id="heading-how-do-i-do-it-now">How do I do it now?</h2>
<p>Now, I've seen enough failures to identify the correct one. I'm confident enough to tell that whatever you're building, it should follow these characteristics:</p>
<ul>
<li><p>should have <strong>as little magic</strong> as it can.</p>
</li>
<li><p><strong>dx</strong> is not a thing to ignore.</p>
</li>
<li><p>Most of the things should be <strong>automated</strong>.</p>
</li>
<li><p>Interfaces and boundaries should be thought of at first.</p>
</li>
<li><p>The system should be <strong>observable</strong>.</p>
</li>
<li><p>There should be a proper document in place to understand "<strong>why</strong>" for all ADRs (architecture decision records)</p>
</li>
</ul>
<p>In the starting, I'll start with some BaaS (Firebase, Supabase, Strapi maybe) because it's not worth investing a lot of code and developer time when your (potential) clients and software don't even understand each other.</p>
<p>Most of the BaaS makes things observable, you can know which services are getting most requests, which queries are taking the most time, what time you are getting a lot of traffic, which is the bottleneck in your system etc. You also get sweet other things out of the box such as authentication/authorization, and data persistence layers and the best of them all is <strong>dx</strong> with it.</p>
<p>After a certain period, you'll get a perfect understanding of which way your software is heading. You can slowly start separating the bottlenecks of the BaaS platform into separate services. You write your code this time, as serverless functions if possible for your service. And you plug it into your BaaS.</p>
<p>Now, you need to start finding out how that BaaS does certain things and how'd you on about doing that on your own, research on the database performance, language, toolings etc.</p>
<p>After a certain level of maturity, you'll realize your business logic is getting too complicated to tune your BaaS and you need to do it on your own. This is the moment you start slowly rewriting your backend and shifting your API into your backend, one service at a time.</p>
<p><strong>At last, this is my personal experience. Let me know if you have any conflicting views or I misunderstood something, I'm learning every day and would be very happy to correct myself.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Is unpacking faster than indexing?]]></title><description><![CDATA[This is a strange story.
One morning, I woke up and wrote a few lines of code. Then, there came an interesting situation. I need to assign two elements of an array to two variables. There are many ways of achieving this in python.
If you're a javascr...]]></description><link>https://maheshchandraregmi.com.np/is-unpacking-faster-than-indexing</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/is-unpacking-faster-than-indexing</guid><category><![CDATA[Python]]></category><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Developer]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Tue, 12 Apr 2022 09:24:34 GMT</pubDate><content:encoded><![CDATA[<p>This is a strange story.</p>
<p>One morning, I woke up and wrote a few lines of code. Then, there came an interesting situation. I need to assign two elements of an array to two variables. There are many ways of achieving this in python.</p>
<p>If you're a javascript developer, your instinct should say this is the way.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [x,y] = items;
</code></pre>
<p>Suppose, I've got an array <code>[1,2]</code> and I need to assign two variables to this value. Something like follow:</p>
<pre><code class="lang-python">a = <span class="hljs-number">1</span>
b = <span class="hljs-number">2</span>
</code></pre>
<p>I did the natural thing I was used to doing, unpacking the variable.</p>
<pre><code class="lang-python">a, b = items
</code></pre>
<p>This works with charm. But suddenly I remember of an another way. What if I index the array and grab the elements that way.</p>
<pre><code class="lang-python">a, b = items[<span class="hljs-number">0</span>], items[<span class="hljs-number">1</span>]
</code></pre>
<p>Or even.</p>
<pre><code class="lang-python">a = items[<span class="hljs-number">0</span>]
b = items[<span class="hljs-number">1</span>]
</code></pre>
<p>Now, I want to profile this code. I know this is over-engineering at max but let's see what exactly happens.</p>
<p>First I wrote the same implementation in python and disassembled the code.</p>
<pre><code><span class="hljs-string">In</span> [<span class="hljs-number">15</span>]<span class="hljs-string">:</span> <span class="hljs-string">def</span> <span class="hljs-string">x():</span>
    <span class="hljs-string">...:</span>     <span class="hljs-string">a</span> <span class="hljs-string">,</span> <span class="hljs-string">b</span> <span class="hljs-string">=</span> <span class="hljs-string">items</span>
    <span class="hljs-string">...:</span>     <span class="hljs-string">return</span>
    <span class="hljs-string">...:</span>

<span class="hljs-string">In</span> [<span class="hljs-number">16</span>]<span class="hljs-string">:</span> <span class="hljs-string">def</span> <span class="hljs-string">y():</span>
    <span class="hljs-string">...:</span>     <span class="hljs-string">a</span> <span class="hljs-string">=</span> <span class="hljs-string">items[0]</span>
    <span class="hljs-string">...:</span>     <span class="hljs-string">b</span> <span class="hljs-string">=</span> <span class="hljs-string">items[1]</span>
    <span class="hljs-string">...:</span>     <span class="hljs-string">return</span>
    <span class="hljs-string">...:</span>

<span class="hljs-string">In</span> [<span class="hljs-number">17</span>]<span class="hljs-string">:</span> <span class="hljs-string">dis(x)</span>
  <span class="hljs-number">2</span>           <span class="hljs-number">0</span> <span class="hljs-string">LOAD_GLOBAL</span>              <span class="hljs-number">0</span> <span class="hljs-string">(items)</span>
              <span class="hljs-number">2</span> <span class="hljs-string">UNPACK_SEQUENCE</span>          <span class="hljs-number">2</span>
              <span class="hljs-number">4</span> <span class="hljs-string">STORE_FAST</span>               <span class="hljs-number">0</span> <span class="hljs-string">(a)</span>
              <span class="hljs-number">6</span> <span class="hljs-string">STORE_FAST</span>               <span class="hljs-number">1</span> <span class="hljs-string">(b)</span>

  <span class="hljs-number">3</span>           <span class="hljs-number">8</span> <span class="hljs-string">LOAD_CONST</span>               <span class="hljs-number">0</span> <span class="hljs-string">(None)</span>
             <span class="hljs-number">10</span> <span class="hljs-string">RETURN_VALUE</span>

<span class="hljs-string">In</span> [<span class="hljs-number">18</span>]<span class="hljs-string">:</span> <span class="hljs-string">dis(y)</span>
  <span class="hljs-number">2</span>           <span class="hljs-number">0</span> <span class="hljs-string">LOAD_GLOBAL</span>              <span class="hljs-number">0</span> <span class="hljs-string">(items)</span>
              <span class="hljs-number">2</span> <span class="hljs-string">LOAD_CONST</span>               <span class="hljs-number">1</span> <span class="hljs-string">(0)</span>
              <span class="hljs-number">4</span> <span class="hljs-string">BINARY_SUBSCR</span>
              <span class="hljs-number">6</span> <span class="hljs-string">STORE_FAST</span>               <span class="hljs-number">0</span> <span class="hljs-string">(a)</span>

  <span class="hljs-number">3</span>           <span class="hljs-number">8</span> <span class="hljs-string">LOAD_GLOBAL</span>              <span class="hljs-number">0</span> <span class="hljs-string">(items)</span>
             <span class="hljs-number">10</span> <span class="hljs-string">LOAD_CONST</span>               <span class="hljs-number">2</span> <span class="hljs-string">(1)</span>
             <span class="hljs-number">12</span> <span class="hljs-string">BINARY_SUBSCR</span>
             <span class="hljs-number">14</span> <span class="hljs-string">STORE_FAST</span>               <span class="hljs-number">1</span> <span class="hljs-string">(b)</span>

  <span class="hljs-number">4</span>          <span class="hljs-number">16</span> <span class="hljs-string">LOAD_CONST</span>               <span class="hljs-number">0</span> <span class="hljs-string">(None)</span>
             <span class="hljs-number">18</span> <span class="hljs-string">RETURN_VALUE</span>

<span class="hljs-string">In</span> [<span class="hljs-number">19</span>]<span class="hljs-string">:</span>
</code></pre><p>Do you see the extra overhead when I index the value? First, it need to load the constant i.e. index value, then perform the subscription. The store the value in <code>a</code>. This is a long way of doing it.</p>
<p>If I look at the other code, which is unpacking. One instruction <code>UNPACK_SEQUENCE</code> is capable of returning all the values and it's followed by two store instructions. </p>
<p>Even by intuition, I suppose the first function <code>(x)</code> will run faster.</p>
<p>Now, let's compare the execution time.</p>
<pre><code><span class="hljs-string">In</span> [<span class="hljs-number">19</span>]<span class="hljs-string">:</span> <span class="hljs-string">%timeit</span> <span class="hljs-string">x()</span>
<span class="hljs-number">84.3</span> <span class="hljs-string">ns</span> <span class="hljs-string">±</span> <span class="hljs-number">3.59</span> <span class="hljs-string">ns</span> <span class="hljs-string">per</span> <span class="hljs-string">loop</span> <span class="hljs-string">(mean</span> <span class="hljs-string">±</span> <span class="hljs-string">std.</span> <span class="hljs-string">dev.</span> <span class="hljs-string">of</span> <span class="hljs-number">7</span> <span class="hljs-string">runs,</span> <span class="hljs-number">10</span><span class="hljs-string">,000,000</span> <span class="hljs-string">loops</span> <span class="hljs-string">each)</span>

<span class="hljs-string">In</span> [<span class="hljs-number">20</span>]<span class="hljs-string">:</span> <span class="hljs-string">%timeit</span> <span class="hljs-string">y()</span>
<span class="hljs-number">108</span> <span class="hljs-string">ns</span> <span class="hljs-string">±</span> <span class="hljs-number">2.42</span> <span class="hljs-string">ns</span> <span class="hljs-string">per</span> <span class="hljs-string">loop</span> <span class="hljs-string">(mean</span> <span class="hljs-string">±</span> <span class="hljs-string">std.</span> <span class="hljs-string">dev.</span> <span class="hljs-string">of</span> <span class="hljs-number">7</span> <span class="hljs-string">runs,</span> <span class="hljs-number">10</span><span class="hljs-string">,000,000</span> <span class="hljs-string">loops</span> <span class="hljs-string">each)</span>
</code></pre><p>To no surprise, the unpacking beats the indexing by around ~24ns. This isn't the kind of optimization you should be thinking when writing a code. Write a clean, readable testable code.</p>
<p>Don't abuse your codebase with lines like the following:</p>
<pre><code>a ,= items
# use <span class="hljs-keyword">this</span>
b = items[<span class="hljs-number">0</span>]
</code></pre>]]></content:encoded></item><item><title><![CDATA[I stopped using environment variables for config.]]></title><description><![CDATA[Environment variables were the standards for passing configurations, keys, and deployment assets in the system for a long time. It's even recommended by the twelve-factor apps guide.
No syntax, No composition
But the problem is once your configuratio...]]></description><link>https://maheshchandraregmi.com.np/i-stopped-using-environment-variables-for-config</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/i-stopped-using-environment-variables-for-config</guid><category><![CDATA[Devops]]></category><category><![CDATA[Security]]></category><category><![CDATA[Developer]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Sun, 10 Apr 2022 06:03:29 GMT</pubDate><content:encoded><![CDATA[<p>Environment variables were the standards for passing configurations, keys, and deployment assets in the system for a long time. It's even recommended by the twelve-factor apps guide.</p>
<h2 id="heading-no-syntax-no-composition">No syntax, No composition</h2>
<p>But the problem is once your configuration starts getting too complex, it's very tough to manage environment variables. Currently, in one of my projects, the environment variable count is 53 and it's bound to increase substantially when we deploy our next release. If only there was composition we could identify which are common variables to be used in all stages and which are the unique ones. For this problem, what we're doing currently is namespacing the environment variables via underscore. 
For example <code>MY_COMMERCE_DB_HOST_NAME</code>. Now, when we deploy another environment it's very tough to identify which environment variable is used in which aspect of the project and how. The complexity and no data types of environment variables is only one part of the problem, and probably a lesser significant one. </p>
<h2 id="heading-security-issues">Security Issues</h2>
<p>Environment variables increase the attack surface for your application when sensitive values like SSH Keys, Database Passwords, authentication credentials, and API Keys are passed via it. Most of the loggers dump all your environment variables into the log file when your application crashes along with the stack trace which silently passes down your secret variables into a plain text log file. Also, the environment variables when supplied to a parent process are passed down to every child process. Now, if you're spawning a subprocess to some third party process it has access to all of your secrets. In ephemeral deployment solutions like AWS Lambda, Azure Functions it maybe not be much of an issue because you can use your own master key to sign your environment variables, and also the container lifecycle is ephemeral which significantly reduces the risk of leaking down your variables but still, it's doable and is happening.</p>
<h1 id="heading-what-is-my-approach">What is my approach?</h1>
<h2 id="heading-store-your-configuration-file-in-yaml">Store your configuration file in YAML.</h2>
<p>It's easy enough to create language and OS agnostic configuration files (INI, YAML, etc.) and it's usually straightforward to make files easy to change between deployments too - e.g. if a deployment is containerized, by mounting the file.</p>
<p>You can replace it like this:</p>
<pre><code class="lang-bash">APP_ID=123
APP_HOST=domain.com
APP_LOGGER=logging-service

DB_HOST=domain.com
DB_PORT=5433
DB_USERNAME=mmm
</code></pre>
<pre><code class="lang-yaml"><span class="hljs-attr">app:</span>
  <span class="hljs-attr">id:</span> <span class="hljs-number">123</span>
  <span class="hljs-attr">host:</span> <span class="hljs-string">domain.com</span>
  <span class="hljs-attr">logger:</span> <span class="hljs-string">logging-service</span>

<span class="hljs-attr">db:</span>
  <span class="hljs-attr">host:</span> <span class="hljs-string">domain.com</span>
  <span class="hljs-attr">port:</span> <span class="hljs-number">5433</span>
  <span class="hljs-attr">username:</span> <span class="hljs-string">mmm</span>
</code></pre>
<p>Now, this is significantly easier to parse and pass down the road to required places which also supports the dependency inversion principle. There are packages that can create schemas from YAML files which will even help you further. Also, you can use YAML validators to add different validations, now your configuration has its own syntax, and data types are composite.</p>
<h2 id="heading-store-your-secrets-in-an-ephemeral-file-system">Store your secrets in an ephemeral file system.</h2>
<p>Different containerization platforms have their own way of passing down secrets in an ephemeral file system.  If you're using Docker in swarm mode, you can utilize the full benefit of docker secrets. Kubernetes has its own configuration mechanisms for passing secrets. One of the methods I personally suggest to pass secrets is using Hashicorp Vault which is very good for implementing in zero-trust environments.</p>
<p>Also, the cloud provider has some sort of secrets management service like AWS Secrets Manager which has a variety of security mechanisms as a service.</p>
]]></content:encoded></item><item><title><![CDATA[Should you use Kubernetes?]]></title><description><![CDATA[No.]]></description><link>https://maheshchandraregmi.com.np/should-you-use-kubernetes</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/should-you-use-kubernetes</guid><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Sun, 03 Apr 2022 10:24:02 GMT</pubDate><content:encoded><![CDATA[<p>No.</p>
]]></content:encoded></item><item><title><![CDATA[Hardening a Docker Image]]></title><description><![CDATA[Hardening
Hardening refers to decrease the potential of a system getting exploited by reducing the attack surface. It may range from adhering different policies like Least Privilege, Zero Trust and also contain different steps like automatic security...]]></description><link>https://maheshchandraregmi.com.np/hardening-a-docker-image</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/hardening-a-docker-image</guid><category><![CDATA[Devops]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Security]]></category><category><![CDATA[Continuous Integration]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Wed, 23 Mar 2022 02:18:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1648001803449/MnEWPSaCf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-hardening">Hardening</h1>
<p>Hardening refers to decrease the potential of a system getting exploited by reducing the attack surface. It may range from adhering different policies like Least Privilege, Zero Trust and also contain different steps like automatic security updates, firewalls, rotating passwords etc.</p>
<p>For hardening a system, basically the system-ops should cut-off unnecessary provisioned processes, services and vast majority of other resources currently used by the system unless they're bare minimum or essential for the system to function.</p>
<p>There are a million steps to be taken in order to prepare an absolutely stone hardened system but we'll look at some essential steps in hardening a docker image so that next time someone tries to own your docker container, they'll have hard time.</p>
<h2 id="heading-limit-the-build-data-with-dockerignore-or-unnecessary-copy">Limit the build data with .dockerignore or unnecessary copy.</h2>
<p>Most of the times when building a docker image, it's a wild practice to move a directory directly inside the image, but this increases the attack surface as .env files, configuration folders, log files may be moved inside the docker image which gives the attacker more information already present inside the docker container regarding the system.</p>
<p>Even if the data are too many to be copied without doing a wild-card copy, I'd suggest to use a <code>.dockerignore</code> file which behaves similar to <code>.gitignore</code> and it stops the files from being copied which are mentioned there.</p>
<h2 id="heading-use-smaller-images-or-scratch-if-possible">Use smaller images or scratch if possible.</h2>
<p>Using a larger docker bases which consist of a thousand of tools your application doesn't need to function but increase the attack surface as there's chances of them having security issues is a great way of helping the hacker. </p>
<p>Try to use a very small image. Also, don't make a nightmare for developer by using images like alpine when the application is supposed to use very complicated libraries as alpine builds everything using musl and sometimes it's a nightmare. </p>
<p>My preferred docker images are slim builds of debian. Also, it's a lot easier when you're using statically compiled languages like go, which can run natively inside docker container when you just ship a container with only the binary. Think about the attack surface reduction when everything the filesystem contains is a single binary.</p>
<h2 id="heading-downgrade-to-non-privileged-user">Downgrade to non-privileged User.</h2>
<p>Getting rid of the root user in a docker image is just a two line configuration change. By doing just this simple change, we introduced a whole new problem of privilege escalation to the potential attacker.</p>
<h2 id="heading-mount-host-file-system-as-read-only">Mount host file system as read-only.</h2>
<p>Often times, we need to mount host data for reading configuration, or many other reasons for the docker container to function properly. For this, if we mount the host file system with full RW access chances are the potential attacker will misbehave with the mounted file system. To mitigate to some extent, we should mount the file system in read-only mode. We should reduce the access in the host file system by stripping down to the only required folder / file.</p>
<h2 id="heading-dont-expose-unnecessary-ports">Don't expose unnecessary ports.</h2>
<p>In development environment, it's a good idea to expose multiple ports, as the developer may require to run remote debugging in the container, or an extra development only network access for whatever reason but those ports should be strictly shut down while running with live users. It's a good idea to expose only the port listened by the main process running inside the docker container.</p>
<h2 id="heading-never-run-in-privileged-mode">Never run in privileged mode</h2>
<p>This requires no explanation. Running a container in privileged mode means it can do basically anything the host system. This is the worst thing through which you not only risk the container but also risk the host system.</p>
<h1 id="heading-other-extra-suggestions">Other Extra Suggestions</h1>
<h2 id="heading-enable-scan-on-push-in-ecr">Enable Scan on Push in ECR.</h2>
<p>Elastic Container Registry (ECR) service provided by Amazon can scan for security issues in your docker images as soon as you push them. This enables you to know about the potential threats in the docker image and quickly update / patch the packages which have CVEs assigned to them.</p>
]]></content:encoded></item><item><title><![CDATA[some notes i took.]]></title><description><![CDATA[The Single Responsibility rule states that a class should have a single purpose, and its methods should all be related to that purpose.

The Encapsulation rule states that a class’s implementation details should be hidden from its clients as much as ...]]></description><link>https://maheshchandraregmi.com.np/some-notes-i-took</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/some-notes-i-took</guid><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Sat, 22 Jan 2022 06:25:32 GMT</pubDate><content:encoded><![CDATA[<ol>
<li><p>The Single Responsibility rule states that a class should have a single purpose, and its methods should all be related to that purpose.</p>
</li>
<li><p>The Encapsulation rule states that a class’s implementation details should be hidden from its clients as much as possible.</p>
</li>
<li><p>The Most Qualified Class rule states that work should be assigned to the class that knows best how to do it.</p>
</li>
<li><p>The Low Coupling rule states that the number of class dependencies should be minimized.</p>
</li>
<li><p>The rule of Transparency states that a client should be able to use an interface without needing to know the classes that implement that interface.</p>
</li>
<li><p>The Open/Closed rule states that programs should be  structured so that they can be revised by creating new  classes instead of modifying existing ones.</p>
</li>
<li><p>The Liskov Substitution Principle (LSP) specifies when it is meaningful for one interface to be a subtype of another. In particular, X should be a subtype of Y only if an object of type X can always be used wherever an object of type Y is expected.</p>
</li>
<li><p>The rule of Abstraction states that a class’s dependencies should be as abstract as possible.</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Splitting a big tfstate into Multiple Environments with Remote Backend]]></title><description><![CDATA[Splitting tfstate files into multiple environments is very useful when your project is growing so much and you've a very big tfstate file and you need to monitor which resource are failing, which are deploying effectively.
It's hard to track resource...]]></description><link>https://maheshchandraregmi.com.np/splitting-a-big-tfstate-into-multiple-environments-with-remote-backend</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/splitting-a-big-tfstate-into-multiple-environments-with-remote-backend</guid><category><![CDATA[Devops]]></category><category><![CDATA[Terraform]]></category><category><![CDATA[backend]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[server]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Mon, 20 Sep 2021 05:31:37 GMT</pubDate><content:encoded><![CDATA[<p>Splitting tfstate files into multiple environments is very useful when your project is growing so much and you've a very big tfstate file and you need to monitor which resource are failing, which are deploying effectively.</p>
<p>It's hard to track resources specifically when you're using for example own mongodb in your dev cluster but want managed service for your production environment.</p>
<p>Let us consider a file structure as below. Currently, all your backend configurations are stored inside the <code>mono/provider.tf</code>. Now, your project is growing and you need to separate out your tfstate into multiple environments.</p>
<p>For this example, we consider s3 backend. But you may use any; the process is same.</p>
<pre><code>
 [FILE] envs ~<span class="hljs-regexp">/devops/</span>learningtf/envs
      dev                                                                                 
     └  provider.tf                                                                        
      mono                                                                      
     └  provider.tf                                  
      prod                                                                           
     └  provider.tf
</code></pre><p>The code inside the <code>mono/provider.tf</code> is as follows.</p>
<p><code>mono/provider.tf</code></p>
<pre><code><span class="hljs-section">terraform</span> {
  <span class="hljs-section">required_providers</span> {
    <span class="hljs-attribute">aws</span> = {
      <span class="hljs-attribute">source</span>  = <span class="hljs-string">"hashicorp/aws"</span>
      version = <span class="hljs-string">"~&gt; 3.0"</span>
    }
  }
  backend <span class="hljs-string">"s3"</span> {
    <span class="hljs-attribute">bucket</span> = <span class="hljs-string">"test-split-backend"</span>
    key    = <span class="hljs-string">"dev"</span>
    region = <span class="hljs-string">"us-east-1"</span>

    dynamodb_table = <span class="hljs-string">"dev-test-split-backend"</span>
  }
}

<span class="hljs-comment"># Configure the AWS Provider</span>
provider <span class="hljs-string">"aws"</span> {
  <span class="hljs-attribute">region</span> = <span class="hljs-string">"us-east-1"</span>
}

resource <span class="hljs-string">"aws_s3_bucket"</span> <span class="hljs-string">"dev-bucket"</span> {
  <span class="hljs-attribute">bucket</span> = <span class="hljs-string">"test-split-qa"</span>
  acl    = <span class="hljs-string">"private"</span>
}

resource <span class="hljs-string">"aws_s3_bucket"</span> <span class="hljs-string">"qa-bucket"</span> {
  <span class="hljs-attribute">bucket</span> = <span class="hljs-string">"test-split-qa"</span>
  acl    = <span class="hljs-string">"private"</span>
}
</code></pre><p>Consider these two buckets <code>dev-bucket</code> and <code>qa-bucket</code>. Now, you want to move these two resources into it's own environment.</p>
<p>Let's make a scaffold for putting resources with provider and backend for dev environment.</p>
<p><code>dev/provider.tf</code></p>
<pre><code><span class="hljs-section">terraform</span> {
  <span class="hljs-section">required_providers</span> {
    <span class="hljs-attribute">aws</span> = {
      <span class="hljs-attribute">source</span>  = <span class="hljs-string">"hashicorp/aws"</span>
      version = <span class="hljs-string">"~&gt; 3.0"</span>
    }
  }
  backend <span class="hljs-string">"s3"</span> {
    <span class="hljs-attribute">bucket</span> = <span class="hljs-string">"test-split-backend"</span>
    key    = <span class="hljs-string">"dev-split/terraform.tfstate"</span>
    region = <span class="hljs-string">"us-east-1"</span>

    dynamodb_table = <span class="hljs-string">"dev-test-split-backend-final"</span>
  }
}
</code></pre><p>Now, you may proceed to <code>terraform apply</code> so that terraform will generate state file and lock files on the remote backend.</p>
<p>If you run <code>terraform state list</code>, the output should be empty as we haven't added any resources in this environment.</p>
<p>Now, the first step is to dump the tfstate file which is very easy, just one command.</p>
<pre><code><span class="hljs-built_in">cd</span> dev &amp;&amp; terraform state pull &gt; dev.tfstate
</code></pre><p>This will pull your current configuration of dev environment which should be not exactly empty but without any resources.</p>
<p>Now, you're ready to move the resource from <code>mono</code> into <code>dev</code> environment.</p>
<p>First of all identify which resource / module you want to move by looking at the tf files.</p>
<p>After identifying the resources, now move them into dev.tfstate using this simple command.</p>
<pre><code>cd mono
terraform <span class="hljs-keyword">state</span> mv -<span class="hljs-keyword">state</span>-out=../dev/dev.tfstate aws_s3_bucket.dev-bucket aws_s3_bucket.dev-bucket
</code></pre><p>This will remove the resource tracking from mono and move into to dev.tfstate which is not synced with dev remote tfstate as of now.</p>
<p>Now, the last thing you need to do is push the dev tfstate into the remote server, which is as easy as the following command.</p>
<pre><code>cd dev
terraform <span class="hljs-keyword">state</span> <span class="hljs-keyword">push</span> dev.tfstate
</code></pre><p>Now, if you run <code>terraform state show</code>, you should be able to see the different as it won't show in the mono but it'll show in the dev.</p>
<p>You can confirm if there's any drift by doing terraform plan inside the dev environment.</p>
]]></content:encoded></item><item><title><![CDATA[Reduce the fear on reduce - Javascript.]]></title><description><![CDATA[The reduce method available on arrays on JavaScript is one of the most powerful feature of functional programming. It is used to combine an sequence of elements together as a binary operation. In general terms, when we reduce an array we produce a si...]]></description><link>https://maheshchandraregmi.com.np/reduce-the-fear-on-reduce-javascript</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/reduce-the-fear-on-reduce-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[data structures]]></category><category><![CDATA[array]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Mon, 24 May 2021 05:21:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621834512505/dJvgiuKa8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The reduce method available on arrays on JavaScript is one of the most powerful feature of functional programming. It is used to combine an sequence of elements together as a binary operation. In general terms, when we reduce an array we produce a single value at the end which consists of a pure function and some important concepts of reduce workflow.</p>
<p>The image below correctly explains the three main pillars provided in javascript to support functional programming paradigm.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621829698169/pDKx_zYNm.png" alt="image.png" /></p>
<p>Map is used to create a new array based on certain manipulation of every item of existing array but not removing them.</p>
<p>Filter is used to create a new array based on certain condition of existing array.</p>
<p>Reduce is the master of all which includes a whole pipeline and can do map, filter and much more. But, as you see in the diagram it is used to produce a single value at the end.</p>
<p>Before getting hands-on with reduce, we need to understand few concepts first.</p>
<h2 id="accumulator">Accumulator</h2>
<p>Accumulator is used to store the current value of our reduce pipeline. Initially, if we provide any initial value to the reduce function, accumulator equals that value if not accumulator takes the first value in the array and the iteration starts from second item. Not clear? Look at the examples below.</p>
<p>Let's start with one of the most basic reducing operation.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>];
<span class="hljs-keyword">const</span> num = arr.reduce(<span class="hljs-function">(<span class="hljs-params">acc, el</span>) =&gt;</span> acc + el);
<span class="hljs-built_in">console</span>.log(num); <span class="hljs-comment">// 55</span>
</code></pre>
<p>Here, the reduce function takes 1 as initial value ( first item in the array ) because no initial value is provided. After taking the first item as initial value, the invocation of function starts with the second item in the array.</p>
<p>Initially, the accumulator stores the same value as the initial value.</p>
<p>So, the initial value is 1, the accumulator holds the value 1, and the current element is 2.</p>
<p>After running the function we passed inside the callback, the returned value of our function is the new value to be set in the accumulator.</p>
<p>After one iteration.</p>
<p>So, the accumulator holds to value 3, and the current element is 3.</p>
<p>After second iteration.</p>
<p>So, the accumulator holds the value 6, and the current element in 4.</p>
<p>So, the accumulator is responsible for holding the returned new item after every iteration which is again passed while invoking the function for next item.</p>
<p>Guess, the above example makes it crystal clear now.</p>
<p>Now, let's try to do the same thing but providing initial value.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>];
<span class="hljs-keyword">const</span> num = arr.reduce(<span class="hljs-function">(<span class="hljs-params">acc, el</span>) =&gt;</span> acc + el, <span class="hljs-number">5</span>);
<span class="hljs-built_in">console</span>.log(num); <span class="hljs-comment">//60</span>
</code></pre>
<p>Here, we pass another argument to the reduce method of array <code>5</code>. Now, the reduce method will take 5 as initial value. The iteration begins on first item because it's not taken as initial value.</p>
<p>So, the initial value is 5, the accumulator holds the value 5, and the current element is 1.</p>
<p>After one iteration.</p>
<p>So, the accumulator holds to value 6, and the current element is 2.</p>
<p>After second iteration.</p>
<p>So, the accumulator holds the value 8, and the current element in 3.</p>
<p>Hope you understood the process.</p>
<p>Now, let's understand the whole syntax.</p>
<pre><code class="lang-javascript">reduce(<span class="hljs-function">(<span class="hljs-params">acc, el</span>) =&gt;</span> { ... } )
reduce(<span class="hljs-function">(<span class="hljs-params">acc, el, i</span>) =&gt;</span> { ... } )
reduce(<span class="hljs-function">(<span class="hljs-params">acc, el, i, arr</span>) =&gt;</span> { ... } )
</code></pre>
<p>We tried the first syntax already. The first item we pass is the accumulated value which is equal to the initialValue ( if we pass ) or the first item of array initially.</p>
<p>The second syntax is also near-equivalent but it takes a third argument <code>i</code> which is equal to the current index of the array.</p>
<p>The third syntax passes the whole array as first argument.</p>
<p>Keep in mind, only the first two are required. All other are optional parameters, pass it if you need them.</p>
<p>Now, you've a foundational knowledge of reduce, let's try to see how it's a swiss knife of functional programming.</p>
<h3 id="converting-an-array-of-number-to-array-of-strings">Converting an array of number to array of strings.</h3>
<p>For this operation map may be suitable and if you do it via map, you can do something like this...</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>];
<span class="hljs-keyword">const</span> num = arr.map(<span class="hljs-function"><span class="hljs-params">el</span> =&gt;</span> el.toString())
<span class="hljs-built_in">console</span>.log(num); <span class="hljs-comment">// ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]</span>
</code></pre>
<p>This is a lot simpler approach. Let's try to approach this with reduce.</p>
<p>First let's think how we can solve this like a functional programmer.</p>
<p>The initial  value for this operation should be blank array i.e. <code>[]</code>. Now, on every reduce operation we convert the number into string and push into the array.</p>
<p>Pretty straight-forward right?</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>];
<span class="hljs-keyword">const</span> num = arr.reduce(<span class="hljs-function">(<span class="hljs-params">acc, el</span>) =&gt;</span> [...acc, el.toString()], []);
<span class="hljs-built_in">console</span>.log(num);
</code></pre>
<p>If you're confused with the part <code>[...acc, el.toString()]</code>, it means to spread the value of current acc array in the place of <code>...acc</code> which means if acc equals to <code>[1,2,3]</code> then our new array will be replaced as <code>[...acc] =&gt; [1,2,3]</code>, here the value inside of acc array is spread in-place.</p>
<p>After the current value held by the acc, we are pushing our current <code>el.toString()</code>.</p>
<p>The flow can be explained as...</p>
<p>At first,  acc = [] and current element = 1</p>
<p>At second, acc =  ["1"] and current element = 2</p>
<p>At third, acc = ["1" , "2"] and current element = 3</p>
<p>Pretty straight forward right?
If you're having issues with spread operator, consider this.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>];

<span class="hljs-keyword">const</span> num = arr.reduce(<span class="hljs-function">(<span class="hljs-params">acc, el</span>) =&gt;</span> {
 acc.push(el.toString());
 <span class="hljs-keyword">return</span> acc;
}, []);

<span class="hljs-built_in">console</span>.log(num);
</code></pre>
<p>Now, what if only even number is required.</p>
<p>Let's try with filter and map.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>];
<span class="hljs-keyword">const</span> num = arr
    .filter(<span class="hljs-function"><span class="hljs-params">el</span> =&gt;</span> el % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>)
    .map(<span class="hljs-function"><span class="hljs-params">el</span> =&gt;</span> el.toString())
<span class="hljs-built_in">console</span>.log(num);
</code></pre>
<p>This does the job. Now, let's try implementing this with reduce.</p>
<p>So, the initial value will be []. Our callback function should return the accumulator if element is odd, else add the stringified-element to the accumulator and return it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>];
<span class="hljs-keyword">const</span> num = arr.reduce(<span class="hljs-function">(<span class="hljs-params">acc, el</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span>(el % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>) acc.push(el.toString());
 <span class="hljs-keyword">return</span> acc;
}, []);
<span class="hljs-built_in">console</span>.log(num);
</code></pre>
<p>Now, this is getting interesting, right?</p>
<p>Let's try to implement a reduce function which reverses an array. It's quite simple because we also have reduce right, which reduces the array from left.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>];
<span class="hljs-keyword">const</span> num = arr.reduceRight(<span class="hljs-function">(<span class="hljs-params">acc, el</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span>(el % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>) acc.push(el.toString());
 <span class="hljs-keyword">return</span> acc;
}, []);
<span class="hljs-built_in">console</span>.log(num);
</code></pre>
<p>We can also do this though...</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>];
<span class="hljs-keyword">const</span> num = arr
    .filter(<span class="hljs-function"><span class="hljs-params">el</span> =&gt;</span> el % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>)
    .map(<span class="hljs-function"><span class="hljs-params">el</span> =&gt;</span> el.toString())
    .reverse()
<span class="hljs-built_in">console</span>.log(num);
</code></pre>
<p>This is just the surface of the power of reduce. You can do much more based on your needs. If you've more examples, feel free to drop those in comments.</p>
<p>Further Reading:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce</p>
]]></content:encoded></item><item><title><![CDATA[Learning Django Middleware by exploring CSRF.]]></title><description><![CDATA[Talking about how much people assume me to be experienced in django, I'm one of those guys who've never seriously thought about how django does specific stuffs and rather rely on it works kind of thoughts. I just simply make my own if I don't want to...]]></description><link>https://maheshchandraregmi.com.np/learning-django-middleware-by-exploring-csrf</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/learning-django-middleware-by-exploring-csrf</guid><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Fri, 21 May 2021 11:15:52 GMT</pubDate><content:encoded><![CDATA[<p>Talking about how much people assume me to be experienced in django, I'm one of those guys who've never seriously thought about how django does specific stuffs and rather rely on it works kind of thoughts. I just simply make my own if I don't want to hassle with django generics and mixins, or I spend 5second of my development time trying to search for it in docs ( thanks for the wonderful examples).</p>
<p>Recently, I had a software engineer interview, and one question that hit me was you've done django but have you written your own csrf (Cross Site Request Forgery) validator? I had written once in node when using with ejs, but I had never thought about how django does it... I answered the same.</p>
<h2 id="csrf">CSRF</h2>
<p>Cross Site Request Forgery refers when an attacker from another website can submit a form in my website. </p>
<p>Imagine  you have a form which allows user to delete his account when he hits a POST request to <code>/deleteprofile</code>.</p>
<p>Now, a third party website can make same form as yours, provide a better SEO and use ads campaign on facebook to make a form which will instead submit a deletion request to your backend.</p>
<p>This is a serious issue. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621590122197/h0ckMl5y6.png" alt="image.png" />
-Image from Portswigger</p>
<p>You need to validate that the request you've received is originated by you and authorized by you to be performed.</p>
<p>Read More About CSRF:
https://portswigger.net/web-security/csrf</p>
<p>One of the general solution to solve this issue is to use <code>csrf token</code>. Now, the token will be given by your backend to the webpage which is responsible to submit the form as a cookie.</p>
<p>And, the webpage will submit you the data including the <code>csrf token</code>. Now, you will validate if the submitted token is same as csrf token issued by your backend.</p>
<p>This cuts off all the attackers trying to request to your system from another system or trying to trick your users into submitting data unknowingly.</p>
<h2 id="how-django-handles-security">How Django handles security?</h2>
<p>If you didn't know django comes with pretty much all the middlewares required to secure your backend. If you want to be practical, just check the settings.py file in your recent django project and find a list called <code>MIDDLEWARE</code>.</p>
<pre><code class="lang-python"><span class="hljs-comment">#other code....</span>
MIDDLEWARE = [
    <span class="hljs-string">'django.middleware.security.SecurityMiddleware'</span>,
    <span class="hljs-string">'django.contrib.sessions.middleware.SessionMiddleware'</span>,
    <span class="hljs-string">'django.middleware.common.CommonMiddleware'</span>,
    <span class="hljs-string">'django.middleware.csrf.CsrfViewMiddleware'</span>, <span class="hljs-comment"># this is the one</span>
    <span class="hljs-string">'django.contrib.auth.middleware.AuthenticationMiddleware'</span>,
    <span class="hljs-string">'django.contrib.messages.middleware.MessageMiddleware'</span>,
    <span class="hljs-string">'django.middleware.clickjacking.XFrameOptionsMiddleware'</span>,
]
<span class="hljs-comment">#other code...</span>
</code></pre>
<h2 id="csrfviewmiddleware">CsrfViewMiddleware</h2>
<p>Let's get into the github repository of django and try to locate where the source of this middleware is located. <a target="_blank" href="https://github.com/django/django/blob/main/django/middleware/csrf.py">Open File in Github</a></p>
<h3 id="a-little-context-on-django-middlewares">A little Context on Django Middlewares.</h3>
<p>In django, a middleware is just a request interceptor which has some hooks associated with it. </p>
<p>If you have zero experience, have a <a target="_blank" href="https://docs.djangoproject.com/en/3.2/topics/http/middleware/">read here</a>.</p>
<p>Some hooks are mentioned below...</p>
<ul>
<li><strong>process_view()</strong> is called just before Django calls the view.</li>
<li><strong>process_request()</strong> is called just before Django parses the requst.</li>
</ul>
<p>Now, you're ready to go into this journey.</p>
<p>In django, a csrf token contains two part mask and actual token. Each part contains 32 characters consisting of letters and digits.</p>
<pre><code class="lang-python">CSRF_SECRET_LENGTH = <span class="hljs-number">32</span>
CSRF_TOKEN_LENGTH = <span class="hljs-number">2</span> * CSRF_SECRET_LENGTH
CSRF_ALLOWED_CHARS = string.ascii_letters + string.digits
</code></pre>
<p>There are couple of helper methods defined there which help us to create a token, mask token, unmask token and compare tokens...</p>
<p>For this purpose.</p>
<pre><code class="lang-python"> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_get_token</span>(<span class="hljs-params">self, request</span>):</span>
        <span class="hljs-keyword">if</span> settings.CSRF_USE_SESSIONS:
            <span class="hljs-comment">#not important for this context.</span>
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">try</span>:
                cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
            <span class="hljs-keyword">except</span> KeyError:
                <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
            csrf_token = _sanitize_token(cookie_token)
            <span class="hljs-keyword">if</span> csrf_token != cookie_token:
                request.csrf_cookie_needs_reset = <span class="hljs-literal">True</span>
            <span class="hljs-keyword">return</span> csrf_token
</code></pre>
<p>This method extracts the token from the cookies using the <code>CSRF_COOKIE_NAME</code> as defined in the settings.</p>
<p>Now, let's go into the lifecycle.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_request</span>(<span class="hljs-params">self, request</span>):</span>
        csrf_token = self._get_token(request)
        <span class="hljs-keyword">if</span> csrf_token <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
            <span class="hljs-comment"># Use same token next time.</span>
            request.META[<span class="hljs-string">'CSRF_COOKIE'</span>] = csrf_token
</code></pre>
<p>This hook utilizes the above helper method to extract the token and save it in <code>request.META</code>.</p>
<p>Now let's get into <code>process_view</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> getattr(request, <span class="hljs-string">'csrf_processing_done'</span>, <span class="hljs-literal">False</span>):
            <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
</code></pre>
<p>skipping checks if processing is already done.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> getattr(callback, <span class="hljs-string">'csrf_exempt'</span>, <span class="hljs-literal">False</span>):
            <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
</code></pre>
<p>skipping checks if csrf_exempt is on.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> request.method <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> (<span class="hljs-string">'GET'</span>, <span class="hljs-string">'HEAD'</span>, <span class="hljs-string">'OPTIONS'</span>, <span class="hljs-string">'TRACE'</span>):
    <span class="hljs-keyword">if</span> getattr(request, <span class="hljs-string">'_dont_enforce_csrf_checks'</span>, <span class="hljs-literal">False</span>):
         <span class="hljs-keyword">return</span> self._accept(request)
</code></pre>
<p>csrf token check is only done for put, patch, post and delete methods only. Also, it's worth nothing django doesn't accept post request without csrf tokens by default.</p>
<p>Then the check starts checking if the HTTP_REFERRER is valid or not.</p>
<pre><code class="lang-python">request_csrf_token = <span class="hljs-string">""</span>
<span class="hljs-keyword">if</span> request.method == <span class="hljs-string">"POST"</span>:
    <span class="hljs-keyword">try</span>:
           request_csrf_token = request.POST.get(<span class="hljs-string">'csrfmiddlewaretoken'</span>, <span class="hljs-string">''</span>)
     <span class="hljs-keyword">except</span> OSError:
            <span class="hljs-keyword">pass</span>
</code></pre>
<p>Now, we get the token sent by the user in the request.</p>
<p>And then the django checks the token with the issued token.</p>
<pre><code class="lang-python">request_csrf_token = _sanitize_token(request_csrf_token)
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> _compare_masked_tokens(request_csrf_token, csrf_token):
       <span class="hljs-keyword">return</span> self._reject(request, REASON_BAD_TOKEN)
</code></pre>
<p>Now, I guess this also explains to you about django middleware. A middleware essentially captures a request in middle, and does something with it and it's upto the middleware whether to forward to next middleware / view or just drop it.</p>
]]></content:encoded></item><item><title><![CDATA[Removing Sensitive Information from Git History]]></title><description><![CDATA[We all have gone through this problem once in our development career. We mistakenly have pushed sensitive info into github and we need to remove it. The sensitive info can be anything like a prod .env file or passwords hard-coded in the code.
Luckily...]]></description><link>https://maheshchandraregmi.com.np/removing-sensitive-information-from-git-history</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/removing-sensitive-information-from-git-history</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Wed, 12 May 2021 07:45:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620805471302/KsyUr-OCg.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We all have gone through this problem once in our development career. We mistakenly have pushed sensitive info into <code>github</code> and we need to remove it. The sensitive info can be anything like a prod <code>.env</code> file or passwords hard-coded in the code.</p>
<p>Luckily, it's pretty straight forward to remove that change from git history both from your local repository and remote repository.</p>
<p>For the demonstration, I've create a local git repository.</p>
<p>And populated with some fake git commits to demonstrate what you may actually do.</p>
<pre><code class="lang-bash">$ git <span class="hljs-built_in">log</span> --oneline
d5d9f70 (HEAD -&gt; main) some more changes to main
c05631b Added Password
ac547a8 Added Main File to Project
</code></pre>
<h2 id="editing-commit">Editing Commit</h2>
<p>Here, I have made clear using commit message to show that the commit with has <code>c05631b</code> adds sensitive information to our git history. Now, we need to remove that.</p>
<p>If you're having hard time finding which commit actually changed the password.  You can use the following git command...</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> -p fileName
</code></pre>
<p>Now, run <code>git rebase</code> using this commit hash to rebase our git history from that commit onwards.</p>
<pre><code class="lang-bash">$ git rebase -i c05631b
pick c05631b Added Password
pick d5d9f70 some more changes to main

<span class="hljs-comment"># Rebase ac547a8..d5d9f70 onto ac547a8 (2 commands)</span>
<span class="hljs-comment"># &lt;Hidden for Content Purpose&gt;</span>
</code></pre>
<p>Now, edit the text in the editor. We need to edit the commit which added password into the git history. So, I'll rewrite the first line as follows...</p>
<pre><code><span class="hljs-attribute">edit</span> c<span class="hljs-number">05631</span>b Added Password
<span class="hljs-attribute">pick</span> d<span class="hljs-number">5</span>d<span class="hljs-number">9</span>f<span class="hljs-number">70</span> some more changes to main

<span class="hljs-comment"># Rebase ac547a8..d5d9f70 onto ac547a8 (2 commands)</span>
</code></pre><p>Note the first line, I've replaced the pick with edit. Now, after saving and exiting the text editor, git will put me right into the staging area of that commit.</p>
<p>Now, edit your password file.
I will remove the password from <code>.env</code> file in this case.</p>
<p>And, I will add the changes into the commit using the given command.</p>
<pre><code>$ git <span class="hljs-keyword">commit</span> <span class="hljs-comment">--amend -a -m "Removed Sensitive Content"</span>
</code></pre><p>This will update the message in that commit and also the changed file.</p>
<p>Now, I will continue the rebase using the following command...</p>
<pre><code class="lang-bash">$ git rebase --<span class="hljs-built_in">continue</span>
</code></pre>
<p>Now, git will try and update the git history by updating that specific commit with our new change.. We may also get some conflicts in the process.</p>
<h2 id="dropping-commit">Dropping Commit</h2>
<p>This section is optional. If that's all you want you can go ahead and skip this section and follow the pushing into GitHub section.</p>
<p>Now, I will drop the same repository.</p>
<p>Use the git rebase command as before, but keep in mind the commit hash will be changed. So, again grab your commit hash using git log.</p>
<pre><code><span class="hljs-attribute">git</span> rebase -i ab<span class="hljs-number">5</span>edff
</code></pre><p>Now, change the pick line into drop which will actually remove the commit from git history.</p>
<p>Make sure you aren't dropping a repository which has other changes, it's generally bad idea to drop a commit. Or, it was a bad idea to create :D.</p>
<pre><code class="lang-bash">$ git rebase -i c05631b
drop c05631b Removed Secure Content
pick d5d9f70 some more changes to main

<span class="hljs-comment"># Rebase ac547a8..d5d9f70 onto ac547a8 (2 commands)</span>
<span class="hljs-comment"># &lt;Hidden for Content Purpose&gt;</span>
</code></pre>
<p>Now, after saving and exiting this file. 
git automatically removes your commit and updates the git history.</p>
<pre><code>$ git <span class="hljs-keyword">log</span> <span class="hljs-comment">--oneline</span>
<span class="hljs-number">9</span>f865e5 (HEAD -&gt; main) <span class="hljs-keyword">some</span> more changes <span class="hljs-keyword">to</span> main
ac547a8 Added Main File <span class="hljs-keyword">to</span> Project
</code></pre><p>YAY!</p>
<h2 id="pushing-to-github">Pushing To Github</h2>
<p>If this repository is already pushed into the github, it's always a bad news to rebase a remote repository, because it'll make conflict on all of your co-workers git history.</p>
<p>The command given below will do the job.</p>
<pre><code class="lang-bash">$ git push origin main --force
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Ownership in RUST - ELIF 5]]></title><description><![CDATA[Hello everyone ! A fellow rust learner here. It's been couple of weeks I've started learning rust. The most confusing part I found about rust as a programming language is the concept of ownership and borrowing.
We all are used to throwing a variable ...]]></description><link>https://maheshchandraregmi.com.np/ownership-in-rust-elif-5</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/ownership-in-rust-elif-5</guid><category><![CDATA[Rust]]></category><category><![CDATA[operating system]]></category><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Tue, 11 May 2021 16:06:04 GMT</pubDate><content:encoded><![CDATA[<p>Hello everyone ! A fellow rust learner here. It's been couple of weeks I've started learning rust. The most confusing part I found about rust as a programming language is the concept of ownership and borrowing.</p>
<p>We all are used to throwing a variable to a function using it later, or just re-assigning to multiple variables by making clones just because we can. But rust follows a strict practice here. </p>
<p>In order to make sure your code doesn't have any data race, it restricts a variable's value to be written only from one place. This also solves the problem of dangling pointers as rust has no garbage collector, it uses the variable scope to automatically clear the memory.</p>
<h2 id="ownership">Ownership</h2>
<p>In rust, every value has a variable which is called it's owner. And there can't be multiple owners at one time.  When you initialize a new variable with a value it's said to be the owner of the value.</p>
<pre><code class="lang-rust"><span class="hljs-keyword">let</span> name = <span class="hljs-string">"mahesh"</span>;
</code></pre>
<p>Here, <code>name</code> is the owner of the string literal <code>"mahesh"</code>. </p>
<pre><code class="lang-rust"><span class="hljs-keyword">let</span> name = <span class="hljs-string">"mahesh"</span>;
</code></pre>
<p>When you use this variable in another variable's assignment. The value is copied into another variable. Or, the variable is cloned. The two variable do not point to the same variable from memory's perspective.</p>
<p>This is because variables like integer, characters, booleans, raw strings implement the <code>Copy</code> trait. They require very less memory and can be copied easily to another. In other words, copying them is efficient enough for a computer.</p>
<p>But, this is not the case with structs or any other compound data types which are stored on heap.</p>
<pre><code class="lang-rust"><span class="hljs-meta">#[derive(Debug)]</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Age</span></span>{
    num: <span class="hljs-built_in">i32</span>
}
<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
   <span class="hljs-keyword">let</span> _name = Age { num: <span class="hljs-number">30</span>};
   <span class="hljs-keyword">let</span> _another = _name;
   <span class="hljs-built_in">println!</span>(<span class="hljs-string">"{:?}"</span>, _name);
}
</code></pre>
<p>In this case, the variable <code>_name</code> is a struct. This _struct declaration doesn't implement the <code>Copy</code> trait. So, whenever you reassign the variable, it's owner is changed. At the line <code>let _another = _name;</code>, the ownership of newly created struct is shifter from <code>_name</code> to <code>_another</code>. Now, rust won't let you access the variable _name because a variable can only have one owner at a time.</p>
<p>But, this is not the case if you use <code>#[derive(Copy)]</code>, it will create a brand new struct everytime you re-assign the variable if it implements the <code>Copy</code> trait.</p>
<pre><code>error[E0382]: borrow <span class="hljs-keyword">of</span> moved <span class="hljs-keyword">value</span>: `_name`
 <span class="hljs-comment">--&gt; src/main.rs:8:21</span>
  |
<span class="hljs-number">6</span> |    let _name = Age { num: <span class="hljs-number">30</span>};
  |        <span class="hljs-comment">----- move occurs because `_name` has type `Age`, which does not implement the `Copy` trait</span>
<span class="hljs-number">7</span> |    let _another = _name;
  |                   <span class="hljs-comment">----- value moved here</span>
<span class="hljs-number">8</span> |    println!("{:?}", _name);
  |                     ^^^^^ <span class="hljs-keyword">value</span> borrowed here <span class="hljs-keyword">after</span> <span class="hljs-keyword">move</span>
</code></pre><p>The rust compiler is also pretty much self explanatory on this matter.</p>
<p>To avoid this from happening, you have multiple one options. One is to derive <code>Copy</code> trait as mentioned before. Another option is to clone the variable. You can either write your own clone method or derive the predefined trait and use it.</p>
<p>But these two are not the trivial solution always. So, the solution is to use referencing.</p>
<h2 id="referencing">Referencing</h2>
<p>Rust allows you to create a read-only or mutable reference to a variable. This allows you to safely access the variable but remember there can never be multiple mutable reference of a variable at once. Rust borrows the same <code>&amp;</code> notation to create reference of a variable.</p>
<pre><code>   <span class="hljs-keyword">let</span> _name = <span class="hljs-type">Age</span> { num: <span class="hljs-number">30</span>};
   <span class="hljs-keyword">let</span> _another = &amp;_name;
   <span class="hljs-keyword">let</span> _other = &amp;_name;
   <span class="hljs-built_in">println</span>!(<span class="hljs-string">"{:?}"</span>, _name);
</code></pre><p>The snippet shown above runs completely fine because in this case we are creating reference of the variable <code>_name</code> and we're good to do it. Because remember, this won't create multiple data and since there isn't  a actual value stored at <code>_another</code>, there won't be issues like double-memory cleaning issue.</p>
<p>But, this isn't the case when you try to create multiple mutable references.</p>
<pre><code>   <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> _name = Age { num: <span class="hljs-number">30</span>};
   <span class="hljs-keyword">let</span> _another = &amp;<span class="hljs-keyword">mut</span> _name;
   <span class="hljs-keyword">let</span> _other = &amp;<span class="hljs-keyword">mut</span> _name;
   <span class="hljs-built_in">println!</span>(<span class="hljs-string">"{:?} {:?}"</span>, _another, _other);
</code></pre><p>In this snippet you'll get a error as follows...</p>
<pre><code>error[E0499]: cannot borrow `_name` <span class="hljs-keyword">as</span> mutable more than once at a time
 --&gt; src/main.rs:<span class="hljs-number">8</span>:<span class="hljs-number">17</span>
  |
<span class="hljs-number">7</span> |    <span class="hljs-keyword">let</span> _another = &amp;<span class="hljs-keyword">mut</span> _name;
  |                   ---------- first mutable borrow occurs here
<span class="hljs-number">8</span> |    <span class="hljs-keyword">let</span> _other = &amp;<span class="hljs-keyword">mut</span> _name;
  |                 ^^^^^^^^^^ second mutable borrow occurs here
<span class="hljs-number">9</span> |    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"{:?} {:?}"</span>, _another, _other);
  |                          -------- first borrow later used here
</code></pre><p>This helps you to avoid data race at compile time. </p>
<p>I'm just getting started with rust migrating from high level language. Would love to hear any suggestions, feedbacks. Cheers! </p>
]]></content:encoded></item><item><title><![CDATA[Efficient Background Processing in NodeJS with BullMQ — MP4 to HLS.]]></title><description><![CDATA[In one of our recent projects, we had to design a scalable distributed system to process incoming videos and serve those videos efficiently to large amount of concurrent users. Like netflix, but not complex from engineer perspective.
Two of the major...]]></description><link>https://maheshchandraregmi.com.np/efficient-background-processing-in-nodejs-with-bullmq-mp4-to-hls-6f12f1ad196d</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/efficient-background-processing-in-nodejs-with-bullmq-mp4-to-hls-6f12f1ad196d</guid><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Mon, 03 May 2021 11:31:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540456431/-ImK2ZOXj.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In one of our recent projects, we had to design a scalable distributed system to process incoming videos and serve those videos efficiently to large amount of concurrent users. Like netflix, but not complex from engineer perspective.</p>
<p>Two of the major concerns we had while designing the system was efficiently converting the video into HLS format, so that user can have better experience and the video adapts with change of the bandwidth, other concern is regarding tracking the watch time and recommending other videos to the user.</p>
<p>The second one is a lot easier because of prior experience of developers in our team with recommendation system on python and websockets for tracking everything the user does.</p>
<p>For converting the video into HLS format, we had a major hassle as this requires a lot of domain knowledge about video encoding and conversions.</p>
<p>Luckily, ffmpeg acted as a saviour for all of our issues. We could have used node-ffmpeg but we went with native ffmpeg in order to keep it simple, as we’re going distributed we may also have an extra endpoint layer of ffmpeg in aws to handle the video conversion in and out from AWS S3.</p>
<pre><code><span class="hljs-string">$</span> <span class="hljs-attr">ffmpeg -i filename.mp4 -codec:</span> <span class="hljs-string">copy</span> <span class="hljs-string">-start_number</span> <span class="hljs-number">0</span> <span class="hljs-string">-hls_time</span> <span class="hljs-number">10</span> <span class="hljs-string">-hls_list_size</span> <span class="hljs-number">0</span> <span class="hljs-string">-f</span> <span class="hljs-string">hls</span> <span class="hljs-string">filename.m3u8</span>
</code></pre><p>We used this script in order to convert a file from mp4 format to HLS.</p>
<p>Currently, we have a bit longer script which re-encodes the video into multiple resolutions for seamless and lag-free streaming experience.</p>
<p>In order to let this script to be executed, we needed a message broker which takes incoming video and consumes it to convert it to HLS.</p>
<p>For that problem, we used bull to act as message broker.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540450518/wYqmgi7c0.png" alt /></p>
<p>We created a queue at first called VideoQueue which will route our messages into the consumer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540452707/2xy-7B4qg.png" alt /></p>
<p>Then, we wrote a very simple consumer function which just encodes the raw video file. Keep in mind, if you’re planning to do the same, you must validate all the inputs. Don’t throw native packages randomly as the file may not be what you want and unsanitized may lead to RCE.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540454803/E_MMMJuC2.png" alt /></p>
<p>This is our internal video converter which uses the shell script in order to convert the file and save it into movies folder.</p>
<p>Bull is extremely easy to use and configure.</p>
<p>It just stores your message into redis and consumer pulls from it. We’ve had a pretty good response time and conversion status with it as of now. We’re currently experimenting other video conversion formats to serve best traffic under certain video bandwidth.</p>
<p>Thanks. Too busy these days. No time to write articles.</p>
]]></content:encoded></item><item><title><![CDATA[Clean Way to Work With JWT —]]></title><description><![CDATA[Working with JWT is a headache specially when you’re starting out building a stateless backend system.

Note: This is not an introduction to JWT ( JSON Web Tokens) or any tutorial to implement JWT from scratch.

In JWT, the token is the most importan...]]></description><link>https://maheshchandraregmi.com.np/clean-way-to-work-with-jwt-b94a5fed488e</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/clean-way-to-work-with-jwt-b94a5fed488e</guid><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Wed, 03 Mar 2021 07:55:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540473017/1EykNx14T.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Working with JWT is a headache specially when you’re starting out building a stateless backend system.</p>
<blockquote>
<p>Note: This is not an introduction to JWT ( JSON Web Tokens) or any tutorial to implement JWT from scratch.</p>
</blockquote>
<p>In JWT, the token is the most important piece of information to identify the user in the system. If user is able to tamper, see and modify the JWT by any means, then he/she’ll be able to perform identity theft with XSS / CSRF attacks when not secured properly.</p>
<p>Let’s try to approach this problem by whatever comes in mind.</p>
<p><strong>What if we tried to save the token in local storage and send it in header on every request?</strong></p>
<p>There are many things wrong with this approach, One of the many being user has complete access to localstorage CRUD operations in the browser with few lines of javascript. This is extremely vulnerable to XSS attacks.</p>
<p>If a potential attacker has access to local storage, he can perform whatever he desires while the backend recognizes him to be the <strong>JWT Stored User.</strong></p>
<p>And he hacker will have access forever, now what if user changes password what will you do?</p>
<p><strong>Store it in database.</strong></p>
<p>If you store the credentials in database and validate if the password has changed since the last token was issued, it’ll help you a little bit. But that’s not the point of JWT. The point of using Token Based Authentication like JWT is make sure the authentication system is maximum stateless as possible.</p>
<p>Let’s change the thought a little bit. What if the token expires after short time? And a new token is issued.</p>
<p><strong>What ? A user logs in every(short)time?</strong></p>
<p>No, let’s not do that way. It’s a terrible UX to login everytime. You can minimize UX such a terrible way just to make sure hacker doesn’t get access for long time.</p>
<p>Let’s use another token called refresh token which will stay with access token but have a greater expiry time. This works, now how will you make sure refresh token is used to refresh after access token is done (expired)?</p>
<p><strong>Expose two endpoints</strong></p>
<p>This works. But not for a long. A sensible hacker will request jwt forever and try to maximize his session as possible.</p>
<p><strong>Keep in mind, our storage of JWT problem is not solved yet.</strong></p>
<h2 id="covering-the-expiry-part"><strong>Covering the expiry part…</strong></h2>
<p>When you specify expiry time in jwt token, it won’t be valid token after the time has expired.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540462512/PAYF0BaSU.png" alt /></p>
<p>Now, the UX won’t be that bad and the token will keep on refreshing every time but how to make sure client / hacker doesn’t have reach to that token?</p>
<p><strong>Using Cookies</strong></p>
<p>What kind of cookies? If you store JWT in plain cookies, that’s how 90% of XSS attacks escalate to massive impact.</p>
<p><strong>Using HTTPOnly Cookies</strong></p>
<p>HTTP Only cookies are such kind of cookies which can’t be accessed and read from the client but will be stored on the client and passed on every request, which means the cookie works sort of like session but in a completely stateless manner.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540464751/FfZjAoPnY.png" alt /></p>
<p>The above code issues a two token which will be expired after 20m and 7days while the cookies can’t be read from the client.</p>
<p>This protects us from maximum attacks.</p>
<p><strong>Little Help to Developers</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540466999/jSxIsltxj.png" alt /></p>
<p>This is how we can write a middleware to make sure, the token is validated and try to refresh the token if there’s any.</p>
<p>Make sure, your CORS enables frontend to work with HTTPOnly Cookies by following…</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540469265/HpAcCsazd.png" alt /></p>
<p>Keep in mind, origin can’t be wildcard when credentials is true..</p>
<p>You can login in this way…</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540471312/pXlAaOBMx.png" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Hand-On — Containerizing Development Environment with Visual Studio Code]]></title><description><![CDATA[The Problem
I was having this problem since few months and I guess most of you are having the same issues.
Do you do development of multiple languages on your laptop and have trouble managing all the environments and dependencies of the projects?
Thi...]]></description><link>https://maheshchandraregmi.com.np/hand-on-containerizing-development-environment-with-visual-studio-code-16c127d11068</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/hand-on-containerizing-development-environment-with-visual-studio-code-16c127d11068</guid><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Tue, 16 Feb 2021 06:39:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540487935/pl1KzRbBK.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The Problem</p>
<p>I was having this problem since few months and I guess most of you are having the same issues.</p>
<p>Do you do development of multiple languages on your laptop and have trouble managing all the environments and dependencies of the projects?</p>
<p>This is one of the biggest burden in my current development environment, specially with slow HDD read/write speed.</p>
<p>Just now, I had issues installing the graphics library files for my development environment as Pillow in python used another version and NodeJS used another version. Updating any of them would break another.</p>
<p>It would be lot better, if I could isolate my programming environment but I can’t run a whole virtual machine just to have a isolation.</p>
<p>I mean, I don’t need a new OS, I just want to isolate my development programs, tools and codebases. Another benefit it comes is that if you stop working in any of the projects in golang, and you can remove the whole development environment with just some commands, and you’re good to go.</p>
<p>Isn’t that already convincing enough to try containerizing your development workflow?</p>
<h2 id="container">Container</h2>
<blockquote>
<p>A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.</p>
</blockquote>
<p>What a container does is, it comes as a software but contains everything it depends upon. Like if a script requires a example.so linker files and a whole g++ installed to run, a container can include all of those and still remain lightweight than you expect!</p>
<p>This is all the magic of linux namespaces and cgroups. The concept of isolation of processes was thought long back then and kept in linux.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540478762/W0ek4a1_D.png" alt /></p>
<p>So, if you’re running a virtual machine, then it runs on top of a hypervisor such as virtualbox, hyper-v, vmware, but docker containers run on the same host, but do not share the same PID list and are isolated from each other.</p>
<p>Keep in mind, docker container are also built secure and has minimal security concerns to think of if you configure it properly.</p>
<p>So, docker is just a platform which is used to control the containers effectively.</p>
<p>Or, quoting from the wiki:</p>
<blockquote>
<p>Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers.</p>
</blockquote>
<p>You can research further about docker and containers.</p>
<p>So, when you convert your whole development environment inside a docker container, it’s totally isolated from the host operating system and also can be managed as a whole from the host operating system, or via docker cli.</p>
<h2 id="solution">Solution</h2>
<p>I won’t cover installing docker in this article, but you can look it up here.
Installing Docker :<a target="_blank" href="https://docs.docker.com/get-docker/">https://docs.docker.com/get-docker/</a></p>
<p>So, in order to convert your visual studio code setup into docker container. the first you need is to choose an docker image to run.</p>
<p>Keep in mind, docker images are the whole software shipped with dependencies which can run isolatedly forming containers.</p>
<p>The most common one to use is ubuntu (if you prefer a big community) or archlinux (if you prefer lightweight)</p>
<pre><code><span class="hljs-comment">#if you want to run ubuntu, execute this after installing docker.</span>
<span class="hljs-attribute">docker</span> pull ubuntu:<span class="hljs-number">20</span>.<span class="hljs-number">04</span>
<span class="hljs-comment">#if you want to run arch, execute this after installing docker.</span>
<span class="hljs-attribute">docker</span> pull archlinux
</code></pre><p>After you’ve pulled the images for your development environment, we’ll use a volume so it’ll be easier for you to share files, to and from the container.</p>
<pre><code><span class="hljs-comment">#For ubuntu,</span>
<span class="hljs-attribute">docker</span> run -d -it --name ubuntu-dev -v ~/my_files:/my_files ubuntu:<span class="hljs-number">20</span>.<span class="hljs-number">04</span> /bin/sh <span class="hljs-comment"># or /bin/bash</span>

<span class="hljs-comment">#For arch,</span>
docker run -d -it --name arch-dev -v ~/my_files:/my_files archlinux /bin/sh <span class="hljs-comment"># or /bin/bash</span>
</code></pre><p>Now, you can check if your container is running using docker container ps</p>
<pre><code><span class="hljs-attribute">CONTAINER</span> ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
<span class="hljs-attribute">84bc37ed215b</span>   ubuntu:<span class="hljs-number">20</span>.<span class="hljs-number">04</span>   <span class="hljs-string">"/bin/bash"</span>   <span class="hljs-number">54</span> minutes ago   Up <span class="hljs-number">44</span> minutes             ubuntu-machine
</code></pre><p>The output should be similar to above one.</p>
<p>Now, you can open vscode and install remote pack extensions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540481086/L8kqtNyjV.png" alt /></p>
<p>Install this extension pack, if you don’t have already which will allow you to setup vscode remotely in a container.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540482995/GCFjEJsec.png" alt /></p>
<p>Now, you’ll see your container listed here. Just click on it and vscode will prepare a development environment in the container and make it ready to start coding.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540485318/ZGh0JQ-ob.png" alt /></p>
<p>Now, you can install all your compilers, interpreters and everything using the provided bash via package managers.</p>
<p>When you need to remove the development environment just remove the container and you’re good to go :)</p>
]]></content:encoded></item><item><title><![CDATA[Automatic Type Conversion in Runtime | Python]]></title><description><![CDATA[Hi. I am back with an exciting topic in python.
How many times you have come across functions which automatically convert your values to required types in runtime?
For e.g. In Django whenever you define your types like this in route definitions the U...]]></description><link>https://maheshchandraregmi.com.np/automatic-type-conversion-in-runtime-python-3e46b97062cb</link><guid isPermaLink="true">https://maheshchandraregmi.com.np/automatic-type-conversion-in-runtime-python-3e46b97062cb</guid><dc:creator><![CDATA[Har Har Mahadev!]]></dc:creator><pubDate>Wed, 02 Dec 2020 12:33:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621540495409/drwrAVZUq.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi. I am back with an exciting topic in python.</p>
<p>How many times you have come across functions which automatically convert your values to required types in runtime?</p>
<p>For e.g. In Django whenever you define your types like this in route definitions the URL parameters are automatically parsed inside of your function.</p>
<pre><code class="lang-python">urlpatterns = [

path(<span class="hljs-string">"/&lt;str:slug&gt;"</span>, someRandomView, name=<span class="hljs-string">"home"</span>),
path(<span class="hljs-string">"/&lt;int:pk&gt;"</span>, someRandomProfile, name=<span class="hljs-string">"home_profile"</span>)

]
</code></pre>
<p>So whenever you define your views, your data types are automatically converted to the required data type.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">someRandomView</span>(<span class="hljs-params">slug</span>):</span>
  ...

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">someRandomProfile</span>(<span class="hljs-params">pk</span>):</span>
  ...
</code></pre>
<p>This offers a huge convenience in your application by automatically converting your type as per your function or something hints the function wants to achieve.</p>
<p>Similar behavior is achieved in fast API.</p>
<p>Let’s define a simple function.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getAge</span>(<span class="hljs-params">age, name</span>):</span>
    print( <span class="hljs-string">f" <span class="hljs-subst">{age}</span> : <span class="hljs-subst">{type(age)}</span> , <span class="hljs-subst">{name}</span> : <span class="hljs-subst">{type(name)}</span> "</span> )
</code></pre>
<p>You can see our types are nowhere defined in this piece of code. But, we can guess the user wants to age as an int variable and name as an str variable ( most probably). But python doesn’t work that way. You can call that function with any variable you want.</p>
<p>It would be a lot better if your code automatically gave the developer some idea about data types.</p>
<p>Let’s refactor that piece of code a little bit.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getAge</span>(<span class="hljs-params">age: int, name: str</span>):</span>
    print( <span class="hljs-string">f" <span class="hljs-subst">{age}</span> : <span class="hljs-subst">{type(age)}</span> , <span class="hljs-subst">{name}</span> : <span class="hljs-subst">{type(name)}</span> "</span> )
</code></pre>
<p>Now, this code is a lot cleaner than your previous code. But, we still have the same problem but it aids a little bit. Your text editor may flag out wrong parameter types if you’re using some linters or running on mypy.</p>
<p>But, what we wanted to achieve is to make automatic type conversions in runtime. So, whenever you call the function, your arguments are automatically parsed to be converted into required data types.</p>
<p>Let’s try writing a decorator to print what exactly we can extract out of the function definition.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Callable

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator</span>(<span class="hljs-params">func: Callable</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_func</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        print(kwargs, func.__annotations__)
        func(*args, **kwargs)

    <span class="hljs-keyword">return</span> inner_func


<span class="hljs-meta">@decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getAge</span>(<span class="hljs-params">age: int, name: str</span>):</span>
    print( <span class="hljs-string">f" <span class="hljs-subst">{age}</span> : <span class="hljs-subst">{type(age)}</span> , <span class="hljs-subst">{name}</span> : <span class="hljs-subst">{type(name)}</span> "</span> )
</code></pre>
<p>When we call the function using getAge(age=12,name=”Mahesh”), this is the output we get.</p>
<pre><code>kwargs: {<span class="hljs-string">'age'</span>: <span class="hljs-number">12</span>, <span class="hljs-string">'name'</span>: <span class="hljs-string">'mahesh'</span>}
__annotations__ : {<span class="hljs-string">'age'</span>: &lt;<span class="hljs-keyword">class</span> <span class="hljs-string">'int'</span>&gt;, <span class="hljs-string">'name'</span>: &lt;<span class="hljs-keyword">class</span> <span class="hljs-string">'str'</span>&gt;}
</code></pre><p>Now, this makes sense. Your annotations are extracted from your function in the compile time of the function and not changed by your arguments.</p>
<p>So, to achieve automatic type conversion on the function, we can write all the code to convert types as mentioned in the function annotations.</p>
<pre><code class="lang-python"><span class="hljs-comment">#/bin/env python</span>
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Callable
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator</span>(<span class="hljs-params">function: Callable</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inner_function</span>(<span class="hljs-params">*args, **kwargs</span>):</span>

        newKwargs = {}

        <span class="hljs-keyword">for</span> argName, typeName <span class="hljs-keyword">in</span> function.__annotations__.items():
            <span class="hljs-keyword">if</span> typeName <span class="hljs-keyword">is</span> int:
                intVar = int(kwargs[argName])
                newKwargs[argName] = intVar
            <span class="hljs-keyword">elif</span> typeName <span class="hljs-keyword">is</span> str:
                strVar = str(kwargs[argName])
                newKwargs[argName] = strVar
        function(*args, **newKwargs)

    <span class="hljs-keyword">return</span> inner_function


<span class="hljs-meta">@decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">getAge</span>(<span class="hljs-params">age: int, name: str</span>):</span>
    print( <span class="hljs-string">f" <span class="hljs-subst">{age}</span> : <span class="hljs-subst">{type(age)}</span> , <span class="hljs-subst">{name}</span> : <span class="hljs-subst">{type(name)}</span> "</span> )
</code></pre>
<p>And boom, this works!</p>
<p>Whenever you call the function, it gets automatically converted to the required type and if it fails, it will throw the value error.</p>
]]></content:encoded></item></channel></rss>