<?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: Lucas Severo Alves</title>
    <description>The latest articles on DEV Community by Lucas Severo Alves (@canelasevero).</description>
    <link>https://dev.to/canelasevero</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%2F159875%2Ff7532cec-c1ef-40f7-ba1f-bdda5678fa88.jpg</url>
      <title>DEV Community: Lucas Severo Alves</title>
      <link>https://dev.to/canelasevero</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/canelasevero"/>
    <language>en</language>
    <item>
      <title>Yet another rant in favor of Kubernetes Secrets</title>
      <dc:creator>Lucas Severo Alves</dc:creator>
      <pubDate>Tue, 01 Aug 2023 04:58:37 +0000</pubDate>
      <link>https://dev.to/canelasevero/yet-another-rant-in-favor-of-kubernetes-secrets-432k</link>
      <guid>https://dev.to/canelasevero/yet-another-rant-in-favor-of-kubernetes-secrets-432k</guid>
      <description>&lt;p&gt;&lt;em&gt;Translation to pt-br at: &lt;a href="https://knela.dev/blog/mais-um-desabafo-em-favor-dos-segredos-do-kubernetes" rel="noopener noreferrer"&gt;https://knela.dev/blog/mais-um-desabafo-em-favor-dos-segredos-do-kubernetes&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Back in the day, Kubernetes secrets had many engineers scratching their heads, like "Is this a joke"? Secrets are implemented in base64 encoding which is not an encryption system at all but a simple encoding. Of course, anybody could then decode it. I must admit I was one of those engineers. My opinion changed, but I can understand the feeling most people have with regard to these objects, however wrong this premise is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1kabyfuxnmapgdyipj2.jpg" 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%2Fl1kabyfuxnmapgdyipj2.jpg" alt="Photo by Sai De Silva on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are Kubernetes secrets base64 encoded? (And why that's ok)
&lt;/h2&gt;

&lt;p&gt;The base64 encoding of Kubernetes secrets was never intended as a security measure. It does not exist to obscure or hide any values. The decision to implement this encoding method was initially made to enable the secrets to accommodate binary data. If the secrets were structured as simple maps, perhaps there would be less confusion. However, this isn't the point. When observers notice the base64 encoding, they often assume it to be a flawed attempt to achieve the protection of a value, even going so far as to regard it as a mistake. This interpretation, as we just saw, isn't accurate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmkh638cqhjq1esonpr6.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%2Fhmkh638cqhjq1esonpr6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to make Kubernetes Secrets secure?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Initially, RBAC (Role Base Access Control):&lt;/strong&gt; Restrict users or teams that have access to secrets, or block that access completely. Give access of a specific secret only to service accounts that need it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you have any policy engine:&lt;/strong&gt; Include policies that won't allow secrets being globally accessible. Come up with policies that make sense with your context, blocking or alerting when someone is violating your guidelines. Maybe you just want to avoid teams having access to other team's secrets. Maybe your control is more fine grained, and that is for you to figure out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encrypt etcd at rest:&lt;/strong&gt; This is the method to safeguard secret values stored within etcd and you shouldn't worry about it being easy to decode when you get the value. &lt;strong&gt;When you retrieve a value from kube API server with curl or kubectl, and it feels odd due to it merely being base64, pause to consider. When you are authenticated and authorized to do so, isn't obtaining a secret from a source you deem secure essentially the same?&lt;/strong&gt; For instance, if you curl Hashicorp Vault (or Azure Key Vault, or any other equivalent), armed with your proper keys and certificates, isn't the response plain text (I know it is obvious, I think we forget about this)? The value needs to be in plain text at some point, to the consumer — to the application that will use that credential — to do something. Our primary objective should be to ensure the secure storage and transmission of these values (though the latter won't be the focus in this article). We shouldn't concern ourselves unnecessarily with the data being displayed in plain text, provided the request comes from an authenticated and authorized entity that requires this information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzfz5ugwxn3b89gwjshc1.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%2Fzfz5ugwxn3b89gwjshc1.png" alt="Photo by Pete Alexopoulos on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Encrypting etcd alone is not enough
&lt;/h2&gt;

&lt;p&gt;Most guides that teach you how to encrypt etcd at rest will get you into a predicament. Encryption keys, in a lot of cases, are still stored in the same machines where your control plane components are running. If you consider an etcd instance to be compromised, and let's say the attacker has access to files on that machine, it is super simple to just decrypt the whole database.&lt;/p&gt;

&lt;p&gt;The preferred method of encrypting etcd values is by using a Key Management Service. Here we have some extra levels of indirection and also another layer of enforcement on authorization. You store the encryption key, encrypted, in a remote service. And only authorized services or users can access and decrypt the key and then the data. This can still be mimicked by an attacker, and reverse engineered into what they need, but it is still the recommended method as of this writing (you can always come up with more indirections, but complexity can also impact negatively security incident response, so better stick to supported approaches).&lt;/p&gt;

&lt;p&gt;A few other adjacent measures will be listed at the end of the article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvofivsm995nkb7ygb1yf.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%2Fvofivsm995nkb7ygb1yf.png" alt="Photo by Ariel on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Who uses Secrets?
&lt;/h2&gt;

&lt;p&gt;Kubernetes 😂. Your control plane, right now, is using Kubernetes Native Secrets, and those secret values are of course stored in etcd. It does not matter the flavor of Kubernetes, which cloud provider. Attackers with access to those secrets can already cause a lot of damage if you don't protect those secrets.&lt;/p&gt;

