<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://devops.nz/feed.xml" rel="self" type="application/atom+xml"/><link href="https://devops.nz/" rel="alternate" type="text/html"/><updated>2025-10-05T17:26:07+13:00</updated><id>https://devops.nz/feed.xml</id><title type="html">DevOps New Zealand</title><subtitle>Kiwi Collaboration, Culture and Technolology</subtitle><entry><title type="html">Statica - how I run some of my favourite AppSec tools</title><link href="https://devops.nz/2025/10/03/statica-a-tool-to-run-some-of-my-favourite-appsec-tools.html" rel="alternate" type="text/html" title="Statica - how I run some of my favourite AppSec tools"/><published>2025-10-03T16:20:45+13:00</published><updated>2025-10-03T16:20:45+13:00</updated><id>https://devops.nz/2025/10/03/statica---a-tool-to-run-some-of-my-favourite-appsec-tools</id><content type="html" xml:base="https://devops.nz/2025/10/03/statica-a-tool-to-run-some-of-my-favourite-appsec-tools.html"><![CDATA[<p>Static analysis is a powerful technique for catching security issues. But tools that depend on compilation aren’t always easy, especially if you don’t have the right dependencies or you’re stuck on Apple Silicon with legacy code.</p><p>So I built <a href="https://github.com/simpsonjulian/statica">Statica</a>: a wrapper for the AppSec tools I trust.</p><h2 id="some-useful-appsec-tools">Some useful AppSec tools</h2><p>Statica runs a hand-picked set of tools to uncover security issues, inspired by classics like <a href="https://github.com/metricfu/metric_fu">metric-fu</a>:</p><ul><li><strong><a href="https://github.com/aquasecurity/trivy">Trivy</a></strong>: Finds secrets in code.</li><li><strong><a href="https://semgrep.dev/">Semgrep</a></strong>: Flags bugs and security holes.</li><li><strong><a href="https://github.com/Bearer/bearer">Bearer</a></strong>: Sniffs out secrets and risky code.</li><li><strong><a href="https://github.com/terryyin/lizard">Lizard</a></strong>: Spots complexity in code.</li><li><strong><a href="https://github.com/RetireJS/retire.js">RetireJS</a></strong>: Catches vulnerable JavaScript libraries.</li><li><strong><a href="https://github.com/pmd/pmd">CPD</a></strong>: Finds copy-paste code.</li><li><strong><a href="https://www.checkov.io/">Checkov</a></strong>: Scans IaaC (e.g. Terraform) code for security slip-ups.</li></ul><h2 id="how-statica-works">How Statica works</h2><p>Statica is a CLI tool. Point it at your codebase, and it runs each tool in sequence, then rolls up the results into a single HTML or console report. Easy install and updates via Homebrew on macOS and Linux.</p><p>Statica saves tool outputs in SARIF format and merges them for a single view of a codebase’s weak spots.</p><h2 id="example">Example</h2><div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew <span class="nb">install </span>simpsonjulian/statica-tap/statica
statica /path/to/codebase html
open /path/to/codebase/statica.html
</code></pre></div></div><h2 id="whats-next">What’s next?</h2><p>More checks, and better insights into the results.</p><h2 id="conclusion">Conclusion</h2><p>Statica is for anyone who wants to get SAST running on their codebase, fast. Try it and let me know how it goes.</p>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[Static analysis is a powerful technique for catching security issues. But tools that depend on compilation aren’t always easy, especially if you don’t have the right dependencies or you’re stuck on Apple Silicon with legacy code.]]></summary></entry><entry><title type="html">Pipeline Pull Request Pain on ADO?</title><link href="https://devops.nz/2022/10/31/pipeline-pull-request-pain-on-ado.html" rel="alternate" type="text/html" title="Pipeline Pull Request Pain on ADO?"/><published>2022-10-31T18:47:42+13:00</published><updated>2022-10-31T18:47:42+13:00</updated><id>https://devops.nz/2022/10/31/pipeline-pull-request-pain-on-ado</id><content type="html" xml:base="https://devops.nz/2022/10/31/pipeline-pull-request-pain-on-ado.html"><![CDATA[<p>I ran into this issue a couple of times recently, so here’s my notes on the matter.</p><p>I’ve needed to make a <a href="https://learn.microsoft.com/en-us/azure/devops/pipelines/get-started/yaml-pipeline-editor?view=azure-devops">YAML pipeline</a> on Azure DevOps, using ADO Git hosting. It’s not the edgiest stack out there, but as a consultant it’s rare that you get to choose the tools you use. Sometimes you just need to get something automated today. It’s easy to set up pipeline triggers from changes in the Git repository:</p><div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">trigger</span><span class="pi">:</span>
  <span class="na">branches</span><span class="pi">:</span>
    <span class="na">include</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s1">'</span><span class="s">*'</span>
