· Piotr Gregorczyk · Engineering  · 6 min read

From Local Secrets to Cloud Security: A DevSecOps Journey with GCP, Spacelift, and Pulumi

A step-by-step guide to building a secure and automated infrastructure for managing secrets, from local development to cloud deployment.

A step-by-step guide to building a secure and automated infrastructure for managing secrets, from local development to cloud deployment.

Speed and security are not opposites — they are two sides of the same coin.


The Unexpected Gift of AI-Assisted Learning

There’s something quietly revolutionary happening in how we learn new technologies. The barrier that used to separate “tools I know” from “tools I’ve always wanted to try” is shrinking fast — and modern AI is the reason why.

What used to take days of documentation diving, Stack Overflow rabbit holes, and trial-and-error can now be compressed into hours. AI doesn’t just answer questions — it scaffolds your thinking, fills in the gaps, and lets you focus on understanding rather than searching.

So when I found myself with some free time between projects, I decided to finally act on a list I’d been building for a while: technologies I was genuinely curious about but never had the right moment to explore.

One of those was Pulumi — writing real code instead of YAML to manage infrastructure. Another was Spacelift — a CI/CD platform purpose-built for infrastructure as code. And I already had a soft spot for GCP from previous projects.

So I gave myself a challenge: build something real with these tools. Something I’d actually use. The result was a DevSecOps pipeline for managing secrets — from my local machine all the way to Google Cloud. This is that story.


The Problem: Secrets Are Everywhere, and That’s Dangerous

Every developer knows the drill. You’re working locally, you need an API key, a database password, a service account token — and before you know it, it’s sitting in a .env file, maybe accidentally committed to Git, maybe shared over Slack. It happens to the best of us.

The real question is: what do you do about it?


The Architecture at a Glance

Before diving in, here’s the high-level flow:

Local Machine (pass + GPG)

Infrastructure as Code (Pulumi)

Automated Deployment (Spacelift)

Cloud Secret Storage (GCP Secret Manager)

Simple. Auditable. Automated.


Step 1: Local Secret Management with pass

pass is the standard Unix password manager — and it’s beautifully simple. It uses GPG encryption to store secrets as encrypted files in a directory tree. Every secret is a file, every folder is a namespace, and everything is version-controllable with Git.

# Initialize pass with your GPG key
pass init <your-gpg-key-id>

# Store a secret
pass insert myproject/gcp/service-account-key

# Retrieve it
pass myproject/gcp/service-account-key

Why pass over other local tools? Because it’s transparent, scriptable, and integrates naturally with shell workflows. No proprietary formats, no vendor lock-in.

💡 Pro tip: If you need to generate a new GPG key for this setup, use gpg --full-generate-key for full control over key type and expiry.


Step 2: Infrastructure as Code with Pulumi

Once secrets are safely stored locally, the next challenge is getting them into the cloud without ever exposing them in plaintext.

This is where Pulumi shines — and honestly, this was the part I was most excited to try. Instead of writing YAML or HCL, you write real code — TypeScript, Python, Go, whatever you prefer. This means you get loops, conditionals, abstractions, and proper software engineering practices applied to your infrastructure. As someone who has spent years writing production code, this just feels right.

Here’s a simplified example of replicating a secret from pass to GCP Secret Manager using Pulumi (TypeScript):

import * as gcp from '@pulumi/gcp';
import { execSync } from 'child_process';

// Fetch secret from local pass store
const secretValue = execSync('pass myproject/gcp/api-key').toString().trim();

// Create the secret in GCP Secret Manager
const secret = new gcp.secretmanager.Secret('api-key', {
  secretId: 'api-key',
  replication: {
    automatic: {},
  },
});

// Add the secret version (the actual value)
const secretVersion = new gcp.secretmanager.SecretVersion('api-key-version', {
  secret: secret.id,
  secretData: secretValue,
});

Your infrastructure is now versioned, reviewable, and repeatable. And it reads like code — because it is code.


Step 3: Enabling GCP Secret Manager

Before deploying, make sure the Secret Manager API is enabled in your GCP project:

gcloud services enable secretmanager.googleapis.com --project=<your-project-id>

For authentication, you have two clean options:

Option A — Service Account Key File:

gcloud auth activate-service-account \
  --key-file=your-service-account.json \
  --project=your-project-id

Option B — Service Account Impersonation (preferred):

gcloud config set auth/impersonate_service_account \
  pulumi-ops@your-project.iam.gserviceaccount.com

Option B is cleaner — no key files on disk, no risk of accidental exposure. Always prefer it when you can.


Step 4: Continuous Delivery with Spacelift

Manually running pulumi up works fine locally, but in a team environment you need automation, auditability, and access control. That’s where Spacelift comes in — and this was the second tool on my “always wanted to try” list.

Spacelift is a continuous delivery platform purpose-built for infrastructure as code. Think of it as CI/CD, but designed specifically for Pulumi, Terraform, and similar tools.

With Spacelift you get:

  • Automated deployments triggered by Git push
  • Policy-as-code for approval workflows
  • Drift detection — know when your real infrastructure diverges from your code
  • Audit logs for every change, every deployment, every approval

The workflow becomes:

  1. You update your Pulumi code and push to Git
  2. Spacelift detects the change and runs a plan
  3. The plan is reviewed (manually or auto-approved based on policy)
  4. Spacelift applies the changes to GCP

No more pulumi up from a developer’s laptop in production. Ever.


The Results: What This Setup Actually Delivers

After implementing this pipeline, here’s what changed:

ConcernBeforeAfter
Secret storage.env files, Slack messagesEncrypted with GPG via pass
Secret replicationManual copy-pasteAutomated via Pulumi
Cloud access controlBroad IAM rolesFine-grained Secret Manager policies
Audit trailNoneFull history in Spacelift + GCP
ComplianceHard to proveAutomated, documented, reproducible

Key Takeaways

  • pass + GPG gives you a simple, transparent, and scriptable local secret store
  • Pulumi lets you treat infrastructure like real software — with all the engineering discipline that implies
  • GCP Secret Manager provides encrypted-at-rest, fine-grained, auditable secret storage in the cloud
  • Spacelift closes the loop by automating deployments and adding governance to your IaC workflow

But beyond the technical stack — the real lesson here is simpler: stability creates space for curiosity, and curiosity is where the best learning happens. I built this because I finally had the headspace to explore. And I’d encourage anyone in a similar position to do the same.

Pick the tool you’ve been watching from a distance. Build something real with it. Write about it.


What’s Next?

This pipeline is a foundation. From here, you can extend it with:

  • Automatic secret rotation policies in GCP Secret Manager
  • Workload Identity Federation to eliminate service account keys entirely
  • OPA policies in Spacelift for fine-grained deployment governance
  • Secret scanning in your CI pipeline to catch accidental exposures before they reach Git
Back to Blog

Related Posts

View All Posts »