<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Common Fate</title>
    <description>The latest articles on Forem by Common Fate (@commonfate).</description>
    <link>https://forem.com/commonfate</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%2F910087%2Fb26fcb3f-8832-412f-a3be-aa668bc46b22.jpg</url>
      <title>Forem: Common Fate</title>
      <link>https://forem.com/commonfate</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/commonfate"/>
    <language>en</language>
    <item>
      <title>Who Cares About Least Privilege?</title>
      <dc:creator>Common Fate</dc:creator>
      <pubDate>Thu, 03 Nov 2022 04:24:04 +0000</pubDate>
      <link>https://forem.com/commonfate/who-cares-about-least-privilege-59i7</link>
      <guid>https://forem.com/commonfate/who-cares-about-least-privilege-59i7</guid>
      <description>&lt;p&gt;&lt;em&gt;Security professionals agree that least privilege is a foundational part of secure design. So then why do so few organizations care about it?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;According to most companies that sell security tools, the world is a dangerous place. Hackers are everywhere. They’re crawling around in your EC2 instances, in your employee laptops, in your Gmail inboxes. They’re hiding behind your watercoolers and under your meetings tables and in your breakout booths. Half of your employees are hackers. Hell, your CISO is probably a hacker too — you should fire her and buy more tools.&lt;/p&gt;

&lt;p&gt;Billions of dollars are spent around this issue. State-of-the-art WAFs, AI-assisted endpoint protections, eye-wateringly priced security logging solutions that take entire teams just to set up and manage — and yet almost zero care seems to be directed towards one of the simplest and most cost-effective defenses: least privilege.&lt;/p&gt;

&lt;p&gt;I’d like to state upfront that this won’t be a persuasive article. I have no grand idea to sell you, no concrete answer to this problem that we’re facing. I’m the Developer Advocate for a company that makes least privilege workflow software, which means the bulk of my job is arguing in comment sections about why least privilege even matters. This article, if anything, is a cry for help. &lt;/p&gt;

&lt;p&gt;All I can really do is share the things that we’ve discovered while working in this space, and hope that you’ll share your own insights too. And maybe then we can start thinking about how to solve this thing.&lt;/p&gt;

&lt;p&gt;So then why &lt;em&gt;do&lt;/em&gt; so few organizations bother to properly scope employee privilege?&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 1: They think it’s about trust
&lt;/h2&gt;

&lt;p&gt;Imagine, for the sake of argument, that there is a lava pit in the middle of your office. Most of your co-workers are so used to the lava pit that they don’t even notice it’s there, while a few others have actually created entire geothermic systems that require the lava pit to function. Occasionally someone will fall into the lava pit, suffer grievous injuries, and then be sent into lava pit awareness training.&lt;/p&gt;

&lt;p&gt;One day you meet with one of the infrastructure teams to discuss how maybe instead of having lava pit awareness training, we should just get rid of the lava pit. The outrage is immediate: w*e’ve always had the lava pit! Too many systems rely on it! Getting rid of the lava pit would mean redesigning the entire floor!*&lt;/p&gt;

&lt;p&gt;Out of all these objections, one of them seems to stand out the most: &lt;em&gt;but we trust our people to not fall into it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Of course, it’s a ridiculous argument. No one &lt;em&gt;chooses&lt;/em&gt; to fall into the lava pit, just as no one chooses to get phished. But it’s one of the more difficult points to argue against. As an engineer, it’s hard to not feel patronized when your lava pit is taken away. Sure, maybe &lt;em&gt;other&lt;/em&gt; people in the company are incompetent goons — but you’d &lt;em&gt;never&lt;/em&gt; fall into the pit. You’re too smart for that.&lt;/p&gt;

&lt;p&gt;Accepting least privilege means admitting to yourself that no matter how smart and good at computers you might be, sometimes shit happens — and you are not immune to it. This is a difficult realization for anyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 2: Move fast, break things
&lt;/h2&gt;

