<?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: Benjamin DeCoste</title>
    <description>The latest articles on DEV Community by Benjamin DeCoste (@bendecoste).</description>
    <link>https://dev.to/bendecoste</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%2F949472%2Fa8a046bb-513e-45fa-a1c9-cfe0cbeaf015.png</url>
      <title>DEV Community: Benjamin DeCoste</title>
      <link>https://dev.to/bendecoste</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bendecoste"/>
    <language>en</language>
    <item>
      <title>How do you share config secrets for development &amp; production?</title>
      <dc:creator>Benjamin DeCoste</dc:creator>
      <pubDate>Fri, 11 Nov 2022 00:53:41 +0000</pubDate>
      <link>https://dev.to/bendecoste/how-do-you-share-config-secrets-for-development-production-1c80</link>
      <guid>https://dev.to/bendecoste/how-do-you-share-config-secrets-for-development-production-1c80</guid>
      <description>&lt;p&gt;If you develop an application that requires a bunch of config (e.g., tokens for third party dependencies like auth0, launch darkly, open telemetry, etc), database password, aws access keys, or any other type of sensitive information: &lt;/p&gt;

&lt;p&gt;How do you share all of that config across your team? If someone new wants to contribute, how do you get them all of the secrets so they can run your app? What tools or workflow do you use to achieve this? What are your best practices so you don't have secrets everywhere?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>discuss</category>
      <category>node</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>What music have you been coding to this week?</title>
      <dc:creator>Benjamin DeCoste</dc:creator>
      <pubDate>Tue, 08 Nov 2022 17:45:44 +0000</pubDate>
      <link>https://dev.to/bendecoste/what-music-have-you-been-coding-to-this-week-3fgb</link>
      <guid>https://dev.to/bendecoste/what-music-have-you-been-coding-to-this-week-3fgb</guid>
      <description>&lt;p&gt;Let's hear your favourite tunes to crank out some code? This week I have been listening to &lt;/p&gt;

&lt;h3&gt;
  
  
  Keys N Krates - Original Classic
&lt;/h3&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%2Fnv6sh0cv2o5kvm7eh3f3.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%2Fnv6sh0cv2o5kvm7eh3f3.png" alt="Original Classic Album Art"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://open.spotify.com/album/6Wy2a9JTkOIY6BESWAXM8K?si=blYrqdjQR8yT86FAzkGhSQ" rel="noopener noreferrer"&gt;Spotify Link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Mastodon - Emperor of Sand
&lt;/h3&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%2Fc8fydqjejcv9uit0tmyw.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%2Fc8fydqjejcv9uit0tmyw.png" alt="Emperor of Sand Album Art"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://open.spotify.com/album/1VzmKgEG38fsUBZVe15wuF?si=GndXZMCTRW-T_4-zZY6LFw" rel="noopener noreferrer"&gt;Spotify Link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Gilla Band - Most Normal
&lt;/h3&gt;

&lt;p&gt;(not sure how I feel about this one yet, lol)&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%2F6vfku5i48ae9drqrxwc6.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%2F6vfku5i48ae9drqrxwc6.png" alt="Most Normal Album Art"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://open.spotify.com/album/3UcqK7oJ4UiScKZD8IQsk0?si=FYu1ooIGS6SS_eb4Cn_U-A" rel="noopener noreferrer"&gt;Spotify Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What about you??&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>music</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Testing time with Golang</title>
      <dc:creator>Benjamin DeCoste</dc:creator>
      <pubDate>Thu, 03 Nov 2022 16:39:08 +0000</pubDate>
      <link>https://dev.to/bendecoste/testing-time-with-golang-31o2</link>
      <guid>https://dev.to/bendecoste/testing-time-with-golang-31o2</guid>
      <description>&lt;p&gt;We can all agree that TDD is the bees knees, right? Something that can trip newbies up with golang is writing tests against a function that has a timeout.&lt;/p&gt;

