<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Watcharin(start)</title>
    <description>The latest articles on Forem by Watcharin(start) (@startpher).</description>
    <link>https://forem.com/startpher</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F718323%2Faea40ef3-aa87-4c55-bc80-ec0d15404403.png</url>
      <title>Forem: Watcharin(start)</title>
      <link>https://forem.com/startpher</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/startpher"/>
    <language>en</language>
    <item>
      <title>🐣Why idempotence was important to DevOps</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Sat, 04 May 2024 19:52:50 +0000</pubDate>
      <link>https://forem.com/startpher/why-idempotence-was-important-to-devops-2jn3</link>
      <guid>https://forem.com/startpher/why-idempotence-was-important-to-devops-2jn3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🚀 I just need to improving myself in everyday and sharing my learned for everyone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hi reader 👋🏼, The adoption of &lt;code&gt;DevOps practices&lt;/code&gt; has become increasingly prevalent within development team today. Many organizations have integrated the role of a DevOps engineer into their teams or have expanded the responsibilities of existing team members to encompass &lt;code&gt;DevOps methodologies&lt;/code&gt; , akin to the Agile framework. In these scenarios, development team either recruit dedicated individuals to drive &lt;code&gt;DevOps processes&lt;/code&gt; or distribute these responsibilities across the job description of all team members. This approach acknowledges that &lt;code&gt;DevOps&lt;/code&gt;  aims to enhance productivity by optimizing the workflows and responsibilities associated with each role. 👨🏻‍💻🧑‍💻👩🏻‍💻&lt;/p&gt;

&lt;p&gt;📜 A crucial aspect of &lt;strong&gt;DevOps&lt;/strong&gt; is the application of the &lt;code&gt;Idempotence principle&lt;/code&gt; (alternatively referred to as idempotent or idempotency) in coding practices. This concept ensures that &lt;code&gt;Infrastructure&lt;/code&gt; can be consistently managed and controlled through code. Fundamentally, it builds upon the previously established concept of &lt;code&gt;Infrastructure as Code&lt;/code&gt; , which is widely implemented using tools such as Ansible, Terraform, Puppet, and other.😺&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Idempotence
&lt;/h2&gt;

&lt;p&gt;🐈 It’s a important principle in IaC or several programming, particularly in the context of operations or functional that modify state or data. An operation is considered idempotent if it can be applied multiple times without changing the result beyond the initial application.&lt;/p&gt;

&lt;p&gt;In programming, idempotence is desirable for several reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Reliability&lt;/strong&gt;: Idempotent operations can be safely retried or repeat without causing unintended side effects or data corruption. This is especially crucial in distributed systems, where network failures or other issues may cause requests to be duplicated or retried.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt;: Idempotent operations ensure that the final state of the system is consistent and predictable, regardless of how many times the operation was performed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: Idempotent operations are easier to reason about and debug since their behavior is deterministic and predictable.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The example use case of Idempotence
&lt;/h2&gt;

&lt;p&gt;Idempotence is particularly valuable in scenarios like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;RESTful APIs&lt;/strong&gt;: In this context is about HTTP methods like GET, PUT, DELETE, and HEAD — are designed to be idempotent. For instance, multiple identical PUT requests should have the same effect as a single PUT request, ensuring data integrity. Furthermore, multiple request DELETE should have only first request was completed, hence other requests will returned the previous state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database operations&lt;/strong&gt;: Operations like UPDATE or DELETE queries that target specific rows based on a unique identifier (e.g., a primary key) are often idempotent. Executing the same query multiple times will result in the same final state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: Caching invalidation or cache warming operations are typically idempotent. Repeated cache invalidation requests for the same key will effectively invalidate the cache entry once, ensuring consistency. Moreover, cache invalidation is the process of invalidating cache by removing data from system when those data is no longer valid or useful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure as Code&lt;/strong&gt;: Tools like Ansible, Terraform, and Puppet often rely on idempotent operations to manage infrastructure resources. Running the same configuration for multiple times should result in the desired state without unintended modifications. Example, you executing the Terraform to provisioning instances more than one time with the same configuration. You could saw the desired state of your resources without modification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data processing&lt;/strong&gt;: The operations as deduplication, normalization, or transformation of data can be designed to be idempotent, ensuring that repeated applications produce the same output.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s significant to note that idempotence is a property of an operation, nor necessarily of an entire system or application. In practice, developers usually strive to make critical operations idempotent to improvement reliability, consistency, and simplicity in the software operational. 🐈‍⬛&lt;/p&gt;

&lt;h2&gt;
  
  
  The example Golang code
&lt;/h2&gt;

&lt;p&gt;The provided example code written in &lt;code&gt;Golang&lt;/code&gt; illustrates the practical implementation of the idempotent concept within the context of a basic data management application.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Person&lt;/code&gt; struct is defined to represent individual records, with the &lt;code&gt;Email&lt;/code&gt; field serving as the unique identifier. Two simple functions are implemented:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For inserting new &lt;code&gt;Person&lt;/code&gt; records into an in-memory database.&lt;/li&gt;
&lt;li&gt;For retrieving all existing records.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Let’s writing a code
&lt;/h3&gt;

&lt;p&gt;Beginning with define a &lt;code&gt;Person&lt;/code&gt; struct&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define a new schema of in-memory database with &lt;code&gt;init()&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create the DB schema&lt;/span&gt;
    &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DBSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Tables&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Indexes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IndexSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IndexSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Unique&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Indexer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringFieldIndex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Email"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IndexSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Unique&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Indexer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntFieldIndex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Age"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;

    &lt;span class="c"&gt;// Create a new data base&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMemDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an Insert function for built transaction into database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;InsertDataWithID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create a write transaction&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Txn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Insert the new person&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Inserting ID: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Commit the transaction&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Create read-only transaction&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Txn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Abort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;InsertMultipleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;InsertDataWithID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a retrieving all existing data from database and print out to console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ListAllValues&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Txn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// List all the people&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All the people:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[+]  %s | %s | %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define &lt;code&gt;main()&lt;/code&gt; function to call both functions as insert and then retrieve them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c"&gt;// Insert some people&lt;/span&gt;
    &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"joe@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"lucy@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Lucy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;35&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"joe@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Joey"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"tariq@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tariq"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"dorothy@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Dorothy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"joely@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;35&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;InsertMultipleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ListAllValues&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see fully code in one file below. you can see my test data that have a duplicated  index as 1 and 3.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// main.go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/hashicorp/go-memdb"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;   &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MemDB&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create the DB schema&lt;/span&gt;
    &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DBSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Tables&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Indexes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IndexSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IndexSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Unique&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Indexer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringFieldIndex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Email"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IndexSchema&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Unique&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;Indexer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntFieldIndex&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Age"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;

    &lt;span class="c"&gt;// Create a new data base&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;memdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewMemDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;InsertDataWithID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create a write transaction&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Txn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Insert the new person&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Inserting ID: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Commit the transaction&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Create read-only transaction&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Txn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Abort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;InsertMultipleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;InsertDataWithID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ListAllValues&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Txn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// List all the people&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All the people:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[+]  %s | %s | %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c"&gt;// Insert some people&lt;/span&gt;
    &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"joe@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"lucy@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Lucy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;35&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"joe@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Joey"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;26&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"tariq@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tariq"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"dorothy@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Dorothy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"joely@aol.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;35&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;InsertMultipleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ListAllValues&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;When you executed the above code, you will see this result. you can see function was inserted the duplicated data and update that row with a new information, which you will see from last function. It isn’t applied idempotent concept.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Inserting ID: joe@aol.com
Inserting ID: lucy@aol.com
Inserting ID: joe@aol.com
Inserting ID: tariq@aol.com
Inserting ID: dorothy@aol.com
Inserting ID: joely@aol.com
All the people:
[+]  Dorothy | dorothy@aol.com | 53
[+]  Joey | joe@aol.com | 26
[+]  Joe | joely@aol.com | 35
[+]  Lucy | lucy@aol.com | 35
[+]  Tariq | tariq@aol.com | 21
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Let’s see how can apply idempotence
&lt;/h3&gt;

&lt;p&gt;For implement the idempotence, I should add code for query as verify existing data before insert or update data.&lt;/p&gt;

&lt;p&gt;Firstly, I just create new function to retrieving existing data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GetDataByID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create a read-only transaction&lt;/span&gt;
    &lt;span class="n"&gt;txn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Txn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;txn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;First&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[-] Not found %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I will update the &lt;code&gt;InsertMultipleData&lt;/code&gt; function to get data that will skipped if it found.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;InsertIdempotentData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;existed&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GetDataByID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;existed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Skipping insertion for ID: %s (already exists)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Insert the new person&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;InsertDataWithID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you replace the previous function call from &lt;code&gt;InsertMultipleData&lt;/code&gt;  to &lt;code&gt;InsertIdempotentData&lt;/code&gt; , you could see result below. You can found 1 logging message that skipped insert operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[-] Not found joe@aol.comInserting ID: joe@aol.com
[-] Not found lucy@aol.comInserting ID: lucy@aol.com
Skipping insertion for ID: joe@aol.com (already exists)
[-] Not found tariq@aol.comInserting ID: tariq@aol.com
[-] Not found dorothy@aol.comInserting ID: dorothy@aol.com
[-] Not found joely@aol.comInserting ID: joely@aol.com
All the people:
[+]  Dorothy | dorothy@aol.com | 53
[+]  Joe | joe@aol.com | 30
[+]  Joe | joely@aol.com | 35
[+]  Lucy | lucy@aol.com | 35
[+]  Tariq | tariq@aol.com | 21
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;🐯 Idempotence is an important concept in programming, particularly when dealing with operations that modify state or data. An operation is considered idempotent if it can be applied multiple times without changing the result beyond the initial application. Idempotent operations are desirable because they enhance reliability, consistency, and simplicity in software designs. They ensure that the final state remains predictable and free from unintended side effects or data corruption, even if the operation is retried or repeated due to failures or other issues. 👻&lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
      <category>idempotent</category>
      <category>coding</category>
    </item>
    <item>
      <title>Why we should provide standard for IaC on our team</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Mon, 25 Dec 2023 05:07:37 +0000</pubDate>
      <link>https://forem.com/startpher/why-we-should-provide-standard-for-iac-on-our-team-1hb1</link>
      <guid>https://forem.com/startpher/why-we-should-provide-standard-for-iac-on-our-team-1hb1</guid>
      <description>&lt;p&gt;😺 Today, let's delve into a common challenge faced by &lt;strong&gt;non-developers&lt;/strong&gt; who take on roles that mimic those of actual &lt;strong&gt;developers&lt;/strong&gt;, such as &lt;code&gt;DevOps Engineers&lt;/code&gt;, &lt;code&gt;Cloud Engineers&lt;/code&gt;, &lt;code&gt;Automated QA&lt;/code&gt;, and others. As we navigate through the intricate landscape of the modern tech world, we encounter numerous like &lt;strong&gt;application design patterns&lt;/strong&gt;, &lt;strong&gt;frameworks&lt;/strong&gt;, and &lt;strong&gt;architectural designs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this dynamic environment, the ability to craft applications and share them within your team or with others becomes a pivotal aspect. The cohesion achieved by adopting shared standards and frameworks ensures that your &lt;strong&gt;ideas&lt;/strong&gt;, &lt;strong&gt;designs&lt;/strong&gt;, and &lt;strong&gt;functionalities&lt;/strong&gt; are comprehensible to everyone involved. This shared foundation not only facilitates mutual understanding but also provides a guiding framework and utility tools that enhance overall performance.&lt;/p&gt;

&lt;p&gt;By adhering to a common working standard, you not only streamline communication within your team but also benefit from the efficiency and support offered by standardized frameworks. This collaborative approach not only fosters understanding but also contributes to a more efficient and high-performing work environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RsTdm9Ep--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9p2ern3xq4g44ixa3iu1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RsTdm9Ep--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9p2ern3xq4g44ixa3iu1.jpg" alt="Team collaboration" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understand several software design principle
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📄 &lt;em&gt;Understand about several design pattern and framework for programming languages.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🧑🏼‍💻 Software design principles are fundamental guidelines that software developers follow to achieve high-quality software design. The principles provide a framework for making design decisions that lead to more maintainable, scalable, and robust software.&lt;/p&gt;