</code></pre></div></div><p>Later on, one wants to ensure that a job runs in Pull Requests, so that people can get feedback on those PR’s before they get merged: it’s a powerful way to go from “LGTM” to”let’s fix that vulnerability first”.</p><div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">pr</span><span class="pi">:</span>
  <span class="na">branches</span><span class="pi">:</span>
    <span class="na">include</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">main</span>
      <span class="pi">-</span> <span class="s">feature-*</span>
</code></pre></div></div><p>It’s possible to spend a lot of time wondering why this doesn’t work. Here’s the thing: presently, <em>it doesn’t work for Azure’s Git hosting</em>. You’ll need to go to the Repository in Azure DevOps and set up a <a href="https://learn.microsoft.com/en-us/azure/devops/repos/git/branch-policies?view=azure-devops&amp;tabs=browser#build-validation">Build validation policy</a>. This is a pointy-click change, but you can use the <a href="https://learn.microsoft.com/en-us/cli/azure/repos/policy/build?view=azure-cli-latest#az-repos-policy-build-create">Azure CLI</a> if you want a hands-off workaround. I can empathise with the Azure DevOps team here: they’ve had to evolve this product over 17 years to keep up with changing fashions in development. This feature hasn’t been migrated to YAML yet. The world has changed a lot, Enterprise customers are looking for stability, and there’s a workaround to keep the pipelines flowing.</p>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[I ran into this issue a couple of times recently, so here’s my notes on the matter.]]></summary></entry><entry><title type="html">Securikube Part 1: Linting and Vulnerability Checking</title><link href="https://devops.nz/2022/10/18/securikube-part-1-linting.html" rel="alternate" type="text/html" title="Securikube Part 1: Linting and Vulnerability Checking"/><published>2022-10-18T17:16:55+13:00</published><updated>2022-10-18T17:16:55+13:00</updated><id>https://devops.nz/2022/10/18/securikube-part-1:-linting</id><content type="html" xml:base="https://devops.nz/2022/10/18/securikube-part-1-linting.html"><![CDATA[<p>( this post carries on from <a href="https://devops.nz/2022/06/06/securikube-part-0.html">Securikube Part 0</a>) It’s all good to secure your servers, be they Kubernetes or anything else. Sometimes the applications make that job harder: the applications will break if you stop them doing insecure things, like running as root. In this post we’ll look at two approaches: linting Dockerfiles, and scanning Docker images for vulnerabilities.</p><p>We want to stop bad things from happening early, not pick them up after publishing or deployment.</p><p>Insecure containers expose the system to application vulnerabilities. Let’s go find some!</p><h1 id="linting">Linting</h1><p>You want to know if you’re building containers with weak security. How do you find out? By Linting the Dockerfile before you build it. I chose <a href="https://github.com/hadolint/hadolint">Hadolint</a> as the tool to do this on a sample application, and added it to the Makefile:</p><div class="language-make highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">lint</span><span class="o">:</span>
	docker run <span class="nt">--rm</span> <span class="nt">-i</span> hadolint/hadolint &lt; Dockerfile

<span class="nl">docker</span><span class="o">:</span> <span class="nf">app.war lint</span>
	docker build <span class="nt">--platform</span> linux/amd64 <span class="nt">--build-arg</span> <span class="nv">JAR_FILE</span><span class="o">=</span>build/libs/<span class="se">\d</span>emo-<span class="p">$(</span>VERSION<span class="p">)</span>.war <span class="nt">-t</span> demo:<span class="p">$(</span>VERSION<span class="p">)</span> .
</code></pre></div></div><p>Hadolint found issues with my 6 line Dockerfile, some of which could have impacted security: for example you shouldn’t leave package cache files sitting around if you happened to install a package in your Docker build.</p><h1 id="scanning">Scanning</h1><p>Any good container repository should let you scan for vulnerabilities: Azure and AWS Container repositories do, the Docker service also does. But why wait? I added <a href="https://github.com/aquasecurity/trivy">Trivy</a> (hat tip to Phil) in order to expose any issues. Oh my Lord there were issues:</p><div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="go">demo:1.0.0 (alpine 3.14.0)