&lt;p&gt;My reasoning for this is as follows: if you believe Kubernetes Secrets should be avoided, does this mean you are also discarding the secrets that inherently come with using Kubernetes? You are probably not doing that. It might be more pragmatic to acknowledge their existence and strategize ways to secure them, along with your other secrets, within this context.&lt;/p&gt;

&lt;p&gt;Furthermore, Cloud Native tools from the Cloud Native Landscape will likely anticipate your secret values to be Kubernetes Native Secrets. If you wish to leverage the plug-and-play capabilities of the Kubernetes Ecosystem, avoiding secrets could lead to unnecessary difficulties. This choice would probably result in an excessive reliance on custom in-house solutions, which not only increase complexity but also introduce additional security risks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fum76idegrei5g3tkyiek.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%2Fum76idegrei5g3tkyiek.png" alt="Photo by Kirk Thornton on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So, etcd is compromised
&lt;/h2&gt;

&lt;p&gt;Let's try to explore a few premises and scenarios with regard to avoiding secrets.&lt;/p&gt;

&lt;h3&gt;
  
  
  The relevant assumptions when avoiding Kubernetes Secrets
&lt;/h3&gt;

&lt;p&gt;The biggest argument against Kubernetes Secrets comes from the fact that if etcd is compromised, you basically have access to any secret value on it. And I can see how that can be very dangerous. But I would argue this is only relevant in a very unrealistic scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attacker has &lt;strong&gt;only&lt;/strong&gt; read access to etcd (biggest gotcha in my opinion)&lt;/li&gt;
&lt;li&gt;Attacker has encryption key (or etcd is unencrypted)&lt;/li&gt;
&lt;li&gt;(Optional) Attacker has kubeconfg/credentials of a dev with limited permissions

&lt;ul&gt;
&lt;li&gt;can't pod exec into a container&lt;/li&gt;
&lt;li&gt;can't create pods in important namespaces&lt;/li&gt;
&lt;li&gt;can only get a few resources, logs, and some other minor permissions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Cluster is updated (above 1.24), and does not have any legacy token secrets for service accounts&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;If this scenario came to fruition (an attack happening exactly like this), avoiding Kubernetes Secrets in fact ended up protecting your environment. That's good.&lt;/p&gt;

&lt;p&gt;So, why do I say this is an unrealistic scenario? Have you ever heard of a security breach where an attacker got only read access to etcd, without write? This would require an attacker to get access to an etcd instance or endpoint, and have access to credentials of an user that only has read (but they have the encryption key). Another option could be: if the attacker has access to the instance and for some reason they have access only to the encryption key and not the credentials. In my experience, and opinion, this is not the scenario that actually happens. When etcd is compromised, it is completely compromised (I will touch on what happens when etcd is completely compromised later in this article).&lt;/p&gt;

&lt;p&gt;The other requirements of this scenario are also important. Avoiding secrets would not help if ANY of those are not true. If an Attacker has pod exec into any pod consuming a secret value (being Kubernetes Native Secret or not) that attacker now has a secret value (if they can grab a shell — if this is not protected or you are not using distro-less). Similarly if attackers can create pods using whatever k8s-secret-avoiding-mechanism you came up with, with a secret value mounted, again, they got a secret.&lt;/p&gt;

&lt;p&gt;Last but not least, if you are on Kubernetes &amp;lt;1.24, service accounts used to store tokens in secrets (not using TokenRequests). Whichever k8s-secret-avoiding-mechanism you might been using, probably used service account tokens or other credentials to talk to external Vaults. An attacker with access to a compromised etcd could just use that token to get a remote secret.&lt;/p&gt;

&lt;p&gt;Given that all these factors must align for avoiding Kubernetes Native Secrets to bear significance from a pure secret value protection standpoint, I would consider it niche, and not really relevant to the majority of setups around the globe.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft23mpka496s8mqo5mcw1.jpg" 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%2Ft23mpka496s8mqo5mcw1.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The non-arguments
&lt;/h3&gt;

&lt;p&gt;Previous scenario is a good example of when you are actually protected by not having Kubernetes Native Secrets, even though it is unrealistic. These other ones listed here are, in my opinion, not good arguments against using Secrets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Saying you can get the value easily decoded through the kube api-server: That's also easily protected by RBAC. And even considering any other way to mount a secret value into a pod, through an unprotected API you can still pod exec into it and get secret values. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Saying Secrets as Env vars are easily inspected: Kubernetes Native Secrets can be mounted as volumes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Saying that compromises that are not etcd related could also leave secrets exposed: The risk still exists with any other k8s-secret-avoiding-mechanism. Root access to nodes with RAM dumping or memory scan, network sniffing, or anything like that. As we said before, applications have the final plain text secret because they need it like that. A memory scan (or similar breach), due to its intrusive nature, could reveal secret values regardless of whether they are Kubernetes Native Secrets or not.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqgjk9dwe25uemkkti7s.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%2Fsqgjk9dwe25uemkkti7s.png" alt="Photo by Eugene Chystiakov on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The write on etcd
&lt;/h3&gt;

&lt;p&gt;If an attacker has write on etcd (and access to any kubeconfig even with a role without permissions), &lt;strong&gt;they have you&lt;/strong&gt;. It does not matter if you are avoiding Kubernetes Native secrets. It does not matter if you are using complex policies with popular policy engines.&lt;/p&gt;