&lt;p&gt;Example are here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;DRY (Don't Repeat Yourself)&lt;/strong&gt;: This principle emphasizes the importance of reducing repetition in code. Every piece of knowledge or logic should be unique and single-represented in a system. This reduces the risk of inconsistencies and makes code more maintainable. Read more &lt;a href="https://thevaluable.dev/dry-principle-cost-benefit-example/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KISS (Keep It Simple, Stupid)&lt;/strong&gt;: This principle suggests that systems work better if they are kept simple rather than made complex. Simplicity should be a key goal in design, and unnecessary complexity should be avoided. Read more &lt;a href="https://www.freecodecamp.org/news/keep-it-simple-stupid-how-to-use-the-kiss-principle-in-design/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From the principle of designs, it provide us to Design patterns and Frameworks that we actually do on our application. It just a common standard for our team to collaborative in the same project that we work together. &lt;/p&gt;

&lt;h2&gt;
  
  
  The IaC programmings
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📄 &lt;em&gt;Definition of IaC, What is purpose to use programming to control infrastructure.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔨 The &lt;strong&gt;Infrastructure as Code&lt;/strong&gt;(also IaC) is a key concept in modern software deployment and operation, fundamentally transforming infrastructure managed in IT environment via readable documentation for developer and machine. We’re trying to reduce the manually setting up and configuring resources. We’re use code to automate the process, which can be more consistent and error-free than manual process.&lt;/p&gt;

&lt;p&gt;Example tools of IaC.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform&lt;/strong&gt;: An open-source tool that uses a declarative configuration language for building, changing, and versioning infrastructure safely and efficiently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ansible&lt;/strong&gt;: An open-source tool that uses YAML for defining infrastructure configurations, primarily for automation of application deployment and intra-service orchestration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Relationship between IaC and several programming languages
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📄 &lt;em&gt;Said about same purpose and different on both&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🤝 We must experience about programming and infrastructure before apply the IaC. The IaC can be implemented using standard programming language like Python, Javascript, Golang or specialized domain-specific language(DSLs). The DSLs are designed specifically for defining and managing infrastructure resources like &lt;strong&gt;Hashicorp’s Terraform&lt;/strong&gt; and &lt;strong&gt;AWS Cloudformation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;📜 In the IaC, script or code are written to automatically set up and manage infrastructure. This code act as a blueprint for our resources. You can be executed to deploy, manage and destroy the infrastructure. We can integrates closely modern deployment practices as the same common programming like CI and CD.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to adopt development practices to IaC
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📄 &lt;em&gt;Talk about current tools and a community experience to improve IaC writing.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;⚒️ Adoption the software development principle in IaC is essential for maintaining the quality, efficiency, and reliability of our the source code to infrastructure automation. Here are several key programming principle and practices that can be effectively applied to IaC.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use &lt;strong&gt;version control&lt;/strong&gt;: Just like code, our infrastructure configuration should be stored in a version control system like Git. This practices allow tracking changes, collaborate with team and maintaining a history of our infrastructure state.&lt;/li&gt;
&lt;li&gt;Write &lt;strong&gt;modularity&lt;/strong&gt;: Write modular script, just as with traditional programming, break down your code into smaller, reusable modules can make them more manageable, and understandable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DRY principle(Don’t Repeat Yourself)&lt;/strong&gt;: Avoid duplication in your code. You can use templates, modules, or function to reuse code as most as possible, which makes it easier to manage and reduces the risk of error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code review&lt;/strong&gt;: We must implement code review process to IaC, just as you would for code. This principle encourages collaboration, improve code quality, and help in sharing knowledge among team member.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;automate testing&lt;/strong&gt;: Apply automate testing into your IaC. You can implement tools and frameworks to IaC script to ensure they perform as expected before deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;: Write the document of IaC script and configurations. Good documentation helps in understanding the purpose and function of your infrastructure, especially in complex environment.&lt;/li&gt;
&lt;li&gt;Keep it &lt;strong&gt;idempotency&lt;/strong&gt;: Ensure your script is idempotent, meaning running your script multiple times in the same environment result in the same state, without unintended side effects. This is crucial for reliability and predictability in automated environments.&lt;/li&gt;
&lt;li&gt;Apply &lt;strong&gt;security practices&lt;/strong&gt;: Most important to embedded the security practice on your IaC development process. This includes using secure access credentials, encrypting sensitive data, and should follow the principle of least privilege.&lt;/li&gt;
&lt;li&gt;Often &lt;strong&gt;refactoring&lt;/strong&gt;: Regularly refactor your IaC code for improvements and optimizations, similar to how you would refactor application code for better performance, readability, and maintainability.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By adopting these practices, team can ensure that their IaC approach is as robust, efficient, and maintainable as their software development process. &lt;/p&gt;

&lt;h2&gt;
  
  
  Example guideline to contribute IaC
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📄 &lt;em&gt;Show my standard to writing Terraform and Ansible&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can apply the previous practices into your IaC code and see what happen in your work. I can sharing some guideline to initial your IaC project here.&lt;/p&gt;

&lt;p&gt;For the &lt;strong&gt;Hashicorp’s Terraform&lt;/strong&gt;: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You might to create a new repository for versioning your script. You can create a folder structure in different purpose like

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;components&lt;/code&gt; to store your reusable and maintainable for script in consistent modules.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deployments&lt;/code&gt; to store your variable files that contain each environment configurations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;modules&lt;/code&gt; in optional to download and freeze external Terraform’s module for your environments.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;You can integrates automation plugins for verify syntax, credentials leak, and missing fields. Use third party tools like &lt;strong&gt;Terrasec&lt;/strong&gt;, &lt;strong&gt;TFlint&lt;/strong&gt;, and other.&lt;/li&gt;
&lt;li&gt;For documentation, you can use &lt;code&gt;terraform-docs&lt;/code&gt; for automate provision code spec when you write a description in your scripts.&lt;/li&gt;
&lt;li&gt;You can integrates your process with CI/CD pipeline for Jenkins, Github-action, and other platforms.&lt;/li&gt;
&lt;li&gt;For integration testing your script, you can use &lt;code&gt;Grantwork’s Terratest&lt;/code&gt; to verify your actually provisioning resources.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can see my example terraform code for initialize from &lt;a href="https://github.com/StartloJ/terraform-initial"&gt;Github repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📄 &lt;em&gt;Recap all topics and drop some question to audiences.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🧳 In our journey towards modernizing infrastructure management, we have embraced to use  modern technology for provisioning, managing, and maintaining infrastructure. This is achieved through programming languages and domain-specific languages(DSLs). By writing code and script, we’re revolutionizing the way we handle infrastructure.&lt;/p&gt;

&lt;p&gt;The purpose of this is to establish standard practices for our team in crafting code that enhances collaboration, readability, and maintainability. This adoption will not only streamline our development processes but also significantly improve the quality of code.&lt;/p&gt;

</description>
      <category>iac</category>
      <category>devops</category>
      <category>terraform</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Lambda parameter from Secret Manager🤫</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Sat, 19 Aug 2023 13:54:25 +0000</pubDate>
      <link>https://forem.com/startpher/lambda-parameter-from-secret-manager-3pjo</link>
      <guid>https://forem.com/startpher/lambda-parameter-from-secret-manager-3pjo</guid>
      <description>&lt;p&gt;Hey everyone, I'm back and ready to dive into some Serverless func with AWS Lambda. Today, I've set myself a cool goal: I want to figure out how to use a Lambda function to grab a secret credential from AWS Secret Manager, you know, the stuff that's locked up tight by AWS KMS service. I'm all about learning how Lambda can smoothly handle secrets from Secret Manager and whatever other secret stashes are out there.&lt;/p&gt;

&lt;p&gt;Alright, check it out. This lab is hooking me up with some sweet Golang code. It's like magic – this code can summon that parameter from Secret Manager and stash it in Lambda’s memory, all sorted out by the code itself. Talk about slick, right? So, here's to cracking open the door to the secrets realm, and getting cozy with Lambda's skills and the hidden treasures they can unlock. Let's rock this journey! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Required Golang library
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://github.com/aws/aws-lambda-go/lambda"&gt;github.com/aws/aws-lambda-go/lambda&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://github.com/aws/aws-secretsmanager-caching-go/secretcache"&gt;github.com/aws/aws-secretsmanager-caching-go/secretcache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;errors&lt;/li&gt;
&lt;li&gt;log&lt;/li&gt;
&lt;li&gt;os&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Coding
&lt;/h2&gt;

&lt;p&gt;Create a new Golang project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init &lt;span class="nv"&gt;$YOUR_PROJECT_NAME&lt;/span&gt;
&lt;span class="c"&gt;# Example&lt;/span&gt;
go mod init lamda-secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s start with first function to ask Lambda handle it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Parameter in Start(...) is func name to handled&lt;/span&gt;
    &lt;span class="n"&gt;lambda&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ExportSecret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a function to export your secret value&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ExportSecret&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Define new variable for cache object&lt;/span&gt;
    &lt;span class="n"&gt;sc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;secretcache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Get a result from getter function and logged it&lt;/span&gt;
    &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GetterSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"We have a secret word is %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a function that get secret from Secret Manager API into cache memory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GetterSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;secretcache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cache&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Request secret from SecretManager API with Secret ID from ENV&lt;/span&gt;
    &lt;span class="n"&gt;secr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetSecretString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SECRET_WORD_ID"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Can't get you secret"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;secr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build and upload them to S3 bucket&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BINARY_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"lsc"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"linux"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GOARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"amd64"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;S3_BUCKET_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws s3api list-buckets &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Buckets[0].Name'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Build binary file from code&lt;/span&gt;
go build &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt; lamda-secret

&lt;span class="c"&gt;# Compress this file into ZIP format&lt;/span&gt;
zip ../../lambda-&lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt;.zip &lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt;

&lt;span class="c"&gt;# Upload to s3 with aws cli&lt;/span&gt;
aws s3api put-object &lt;span class="nt"&gt;--bucket&lt;/span&gt; &lt;span class="nv"&gt;$S3_BUCKET_NAME&lt;/span&gt; &lt;span class="nt"&gt;--key&lt;/span&gt; lambda-&lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt;.zip &lt;span class="nt"&gt;--body&lt;/span&gt; ./lambda-&lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt;.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Proof your result
&lt;/h2&gt;

&lt;p&gt;Create AWS lambda function and upload your ZIP binary file. Example CLI to create&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda create-function &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--function-name&lt;/span&gt; YourFunctionName &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--runtime&lt;/span&gt; go1.x &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--role&lt;/span&gt; your-iam-role-arn &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--handler&lt;/span&gt; your-bin-name &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--zip-file&lt;/span&gt; s3-url-with-zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manual trigger to Lambda function and you can see result on CloudWatch log group.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda invoke &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--function-name&lt;/span&gt; YourFunctionName
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;!! Before execute function you should attach IAM role to Lambda and that role will provide below permission.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"Id"&lt;/span&gt;: &lt;span class="s2"&gt;"AllowLambdaAccessSecret"&lt;/span&gt;,
    &lt;span class="s2"&gt;"Statement"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Action"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"secretsmanager:GetSecretValue"&lt;/span&gt;,
                &lt;span class="s2"&gt;"secretsmanager:DescribeSecret"&lt;/span&gt;
            &lt;span class="o"&gt;]&lt;/span&gt;,
            &lt;span class="s2"&gt;"Effect"&lt;/span&gt;: &lt;span class="s2"&gt;"Allow"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Resource"&lt;/span&gt;: &lt;span class="s2"&gt;"*"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Sid"&lt;/span&gt;: &lt;span class="s2"&gt;"AllowLambdaAccessToSecretManager"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Action"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                &lt;span class="s2"&gt;"kms:ReEncrypt*"&lt;/span&gt;,
                &lt;span class="s2"&gt;"kms:GenerateDataKey*"&lt;/span&gt;,
                &lt;span class="s2"&gt;"kms:Encrypt"&lt;/span&gt;,
                &lt;span class="s2"&gt;"kms:Decrypt"&lt;/span&gt;
            &lt;span class="o"&gt;]&lt;/span&gt;,
            &lt;span class="s2"&gt;"Effect"&lt;/span&gt;: &lt;span class="s2"&gt;"Allow"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Resource"&lt;/span&gt;: &lt;span class="s2"&gt;"arn:aws:kms:ap-southeast-1:xxxxxx:key/xxxxx-xxx-xxxx-xxxx-xxxxxd96cc"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Sid"&lt;/span&gt;: &lt;span class="s2"&gt;"AllowLambdaAccessToKMSKey"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;,
    &lt;span class="s2"&gt;"Version"&lt;/span&gt;: &lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or you can create and invoke function via web console&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_cache-go.html"&gt;https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_cache-go.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_cache-go_cache.html"&gt;https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_cache-go_cache.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/golang-logging.html"&gt;https://docs.aws.amazon.com/lambda/latest/dg/golang-logging.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;👾 Handling secrets within a Lambda function becomes a breeze with the assistance of the AWS SDK. This concept can be seamlessly extended to explore alternative techniques, such as accessing retained secrets, orchestrating secret updates, or even orchestrating the deletion of secrets through automated processes.&lt;/p&gt;

&lt;p&gt;Excitingly, my forthcoming blog will delve into the practical implementation of the aforementioned functionalities, all achievable with a single click using the powerful tool that is Terraform. Stay tuned for the upcoming content! Catch you later! ✌️😋&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>go</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Jmeter load test with real time dashboard(InfluxDB)</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Sun, 13 Aug 2023 12:47:19 +0000</pubDate>
      <link>https://forem.com/startpher/jmeter-load-test-with-real-time-dashboardinfluxdb-302d</link>
      <guid>https://forem.com/startpher/jmeter-load-test-with-real-time-dashboardinfluxdb-302d</guid>
      <description>&lt;p&gt;🤖 Hey there! Just wanted to give you a quick update. Right now, I'm working on setting up a way to test how well our app performs. We're building a web app for our customers, so making sure it works smoothly is a big deal. We're using a user-friendly interface to create different performance test scenarios. The idea is to show how the app holds up under different conditions.&lt;/p&gt;

&lt;p&gt;To do this, we're using JMeter to create scripts that simulate a bunch of people using the app at once. The only catch is that JMeter doesn't create fancy comparison reports for our customers. It mostly gives us raw data and documentation-style reports. So, I've come up with a plan. We're going to hook up InfluxDB to help us store performance data in a way that's easy to understand. Later on, we'll turn this data into cool visual dashboards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Develop a docker-compose into workspace&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;influx-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;dev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;influxdb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;influxdb:2.7-alpine&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;influxdb&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8086:8086&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;influx-data:/var/lib/influxdb2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./influxdb2/conf:/etc/influxdb2&lt;/span&gt;
  &lt;span class="na"&gt;demo-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go-example:1.0&lt;/span&gt; &lt;span class="c1"&gt;# build from my local app&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go-app&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;3000:3000&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;blockquote&gt;
&lt;p&gt;You can replace demo-app with your app&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide docker compose with &lt;code&gt;docker-compose up&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verify application is available with cURL&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl localhost:3000/healthz
OK%
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then open web browser to config InfluxDB &lt;code&gt;http://localhost:8086&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw8n3820ao7qspll0v2qm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw8n3820ao7qspll0v2qm.png" alt="InfluxDB welcome page"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a user to manage InfluxDB &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpj2n6uk9ie7t09w3bips.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpj2n6uk9ie7t09w3bips.png" alt="Init admin user"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Save a token for access database via API and select configure later. Finish!! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiiipj882b1tkvo5ubo49.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiiipj882b1tkvo5ubo49.png" alt="First token for admin"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, we’re already to collect data from Jmeter&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Create a Jmeter script
&lt;/h2&gt;

&lt;p&gt;You can develop your own scenarios like below&lt;/p&gt;

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

&lt;p&gt;In the last step of your script, you add &lt;code&gt;backend listener&lt;/code&gt; to InfluxDB.&lt;/p&gt;

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

