Security11 min read

SOC 2 for Startups: The DevOps Work Nobody Warns You About

Share:

Free DevOps Audit Checklist

Get our comprehensive checklist to identify gaps in your infrastructure, security, and deployment processes

Instant delivery. No spam, ever.

SOC 2 for Startups: The DevOps Work Nobody Warns You About

The pattern is always the same. A deal is moving, the champion is enthusiastic, and then procurement forwards a 200-row security questionnaire with a cell that says "SOC 2 Type II report attached?" The deal does not die. It just stops moving until you answer.

At that point most founders start shopping for compliance software, because that is what the ads are for. The software is useful. It is also the smaller half of the job. The larger half is infrastructure work that has to be done by someone who can log into your AWS account and change things.

Here is what SOC 2 actually asks of your systems, what is engineering versus paperwork, and how long it really takes.

What SOC 2 is, stated correctly

SOC 2 is not a certification and there is no such thing as being "SOC 2 certified." It is an attestation: a licensed CPA firm examines your controls and issues a report with their opinion. You do not get a badge from a standards body, you get a PDF from an audit firm that your customer's security team reads.

The controls are organized under the AICPA Trust Services Criteria. Security (the common criteria) is required in every SOC 2 engagement. Availability, Confidentiality, Processing Integrity, and Privacy are optional categories you include based on what you promise customers. Most startups scope Security only for the first report, sometimes adding Availability and Confidentiality if contracts require it. Every category you add expands the evidence you have to produce, so scope deliberately.

There are two report types:

  • Type I describes your controls and whether they are suitably designed as of a specific date. It is a point-in-time snapshot.
  • Type II tests whether those controls actually operated effectively across an observation window, commonly 3 to 12 months.

Enterprise buyers almost always want Type II. Type I is a reasonable interim answer that shows the program exists, and some buyers will accept it with a commitment to Type II. Ask your champion which one actually unblocks the deal before you spend money.

One more thing worth being clear-eyed about: an auditor does not scan your infrastructure. They ask you for evidence, then test samples of it. If you pulled 12 offboarding tickets, they might test 5. That cuts both ways. It means you cannot be caught by an automated scan you never ran, and it means a single sampled item with no evidence behind it becomes an exception in your report.

Which criteria map to which infrastructure control

Most of the common criteria that touch engineering come down to a handful of concrete things.

Trust Services Criteria theme Concrete DevOps control Evidence the auditor asks for
Logical access provisioning and removal SSO with a single identity provider, no local IAM users with console access, group-based role assignment Termination tickets matched to access-removal timestamps
Least privilege for production Role assumption with MFA, time-bound elevation, no shared accounts IAM policy exports, role trust policies, sample access reviews
Change management Pull requests with required review, protected branches, CI checks before deploy PR history for a sampled set of production deploys
System monitoring Centralized logs, CloudTrail in all regions, alerting with a named on-call owner Alert history plus proof someone responded
Encryption in transit and at rest TLS enforced at the edge and between services, KMS on volumes, buckets, and databases Config rule results, bucket policies, RDS settings
Backup and recovery Automated backups with defined retention, plus a documented restore test Backup config and a dated restore test record
Vulnerability management Dependency and image scanning, patch SLAs by severity, tracked remediation Scan output and tickets showing fixes inside the SLA
Vendor management Inventory of subprocessors with their own reports reviewed Vendor list, review dates, signed DPAs

Read the right-hand column again. Almost every row asks for a record produced over time, not a screenshot of a settings page. That is the thing that surprises people.

Turning on the audit trail properly

CloudTrail is the most valuable single piece of evidence infrastructure in an AWS account, and the default setup most startups have is not sufficient. You want a multi-region trail, log file validation enabled, an immutable destination bucket, and KMS encryption.

resource "aws_s3_bucket" "audit_logs" {
  bucket = "acme-audit-logs-prod"
}

resource "aws_s3_bucket_versioning" "audit_logs" {
  bucket = aws_s3_bucket.audit_logs.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_public_access_block" "audit_logs" {
  bucket                  = aws_s3_bucket.audit_logs.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_server_side_encryption_configuration" "audit_logs" {
  bucket = aws_s3_bucket.audit_logs.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.audit.arn
    }
    bucket_key_enabled = true
  }
}