&lt;p&gt;A few ways to get secrets (or almost anything) with write on etcd:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insert a RoleBinding with any privileged role to get access to pods with secret values mounted.&lt;/li&gt;
&lt;li&gt;Insert a pod or Deployment directly through etcd with inline secret value mounting.&lt;/li&gt;
&lt;li&gt;If a pod has a service account that lets it get secrets from a remote Vault: Insert a pod in etcd and make it use the same service account that can talk with the external Vault and write a simple code to call the TokenRequest API. This would also work on Kubernetes &amp;gt;1.24. You can log the token and get all secrets before it expires.&lt;/li&gt;
&lt;li&gt;There are a few other more complicated ways to get secrets even if the attacker does not have access to kube api-server. Shifting roles and role bindings around, getting privileged pods inside the cluster, acting and getting responses all from etcd. It is harder, but possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkazujowl0xluctscico1.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%2Fkazujowl0xluctscico1.png" alt="Photo by Jon Tyson on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So, nothing is secure?
&lt;/h2&gt;

&lt;p&gt;That is not the point. The point is that you have very similar threat models while avoiding Kubernetes Native Secrets and while not avoiding them. So, with similar threat models, the best option is the simplest option. To just use what you are used to, and figure out how to protect that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F90upfqx1wpll8ajv55a5.jpg" 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%2F90upfqx1wpll8ajv55a5.jpg" alt="Photo by Piret Ilver on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So..., we don't have any reason to avoid Kubernetes Secrets?
&lt;/h2&gt;

&lt;p&gt;Now, that is the right question! Do you? There are plenty of reasons to avoid Kubernetes Secrets. Maybe you have a company policy to follow. Perhaps you have to adhere to multiple types of compliance. Maybe the complexity of avoiding Kubernetes Native Secrets is worth it in your case, because it will make your life easier during auditing and some other recurring processes.&lt;/p&gt;

&lt;p&gt;My point is more on the side of: Avoiding Kubernetes Secrets is not intrinsically more secure all the time. On the other hand, hashing passwords when storing them into a database table is, and it is simple enough to always be worth it, and this is clearly not the same thing. You HAVE to check your requirements, and see what works for you, in this case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7j9tnd45llo7bmx6prn.jpg" 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%2Fw7j9tnd45llo7bmx6prn.jpg" alt="Photo by Jay Heike on Unsplash"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What is the best way to protect your secrets then?
&lt;/h1&gt;

&lt;p&gt;A few of the best practices were listed in the beginning of the article when we talked about RBAC, policies and encrypting and protecting ETCD. But there are other common security practices that are maybe even more important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Avoid initial attack vectors and using vulnerable software/dependencies (supply chain security). If your frontend has a vulnerable lib that lets people inject arbitrary code and somehow grab a shell of that frontend container. Then if somehow they can escape the container and escalate privileges to root, and then do a memory scan... This person has all your secrets on this node. It does not matter if you are avoiding Kubernetes Native Secrets or which solution you are using for synchronizing your secrets. Besides avoiding vulnerable software/dependencies, there are a bunch of other ways to protect yourself, like phishing training for non technical employees, WAF, and many others.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be mindful about Access Management all around. Not only RBAC on Kubernetes, but also to your cloud accounts, sub-accounts and your whole infrastructure. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design good identity and security boundaries for your system. Isolate tenants or teams of your company in a way that makes sense with regard to their daily work, your software architecture and your team structure, giving permissions and accesses only to people that need it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I know, these sound generic and basically best practices to protect your system in general. My point is that exactly. You have to do that first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhkdgnm8iwe0btryvxkoj.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%2Fhkdgnm8iwe0btryvxkoj.png" alt="eso"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Make sure your approach takes into consideration security response, and not only prevention. It is not only about protecting secrets. It also about what to do when (&lt;strong&gt;not if&lt;/strong&gt;) they leak.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Being one of the maintainers of External Secrets Operator (ESO) and getting most of the general advice out of the way, I also want to give you some reasons why ESO helps with security and facilitates your processes and I think you should also consider it (or some other tools that also deliver on some of these points): &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you can give your developers only references to secrets, and not secret values directly.&lt;/li&gt;
&lt;li&gt;ESO integrates into developers GitOps processes facilitating adoption and debugability.&lt;/li&gt;
&lt;li&gt;it facilitates the toll of &lt;a href="https://dev.to/canelasevero/true-secrets-auto-rotation-with-eso-and-vault-1g4o"&gt;auto-rotation&lt;/a&gt; and secret generation, helping with prevention and response.&lt;/li&gt;
&lt;li&gt;ESO already considers multi-tenant and multi cluster setups, then if that's your case you don't have to improvise&lt;/li&gt;
&lt;li&gt;ESO can use another service-account identity, per provider configuration, so you don't have to give permissions to the operator pod on all your providers. This also allows the pod itself to not have any permissions to the provider, just a detached service account.&lt;/li&gt;
&lt;li&gt;Accepting Kubernetes Native Secrets as the final destination to secret values simplifies your solution (most of the time). Complexity will mostly hurt the security of your system.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Summarizing everything
&lt;/h1&gt;