&lt;p&gt;Or you can add this &lt;strong&gt;XML&lt;/strong&gt; to your &lt;strong&gt;JMX&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;...
                &lt;span class="nt"&gt;&amp;lt;BackendListener&lt;/span&gt; &lt;span class="na"&gt;guiclass=&lt;/span&gt;&lt;span class="s"&gt;"BackendListenerGui"&lt;/span&gt; &lt;span class="na"&gt;testclass=&lt;/span&gt;&lt;span class="s"&gt;"BackendListener"&lt;/span&gt; &lt;span class="na"&gt;testname=&lt;/span&gt;&lt;span class="s"&gt;"Influxdb"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"arguments"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Arguments"&lt;/span&gt; &lt;span class="na"&gt;guiclass=&lt;/span&gt;&lt;span class="s"&gt;"ArgumentsPanel"&lt;/span&gt; &lt;span class="na"&gt;testclass=&lt;/span&gt;&lt;span class="s"&gt;"Arguments"&lt;/span&gt; &lt;span class="na"&gt;enabled=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;collectionProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Arguments.arguments"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"influxdbMetricsSender"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;influxdbMetricsSender&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;org.apache.jmeter.visualizers.backend.influxdb.HttpMetricsSender&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"influxdbUrl"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;influxdbUrl&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;http://localhost:8086/api/v2/write?org=start&lt;span class="ni"&gt;&amp;amp;amp;&lt;/span&gt;bucket=jmeter&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"application"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;application&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;demo-go&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"measurement"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;measurement&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;jmeter&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"summaryOnly"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;summaryOnly&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;false&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"samplersRegex"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;samplersRegex&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;.*&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"percentiles"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;percentiles&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;90;95;99&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"testTitle"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;testTitle&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Test simple&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"eventTags"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;eventTags&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;elementProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"influxdbToken"&lt;/span&gt; &lt;span class="na"&gt;elementType=&lt;/span&gt;&lt;span class="s"&gt;"Argument"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;influxdbToken&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;NykJl8CX4paZEN3q7yNnIs9F_mLlnpITDWnWyfDSDv4yTyx6y0JOTMbExQljc_sq1qBVEYl5r4FFW3_NJd9SmQ==-7IV6tg8MsuwYU-5l4UyrtA==&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Argument.metadata"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;=&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/collectionProp&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/elementProp&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;stringProp&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"classname"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;org.apache.jmeter.visualizers.backend.influxdb.InfluxdbBackendListenerClient&lt;span class="nt"&gt;&amp;lt;/stringProp&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/BackendListener&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Import InfluxDB dashboard
&lt;/h2&gt;

