<?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: Yann Soubeyrand</title>
    <description>The latest articles on DEV Community by Yann Soubeyrand (@yann).</description>
    <link>https://dev.to/yann</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%2F376963%2F4ff7dc9d-97cf-4bbd-8d92-8e9f042a422d.png</url>
      <title>DEV Community: Yann Soubeyrand</title>
      <link>https://dev.to/yann</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yann"/>
    <language>en</language>
    <item>
      <title>Investigating a timeout issue in an Istio service mesh</title>
      <dc:creator>Yann Soubeyrand</dc:creator>
      <pubDate>Thu, 07 May 2020 07:53:11 +0000</pubDate>
      <link>https://dev.to/camptocamp-ops/investigating-a-timeout-issue-in-an-istio-service-mesh-4m6e</link>
      <guid>https://dev.to/camptocamp-ops/investigating-a-timeout-issue-in-an-istio-service-mesh-4m6e</guid>
      <description>&lt;p&gt;Last week, with my colleague &lt;a href="https://dev.to/mfournier"&gt;Marc&lt;/a&gt;, we faced a timeout issue in an &lt;a href="https://istio.io/" rel="noopener noreferrer"&gt;Istio&lt;/a&gt; service mesh. An idle PostgreSQL connection was shut down precisely one hour after it has been opened. During our investigations, I had to capture the network traffic entering and leaving the PostgreSQL client pod.&lt;/p&gt;

&lt;h1&gt;
  
  
  Ksniff
&lt;/h1&gt;

&lt;p&gt;For this, I've been using &lt;a href="https://github.com/eldadru/ksniff" rel="noopener noreferrer"&gt;Ksniff&lt;/a&gt;. This Kubernetes plugin tries to deploy a statically compiled tcpdump binary inside the pod which traffic you want to capture and then streams the captured packets to a &lt;a href="https://www.wireshark.org/" rel="noopener noreferrer"&gt;Wireshark&lt;/a&gt; instance running on your workstation. This plugin is just awesome, thanks a lot to its author &lt;a href="https://github.com/eldadru" rel="noopener noreferrer"&gt;Eldad Rudich&lt;/a&gt;!&lt;/p&gt;

&lt;h1&gt;
  
  
  Envoy traffic interception
&lt;/h1&gt;

&lt;p&gt;Istio works by injecting an &lt;a href="https://www.envoyproxy.io/" rel="noopener noreferrer"&gt;Envoy proxy&lt;/a&gt; sidecar container inside every pod, which will intercept inbound and outbound network traffic. So when a process inside your container communicates with an external server, there are in fact two TCP connections: one between the process and Envoy, and one between Envoy and the distant server. However, in Wireshark, I saw only the packets between Envoy and the distant server and the packets from Envoy to the process but not the packets from the process to Envoy.&lt;/p&gt;

&lt;p&gt;In the Wireshark screenshot below, &lt;code&gt;10.0.9.225&lt;/code&gt; is the IP address of the process, &lt;code&gt;172.20.94.219&lt;/code&gt; is the IP address of the virtual service the process communicates with, and &lt;code&gt;10.0.5.234&lt;/code&gt; is the IP address of the distant (real) server backing the virtual service.&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%2Fi%2F4c4jnavfwdm37os1art0.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%2Fi%2F4c4jnavfwdm37os1art0.png" alt="Wireshark screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was a bit surprised 🤔 So I searched how Istio diverted the network traffic through Envoy. It does so by adding iptables &lt;code&gt;REDIRECT&lt;/code&gt; rules to send the traffic to port &lt;code&gt;15001&lt;/code&gt; on &lt;code&gt;localhost&lt;/code&gt; which Envoy is listening on. Indeed, I could see it in Wireshark:&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%2Fi%2Fjkic48lkvvbhp4axu9af.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%2Fi%2Fjkic48lkvvbhp4axu9af.png" alt="Wireshark screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But then, how can Envoy know where to forward the traffic if all the traffic it sees entering is destined for &lt;code&gt;127.0.0.1:15001&lt;/code&gt;? All my knowledge on IP network functioning was questioned! However, after some time spent looking for the answer, I finally found it!&lt;/p&gt;