&lt;p&gt;The understanding and proper management of Kubernetes secrets are critical, and base64 encoding, often misunderstood as a weak security measure, is intended to handle binary data. Using RBAC and policies, and encrypting etcd at rest are ways to make secrets secure. However, the total avoidance of Kubernetes secrets is not necessarily safer and could add complexity. Always evaluate your specific needs to choose the right approach. Focus not only on prevention but also on effective response strategies for potential leaks. Tools like the External Secrets Operator (ESO) can assist in securing Kubernetes secrets, especially by making it easy to perform &lt;a href="https://dev.to/canelasevero/true-secrets-auto-rotation-with-eso-and-vault-1g4o"&gt;rotations&lt;/a&gt;. Essentially, system security requires a comprehensive view rather than focusing only on individual elements.&lt;/p&gt;

&lt;h1&gt;
  
  
  References:
&lt;/h1&gt;

&lt;p&gt;Unfortunately the reasoning behind base64 encoding on secrets is not shared on the documentation, or PRs/issues, as this of course feels obvious to core Kubernetes developers. However, Jordan Liggitt, one of Kubernetes top contributors, shares an answer here: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/49046439/why-does-k8s-secrets-need-to-be-base64-encoded-when-configmaps-does-not" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/49046439/why-does-k8s-secrets-need-to-be-base64-encoded-when-configmaps-does-not&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With regard to encryption at rest and KMS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/kms-provider/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/administer-cluster/kms-provider/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Considering my statement about any Kubernetes Control Plane using secrets to work under the hood: If you are an admin you can just &lt;code&gt;kubectl get secrets -A&lt;/code&gt; within a fresh provisioned cluster to see all the secrets being used. A few managed solutions won't even hide some from you. If it's self managed you are going to see hundreds of them.&lt;/p&gt;

&lt;p&gt;Given my opinion and experience on the read/write aspect of etcd during incidents. I would be curious to hear about other people experiences. Maybe I am completely mistaken here. Feel free to reach out!&lt;/p&gt;

&lt;p&gt;It is relevant to also have a look over documentation for Secrets and RBAC on official docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/concepts/configuration/secret/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/reference/access-authn-authz/rbac/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking back at the part we talked about injecting pods or other resources into etcd directly, here you can see a simple  step by step example of injecting a pod:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lobuhisec.medium.com/using-etcd-to-inject-resources-and-bypass-rbac-and-admission-controller-restrictions-f240ae31e7f0" rel="noopener noreferrer"&gt;https://lobuhisec.medium.com/using-etcd-to-inject-resources-and-bypass-rbac-and-admission-controller-restrictions-f240ae31e7f0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even though I don't necessarily agree with all statements on the following article (as I still think it is worth it to use external providers), this was one of the blogs that resonated with me some time ago when we were having these kinds of discussions within the community: &lt;a href="https://www.macchaffee.com/blog/2022/k8s-secrets/" rel="noopener noreferrer"&gt;https://www.macchaffee.com/blog/2022/k8s-secrets/&lt;/a&gt;, written by Mac Chaffee. I get some analogies and threat modeling way of thinking from it.&lt;/p&gt;

&lt;p&gt;Finally, since we mentioned ESO, I would recommend looking at ESO's docs and the talk given at Kubecon:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://external-secrets.io/" rel="noopener noreferrer"&gt;https://external-secrets.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/upwIlUHkDf8" rel="noopener noreferrer"&gt;https://youtu.be/upwIlUHkDf8&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And would also like to thank the whole external-secrets community for trusting ESO when handling their secrets! :D&lt;/p&gt;

&lt;p&gt;As a follow up blog post I'm thinking about sharing some lab examples of how to get secrets in multiple scenarios, and how to protect from those attacks. Please let me know if that would be interesting to you, as it would be a lot of work, and I can do it on demand! 😁&lt;/p&gt;

</description>
      <category>security</category>
      <category>devsecops</category>
      <category>kubernetes</category>
      <category>secrets</category>
    </item>
    <item>
      <title>True Secrets Auto Rotation with ESO and Vault</title>
      <dc:creator>Lucas Severo Alves</dc:creator>
      <pubDate>Thu, 27 Jul 2023 20:40:37 +0000</pubDate>
      <link>https://dev.to/canelasevero/true-secrets-auto-rotation-with-eso-and-vault-1g4o</link>
      <guid>https://dev.to/canelasevero/true-secrets-auto-rotation-with-eso-and-vault-1g4o</guid>
      <description>&lt;p&gt;&lt;em&gt;Translation to pt-br at &lt;a href="https://knela.dev/blog/auto-rotao-de-segredos-de-verdade-com-eso-e-vault" rel="noopener noreferrer"&gt;https://knela.dev/blog/auto-rotao-de-segredos-de-verdade-com-eso-e-vault&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Kubernetes cluster that you can use (kind, minikube, something managed) and kubectl to connect to it&lt;/li&gt;
&lt;li&gt;Vault CLI&lt;/li&gt;
&lt;li&gt;External Secrets Operator (&lt;a href="https://external-secrets.io/" rel="noopener noreferrer"&gt;ESO&lt;/a&gt;) &lt;a href="https://artifacthub.io/packages/helm/external-secrets-operator/external-secrets" rel="noopener noreferrer"&gt;installed&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Vault installed through the &lt;a href="https://developer.hashicorp.com/vault/tutorials/kubernetes/kubernetes-minikube-raft" rel="noopener noreferrer"&gt;helm chart&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we want to achieve
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk3769u373fiungnrn8e.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%2Fvk3769u373fiungnrn8e.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This guide aims to establish an automatic hourly rotation of a database connection secret. Following these steps, an administrator sets up the process once, ensuring that the secret refreshes/changes every hour. Simultaneously, the application will always maintain new valid credentials for seamless database interactions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fughfgbdpt2nrtjjlvpzu.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%2Fughfgbdpt2nrtjjlvpzu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ESO secret &lt;a href="https://external-secrets.io/v0.8.5/api/generator/vault/" rel="noopener noreferrer"&gt;Generators&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;⚠️ As of this writing this feature is in alpha state, and we want more people to help test it, so we can make improvements, and eventually promote to stable.&lt;/p&gt;

