<?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: Rohit Salecha</title>
    <description>The latest articles on Forem by Rohit Salecha (@salecharohit).</description>
    <link>https://forem.com/salecharohit</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%2F684103%2Fcb79ff56-6229-4314-9259-41c51b749f61.jpeg</url>
      <title>Forem: Rohit Salecha</title>
      <link>https://forem.com/salecharohit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/salecharohit"/>
    <language>en</language>
    <item>
      <title>My Cloud Desktop</title>
      <dc:creator>Rohit Salecha</dc:creator>
      <pubDate>Thu, 16 Mar 2023 16:33:15 +0000</pubDate>
      <link>https://forem.com/salecharohit/my-cloud-desktop-25f</link>
      <guid>https://forem.com/salecharohit/my-cloud-desktop-25f</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;For quite some time I've primarily been using *nix terminal (Ubuntu-WSL2 and MacOS) and VSCode for most of my research/pentest and day-to-day work. I like to keep my base machine as clean as possible with the least number of softwares needed like just the CLI and browser. I would use this bare-minimum software to connect to my cloud machine where most of my softwares/services are installed like nmap,metasploit,awscli,terraform etc ... &lt;/p&gt;

&lt;p&gt;But the problem was that I the requirement for this machine was quite intermittent and sporadic, it was never constant. So each time I needed the machine, I'd login to my console,start it,change my IP in the laptop and then go about doing my job. This was quite cumbersome and tedious and manual.&lt;/p&gt;

&lt;p&gt;Also, I didn't want to remember the IP address everytime I spin up, just the Domain name as it becomes easier to configure domain names on internet than IP addresses.&lt;/p&gt;