&lt;p&gt;When a packet hits an iptables &lt;code&gt;REDIRECT&lt;/code&gt; rules, the kernel sets a socket option named &lt;code&gt;SO_ORIGINAL_DST&lt;/code&gt; which contains the original packet destination. Envoy just has to &lt;a href="https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/listener_filters/original_dst_filter" rel="noopener noreferrer"&gt;read&lt;/a&gt; this option to decide what to do with this packet.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We've seen how network traffic is redirected in an Istio service mesh using iptables &lt;code&gt;REDIRECT&lt;/code&gt; rules and &lt;code&gt;SO_ORIGINAL_DST&lt;/code&gt; socket option.&lt;/p&gt;

&lt;p&gt;Going back to our original issue, the investigations confirmed that the culprit was Envoy's &lt;a href="https://www.envoyproxy.io/docs/envoy/latest/faq/configuration/timeouts.html#tcp" rel="noopener noreferrer"&gt;idle timeout&lt;/a&gt;. From what I understand, it should be possible to &lt;a href="https://github.com/istio/istio/pull/13515" rel="noopener noreferrer"&gt;configure&lt;/a&gt; it, but I didn't figure out yet how to do so.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>istio</category>
      <category>network</category>
    </item>
    <item>
      <title>Argo CD secrets management using Sops</title>
      <dc:creator>Yann Soubeyrand</dc:creator>
      <pubDate>Mon, 04 May 2020 14:56:19 +0000</pubDate>
      <link>https://dev.to/camptocamp-ops/argo-cd-secrets-management-using-sops-1eke</link>
      <guid>https://dev.to/camptocamp-ops/argo-cd-secrets-management-using-sops-1eke</guid>
      <description>&lt;p&gt;At &lt;a href="https://camptocamp.com"&gt;Camptocamp&lt;/a&gt;, we've been using &lt;a href="https://argoproj.github.io/argo-cd/"&gt;Argo CD&lt;/a&gt; for some time. It does a wonderful job of deploying Helm charts to Kubernetes clusters. But we lacked a way to manage our secrets so that we could safely commit them to our Git repositories.&lt;/p&gt;

&lt;h1&gt;
  
  
  Helm Secrets plugin
&lt;/h1&gt;

&lt;p&gt;We knew about &lt;a href="https://github.com/zendesk/helm-secrets"&gt;Helm Secrets&lt;/a&gt;, a Helm plugin which uses &lt;a href="https://github.com/mozilla/sops"&gt;Sops&lt;/a&gt; under the hood to manage encrypted value files. We intended to use it with Argo CD but we faced several issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To render an Helm chart's manifests, Argo CD issues a &lt;code&gt;helm template&lt;/code&gt; command. To use Helm Secrets, it would have to execute &lt;code&gt;helm secrets template&lt;/code&gt; instead. However, there is no way to edit the Helm command used by Argo CD. One has to configure a &lt;a href="https://argoproj.github.io/argo-cd/user-guide/config-management-plugins/"&gt;custom plugin&lt;/a&gt;. This has the drawback of loosing Helm specific features (like specifying value files or parameters).&lt;/li&gt;
&lt;li&gt;Helm Secrets works by decrypting secret value files to temporary files on disk before actually calling Helm. While not a big concern, it's not a security best practice. Secrets should never touch the disk when they are unencrypted.&lt;/li&gt;
&lt;li&gt;Helm Secrets seemed unmaintained at the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Helm Sops
&lt;/h1&gt;