&lt;p&gt;Documentation around it is a bit limited, that's why I am getting this guide out in my blog, while we figure better ways to bring these into our documentation. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8u4nmhydcsg4mg3ly63c.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%2F8u4nmhydcsg4mg3ly63c.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Let's make sure we start with the same setup locally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have installed Vault in a namespace named vault.

&lt;ul&gt;
&lt;li&gt;You can use &lt;code&gt;helm install vault hashicorp/vault -n vault --create-namespace&lt;/code&gt; command instead of the one provided &lt;a href="https://developer.hashicorp.com/vault/tutorials/kubernetes/kubernetes-minikube-raft" rel="noopener noreferrer"&gt;in the guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Follow all steps in there to init Vault, unseal, and get the &lt;code&gt;cluster-keys.json&lt;/code&gt; with the token.&lt;/li&gt;
&lt;li&gt;You can skip other steps.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;I have &lt;a href="https://artifacthub.io/packages/helm/external-secrets-operator/external-secrets" rel="noopener noreferrer"&gt;installed ESO&lt;/a&gt; in the default namespace.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In this guide we are going to use Vault token authentication just for the sake of simplicity. However, please never use this in real setups. Prefer service account auth.&lt;/p&gt;

&lt;p&gt;After properly starting Vault and unsealing it, take note of your auth token. Let's do a port forward and authenticate in our work desktop so we don't have to exec into Vault every time we need to run commands.&lt;/p&gt;

&lt;p&gt;In a new terminal (this terminal will be blocked)&lt;/p&gt;

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

kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; vault port-forward service/vault 8200:8200


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

&lt;/div&gt;

&lt;p&gt;In another terminal you can run.&lt;/p&gt;

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

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VAULT_ADDR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:8200
vault login
&lt;span class="c"&gt;## type your auth token&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fayv1stf8hjfb135mmil1.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%2Fayv1stf8hjfb135mmil1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple Deployment of PostgreSQL
&lt;/h2&gt;

&lt;p&gt;To have an interesting example, let's deploy psql and configure it so we can let Vault and other workloads connect to it.&lt;/p&gt;

&lt;p&gt;Let's first create a configmap with an admin user and password for this psql instance (just for simplicity and to get to the other part of the guide quickly).&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;cat &amp;lt;&amp;lt;EOF &amp;gt; postgres-config.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ConfigMap&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres-config&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresdb&lt;/span&gt;
  &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
  &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;psltest&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Apply it.&lt;/p&gt;

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

kubectl apply -f postgres-config.yaml


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

&lt;/div&gt;

&lt;p&gt;Now create the postgres-deployment.yaml.&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;cat &amp;lt;&amp;lt;EOF &amp;gt; postgres-deployment.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;  &lt;span class="c1"&gt;# Sets Deployment name&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:10.1&lt;/span&gt; &lt;span class="c1"&gt;# Sets Image&lt;/span&gt;
          &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;IfNotPresent"&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5432&lt;/span&gt;  &lt;span class="c1"&gt;# Exposes container port&lt;/span&gt;
          &lt;span class="na"&gt;envFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;configMapRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres-config&lt;/span&gt;

&lt;span class="s"&gt;EOF&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Apply it.&lt;/p&gt;

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

kubectl apply -f postgres-deployment.yaml


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

&lt;/div&gt;

&lt;p&gt;And finally, let's create a service, so other workloads can access it:&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;cat &amp;lt;&amp;lt;EOF &amp;gt; postgres-service.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt; &lt;span class="c1"&gt;# Sets service name&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt; &lt;span class="c1"&gt;# Labels and Selectors&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePort&lt;/span&gt; &lt;span class="c1"&gt;# Sets service type&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5432&lt;/span&gt; &lt;span class="c1"&gt;# Sets port to run the postgres application&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;

&lt;span class="s"&gt;EOF&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Apply it.&lt;/p&gt;

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

kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; postgres-service.yaml


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Preparing DB with new readonly role
&lt;/h2&gt;

&lt;p&gt;Exec into the psql pod.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

kubectl get pods &lt;span class="c"&gt;# get pod name&lt;/span&gt;
kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &amp;lt;postgres-pod-name&amp;gt; &lt;span class="nt"&gt;--&lt;/span&gt; bash


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

&lt;/div&gt;

&lt;p&gt;Change into postgres user, and run commands to create the new role.&lt;/p&gt;

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

su postgres
psql -c "CREATE ROLE \"ro\" NOINHERIT;"
psql -c "GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"ro\";"


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

&lt;/div&gt;

&lt;p&gt;We are going to use this role when configuring Vault to use Dynamic Secrets with psql plugin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr74yrbcr68cocp3v0vlj.jpg" 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%2Fr74yrbcr68cocp3v0vlj.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Vault Dynamic Secrets
&lt;/h2&gt;