&lt;p&gt;Often when waiting for a result over a channel, it can make sense to add a timeout so we don't wait forever. Consider the following code&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;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// simulate an operation that takes too long&lt;/span&gt;
  &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// We need to test this&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;MyCode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;

  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="c"&gt;// hurray!&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// oh no!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Writing a unit test that exercises our timeout logic and doesn't take 5 seconds to run can seem difficult at first, but it is actually quite simple. We can use something called remote function overriding to declare a variable that we can override in our test.&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;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;After&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And our switch statement changes like so&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;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="c"&gt;// hurray!&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// oh no!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in our tests, we can easily change the definition of after, to make it happen instantly&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;TestSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&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;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;// your test code here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>go</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Customizing nushell prompt</title>
      <dc:creator>Benjamin DeCoste</dc:creator>
      <pubDate>Wed, 02 Nov 2022 13:28:50 +0000</pubDate>
      <link>https://dev.to/bendecoste/customizing-nushell-prompt-3loh</link>
      <guid>https://dev.to/bendecoste/customizing-nushell-prompt-3loh</guid>
      <description>&lt;p&gt;By default, &lt;a href="https://www.nushell.sh/" rel="noopener noreferrer"&gt;nushell&lt;/a&gt;'s prompt shows your working directory on the left, and the date &amp;amp; time on the right. It looks like this:&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%2Ficsj0787zf7syday98nx.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%2Ficsj0787zf7syday98nx.png" alt="nushell default prompt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As someone who was trying nu after using zsh for a long time, I wanted to replicate my old prompt, which showed me my working directory, current kubernetes cluster, and current k8s namespace:&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%2F0tbii5o21cb4r2m34f2m.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%2F0tbii5o21cb4r2m34f2m.png" alt="zsh prompt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nushell configures your prompt in its environment script (&lt;code&gt;$nu.env-path&lt;/code&gt;). If you open this file you will see two functions at the very top, &lt;code&gt;create_left_prompt&lt;/code&gt; and &lt;code&gt;create_right_prompt&lt;/code&gt;. you can see the default implementation for the date &lt;/p&gt;

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

def create_right_prompt [] {
    let time_segment = ([
        (date now | date format '%m/%d/%Y %r')
    ] | str join)

    $time_segment
}


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

&lt;/div&gt;

&lt;p&gt;I created a new function for my k8s prompt. I liked having the time on the prompt, so I left that (thought I didn't feel like I needed the date).&lt;/p&gt;

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

def kube_prompt [] {
    let k_prompt =  ([(kubectl ctx -c), (kubectl ns -c)] | str trim | str join '/')
    let d_prompt = ([(date now | date format '%r')] | str join)
    $"\(($k_prompt)\) ($d_prompt)"
}


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

&lt;/div&gt;

&lt;p&gt;Just below, we can edit the &lt;code&gt;let-env PROMPT_COMMAND_RIGHT&lt;/code&gt; to look like:&lt;/p&gt;

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

let-env PROMPT_COMMAND_RIGHT = { kube_prompt }


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

&lt;/div&gt;

&lt;p&gt;Restarting your shell and you will see the new prompt&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%2F63s6q2ff2udw853ekb77.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%2F63s6q2ff2udw853ekb77.png" alt="nushell with k8s prompt"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nushell</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
    <item>
      <title>30 Days of Developer Advocacy</title>
      <dc:creator>Benjamin DeCoste</dc:creator>
      <pubDate>Tue, 01 Nov 2022 17:48:31 +0000</pubDate>
      <link>https://dev.to/bendecoste/30-days-of-developer-advocacy-14al</link>
      <guid>https://dev.to/bendecoste/30-days-of-developer-advocacy-14al</guid>
      <description>&lt;p&gt;For the next 30 days I am going to spend a large portion of my time on developer advocacy. I have minimal experience in this area but it is something that I want to get better at. I am writing this document at the start to commit myself to giving it my all for a month, then figuring out a more sustainable approach afterwards.&lt;/p&gt;

&lt;p&gt;My goals for this exercise are to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build a developer audience&lt;/li&gt;
&lt;li&gt;Learn new things&lt;/li&gt;
&lt;li&gt;Get out of my comfort zone&lt;/li&gt;
&lt;li&gt;Advocate for enclaves &amp;amp; confidential computing&lt;/li&gt;
&lt;li&gt;Advocate for my company: capeprivacy.com &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I don't know much about community building or this space, so I will be learning as I go. I expect to not be great at it and produce stuff with lots of rough edges.&lt;/p&gt;

&lt;p&gt;What I do have going for me is that I am a good software engineer, and I like to learn and try new things.&lt;/p&gt;

&lt;p&gt;What I think will work against me is lack of experience putting myself out there and the social anxiety that comes along with doing that.&lt;/p&gt;

&lt;p&gt;Since I know nothing about this, my naive initial approach is going to be trying to stick to a content schedule. I will try to make a few different types of content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Videos (1 per week)&lt;/li&gt;
&lt;li&gt;Tweets (&amp;gt;= 1 one per day)&lt;/li&gt;
&lt;li&gt;Blogs (2x per week)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other things I will try to do but not committing to an amount include&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comments on HN &lt;/li&gt;
&lt;li&gt;Comments / posting on random subreddits

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/golang"&gt;/r/golang&lt;/a&gt;, &lt;a href="https://www.reddit.com/r/kubernetes"&gt;/r/kubernetes&lt;/a&gt;, etc&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;I'll change this up as I learn more.&lt;/p&gt;

&lt;p&gt;How will I know I was successful? I am not sure. I think there will be a lot to learn just in doing the exercise, even if I gain 0 followers (although I hope I get at least one). I can also look at metrics for social posts (e.g., am I getting more impressions?), follower counts on twitter &amp;amp; linkedIn, etc.&lt;/p&gt;

&lt;p&gt;Looking forward to the next 30 days! If you are reading this and have ideas for me or things to try out, or would like to play along, let me know! I would love to learn from anyone that has done this before :).&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>motivation</category>
    </item>
    <item>
      <title>Running an HTTP Server with AWS Nitro Enclaves</title>
      <dc:creator>Benjamin DeCoste</dc:creator>
      <pubDate>Wed, 26 Oct 2022 18:52:14 +0000</pubDate>
      <link>https://dev.to/bendecoste/running-an-http-server-with-aws-nitro-enclaves-elo</link>
      <guid>https://dev.to/bendecoste/running-an-http-server-with-aws-nitro-enclaves-elo</guid>
      <description>&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave.html" rel="noopener noreferrer"&gt;AWS Nitro enclaves&lt;/a&gt; are isolated execution environments. They allow us to compute on sensitive and/or private data.&lt;/p&gt;