&lt;p&gt;Since we only needed a small subset of Helm Secrets' functionalities, we decided to write a small Go binary which would transparently wrap Helm so that we could substitute the Helm binary with it in the Argo CD Docker image. Let's introduce &lt;a href="https://github.com/camptocamp/helm-sops"&gt;Helm Sops&lt;/a&gt;!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/camptocamp"&gt;
        camptocamp
      &lt;/a&gt; / &lt;a href="https://github.com/camptocamp/helm-sops"&gt;
        helm-sops
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Helm Sops&lt;/h1&gt;
&lt;p&gt;Helm Sops is a Helm wrapper which decrypts Sops encrypted value files before invoking Helm. It does so by using named pipes to pass cleartext value files to Helm in order to avoid secrets being written to disk in clear.&lt;/p&gt;
&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;h3&gt;
Prerequisites&lt;/h3&gt;
&lt;p&gt;Helm is needed for Helm Sops to work. Follow the instructions &lt;a href="https://helm.sh/docs/intro/install/" rel="nofollow"&gt;here&lt;/a&gt; to install it.&lt;/p&gt;
&lt;h3&gt;
Getting Helm Sops binary&lt;/h3&gt;
&lt;h4&gt;
Helm Sops releases&lt;/h4&gt;
&lt;p&gt;Helm Sops released binaries can be downloaded from &lt;a href="https://github.com/camptocamp/helm-sops/releases"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
Building from sources&lt;/h4&gt;
&lt;p&gt;Helm Sops can be built using the &lt;code&gt;go build&lt;/code&gt; command.&lt;/p&gt;
&lt;h3&gt;
Deploying Helm Sops&lt;/h3&gt;
&lt;p&gt;Deploy Helm Sops executable (&lt;code&gt;helm-sops&lt;/code&gt;) in a directory present in the &lt;em&gt;PATH&lt;/em&gt;. When invoking Helm Sops, it will look for a Helm executable named &lt;code&gt;helm&lt;/code&gt; in the &lt;em&gt;PATH&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Alternatively, Helm Sops executable can be renamed &lt;code&gt;helm&lt;/code&gt; before deploying it. When invoked as &lt;code&gt;helm&lt;/code&gt;, Helm Sops will look for a Helm executable named &lt;code&gt;_helm&lt;/code&gt;…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/camptocamp/helm-sops"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Helm Sops is loosely inspired by Helm Secrets but uses named pipes instead of temporary files to pass decrypted secret value files to Helm.&lt;/p&gt;

&lt;p&gt;To use it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;deploy our custom Argo CD &lt;a href="https://github.com/camptocamp/docker-argocd"&gt;Docker image&lt;/a&gt; integrating Helm Sops to your Kubernetes cluster,&lt;/li&gt;
&lt;li&gt;install Sops on your workstation and create a &lt;a href="https://github.com/mozilla/sops#using-sops-yaml-conf-to-select-kms-pgp-for-new-files"&gt;&lt;code&gt;.sops.yaml&lt;/code&gt;&lt;/a&gt; file to specify the encryption method to use (GPG key, AWS KMS key, etc),&lt;/li&gt;
&lt;li&gt;use Sops to create a file named &lt;code&gt;secrets.yaml&lt;/code&gt; and put your Helm secret values inside,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git commit&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git push&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;finally, visit the Argo CD web interface to deploy your Helm application \o/&lt;/li&gt;
&lt;li&gt;(optional) install Helm Sops on your workstation to be able to use the Argo CD CLI with encrypted value files.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Full step by step instructions can be found &lt;a href="https://github.com/camptocamp/argocd-helm-sops-example"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Security Considerations
&lt;/h1&gt;

&lt;p&gt;While Sops uses battle tested cryptography, the way we use it with Argo CD makes it vulnerable to the &lt;a href="https://en.wikipedia.org/wiki/Confused_deputy_problem"&gt;confused deputy problem&lt;/a&gt;. Someone which can deploy applications using Argo CD and has access to an encrypted value file but cannot decrypt it, can deploy a new application accompanied by the encrypted value file and make Argo CD decrypt it for them.&lt;/p&gt;

&lt;p&gt;This limitation can be problematic in multi-tenant environments. A way to solve it is to make use of &lt;a href="https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data"&gt;AEAD&lt;/a&gt;. AWS KMS offers &lt;a href="https://aws.amazon.com/fr/blogs/security/how-to-protect-the-integrity-of-your-encrypted-data-by-using-aws-key-management-service-and-encryptioncontext/"&gt;encryption context&lt;/a&gt; to this end.&lt;/p&gt;

&lt;p&gt;Sops already supports AWS KMS encryption context but it relies on the one specified in the metadata of the encrypted file. We would need Argo CD to be able to overwrite this encryption context when decrypting secret value files so that it cannot be confused anymore. We'd be happy to work with Sops maintainers to add this possibility 😉&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>security</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