&lt;p&gt;Vault Dynamic secrets are in fact meant to be used as a way to get short lived credentials. However, there is nothing stopping us from using them in our auto-rotation process. There are various other plugins that integrate with other systems, like AWS credentials, or certificate issuing systems. Most of these are also interesting in the context of ESO, but I wanted a self-contained example with no need to create external accounts for you to try it out.&lt;/p&gt;

&lt;p&gt;Lets first enable the database engine.&lt;/p&gt;

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

vault secrets &lt;span class="nb"&gt;enable &lt;/span&gt;database


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

&lt;/div&gt;

&lt;p&gt;After that, let's configure PostgreSQL secrets engine, with the admin creds we had before (we are passing credentials into the connection url here, never do that outside of test labs).&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;## POSTGRES_URL with name of the service and namespace&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres.default.svc.cluster.local:5432

vault write database/config/postgresql &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nv"&gt;plugin_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgresql-database-plugin &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;connection_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"postgresql://admin:psltest@&lt;/span&gt;&lt;span class="nv"&gt;$POSTGRES_URL&lt;/span&gt;&lt;span class="s2"&gt;/postgres?sslmode=disable"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nv"&gt;allowed_roles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;readonly&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nv"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"root"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"rootpassword"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Create an SQL file container the templated command that will be used by Vault when dynamically creating roles.&lt;/p&gt;

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

&lt;span class="nb"&gt;tee &lt;/span&gt;readonly.sql &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}' INHERIT;
GRANT ro TO "{{name}}";
&lt;/span&gt;&lt;span class="no"&gt;EOF


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

&lt;/div&gt;

&lt;p&gt;Write that into Vault and configure default expiration of new requested roles and other fields (this will fail if you did not create the ROLE 'ro' correctly while setting up psql).&lt;/p&gt;

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

vault write database/roles/readonly \
      db_name=postgresql \
      creation_statements=@readonly.sql \
      default_ttl=1h \
      max_ttl=24h


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

&lt;/div&gt;

&lt;p&gt;You can already check within Vault if you can get the temporary credentials before setting up other steps.&lt;/p&gt;

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

vault read database/creds/readonly
## response
Key                Value
---                -----
lease_id           database/creds/readonly/CPqcUrG55f8qfrA9QKMV3peO
lease_duration     1h
lease_renewable    true
password           5p-xDWSC5Iu9z-hlZPrs
username           v-root-readonly-SQjhNhGxxmKx9QaRKsxM-1690473242


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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F822vruepu9ahl0oduhz6.jpg" 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%2F822vruepu9ahl0oduhz6.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ESO Generator and ExternalSecret
&lt;/h2&gt;

&lt;p&gt;Before next steps we are going to base64 encode the token so we can apply it with a secret. Grab you Vault token and echo it into base64.&lt;/p&gt;

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

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"somethinsomething"&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now we can use the new External Secrets Operator CRD, the Generator. Use the value outputted above for the auth token secret (vault-token). &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;cat &amp;lt;&amp;lt;EOF &amp;gt; vaultDynamicSecret.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;generators.external-secrets.io/v1alpha1&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;VaultDynamicSecret&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;psql-example"&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/database/creds/readonly"&lt;/span&gt; &lt;span class="c1"&gt;## this is how you choose which vault dynamic path to use&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET"&lt;/span&gt; &lt;span class="c1"&gt;## this path will only work with GETs&lt;/span&gt;
  &lt;span class="c1"&gt;# parameters: ## no needed parameters &lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://vault.vault.svc.cluster.local:8200"&lt;/span&gt; &lt;span class="c1"&gt;## vault url. In this case vault service on the vault namespace&lt;/span&gt;
    &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# points to a secret that contains a vault token&lt;/span&gt;
      &lt;span class="c1"&gt;# https://www.vaultproject.io/docs/auth/token&lt;/span&gt;
      &lt;span class="na"&gt;tokenSecretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;## reference to the secret holding the Vault auth token&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vault-token"&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Secret&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vault-token&lt;/span&gt;
&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aHZzLkM4M0o2UWNQSW1YQkRJVU96aWNNNzVHdwo=&lt;/span&gt; &lt;span class="c1"&gt;## token base64 encoded&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Apply this file.&lt;/p&gt;

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

kubectl apply -f vaultDynamicSecret.yaml


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

&lt;/div&gt;

&lt;p&gt;And finally we can now create our ExternalSecret that in the end will let the operator create the final Kubernetes Secret.&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;cat &amp;lt;&amp;lt;EOF &amp;gt; vaultDynamicSecret.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;external-secrets.io/v1beta1&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;ExternalSecret&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;psql-example-es"&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;refreshInterval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1h"&lt;/span&gt; &lt;span class="c1"&gt;## the same as the expiry time on the dynamic config of Vault, or lower, so apps have always new valid credentials&lt;/span&gt;
  &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;psql-example-for-use&lt;/span&gt; &lt;span class="c1"&gt;## the final name of the kubernetes secret created in your cluster&lt;/span&gt;
  &lt;span class="na"&gt;dataFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;sourceRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;generatorRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;generators.external-secrets.io/v1alpha1&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;VaultDynamicSecret&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;psql-example"&lt;/span&gt; &lt;span class="c1"&gt;## reference to the generator&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Apply this and check if the status of the ExternalSecret is ok.&lt;/p&gt;

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

kubectl get externalsecret
&lt;span class="c"&gt;## response&lt;/span&gt;
NAME              STORE   REFRESH INTERVAL   STATUS         READY
psql-example-es           1h                 SecretSynced   True


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

&lt;/div&gt;