&lt;p&gt;No one ever got seed funding for not getting hacked.&lt;/p&gt;

&lt;p&gt;Many growth-focused companies tend to sacrifice security in favor of pushing out their product quicker. The narrative is usually “we’ll make it secure once we’ve actually built it”. The issue is that security debt works just the same way that tech debt does — all these oversights and shortcuts accumulate to eventually make any sort of positive change almost impossible. Giving people sweeping amounts of access results in them creating workflows that rely on that over-privileged access, and as more time passes those processes become more ingrained. Removing people’s access is a hell of a lot harder than just not having given them that access in the first place.&lt;/p&gt;

&lt;p&gt;This is a problem that mostly applies to startups and rapidly scaling companies (large business have no problem putting red tape around every single access request and process — most of their executives probably have KPIs based around doing so).&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 3: What’s your job again?
&lt;/h2&gt;

&lt;p&gt;Implementing least privilege requires actually knowing what all your coworkers do.&lt;/p&gt;

&lt;p&gt;That’s an easy enough thing if you work in an organization where everyone has clearly defined roles and never has to step outside those roles to help someone else or meet a changing requirement. But you don’t work in that organization, because it doesn’t exist and we live in Hell.&lt;/p&gt;

&lt;p&gt;Any good least privilege architecture must assume that people will sometimes need to do things outside their roles. Overly broad permissions are dangerous, while extremely scoped permissions can limit cross-team functionality and kill creativity. It’s not an easy balance to strike, and ultimately this requires a lot of communication between the security team and everyone else — which, let’s face it, is a whole other article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 4: It’s all business, baby
&lt;/h2&gt;

&lt;p&gt;This is a section that I hesitate to add, and if it’s included in the final article then it’s only due to the good grace and patience of the people who pay me. But there’s a problem in the business of security: and it’s the &lt;em&gt;business&lt;/em&gt; part.&lt;/p&gt;

&lt;p&gt;In an earlier company I worked at, I once met with the CFO to request budget approval for a new security hire. I will never forgot what he told me: “What’s the ROI on security?”&lt;/p&gt;

&lt;p&gt;I could have replied “what’s the ROI on looking both ways when you cross the street?”, but I didn’t. That was a line that came to me months later, when I was still the only security hire and still bitter about the meeting. &lt;/p&gt;

&lt;p&gt;At the time, I thought the CFO was naive and had no business sense. But he was right: there &lt;em&gt;is&lt;/em&gt; no ROI on security, only on security optics.&lt;/p&gt;

&lt;p&gt;Good security can save you lots of money years down the line, but businesses don’t work on a timescale of years. They work in quarters. Investors want to see what you’ve achieved in the past three months, and telling them that you’ve become unhackable by buying a machine-learning anti-virus is a hell of a lot more impressive than telling them you’ve taken away Dylan’s root access to all the customer data. The first one lets you show off slides full of cool graphs and mean-looking falcon logos, and the second one gets people asking: why the **** did Dylan have root access to all the customer data?&lt;/p&gt;

&lt;p&gt;The problem, of course, is that buying the cool anti-virus is often a lot cheaper and less problematic than taking away Dylan’s access. So, here we are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 5: Implementation
&lt;/h2&gt;

&lt;p&gt;In security, the most interesting (and difficult) problems tend to involve people, not technology. Unfortunately, most least privilege solutions are blatantly anti-people.&lt;/p&gt;

&lt;p&gt;No one wants to fill out a Google document and then figure out who to email it to just to get access to a basic part of their job. No one wants to look at tickets on a kanban board just to figure out who they need to give access to. And no one wants to go through all the IAM roles to discover that the penetration tester from two years ago still has AWS access just because no one remembered to revoke it.&lt;/p&gt;

&lt;p&gt;So that’s why we’ve created &lt;a href="https://commonfate.io/"&gt;Common Fate&lt;/a&gt;, an open-source developer workflow tool that helps you request and approve specific, timeboxed permissions with just a few clicks.&lt;/p&gt;