&lt;p&gt;InfluxDB provide a web service that you can import a dashboard template on it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to InfluxDB web UI&lt;/li&gt;
&lt;li&gt;Go to Dashboard &amp;gt;&amp;gt; Click Create Dashboard &amp;gt;&amp;gt; Add a Template&lt;/li&gt;
&lt;li&gt;Parse a YAML file URL into block number 2(You can copy URL &lt;a href="https://raw.githubusercontent.com/influxdata/community-templates/master/apache_jmeter/apache_jmeter.yml" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Click Lookup Template &amp;gt;&amp;gt; Install template&lt;/li&gt;
&lt;li&gt;After finish you can see a dashboard on your page&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h2&gt;
  
  
  Execute load test
&lt;/h2&gt;

&lt;p&gt;After you prepare your workspace, Let’s start your Jmeter script to test your application.&lt;/p&gt;

&lt;p&gt;Then, you can see realtime result on your dashboard.&lt;/p&gt;

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

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

&lt;p&gt;Enhance your load testing experience by seamlessly integrating your testing tools with a visualization platform, allowing you to create insightful dashboards that display real-time results of your testing scenarios. For this purpose, I've employed a widely recognized tool, JMeter, which conveniently offers a plugin for seamless integration with InfluxDB.&lt;/p&gt;

&lt;p&gt;I'm optimistic that my upcoming workshop will prove invaluable in enhancing your testing journey. Looking forward to sharing knowledge and boosting your testing prowess. 🤖👾&lt;/p&gt;

</description>
      <category>devops</category>
      <category>loadtest</category>
      <category>development</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Terraform AWS lambda integrated with EventBridge</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Tue, 01 Aug 2023 11:57:09 +0000</pubDate>
      <link>https://forem.com/startpher/terraform-aws-lambda-integrated-with-eventbridge-1lca</link>
      <guid>https://forem.com/startpher/terraform-aws-lambda-integrated-with-eventbridge-1lca</guid>
      <description>&lt;p&gt;😎🎶 In the previous session, I shared how to develop a Lambda function that requests RDS to copy a snapshot from a source region to a target region. It was developed using Golang and AWS SDK to build data into the AWS API structure. Then, I used some programming logic to manage already replicated snapshots in the target region by copying only those that do not yet exist in the target region. You can read more &lt;a href="https://dev.to/startpher/aws-lambda-replicate-rds-snapshot-2g8p"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;😜🤪 This session covers how to deploy the previous source code to real infrastructure on AWS using Terraform. I will demonstrate how to use Terraform to provide Infrastructure as Code and create a cloud service environment for serving the Lambda function from the requirements mentioned earlier.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  AWS service is related
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;EventBridge&lt;/code&gt;; event bus and event rules.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IAM&lt;/code&gt;; policy and roles.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;S3&lt;/code&gt;; bucket and objects.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Lambda&lt;/code&gt;; functions and policy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cloudwatch&lt;/code&gt;; log group&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;KMS&lt;/code&gt;; multi-region key&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Preparations
&lt;/h2&gt;

&lt;p&gt;Before develop a Terraform code, you should install the following.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform cli&lt;/li&gt;
&lt;li&gt;AWS cli&lt;/li&gt;
&lt;li&gt;Go bin&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Get started develop
&lt;/h2&gt;

&lt;p&gt;Define the Terraform information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="n"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;required_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&amp;gt;=0.12"&lt;/span&gt;

  &lt;span class="n"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;aws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;source&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hashicorp/aws"&lt;/span&gt;
      &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"5.7.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define AWS provider&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;providers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="s"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Configuration&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;
  &lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To define local variables for use in this environment, create a main terraform file. Define variables that may be changed in other scenarios, and replace those values with resources from other files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="n"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;providers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
  &lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ap-southeast-1"&lt;/span&gt;

  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;S3&lt;/span&gt;
  &lt;span class="n"&gt;S3_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"lambda-lake-"&lt;/span&gt;

  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;Lambda&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;
  &lt;span class="n"&gt;lambda_func_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"rds_copy_snap"&lt;/span&gt;
  &lt;span class="n"&gt;lambda_s3_key&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"lambda-hello.zip"&lt;/span&gt;
  &lt;span class="n"&gt;handler_bin_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;
  &lt;span class="n"&gt;func_env_var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;OPT_SRC_REGION&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ap-southeast-1"&lt;/span&gt;
    &lt;span class="n"&gt;OPT_TARGET_REGION&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ap-southeast-2"&lt;/span&gt;
    &lt;span class="n"&gt;OPT_BEDUG&lt;/span&gt;             &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"True"&lt;/span&gt;
    &lt;span class="n"&gt;OPT_DB_NAME&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="n"&gt;OPT_OPTION_GROUP_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
    &lt;span class="n"&gt;OPT_KMS_KEY_ID&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;EventBridge&lt;/span&gt;
  &lt;span class="n"&gt;bus_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"rds-bus"&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Leave&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="s"&gt;`default`&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;AWS&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="n"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;rds_events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Capture for RDS snapshot event"&lt;/span&gt;
    &lt;span class="n"&gt;event_pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="s"&gt;"source"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"aws.rds"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"demo.event"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="s"&gt;"detail"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"EventID"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"RDS-EVENT-0042"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"RDS-EVENT-0091"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Default&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Owner&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"watcharin"&lt;/span&gt;
    &lt;span class="n"&gt;Project&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"local-dev"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Use&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt; &lt;span class="n"&gt;AWS&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="n"&gt;information&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="s"&gt;"aws_caller_identity"&lt;/span&gt; &lt;span class="s"&gt;"current"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, I created an S3 resource in a separate file. This resource provides a new S3 bucket to store compressed binary files from the built Go code and upload them into Lambda. To generate the bucket name, I defined a prefix and added a random suffix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="s"&gt;"s3_lambda"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"terraform-aws-modules/s3-bucket/aws"&lt;/span&gt;

  &lt;span class="n"&gt;bucket_prefix&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S3_prefix&lt;/span&gt;
  &lt;span class="n"&gt;create_bucket&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;block_public_acls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

  &lt;span class="n"&gt;control_object_ownership&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;object_ownership&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ObjectWriter"&lt;/span&gt;

  &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After created S3 bucket, I built Go binary and push into its.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use taskfile help a pipeline step. Or you can read a manual step in Taskfile.yml.&lt;/span&gt;
task build
task upload:lambda
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s create Lambda resource. I will provision an IAM role for assume privilege from function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# lambda.tf&lt;/span&gt;
data &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"lambda_assume"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  statement &lt;span class="o"&gt;{&lt;/span&gt;
    effect &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;
    principals &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;type&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Service"&lt;/span&gt;
      identifiers &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"lambda.amazonaws.com"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    actions &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
resource &lt;span class="s2"&gt;"aws_iam_role"&lt;/span&gt; &lt;span class="s2"&gt;"lambda_iam_role"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  name               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"iam_for_lambda"&lt;/span&gt;
  assume_role_policy &lt;span class="o"&gt;=&lt;/span&gt; data.aws_iam_policy_document.lambda_assume.json
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, provide a policy document and attachment to Lambda role. This function will permission for access to AWS resource as Cloudwatch log group, KMS key, and RDS snapshot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;lambda&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="s"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s"&gt;"allow_logging"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;policy_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AllowLambdaPushLog"&lt;/span&gt;
  &lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Allow"&lt;/span&gt;
    &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s"&gt;"logs:CreateLogStream"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"logs:PutLogEvents"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"arn:aws:logs:*:*:*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="s"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s"&gt;"allow_copy_rds_snapshot"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;policy_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AllowLambdaCopyRdsSnapshot"&lt;/span&gt;
  &lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Allow"&lt;/span&gt;
    &lt;span class="n"&gt;sid&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AllowLambdaAccessToRdsSnapshot"&lt;/span&gt;
    &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s"&gt;"rds:CopyDBSnapshot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"rds:ModifyDBSnapshot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"rds:DescribeDBSnapshots"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"rds:ModifyDBSnapshotAttribute"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sid&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AllowLambdaAccessToKMSKey"&lt;/span&gt;
    &lt;span class="n"&gt;effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Allow"&lt;/span&gt;
    &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s"&gt;"kms:Encrypt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"kms:Decrypt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"kms:ReEncrypt*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"kms:GenerateDataKey*"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"${aws_kms_key.rds_snap.arn}"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"aws_iam_policy"&lt;/span&gt; &lt;span class="s"&gt;"lambda_logging"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"lambda-logging-cloudwatch"&lt;/span&gt;
  &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allow_logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"aws_iam_policy"&lt;/span&gt; &lt;span class="s"&gt;"lambda_rds"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"lambda-access-rds"&lt;/span&gt;
  &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allow_copy_rds_snapshot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"aws_iam_role_policy_attachment"&lt;/span&gt; &lt;span class="s"&gt;"func_log_policy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;role&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_iam_role&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lambda_iam_role&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
  &lt;span class="n"&gt;policy_arn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_iam_policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lambda_logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arn&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"aws_iam_role_policy_attachment"&lt;/span&gt; &lt;span class="s"&gt;"func_rds"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;role&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_iam_role&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lambda_iam_role&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
  &lt;span class="n"&gt;policy_arn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_iam_policy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lambda_rds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arn&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I define an information about the Lambda that I want to created. In this function, I define configuration as &lt;code&gt;source file from S3&lt;/code&gt;, &lt;code&gt;memory size&lt;/code&gt;, and &lt;code&gt;env var&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;lambda&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"aws_lambda_function"&lt;/span&gt; &lt;span class="s"&gt;"rds_snap"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;function_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lambda_func_name&lt;/span&gt;
  &lt;span class="n"&gt;description&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Func to handle event from EventBridge to request RDS copy snapshot."&lt;/span&gt;
  &lt;span class="n"&gt;role&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_iam_role&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lambda_iam_role&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arn&lt;/span&gt;

  &lt;span class="n"&gt;handler&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handler_bin_name&lt;/span&gt;
  &lt;span class="n"&gt;runtime&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"go1.x"&lt;/span&gt;
  &lt;span class="n"&gt;s3_bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s3_lambda&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s3_bucket_id&lt;/span&gt;
  &lt;span class="n"&gt;s3_key&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lambda_s3_key&lt;/span&gt;

  &lt;span class="n"&gt;package_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Zip"&lt;/span&gt;
  &lt;span class="n"&gt;memory_size&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;128&lt;/span&gt;

  &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;variables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func_env_var&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We still cannot access this function from EventBridge because I did not provide a Lambda policy that allows invoking this function. You can see the Terraform code below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;lambda&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"aws_lambda_permission"&lt;/span&gt; &lt;span class="s"&gt;"allow_eventbridge"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;statement_id&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AllowExecutionFromEventBridge"&lt;/span&gt;
  &lt;span class="n"&gt;action&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"lambda:InvokeFunction"&lt;/span&gt;
  &lt;span class="n"&gt;function_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_lambda_function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rds_snap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function_name&lt;/span&gt;
  &lt;span class="n"&gt;principal&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"events.amazonaws.com"&lt;/span&gt;
  &lt;span class="n"&gt;source_arn&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventbridge_rule_arns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have created a Cloudwatch log group to store activity logs for Lambda. However, to reduce costs for this lab, I have set the retention period for the logs to one day. (Note: You can adjust this setting as necessary.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;cloudwatch&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"aws_cloudwatch_log_group"&lt;/span&gt; &lt;span class="s"&gt;"lambda"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/aws/lambda/${local.lambda_func_name}"&lt;/span&gt;
  &lt;span class="n"&gt;retention_in_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;prevent_destroy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a KMS key that will be used by a Lambda function to encrypt a snapshot from a source region and transfer it to a target region.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="s"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s"&gt;"kms"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Allow&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="n"&gt;managed&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
  &lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Allow"&lt;/span&gt;
    &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s"&gt;"kms:*"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;principals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;type&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AWS"&lt;/span&gt;
      &lt;span class="n"&gt;identifiers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Allow&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;limited&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;
  &lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Allow"&lt;/span&gt;
    &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s"&gt;"kms:CreateGrant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"kms:Encrypt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"kms:Decrypt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"kms:ReEncrypt*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"kms:GenerateDataKey*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"kms:DescribeKey"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;principals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;type&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AWS"&lt;/span&gt;
      &lt;span class="n"&gt;identifiers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"${data.aws_caller_identity.current.arn}"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"aws_kms_key"&lt;/span&gt; &lt;span class="s"&gt;"rds_snap"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;description&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"CMK for AWS RDS backup"&lt;/span&gt;
  &lt;span class="n"&gt;enable_key_rotation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;policy&lt;/span&gt;              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
  &lt;span class="n"&gt;multi_region&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s"&gt;"aws_kms_alias"&lt;/span&gt; &lt;span class="s"&gt;"rds_snap"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;target_key_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aws_kms_key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rds_snap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"alias/%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"START_RDS_SNAP"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, I provide EventBridge rules to filter the interested events and send them to a Lambda function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: For event bus, If you need to tracking AWS services event, you will define with &lt;code&gt;default&lt;/code&gt;.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;eventbridge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="s"&gt;"eventbridge"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;source&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"terraform-aws-modules/eventbridge/aws"&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2.3.0"&lt;/span&gt;

  &lt;span class="n"&gt;bus_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bus_name&lt;/span&gt;
  &lt;span class="n"&gt;rules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rds_events&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"event-to-lambda"&lt;/span&gt;
        &lt;span class="n"&gt;arn&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"${aws_lambda_function.rds_snap.arn}"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;

  &lt;span class="n"&gt;depends_on&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;aws_lambda_function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rds_snap&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you finish developing the Terraform code, you can deploy it to your environment and wait for Terraform to create the necessary resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to prove it
&lt;/h2&gt;

&lt;p&gt;You can simulate an event that you interesting. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Goto AWS web console.&lt;/li&gt;
&lt;li&gt;Goto EventBridge &amp;gt;&amp;gt; Event buses&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;code&gt;Send events&lt;/code&gt; and define event details like below. Then, the event source you will use &lt;code&gt;demo.event&lt;/code&gt; that I define in the terraform and event pattern.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"EventCategories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"creation"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"SourceType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SNAPSHOT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"SourceArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:rds:us-east-1:123456789012:snapshot:rds:snapshot-replica-2018-10-06-12-24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2018-10-06T12:26:13.882Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"SourceIdentifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rds:snapshot-replica-2018-10-06-12-24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Automated snapshot created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"EventID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RDS-EVENT-0091"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After click send. you can wait a minute and see your resource on lambda monitor(metrics and log)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;👏🏻😉 We now have the ability to efficiently manage and provide the Lambda function with Terraform while simultaneously preparing related resources. In this article, I'll present an innovative approach to design the Serverless architecture, enabling Lambda to achieve what it couldn't do independently. By creating a co-worker to collaborate with Lambda, we open up new possibilities and enhance its capabilities.&lt;/p&gt;

&lt;p&gt;😋😜 My hope is that this article will serve as an inspiration for you to leverage Serverless services in your own scenarios. Embrace the power of Serverless and discover how it can revolutionize your projects!😘😘&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>serverless</category>
      <category>eventdriven</category>
    </item>
    <item>
      <title>AWS Lambda replicate RDS snapshot</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Fri, 28 Jul 2023 11:59:09 +0000</pubDate>
      <link>https://forem.com/startpher/aws-lambda-replicate-rds-snapshot-2g8p</link>
      <guid>https://forem.com/startpher/aws-lambda-replicate-rds-snapshot-2g8p</guid>
      <description>&lt;p&gt;A few days ago, I encountered an issue with AWS RDS services, specifically with SQL server databases that could not be backed up using the AWS Backup service. Currently, there are limitations for requesting RDS to backup databases. However, it is still possible to create backup requests for our database using the RDS API.&lt;/p&gt;

&lt;p&gt;Therefore, I want to remove the activity of engineers having to create backups manually through API or web console, and instead develop Serverless services to automate this process. This approach can also be extended to solve other issues in the future.&lt;/p&gt;

&lt;p&gt;Let’s go from this guideline&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparations
&lt;/h2&gt;

&lt;p&gt;Before creating any Lambda function, we need to read a document that explains how to develop them. You can find it &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-golang.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Then, you should have the following.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Golang&lt;/code&gt; version 1.16 or higher&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Pre-commit&lt;/code&gt; that use to ensure you are pushing a verified source code to the SCM&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Taskfile&lt;/code&gt; the optional, that use to reduce routine step in your development.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Overview solution is…
&lt;/h2&gt;

&lt;p&gt;We focus on events generated by RDS when a snapshot is created. These events are triggered by AWS EventBridge, which provisions a function in AWS Lambda to execute the necessary actions.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  First thing
&lt;/h2&gt;

&lt;p&gt;You can provide a folder structure for develop a Lambda function in your workspace.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create new Github repository and clone it into your local machine.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;your_repo_url&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to your folder and init a new Golang project. it will create a new &lt;code&gt;go.mod&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init &amp;lt;your_repo_url&amp;gt;
&lt;span class="c"&gt;#Example&lt;/span&gt;
go mod init github.com/StartloJ/lambda-rds-utils
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(Optional) Create a pre-commit policy file to help you improve development quality.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;#.pre-commit-config.yaml&lt;/span&gt;
&lt;span class="na"&gt;repos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/dnephin/pre-commit-golang&lt;/span&gt;
  &lt;span class="na"&gt;rev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
  &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go-fmt&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go-vet&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go-imports&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go-mod-tidy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Create a first function
&lt;/h2&gt;

&lt;p&gt;Now, we are ready to develop the Lambda function to handle the event. You can follow the steps below to create a real use case function that replicates the RDS snapshot across regions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remember the event structure from AWS EventBridge
&lt;/h3&gt;

&lt;p&gt;You can see more event on official docs &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.Messages.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"844e2571-85d4-695f-b930-0153b71dcb42"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"detail-type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RDS DB Snapshot Event"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws.rds"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"account"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456789012"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2018-10-06T12:26:13Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"region"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:rds:us-east-1:123456789012:snapshot:rds:snapshot-replica-2018-10-06-12-24"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"EventCategories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"creation"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"SourceType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SNAPSHOT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"SourceArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:rds:us-east-1:123456789012:snapshot:rds:snapshot-replica-2018-10-06-12-24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2018-10-06T12:26:13.882Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"SourceIdentifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rds:snapshot-replica-2018-10-06-12-24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Automated snapshot created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"EventID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RDS-EVENT-0091"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define a configuration for functions
&lt;/h3&gt;

&lt;p&gt;I will define parameters to reuse this function below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;OPT_SRC_REGION&lt;/code&gt; is a source region of RDS snapshots for copy.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OPT_TARGET_REGION&lt;/code&gt; is a target region that we need to store snapshots.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OPT_DB_NAME&lt;/code&gt; is a identity of RDS DB name that we need to copy snapshots.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OPT_OPTION_GROUP_NAME&lt;/code&gt; is a target option group to attachment to replicate snapshot in the target region.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OPT_KMS_KEY_ID&lt;/code&gt; is a KMS key that use to encrypt snapshot on target region.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Define main func
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/aws/aws-lambda-go/lambda"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/sirupsen/logrus"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Make the hangler available for remote procedure call by Lambda&lt;/span&gt;
    &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"we starting handle lambda..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;lambda&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HandleEvents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a function handle by lambda
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Define func to receive a variable from `BridgeEvent`&lt;/span&gt;
&lt;span class="c"&gt;// and it should return `error` if any mistake.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;HandleEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="n"&gt;BridgeEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define a new AWS session
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// define AWS session for source and target region to copy snapshot&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;HandleEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="n"&gt;BridgeEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// start copy code&lt;/span&gt;
    &lt;span class="n"&gt;des_sess&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSessionWithOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Region&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"target_region"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="n"&gt;src_sess&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSessionWithOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Region&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"src_region"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="c"&gt;// end copy code&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create func to get all existing snapshot
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// This func input session of RDS service. Then, it get all list of database&lt;/span&gt;
&lt;span class="c"&gt;// snapshot that already in your resources in List of Snapshot name.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ListAllSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DB_NAME"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// This line will return a list of snapshots included snapshot name.&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;svc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DescribeDBSnapshots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DescribeDBSnapshotsInput&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;DBInstanceIdentifier&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;snapShotName&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;

    &lt;span class="c"&gt;// this loop is extract a snapshot name only.&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DBSnapshots&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"We have %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ConvertToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DBSnapshotArn&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;snapShotName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snapShotName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ConvertToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DBSnapshotArn&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;snapShotName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get a list of RDS snapshot name from source and target region
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;HandleEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="n"&gt;BridgeEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="c"&gt;// start copy code&lt;/span&gt;
    &lt;span class="n"&gt;targetSvc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;des_sess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;rep_dbSnapshots&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ListAllSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetSvc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"we can't get any Snapshot name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;srcSvc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src_sess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;src_dbSnapshots&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ListAllSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srcSvc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"we can't get any Snapshot name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// End copy code&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a func to remove duplicate snapshot as source and target
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// this func use to remove duplicate name source if found in target&lt;/span&gt;
&lt;span class="c"&gt;// you shouldn't switch position input to this func.&lt;/span&gt;
&lt;span class="c"&gt;// `t` is mean a target that use double check to `s`&lt;/span&gt;
&lt;span class="c"&gt;// it will remove a value in `s` if found it in `t`&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GetUniqueSnapShots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;//Create a map to keep track a unique strings&lt;/span&gt;
    &lt;span class="n"&gt;uniqueMap&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;//Iterate over `s` and add each string to map&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;uniqueMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;//Iterate over `t` and remove any string that are already in uniqueMap&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;str2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uniqueMap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;str2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;//Convert the unique string from Map to slice string&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uniqueMap&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;uniqueMap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"not any Snapshot unique between source and target region"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define a unique snapshot
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;HandleEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="n"&gt;BridgeEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="c"&gt;// start copy code&lt;/span&gt;
    &lt;span class="n"&gt;dbSnapShots2Copy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;GetUniqueSnapShots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rep_dbSnapshots&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;src_dbSnapshots&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warnf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"it doesn't any task copy snapshot to %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"target_region"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// End copy code&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a func copy RDS snapshot across region
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Request to AWS RDS API for create event copy a specific snapshot&lt;/span&gt;
&lt;span class="c"&gt;// into across region and encrypt it by KMS key multi-region&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;CopySnapshotToTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snap&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;targetSnapArn&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;":"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;targetSnapName&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;targetSnapArn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetSnapArn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c"&gt;// Copy the snapshot to the target region&lt;/span&gt;
    &lt;span class="n"&gt;copySnapshotInput&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rds&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CopyDBSnapshotInput&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;OptionGroupName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;            &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"option_group_name"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="n"&gt;KmsKeyId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;                   &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"kms_key_id"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="n"&gt;CopyTags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;                   &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SourceDBSnapshotIdentifier&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;TargetDBSnapshotIdentifier&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetSnapName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;SourceRegion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;               &lt;span class="n"&gt;aws&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"src_region"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;svc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CopyDBSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;copySnapshotInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Copy request %s is failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Copy %s is created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Copy %s is created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define loop to execute all snapshot value
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;HandleEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="n"&gt;BridgeEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="c"&gt;// start copy code&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;dbSnapShots2Copy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Infof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"trying to copy DBSnapshot to %s..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"target_region"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;CopySnapshotToTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetSvc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dbSnapShots2Copy&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;logrus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// End copy code&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If all workflow is complete, it will normal end function from AWS Lambda controller.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Finally steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If you finished to develop function, you will build and pack it with ZIP format.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BINARY_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"lambda-rds-util"&lt;/span&gt; &lt;span class="c"&gt;#you can change this name.&lt;/span&gt;
go build &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt; main.go
zip lambda-&lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt;.zip &lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can upload your compress file(also ZIP file) to S3.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#you can push it with below command&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;S3_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your_s3_bucket_name&amp;gt;"&lt;/span&gt;
aws s3api put-object &lt;span class="nt"&gt;--bucket&lt;/span&gt; &lt;span class="nv"&gt;$S3_NAME&lt;/span&gt; &lt;span class="nt"&gt;--key&lt;/span&gt; lambda-&lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt;.zip &lt;span class="nt"&gt;--body&lt;/span&gt; ./lambda-&lt;span class="nv"&gt;$BINARY_NAME&lt;/span&gt;.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the web console of AWS Lambda, you can define a new resource and select source from S3.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the web console, you can test function in AWS Lambda to ensure your code is work!.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;You can automate certain activities on AWS or other cloud providers using the &lt;code&gt;Serverless&lt;/code&gt; service, such as AWS Lambda. It can enhance your development experience and enable you to explore new possibilities. You can even extend this idea to develop a new workflow in your work.&lt;/p&gt;

&lt;p&gt;I hope this blog has inspired you to consider using &lt;code&gt;Serverless&lt;/code&gt; in your development journey.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>devops</category>
      <category>go</category>
    </item>
    <item>
      <title>Get starting DevOps at Opsta: Your Path to Success</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Sun, 11 Jun 2023 08:47:22 +0000</pubDate>
      <link>https://forem.com/startpher/get-starting-devops-at-opsta-your-path-to-success-2hki</link>
      <guid>https://forem.com/startpher/get-starting-devops-at-opsta-your-path-to-success-2hki</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A good DevOps person is someone who acts as a connector between the development and operations teams, seamlessly integrating automation, collaboration, and continuous improvement to orchestrate and drive organizations to the pinnacle of innovation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;! In today’s rapidly evolving technologies landscape, The role of the DevOps professional is becoming increasingly crucial. Our organization strive for faster development cycles, efficient collaboration, reliable deployment, innovation researcher, and business partnership. We’re focus the demand for skilled DevOps practitioners continues to grow.&lt;/p&gt;

&lt;p&gt;Opsta, a leading company in the industry, present a remarkable opportunity to embark on a fulfilling DevOps career. This guide aims to equip aspiring DevOps professional with the knowledge and skill necessary to excel in the VUCA(acronym, which stands for "Volatile," "Uncertain," "Complex," and "Ambiguous”) world of DevOps at Opsta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the DevOps culture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sL31ceEV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rrwelt3v79wfdn5pjdz9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sL31ceEV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rrwelt3v79wfdn5pjdz9.jpg" alt="communication" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Explore the core principles and methodology that underpin the DevOps culture at our company.&lt;/li&gt;
&lt;li&gt;Learn how to promotes &lt;strong&gt;collaboration&lt;/strong&gt;, &lt;strong&gt;communication&lt;/strong&gt;, and &lt;strong&gt;shared responsibilities&lt;/strong&gt; among team&lt;/li&gt;
&lt;li&gt;Discover the significance of &lt;strong&gt;automation&lt;/strong&gt;, &lt;strong&gt;continuous integration&lt;/strong&gt; &amp;amp; &lt;strong&gt;continuous delivery&lt;/strong&gt;, &lt;strong&gt;observability(metrics, log, trace)&lt;/strong&gt;, &lt;strong&gt;Infrastructure as Code&lt;/strong&gt;, and &lt;strong&gt;Network &amp;amp; OS&lt;/strong&gt; in DevOps approach.&lt;/li&gt;
&lt;li&gt;To drive cross-functional teams for tools, you need to be &lt;strong&gt;adaptable&lt;/strong&gt;, &lt;strong&gt;goal-focused&lt;/strong&gt;, and able to &lt;strong&gt;innovate&lt;/strong&gt; towards your target.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Essentials technical skills for the DevOps engineer
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6Is6bVYf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pcqi63i3yd54go8cx47o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Is6bVYf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pcqi63i3yd54go8cx47o.jpg" alt="Tech skill" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To design, manage, and troubleshoot networks and operating systems, you need a solid foundation of knowledge in these areas..&lt;/li&gt;
&lt;li&gt;Dive into Infrastructure as Code(IaC) conceptual and implementation such as Terraform and Ansible for provisioning and managing infrastructure. Maybe, the others can do it same.&lt;/li&gt;
&lt;li&gt;Strong knowledge in containerize technologies such as Docker, Podman, or Kubernetes for scalable, resilience, and portable.&lt;/li&gt;
&lt;li&gt;Gain proficiency in public cloud platform like GCP, AWS, and Azure to leverage our services for building and deploying application.&lt;/li&gt;
&lt;li&gt;Understanding into Observability(also monitoring, logging, tracing) platform such as Prometheus, Grafana, ELK stack, Istio, and others to ensure reliability, consistency, and availability on system.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Collaboration and communication in DevOps environment
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wywqBd2S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5nw2x0oyo4nhbqu4z90g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wywqBd2S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5nw2x0oyo4nhbqu4z90g.jpg" alt="Collaboration" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Explore the importance of effective communication among team members and related teams.&lt;/li&gt;
&lt;li&gt;Learn about agile methodologies, such as Scrum or Kanban, that are adopted to streamline development and delivery.&lt;/li&gt;
&lt;li&gt;Discover significance of cross-function teams and encourage a culture of knowledge sharing and continuous learning.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Embracing automation in DevOps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YGxBbaZu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m29vg04304p8mep1b6ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YGxBbaZu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m29vg04304p8mep1b6ng.png" alt="Automation" width="589" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Learn about the advantages of implementing a configuration management tool such as Ansible, Puppet, or others. These tools can be used to manage and configure both infrastructure and applications.&lt;/li&gt;
&lt;li&gt;Explore the benefits of using a CI/CD pipeline with tools such as Jenkins, Gitlab-CI, Github Actions, ArgoCD, Tekton, and others to reduce human effort, team workload, and ensure compliance.&lt;/li&gt;
&lt;li&gt;Learn the benefits of using cloud native services like AWS codepipeline, GCP cloudbuild, and Azure DevOps to automate for effective CI and CD applications.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Continuous learning and professional development
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qCp9MEWm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3c9auziyf2uw6srr1oxi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qCp9MEWm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3c9auziyf2uw6srr1oxi.jpg" alt="learning" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Continue moving and keeping abreast of DevOps along with technologies' innovations, trends, and expertise.&lt;/li&gt;
&lt;li&gt;Discover resources that can help you improve your knowledge and skills, such as blogs, online and offline courses, and conferences.&lt;/li&gt;
&lt;li&gt;Learn how to contribute to the community in order to assist the development of teams and other individuals through knowledge sharing, documentation, and training programs.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Technical know-how, teamwork, and a commitment to continual development were necessary for becoming an effective DevOps practitioner. You may start your journey toward becoming a successful DevOps professional by adopting the DevOps culture, developing key technical skills, and fostering good communication. Take embrace the chance to contribute meaningfully by promoting efficiency, creativity, and technical excellence within the DevOps environment.&lt;/p&gt;

&lt;p&gt;I'll go into further detail about the technical skills you need to adopt the DevOps culture. Then, I'll talk about my experience working in a DevOps position and how it contributed to shifting a tech team toward DevOps culture. If you living in Thailand and have faith in technical professionals, you are welcome to join us in tackling challenging problems and empowering customers with technical standards.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>productivity</category>
      <category>development</category>
      <category>community</category>
    </item>
    <item>
      <title>Level up your development in Git</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Sat, 03 Jun 2023 12:41:07 +0000</pubDate>
      <link>https://forem.com/startpher/level-up-your-development-in-git-38l3</link>
      <guid>https://forem.com/startpher/level-up-your-development-in-git-38l3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;As developers, we strive to improve ourselves every day and become better than we were before. I have found some tools and solutions that can help us. I would like to share a trick that I often use to simplify complex processes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today, we use GIT to &lt;strong&gt;version control&lt;/strong&gt; in daily work. We have many styles in GIT workflow like feature branch, single branch, and other. The Git is concept and software that help us to saving and tracking file(code) history in standard idea. We use Git in different platforms such as GitHub, Gitlab, Bitbucket, and other. &lt;/p&gt;

&lt;p&gt;We have process in step to review and ensure our code source before we commit code and push them to the Git server. How can we ensure our source code that correct syntax or available to execute in another place? Therefore, we make an Unit-test and a linter(also linting framework) that we can execute to verify our code in local. Maybe, We have a separate environment that make to test our source code, up to you!.&lt;/p&gt;

&lt;p&gt;To help us to accelerate in development feature. I prefer you to use a open source project from community that called &lt;a href="https://github.com/pre-commit"&gt;Pre-commit&lt;/a&gt;. We can use them to replace our manual step such as run unit-test and fix format. Then, how can we use it? I will show you in this blogs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is pre-commit
&lt;/h2&gt;

&lt;p&gt;It is a framework for managing and maintaining multi-language pre-commit hooks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Git hook scripts are useful for identifying simple issues before submission to code review. We run our hooks on every commit to automatically point out issues in code&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lCzZ2hrp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9910b573-8d9d-400c-8f43-bb4393894068/Untitled.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lCzZ2hrp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9910b573-8d9d-400c-8f43-bb4393894068/Untitled.png" alt="Untitled" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage step by step
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install into local machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before you can run hooks, you need to have the pre-commit package manager installed.&lt;/p&gt;

&lt;p&gt;Using pip for Linux&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# for Python2&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;pre-commit

&lt;span class="c"&gt;# for Python3&lt;/span&gt;
pip3 &lt;span class="nb"&gt;install &lt;/span&gt;pre-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;homebrew&lt;/code&gt; for MacOS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;pre-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Initial pre-commit policy in root directory source code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add a pre-commit configuration. You must created file named &lt;code&gt;.pre-commit-config.yaml&lt;/code&gt;. You can generate a very basic configuration using &lt;code&gt;pre-commit sample-config&lt;/code&gt; .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;repos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt;   &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/pre-commit/pre-commit-hooks&lt;/span&gt;
    &lt;span class="na"&gt;rev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2.3.0&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt;   &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;check-yaml&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt;   &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;end-of-file-fixer&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt;   &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;trailing-whitespace&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt;   &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/psf/black&lt;/span&gt;
    &lt;span class="na"&gt;rev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;22.10.0&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt;   &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;black&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install Git hook script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to automate execute &lt;strong&gt;pre-commit&lt;/strong&gt; in every committed. You should install Git hook before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pre-commit &lt;span class="nb"&gt;install
&lt;/span&gt;pre-commit installed at .git/hooks/pre-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now &lt;strong&gt;pre-commit&lt;/strong&gt; will run automatically on git commit!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run against all files
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pre-commit run &lt;span class="nt"&gt;--all-files&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;INFO] Initializing environment &lt;span class="k"&gt;for &lt;/span&gt;https://github.com/pre-commit/pre-commit-hooks.
&lt;span class="o"&gt;[&lt;/span&gt;INFO] Initializing environment &lt;span class="k"&gt;for &lt;/span&gt;https://github.com/psf/black.
&lt;span class="o"&gt;[&lt;/span&gt;INFO] Installing environment &lt;span class="k"&gt;for &lt;/span&gt;https://github.com/pre-commit/pre-commit-hooks.
&lt;span class="o"&gt;[&lt;/span&gt;INFO] Once installed this environment will be reused.
&lt;span class="o"&gt;[&lt;/span&gt;INFO] This may take a few minutes...
&lt;span class="o"&gt;[&lt;/span&gt;INFO] Installing environment &lt;span class="k"&gt;for &lt;/span&gt;https://github.com/psf/black.
&lt;span class="o"&gt;[&lt;/span&gt;INFO] Once installed this environment will be reused.
&lt;span class="o"&gt;[&lt;/span&gt;INFO] This may take a few minutes...
Check Yaml...............................................................Passed
Fix End of Files.........................................................Passed
Trim Trailing Whitespace.................................................Failed
- hook &lt;span class="nb"&gt;id&lt;/span&gt;: trailing-whitespace
- &lt;span class="nb"&gt;exit &lt;/span&gt;code: 1

Files were modified by this hook. Additional output:

Fixing sample.py

black....................................................................Passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;oops! looks like I had some trailing whitespace. Now, you can fix your error first and re-add your code to commit stage in Git again.&lt;/p&gt;

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

&lt;p&gt;We can automate our development processes with framework called &lt;code&gt;pre-commit&lt;/code&gt;. If you need to use &lt;code&gt;pre-commit&lt;/code&gt; in advance step, you can read more details in below reference link and kindly share your idea to improve our process with us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ref
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://pre-commit.com/#intro"&gt;https://pre-commit.com/#intro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pre-commit/pre-commit"&gt;https://github.com/pre-commit/pre-commit&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>git</category>
      <category>devops</category>
      <category>development</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Data ETL in DevOps processes</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Sat, 04 Jun 2022 10:06:34 +0000</pubDate>
      <link>https://forem.com/startpher/data-etl-in-devops-processes-2df3</link>
      <guid>https://forem.com/startpher/data-etl-in-devops-processes-2df3</guid>
      <description>&lt;p&gt;🤗 Hi everyone, I have new blog's series to you. It have long time that I need to public this content. I would shared my perspective about relative of DevOps process and Data process. This post base on my experience.  &lt;/p&gt;

&lt;p&gt;In the normal Development and Operation process, we have a lot of &lt;strong&gt;data&lt;/strong&gt; or &lt;strong&gt;message&lt;/strong&gt; generation.&lt;br&gt;
We can see the behavior of events from user(client) to the latest service in workflow. When a user accesses our platform or service, it is called a &lt;strong&gt;request&lt;/strong&gt;.&lt;br&gt;
The request is one of the message types that we can use to &lt;strong&gt;process&lt;/strong&gt; or &lt;strong&gt;analytic&lt;/strong&gt;. For all transactions on user workflow we have many many &lt;strong&gt;messages&lt;/strong&gt;(also data or events)&lt;br&gt;
to see what happens in your services. Further, we can see other messages on the infrastructure layer and Networking layer.&lt;/p&gt;

&lt;p&gt;Oftenly, &lt;code&gt;DevOps processes&lt;/code&gt; focus on the &lt;strong&gt;What happened in our platform&lt;/strong&gt;, so they use logs messages created by application and observability tools.&lt;br&gt;
In this session, I will present how DevOps uses previous data to observe what happened in your platform and what we should do if we have data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is ETL
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ETL&lt;/strong&gt; is called &lt;code&gt;Extract, Transform and Load&lt;/code&gt;. It is &lt;strong&gt;data integration&lt;/strong&gt; that refers to three distinct processes. We use to transfer data from multiple sources with any format to any data storage and already to visualize future trends or current information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8tMgj-sM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c6mrnxi293nqdt2qbppb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8tMgj-sM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c6mrnxi293nqdt2qbppb.png" alt="Overview" width="621" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we can work each function in following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extract&lt;/strong&gt; is used to scrape data from &lt;code&gt;any sources and any format&lt;/code&gt; like app log, flat file, metrics, or api response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FKa2Vr1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8oslbguty8ydl7ur1gy4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FKa2Vr1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8oslbguty8ydl7ur1gy4.png" alt="Extract" width="351" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transform&lt;/strong&gt; is used to convert different data formats to the same format, &lt;em&gt;cleaning data&lt;/em&gt;, &lt;em&gt;filter useless data&lt;/em&gt;, &lt;em&gt;add metadata in each message&lt;/em&gt;, and other processes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QvJ67MW0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xdmnpk87adtc8l7ddyzm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QvJ67MW0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xdmnpk87adtc8l7ddyzm.png" alt="Transform" width="521" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Load&lt;/strong&gt; is used to transfer data that is transformed to store in a &lt;strong&gt;data lake&lt;/strong&gt;, &lt;strong&gt;data warehouse&lt;/strong&gt;, or other storage.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5rEaRV74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wsq4sp0vxsypgxffuuk0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5rEaRV74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wsq4sp0vxsypgxffuuk0.png" alt="Load" width="321" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the data pipeline, we can adapt with  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;extract → transformation → load&lt;br&gt;&lt;br&gt;
or&lt;br&gt;&lt;br&gt;
extract → load → transformation.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can design your &lt;code&gt;data pipeline&lt;/code&gt; base-on your platform and tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  ETL in basically
&lt;/h2&gt;

&lt;p&gt;Now, you understand what &lt;strong&gt;ETL&lt;/strong&gt; is, but when should we implement them? In begin to, answer this question, you need to design &lt;code&gt;data flow&lt;/code&gt; from top layer to bottom or bottom layer to top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data design top layer to bottom
&lt;/h2&gt;

&lt;p&gt;We will gather requirements from &lt;strong&gt;business&lt;/strong&gt; about what we need to see in the end.&lt;br&gt;&lt;br&gt;
Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We need to see how many users have had bad experiences on our platform.&lt;/li&gt;
&lt;li&gt;We need to see where the web page that users focus and oftenly use.&lt;/li&gt;
&lt;li&gt;We need to see what the root cause of our service is broken.&lt;/li&gt;
&lt;li&gt;We need to see what services we should expand resources, improve performance, and scale.
ETC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We were started with what we need to design &lt;code&gt;data flow&lt;/code&gt; in the &lt;code&gt;platform lifecycle&lt;/code&gt;. You can use goals from the &lt;strong&gt;engineer team&lt;/strong&gt;, &lt;strong&gt;business team&lt;/strong&gt;, or &lt;strong&gt;developer team&lt;/strong&gt; to design and implement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data design bottom layer to top
&lt;/h3&gt;

&lt;p&gt;We will survey the existing resources and data in our system. Next, we try to expand ideas from our data to what we can see in current data.&lt;br&gt;&lt;br&gt;
Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have requested errors and many transactions in a few minutes, so that we can detect this event and analyze what happened and who is facing this problem.&lt;/li&gt;
&lt;li&gt;We have frequency response time more than 3 sec in some features that should have response time less than 3 sec. We can use this data to analyze to see what service has a delay and what is the root cause.&lt;/li&gt;
&lt;li&gt;We have an error log that shows the transaction failed. We can use this data and surround log to analyze what happened.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my example, you can see patterns on what we have, then how can we use this data to analyze what happened currently. In advance, we can analyze information to get insight on your information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge in data integration
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;application factor&lt;/strong&gt;, we do not think about data in the software design phase. We expose &lt;em&gt;useless information&lt;/em&gt; in our services or we do not have &lt;em&gt;necessary data&lt;/em&gt; that can tell us what we want.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;person factor&lt;/strong&gt;, &lt;code&gt;who is using data not designed, who is designed do not use them&lt;/code&gt;. As explained, the developer team is designing architecture for their services with business requirements, but in the design phase, they have no other team to participate like the operation team or person who is using data from this service to analyze.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;observed tools&lt;/strong&gt;, each team will have their stack for &lt;em&gt;data integration&lt;/em&gt; and other teams can not use this data because they &lt;em&gt;can not access&lt;/em&gt; this data or &lt;em&gt;incompatibility&lt;/em&gt; between tools. For example, team-A uses &lt;code&gt;AWS Redshift&lt;/code&gt; to store data and native AWS service to build their data pipeline, but team-B uses an on-premise stack like &lt;code&gt;Hadoop&lt;/code&gt; and their developed tool to integrate &lt;code&gt;Apache Hadoop&lt;/code&gt;. Another team can not access &lt;code&gt;AWS Redshift&lt;/code&gt; because they have &lt;em&gt;compliance&lt;/em&gt; or some reason. Then, we have 2 locations to store data that we can not merge and analyze.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next session, I will talk about simple scenario to use ETL concept on DevOps world.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>etl</category>
      <category>dataengineering</category>
      <category>100daysofdevops</category>
    </item>
    <item>
      <title>Simple PKI with CA issuer</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Sun, 22 May 2022 10:37:26 +0000</pubDate>
      <link>https://forem.com/startpher/simple-pki-with-ca-issuer-1fn3</link>
      <guid>https://forem.com/startpher/simple-pki-with-ca-issuer-1fn3</guid>
      <description>&lt;p&gt;This workshop will simulate the scenario in how we can use PKI to make secure communication. All this session we work on terminal, you can following in step-by-step.&lt;/p&gt;

&lt;p&gt;In the late session, we learned about how to use public/private keys in an easy case.&lt;br&gt;&lt;br&gt;
I explained the workshop to implement a solution. Then, We upgrade to an advanced workshop&lt;br&gt;&lt;br&gt;
to understand how to implement public/private CA intermediate servers.&lt;br&gt;&lt;br&gt;
If you are not read previous topic, you can go to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/startpher/what-we-should-know-in-pki-l25"&gt;what-we-should-know-in-pki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/startpher/little-step-to-use-pki-easiest-mmg"&gt;little-step-to-use-pki-easiest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;OpenSSL&lt;/li&gt;
&lt;li&gt;cURL&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;tree&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Create root CA certificate
&lt;/h2&gt;

&lt;p&gt;In first thing, we will generate simple self-sign root CA certificate with following step:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create SSL private key
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nv"&gt;$ &lt;/span&gt;openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; rootCAkey.pem 4096
   Generating RSA private key, 4096 bit long modulus &lt;span class="o"&gt;(&lt;/span&gt;2 primes&lt;span class="o"&gt;)&lt;/span&gt;
   .........................................++++
   .........++++
   e is 65537 &lt;span class="o"&gt;(&lt;/span&gt;0x010001&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;We generate random keys with 4,096 character and you can use other lengths like 1024, 2048, 8192, or ETC. You can increase or decrease your key length to optimize cpu power to process them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Create Certificate from private key
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nv"&gt;$ &lt;/span&gt;openssl req &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="nt"&gt;-sha256&lt;/span&gt; &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-nodes&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; rootCAkey.pem &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;-days&lt;/span&gt; 14 &lt;span class="nt"&gt;-out&lt;/span&gt; rootCAcert.pem
   You are about to be asked to enter information that will be incorporated
   into your certificate request.
   What you are about to enter is what is called a Distinguished Name or a DN.
   There are quite a few fields but you can leave some blank
   For some fields there will be a default value,
   If you enter &lt;span class="s1"&gt;'.'&lt;/span&gt;, the field will be left blank.
   &lt;span class="nt"&gt;-----&lt;/span&gt;
   Country Name &lt;span class="o"&gt;(&lt;/span&gt;2 letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU]:TH
   State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State]:Bangkok
   Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:BangKhea
   Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd]:Opsta Thailand
   Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:DevOps
   Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:OpstaRootCA
   Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:watcharin@opsta.co.th
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;For the previous command, I request a new certificate file with some information. I use the digest algorithm &lt;code&gt;SHA-256&lt;/code&gt; and set it to expire before &lt;strong&gt;14 days&lt;/strong&gt;. It shows a prompt on your terminal for adding more information. You can see an example above.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Now, we can verify own root CA
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   openssl x509 &lt;span class="nt"&gt;-text&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; rootCAcert.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;You can see your certificate information. Then go to the next step to create a chain certificate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Create server certificate with issuer
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Generate random private key with same step root CA
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="c"&gt;# You can replace rsaServerKey.pem to your name&lt;/span&gt;
   &lt;span class="c"&gt;# And can change key size from 2048 to other length&lt;/span&gt;
   &lt;span class="nv"&gt;$ &lt;/span&gt;openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; rsaServerKey.pem 2048
   Generating RSA private key, 2048 bit long modulus &lt;span class="o"&gt;(&lt;/span&gt;2 primes&lt;span class="o"&gt;)&lt;/span&gt;
   ......................................................................+++++
   ...............+++++
   e is 65537 &lt;span class="o"&gt;(&lt;/span&gt;0x010001&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Create CNF file that provide meta data for CSR
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;   &lt;span class="c"&gt;# req.cnf
&lt;/span&gt;   &lt;span class="nn"&gt;[req]&lt;/span&gt;
   &lt;span class="py"&gt;req_extensions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;v3_req&lt;/span&gt;
   &lt;span class="py"&gt;distinguished_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;dn&lt;/span&gt;
   &lt;span class="py"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;no&lt;/span&gt;

   &lt;span class="nn"&gt;[dn]&lt;/span&gt;
   &lt;span class="py"&gt;CN&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ssl-lab.example.local&lt;/span&gt;
   &lt;span class="py"&gt;C&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;TH&lt;/span&gt;
   &lt;span class="py"&gt;L&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Bangkok&lt;/span&gt;
   &lt;span class="py"&gt;O&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Opsta Thailand&lt;/span&gt;
   &lt;span class="py"&gt;OU&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;DevOps&lt;/span&gt;

   &lt;span class="nn"&gt;[v3_req]&lt;/span&gt;
   &lt;span class="py"&gt;subjectAltName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@san_names&lt;/span&gt;

   &lt;span class="nn"&gt;[san_names]&lt;/span&gt;
   &lt;span class="py"&gt;DNS.1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ssl-lab.example.local&lt;/span&gt;
   &lt;span class="py"&gt;DNS.2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
   &lt;span class="py"&gt;DNS.3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Provide simple configuration to create CSR file. This file has &lt;strong&gt;SAN(Subject Alternative Name)&lt;/strong&gt; with 3 names in &lt;code&gt;[san_names]&lt;/code&gt;. For &lt;code&gt;@san_names&lt;/code&gt;, I use for extend alternative name for server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Generate CSR certificate
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nv"&gt;$ &lt;/span&gt;openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; req.csr &lt;span class="nt"&gt;-key&lt;/span&gt; rsaServerKey.pem &lt;span class="nt"&gt;-sha256&lt;/span&gt; &lt;span class="nt"&gt;-config&lt;/span&gt; req.cnf
   &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;req.csr
   &lt;span class="nt"&gt;-----BEGIN&lt;/span&gt; CERTIFICATE REQUEST-----
   MIIC9zCCAd8CAQAwaTEeMBwGA1UEAwwVc3NsLWxhYi5leGFtcGxlLmxvY2FsMQsw
   CQYDVQQGEwJUSDEQMA4GA1UEBwwHQmFuZ2tvazEXMBUGA1UECgwOT3BzdGEgVGhh
   aWxhbmQxDzANBgNVBAsMBkRldk9wczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
   …
   k9jkEKhPeICqJgHLbyiEcEc9xaPTMPb35cBQT8irnUq1+WbQamhWDIBmwzDHCSyf
   jCK672ACRleQCj8kk5l+dOB0wzWEaDcCoQNwIwqg2RpfDKc1lHARroBzm1P/4grg
   NaF5EYJJWhXUXGKq68meHpCTGzgC7M06rwBdOR+8l0GIUZ5K25MvNg3+ZA&lt;span class="o"&gt;==&lt;/span&gt;
   &lt;span class="nt"&gt;-----END&lt;/span&gt; CERTIFICATE REQUEST-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Verify CSR information, we focus on Requested Extension.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nv"&gt;$ &lt;/span&gt;openssl req &lt;span class="nt"&gt;-in&lt;/span&gt; req.csr &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-text&lt;/span&gt;
   …
   Requested Extensions:
               X509v3 Subject Alternative Name: 
                   DNS:ssl-lab.example.local, DNS:localhost, DNS:127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Create trusted certificate with root CA with CSR file
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nv"&gt;$ &lt;/span&gt;openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-sha256&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; req.csr &lt;span class="nt"&gt;-CA&lt;/span&gt; ../rootCAcert.pem &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-extfile&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"subjectAltName=DNS:ssl-lab.example.local,DNS:localhost"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-CAkey&lt;/span&gt; ../rootCAkey.pem &lt;span class="nt"&gt;-CAcreateserial&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; CertServer.pem &lt;span class="nt"&gt;-days&lt;/span&gt; 7
   …
   Signature ok
   &lt;span class="nv"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CN &lt;span class="o"&gt;=&lt;/span&gt; ssl-lab.example.local, C &lt;span class="o"&gt;=&lt;/span&gt; TH, L &lt;span class="o"&gt;=&lt;/span&gt; Bangkok, O &lt;span class="o"&gt;=&lt;/span&gt; Opsta Thailand, OU &lt;span class="o"&gt;=&lt;/span&gt; DevOps
   Getting CA Private Key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;We create trusted certificates with digest algorithm &lt;code&gt;SHA-256&lt;/code&gt; and create root CA serials that track how many certificates were issued with &lt;code&gt;-CAcreateserial&lt;/code&gt; , so if &lt;em&gt;not the first certificate&lt;/em&gt; you will use &lt;code&gt;-CAserial&lt;/code&gt; instead. Then, this certificate will stay for 7 days only.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Verify certificate information that should have issuer
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nv"&gt;$ &lt;/span&gt;openssl x509 &lt;span class="nt"&gt;-text&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; CertServer.pem
   …
   Issuer: C &lt;span class="o"&gt;=&lt;/span&gt; TH, ST &lt;span class="o"&gt;=&lt;/span&gt; Bangkok, L &lt;span class="o"&gt;=&lt;/span&gt; BangKhea, O &lt;span class="o"&gt;=&lt;/span&gt; Opsta Thailand, OU &lt;span class="o"&gt;=&lt;/span&gt; DevOps, CN &lt;span class="o"&gt;=&lt;/span&gt; OpstaRootCA, emailAddress &lt;span class="o"&gt;=&lt;/span&gt; watcharin@opsta.co.th
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;We will see Issuer information under Certificate &amp;gt;&amp;gt; Data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Run demo web server
&lt;/h2&gt;

&lt;p&gt;Now you can replace this certificate and private key with the previous session (also topic name &lt;a href="https://dev.to/startpher/little-step-to-use-pki-easiest-mmg"&gt;little-step-to-use-pki-easiest&lt;/a&gt;) and test again. You will install your custom root CA to your browser or machine to see a difference between a single self-signed certificate and certificate with CA issuer.&lt;/p&gt;
&lt;h1&gt;
  
  
  Run demo web server
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create Dockerfile with simple configuration&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:1.20-alpine&lt;/span&gt;

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; default.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ssl /etc/nginx/ssl&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 0:0 /etc/nginx/ssl &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 0:0 /etc/nginx/conf.d/default.conf
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Create Nginx site configuration in following code&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;server&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;listen&lt;/span&gt;       &lt;span class="err"&gt;80&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;server_name&lt;/span&gt;  &lt;span class="err"&gt;localhost&lt;/span&gt; &lt;span class="err"&gt;ssl-lab.example.local&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;return&lt;/span&gt; &lt;span class="err"&gt;301&lt;/span&gt; &lt;span class="err"&gt;https://localhost:8443$request_uri&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;server&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;listen&lt;/span&gt;              &lt;span class="err"&gt;443&lt;/span&gt; &lt;span class="err"&gt;ssl&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;server_name&lt;/span&gt;         &lt;span class="err"&gt;localhost&lt;/span&gt; &lt;span class="err"&gt;ssl-lab.example.local&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;keepalive_timeout&lt;/span&gt;   &lt;span class="err"&gt;70&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;ssl_certificate&lt;/span&gt;     &lt;span class="err"&gt;/etc/nginx/ssl/CertServer.pem&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="err"&gt;/etc/nginx/ssl/rsaServerKey.pem&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;ssl_protocols&lt;/span&gt;       &lt;span class="err"&gt;TLSv1.1&lt;/span&gt; &lt;span class="err"&gt;TLSv1.2&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class="err"&gt;off&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;location&lt;/span&gt; &lt;span class="err"&gt;/&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;root&lt;/span&gt;   &lt;span class="err"&gt;/usr/share/nginx/html&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;        &lt;span class="err"&gt;index&lt;/span&gt;  &lt;span class="err"&gt;index.html&lt;/span&gt; &lt;span class="err"&gt;index.htm&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;error_page&lt;/span&gt;   &lt;span class="err"&gt;500&lt;/span&gt; &lt;span class="err"&gt;502&lt;/span&gt; &lt;span class="err"&gt;503&lt;/span&gt; &lt;span class="err"&gt;504&lt;/span&gt;  &lt;span class="err"&gt;/50x.html&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="py"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/50x.html {&lt;/span&gt;
        &lt;span class="err"&gt;root&lt;/span&gt;   &lt;span class="err"&gt;/usr/share/nginx/html&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Start docker with default options&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; nginx-ca:demo &lt;span class="nb"&gt;.&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 &lt;span class="nt"&gt;-p&lt;/span&gt; 8443:443 nginx-ca:demo
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Use cUrl with verbose argument to verify&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-vIL&lt;/span&gt; &lt;span class="nt"&gt;--cacert&lt;/span&gt; ../rootCA/rootCAcert.pem &lt;span class="nt"&gt;-XGET&lt;/span&gt; https://localhost:8443

&lt;span class="k"&gt;*&lt;/span&gt;   Trying 127.0.0.1:8443...
&lt;span class="k"&gt;*&lt;/span&gt; Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt; port 8443 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; ALPN, offering h2
&lt;span class="k"&gt;*&lt;/span&gt; ALPN, offering http/1.1
&lt;span class="k"&gt;*&lt;/span&gt;  CAfile: rootCA/rootCAcert.pem
&lt;span class="k"&gt;*&lt;/span&gt;  CApath: /etc/ssl/certs
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.0 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Certificate Status &lt;span class="o"&gt;(&lt;/span&gt;22&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.3 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Client hello &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Certificate Status &lt;span class="o"&gt;(&lt;/span&gt;22&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.3 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Server hello &lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Certificate Status &lt;span class="o"&gt;(&lt;/span&gt;22&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Certificate &lt;span class="o"&gt;(&lt;/span&gt;11&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Certificate Status &lt;span class="o"&gt;(&lt;/span&gt;22&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Server key exchange &lt;span class="o"&gt;(&lt;/span&gt;12&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Certificate Status &lt;span class="o"&gt;(&lt;/span&gt;22&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Server finished &lt;span class="o"&gt;(&lt;/span&gt;14&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Certificate Status &lt;span class="o"&gt;(&lt;/span&gt;22&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Client key exchange &lt;span class="o"&gt;(&lt;/span&gt;16&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Finished &lt;span class="o"&gt;(&lt;/span&gt;20&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS change cipher, Change cipher spec &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Certificate Status &lt;span class="o"&gt;(&lt;/span&gt;22&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Finished &lt;span class="o"&gt;(&lt;/span&gt;20&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Finished &lt;span class="o"&gt;(&lt;/span&gt;20&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS header, Certificate Status &lt;span class="o"&gt;(&lt;/span&gt;22&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Finished &lt;span class="o"&gt;(&lt;/span&gt;20&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
&lt;span class="k"&gt;*&lt;/span&gt; ALPN, server accepted to use http/1.1
&lt;span class="k"&gt;*&lt;/span&gt; Server certificate:
&lt;span class="k"&gt;*&lt;/span&gt;  subject: &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ssl-lab.example.local&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;TH&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Bangkok&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Opsta Thailand&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DevOps
&lt;span class="k"&gt;*&lt;/span&gt;  start &lt;span class="nb"&gt;date&lt;/span&gt;: Sep 16 06:36:23 2022 GMT
&lt;span class="k"&gt;*&lt;/span&gt;  expire &lt;span class="nb"&gt;date&lt;/span&gt;: Oct 16 06:36:23 2022 GMT
&lt;span class="k"&gt;*&lt;/span&gt;  subjectAltName: host &lt;span class="s2"&gt;"localhost"&lt;/span&gt; matched cert&lt;span class="s1"&gt;'s "localhost"
*  issuer: C=TH; ST=Bangkok; O=Opsta Thailand; OU=DevOps; CN=OpstaRootCA; emailAddress=watcharin@opsta.co.th
*  SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
&amp;gt; GET / HTTP/1.1
&amp;gt; Host: localhost:8443
&amp;gt; User-Agent: curl/7.81.0
&amp;gt; Accept: */*
&amp;gt; 
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Mark bundle as not supporting multiuse
&amp;lt; HTTP/1.1 200 OK
HTTP/1.1 200 OK
&amp;lt; Server: nginx/1.20.2
Server: nginx/1.20.2
&amp;lt; Date: Mon, 19 Sep 2022 02:57:09 GMT
Date: Mon, 19 Sep 2022 02:57:09 GMT
&amp;lt; Content-Type: text/html
Content-Type: text/html
&amp;lt; Content-Length: 612
Content-Length: 612
&amp;lt; Last-Modified: Tue, 16 Nov 2021 15:04:23 GMT
Last-Modified: Tue, 16 Nov 2021 15:04:23 GMT
&amp;lt; Connection: keep-alive
Connection: keep-alive
&amp;lt; ETag: "6193c877-264"
ETag: "6193c877-264"
&amp;lt; Accept-Ranges: bytes
Accept-Ranges: bytes

&amp;lt; 
* Excess found: excess = 612 url = / (zero-length body)
* Connection #0 to host localhost left intact
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>linux</category>
      <category>operations</category>
    </item>
    <item>
      <title>Little step to use PKI easiest</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Sun, 01 May 2022 12:13:28 +0000</pubDate>
      <link>https://forem.com/startpher/little-step-to-use-pki-easiest-mmg</link>
      <guid>https://forem.com/startpher/little-step-to-use-pki-easiest-mmg</guid>
      <description>&lt;p&gt;From previous posts, I said about &lt;code&gt;What is PKI&lt;/code&gt;. Then this post, I will explain &lt;code&gt;How to use them in some case&lt;/code&gt; and next post I will give an advanced technique for PKI.&lt;/p&gt;

&lt;p&gt;This lab will simulate the scenario in how we can use PKI to make secure communication. All this session we work on terminal, you can following in step-by-step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CLI terminal(On linux or something like that)&lt;/li&gt;
&lt;li&gt;OpenSSL&lt;/li&gt;
&lt;li&gt;cURL&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;tree&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Use self-sign to secure communication
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; We will provide simple web server and map SSL certificate on it. We create connection with cURL and debug it to see what's happen in handshake state. Then, we compare between insecure and secure.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate SSL with CN is &lt;code&gt;ssl-lab.example.local&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$ &lt;/span&gt;openssl req &lt;span class="nt"&gt;-newkey&lt;/span&gt; rsa:4096 &lt;span class="nt"&gt;-nodes&lt;/span&gt; &lt;span class="nt"&gt;-keyout&lt;/span&gt; ssl/ssl-lab.example.local.key &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-x509&lt;/span&gt; &lt;span class="nt"&gt;-sha256&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 3 &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-subj&lt;/span&gt; &lt;span class="s2"&gt;"/C=TH/ST=BKK/O=Opsta/OU=DevOps/CN=ssl-lab.example.local"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-addext&lt;/span&gt; &lt;span class="s2"&gt;"subjectAltName = DNS:ssl-lab.example.local, DNS:localhost, DNS:127.0.0.1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-out&lt;/span&gt; ssl/ssl-lab.example.local.crt

    Generating a RSA private key
    ...................++++
    ..............................................................................++++
    writing new private key to &lt;span class="s1"&gt;'ssl-lab.example.local.key'&lt;/span&gt;
    &lt;span class="nt"&gt;-----&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Explain command&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
For create certificated, we use OpenSSL library to create and manage them.&lt;br&gt;&lt;br&gt;
You can use following arguments to generate 2 files like private and public key:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;req&lt;/strong&gt; = request new resources&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-newkey rsa:4096&lt;/strong&gt; = create new private key with length 4096 keys.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-nodes&lt;/strong&gt; = export output key with plaintext.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-keyout /path/to/save/file.key&lt;/strong&gt; = specific location to save private key.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-x509&lt;/strong&gt; = output with x509 structure.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-sha256&lt;/strong&gt; = choose a message digest algorithm.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-days 3&lt;/strong&gt; = expired date for this certificate in 3 day.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-subj "something"&lt;/strong&gt; = quick add metadata for certificate. The arg must be formatted as &lt;code&gt;/type0=value0/type1=value1/type2=...&lt;/code&gt;, characters may be escaped by &lt;code&gt;\ (backslash)&lt;/code&gt;, no spaces are skipped.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-addext "something"&lt;/strong&gt; = add some extension metadata. The arg must be formatted as &lt;code&gt;key=value&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;-out&lt;/strong&gt; = specific location to save public key and digital certificate.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check file should created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$ &lt;/span&gt;tree ssl

    ssl
    ├── ssl-lab.example.local.crt
    └── ssl-lab.example.local.key
    0 directories, 2 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Verify certificate is matched with openssl cli.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-modulus&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; ssl/ssl-lab.example.local.crt | openssl md5
&lt;span class="o"&gt;(&lt;/span&gt;stdin&lt;span class="o"&gt;)=&lt;/span&gt; ac9173e222ab6b766e49da3069268dd0
&lt;span class="c"&gt;# OUTPUT will difference in your terminal&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;openssl rsa &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-modulus&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; ssl/ssl-lab.example.local.key | openssl md5
&lt;span class="o"&gt;(&lt;/span&gt;stdin&lt;span class="o"&gt;)=&lt;/span&gt; ac9173e222ab6b766e49da3069268dd0
&lt;/code&gt;&lt;/pre&gt;


&lt;blockquote&gt;
&lt;p&gt;If your see same &lt;code&gt;stdin&lt;/code&gt; in 2 output, you're right.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now, you already to create web server in docker for learn how SSL work. First, you will check your docker daemon working and run a sample Nginx web server.&lt;/p&gt;

&lt;p&gt;Create a Nginx site config in following.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="s"&gt;file&lt;/span&gt; &lt;span class="s"&gt;location&lt;/span&gt; &lt;span class="s"&gt;in&lt;/span&gt; &lt;span class="s"&gt;./config/default.conf&lt;/span&gt; &lt;span class="s"&gt;--&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt;       &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt;  &lt;span class="s"&gt;localhost&lt;/span&gt; &lt;span class="s"&gt;ssl-lab.example.local&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;root&lt;/span&gt;   &lt;span class="n"&gt;/usr/share/nginx/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;index&lt;/span&gt;  &lt;span class="s"&gt;index.html&lt;/span&gt; &lt;span class="s"&gt;index.htm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;error_page&lt;/span&gt;   &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="mi"&gt;502&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt; &lt;span class="mi"&gt;504&lt;/span&gt;  &lt;span class="n"&gt;/50x.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/50x.html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;root&lt;/span&gt;   &lt;span class="n"&gt;/usr/share/nginx/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt;              &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt;         &lt;span class="s"&gt;localhost&lt;/span&gt; &lt;span class="s"&gt;ssl-lab.example.local&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;keepalive_timeout&lt;/span&gt;   &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt;     &lt;span class="n"&gt;/etc/nginx/ssl/ssl-lab.example.local.crt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/ssl/ssl-lab.example.local.key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt;       &lt;span class="s"&gt;TLSv1.1&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;root&lt;/span&gt;   &lt;span class="n"&gt;/usr/share/nginx/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;index&lt;/span&gt;  &lt;span class="s"&gt;index.html&lt;/span&gt; &lt;span class="s"&gt;index.htm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;error_page&lt;/span&gt;   &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="mi"&gt;502&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt; &lt;span class="mi"&gt;504&lt;/span&gt;  &lt;span class="n"&gt;/50x.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;/50x.html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;root&lt;/span&gt;   &lt;span class="n"&gt;/usr/share/nginx/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Create a Dockerfile in following.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:1.20-alpine&lt;/span&gt;

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; config/default.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ssl /etc/nginx/ssl&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 0:0 /etc/nginx/ssl &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 0:0 /etc/nginx/conf.d/default.conf
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Then, build customize http server in docker.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; http:lab &lt;span class="nb"&gt;.&lt;/span&gt;

Sending build context to Docker daemon  233.5kB
Step 1/4 : FROM nginx:1.20-alpine
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 5c05ca045835
Step 2/4 : ADD config/default.conf /etc/nginx/conf.d/default.conf
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Using cache
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 1284fcf47f5b
Step 3/4 : COPY ssl /etc/nginx/ssl
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 920c31460cbf
Step 4/4 : RUN &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 0:0 /etc/nginx/ssl     &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 0:0 /etc/nginx/conf.d/default.conf
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Running &lt;span class="k"&gt;in &lt;/span&gt;f8bfa038944f
Removing intermediate container f8bfa038944f
 &lt;span class="nt"&gt;---&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 725ee42e058b
Successfully built 725ee42e058b
Successfully tagged http:lab
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can run http(s) server in terminal.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 &lt;span class="nt"&gt;-p&lt;/span&gt; 8443:443 http:lab
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verify http server has running with &lt;code&gt;docker ps&lt;/code&gt; or &lt;code&gt;curl http://localhost:8080&lt;/code&gt;. It just return result on STDOUT.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker ps

CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS         PORTS                                                                            NAMES
1235d24fe059   http:lab   &lt;span class="s2"&gt;"/docker-entrypoint.…"&lt;/span&gt;   7 minutes ago   Up 7 minutes   0.0.0.0:8080-&amp;gt;80/tcp, :::8080-&amp;gt;80/tcp, 0.0.0.0:8443-&amp;gt;443/tcp, :::8443-&amp;gt;443/tcp   relaxed_montalcini
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can use &lt;code&gt;cURL&lt;/code&gt; to see what happen.&lt;/p&gt;

&lt;p&gt;Get web page with insecure protocol(HTTP).&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; http://localhost:8080

&lt;span class="k"&gt;*&lt;/span&gt;   Trying 127.0.0.1:8080...
&lt;span class="k"&gt;*&lt;/span&gt; Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt; port 8080 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; GET / HTTP/1.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Host: localhost:8080
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; User-Agent: curl/7.74.0
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="k"&gt;*&lt;/span&gt; Mark bundle as not supporting multiuse
&amp;lt; HTTP/1.1 200 OK
&amp;lt; Server: nginx/1.20.2
&amp;lt; Date: Mon, 18 Apr 2022 11:45:35 GMT
&amp;lt; Content-Type: text/html
&amp;lt; Content-Length: 612
&amp;lt; Last-Modified: Tue, 16 Nov 2021 15:04:23 GMT
&amp;lt; Connection: keep-alive
&amp;lt; ETag: &lt;span class="s2"&gt;"6193c877-264"&lt;/span&gt;
&amp;lt; Accept-Ranges: bytes
&amp;lt; 
&amp;lt;&lt;span class="o"&gt;!&lt;/span&gt;DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;&lt;span class="nb"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;
&amp;lt;style&amp;gt;
    body &lt;span class="o"&gt;{&lt;/span&gt;
        width: 35em&lt;span class="p"&gt;;&lt;/span&gt;
        margin: 0 auto&lt;span class="p"&gt;;&lt;/span&gt;
        font-family: Tahoma, Verdana, Arial, sans-serif&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;Welcome to nginx!&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;For online documentation and support please refer to
&amp;lt;a &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://nginx.org/"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;nginx.org&amp;lt;/a&amp;gt;.&amp;lt;br/&amp;gt;
Commercial support is available at
&amp;lt;a &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://nginx.com/"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;nginx.com&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Thank you &lt;span class="k"&gt;for &lt;/span&gt;using nginx.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;span class="k"&gt;*&lt;/span&gt; Connection &lt;span class="c"&gt;#0 to host localhost left intact&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Use &lt;code&gt;curl&lt;/code&gt; in default option and see &lt;strong&gt;error&lt;/strong&gt; in https tunnel.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://localhost:8443

&lt;span class="k"&gt;*&lt;/span&gt;   Trying 127.0.0.1:8443...
&lt;span class="k"&gt;*&lt;/span&gt; Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt; port 8443 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; ALPN, offering h2
&lt;span class="k"&gt;*&lt;/span&gt; ALPN, offering http/1.1
&lt;span class="k"&gt;*&lt;/span&gt; successfully &lt;span class="nb"&gt;set &lt;/span&gt;certificate verify locations:
&lt;span class="k"&gt;*&lt;/span&gt;  CAfile: /etc/ssl/certs/ca-certificates.crt
&lt;span class="k"&gt;*&lt;/span&gt;  CApath: /etc/ssl/certs
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.3 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Client hello &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.3 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Server hello &lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Certificate &lt;span class="o"&gt;(&lt;/span&gt;11&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS alert, unknown CA &lt;span class="o"&gt;(&lt;/span&gt;560&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; SSL certificate problem: self signed certificate
&lt;span class="k"&gt;*&lt;/span&gt; Closing connection 0
curl: &lt;span class="o"&gt;(&lt;/span&gt;60&lt;span class="o"&gt;)&lt;/span&gt; SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In the error response, We can translate in a part of message.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;They're try to make a connection to endpoint.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Trying 127.0.0.1:8443...  
Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt; port 8443 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;They're prepared information for connection.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ALPN, offering h2  
ALPN, offering http/1.1  
successfully &lt;span class="nb"&gt;set &lt;/span&gt;certificate verify locations:  
  CAfile: /etc/ssl/certs/ca-certificates.crt  
  CApath: /etc/ssl/certs 
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;They're send first contact message in &lt;code&gt;hello&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;TLSv1.3 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Client hello &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;:  
TLSv1.3 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Server hello &lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Server send digital certificate to client.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Certificate &lt;span class="o"&gt;(&lt;/span&gt;11&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Client verify certificate integrity and found in self-sign issue.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS alert, unknown CA &lt;span class="o"&gt;(&lt;/span&gt;560&lt;span class="o"&gt;)&lt;/span&gt;:
SSL certificate problem: self signed certificate
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Client close connection and report error message.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Closing connection 0  
curl: &lt;span class="o"&gt;(&lt;/span&gt;60&lt;span class="o"&gt;)&lt;/span&gt; SSL certificate problem: self signed certificate  
More details here: &lt;span class="s1"&gt;'https://curl.se/docs/sslcerts.html'&lt;/span&gt;  

curl failed to verify the legitimacy of the server and therefore could not  
establish a secure connection to it. To learn more about this situation and  
how to fix it, please visit the web page mentioned above.  
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;You can use &lt;code&gt;crt&lt;/code&gt; certificate file in previous step to trust this communication.&lt;/p&gt;

&lt;p&gt;You can see normal establish connection in debug log.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;--cacert&lt;/span&gt; ssl/ssl-lab.example.local.crt https://localhost:8443

&lt;span class="k"&gt;*&lt;/span&gt;   Trying 127.0.0.1:8443...
&lt;span class="k"&gt;*&lt;/span&gt; Connected to localhost &lt;span class="o"&gt;(&lt;/span&gt;127.0.0.1&lt;span class="o"&gt;)&lt;/span&gt; port 8443 &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#0)&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt; ALPN, offering h2
&lt;span class="k"&gt;*&lt;/span&gt; ALPN, offering http/1.1
&lt;span class="k"&gt;*&lt;/span&gt; successfully &lt;span class="nb"&gt;set &lt;/span&gt;certificate verify locations:
&lt;span class="k"&gt;*&lt;/span&gt;  CAfile: ssl/ssl-lab.example.local.crt
&lt;span class="k"&gt;*&lt;/span&gt;  CApath: /etc/ssl/certs
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.3 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Client hello &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.3 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Server hello &lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Certificate &lt;span class="o"&gt;(&lt;/span&gt;11&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Server key exchange &lt;span class="o"&gt;(&lt;/span&gt;12&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Server finished &lt;span class="o"&gt;(&lt;/span&gt;14&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Client key exchange &lt;span class="o"&gt;(&lt;/span&gt;16&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS change cipher, Change cipher spec &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;OUT&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Finished &lt;span class="o"&gt;(&lt;/span&gt;20&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; TLSv1.2 &lt;span class="o"&gt;(&lt;/span&gt;IN&lt;span class="o"&gt;)&lt;/span&gt;, TLS handshake, Finished &lt;span class="o"&gt;(&lt;/span&gt;20&lt;span class="o"&gt;)&lt;/span&gt;:
&lt;span class="k"&gt;*&lt;/span&gt; SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
&lt;span class="k"&gt;*&lt;/span&gt; ALPN, server accepted to use http/1.1
&lt;span class="k"&gt;*&lt;/span&gt; Server certificate:
&lt;span class="k"&gt;*&lt;/span&gt;  subject: &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;TH&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;BKK&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Opsta&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DevOps&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ssl-lab.example.local
&lt;span class="k"&gt;*&lt;/span&gt;  start &lt;span class="nb"&gt;date&lt;/span&gt;: Apr 17 15:41:24 2022 GMT
&lt;span class="k"&gt;*&lt;/span&gt;  expire &lt;span class="nb"&gt;date&lt;/span&gt;: Apr 20 15:41:24 2022 GMT
&lt;span class="k"&gt;*&lt;/span&gt;  subjectAltName: host &lt;span class="s2"&gt;"localhost"&lt;/span&gt; matched cert&lt;span class="se"&gt;\'&lt;/span&gt;s &lt;span class="s2"&gt;"localhost"&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt;  issuer: &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;TH&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;ST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;BKK&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Opsta&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;OU&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DevOps&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;CN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ssl-lab.example.local
&lt;span class="k"&gt;*&lt;/span&gt;  SSL certificate verify ok.
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; GET / HTTP/1.1
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Host: localhost:8443
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; User-Agent: curl/7.74.0
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Accept: &lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="k"&gt;*&lt;/span&gt; Mark bundle as not supporting multiuse
&amp;lt; HTTP/1.1 200 OK
&amp;lt; Server: nginx/1.20.2
&amp;lt; Date: Mon, 18 Apr 2022 12:03:50 GMT
&amp;lt; Content-Type: text/html
&amp;lt; Content-Length: 612
&amp;lt; Last-Modified: Tue, 16 Nov 2021 15:04:23 GMT
&amp;lt; Connection: keep-alive
&amp;lt; ETag: &lt;span class="s2"&gt;"6193c877-264"&lt;/span&gt;
&amp;lt; Accept-Ranges: bytes
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;You can see how to use PKI concept to make secure communication in this post. Then, you can adapt this step to your application to basic secure communication.&lt;br&gt;&lt;br&gt;
See ya in next posts to use CA for intermediate issuer.&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>pki</category>
      <category>docker</category>
    </item>
    <item>
      <title>What we should know in PKI</title>
      <dc:creator>Watcharin(start)</dc:creator>
      <pubDate>Mon, 18 Apr 2022 12:36:31 +0000</pubDate>
      <link>https://forem.com/startpher/what-we-should-know-in-pki-l25</link>
      <guid>https://forem.com/startpher/what-we-should-know-in-pki-l25</guid>
      <description>&lt;h2&gt;
  
  
  PKI(Public Key Infrastructure)
&lt;/h2&gt;

&lt;p&gt;In this topic, we're learn about &lt;code&gt;What is PKI&lt;/code&gt; and &lt;code&gt;How can we use it&lt;/code&gt;. You can imagine the importance of &lt;strong&gt;security&lt;/strong&gt; and &lt;strong&gt;privacy&lt;/strong&gt; in customer’s data. This topic should help you to understand.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;What is PKI?&lt;/code&gt; Before answering this question, you should know: What is &lt;strong&gt;Symmetric&lt;/strong&gt; and &lt;strong&gt;Asymmetric&lt;/strong&gt; encryption.  &lt;/p&gt;

&lt;p&gt;You can understand a key difference between &lt;strong&gt;Symmetric&lt;/strong&gt; and &lt;strong&gt;Asymmetric&lt;/strong&gt; encryption. In a simple scenario, Asymmetric encryption will be stronger and more secure than Symmetric encryption because we do not use same secret key for encrypt/decrypt messages.  &lt;/p&gt;

&lt;p&gt;Information security has grown to be a hugely important factor in any communication, transaction, and ETC. A little vulnerability or weakness in communication that can be leveraged to devastating effects. This session will show you two encryption techniques that can be used to tighten communication security.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Little note
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Algorithm&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o9E4u3cO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymsh9ljv4ng6m1utxjrm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o9E4u3cO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ymsh9ljv4ng6m1utxjrm.png" alt="algorithm" width="501" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a process or set of rules to be followed in calculations or other problem-solving operations.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An encryption algorithm that means formula in mathematical procedure for shift a bits or convert in original data. An information is made in cipher text and requires use of the key to transform the data into its original form.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cryptography&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The study of secure communications techniques that allow only the sender and intended recipient of a message to view its contents. The term is derived from the Greek word kryptos, which means hidden. An encryption algorithm will take an original message(plain text) converted to cipher text. We can use the key to &lt;strong&gt;encrypt&lt;/strong&gt; or &lt;strong&gt;decrypt&lt;/strong&gt; messages.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Symmetric encryption
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U9YFi5m6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whjxh6mdgbg93awnvqbh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U9YFi5m6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whjxh6mdgbg93awnvqbh.png" alt="Symmetric Encryption" width="796" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a simplest procedure used to convert messages between &lt;strong&gt;plain text&lt;/strong&gt; and &lt;strong&gt;cipher text&lt;/strong&gt;. We can use the same key in the encryption and decryption process. It’s easy to manage and exchange for sender and receiver to use it. You can allow your services to generate the secret key and exchange in their trusted zone to communicate with a secure tunnel. You mostly set timeout or expire in a secret key to avoid loopholes in capture pattern messages.&lt;/p&gt;

&lt;p&gt;Example encryption algorithm such as &lt;code&gt;Blowfish&lt;/code&gt;, &lt;code&gt;AES&lt;/code&gt;, &lt;code&gt;RC4&lt;/code&gt;, &lt;code&gt;DES&lt;/code&gt;, &lt;code&gt;RC5&lt;/code&gt;, and &lt;code&gt;RC6&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Asymmetric encryption
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WmKidpaH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5dm43zoq9df4g2osbkv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WmKidpaH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5dm43zoq9df4g2osbkv.png" alt="Asymmetric Encryption" width="796" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are public and private keys to encrypt/decrypt, which is a new method for isolating one secret key to encryption and one secret key to decryption. You will create two secret keys: public key and private key. It is most likely used to exchange on extranet(also internet) or untrust zone to secure communication. You can share a public key to another person for only encrypting some message and send it to a person that has a private key for decrypting the cipher into the original message.&lt;/p&gt;

&lt;p&gt;Example encryption algorithm such as &lt;code&gt;RSA&lt;/code&gt;, &lt;code&gt;ECC&lt;/code&gt;, &lt;code&gt;Diffie-Hellman&lt;/code&gt;, &lt;code&gt;DSS&lt;/code&gt;, and &lt;code&gt;DSA&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSL/TLS communication(combination of Asymmetric and Symmetric)
&lt;/h3&gt;

&lt;p&gt;For most likely cases, We can summarize steps for creating communication between client and server. Before any communication, They must initial rules and keys for security. You can follow these steps to understand how they work to create secure communication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PQAxecFA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kjspull2eewbvnozf7zm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PQAxecFA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kjspull2eewbvnozf7zm.png" alt="SSL/TLS handshake" width="761" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Client --&amp;gt; send hello package to target server. In message has client's information such as support cipher suits(algorithms), SSL/TLS versions, and other.&lt;/li&gt;
&lt;li&gt;Server --&amp;gt; Check client's information that match a policies you configure. If not match they will reject request. For match policies, They send certificate with public key to client.&lt;/li&gt;
&lt;li&gt;Client --&amp;gt; Verify server's certificate that trusted or not. The certificate information should match in your request like common name, expired date, and ETC.&lt;/li&gt;
&lt;li&gt;Client --&amp;gt; Create session key(also symmetric secret key) for secure communication tunnel. Then encrypt payload with public key in certificate before send them to server.&lt;/li&gt;
&lt;li&gt;Server --&amp;gt; Receive message with session key, so decrypt with private key. They send acknowledge message to client for accept this key in secure tunnel.&lt;/li&gt;
&lt;li&gt;Both --&amp;gt; Send/receive messages with session key. If session key expire, they will repeat above step to establish communication.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  More secure with CA(Certificate Authority)
&lt;/h3&gt;

&lt;p&gt;In the previous topic, We can see some weaknesses in the initial process. If your contact server endpoint is not your target server, they will fake the server or something like that. Can you trust it?  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bQaw5cMW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/via5prb2n92xgm7adq36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bQaw5cMW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/via5prb2n92xgm7adq36.png" alt="SSL with CA" width="751" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For solved, You can use CA to help you verify certificates that you can trust. In step 3, you can get the issuer from the server's certificate and ask them to guarantee this certificate.  &lt;/p&gt;

&lt;p&gt;If you have doubt in CA issuer from the server certificate. You can trust the root CA in your host, so you will integrity check with the root CA for a guarantee certificate. We call this process is &lt;code&gt;Chain of trust&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Next, I will show you how it work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reference
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.ssl2buy.com/wiki/symmetric-vs-asymmetric-encryption-what-are-differences"&gt;https://www.ssl2buy.com/wiki/symmetric-vs-asymmetric-encryption-what-are-differences&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/introduction-to-algorithms/"&gt;https://www.geeksforgeeks.org/introduction-to-algorithms/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://encryptionconsulting.com/education-center/what-is-cryptography/"&gt;https://encryptionconsulting.com/education-center/what-is-cryptography/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>pki</category>
      <category>security</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