Total: 36 (UNKNOWN: 0, LOW: 0, MEDIUM: 6, HIGH: 26, CRITICAL: 4)

┌──────────────┬────────────────┬──────────┬───────────────────┬───────────────┬─────────────────────────────────────────────────────────────┐
│   Library    │ Vulnerability  │ Severity │ Installed Version │ Fixed Version │                            Title                            │
├──────────────┼────────────────┼──────────┼───────────────────┼───────────────┼─────────────────────────────────────────────────────────────┤
│ apk-tools    │ CVE-2021-36159 │ CRITICAL │ 2.12.5-r1         │ 2.12.6-r0     │ libfetch before 2021-07-26, as used in apk-tools, xbps, and │
│              │                │          │                   │               │ other products, mishandles...                               │
│              │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2021-36159                  │
├──────────────┼────────────────┼──────────┼───────────────────┼───────────────┼─────────────────────────────────────────────────────────────┤
│ busybox      │ CVE-2021-42378 │ HIGH     │ 1.33.1-r2         │ 1.33.1-r6     │ busybox: use-after-free in awk applet leads to denial of    │
│              │                │          │                   │               │ service and possibly...                                     │
│              │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2021-42378                  │
│              ├────────────────┤          │                   │               ├─────────────────────────────────────────────────────────────┤
│              │ CVE-2021-42379 │          │                   │               │ busybox: use-after-free in awk applet leads to denial of    │

</span></code></pre></div></div><p>There were so many issues found in the Docker image and the Java app inside it, that I had to pause writing and go fix it. Even then I couldn’t find a clean Docker image, and there are still transitive dependencies from Spring Boot that cause noise. That’s a challenge managing vulnerabilities in a live project, so I configured it to exclude unfixed findings, and only fail at a threshold. Right now it fails the build if there are Critical vulnerabilities discovered.</p><div class="language-make highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">docker</span><span class="o">:</span> <span class="nf">app.war lint</span>
	docker build <span class="nt">--platform</span> linux/amd64 <span class="nt">--build-arg</span> <span class="nv">JAR_FILE</span><span class="o">=</span>build/libs/<span class="se">\d</span>emo-<span class="p">$(</span>VERSION<span class="p">)</span>.war <span class="nt">-t</span> demo:<span class="p">$(</span>VERSION<span class="p">)</span> .
	trivy image demo:<span class="p">${</span>VERSION<span class="p">}</span> <span class="nt">--exit-code</span> 1  <span class="nt">--ignore-unfixed</span>  <span class="nt">--severity</span> CRITICAL <span class="c">#,HIGH</span>