&lt;p&gt;Hence, out of pure laziness I decided to write a &lt;code&gt;terraform&lt;/code&gt; + &lt;code&gt;ansible&lt;/code&gt; script (a combination I'd been wanting to work on for a long long long long long time) that does the following &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spins up an EC2 Ubuntu Focal (❤️) &lt;/li&gt;
&lt;li&gt;Configures it with my most used softwares - VSCode,NMap,Nuclei,Semgrep,awscli and some pentest tools.&lt;/li&gt;
&lt;li&gt;Configure my Duck DNS domain name (rohit-salecha.duckdns.org) with the IP Address of the EC2 with LetsEncrypt Certificate. &lt;/li&gt;
&lt;li&gt;Have a Source IP restriction such that it is accessible only from a specific IP Address like my home ip.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pre-Requisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account with credentials configured in CLI

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;DuckDNS Account and Domain - &lt;a href="https://www.duckdns.org/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://www.duckdns.org/" rel="noopener noreferrer"&gt;https://www.duckdns.org/&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Please read through the Terms and Conditions before using this service &lt;a href="https://www.duckdns.org/tac.jsp" rel="noopener noreferrer"&gt;https://www.duckdns.org/tac.jsp&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Terraform binary installed

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Minimum version 1.4&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Warnings
&lt;/h2&gt;

&lt;p&gt;Some important warnings before you start using the code&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running the scripts in this blog will charge you money as we are downloading quite a lot of content to the cloud machine and the bare minimum 4 GB RAM machine is needed which doesn't fall into free tier.&lt;/li&gt;
&lt;li&gt;Opening up of port 80 is necessary for the entire internet as it's needed for LetsEncrypt validation.
&lt;a href="https://letsencrypt.org/docs/allow-port-80/" rel="noopener noreferrer"&gt;https://letsencrypt.org/docs/allow-port-80/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Port 53 is also open but no service is currently configured to listen on it. You can start your own DNS server for SSRF pingbacks.
&lt;/li&gt;
&lt;li&gt;Any abuse of the code and the service provided is solely the responsibility of the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Duck DNS
&lt;/h2&gt;

&lt;p&gt;Duck DNS is a free service where you can create a sub-domain of your choice .duckdns.org and they  have a simple curl command that allows you to update the DNS A record with the IP Address of the EC2 machine as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.duckdns.org/update?domains={YOURVALUE}&amp;amp;token={YOURVALUE}[&amp;amp;ip={YOURVALUE}][&amp;amp;ipv6={YOURVALUE}][&amp;amp;verbose=true][&amp;amp;clear=true]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've implemented this as a curl command in my terraform code which automatically reads the IP from the EC2 machine and updates the DNS record.&lt;/p&gt;

&lt;p&gt;In order to use this, you'll first need to sign up, create a sub-domain of your choice and save the token provided as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F1.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%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F1.png" alt="Duck DNS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any abuse of the code and the service provided is solely the responsibility of the user.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Github Clone
&lt;/h2&gt;

&lt;p&gt;Clone the Github repository &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/salecharohit/my-cloud-desktop.git" rel="noopener noreferrer"&gt;https://github.com/salecharohit/my-cloud-desktop.git&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd&amp;gt; git clone https://github.com/salecharohit/my-cloud-desktop.git
cmd&amp;gt; &lt;span class="nb"&gt;cd &lt;/span&gt;my-cloud-desktop
cmd&amp;gt; &lt;span class="nb"&gt;mv &lt;/span&gt;terraform.auto.tfvars.bak terraform.auto.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once clone is done edit the &lt;strong&gt;terraform.auto.tfvars&lt;/strong&gt; file and configure the following required variables with the necessary data.&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="c1"&gt;# Region of deployment of EC2, its recommended to deploy closest possible to avoid latency&lt;/span&gt;
&lt;span class="s"&gt;region                      = "ap-south-1"&lt;/span&gt;
&lt;span class="c1"&gt;# Recommneded is t3.medium or select from here https://instances.vantage.sh/&lt;/span&gt;
&lt;span class="s"&gt;instance_type               = "t3.medium"&lt;/span&gt;
&lt;span class="c1"&gt;# Whether to apply source IP restrictions for SSH Access. &lt;/span&gt;
&lt;span class="c1"&gt;# IP Address from where you are executing the terraform script will be used to restrict access to port 443 and 22.&lt;/span&gt;
&lt;span class="c1"&gt;# Check file networking.tf&lt;/span&gt;
&lt;span class="s"&gt;apply_source_ip_restriction = &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="s"&gt;duckdns_token               = "XXXXXXXXXXXXXXXXXXXXXXXXXX"&lt;/span&gt;
&lt;span class="s"&gt;duckdns_hostname            = "XXXXXXXXXXXX.duckdns.org"&lt;/span&gt;
&lt;span class="s"&gt;email                       = "XXXXXX@XXXXXX.com"&lt;/span&gt;
&lt;span class="s"&gt;vscode_password             = "XXXXXXXXXXXXXXXXXXXXXX"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE : The &lt;strong&gt;terraform.auto.tfvars&lt;/strong&gt; is part of your .gitignore hence any changes made in this file will not be comitted in your remote repository and will only remain on your machine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Terraform Execution
&lt;/h2&gt;

&lt;p&gt;Once everything is set its time to execute our code using the commands as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd&amp;gt; &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-profile&amp;gt;
cmd&amp;gt; &lt;span class="nb"&gt;cd &lt;/span&gt;my-cloud-desktop
cmd&amp;gt; terraform init
cmd&amp;gt; terraform validate
cmd&amp;gt; terraform apply &lt;span class="nt"&gt;--auto-approve&lt;/span&gt;

XXXXXXXXXXXXXXX------SNIPPED-------XXXXXXXXXXXXXXXXXXXXX
Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 43 added, 0 changed, 0 destroyed.

Outputs:

server_ip &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"15.206.158.91"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Accessing VSCode in browser
&lt;/h2&gt;

&lt;p&gt;Once the apply is complete navigate to domain name you've configured and enter the password as shown in the screen 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%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F2.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%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F2.png" alt="Accessing VSCode in browser Password"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After entering the password we can start using VSCode as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F3.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%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F3.png" alt="Accessing VSCode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Accessing Terminal from VSCode ex : Metasploit&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%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F6.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%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F6.png" alt="Accessing CLI from browser"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing Server through SSH
&lt;/h2&gt;

&lt;p&gt;The code generates a private SSH key called &lt;code&gt;ubuntu_key.pem&lt;/code&gt; in the keypair.tf file and stores it in your local system. The .gitignore file ignores all *.pem files and hence this will not be committed to your Git history and usable only from the local machine you are operating from.&lt;/p&gt;

&lt;p&gt;Accessing the server is quite simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd&amp;gt; ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ubuntu_key.pem ubuntu@&amp;lt;your-duckdns-domain&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F4.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%2Fwww.rohitsalecha.com%2Fproject%2Fmy_cloud_desktop%2Fimg%2F4.png" alt="SSH through DNS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or you could also save it in an ssh config as which is something that you no longer need to change now. Just ensure the &lt;code&gt;path-to-ubuntu-key&lt;/code&gt; is configured correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;Host&lt;/span&gt; &lt;span class="n"&gt;cloud&lt;/span&gt;-&lt;span class="n"&gt;desktop&lt;/span&gt;
&lt;span class="n"&gt;HostName&lt;/span&gt; &amp;lt;&lt;span class="n"&gt;your&lt;/span&gt;-&lt;span class="n"&gt;domain&lt;/span&gt;&amp;gt;.&lt;span class="n"&gt;duckdns&lt;/span&gt;.&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;Port&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;
&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="n"&gt;ubuntu&lt;/span&gt;
&lt;span class="n"&gt;IdentitiesOnly&lt;/span&gt; &lt;span class="n"&gt;yes&lt;/span&gt;
&lt;span class="n"&gt;IdentityFile&lt;/span&gt; &amp;lt;&lt;span class="n"&gt;path&lt;/span&gt;-&lt;span class="n"&gt;to&lt;/span&gt;-&lt;span class="n"&gt;ubuntu&lt;/span&gt;-&lt;span class="n"&gt;key&lt;/span&gt;&amp;gt;/&lt;span class="n"&gt;ubuntu_key&lt;/span&gt;.&lt;span class="n"&gt;pem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Accessing Miscellaneous Services
&lt;/h2&gt;

&lt;p&gt;In case you wish to access any GUI service within the server that's running on a port like 8080, but you donot wish to open it up on the internet then simply execute the following commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ubuntu_key.pem ubuntu@&amp;lt;your-duckdns-domain&amp;gt; &lt;span class="nt"&gt;-L&lt;/span&gt; 8081:localhost:8080
curl http://localhost:8081
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the above command you are instructing that port 8081 on your local computer needs to be forwarded to port 8080 on the EC2 server. This forwarding of the traffic is now happening over a secure channel and you donot have to open up your machine to the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform Destroy
&lt;/h2&gt;

&lt;p&gt;To destroy the app simply fire the below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd&amp;gt; &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-profile&amp;gt; 
cmd&amp;gt; terraform destroy &lt;span class="nt"&gt;--auto-approve&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>AWS EKS Playground using Terraform</title>
      <dc:creator>Rohit Salecha</dc:creator>
      <pubDate>Wed, 22 Feb 2023 10:44:49 +0000</pubDate>
      <link>https://forem.com/salecharohit/aws-eks-playground-using-terraform-3jk</link>
      <guid>https://forem.com/salecharohit/aws-eks-playground-using-terraform-3jk</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;This blog is a leaf out of my book Practical GitOps where I discuss how one can manage AWS infrastructure using Terraform and orchestrate it with Github Actions.&lt;/p&gt;

&lt;p&gt;As part of my book I’ve deployed a working SpringBoot application on AWS EKS as a base for explaining everything around it right from AWS Organizations to Secrets Management, IRSA to setting up an observability stack. This blog is all about that base application and the surrounding infrastructure.&lt;/p&gt;

&lt;p&gt;Also, with the entire cloud and cloud native ecosystem having so many different tools I needed a playground which I could set up quickly and then destroy. This project gives me that flexibility so that I can quickly set up an EKS(kubernetes) environment and then play around with various different tools and its obvious integration with AWS.&lt;/p&gt;

&lt;p&gt;Link to buy the book and how to get a 20% discount coupon code is shared towards the end of the post&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fw0S3gVT-wkON1l46vEXQb5resRWEkJ-60u7-EHS7hqkIbu9Zvz5gyHjO_GuPMYaot-MdU5xZJ2arYqAq6PRHisD05HRfsPrZAdQj2k0WQ7w9lwUU38G6E_3GkYc8gof7_pF3ing81FaFBqkubtV6Y_0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fw0S3gVT-wkON1l46vEXQb5resRWEkJ-60u7-EHS7hqkIbu9Zvz5gyHjO_GuPMYaot-MdU5xZJ2arYqAq6PRHisD05HRfsPrZAdQj2k0WQ7w9lwUU38G6E_3GkYc8gof7_pF3ing81FaFBqkubtV6Y_0" title="AWS EKS Architecture" alt="AWS EKS Architecture" width="671" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above diagram shows a high-level architecture of the base infrastructure that we are doing to deploy.Other than Route53, rest everything will be set up using Terraform in this blog. A brief description follows&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We’ll be creating a VPC with three subnets namely: public,private and database.&lt;/li&gt;
&lt;li&gt;Public subnet will have resources that need to be externally facing like the AWS Application Load Balancer which will be spun up as an Ingress Controller.&lt;/li&gt;
&lt;li&gt;Our Kubernetes Nodes (managed by us) will be spun up in the Private subnet having and will not be accessible from the internet.&lt;/li&gt;
&lt;li&gt;The Master node of Kubernetes is completely managed by AWS and hence we have no control over its placement. However the Kubernetes API-endpoint will be available over 443 on the internet for authentication to EKS cluster.&lt;/li&gt;
&lt;li&gt;Our PostgreSQL Database is living in the database subnet which is a separate subnet having additional security controls.&lt;/li&gt;
&lt;li&gt;The connectivity between the Public Subnet and the Private subnet is established using a NAT gateway. There is no NAT gateway to route traffic between Database Subnet and Public subnet hence it is sufficiently isolated.&lt;/li&gt;
&lt;li&gt;We’ll be utilizing AWS Certificate Manager (ACM) to generate the public SSL certificates for our application. Our Terraform code will not only generate the certificates but also validate the certificates by creating necessary Route53 name records.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pre-Requisites
&lt;/h2&gt;

&lt;p&gt;In order to follow along this blog you’ll need the following&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account with credentials configured in CLI

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;A top level domain/subdomain name&lt;/li&gt;

&lt;li&gt;Kubectl Utility - Kubectl is the default utility to talk with the kubernetes service that we’ll be spinning up using Terraform. Recommended to have version 1.20 or above.

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/tools/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Terraform binary installed

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli" rel="noopener noreferrer"&gt;https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Your favorite Code editor&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;WARNING : Running the scripts in this blog will charge you some amount of money as AWS EKS and other services here are not under the free-tier. Also, this is only a demo project. Exercise caution and encourage you to learn more about it before trying it out.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  AWS Route53
&lt;/h2&gt;

&lt;p&gt;First thing we need to do is create a &lt;a href="https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-working-with.html" rel="noopener noreferrer"&gt;Route53 Hosted Zone&lt;/a&gt; with a domain/subdomain of your choice. I am demonstrating using a sub-domain that is &lt;strong&gt;ekspg.rohitsalecha.com&lt;/strong&gt;. You could use a primary domain as well but the nameserver configuration will need to be tweaked accordingly.&lt;/p&gt;

&lt;p&gt;The below command will help you in creating a route53 hosted zone from CLI and make a note of the &lt;strong&gt;NameServers&lt;/strong&gt; as shown below. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“--caller-reference”&lt;/strong&gt; is a random number so the best bet is to use your current timestamp as shown.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd&amp;gt; &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-profile&amp;gt;
cmd&amp;gt; aws route53 create-hosted-zone &lt;span class="nt"&gt;--name&lt;/span&gt; ekspg.rohitsalecha.com &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--caller-reference&lt;/span&gt; 2023-02-21-24:35

&lt;span class="o"&gt;{&lt;/span&gt;
XXXXXXXXXXXXXXX------SNIPPED-------XXXXXXXXXXXXXXXXXXXXX
    &lt;span class="s2"&gt;"DelegationSet"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"NameServers"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;"ns-537.awsdns-03.net"&lt;/span&gt;,
            &lt;span class="s2"&gt;"ns-449.awsdns-56.com"&lt;/span&gt;,
            &lt;span class="s2"&gt;"ns-1848.awsdns-39.co.uk"&lt;/span&gt;,
            &lt;span class="s2"&gt;"ns-1415.awsdns-48.org"&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;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring NameServers
&lt;/h2&gt;

&lt;p&gt;The command output provides 4 different Nameserver values that need to be configured with your DNS provider depending on whether you are configuring a Top-level domain like &lt;strong&gt;rohitsalecha.com&lt;/strong&gt; or a subdomain like &lt;strong&gt;ekspg.rohitsalecha.com&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have GoDaddy as your DNS provider then follow this guide for Top-Level Domains &lt;a href="https://in.godaddy.com/help/change-nameservers-for-my-domains-664" rel="noopener noreferrer"&gt;https://in.godaddy.com/help/change-nameservers-for-my-domains-664&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For subdomain in GoDaddy this is how you can add a NS as a record &lt;a href="https://in.godaddy.com/help/add-an-ns-record-19212" rel="noopener noreferrer"&gt;https://in.godaddy.com/help/add-an-ns-record-19212&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since I am using a Subdomain this is how I configured my NS records provided by the hosted zone command fired above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FW40OyHneb4wWSE0HZ9ESbXMqPFAOLmFN4LyYsqvUGUfq01kU0vb45R3b7sO8KUZSu2jBa2RF9AOU_ci8aU8_Pg1HSnDqBZTtZoGnDQ3L50gcXUk22nftibF2y0YCjHQ1x_HO8nh7mlc7-aGSXyEDaqY" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FW40OyHneb4wWSE0HZ9ESbXMqPFAOLmFN4LyYsqvUGUfq01kU0vb45R3b7sO8KUZSu2jBa2RF9AOU_ci8aU8_Pg1HSnDqBZTtZoGnDQ3L50gcXUk22nftibF2y0YCjHQ1x_HO8nh7mlc7-aGSXyEDaqY" title="NS Records Configuration" alt="NS Records Configuration" width="1600" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once your DNS configuration is done do give it a check on &lt;a href="https://dnschecker.org/" rel="noopener noreferrer"&gt;https://dnschecker.org/&lt;/a&gt; as shown below. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Only once all is green move on to the next steps. Give it atleast 30 mins to propogate&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FrIkm4c4VlsqvbB0XjUGWU5FWdQntiAhuzfqb6DucdPcZXGEnu7tGBhitG_DX85fvAn80voNHbs9E2dHeMLMDIrHOnNLk05ganFFnxvkY7b_ZGgihgAYD6NWTtRxtzV94-ggprnJB0DEasUosuTo8VSQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FrIkm4c4VlsqvbB0XjUGWU5FWdQntiAhuzfqb6DucdPcZXGEnu7tGBhitG_DX85fvAn80voNHbs9E2dHeMLMDIrHOnNLk05ganFFnxvkY7b_ZGgihgAYD6NWTtRxtzV94-ggprnJB0DEasUosuTo8VSQ" title="DNS Checker" alt="dns checker ekspg.rohitsalecha.com" width="1600" height="905"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Github Clone
&lt;/h2&gt;

&lt;p&gt;Clone the Github repository  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/salecharohit/eks-playground" rel="noopener noreferrer"&gt;https://github.com/salecharohit/eks-playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open the repository in your favorite code editor and open the file &lt;strong&gt;infra/terraform.auto.tfvars&lt;/strong&gt; as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File: infra/terraform.auto.tfvars
{
XXXXXXXXXXXXXXX------SNIPPED-------XXXXXXXXXXXXXXXXXXXXX

33: 
34: /********** EKS Module ***************/
35: 
36: eks_version    = "1.21"
37: instance_types = ["t3.medium","t3.small"]
38: 
39: /********** Global Variables ***************/
40: org_name = "ekspg"
41: domain   = "ekspg.rohitsalecha.com"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to modify the value &lt;strong&gt;domain&lt;/strong&gt; on &lt;strong&gt;Line41&lt;/strong&gt; as shown above pointing to the domain that you’ve setup in the earlier section.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: Feel free to modify the above parameters as you see fit provided you know what you are doing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Terraform Execution
&lt;/h2&gt;

&lt;p&gt;Once the modification of the domain name is done, its time to execute our code using the commands as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd&amp;gt; &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-profile&amp;gt;
cmd&amp;gt; &lt;span class="nb"&gt;cd &lt;/span&gt;eks-playground/infra
cmd&amp;gt; terraform init
cmd&amp;gt; terraform validate
cmd&amp;gt; terraform plan
cmd&amp;gt; terraform apply &lt;span class="nt"&gt;--auto-approve&lt;/span&gt;

XXXXXXXXXXXXXXX------SNIPPED-------XXXXXXXXXXXXXXXXXXXXX
Apply &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; Resources: 88 added, 0 changed, 0 destroyed.

Outputs:

cluster_name &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ekspg-us-east-1-dev"&lt;/span&gt;
region &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;After executing Terraform apply it’ll take upto 20-25 minutes to spin up the entire application+infrastructure. Once the Apply Complete message is shown , wait for 5 minutes more for the Load Balancer to warm up and our site should start functioning and accessible as shown below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ekspg.rohitsalecha.com" rel="noopener noreferrer"&gt;https://ekspg.rohitsalecha.com&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FAIVuWBAQH85c0BTs9nFbFAxWPVkZAo8ceKtiYcoSz5YEWBl9V5q1nfDQAba3U-2R3Udji7UhPWJH9yRxf7MkqUji6lxExRVcsrqD7J7xpBpd60TSouh4_2wvLx3pBkddGMc0QVbpxbiqXsBf1pwBg2Q" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FAIVuWBAQH85c0BTs9nFbFAxWPVkZAo8ceKtiYcoSz5YEWBl9V5q1nfDQAba3U-2R3Udji7UhPWJH9yRxf7MkqUji6lxExRVcsrqD7J7xpBpd60TSouh4_2wvLx3pBkddGMc0QVbpxbiqXsBf1pwBg2Q" title="Access EKS PG App" alt="Accessing EKS PG Prod App" width="581" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Accessing through kubectl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd&amp;gt; &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-profile&amp;gt;
cmd&amp;gt; &lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;terraform output &lt;span class="nt"&gt;-raw&lt;/span&gt; region&lt;span class="si"&gt;)&lt;/span&gt;
cmd&amp;gt; &lt;span class="nv"&gt;CLUSTER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;terraform output &lt;span class="nt"&gt;-raw&lt;/span&gt; cluster_name&lt;span class="si"&gt;)&lt;/span&gt;
cmd&amp;gt; aws eks &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="nv"&gt;$REGION&lt;/span&gt; update-kubeconfig &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$CLUSTER&lt;/span&gt;

Added new context arn:aws:eks:us-east-1:26XXXXXXXXX23:cluster/ekspg-us-east-1-prod to /Users/XXXXXXXXXXX/.kube/config

cmd&amp;gt; kubectl get nodes

NAME                          STATUS   ROLES    AGE   VERSION
ip-10-0-12-238.ec2.internal   Ready    &amp;lt;none&amp;gt;   14m   v1.21.14-eks-48e63af
ip-10-0-13-155.ec2.internal   Ready    &amp;lt;none&amp;gt;   14m   v1.21.14-eks-48e63af
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Terraform Destroy
&lt;/h2&gt;

&lt;p&gt;To destroy the app simply fire the below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd&amp;gt; &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-profile&amp;gt; 
cmd&amp;gt; terraform destroy &lt;span class="nt"&gt;--auto-approve&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Destroy Hosted Zone
&lt;/h2&gt;

&lt;p&gt;If the hosted zone is not needed destroy that too as it costs 0.5$ per month&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cmd&amp;gt; &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-profile&amp;gt; 
cmd&amp;gt; aws route53 list-hosted-zones

&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"HostedZones"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Id"&lt;/span&gt;: &lt;span class="s2"&gt;"/hostedzone/Z0649256M3CSJUPI94TE"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Name"&lt;/span&gt;: &lt;span class="s2"&gt;"ekspg.rohitsalecha.com."&lt;/span&gt;,
            &lt;span class="s2"&gt;"CallerReference"&lt;/span&gt;: &lt;span class="s2"&gt;"2023-02-21-24:35"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Config"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"PrivateZone"&lt;/span&gt;: &lt;span class="nb"&gt;false&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;,
            &lt;span class="s2"&gt;"ResourceRecordSetCount"&lt;/span&gt;: 2
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

cmd&amp;gt; aws route53 delete-hosted-zone &lt;span class="nt"&gt;--id&lt;/span&gt; Z0649256M3CSJUPI94TE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Multi-Environment Configuration
&lt;/h2&gt;

&lt;p&gt;If you’d like to configure multiple environments like dev,staging etc … then this script allows you to modify the same in &lt;strong&gt;_infra/variables.tf _&lt;/strong&gt; as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File: infra/variables.tf

3: 
4: variable "environment" {
5:   description = "The Deployment environment"
6:   type        = string
7:   default     = "prod"
8: }
9: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Default value is configured as “prod” however the same can be overridden in the infra/terraform.auto.tfvars file as dev or staging.&lt;/p&gt;

&lt;p&gt;The script shall automatically check which environment is configured and also update the Route53 domain. As an example, I modified the environment variable as “dev” and once I started the application I got the URL as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.ekspg.rohitsalecha.com/" rel="noopener noreferrer"&gt;https://dev.ekspg.rohitsalecha.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FYx0qHFuL2E2JIgNAjzHmUJVjQFnxNHgPKKvcxZXiRQ80_X8FQYO9OQpi6_yp72ywh-4px3GpAZrEnmjnd2WkWpnwHRcp68dg_mJUZjiRi9Cdpm-5gLofk8c6kzgaZkNn7ymluqTtSXulHLnskDhVFGs" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FYx0qHFuL2E2JIgNAjzHmUJVjQFnxNHgPKKvcxZXiRQ80_X8FQYO9OQpi6_yp72ywh-4px3GpAZrEnmjnd2WkWpnwHRcp68dg_mJUZjiRi9Cdpm-5gLofk8c6kzgaZkNn7ymluqTtSXulHLnskDhVFGs" title="dev environment setup" alt="dev.ekspg.rohitsalecha.com" width="1351" height="695"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This magic is happening in this script between &lt;strong&gt;Line10-16&lt;/strong&gt; as shown below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File: infra/dns.tf

10: locals {
11: 
12:   staging_url = var.environment == "staging" ? "staging.${var.domain}" : ""
13:   prod_url    = var.environment == "prod" ? "${var.domain}" : ""
14:   dev_url     = var.environment == "dev" ? "dev.${var.domain}" : ""
15: 
16:   url = coalesce(local.staging_url, local.prod_url, local.dev_url)
17: 
18: }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Next ?
&lt;/h2&gt;

&lt;p&gt;As can be seen we deployed the SpringBoot app in the “app” folder which is dockerized as “salecharohit/practicalgitops“ on hub.docker.com.&lt;/p&gt;

&lt;p&gt;This app can be changed in the file &lt;strong&gt;infra/app.tf&lt;/strong&gt; as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File: infra/app.tf
24: 
25: resource "kubernetes_deployment_v1" "app" {
XXXXXXXXXXXXXXX------SNIPPED-------XXXXXXXXXXXXXXXXXXXXX
49: 
50:       spec {
51:         container {
52:           image = "salecharohit/practicalgitops"
53:           name  = var.org_name
54:           env {
55:             name  = "DB_PORT"
56:             value = "5432"
57:           }
58:           env {
59:             name  = "DB_HOST"
60:             value = module.pgsql.db_instance_address
61:           }
62:           env {
63:             name  = "DB_NAME"
64:             value = var.db_name
65:           }
66:           env {
67:             name  = "DB_USERNAME"
68:             value = var.db_user_name
69:           }
70:           env {
71:             name  = "DB_PASSWORD"
72:             value = module.ssmr-db-password.ssm-value
73:           }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Line 52&lt;/strong&gt; is where the docker image location needs to be modified. Do configure the remaining parameters as shown between &lt;strong&gt;L54-73&lt;/strong&gt; as environment variables which will be very specific to your app.&lt;/p&gt;

&lt;p&gt;For More AWS EKS specific use-cases/scenarios like installing Karpenter,working with secrets store etc … to check out this repo , it’s awesome and well maintained.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aws-ia/terraform-aws-eks-blueprints" rel="noopener noreferrer"&gt;https://github.com/aws-ia/terraform-aws-eks-blueprints&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Shameless Plug
&lt;/h2&gt;

&lt;p&gt;Using this setup as a base I am discussing the following in my book &lt;a href="https://link.springer.com/book/10.1007/978-1-4842-8673-9" rel="noopener noreferrer"&gt;Practical GitOps - Infrastructure Management using AWS,Terraform and Github Actions.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI/CD and Multi-Environment&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Orchestrate the entire CI/CD pipeline for Docker build and Terraform Deployment in Github Actions.&lt;/li&gt;
&lt;li&gt;Managing the state of Terraform in a multi-environment configuration like dev,staging and prod.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Authentication and Access Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting Up AWS Organisations with different OUs for environments like dev,staging,production and identity.&lt;/li&gt;
&lt;li&gt;Configuring all users in a single identity account and creating IAM Roles for them in the respective dev, staging and prod accounts for them to assume with full RBAC.&lt;/li&gt;
&lt;li&gt;Creating Kubernetes RBAC by aligning IAM Roles with specific k8s groups. So an engineer in dev account gets admin in k8s but in prod account the same engineer gets only read only. Accessing Kubernetes through kubcectl only by assuming the specific IAM Role that user has been given.&lt;/li&gt;
&lt;li&gt;Implementing IRSA(IAM Roles and Service Account) through Terraform and attaching limited identity/privileges to k8s pods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating secrets in AWS Secrets Manager and loading them onto K8s Pods using "Secrets Store CSI Driver" by leveraging IRSA&lt;/li&gt;
&lt;li&gt;Implementing basic security controls on EC2 Nodes created by EKS like IMDSv2 ,Encrypting EBS drives and encrypting k8s Secrets using AWS KMS keys.&lt;/li&gt;
&lt;li&gt;Integrating Checkov using Github Actions and spooling results in PRs&lt;/li&gt;
&lt;li&gt;Creating Route53 DNS Zones for each of the dev, staging and prod accounts&lt;/li&gt;
&lt;li&gt;Implementing Service Control Policies that lock regions of deployment,Ensuring that only encrypted EBS and RDS are deployed in staging/production,Disabling user creation in all accounts except identity,Restricting the instance types that can be created in Development OU&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralizing CloudTrail into master account by leveraging and creating organization trail&lt;/li&gt;
&lt;li&gt;Storing AWS ALB logs in S3 bucket&lt;/li&gt;
&lt;li&gt;Creating CloudWatch Alarms for detecting root login in AWS accounts &lt;/li&gt;
&lt;li&gt;Starting OpenSearch and spooling all k8s and app logs to it for prod account &lt;/li&gt;
&lt;li&gt;Spinning up Prometheus and Graphana for Prod account for performance monitoring&lt;/li&gt;
&lt;li&gt;Installing Karpenter for node scaling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use the following link to buy the book&lt;/p&gt;

&lt;p&gt;&lt;a href="https://link.springer.com/book/10.1007/978-1-4842-8673-9" rel="noopener noreferrer"&gt;https://link.springer.com/book/10.1007/978-1-4842-8673-9&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;DM me for a 20% Coupon Code on&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/rohitsalecha/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rohitsalecha/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OR&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/salecharohit" rel="noopener noreferrer"&gt;https://twitter.com/salecharohit&lt;/a&gt; &lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>AWS Inventory Extraction using CloudQuery</title>
      <dc:creator>Rohit Salecha</dc:creator>
      <pubDate>Thu, 17 Mar 2022 17:53:01 +0000</pubDate>
      <link>https://forem.com/salecharohit/aws-inventory-extraction-using-cloudquery-31a3</link>
      <guid>https://forem.com/salecharohit/aws-inventory-extraction-using-cloudquery-31a3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I wanted to extract the AWS Inventory spread out over multiple regions and accounts. Offcourse there are many solutions and different ways to do this but in this post I'd like to share how I was able to do this using an opensource tool called as &lt;a href="https://www.cloudquery.io/" rel="noopener noreferrer"&gt;CloudQuery&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To put in extremely simple words , CloudQuery converts your Cloud(AWS,GCP and many more) asset information into a SQL Database.&lt;br&gt;
For Ex: Below are the columns for the table storing information about your EC2 instances&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cq_id,cq_meta,account_id,region,arn,state_transition_reason_time,ami_launch_index,architecture,boot_mode,capacity_reservation_id,cap_reservation_preference,cap_reservation_target_capacity_reservation_id,cap_reservation_target_capacity_reservation_rg_arn,client_token,cpu_options_core_count,cpu_options_threads_per_core,ebs_optimized,ena_support,enclave_options_enabled,hibernation_options_configured,hypervisor,iam_instance_profile_arn,iam_instance_profile_id,image_id,id,instance_lifecycle,instance_type,kernel_id,key_name,launch_time,licenses,metadata_options_http_endpoint,metadata_options_http_protocol_ipv6,metadata_options_http_put_response_hop_limit,metadata_options_http_tokens,metadata_options_state,monitoring_state,outpost_arn,placement_affinity,placement_availability_zone,placement_group_name,placement_host_id,placement_host_resource_group_arn,placement_partition_number,placement_spread_domain,placement_tenancy,platform,private_dns_name,private_ip_address,public_dns_name,public_ip_address,ramdisk_id,root_device_name,root_device_type,source_dest_check,spot_instance_request_id,sriov_net_support,state_code,state_name,state_reason_code,state_reason_message,state_transition_reason,subnet_id,tags,virtualization_type,vpc_id&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With the power of SQL, possibilities of utilising this data is endless as an example, if you'd like to identify which EC2 instances are still using IMDSv1 then simply fire the query as &lt;/p&gt;

&lt;p&gt;&lt;code&gt;select * from aws_ec2_instances where metadata_options_http_tokens = 'optional' ;&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Pre-Requisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A PostgreSQL database. Below command can be used to quickly spin one up using docker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;docker run --name cloudquery_postgres -p 5432:5432 -v ${PWD}:/tmp -e POSTGRES_PASSWORD=pass -d postgres&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A PostgreSQL Administrator tool that can connect to the PGSQL database that we'll spin up&lt;/li&gt;
&lt;li&gt;AWS Access Keys configure in ~/.aws/credentials&lt;/li&gt;
&lt;li&gt;CloudQuery&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: We are setting up a test bed here and not a production-grade solution.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Configuring CloudQuery is quite straightforward and can be easily followed through this link &lt;a href="https://docs.cloudquery.io/docs/getting-started/getting-started-with-aws" rel="noopener noreferrer"&gt;https://docs.cloudquery.io/docs/getting-started/getting-started-with-aws&lt;/a&gt; for AWS.&lt;/p&gt;

&lt;p&gt;Once CloudQuery has been initialised we need to edit the &lt;code&gt;config.hcl&lt;/code&gt; file which cloudquery will read in order to fetch the details.&lt;br&gt;
A sample config.hcl file is as shown below. &lt;/p&gt;

&lt;p&gt;The accounts configured must match the different aws profiles configured in &lt;code&gt;~/.aws/credentials&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Configuration AutoGenerated by CloudQuery CLI
cloudquery {
  plugin_directory = "./cq/providers"
  policy_directory = "./cq/policies"

  provider "aws" {
    version = "latest"
  }

// Ensure the credentials match to that of the docker command provided above.
  connection {
    dsn = "postgres://postgres:pass@localhost:5432/postgres?sslmode=disable"
  }
}

// All Provider Configurations

provider "aws" {
  configuration {
// Configuring the different accounts.
    accounts "dev" {
      local_profile = "example-dev"
    }
    accounts "prod" {
      local_profile = "example-prod"
    }
    accounts "staging" {
      local_profile = "example-staging"
    }
    // Optional. by default assumes all regions
    // regions = ["us-east-1", "us-west-2"]
    // Optional. Enable AWS SDK debug logging.
    aws_debug = false
    // The maximum number of times that a request will be retried for failures. Defaults to 5 retry attempts.
    // max_retries = 5
    // The maximum back off delay between attempts. The backoff delays exponentially with a jitter based on the number of attempts. Defaults to 60 seconds.
    // max_backoff = 30
  }

  // list of resources to fetch
  resources = [
    "accessanalyzer.analyzers",
    "acm.certificates",
    "apigateway.api_keys",
    "apigateway.client_certificates",
    "apigateway.domain_names",
    "apigateway.rest_apis",
    "apigateway.usage_plans",
    "apigateway.vpc_links",
    "apigatewayv2.apis",
    "apigatewayv2.domain_names",
    "apigatewayv2.vpc_links",
    "applicationautoscaling.policies",
    "autoscaling.groups",
    "autoscaling.launch_configurations",
    "aws.regions",
    "cloudfront.cache_policies",
    "cloudfront.distributions",
    "cloudtrail.trails",
    "cloudwatch.alarms",
    "cloudwatchlogs.filters",
    "codebuild.projects",
    "cognito.identity_pools",
    "cognito.user_pools",
    "config.configuration_recorders",
    "config.conformance_packs",
    "dax.clusters",
    "directconnect.connections",
    "directconnect.gateways",
    "directconnect.lags",
    "directconnect.virtual_gateways",
    "directconnect.virtual_interfaces",
    "dms.replication_instances",
    "dynamodb.tables",
    "ec2.byoip_cidrs",
    "ec2.customer_gateways",
    "ec2.ebs_snapshots",
    "ec2.ebs_volumes",
    "ec2.eips",
    "ec2.flow_logs",
    "ec2.images",
    "ec2.instances",
    "ec2.internet_gateways",
    "ec2.nat_gateways",
    "ec2.network_acls",
    "ec2.regional_config",
    "ec2.route_tables",
    "ec2.security_groups",
    "ec2.subnets",
    "ec2.transit_gateways",
    "ec2.vpc_endpoints",
    "ec2.vpc_peering_connections",
    "ec2.vpcs",
    "ec2.vpn_gateways",
    "ecr.repositories",
    "ecs.clusters",
    "ecs.task_definitions",
    "efs.filesystems",
    "eks.clusters",
    "elasticbeanstalk.applications",
    "elasticbeanstalk.environments",
    "elasticsearch.domains",
    "elbv1.load_balancers",
    "elbv2.load_balancers",
    "elbv2.target_groups",
    "emr.block_public_access_configs",
    "emr.clusters",
    "fsx.backups",
    "guardduty.detectors",
    "iam.accounts",
    "iam.groups",
    "iam.openid_connect_identity_providers",
    "iam.password_policies",
    "iam.policies",
    "iam.roles",
    "iam.saml_identity_providers",
    "iam.server_certificates",
    "iam.users",
    "iam.virtual_mfa_devices",
    "iot.billing_groups",
    "iot.ca_certificates",
    "iot.certificates",
    "iot.policies",
    "iot.streams",
    "iot.thing_groups",
    "iot.thing_types",
    "iot.things",
    "iot.topic_rules",
    "kms.keys",
    "lambda.functions",
    "lambda.layers",
    "lambda.runtimes",
    "mq.brokers",
    "organizations.accounts",
    "rds.certificates",
    "rds.cluster_parameter_groups",
    "rds.cluster_snapshots",
    "rds.clusters",
    "rds.db_parameter_groups",
    "rds.db_security_groups",
    "rds.db_snapshots",
    "rds.db_subnet_groups",
    "rds.event_subscriptions",
    "rds.instances",
    "redshift.clusters",
    "redshift.subnet_groups",
    "route53.domains",
    "route53.health_checks",
    "route53.hosted_zones",
    "route53.reusable_delegation_sets",
    "route53.traffic_policies",
    "s3.accounts",
    "s3.buckets",
    "sagemaker.endpoint_configurations",
    "sagemaker.models",
    "sagemaker.notebook_instances",
    "sagemaker.training_jobs",
    "secretsmanager.secrets",
    "sns.subscriptions",
    "sns.topics",
    "sqs.queues",
    "ssm.documents",
    "ssm.instances",
    "waf.rule_groups",
    "waf.rules",
    "waf.subscribed_rule_groups",
    "waf.web_acls",
    "wafv2.managed_rule_groups",
    "wafv2.rule_groups",
    "wafv2.web_acls"
  ]
}

// Module Configurations
modules {
  // drift configuration block
  drift "drift-example" {
    // state block defines from where to access the state
    terraform {
      // backend: "local" or "s3"
      backend = "local"

      // local backend options
      // files: list of tfstate files
      files = ["/path/to.tfstate"]

      // s3 backend options
      // bucket   = "&amp;lt;tfstate bucket&amp;gt;"
      // keys     = [ "&amp;lt;tfstate key&amp;gt;" ]
      // region   = "us-east-1"
      // role_arn = ""
    }

    // provider "aws" {
    //   account_ids      = ["123456789"]
    //   check_resources   = ["ec2.instances:*"]
    //   ignore_resources = ["ec2.instances:i-123456789", "aws_cloudwatchlogs_filters:*"]
    // }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the above stuff is in place fire &lt;code&gt;cloudquery fetch&lt;/code&gt; and it'll start populating the SQL database by accessing the AWS inventory from all the accounts that've been configured in the &lt;code&gt;config.hcl&lt;/code&gt; file.&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%2Fwww.rohitsalecha.com%2Fpost%2Faws_inventory_extraction_using_cloudquery%2Fimg%2F2.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%2Fwww.rohitsalecha.com%2Fpost%2Faws_inventory_extraction_using_cloudquery%2Fimg%2F2.png" alt="cloudquery fetch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extraction
&lt;/h2&gt;

&lt;p&gt;Once the fetch command completes, open up your favourite PGAdmin console and fire the below SQL Query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DO&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;DECLARE&lt;/span&gt; 
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;RECORD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;tbl_name&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;data_exists&lt;/span&gt; &lt;span class="nb"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
    &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;information_schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tables&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;table_schema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'public'&lt;/span&gt;
    &lt;span class="n"&gt;LOOP&lt;/span&gt;
    &lt;span class="n"&gt;tbl_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;RAISE&lt;/span&gt; &lt;span class="n"&gt;NOTICE&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;tbl_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'select count(*) where exists (select 1 from %s)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;tbl_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;data_exists&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;RAISE&lt;/span&gt; &lt;span class="n"&gt;NOTICE&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;data_exists&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="n"&gt;data_exists&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
       &lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'COPY %s TO &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt; WITH (FORMAT CSV, HEADER)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;tbl_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/tmp/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;tbl_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'.csv'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Query above iterates through all the tables created by CloudQuery and exports only non-empty &lt;br&gt;
tables in CSV format. The tables aggregate resources from all accounts.&lt;/p&gt;

&lt;p&gt;For Ex: if you have 5 S3 buckets , in 3 different accounts , CloudQuery will aggregate all the 5 S3 buckets as 5 rows and a column to desginate the associated account IDs.&lt;/p&gt;

&lt;p&gt;End Result would be something 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%2Fwww.rohitsalecha.com%2Fpost%2Faws_inventory_extraction_using_cloudquery%2Fimg%2F1.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%2Fwww.rohitsalecha.com%2Fpost%2Faws_inventory_extraction_using_cloudquery%2Fimg%2F1.png" alt="AWS Inventory in CSV"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;That's all folks hope you find this post useful :-)&lt;/p&gt;

</description>
      <category>aws</category>
      <category>inventory</category>
      <category>cloudquery</category>
      <category>csv</category>
    </item>
    <item>
      <title>Shift Left, Scale Up Security Using Threat Modelling</title>
      <dc:creator>Rohit Salecha</dc:creator>
      <pubDate>Mon, 20 Sep 2021 13:01:20 +0000</pubDate>
      <link>https://forem.com/salecharohit/shift-left-scale-up-security-using-threat-modelling-3afi</link>
      <guid>https://forem.com/salecharohit/shift-left-scale-up-security-using-threat-modelling-3afi</guid>
      <description>&lt;p&gt;Security strategies today for most organisations is to &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shift Security left more towards the developers&lt;/li&gt;
&lt;li&gt;Engage developers/architects in security processes so as to scale up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both these points are mutually inclusive i.e. need to be done hand-in-hand. One cannot scaleup security without shifting more towards the left and vice versa. If focus is trained on any one of them then the organisation will end-up in a catch-22 situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Addressing the Catch-22
&lt;/h2&gt;

&lt;p&gt;The answer is simple ,&lt;strong&gt;Threat Modelling&lt;/strong&gt; , which is now even recommended in the new &lt;a href="https://owasp.org/Top10/"&gt;OWASP Top 10 - 2021&lt;/a&gt; in the form of &lt;code&gt;A04:2021-Insecure Design&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Currently the new Top 10 is still in the DRAFT stage however, the comunity identifying this as a weakness certainly calls for a change in the way manage security across our organisations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is Threat Modelling ?
&lt;/h2&gt;

&lt;p&gt;There are many definitions out there describing threat modelling but in extremely simple terms it is an attempt to identify threats even before the application/feature development starts. Some example threats&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Potential security flaw being exploited&lt;/li&gt;
&lt;li&gt;Data leakage&lt;/li&gt;
&lt;li&gt;Business continuity being affected&lt;/li&gt;
&lt;li&gt;Privilege Escalation&lt;/li&gt;
&lt;li&gt;Customer confidence going down and many more ...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the best resources that I found is &lt;a href="https://github.com/segmentio/threat-modeling-training"&gt;Segment's Threat Modelling Training&lt;/a&gt; that they developed internally with an intent to scale up security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues with Adoption of TM
&lt;/h2&gt;

&lt;p&gt;Not many organisations are able to adopt Threat Modelling as a process because&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Most of the times Architecture diagrams and other application artefacts like documentation,functional and non-functional requirements are not updated or not captured. Hence contextual information is absent.&lt;/li&gt;
&lt;li&gt;In absence of a proper context its difficult to derive threat models&lt;/li&gt;
&lt;li&gt;Developers/technical architects are quite averse to using security tools.&lt;/li&gt;
&lt;li&gt;Generally a threat modelling tool would spool out quite a lot of threats which overhwhelms the developers leading to friction.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How To ScaleUp + ShiftLeft ?
&lt;/h2&gt;

&lt;p&gt;So how exactly can we scale up and shift left security using Threat Modelling ?&lt;/p&gt;

&lt;p&gt;Let's analyse that through the lens of People,Process and Technology, the three pillars of success for any organisation.&lt;/p&gt;

&lt;h3&gt;
  
  
  People
&lt;/h3&gt;

&lt;p&gt;We'll need two sets of profiles here that are mostly in a mid-senior roles who are an expert in their domain&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technical Architect

&lt;ul&gt;
&lt;li&gt;Should have hands-on experience with software development best practices.&lt;/li&gt;
&lt;li&gt;Should be able conceptualise and visualise the architecture of a particular application/product/service alongwith its integrations.&lt;/li&gt;
&lt;li&gt;Should be responsible and accountable for creation and maintenance of the relevant artefacts of a particular application like Architecture Diagrams,Data Flow Diagrams,UMLs,Functional and non-functional requirements,source code etc ...&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;This is just a very brief of the roles and responsibility of a Technical Architect. Below are some guides for a much more detailed job description&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.randstad.co.uk/career-advice/job-profiles/what-does-a-technical-architect-do/"&gt;What Does a Technical Architect do - Randstad&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://resources.workable.com/technical-architect-job-description"&gt;Technical Architect Job Description - Workable&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security Architect&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Should be able to enumerate the threats by understanding the application's assets created by the Technical Architects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Should have a broad understanding of technology components so as to evaluate the risks associated with it. For Ex: most organisations today are migrating to Kubernetes,hence a Security Architect must have some knowledge of how Kubernetes works and how is it being operated not necessary a hands-on,deep dive knowledge.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide countermeasures for the identified threats through a medium and context that developers understand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://aarushikoolwal.com/post/security-architect-job-role-at-a-glance/"&gt;Security Architect: Job role at a glance - Aarushi Koolwal&lt;/a&gt; is a fantastic article describing more about the Security Architect job role.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Technology
&lt;/h3&gt;

&lt;p&gt;In order for the Technical Architect(TA) and Security Architect(SA) to scale up their work they'll need tools.&lt;br&gt;
A tool that can cater to both their requirements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The interface of the tool should be developer friendly so that she can create architecture diagrams and input application requirements with ease.&lt;/li&gt;
&lt;li&gt;Once the requisite information from the TA is received the tool should be able to evaluate the information and generate threats and countermeasures.&lt;/li&gt;
&lt;li&gt;Tool must also integrate with whatever ticketting system is being used by the developers to track issues. &lt;/li&gt;
&lt;li&gt;The sync between the tool and the ticketting system should also be bi-directional as this will help security architects track issues that've been closed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Process
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Technical Architect should prepare the relevant application artefacts like app documentation,relevant diagrams , requirements etc ... and add them in the threat modelling tool.&lt;/li&gt;
&lt;li&gt;She should be able to present the artefacts to all relevant stakeholders for any new feature/change or a new project altogether by keeping this tool as the point of reference.&lt;/li&gt;
&lt;li&gt;Security architects would review the artefacts and the diagrams in the threat modelling tool, remove false +ves and other noise and then add the threats with their countermeasures as a requirement/user story.&lt;/li&gt;
&lt;li&gt;Developers can now work on the security requirements alongside other features.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Would this Help?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;With this technique Technical Architects would keep their Architecture Diagrams and other artefacts "Live" and continue to update in the same tool. Hence TA's are now using this tool for their own purpose and not necessarily for security.&lt;/li&gt;
&lt;li&gt;Security Architects can keep track of changes and accordingly provide their security requirements by filtering out the noise.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Basically both teams are now working on the same platform and performing their own jobs while at the sametime collaborating with each other ! Hence, we are solving two problems with a single solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.microsoft.com/en-us/securityengineering/sdl/threatmodeling"&gt;Image Credit: Microsoft&lt;/a&gt;&lt;/p&gt;

</description>
      <category>threatmodelling</category>
      <category>security</category>
      <category>shiftleft</category>
      <category>scalesecurity</category>
    </item>
    <item>
      <title>Bootstrap Security in Kubernetes Deployments</title>
      <dc:creator>Rohit Salecha</dc:creator>
      <pubDate>Wed, 11 Aug 2021 09:29:18 +0000</pubDate>
      <link>https://forem.com/salecharohit/bootstrap-security-in-kubernetes-deployments-2e59</link>
      <guid>https://forem.com/salecharohit/bootstrap-security-in-kubernetes-deployments-2e59</guid>
      <description>&lt;p&gt;Kubernetes, is one of the &lt;a href="https://devopscube.com/docker-container-clustering-tools/" rel="noopener noreferrer"&gt;most popular and most used&lt;/a&gt; container orchestration tool. &lt;a href="https://kubernetes.io/docs/concepts/workloads/" rel="noopener noreferrer"&gt;Kubernetes Workloads&lt;/a&gt; are the actual applications that are executed like a simple nginx server or maybe a cron job. &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="noopener noreferrer"&gt;Kubernetes Deployments&lt;/a&gt; is the &lt;a href="https://rancher.com/learning-paths/introduction-to-kubernetes-workloads/#:~:text=Deployments%20are%20one%20of%20the,updates%2C%20rollbacks%2C%20and%20scaling." rel="noopener noreferrer"&gt;most commonly used&lt;/a&gt; workload as it can be easily updated,scaled and managed.&lt;/p&gt;

&lt;p&gt;The recently released &lt;a href="https://media.defense.gov/2021/Aug/03/2002820425/-1/-1/1/CTR_KUBERNETES%20HARDENING%20GUIDANCE.PDF" rel="noopener noreferrer"&gt;Kubernetes Hardening Guide&lt;/a&gt; is an excellent resource that provides a proper guidance on how to effectively secure Kubernetes. The information presented in the guide clearly shows that securing and hardening kubernetes is not just the job of the Kubernetes administrator but also of the developers who are deploying their workload on the clusters.&lt;/p&gt;

&lt;p&gt;In this blog I'll discuss about how developers deploying Kubernetes workloads like Deployments can bootstrap security by applying some of the guidelines provided by the 'Kubrnetes Hardening guide'.&lt;/p&gt;

&lt;p&gt;This will be a practical hands-on guide where I shall take a simple Dockerfile and then incrementally add the security best practices to &lt;strong&gt;create a template Deployment manifest file&lt;/strong&gt; which can then be reused by developers in a hurry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-Requisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker is required as we'll be building from ground up.&lt;/li&gt;
&lt;li&gt;A single-node Kubernetes cluster like minikube should be sufficient to follow along with this guide alongwith the &lt;code&gt;kubectl&lt;/code&gt; utility. You can use the &lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;official minikube&lt;/a&gt; documentation to set it up in your environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am using a standalone cluster created by &lt;a href="https://hub.docker.com/editions/community/docker-ce-desktop-windows" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt; tied to WSL2 as the backend.&lt;/p&gt;

&lt;p&gt;This guide will assume that you have a running cluster which is accessible through the kubectl utility as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F1.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F1.png" alt="Docker Desktop"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Securing Deployments
&lt;/h2&gt;

&lt;p&gt;Securing the kubernetes workloads can effectively be compartimentalised into 'Buildtime' and 'Runtime' security. In order to run with the examples we'll make use of this simple Spring Boot HelloWorld application and deploy it in Kubernetes with buildtime and runtime security applied.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment" rel="noopener noreferrer"&gt;https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So before starting off let's clone this repository,build the docker container and run the application locally&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:salecharohit/bootstrapsecurityinkubernetesdeployment.git
&lt;span class="nb"&gt;cd &lt;/span&gt;springbootmaven
docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; Dockerfile.basic &lt;span class="nt"&gt;-t&lt;/span&gt; springbootmaven
docker run &lt;span class="nt"&gt;--name&lt;/span&gt; springboot &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 springbootmaven
curl http://localhost:8080

Expected Response:

Hello World From Spring Boot Build Using Maven on Alpine OS!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Build Time Security
&lt;/h2&gt;

&lt;p&gt;Buildtime security focusses more on how the underlying containers can be build with a reduced footprint and are programmed to be executed with least possible privileges.&lt;/p&gt;

&lt;p&gt;We'll discuss both these approaches with a problem solution approach&lt;/p&gt;

&lt;h3&gt;
  
  
  Attack Surface Reduction
&lt;/h3&gt;

&lt;p&gt;When building applications in a container the primary objective is to have the app run consistently and indepdently regardless of the environment be it a data center,cloud or even onpremise.&lt;br&gt;
However, when building these apps there is one unwritten rule that it should be a standalone application without much dependencies.&lt;/p&gt;

&lt;p&gt;Let's take example of our SpringBoot application. The only dependency for our application to run is that it needs a JVM or Java runtime. Anything else baked into the container is practically useless.&lt;/p&gt;

&lt;p&gt;As an example, in our SpringBoot container , which is build on Alpine OS , we don't have any specific need to have the requirement for the &lt;code&gt;apk&lt;/code&gt; package manager to be installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; springboot /bin/sh
apk add curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F2.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F2.png" alt="APK installed"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;So let's try to &lt;a href="https://stackoverflow.com/a/54428406/1679541" rel="noopener noreferrer"&gt;remove the &lt;code&gt;apk&lt;/code&gt;&lt;/a&gt; binary and rebuild or docker image.&lt;/p&gt;

&lt;p&gt;We'll make use of the &lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment/blob/main/Dockerfile.asr" rel="noopener noreferrer"&gt;Dockerfile.asr&lt;/a&gt; at this time to rebuild our docker container which is shared below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;maven:3.8.1-openjdk-17-slim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;MAVEN_BUILD&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /build/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; pom.xml /build/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; src /build/src/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;mvn package

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; openjdk:17-alpine&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /sbin/apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /etc/apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /lib/apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /usr/share/apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apk

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=MAVEN_BUILD /build/target/springbootmaven.jar /springbootmaven.jar&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; java -jar /springbootmaven.jar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets rebuild and re-rerun&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;# First let's stop the previously running container&lt;/span&gt;
docker stop springboot

&lt;span class="c"&gt;# Next let's re-build and re-run&lt;/span&gt;
docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; Dockerfile.asr &lt;span class="nt"&gt;-t&lt;/span&gt; springbootmaven
docker run &lt;span class="nt"&gt;--name&lt;/span&gt; springboot &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 springbootmaven
docker run &lt;span class="nt"&gt;--name&lt;/span&gt; springboot &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 springbootmaven
curl http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's try to run the &lt;code&gt;apk add curl&lt;/code&gt; command again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; springboot /bin/sh
apk add curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F3.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F3.png" alt="APK removed"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;So we successfully got rid of the apk dependency and yet have our application running successfully !&lt;/p&gt;

&lt;p&gt;Below are some good scripts that've been written specifically for hardenning Alpine OS. Pick and choose depending on your programming language and harden your base alpine image accordingly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/kost/017e95aa24f454f77a37" rel="noopener noreferrer"&gt;https://gist.github.com/kost/017e95aa24f454f77a37&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ironpeakservices/iron-alpine/blob/master/Dockerfile" rel="noopener noreferrer"&gt;https://github.com/ironpeakservices/iron-alpine/blob/master/Dockerfile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the Flip-side you can also have a look at the distroless container created by google which is also very highly recommended.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/GoogleContainerTools/distroless/tree/main/examples" rel="noopener noreferrer"&gt;https://github.com/GoogleContainerTools/distroless/tree/main/examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Switching User Context
&lt;/h3&gt;

&lt;p&gt;One might argue that if an attacker gains an RCE inside the container she might not be able to install packages like curl,wget etc ... to establish her persistence.&lt;/p&gt;

&lt;p&gt;However, we are still running as "root" user and technically it is still possible to &lt;a href="https://unix.stackexchange.com/a/339590/335263" rel="noopener noreferrer"&gt;install apk back&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets re-run our docker container and check the privileges with which it is currently running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; springboot /bin/sh
&lt;span class="nb"&gt;whoami
&lt;/span&gt;ping rohitsalecha.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F4.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F4.png" alt="Running as root"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hence, it is important that we run our container not as root but as a user with limited privileges.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment/blob/main/Dockerfile.lpr" rel="noopener noreferrer"&gt;Dockerfile.lpr&lt;/a&gt; shows addition of a few more commands that add a user and group called "boot" and assign it a working directory (Which is its home directory)&lt;br&gt;
I've also assigned numerical values to the user and group which we'll discuss in detail in the &lt;a href="//{{&amp;lt;%20relref%20"&gt;}}"&amp;gt;Pod Security Context Section&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;maven:3.8.1-openjdk-17-slim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;MAVEN_BUILD&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /build/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; pom.xml /build/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; src /build/src/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;mvn package

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; openjdk:17-alpine&lt;/span&gt;

&lt;span class="c"&gt;# Removing apk package manager&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /sbin/apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /etc/apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /lib/apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /usr/share/apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apk

&lt;span class="c"&gt;# Adding a user and group called "boot"&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;addgroup boot &lt;span class="nt"&gt;-g&lt;/span&gt; 1337 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt;
    adduser -D -h /home/boot -u 1337 -s /bin/ash boot -G boot

&lt;span class="c"&gt;# Changing the context that shall run the below commands with User "boot" instead of root&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; boot&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /home/boot&lt;/span&gt;

&lt;span class="c"&gt;# By default even in a non-root context, Docker copies the file as root. Hence its best practice to chown&lt;/span&gt;
&lt;span class="c"&gt;# the files being copied as the user. https://stackoverflow.com/a/44766666/1679541&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --chown=boot:boot --from=MAVEN_BUILD /build/target/springbootmaven.jar /home/boot/springbootmaven.jar&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; java -jar /home/boot/springbootmaven.jar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets rebuild and re-rerun&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;# First let's stop the previously running container&lt;/span&gt;
docker stop springboot

&lt;span class="c"&gt;# Next let's re-build and re-run&lt;/span&gt;
docker build &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; Dockerfile.lpr &lt;span class="nt"&gt;-t&lt;/span&gt; springbootmaven
docker run &lt;span class="nt"&gt;--name&lt;/span&gt; springboot &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 springbootmaven
curl http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's try to run the &lt;code&gt;whoami&lt;/code&gt; command and check whats the privileges with which the container is now running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; springboot /bin/sh
&lt;span class="nb"&gt;whoami
&lt;/span&gt;ping rohitsalecha.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F5.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F5.png" alt="Running as boot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime Security
&lt;/h2&gt;

&lt;p&gt;Now that we've got a good level of confidence in the build-time security wherein we've learnt to remove the packages and also update the user context to run the container with limited privileges.&lt;br&gt;
These security features are applied when we are building the docker container however we also need to focus on the security posture of the container when it is running in the Kubernetes environment which we'll explore below.&lt;/p&gt;

&lt;p&gt;Before we start of with securing our Kubrnetes deployment let's run our application on our Kubernetes cluster by first pushing our docker container to hub.docker.com. You can use &lt;a href="https://docs.docker.com/docker-hub/repos/" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; to get started for the same&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build . -f Dockerfile.lpr -t springbootmaven
docker tag springbootmaven salecharohit/springbootmaven
docker push salecharohit/springbootmaven
docker run -d -p 8080:8080 --name springboot salecharohit/springbootmaven
curl http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that our docker image is ready let's apply our &lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment/blob/main/kubernetes-basic.yaml" rel="noopener noreferrer"&gt;kubernetes-basic.yaml&lt;/a&gt; file that will deploy this application and also a service that will help us connect to it.&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="c1"&gt;# Create Namespace&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Namespace&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Create SpringBoot Deployment&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&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;salecharohit/springbootmaven&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&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="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Create Service for SpringBoot Deployment&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&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="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http"&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next let's deploy our Kubernetes manifests using the below commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; kubernetes-basic.yaml
kubectl get deploy &lt;span class="nt"&gt;-n&lt;/span&gt; boot
&lt;span class="c"&gt;# Run a temporary container that will only curl our bootservice&lt;/span&gt;
kubectl run &lt;span class="nt"&gt;-it&lt;/span&gt; testpod &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;radial/busyboxplus:curl &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Never &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; curl http://springbootmaven.boot.svc.cluster.local:8080

Expected Output:
Hello World From Spring Boot Build Using Maven on Alpine OS!pod &lt;span class="s2"&gt;"testpod"&lt;/span&gt; deleted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F6.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F6.png" alt="Running Basic Deployment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Service Account Tokens
&lt;/h3&gt;

&lt;p&gt;If a Pod needs to communicate with the Kubernetes API-Server it needs &lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" rel="noopener noreferrer"&gt;Service Account Tokens&lt;/a&gt; for authentication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server" rel="noopener noreferrer"&gt;By default&lt;/a&gt; every pod gets assigned a service account token which is mounted on &lt;code&gt;/var/run/secrets/kubernetes.io/serviceaccount/token&lt;/code&gt;.&lt;br&gt;
Lets view this in practice by deploying our SpringBoot app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; boot
kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; springbootmaven-7d7c5c8597-mndv9 &lt;span class="nt"&gt;-n&lt;/span&gt; boot &lt;span class="nt"&gt;--&lt;/span&gt; /bin/sh
&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/run/secrets/kubernetes.io/serviceaccount/token&lt;span class="si"&gt;)&lt;/span&gt;
curl &lt;span class="nt"&gt;-k&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization:Bearer &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; https://kubernetes.docker.internal:6443/version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F7.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F7.png" alt="Kubernetes Service Account Token Default"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An RCE vulnerability on your application can leak this access token to the attacker which &lt;a href="https://hackersvanguard.com/abuse-kubernetes-with-the-automountserviceaccounttoken/" rel="noopener noreferrer"&gt;she can abuse to read-write resources in the same namespace or even have a global read permissions.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The resolution for this issue is two-fold depending upon the situation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pods donot need any access to the API-Server&lt;/li&gt;
&lt;li&gt;Pods need access to the API-Server&lt;/li&gt;
&lt;/ol&gt;

&lt;h5&gt;
  
  
  Pods that donot need access to the API-Server
&lt;/h5&gt;

&lt;p&gt;This situation is farily simple to solve by simply adding two lines to the kubernetes manifest file as shown below&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;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
      &lt;span class="na"&gt;automountServiceAccountToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete deployment file &lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment/blob/main/kubernetes-nosa.yaml" rel="noopener noreferrer"&gt;kubernetes-nosa.yaml&lt;/a&gt; is as follows&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&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;salecharohit/springbootmaven&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&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="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
      &lt;span class="na"&gt;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
      &lt;span class="na"&gt;automountServiceAccountToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check if the service account token is now mounted or not&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;# Ensure our previous deploy is deleted. &lt;/span&gt;
kubectl delete ns boot

&lt;span class="c"&gt;# Apply with no service account token&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; kubernetes-nosa.yaml
kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; boot
kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; springbootmaven-5568b9874f-8nml8 &lt;span class="nt"&gt;-n&lt;/span&gt; boot &lt;span class="nt"&gt;--&lt;/span&gt; /bin/sh
&lt;span class="nb"&gt;cat&lt;/span&gt; /var/run/secrets/kubernetes.io/serviceaccount/token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As can be seen from the image the default service account token is no longer mounted.&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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F8.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F8.png" alt="Kubernetes Service Account Token Default"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Pods that need access to the API-Server
&lt;/h5&gt;

&lt;p&gt;In this situation we need to create a ServiceAccount,Role and RoleBinding that maps the ServiceAccount to the Role. &lt;br&gt;
The below Kubernetes manifest &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a ServiceAccount called bootserviceaccount to a specific namepspace i.e. boot&lt;/li&gt;
&lt;li&gt;Creates a Role called bootservicerole with only privileges to view running pods&lt;/li&gt;
&lt;li&gt;Creates a RoleBinding called bootservicerolebinding&lt;/li&gt;
&lt;li&gt;Mount the ServiceAccount thus created using the following lines in the Deployment
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="s"&gt;---&lt;/span&gt;
          &lt;span class="s"&gt;spec&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&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;salecharohit/springbootmaven&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&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="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
      &lt;span class="na"&gt;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bootserviceaccount&lt;/span&gt;
    &lt;span class="s"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This shall allow to only read pods in the "boot" namespace.&lt;/p&gt;

&lt;p&gt;The complete deployment file &lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment/blob/main/kubernetes-withsa.yaml" rel="noopener noreferrer"&gt;kubernetes-withsa.yaml&lt;/a&gt; is as follows&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="c1"&gt;# Create Namespace&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Namespace&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bootserviceaccount&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bootservicerole&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pods"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;watch"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RoleBinding&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bootservicerolebinding&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bootserviceaccount&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;roleRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bootservicerole&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Create SpringBoot Deployment&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&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;salecharohit/springbootmaven&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&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="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
      &lt;span class="na"&gt;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bootserviceaccount&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Create Service for SpringBoot Deployment&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&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="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http"&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's apply and check if our application is running fine&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;# Ensure our previous deploy is deleted. &lt;/span&gt;
kubectl delete ns boot

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; kubernetes-withsa.yaml
kubectl run &lt;span class="nt"&gt;-it&lt;/span&gt; testpod &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;radial/busyboxplus:curl &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Never &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; curl http://springbootmaven.boot.svc.cluster.local:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pod Security Contexts
&lt;/h3&gt;

&lt;p&gt;Though we've configured our base docker image to run with non-root privileges however, there are still few more configurations that need to be added as security best practices. These are&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Restricting the capabilities of the container and the pod&lt;/li&gt;
&lt;li&gt;Disabling Privilege Escalation&lt;/li&gt;
&lt;li&gt;Configuring the container to run with a specific uid/gid created earlier in our &lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment/blob/main/Dockerfile.lpr" rel="noopener noreferrer"&gt;Dockerfile.lpr&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the kubernetes manifest files there are two types of "SecurityContexts" defined.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running at Pod-Level which will be applied to all containers running in this pod
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="s"&gt;---&lt;/span&gt;
      &lt;span class="s"&gt;securityContext&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;fsGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1337&lt;/span&gt;
        &lt;span class="na"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1337&lt;/span&gt;
&lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="s"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Running at Container-level
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;      &lt;span class="s"&gt;---&lt;/span&gt;
        &lt;span class="s"&gt;securityContext&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1337&lt;/span&gt;
          &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SETUID"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SETGID"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="na"&gt;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
      &lt;span class="na"&gt;automountServiceAccountToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="s"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete deployment file &lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment/blob/main/kubernetes-ps.yaml" rel="noopener noreferrer"&gt;kubernetes-ps.yaml&lt;/a&gt; embedded with the PodSecurity contexts is below&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="c1"&gt;# Create Namespace&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Namespace&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Create SpringBoot Deployment&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;fsGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1337&lt;/span&gt;
        &lt;span class="na"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1337&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&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;salecharohit/springbootmaven&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&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="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
        &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1337&lt;/span&gt;
          &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SETUID"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SETGID"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
      &lt;span class="na"&gt;automountServiceAccountToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Create Service for SpringBoot Deployment&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&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="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http"&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's apply and test if our application is running&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;# Ensure our previous apply is deleted&lt;/span&gt;
kubectl delete ns boot
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; kubernetes-ps.yaml
kubectl run &lt;span class="nt"&gt;-it&lt;/span&gt; testpod &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;radial/busyboxplus:curl &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Never &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; curl http://springbootmaven.boot.svc.cluster.local:8080
kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; boot
kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; springbootmaven-56c64ff85-mqz2z &lt;span class="nt"&gt;-n&lt;/span&gt; boot &lt;span class="nt"&gt;--&lt;/span&gt; /bin/sh
&lt;span class="nb"&gt;whoami
id
&lt;/span&gt;ping google.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F9.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F9.png" alt="Kubernetes Low Privilege"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can drop more capabilities as per your requirements. The complete list of capabilities can be found here&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h" rel="noopener noreferrer"&gt;https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Features like AppArmor,SecComp etc ... require additional configurations of the control plane components and hence I've limited my discussion to out-of-the-box features that can be easily activated and ensure good level of security assurance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Immutable File-Systems
&lt;/h3&gt;

&lt;p&gt;Applications running in a containerised environment seldom write data as it practically goes against the logic of having an &lt;code&gt;immutable&lt;/code&gt; system. However, at times it maybe needed for caching or temporary swapping/processing of files. Hence, to provide this functionality to the developer we can mount an &lt;a href="https://kubernetes.io/docs/concepts/storage/volumes/#emptydir" rel="noopener noreferrer"&gt;&lt;code&gt;emptyDir&lt;/code&gt;&lt;/a&gt; as an ephemeral volume which is lost once the container is killed.&lt;/p&gt;

&lt;p&gt;With this in place we can also add another security context attribute called "readOnlyRootFilesystem" and set it as true since the application running inside the container no longer needs to write anywhere on the file-system other than the 'tmp' directory.&lt;/p&gt;

&lt;p&gt;The above requirements can be configured as shown below.&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="s"&gt;---&lt;/span&gt;
      &lt;span class="s"&gt;containers&lt;/span&gt;&lt;span class="err"&gt;:&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;salecharohit/springbootmaven&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&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="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
        &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tmp&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="na"&gt;emptyDir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tmp&lt;/span&gt;
  &lt;span class="s"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete deployment file &lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment/blob/main/kubernetes-rofs.yaml" rel="noopener noreferrer"&gt;kubernetes-rofs.yaml&lt;/a&gt; is as follows&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="c1"&gt;# Create Namespace&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Namespace&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Create SpringBoot Deployment&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;fsGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1337&lt;/span&gt;
        &lt;span class="na"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1337&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&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;salecharohit/springbootmaven&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&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="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
        &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;privileged&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1337&lt;/span&gt;
          &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SETUID"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SETGID"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tmp&lt;/span&gt;
      &lt;span class="na"&gt;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
      &lt;span class="na"&gt;automountServiceAccountToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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="na"&gt;emptyDir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tmp&lt;/span&gt;

&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Create Service for SpringBoot Deployment&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;boot&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&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="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http"&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springbootmaven&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Let's apply and test if our application is running&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;# Ensure our previous apply is deleted&lt;/span&gt;
kubectl delete ns boot

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; kubernetes-rofs.yaml
kubectl run &lt;span class="nt"&gt;-it&lt;/span&gt; testpod &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;radial/busyboxplus:curl &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Never &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; curl http://springbootmaven.boot.svc.cluster.local:8080
kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; boot
kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; springbootmaven-56c64ff85-mqz2z &lt;span class="nt"&gt;-n&lt;/span&gt; boot &lt;span class="nt"&gt;--&lt;/span&gt; /bin/sh
&lt;span class="nb"&gt;pwd
touch &lt;/span&gt;test.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F10.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%2Fwww.rohitsalecha.com%2Fpost%2Fbootstrap_security_in_kubernetes_deployments%2Fimg%2F10.png" alt="Read-Only File-System"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We've learnt what are the different controls we can embed in our containerised application and also looked at how to enable run-time protection mechanisms that can atleast make things difficult for an external attacker to gain foothold into our containerised systems.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/salecharohit/bootstrapsecurityinkubernetesdeployment/blob/main/kubernetes-rofs.yaml" rel="noopener noreferrer"&gt;kubernetes-rofs.yaml&lt;/a&gt; can serve as a good template for developers to containerise their applications with default security features enabled while deploying in a Kubernetes environment.&lt;/p&gt;

&lt;p&gt;Offcourse the Dockerfile needs to be created for the specific applications but for that purpose I've collected a few of them here &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/salecharohit/dockerfilesrepo" rel="noopener noreferrer"&gt;https://github.com/salecharohit/dockerfilesrepo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reposted From : &lt;a href="https://www.rohitsalecha.com/post/bootstrap_security_in_kubernetes_deployments/" rel="noopener noreferrer"&gt;https://www.rohitsalecha.com/post/bootstrap_security_in_kubernetes_deployments/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.atomist.com/security-of-docker-kubernetes/" rel="noopener noreferrer"&gt;https://blog.atomist.com/security-of-docker-kubernetes/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;-&lt;a href="https://media.defense.gov/2021/Aug/03/2002820425/-1/-1/1/CTR_KUBERNETES%20HARDENING%20GUIDANCE.PDF" rel="noopener noreferrer"&gt;https://media.defense.gov/2021/Aug/03/2002820425/-1/-1/1/CTR_KUBERNETES%20HARDENING%20GUIDANCE.PDF&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloudogu.com/en/blog/k8s-app-ops-part-3-security-context-1" rel="noopener noreferrer"&gt;https://cloudogu.com/en/blog/k8s-app-ops-part-3-security-context-1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cyberciti.biz/faq/how-to-add-and-delete-users-on-alpine-linux/" rel="noopener noreferrer"&gt;https://www.cyberciti.biz/faq/how-to-add-and-delete-users-on-alpine-linux/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/configure-pod-container/security-context/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sysdig.com/wp-content/uploads/2019/01/kubernetes-security-guide.pdf" rel="noopener noreferrer"&gt;https://sysdig.com/wp-content/uploads/2019/01/kubernetes-security-guide.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>docker</category>
      <category>security</category>
      <category>defenseindepth</category>
    </item>
  </channel>
</rss>