&lt;p&gt;What? Did you think we were going to write this whole thing without advertising our product even once? Nah.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what do we do about all this?
&lt;/h2&gt;

&lt;p&gt;Honestly? I don’t know. On a more granular level, each of the above problems have their own solution. Talk to your coworkers about how you &lt;em&gt;trust&lt;/em&gt; them, you just don’t want to take unnecessary risks. Make sure to do good security design &lt;em&gt;before&lt;/em&gt; you need to pay KPMG $25 million to fix it for you. Talk to your coworkers about what their jobs actually are. Check out our &lt;a href="https://github.com/common-fate/granted-approvals"&gt;Github repo&lt;/a&gt;, etc. etc.&lt;/p&gt;

&lt;p&gt;On a more holistic level, many of these problems are underpinned by a common factor: an organization’s inability or unwillingness to properly map out their structure and commit to designing better permission workflows. The inability part can be solved with a bit of time and strategy — the unwillingness part, not so much.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to log in to multiple AWS accounts — the easy way</title>
      <dc:creator>Common Fate</dc:creator>
      <pubDate>Thu, 15 Sep 2022 03:49:52 +0000</pubDate>
      <link>https://forem.com/commonfate/how-to-log-in-to-multiple-aws-accounts-the-easy-way-2oif</link>
      <guid>https://forem.com/commonfate/how-to-log-in-to-multiple-aws-accounts-the-easy-way-2oif</guid>
      <description>&lt;p&gt;Here’s how it goes: you’ve got a Chrome window open for your Production AWS account, and a Firefox window open for the Staging account. There’s a Safari window open for the Dev account, and an incognito Firefox window open for the Sandbox account. Buried somewhere in your dock’s 200 open windows is a Chrome incognito account for the &lt;em&gt;other&lt;/em&gt; Sandbox account (because your org really, really cares about account-level separation), but by the time you manage to find it your session will probably be expired and you’ll have to go through the whole kerfuffle of signing in again.&lt;/p&gt;

&lt;p&gt;I can’t explain to you &lt;em&gt;why&lt;/em&gt; AWS decided to make their user experience like this — who am I to question the will of God? But I &lt;em&gt;can&lt;/em&gt; offer you a solution: a simple, open-source CLI tool that’ll take you 10 minutes to install and will save you from AWS browser window hell forever.&lt;/p&gt;

&lt;p&gt;Here’s how &lt;a href="https://github.com/common-fate/granted" rel="noopener noreferrer"&gt;Granted&lt;/a&gt; CLI works. Run the &lt;code&gt;assume&lt;/code&gt; command in your terminal and pick which AWS profile to sign in to (in my case, &lt;code&gt;testing&lt;/code&gt;):&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%2Fl7je8n88jt52w9g3l9jh.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%2Fl7je8n88jt52w9g3l9jh.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And in a few seconds, it’ll open a new tab in your browser of choice (in my case, Firefox):&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%2Fomrkebi9fz39tldwjbha.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%2Fomrkebi9fz39tldwjbha.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s say you want to work in a second AWS account simultaneously. All you have to do is run the same command, this time selecting a different profile (in my case, &lt;code&gt;release&lt;/code&gt;)&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%2Fo57h5rtmfesdta8x6502.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%2Fo57h5rtmfesdta8x6502.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then you’ll have a second tab open in a new container:&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%2F3o0q5k3pybgchgjb2e2z.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%2F3o0q5k3pybgchgjb2e2z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can switch between these tabs to work in these accounts simultaneously with no extra hassle. Opening another profile is as simple as just running another command.&lt;/p&gt;

&lt;p&gt;If you think this is as cool as we do, you can read our &lt;a href="https://docs.commonfate.io/granted/getting-started/" rel="noopener noreferrer"&gt;Getting Started guide&lt;/a&gt; to get set up with Granted — but to save you a click I’ll run through the MacOS instructions here (the Getting Started guide contains specific instructions for Linux and Windows, too).&lt;/p&gt;

