43.8 go vet, staticcheck, and gosec for Static Security Analysis

Right, let’s talk about making your code less of a liability. You’ve written it, it compiles, and the tests pass. Great. But is it secure? Or did you just accidentally create a delightful little Rube Goldberg machine for an attacker? This is where static analysis tools come in—they’re the nitpicky, hyper-vigilant friend who reads the terms and conditions so you don’t have to. We’re going to look at the big three in the Go ecosystem: go vet, staticcheck, and gosec. They overlap in places, but each brings its own unique flavor of paranoia to the party.

43.7 Secrets Management: Environment Variables and Vault in Go

Right, let’s talk about secrets. You know, the things that, if they get out, turn your expensive cloud bill into someone else’s very expensive free crypto-mining rig. We’ve all seen the GitHub repo with AWS_ACCESS_KEY_ID="AKIAIMNOTTELLINGYOU" committed three years ago and never rotated. Don’t be that person. Managing secrets is arguably more about discipline than technology, but since this is a Go book, we’ll focus on how the technology can save you from yourself.

43.6 JWT Handling: Parsing and Validating Tokens Safely

Alright, let’s talk about JWTs. You’ve probably seen these things everywhere, the bearer tokens that look like a string of gibberish separated by dots. They’re a decent standard, but oh boy, the number of ways you can shoot yourself in the foot with them is truly impressive. I’ve seen more production fires started by bad JWT handling than by a toddler with a flamethrower. So let’s do it right. First, a brutal truth: you are not just “parsing” a JWT. You are validating it. Any library that just decodes that thing and hands you back a JSON object without so much as a “how do you do?” is a trap. Treat it like a suspect package. You must verify its contents, its authenticity, and its expiration before you even think about trusting what’s inside.

43.5 Password Hashing with bcrypt: golang.org/x/crypto/bcrypt

Right, let’s talk about password hashing. This is one of those things where if you get it wrong, you’re the person on the Hacker News post everyone clowns on. We don’t want that. You’re storing a secret the user entrusted to you, not a plaintext monument to your own laziness. So we’re going to do it properly, and in Go, that means reaching for golang.org/x/crypto/bcrypt. It’s the community’s battle-tested choice, and for good reason.

43.4 Hashing and HMAC with the crypto Package

Right, let’s talk about making things unreadable on purpose. Hashing is the workhorse of crypto, and Go’s crypto package gives you a solid, if slightly opinionated, toolbox. We’re not encrypting here—we’re taking some data, scrambling it beyond all recognition, and getting a fixed-size fingerprint. The key idea is that you can’t reverse it. You can’t take the fingerprint and get the original data back. This is perfect for checking if a file has been tampered with or, more commonly, for safely storing passwords (though we’ll get to the massive caveats there in a second).

43.3 TLS Configuration: Cipher Suites, Minimum Version, and Certificates

Look, TLS configuration is one of those things that separates the pros from the amateurs. It’s not enough to just slap tls.Config{} on your http.Server and call it a day. That’s like installing a vault door but leaving the key under the mat. The Go standard library gives you the tools to build a fortress, but it’s up to you to not build it with glaring weaknesses. Let’s get into the weeds.

43.2 crypto/rand: Cryptographically Secure Random Values

Right, let’s talk about randomness. It’s the bedrock of almost everything secure you’ll do. Passwords, encryption keys, session tokens—you name it. If an attacker can guess it, you’ve already lost. So we need numbers that are truly, unpredictably random. Not the fake, predictable randomness you get from math/rand for shuffling your game’s card deck. We need the cryptographic-grade stuff. That’s what crypto/rand is for. Think of math/rand as a clever magician doing a card trick: it looks random to you, but it’s following a secret script (a seed). Anyone who knows the script knows the trick. crypto/rand, on the other hand, is pulling cards from a giant, chaotic deck being constantly shuffled by cosmic noise from your operating system. It’s fundamentally unpredictable.

43.1 Avoiding Common Vulnerabilities: Injection, Path Traversal, SSRF

Let’s be honest: most security vulnerabilities aren’t clever zero-days; they’re us, the developers, leaving the front door wide open with a welcome mat that says “PLEASE INJECT HERE.” The good news? In Go, slamming that door shut is often straightforward, provided you know which doors exist. We’re going to tour the most common ones and arm you with the tools to deadbolt them. SQL Injection: Your Query is Not a String Builder If you take one thing from this section, let it be this: never, ever concatenate user input directly into a SQL query. I don’t care how much you sanitize it in your head. Don’t do it. This isn’t a questionable design choice; it’s a cardinal sin.

18.9 External Secrets Operator: Syncing from Vault, AWS SSM, GCP Secret Manager

Right, so you’ve got ConfigMaps and Secrets down. You’re manually kubectl create secret generic-ing your life away. It works, but it feels a bit… medieval. You’re duplicating secrets into Kubernetes, which is a fantastic way to have them rot in two different places instead of one. And let’s be honest, you’re probably not rotating them as often as you should. Nobody is. The real grown-ups keep their secrets in a proper vault—Hashicorp Vault, AWS Secrets Manager, Google Cloud Secret Manager, Azure Key Vault, you name it. These tools are built for this job: tight access controls, auditing, rotation, the whole nine yards. The question is, how do you bridge that world with the frantic, YAML-obsessed world of Kubernetes?

18.8 Sealed Secrets: Encrypting Secrets for GitOps