&lt;p&gt;If you get errors here, verify that you used the right path in the Generator. Also check that you created the right roles inside psql and you can ping vault from a pod in the ESO namespace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking the final secret
&lt;/h2&gt;

&lt;p&gt;You should get a secret containing new users and passwords with read-only access to the database every hour.&lt;/p&gt;

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

kubectl get secrets psql-example-for-use &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{.data}"&lt;/span&gt;
&lt;span class="c"&gt;## response&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;:&lt;span class="s2"&gt;"V2lSWUlqZzdvQS1yOTFaV2N1SWE="&lt;/span&gt;,&lt;span class="s2"&gt;"username"&lt;/span&gt;:&lt;span class="s2"&gt;"di1yb290LXJlYWRvbmx5LVlXQ3kzZ01hbkhSbGtuY3FqTUg2LTE2OTA0NzIwMzc="&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;To check one of the values you can get it and base64 decode it.&lt;/p&gt;

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

kubectl get secrets psql-example-for-use &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{.data.password}"&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now your application can use this secret, it will be automatically auto-rotated, and still be a valid credential to the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;If you use secrets as Environment Variables you will need to use something to make workloads get the new credentials, if they just loose connection. You can use the &lt;a href="https://github.com/stakater/Reloader" rel="noopener noreferrer"&gt;Reloader&lt;/a&gt; project for that.&lt;/p&gt;

&lt;p&gt;If you use secrets as volumes, pods will get that update automatically, and you won't have problems connecting, as long as your application can get the new values.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx079b7hakbqw2qhex5qk.jpg" 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%2Fx079b7hakbqw2qhex5qk.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it! We've set up an auto-rotating secret for a database connection using ESO and Vault. The magic is, as we said, you can set it once and forget. Your secret refreshes every hour and your app stays connected to the database with new valid credentials. It is secure, you follow best practices with regard to rotation, and you avoid manual intervention if that is not needed.&lt;/p&gt;

</description>
      <category>secrets</category>
      <category>kubernetes</category>
      <category>security</category>
      <category>vault</category>
    </item>
    <item>
      <title>As a Dev, you should know Ops</title>
      <dc:creator>Lucas Severo Alves</dc:creator>
      <pubDate>Mon, 03 Jun 2019 23:13:44 +0000</pubDate>
      <link>https://dev.to/canelasevero/as-a-dev-you-should-know-ops-3bkh</link>
      <guid>https://dev.to/canelasevero/as-a-dev-you-should-know-ops-3bkh</guid>
      <description>&lt;h2&gt;
  
  
  Cause DevOps.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2F66.media.tumblr.com%2F3c3dcedd1f0a367c441b7459bf938649%2Ftumblr_neav81r0xw1swi8zgo1_400.gif" 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%2F66.media.tumblr.com%2F3c3dcedd1f0a367c441b7459bf938649%2Ftumblr_neav81r0xw1swi8zgo1_400.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some would say that you should learn it simply because you should, end of story. But it’s not that simple. Regardless of your reasons, I think that you should learn it to be a better dev and to boost your technical career.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lets quickly look at DevOps
&lt;/h2&gt;

&lt;p&gt;Think about the traditional Dev vs Ops goals that existed “long ago” (Hopefully, you’re past dealing with this today): Devs were rewarded for shipping features and making changes, while Ops were rewarded by keeping things stable, and thus change was an enemy.&lt;/p&gt;

&lt;p&gt;A massive number of methodologies were created, or borrowed, to get rid of this conflict, like &lt;a href="https://landing.google.com/sre/sre-book/chapters/postmortem-culture/" rel="noopener noreferrer"&gt;Blameless Postmortems&lt;/a&gt; and &lt;a href="https://books.google.com.br/books/about/Just_Culture.html?id=ZA0uXmtR96MC&amp;amp;redir_esc=y" rel="noopener noreferrer"&gt;Just Culture&lt;/a&gt;. Another example is error-budgeting, in which SLAs and SLOs define how stable something has to be, and also how unstable it 'must' be. This is done to cut costs while encouraging change.&lt;/p&gt;

&lt;p&gt;These things, paired with the LEAN practices, reflect the cultural and organizational pillars of DevOps. They are crucial, but often disregarded by some people. The other pillars use automation to cut down on repetitive tasks, and improve intelligent decision making with better data through monitoring, observing, and using this data as a guide.&lt;/p&gt;

&lt;p&gt;With all that in mind, I would say that there is a lot more about DevOps than just Devs knowing Ops.&lt;/p&gt;

&lt;p&gt;So, why would you, as a Dev, need to know some Ops, if not because of DevOps ? I’ll now try to give you four reasons that answer this question in a more career-oriented vibe. Maybe your company or your current position doesn’t require this knowledge, but knowing it will make you a better Dev overall, helping you write better services and giving you more “power”.&lt;/p&gt;

&lt;h2&gt;
  
  
  1- You can be part of important technical decisions/discussions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7uks54hbzkl1925o05br.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7uks54hbzkl1925o05br.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ops knowledge can open many doors for you. If your company has an architecture-steering committee or something similar, having such knowledge may play a big role in you becoming part of it, or even in bringing things for the committee to discuss. You may have a say in decisions related to stack, architecture, and even business.&lt;/p&gt;