&lt;p&gt;First, you’ll need to set up at least once role in your &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html" rel="noopener noreferrer"&gt;AWS config file&lt;/a&gt;. On MacOS, this is stored in &lt;code&gt;~/.aws/config&lt;/code&gt;. A config file for AWS SSO should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/.aws/config
# Change the values below to match your AWS SSO configuration
# Granted uses the profile name: in this case 'my-profile' to choose the role.

[profile my-profile]
sso_start_url=https://mycompany.awsapps.com/start
sso_region=us-east-1
sso_account_id=123456789012
sso_role_name=DeveloperRole
region=us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(you can use AWS IAM too - but we recommend SSO.)&lt;/p&gt;

&lt;p&gt;Once you’ve got that set up, you can use Homebrew to install Granted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew tap common-fate/granted
brew install granted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And verify your installation:&lt;br&gt;
&lt;/p&gt;

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

Granted v0.2.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(mine is v0.2.9 at the time of writing — yours will probably be a later version)&lt;/p&gt;

&lt;p&gt;Once you’ve verified that Granted is installed correctly, you can run the &lt;code&gt;assume&lt;/code&gt; command to get started with the setup wizard where you’ll be prompted to choose your browser.&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%2Fxa2wb4rued8g4hbjmrc1.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%2Fxa2wb4rued8g4hbjmrc1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After setup, you can run &lt;code&gt;assume&lt;/code&gt; again to choose roles:&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%2Fc35nqud5ysppedohx4rn.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%2Fc35nqud5ysppedohx4rn.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also pass the role name directly and use the -c flag to open the console, e.g. &lt;code&gt;assume -c testing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And that’s it! If you’ve got any questions, you can check out &lt;a href="https://docs.commonfate.io/granted/getting-started" rel="noopener noreferrer"&gt;the docs&lt;/a&gt; or join our &lt;a href="https://join.slack.com/t/commonfatecommunity/shared_invite/zt-q4m96ypu-_gYlRWD3k5rIsaSsqP7QMg" rel="noopener noreferrer"&gt;Slack&lt;/a&gt; where we’ll be happy to chat with you directly. And if you like Granted, you can follow our &lt;a href="https://twitter.com/CommonFateTech" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; for updates and terrible jokes.&lt;/p&gt;

&lt;p&gt;Happy ClickOpsing!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>security</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Prevent Logging Secrets in Go by Using Custom Types</title>
      <dc:creator>Common Fate</dc:creator>
      <pubDate>Wed, 17 Aug 2022 02:31:00 +0000</pubDate>
      <link>https://forem.com/commonfate/prevent-logging-secrets-in-go-by-using-custom-types-888</link>
      <guid>https://forem.com/commonfate/prevent-logging-secrets-in-go-by-using-custom-types-888</guid>
      <description>&lt;p&gt;In our codebase for &lt;a href="https://docs.commonfate.io/granted-approvals/introduction/"&gt;Granted Approvals&lt;/a&gt;, we’ve got a structure that looks like this:&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;type&lt;/span&gt; &lt;span class="n"&gt;Provider&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;OrgUrl&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;APIToken&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we’ve got a value named &lt;code&gt;apiToken&lt;/code&gt;. It’s a secret, and we’d rather it doesn’t get leaked somewhere. Your secret value could also be an API token, or maybe it’s a password or a user address or anything else that you don’t want to get a Privacy Act lawsuit for.&lt;/p&gt;

&lt;p&gt;The trouble with storing your secrets in strings like this is that it’s very easy to accidentally log them. It only takes one &lt;code&gt;fmt&lt;/code&gt; or &lt;code&gt;zap&lt;/code&gt; line for your secret value to be printed in plaintext and then possibly even sent to your external logging solutions. Using unexported fields can help, but Zap will still include them anyway.&lt;/p&gt;