Right, so you’ve got your Kubernetes cluster humming along, you’re deploying with GitOps, and you’ve hit the classic snag: you can’t just git commit your database password. Pushing a plain-text Secret to a git repo is like writing your PIN on a postcard. It’s a spectacularly bad idea. This is where Sealed Secrets come in. Think of them as a one-way encryption wrapper for your regular Kubernetes Secrets. You encrypt the secret on your local machine into a SealedSecret custom resource, you commit that to git, and the controller running in your cluster decrypts it, turning it back into a regular Secret. It’s magic, but the kind that runs on public-key cryptography.

18.7 Secret Security: Encryption at Rest and RBAC

Right, let’s talk about keeping your secrets secret. Because by default, Kubernetes doesn’t. I know, I was disappointed too. When you create a Secret, the API server slaps it into etcd, the cluster’s brain, and just… leaves it there. In plain text. It’s the digital equivalent of writing your database password on a post-it note and sticking it to the monitor. We can, and must, do better. This involves two key concepts: encryption at rest (so the post-it note is in a locked drawer) and RBAC (so only certain people have the key to that drawer).

18.6 Secrets as Environment Variables vs Volume Mounts

Alright, let’s get down to brass tacks. You’ve got your shiny new Secret, and now you need to get its precious data into your Pod. You’ve got two main highways for this: injecting them as environment variables or mounting them as files in a volume. The choice isn’t just about preference; it’s a fundamental decision that affects security, observability, and how your application behaves. Let’s break it down. The Quick and Dirty: Environment Variables This is the method everyone reaches for first because it’s dead simple. You define your environment variables in your Pod spec, and Kubernetes magically populates them from your Secret. It feels familiar, especially if you’re coming from a traditional app development background.

18.5 Secret Types: Opaque, TLS, dockerconfigjson, service-account-token

Right, so you’ve got your ConfigMaps for your regular, non-secret configuration. That’s great. But sometimes you have things you’d rather not broadcast to the entire cluster, like API keys, database passwords, or the fact that you still use abc123 as a password. Enter Secrets. They’re like ConfigMaps, but with a thin, almost performative veil of secrecy. Don’t get too excited; by default, they’re just base64-encoded, not encrypted. Anyone with kubectl get secrets -o yaml can decode them in about five seconds. It’s the Kubernetes equivalent of hiding your house key under the doormat. We’ll get to making them actually secret later, but first, let’s talk about the different types, because Kubernetes, in its infinite wisdom, decided there shouldn’t just be one kind.

18.4 Secrets: Base64-Encoded Sensitive Data

Alright, let’s talk about Secrets. You’ve just learned about ConfigMaps, and you’re thinking, “Great! I’ll just shove my database password in one of those!” Please, for the love of all that is holy, do not do that. That’s why we have Secrets. They’re the ConfigMap’s more paranoid, security-conscious cousin who whispers instead of shouting. The core idea is simple: Secrets are a Kubernetes object for storing sensitive data like passwords, API keys, TLS certificates, and OAuth tokens. The key difference from a ConfigMap? They’re not just plain text. Well, sort of. Here’s the first thing you need to know, and it’s a bit of a doozy: the data in a Secret is base64-encoded, not encrypted. Let me say that again for the people in the back. It is not encrypted. Base64 is an encoding scheme, designed to avoid weird binary/control characters, not a encryption cipher designed to keep prying eyes out. Anyone with kubectl get secret my-secret -o yaml can see the encoded data, and any mildly curious intern can run echo 'dGhpcyBpcyBzb21lIHNlY3JldA==' | base64 --decode on their laptop to reveal the plain text “this is some secret”. This is the first and most important pitfall. Secrets are a way to avoid accidentally shoulder-surfing a password, not a way to secure it against a determined attacker. For real encryption at rest, you need to enable and configure the EncryptionConfiguration for the Kubernetes API server, which is a whole other chapter of pain.

18.3 Consuming ConfigMaps as Mounted Files

Right, so you’ve defined your ConfigMap. Good for you. Now, how do you actually get those configuration values into your grumpy little application that expects a good old-fashioned file on the filesystem? You mount it. This is the most robust and common way to consume ConfigMaps, and it works exactly like it sounds: you take the contents of the ConfigMap and make them appear as files in a directory inside your Pod.

18.2 Consuming ConfigMaps as Environment Variables

Right, so you’ve defined your ConfigMap. Good for you. You’ve written a beautiful YAML file full of pristine configuration data. It’s a work of art. But it’s about as useful as a screen door on a submarine until you actually get those values into your application. The most straightforward way to do that is by injecting them as environment variables. It’s the lingua franca of application configuration, and Kubernetes, bless its heart, makes this pretty simple, albeit with a few quirks that will make you question your life choices.

18.1 ConfigMaps: Storing Non-Sensitive Configuration

Right, let’s talk about ConfigMaps. This is where we stop hard-coding configuration details like database URLs or feature flags directly into our application code. Hard-coding is for amateurs and prototypes that accidentally get pushed to production. We’re better than that. Think of a ConfigMap as a simple, string-based key-value dictionary that you can hand to your application running in Kubernetes. It’s not a fancy database; it’s more like a stack of sticky notes you can pass to your Pod. The crucial thing to remember: ConfigMaps are for non-sensitive configuration data. We’re talking database URLs (db-service.prod.svc.cluster.local), config file contents, environment names (“dev”, “staging”), and other mundane details. If you put a password in here, I will find out, and I will be very disappointed in you. For secrets, we have another tool, which we’ll get to shortly.

— joke —

...