</code></pre></div></div><p>It takes about 2 seconds to build and check the Docker image (excluding building the toy Spring Boot app). See below for details. Doing this for all your container images gives a high ROI for your time: you’ll reduce your exposure to application and container vulnerabilities.</p><div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="go">time make docker
docker run --rm -i hadolint/hadolint &lt; Dockerfile
docker build --platform linux/amd64 --build-arg JAR_FILE=build/libs/\demo-1.0.0.war -t demo:1.0.0 .
[+] Building 1.0s (7/7) FINISHED
</span><span class="gp"> =&gt;</span><span class="w"> </span><span class="o">[</span>internal] load build definition from Dockerfile                                                                                                                                     0.0s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">=&gt;</span> transferring dockerfile: 37B                                                                                                                                                      0.0s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">[</span>internal] load .dockerignore                                                                                                                                                        0.0s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">=&gt;</span> transferring context: 2B                                                                                                                                                          0.0s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">[</span>internal] load metadata <span class="k">for </span>docker.io/library/openjdk:18                                                                                                                            0.9s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">[</span>internal] load build context                                                                                                                                                        0.0s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">=&gt;</span> transferring context: 104B                                                                                                                                                        0.0s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">[</span>1/2] FROM docker.io/library/openjdk:18@sha256:ac8bc800c76446207675f93939a8977e032043a182c1a6be23c6cdd300db0cc5                                                                      0.0s
<span class="gp"> =&gt;</span><span class="w"> </span>CACHED <span class="o">[</span>2/2] COPY build/libs/demo-1.0.0.war /app.war                                                                                                                                 0.0s
<span class="gp"> =&gt;</span><span class="w"> </span>exporting to image                                                                                                                                                                   0.0s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">=&gt;</span> exporting layers                                                                                                                                                                  0.0s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">=&gt;</span> writing image sha256:8ff141dc971724c6602aa51bb709b6ae804c720cdfa44e19fc866a4ffe214a8a                                                                                             0.0s
<span class="gp"> =&gt;</span><span class="w"> </span><span class="o">=&gt;</span> naming to docker.io/library/demo:1.0.0                                                                                                                                            0.0s
<span class="gp">trivy image demo:1.0.0 --exit-code 1  --ignore-unfixed  --severity CRITICAL #</span>,HIGH
<span class="go">2022-10-24T12:45:49.662+1300	INFO	Vulnerability scanning is enabled
2022-10-24T12:45:49.662+1300	INFO	Secret scanning is enabled
2022-10-24T12:45:49.662+1300	INFO	If your scanning is slow, please try '--security-checks vuln' to disable secret scanning
</span><span class="gp">2022-10-24T12:45:49.662+1300	INFO	Please see also https://aquasecurity.github.io/trivy/v0.32/docs/secret/scanning/#</span>recommendation <span class="k">for </span>faster secret detection
<span class="go">2022-10-24T12:45:49.692+1300	INFO	Detected OS: oracle
2022-10-24T12:45:49.692+1300	INFO	Detecting Oracle Linux vulnerabilities...
2022-10-24T12:45:49.699+1300	INFO	Number of language-specific files: 1
2022-10-24T12:45:49.699+1300	INFO	Detecting jar vulnerabilities...

demo:1.0.0 (oracle 8.6)

Total: 0 (CRITICAL: 0)