&lt;p&gt;In this blog we will look at how you can run an HTTP server in Go on a Nitro Enclave. Final code is available on &lt;a href="https://github.com/bendecoste/Enclave-Server" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Server
&lt;/h2&gt;

&lt;p&gt;We will start with an HTTP server running outside of an enclave.&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"io"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;":8888"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, regular server!&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"listening on"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We will run and test our enclave in Docker. That will be the easiest way to get our code running in the enclave later. We can use the following Dockerfile.&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; golang:1.18-alpine&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.mod ./&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.sum ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go mod download
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; *.go ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; /enclave-server

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

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "/enclave-server" ]&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Set up an Enclave Capable EC2 Instance
&lt;/h2&gt;

&lt;p&gt;Next up, let’s run our server inside of an enclave. To do this, we need a Nitro Enclave capable EC2 instance. You can follow the &lt;a href="https://docs.aws.amazon.com/enclaves/latest/user/getting-started.html" rel="noopener noreferrer"&gt;instructions from AWS&lt;/a&gt; to get an image, and &lt;a href="https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave-cli-install.html" rel="noopener noreferrer"&gt;installing the Nitro Enclaves CLI&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Building our Enclave Image File (EIF)
&lt;/h2&gt;

&lt;p&gt;The Nitro CLI can turn Dockerfiles into Enclave Image Files. We will then pass the Enclave Image file to the run-enclave command.&lt;/p&gt;

&lt;p&gt;We will first build our docker image&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker build -t hello-nitro .


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

&lt;/div&gt;

&lt;p&gt;Then create our EIF&lt;/p&gt;

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

nitro-cli build-enclave --docker-uri hello-nitro --output-file hello-nitro.eif


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

&lt;/div&gt;

&lt;p&gt;You should see an output that looks something like&lt;/p&gt;

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

Start building the Enclave Image...
Using the locally available Docker image...
Enclave Image successfully created.
{
  "Measurements": {
    "HashAlgorithm": "Sha384 { ... }",
    "PCR0": "bf9b5743dc00c63972e7cc06da44bda4a18e40a80173c5a5203651853509f37c1e4c6794fa028e29e60081b007175b09",
    "PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
    "PCR2": "ad8dfc09b5415f3a1d5586d7de878e87785669371a590aa4e392e14f2fc70aeba5bd53d04ef0043447e9ad04cd0c4893"
  }
}


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

&lt;/div&gt;

&lt;p&gt;Then we run our EIF&lt;/p&gt;

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

nitro-cli run-enclave --eif-path hello-nitro.eif --memory 2000 --cpu-count 2 --enclave-cid 16 --debug-mode


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

&lt;/div&gt;

&lt;p&gt;Note that we will run in debug mode for now. Debug mode lets us see console output. The enclave is not secure when we use debug mode, but it is very helpful with prototyping. We also ran the enclave with context identifier (CID) 16. This is not necessary but ensures that you can copy-paste some commands that refer to this CID below.&lt;/p&gt;

&lt;p&gt;We can see that our enclave is running with the &lt;code&gt;describe-enclaves&lt;/code&gt; command&lt;/p&gt;

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

$ nitro-cli describe-enclaves
[
  {
    "EnclaveName": "hello-nitro",
    "EnclaveID": "i-02d0ff88a0e47b51d-enc183d6a008ea4b9a",
    "ProcessID": 26734,
    "EnclaveCID": 16,
    "NumberOfCPUs": 2,
    "CPUIDs": [
      1,
      17
    ],
    "MemoryMiB": 2048,
    "State": "RUNNING",
    "Flags": "DEBUG_MODE",
    "Measurements": {
      "HashAlgorithm": "Sha384 { ... }",
      "PCR0": "bf9b5743dc00c63972e7cc06da44bda4a18e40a80173c5a5203651853509f37c1e4c6794fa028e29e60081b007175b09",
      "PCR1": "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
      "PCR2": "ad8dfc09b5415f3a1d5586d7de878e87785669371a590aa4e392e14f2fc70aeba5bd53d04ef0043447e9ad04cd0c4893"
    }
  }
]


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