resource "aws_s3_bucket_lifecycle_configuration" "audit_logs" {
  bucket = aws_s3_bucket.audit_logs.id
  rule {
    id     = "retain-13-months"
    status = "Enabled"
    filter {}
    expiration {
      days = 400
    }
  }
}

resource "aws_cloudtrail" "org" {
  name                          = "acme-org-trail"
  s3_bucket_name                = aws_s3_bucket.audit_logs.id
  kms_key_id                    = aws_kms_key.audit.arn
  is_multi_region_trail         = true
  include_global_service_events = true
  enable_log_file_validation    = true
  enable_logging                = true

  depends_on = [aws_s3_bucket_policy.audit_logs]
}

The trail needs a bucket policy allowing the CloudTrail service to write, scoped with a source ARN condition so another account cannot drop logs into your bucket:

data "aws_iam_policy_document" "audit_logs" {
  statement {
    sid     = "AWSCloudTrailAclCheck"
    actions = ["s3:GetBucketAcl"]
    resources = [aws_s3_bucket.audit_logs.arn]
    principals {
      type        = "Service"
      identifiers = ["cloudtrail.amazonaws.com"]
    }
    condition {
      test     = "StringEquals"
      variable = "aws:SourceArn"
      values   = ["arn:aws:cloudtrail:${var.region}:${var.account_id}:trail/acme-org-trail"]
    }
  }

  statement {
    sid       = "AWSCloudTrailWrite"
    actions   = ["s3:PutObject"]
    resources = ["${aws_s3_bucket.audit_logs.arn}/AWSLogs/${var.account_id}/*"]
    principals {
      type        = "Service"
      identifiers = ["cloudtrail.amazonaws.com"]
    }
    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-acl"
      values   = ["bucket-owner-full-control"]
    }
    condition {
      test     = "StringEquals"
      variable = "aws:SourceArn"
      values   = ["arn:aws:cloudtrail:${var.region}:${var.account_id}:trail/acme-org-trail"]
    }
  }

  statement {
    sid       = "DenyInsecureTransport"
    effect    = "Deny"
    actions   = ["s3:*"]
    resources = [aws_s3_bucket.audit_logs.arn, "${aws_s3_bucket.audit_logs.arn}/*"]
    principals {
      type        = "*"
      identifiers = ["*"]
    }
    condition {
      test     = "Bool"
      variable = "aws:SecureTransport"
      values   = ["false"]
    }
  }
}

Retention matters here. If your observation window is 6 months and your log retention is 30 days, you cannot produce evidence for month one. Set retention to cover the window plus the audit fieldwork, and set it before the window opens.

Change management is a GitHub configuration problem

The change management criteria are the easiest to satisfy and the most commonly failed, because teams satisfy them informally. Everyone reviews each other's PRs, but nothing enforces it, so when the auditor samples 25 production deploys and two of them were direct pushes to main at 2am during an incident, those are exceptions.

Enforce it in configuration so the evidence generates itself:

resource "github_branch_protection" "main" {
  repository_id                   = github_repository.api.node_id
  pattern                         = "main"
  enforce_admins                  = true
  require_conversation_resolution = true
  required_linear_history         = true
  allows_force_pushes             = false
  allows_deletions                = false

  required_pull_request_reviews {
    required_approving_review_count = 1
    dismiss_stale_reviews           = true
    require_code_owner_reviews      = true
  }

  required_status_checks {
    strict   = true
    contexts = ["build", "test", "security-scan"]
  }
}

Two notes on this. First, enforce_admins = true is the line people quietly remove when it gets inconvenient, and removing it is exactly what the auditor's sample will surface. Decide now whether you can live with it. Second, if you have an emergency break-glass path, document it as a policy with an after-the-fact review requirement rather than pretending it does not exist. Auditors are far more comfortable with a documented exception process than with an undocumented one they discover in the logs.

The parts that are genuinely engineering

Strip out everything a template can produce and this is the actual work list:

Identity consolidation. Getting every human out of long-lived IAM users and into SSO with role assumption. This is the single biggest lift for most startups because it touches every tool, and because there is always one legacy service account nobody wants to rotate.