&lt;p&gt;Let’s say your company has a bit of a delay when it comes to response in some situations and in some services. One possible solution is to re-implement some of these services and part of the architecture. However, this could be very time consuming and demand a lot of effort. A better option might be to do a mix of software and infrastructure architecture change, hopefully with less effort. You might arrive at this solution by yourself from having a “mixed bag” of knowledge. You can then bring more people in for discussion on the topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  2- You can write better services
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flibbz51il7t24wqb94p6.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flibbz51il7t24wqb94p6.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the same way that you can provide better answers to problems that emerge in your services regarding its architecture and code, Ops knowledge may allow you to foresee problems that are bound to happen.&lt;/p&gt;

&lt;p&gt;Your development can be really modular and focused on the thing your service is solving. But the ability to visualize problems regarding how your service interacts with other services and with the systems holding it is crucial for applications with really high SLOs and SLAs. This makes your services both reliable and available.&lt;/p&gt;

&lt;p&gt;Hopefully, with some Ops or System Administrator experience under your belt, you will also feel the need to keep your services observable. With operability and observability you make possible to have people on call with less stress. &lt;/p&gt;

&lt;h2&gt;
  
  
  3- Being on call can make you foolproof when coding
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fya0vj3lqvidkbe24k0an.jpg" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fya0vj3lqvidkbe24k0an.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here I am not talking about just Ops knowledge, but also Ops experience with being on call. With enough of it, you start to see the weak links and parts most prone to failure in your system. This gets to you, you start feeling it under your skin, and when you go back to coding , it should influence you to write better code.&lt;/p&gt;

&lt;p&gt;This one is almost the same as the second item, but I believe that the experience of being on call brings something that only it can bring: empathy for service operability. The second item refers to Ops knowledge you can acquire by reading or listening to people. This one refers to the knowledge acquired by your own experience and how this can later be used in writing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  4- You can be part of all the life cycle of your code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp4n6j67cqq1vayl3k8af.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fp4n6j67cqq1vayl3k8af.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can write your code, and &lt;a href="https://medium.com/@copyconstruct/testing-microservices-the-sane-way-9bb31d158c16" rel="noopener noreferrer"&gt;test it&lt;/a&gt;; you know how to CI/CD it, and you know how to operate it in the production. You also know how to &lt;a href="https://twitter.com/mipsytipsy/status/1086366949682995200" rel="noopener noreferrer"&gt;observe&lt;/a&gt; everything. I’m not saying you will be doing all these things every time, but you have the know-how, and may have done it before.&lt;/p&gt;

&lt;p&gt;Your company shouldn’t expect everyone to know all of these things. But knowing them might reward you greatly. And thus, this pursuit should be encouraged by your company.&lt;/p&gt;

&lt;h1&gt;
  
  
  So, how do we go about this?
&lt;/h1&gt;

&lt;p&gt;I hope I have convinced you to learn some Ops. If you don’t know how, here are some options:&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;I like the &lt;a href="https://www.opsschool.org/" rel="noopener noreferrer"&gt;opsschool readthedocs&lt;/a&gt;. There are a lot of topics missing content, but you can still use it as a list of topics to further research on the internet, and maybe get some books and articles on.&lt;/p&gt;

&lt;p&gt;There are lots of specific tools-focused books that I could suggest, but you’d be better off looking for them based on what your company uses and what you want to learn.&lt;/p&gt;

&lt;p&gt;For more general learning you could get &lt;a href="https://www.amazon.com/Practice-Cloud-System-Administration-Practices/dp/032194318X" rel="noopener noreferrer"&gt;The Practice of Cloud System Administration&lt;/a&gt; and &lt;a href="https://www.amazon.com/UNIX-Linux-System-Administration-Handbook/dp/0134277554" rel="noopener noreferrer"&gt;UNIX Linux System Administration Handbook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For Linux, &lt;a href="https://www.amazon.com/Linux-Programming-Interface-System-Handbook/dp/1593272200/ref=sr_1_1?crid=VX920BJV6BJ2&amp;amp;keywords=linux+programming+interface&amp;amp;qid=1559098222&amp;amp;s=gateway&amp;amp;sprefix=linux+pro%2Caps%2C311&amp;amp;sr=8-1" rel="noopener noreferrer"&gt;Linux Programming Interface System Handbook&lt;/a&gt; is a great book. Mostly to be used as reference.&lt;/p&gt;

&lt;p&gt;For networking you can read &lt;a href="https://www.amazon.com/Computer-Networks-Tanenbaum-International-Economy/dp/9332518742" rel="noopener noreferrer"&gt;Computer Networks by Tanenbaum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can read this references about observability: &lt;a href="https://www.honeycomb.io/resources/guide-achieving-observability/" rel="noopener noreferrer"&gt;Honeycombio Guide to Achieving Observability&lt;/a&gt; and &lt;a href="https://www.oreilly.com/library/view/distributed-systems-observability/9781492033431/ch01.html" rel="noopener noreferrer"&gt;Distributed Systems Observability&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I know this seems like a lot, but don’t be intimidated by it all! Remember, there’s no need to read all of it. And here’s the actual best way to learn Ops:&lt;/p&gt;

&lt;h3&gt;
  
  
  Just do it!
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/TCaq4FekwSV5m/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/TCaq4FekwSV5m/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See if your company gives you the option to try other positions and go for it. Ask for guidance and try to stay on call sometimes. If you have people around you who know something, talking to them and sharing what you know might be the best way to learn. So long as you have solid development skills, the addition of Ops experience could help you achieve even greater things!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ops</category>
      <category>career</category>
    </item>
  </channel>
</rss>