real	0m2.011s
user	0m0.439s
sys	0m0.095s
</span></code></pre></div></div>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[( this post carries on from Securikube Part 0) It’s all good to secure your servers, be they Kubernetes or anything else. Sometimes the applications make that job harder: the applications will break if you stop them doing insecure things, like running as root. In this post we’ll look at two approaches: linting Dockerfiles, and scanning Docker images for vulnerabilities.]]></summary></entry><entry><title type="html">Addition on the command line</title><link href="https://devops.nz/2022/06/25/addition-on-the-command-line.html" rel="alternate" type="text/html" title="Addition on the command line"/><published>2022-06-25T16:50:54+12:00</published><updated>2022-06-25T16:50:54+12:00</updated><id>https://devops.nz/2022/06/25/addition-on-the-command-line</id><content type="html" xml:base="https://devops.nz/2022/06/25/addition-on-the-command-line.html"><![CDATA[<p>How much did our household spend on power last year? I wish I had an app that would parse all my bank statements and tell me what it costs just to stay alive, but my bank doesn’t do integrations well. In fact, given that my power company sunset their consumer API, things seem to be even less connected.</p><p>So I downloaded a year’s worth of withdrawals in CSV format, and did this:</p><p><code class="language-plaintext highlighter-rouge">egrep -i "powerco|gasco" account.csv | awk -F "," '{s+=$4} END {printf "%.0f\n", s}'</code></p><p>I could write the whole thing in awk, but these things evolve by tacking commands onto the pipelines, and there’s no need to get clever.</p><p>We spent more than I’d expected to, so my next job is to find out what is chewing up so much energy. Of course, normal people would use a spreadsheet.</p>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[How much did our household spend on power last year? I wish I had an app that would parse all my bank statements and tell me what it costs just to stay alive, but my bank doesn’t do integrations well. In fact, given that my power company sunset their consumer API, things seem to be even less connected.]]></summary></entry><entry><title type="html">Securikube, part 0</title><link href="https://devops.nz/2022/06/06/securikube-part-0.html" rel="alternate" type="text/html" title="Securikube, part 0"/><published>2022-06-06T18:34:02+12:00</published><updated>2022-06-06T18:34:02+12:00</updated><id>https://devops.nz/2022/06/06/securikube-part-0</id><content type="html" xml:base="https://devops.nz/2022/06/06/securikube-part-0.html"><![CDATA[<p>I’ve been avoiding unnecessary outings because of COVID cases in our household. This is a perfect opportunity to do some research. I’ve done plenty with Docker: I’ve found it great for externalizing dependencies in development environments. I have also done security work around the edges of <a href="https://docs.microsoft.com/en-us/azure/aks/intro-kubernetes">AKS</a> or <a href="https://aws.amazon.com/eks/">EKS</a>. Next I’m interested in digging deeper into Kubernetes security inside the cluster, but I’d like to deploy a cluster or two for myself first.</p><p>I started from first principles with a basic <a href="https://github.com/simpsonjulian/spring-boot-docker-app">Spring Boot</a> application, tried some different distributions of Kubernetes, and made an application deploy. Then made the thing visible from my local computer. That took a long time. Here’s what I learned:</p><p><strong>Apple Silicon has teething issues:</strong> I love my M1 MacBook Pro. I found the following gumption traps in my first session:</p><ul><li>The <a href="https://kubernetes.io/docs/tutorials/hello-minikube/">official Kubernetes tutorial</a> doesn’t work by default on ARM, as it refers to images that aren’t binary compatible.</li><li><a href="https://www.docker.com">Docker</a> will throw occasional errors - either crashing on start, or having networking glitches. I’m sure that will get fixed. I’m using <a href="https://rancherdesktop.io">Rancher</a> in the interim.</li><li><a href="https://minikube.sigs.k8s.io/docs/start/">Minikube</a> didn’t work out of the box. Many posts online suggest configuring minikube to use Docker, which didn’t work for me.</li><li>You’ll get used to setting the <code class="language-plaintext highlighter-rouge">platform</code> parameter everywhere, to run Intel/AMD containers instead of ARM.</li></ul><p><strong>The ecosystem is a loud bazaar:</strong> On the desktop there’s several different distributions of Kubernetes. Each cloud provider supports at least one implementation. The ecosystem that interacts with these is huge. Similar itches are being scratched many different ways. My view is that you needs to work out what Dev and Ops cultures matter in your team:</p><ul><li>If GitOps is your thing, then you might like <a href="https://argoproj.github.io/cd/">ArgoCD</a></li><li>If you’re into configuration as code, you might like <a href="https://cdk8s.io">CDK8S</a></li><li>If you like templating YAML or JSON, there are many different tools (<a href="https://kustomize.io">Kustomize</a>, <a href="https://tanka.dev">Tanka</a> out there for you.</li></ul><p><strong>It’s hard to choose tools correctly the first time:</strong> as communities and systems evolve, yesterday’s right choice might be today’s technical debt. If you can keep an open mind about where to apply different approaches, then you may be able to incubate newer tools and get some payoff from them. If you stick to the tools that you’re comfortable with, you may find yourself with an obsolete stack.</p><p><strong>Where I got to</strong> with my playpen application: I’m building local images using the Docker CLI against Rancher, orchestrated with Make, and calling down to Gradle to build Java stuff. After experimenting with plain YAML and kubetcl, exploring Tanka, I finished with the <a href="https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs">Terraform provider for Kubernetes</a>. I would want to deploy AKS or EKS infrastructure with Terraform, and to kick the tyres I will continue with Terraform to get apps lifted and shifted to Kubernetes. That won’t scale forever, and at some point I’ll find the right tools to manage the inside of the cluster. But for today, I’m going to add one new tool to the toolbelt.</p><p><em>Update:</em> I got around to <a href="https://devops.nz/2022/10/18/securikube-part-1-linting.html">Securikube Part 1</a>.</p>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[I’ve been avoiding unnecessary outings because of COVID cases in our household. This is a perfect opportunity to do some research. I’ve done plenty with Docker: I’ve found it great for externalizing dependencies in development environments. I have also done security work around the edges of AKS or EKS. Next I’m interested in digging deeper into Kubernetes security inside the cluster, but I’d like to deploy a cluster or two for myself first.]]></summary></entry><entry><title type="html">The fish rots from the headers down</title><link href="https://devops.nz/2022/01/26/the-fish-rots-from-the-headers-down.html" rel="alternate" type="text/html" title="The fish rots from the headers down"/><published>2022-01-26T19:14:23+13:00</published><updated>2022-01-26T19:14:23+13:00</updated><id>https://devops.nz/2022/01/26/the-fish-rots-from-the-headers-down</id><content type="html" xml:base="https://devops.nz/2022/01/26/the-fish-rots-from-the-headers-down.html"><![CDATA[<p>OK, the real saying is <code class="language-plaintext highlighter-rouge">the fish rots from the head down</code>: if your CEO allows awful behaviours to happen at work without intervention, then they should take the blame when those behaviours become normalised in the organisation that they run. This post is not about that.</p><p>When you’re getting a pen test for your web application, testers are duty bound to give you findings about your missing HTTP headers. It’s important, but it also muddies the waters with findings that anyone could generate. If you visit <a href="https://securityheaders.com/">Security Headers</a> and ensure that your application has a clean scan before the pen testers show up, you’ll get a cleaner report.</p><p>I scanned this site last week and got a D. After reading the recommendations and adding some Zeit config, it’s an A+. Probably not a huge acheivement for this static site, but a good tool to have in the shed.</p>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[OK, the real saying is the fish rots from the head down: if your CEO allows awful behaviours to happen at work without intervention, then they should take the blame when those behaviours become normalised in the organisation that they run. This post is not about that.]]></summary></entry><entry><title type="html">Misadventures in securing IaC</title><link href="https://devops.nz/2021/08/07/misadventures-in-securing-iac.html" rel="alternate" type="text/html" title="Misadventures in securing IaC"/><published>2021-08-07T16:24:30+12:00</published><updated>2021-08-07T16:24:30+12:00</updated><id>https://devops.nz/2021/08/07/misadventures-in-securing-iac</id><content type="html" xml:base="https://devops.nz/2021/08/07/misadventures-in-securing-iac.html"><![CDATA[<p>I’ve had an Infrastructure-as-Code repo since around 2005. That used to be Puppet code, and included config for bind, apache/nginx, dovecot IMAP, and postfix. There were a few years of apathy in which I hosted DNS elsewhere: this cascaded into all sorts of pain.</p><p>I’ve since pulled nearly everything back to AWS so I can manage it all with Terraform in a GitHub repo. That raises a question: how secure are my AWS resources? Inspecting stuff with AWS is possible, with tools like <a href="https://aws.amazon.com/security-hub/">AWS Security Hub</a>. It would be nice to know that I were making secure Terraform code before I pushed it and applied. I chose <a href="https://github.com/bridgecrewio/checkov">Checkov</a>. There are other tools out there, like <a href="https://snyk.io/product/infrastructure-as-code-security/">Snyk IaC</a>.</p><p>I installed the Checkov package from <a href="https://www.xkcd.com/927/">PiPi using Pipenv</a>, and then invoked <code class="language-plaintext highlighter-rouge">pipenv shell</code> to call the <code class="language-plaintext highlighter-rouge">checkov</code> script from a Makefile. Here’s the kind of output that Checkov gives you:</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(terraform) bash-3.2$ checkov --quiet -d .; exit

       _               _
   ___| |__   ___  ___| | _______   __
  / __| '_ \ / _ \/ __| |/ / _ \ \ / /
 | (__| | | |  __/ (__|   &lt; (_) \ V /
  \___|_| |_|\___|\___|_|\_\___/ \_/

By bridgecrew.io | version: 2.0.338

terraform scan results:

Passed checks: 91, Failed checks: 3, Skipped checks: 43

Check: CKV_AWS_19: "Ensure all data stored in the S3 bucket is securely encrypted at rest"
	FAILED for resource: aws_s3_bucket.media-build-doctor-com
	File: /build-doctor.com.tf:84-90
	Guide: https://docs.bridgecrew.io/docs/s3_14-data-encrypted-at-rest

		84 | resource "aws_s3_bucket" "media-build-doctor-com" {
		88 |   bucket = "foo.build-doctor.com"
		89 |   acl = "private"
		90 | }
</code></pre></div></div><p>Here’s what I learned:</p><h2 id="refactor-for-a-better-time">Refactor for a better time</h2><p>Checkov will tell you in no uncertain terms that your Terraform code is insecure; you’ll end up questioning your life choices. It was especially bad for my poorly composed Terraform code - I had lot of similar resources in my code, each of which picked up many warnings.</p><p>Doing the right thing and extracting modules for my static websites was a good thing - it drove consistency and reduced the howls of outage from Checkov.</p><h2 id="apply-and-test-often">Apply and test often</h2><p>The age old struggle between convenience and security played out again - I spent a couple of hours happily smashing security vulnerabilities that Checkov reported, before finding that I’d completely broken the sites, with no access from S3 buckets to Cloudfront. The log buckets were so tightly locked down that I couldn’t even see what happened. After quite some time kicking tyres, I rolled the changes back.</p><p>I made some some really simple tests using curl, that I can easily run from make. This gives me confidence that the websites still work. I try to get early feedback by applying the changes in Terraform and then testing afterward.</p><h2 id="suppress-the-false-positives">Suppress the false positives</h2><p>The many findings about S3 security make a great deal of sense in many contexts - the way we use S3 has changed during the lifetime of the S3 service. Nobody wants to win a <a href="https://twitter.com/quinnypig/status/1249862200333717504?lang=en">Bucket Negligence Award</a>. In my case, where I host some very basic static websites, I’m happy to suppress those:</p><div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>resource "aws_s3_bucket" "bucket" {
  #checkov:skip=CKV2_AWS_6:We have a public access block
  #checkov:skip=CKV_AWS_18:this kind of content doesn't need encryption
  #checkov:skip=CKV_AWS_19:this kind of content doesn't need encryption
  #checkov:skip=CKV_AWS_20=Public ACLs are fine for this
  #checkov:skip=CKV_AWS_52:MFA delete hard to apply via TF
  #checkov:skip=CKV_AWS_144:Cross Region Replication not important
  #checkov:skip=CKV_AWS_145:We're not going to encrypt public website stuff
</code></pre></div></div><p>Suppression helps me to focus on the things that matter in my context.</p>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[I’ve had an Infrastructure-as-Code repo since around 2005. That used to be Puppet code, and included config for bind, apache/nginx, dovecot IMAP, and postfix. There were a few years of apathy in which I hosted DNS elsewhere: this cascaded into all sorts of pain.]]></summary></entry><entry><title type="html">Using SAST tools to prevent disaster</title><link href="https://devops.nz/2021/05/25/using-sast-tools-to-prevent-disaster.html" rel="alternate" type="text/html" title="Using SAST tools to prevent disaster"/><published>2021-05-25T11:46:22+12:00</published><updated>2021-05-25T11:46:22+12:00</updated><id>https://devops.nz/2021/05/25/using-sast-tools-to-prevent-disaster</id><content type="html" xml:base="https://devops.nz/2021/05/25/using-sast-tools-to-prevent-disaster.html"><![CDATA[<p>Static analysis tools help people write better software, by telling them how they goofed. <a href="https://owasp.org/www-community/Source_Code_Analysis_Tools">SAST tools</a> are the evolution of static analysis: tools that point out the security goofs in your code. No tool is perfect, or the replacement for a very skilled reviewer with a lot of time: for example, SAST tools will generate false positives. They’re also very low-effort method of getting feedback for developers.</p><p>I’ve collected a few easy options for deploying SAST tools in this post.</p><p>First on the list is <a href="https://www.sonarqube.org">SonarQube</a>. As it supports many tools under the hood, it can give you an overwhelming list of things to fix. With a bit of setup, it’s useful for tracking the health of a codebase over time. The neat thing is that it will also detect and track security issues. If you’re being asked by clients about your SAST or DAST tooling, it’s a great way to check the box. SonarQube also works with the <a href="https://www.sonarlint.org">SonarLint IDE plugin</a>, which is very helpful. You’ll need to buy the cloud service, or run your own SonarQube server.</p><p>Next up, is <a href="https://github.com/features/security/code">GitHub Advanced Security</a>. Being a GitHub feature, it’s tightly integrated with GitHub and can be configured to run on push, or as an Action. You can also add third party scanners, and use webhooks to add Jira tickets to the backlog. Advanced Security needs an Enterprise plan, so if you’re looking to throw money at the problem, this could be the solution.</p><p>Finally, there’s two other tools that I think deserve a mention: <a href="https://snyk.io">Snyk</a>, because they have good IDE support (why not squash them at the source?), and it integrates with BitBucket and GitLab. Also, of note is <a href="https://www.sonatype.com/product/musedev-maven">Muse</a>; Sonatype acquired this recently and will be releasing hosted and free versions. It’ll be branded as Sonatype Lift and will integrate with the Maven ecosystem, to help address supply chain compromises.</p>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[Static analysis tools help people write better software, by telling them how they goofed. SAST tools are the evolution of static analysis: tools that point out the security goofs in your code. No tool is perfect, or the replacement for a very skilled reviewer with a lot of time: for example, SAST tools will generate false positives. They’re also very low-effort method of getting feedback for developers.]]></summary></entry><entry><title type="html">Site improvements</title><link href="https://devops.nz/2021/05/21/site-improvements.html" rel="alternate" type="text/html" title="Site improvements"/><published>2021-05-21T12:02:53+12:00</published><updated>2021-05-21T12:02:53+12:00</updated><id>https://devops.nz/2021/05/21/site-improvements</id><content type="html" xml:base="https://devops.nz/2021/05/21/site-improvements.html"><![CDATA[<p>I’ve had a little time to clean up this website. There were a few issues:</p><ul><li>The site still had stylesheets loading for Bulma, which I stopped using in favour of my own minimal CSS. I also had references to Bulma classes because the stylesheet was still there.</li><li>I hadn’t set the <code class="language-plaintext highlighter-rouge">JEKYLL_ENV</code> environment variable in Vercel, which stopped Google Analytics from loading, but I still had leftover Google Analytics code lying around, and Discuss includes rotting away.</li><li>There was a bad client side contact form made for for another site in 2017 or sot. It’s replaced with a third party service, but I’m tempted to write something else to accept forms from this site.</li><li>The one image that loads on the site was slowing down the first render, so I fired up ImageMagick and changed it to a more performant format.</li><li>I also added compression to make the site load even faster.</li></ul><p>Very satisfying to fix tech debt. There’s always tech debt.</p>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[I’ve had a little time to clean up this website. There were a few issues:]]></summary></entry><entry><title type="html">3 lessons learned from a decade in startups</title><link href="https://devops.nz/2021/04/27/3-lessons-learned-from-a-decade-in-startups.html" rel="alternate" type="text/html" title="3 lessons learned from a decade in startups"/><published>2021-04-27T23:00:35+12:00</published><updated>2021-04-27T23:00:35+12:00</updated><id>https://devops.nz/2021/04/27/3-lessons-learned-from-a-decade-in-startups</id><content type="html" xml:base="https://devops.nz/2021/04/27/3-lessons-learned-from-a-decade-in-startups.html"><![CDATA[<p>I’m currently working in the 5th venture funded organisation in my career. It’s almost 10 years since I started working with Neo4j: I was consulting for them around the 3rd quarter of 2011, and then joined full-time for the next few years. Here’s some idle thoughts around startups:</p><p><em>Staying alive beats everything else</em>. Like a living thing, startups will endure all sorts of horrors to stay alive. Crappy work conditions, penny-pinching, super economy travel: all necessary unless you have the enough runway to upgrade. It’s the job of the management team to keep the business afloat, so don’t complain about having to buy your own lunch. The present amount of funding available means that startup employees get amazing benefits: it’s not normal.</p><p><em>Silos will hurt your startup</em>. It’s easier than ever for organisations to spread around the world. It’s also easy to create geographic as well as organisational silos. You need to work out how to prevent that in your organisation: having Sales based in one region and Engineering in another can easily lead to silos. We’re tribal creatures, and will naturally create ingroups and outgroups based on department and geography. Plan accordingly.</p><p><em>Risk and compliance will matter</em>. Sure, go ahead and pivot all you like while you’re trying to find your startup’s place in the world. Kick as many cans down the road as you can: you might not even stay on that road. Once you’re on that road: start investing in the tools to make compliance and security easier. You don’t have to start with much; perhaps some advice on how to get started. I’ve seen several organisations make compliance difficult, or be unaware of the risk that they’re running by uh, not managing risk.</p><p>While you’re reading about risk: after ten long years in startups I’m moving back to consulting. I’ll be joining <a href="https://www.safeadvisory.co.nz">Safe Advisory</a> at the beginning of May to do security and DevSecOps advisory. I’m looking forward to the change: helping people to demystify security and fearlessly secure their organisations feels like a worthwhile pursuit. It also gets me out of the house from time to time.</p>]]></content><author><name>Julian Simpson</name></author><summary type="html"><![CDATA[I’m currently working in the 5th venture funded organisation in my career. It’s almost 10 years since I started working with Neo4j: I was consulting for them around the 3rd quarter of 2011, and then joined full-time for the next few years. Here’s some idle thoughts around startups:]]></summary></entry></feed>