&lt;p&gt;If you’re reading this, then you probably already know why having sensitive data in your logs is dangerous. If you don’t, you can check out &lt;a href="https://www.theregister.com/2022/05/27/github_publishes_a_post_mortem/"&gt;this&lt;/a&gt;. Or &lt;a href="https://www.bleepingcomputer.com/news/security/twitter-admits-recording-plaintext-passwords-in-internal-logs-just-like-github/"&gt;this&lt;/a&gt;. Or &lt;a href="https://techcrunch.com/2022/07/26/justalk-spilled-millions-of-user-messages-and-locations-for-months/"&gt;this&lt;/a&gt;. Or…. you get the point.&lt;/p&gt;

&lt;p&gt;And if you’re rolling your eyes and saying &lt;em&gt;I’d never log sensitive data&lt;/em&gt;, I’d ask: are you sure? You’re never going to accidentally type the wrong variable name in your print function? You’re never going to have a new dev join your team? Nobody on your team is ever going to be one night away from a deadline debugging why the hell the password reset function isn’t working and just go &lt;em&gt;screw it, I don’t get paid enough to care about security anyway&lt;/em&gt;? I’m not so sure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our solution&lt;/strong&gt;: custom types.&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;type&lt;/span&gt; &lt;span class="n"&gt;Provider&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;OrgUrl&lt;/span&gt; &lt;span class="n"&gt;StringValue&lt;/span&gt;
    &lt;span class="n"&gt;APIToken&lt;/span&gt; &lt;span class="n"&gt;SecretStringValue&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now instead of &lt;code&gt;orgUrl&lt;/code&gt; and &lt;code&gt;apiToken&lt;/code&gt; being type &lt;em&gt;string&lt;/em&gt;, they’re &lt;em&gt;StringValue&lt;/em&gt; and &lt;em&gt;SecretStringValue.&lt;/em&gt; Both of these custom types provide a small abstraction over a standard string type:&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;type&lt;/span&gt; &lt;span class="n"&gt;StringValue&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SecretStringValue&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The part that’s important to us though is how they both implement the &lt;a href="https://go.dev/tour/methods/17"&gt;Stringer&lt;/a&gt; and MarshalJSON interfaces:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&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;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;
&lt;span class="p"&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;s&lt;/span&gt; &lt;span class="n"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;MarshalJSON&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&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;s&lt;/span&gt; &lt;span class="n"&gt;SecretStringValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"*****"&lt;/span&gt;
&lt;span class="p"&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;s&lt;/span&gt; &lt;span class="n"&gt;SecretStringValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;MarshalJSON&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&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;The String() implementation for &lt;code&gt;SecretStringValue&lt;/code&gt; will only return the redacted string “*****”, and same goes for the JSON. This makes it a whole lot more difficult to accidentally log the secret by just plugging it into fmt or zap.&lt;/p&gt;

&lt;p&gt;So now, if you’re got something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;oops&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;OrgURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s"&gt;"commonfate.io"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;APIToken&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s"&gt;"secret"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;oops&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;oops&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;OrgURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"commonfate.io"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;APIToken&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"secret"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oops&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All you should hopefully get in return is &lt;code&gt;*****&lt;/code&gt; or &lt;code&gt;{"OrgUrl":"commonfate.io","APIToken":"*****"}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Is it totally foolproof? No. You can still log the secret if someone decides to deliberately print the Value, but at least now the team has clearer context on whether or not something is intended to be a Secret or just a regular Value. It makes it just that little bit harder to make a mistake — and in security, that’s all we can really ask.&lt;/p&gt;

&lt;p&gt;If you want to check out the code for yourself, here’s a &lt;a href="https://go.dev/play/p/Ha3ade158vi"&gt;Go Playground link&lt;/a&gt;. And if you’re interested in seeing how we’ve implemented this in our own project, you can check out our &lt;a href="https://github.com/common-fate/granted-approvals/tree/main/pkg/gconfig"&gt;gconfig package&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>security</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