&lt;/div&gt;

&lt;p&gt;Note that the PCR 0, 1, and 2 output is the same from when we built the enclave. These values can be used during &lt;a href="https://capeprivacy.com/blog/attestation-with-cape-privacy" rel="noopener noreferrer"&gt;Attestation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, since we are using debug mode, we can see the console output of our enclave with the console command.&lt;/p&gt;

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

$ nitro-cli console --enclave-name hello-enclave
&amp;lt;enclave setup output redacted&amp;gt;
2022/10/14 13:12:41 listening on :8888


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

&lt;/div&gt;

&lt;p&gt;Seems easy enough, right? However, we have no way to request this endpoint. The only way to connect to a running enclave is through &lt;a href="https://man7.org/linux/man-pages/man7/vsock.7.html" rel="noopener noreferrer"&gt;vsock&lt;/a&gt;. Great! How do we do that?&lt;/p&gt;

&lt;p&gt;To connect be able to connect to our HTTP server, we will make two modifications to our setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our go server needs to listen on a vsock address. By default, http.ListenAndServe will listen on the provided TCP network address, which will be non-functional inside the enclave.&lt;/li&gt;
&lt;li&gt;We would like to be able to make requests to our server with standard tools. So far we have used cURL, but we would like any http client to work without modification. We will use [socat[(&lt;a href="https://linux.die.net/man/1/socat" rel="noopener noreferrer"&gt;https://linux.die.net/man/1/socat&lt;/a&gt;) to maintain this compatibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Listen on vsock
&lt;/h2&gt;

&lt;p&gt;We can use &lt;a href="https://github.com/mdlayher/vsock" rel="noopener noreferrer"&gt;https://github.com/mdlayher/vsock&lt;/a&gt; to get a vsock implementation of net.Listener that we can pass to http.Serve.&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"io"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/mdlayher/vsock"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, Enclave!&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;listener&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;vsock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8888&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Proxy HTTP to vsock
&lt;/h2&gt;

&lt;p&gt;Using socat, we can allow clients to continue to make HTTP requests, and socat will proxy them to vsock for us. An image is available on &lt;a href="https://hub.docker.com/r/alpine/socat" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker run -d -p 8888:8888 --name socat alpine/socat tcp-listen:8888,fork,reuseaddr vsock-connect:16:8888


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

&lt;/div&gt;

&lt;p&gt;If you are unfamiliar with socat, what this command is saying is to listen for tcp connections on port 8888, and forward them to vsock. The fork option makes this happen in a new child process, while the parent goes back to waiting for new connections (useful if you wish to handle concurrent requests). reuseaddr allows other sockets to bind to an address if parts of it are already in use by socat.&lt;/p&gt;

&lt;p&gt;The second argument describes how to connect to vsock. 8888 matches up with the port we listened to in our http server. The 16 is the context identifier which identifies the enclave (we explicitly set this above).&lt;/p&gt;

&lt;p&gt;You can find the address of your socat server by inspecting the bridge docker network. Mine was at 172.17.0.2.&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%2Fkykfmk7cn4z3f64y95h5.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%2Fkykfmk7cn4z3f64y95h5.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it! we can now request to our enclave&lt;/p&gt;


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

&lt;p&gt;$ curl 172.17.0.2:9090&lt;br&gt;
Hello, Enclave!&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion &amp;amp; Next Steps&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;We now have an HTTP server running inside of an enclave. We can now put confidential workloads behind these HTTP endpoints.&lt;/p&gt;

&lt;p&gt;In future blogs, we will explore running our server on HTTPS, so callers have a secure connection directly into the enclave. We will also look at running our enclave capable EC2 instances on Kubernetes for a more production ready environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shameless plug
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! I work full time on enclaves at &lt;a href="https://capeprivacy.com/" rel="noopener noreferrer"&gt;https://capeprivacy.com/&lt;/a&gt;. We are trying to make enclaves easy to access and use for all developers and data scientists. Cape Privacy is currently in open beta. I would love to hear any feedback, comments, or questions you have on the product. Check it out! &lt;a href="https://docs.capeprivacy.com/getting-started/" rel="noopener noreferrer"&gt;https://docs.capeprivacy.com/getting-started/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>enclave</category>
      <category>aws</category>
      <category>security</category>
      <category>go</category>
    </item>
  </channel>
</rss>