Offboarding that leaves a trail. Not just removing access, but producing a record showing access was removed within your stated SLA. If offboarding is a Slack message to whoever is around, you have no evidence. Wire it to a ticket and to your identity provider's audit log.

Encryption sweep. Unencrypted EBS volumes, RDS instances created before you cared, S3 buckets without default encryption, internal traffic on plain HTTP. Each is a small fix and there are always more than you expected. AWS Config with managed rules like ENCRYPTED_VOLUMES, RDS_STORAGE_ENCRYPTED, and S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED will find them and, more usefully, keep producing dated compliance results as evidence.

Restore testing. Backups being configured is not the control. Restoring from them is. You need a dated record of an actual restore, ideally into a scratch environment, with the outcome written down. This is the control I see missing most often, and it is also the one that would save the company in a real incident.

Alerting with an owner. An alert that fires into a channel nobody reads fails the criteria, and the auditor will find it by asking for the response to a specific alert. You need a defined on-call rotation and a record of triage.

Vulnerability management with an SLA. Scanning is easy. Having written severity-based remediation windows and evidence you met them is the part that takes discipline.

Everything else (the information security policy, the incident response plan, the risk assessment, the vendor register, the security awareness training) is documentation. Real, necessary documentation that someone has to write and management has to approve, but not engineering.

What compliance vendors do and do not do

Compliance platforms are worth buying. They give you policy templates, they collect evidence continuously through read-only integrations, they track control status, and they shorten the auditor's fieldwork considerably. If your alternative is a folder of screenshots, buy the tool.

What they do not do is fix your infrastructure. The platform will tell you that 14 EBS volumes are unencrypted. It will not encrypt them. It will tell you that three people still have IAM access keys. It will not migrate you to SSO. It will flag that no restore test is recorded. It will not run one.

That gap is the entire project. The dashboard turning green requires someone to plan a volume-by-volume encryption migration with downtime windows, rebuild the access model, and change how deploys work. Budget for that person, whether they are on your team or not.

A realistic timeline

For a startup with a normal AWS setup and no prior compliance work, remediation runs 4 to 10 weeks of focused engineering time. That is the part you control and the part that is usually underestimated.

After remediation you either take a Type I quickly (weeks) or start your Type II observation window. The window itself is calendar time you cannot compress: a 3 month window takes 3 months. Then auditor fieldwork and report issuance adds a few more weeks.

So "SOC 2 in 90 days" is achievable if it means a Type I plus an open Type II window, and it is not achievable if it means a Type II report in hand. Say that clearly to your customer. Most will accept a Type I and a dated commitment. The ones who will not were probably never going to close this quarter.

The five failure modes

  1. No offboarding trail. Access was removed, but nothing recorded when or by whom.
  2. Shared production credentials. A root key or a shared login in a password manager, which makes every action in the audit log unattributable.
  3. Backups that have never been restored. The config exists, the test does not.
  4. Alerts nobody acts on. Monitoring is in place, response evidence is not.
  5. Starting the observation window before remediating. Every day of the window with a broken control is a day of failing evidence, and you cannot retroactively fix it.

The order matters. Remediate, verify the controls actually produce evidence, then open the window.

If you want help with the infrastructure half

The policies and the evidence platform you can handle in-house or with a compliance vendor. The infrastructure remediation is where teams stall, because it is real engineering on production systems while you are also shipping product. We do that part for clients: identity consolidation, encryption sweeps, change management enforcement, logging and retention, backup restore testing, and the runbooks that keep the controls operating after the auditor leaves. If your deal is stalled on a questionnaire, a short call is usually enough to tell you which of the items above actually apply to your stack.

InstaDevOps runs this kind of work for startups and scale-ups on a flat monthly fee.

Ready to Transform Your DevOps?

Senior DevOps engineers on a flat monthly retainer, from $2,999/mo. See what is included or book a call.

Book a Free Call

Never Miss an Update

Get the latest DevOps insights, tutorials, and best practices delivered straight to your inbox. Join 500+ engineers leveling up their DevOps skills.

We respect your privacy. Unsubscribe at any time. No spam, ever.