Commit Graph

21 Commits

Author SHA1 Message Date
Spike Curtis 132fa87bf3 fix: only embed Azure roots on darwin (#25312)
Partially reverts #25136 for non-darwin platforms.

In general we want to avoid pinning trust roots to embedded Certs, since that limits operational flexibility. If Azure changes CAs, operators should, at most, be able to update the OS trust store to keep Coder working correctly. Embedding roots means we need to upgrade the Coder binary.

Since Coder Server on macOS is not really supported for production use, embedding only in that case to ease development and testing is OK.
2026-05-14 11:45:21 -04:00
George K 49c6191bbe fix(coderd/azureidentity): add Azure IMDS G2 chain certificates (#25243)
Azure IMDS attested data signatures can now chain through
Microsoft TLS G2 RSA CA OCSP intermediates, then through the
cross-signed Microsoft TLS RSA Root G2 certificate, before reaching
DigiCert Global Root G2.

coderd did not bundle the new G2 OCSP intermediates or the
cross-signed Microsoft TLS RSA Root G2 bridge certificate, so it could
fail to build a trusted chain for affected IMDS signatures.

Related to:
https://linear.app/codercom/issue/PLAT-205/bug-azure-instance-identity-verification-is-broken
2026-05-13 09:07:44 -07:00
Jakub Domeracki 1a1f06aa79 fix: verify PKCS7 signature on Azure instance identity tokens (#25286)
Migrates Azure instance identity verification from
`go.mozilla.org/pkcs7` and `github.com/fullsailor/pkcs7` to
`github.com/smallstep/pkcs7`, using `VerifyWithChainAtTime` to validate
both the PKCS7 signature and the certificate chain in one call. The
previous code only verified the signer certificate against a set of
intermediates/roots but did not verify that the PKCS7 signature itself
covered the content, meaning tampered payloads could be accepted.

The `Options` struct is restructured to accept `Roots`, `Intermediates`,
and `CurrentTime` as explicit fields instead of embedding
`x509.VerifyOptions`. The test helper `NewAzureInstanceIdentity` now
builds a realistic 3-level certificate chain (Root CA -> Intermediate CA
-> Signing Cert) matching real Azure trust hierarchy. New tests
(`TestValidate_TamperedContent`,
`TestValidate_UntrustedCertWithValidSignature`) confirm tampered and
untrusted envelopes are rejected.

Addresses GHSA-6x44-w3xg-hqqf.

> [!NOTE]
> This PR was authored by Coder Agents.

<details>
<summary>Implementation Plan</summary>

### Files Changed

| File | Summary |
|------|---------|
| `coderd/azureidentity/azureidentity.go` | Replace `signer.Verify()`
with `VerifyWithChainAtTime`; restructure `Options` struct; add
`ParseCertificates()` helper |
| `coderd/azureidentity/azureidentity_test.go` | Add `testCertChain`
builder, tampered-content and untrusted-cert tests; update existing
tests for new `Options` API |
| `coderd/coderd.go` | Change `AzureCertificates` field from
`x509.VerifyOptions` to `azureidentity.Options` |
| `coderd/workspaceresourceauth.go` | Pass `api.AzureCertificates`
directly instead of wrapping |
| `coderd/coderdtest/coderdtest.go` | Migrate to `smallstep/pkcs7`;
build 3-level cert chain in test helper |
| `go.mod` / `go.sum` | Add `github.com/smallstep/pkcs7`; remove
`fullsailor/pkcs7` and `go.mozilla.org/pkcs7` |

</details>
2026-05-13 14:14:07 +00:00
Jakub Domeracki 57b11d405f fix(coderd): harden Azure identity certificate fetch (#25274)
Security improvements:
- Restrict cert fetches to a host+port allowlist (Microsoft and DigiCert
on 80/443).
- Route requests through a dedicated `http.Client` that resolves the
host once and dials the validated IP directly, preventing DNS rebinding.
- Reject loopback, private (RFC 1918 / IPv6 ULA), link-local, multicast,
unspecified, CGNAT, benchmarking, and IPv4-mapped IPv6 addresses.
- Cap the certificate response body at 1 MiB.
- Log the underlying error via slog and return a generic detail to the
caller to prevent information disclosure.
2026-05-13 12:51:44 +02:00
Jakub Domeracki 9400eaa957 revert(coderd): "Merge commit from fork" (#25273)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:10:27 +02:00
Jakub Domeracki fb3aef1883 Merge commit from fork
* fix(coderd): Harden Azure identity certificate fetch

- Restrict cert fetches to a host+port allowlist (Microsoft and
  DigiCert on 80/443).
- Route requests through a dedicated `http.Client` that resolves
  the host once and dials the validated IP directly.
- Reject loopback, private (RFC 1918 / IPv6 ULA), link-local,
  multicast, unspecified, CGNAT, benchmarking, and IPv4-mapped
  IPv6 addresses.
- Cap the certificate response body at 1 MiB.
- Log the underlying error via slog and return a generic detail
  to the caller.
- Add unit tests for the URL allowlist, IP classification, and
  dialer.

* fix(coderd/azureidentity): add IPv6 special-use ranges to SSRF blocklist

The extraBlockedNetworks list only contained IPv4 CIDRs. Add IPv6
equivalents that Go's stdlib classification methods do not cover:

  - 64:ff9b:1::/48  RFC 8215 NAT64 translation
  - 100::/64         RFC 6666 discard-only
  - 2001:2::/48      RFC 5180 benchmarking
  - 2001:db8::/32    RFC 3849 documentation

IPv6 ranges already handled by stdlib (unchanged):

  - ::1/128   (IsLoopback)
  - fc00::/7  (IsPrivate, ULA)
  - fe80::/10 (IsLinkLocalUnicast)
  - ff00::/8  (IsMulticast)
  - ::/128    (IsUnspecified)
2026-05-13 11:55:41 +02:00
Kyle Carberry e3db203011 fix(coderd/azureidentity): set explicit roots to avoid macOS system verifier (#25136)
Fixes
[CODAGT-372](https://linear.app/codercom/issue/CODAGT-372/coderdazureidentity-testvalidateregular-fails-on-macos).
Closes coder/internal#101.

## Problem

`coderd/azureidentity TestValidate/regular` fails on macOS with:

```
verify signature:
    github.com/coder/coder/v2/coderd/azureidentity.Validate
        /Users/runner/work/coder/coder/coderd/azureidentity/azureidentity.go:75
  - x509: “metadata.azure.com” certificate is not standards compliant
```

When `crypto/x509.VerifyOptions.Roots` is `nil`, Go's verifier on
macOS/iOS falls back to the system verifier (`systemVerify` in
`crypto/x509/root_darwin.go`), which delegates to Apple's
`SecTrustEvaluateWithError`. Apple's framework enforces stricter
standards-compliance checks than Go's pure-Go verifier and rejects some
otherwise valid Azure instance-identity leaf certificates with
`errSecCertificateIsNotStandardsCompliant`, surfaced as the `not
standards compliant` error.

The test had been skipped on darwin since #12979 (April 2024) as a
workaround.

## Fix

- Embed the three root CAs that Azure instance-identity certificates
ultimately chain to:
  - DigiCert Global Root G2
  - DigiCert Global Root G3
- Baltimore CyberTrust Root (kept for historical chains via `Microsoft
RSA TLS CA 01/02`)
- In `Validate`, populate `options.Roots` from those embedded roots when
the caller does not supply its own pool. Because `Roots != nil`, Go no
longer takes the `systemVerify` path on darwin and uses the pure-Go
verifier on all platforms.
- Remove the `runtime.GOOS == "darwin"` skip from `TestValidate`.
- Add `TestEmbeddedRoots` to guard against future regressions in the
embedded root list (parses each PEM, asserts self-signed, requires all
three named roots).

The caller's existing `Intermediates` handling is unchanged. Tests that
pass their own `Roots` (e.g. `coderdtest.NewAzureInstanceIdentity`) are
unaffected.

## Verification

On Linux:

```
$ go test ./coderd/azureidentity/ -race -count=1 -v
=== RUN   TestValidate
=== RUN   TestValidate/regular
=== RUN   TestValidate/govcloud
=== RUN   TestValidate/rsa
--- PASS: TestValidate (0.00s)
    --- PASS: TestValidate/regular (0.00s)
    --- PASS: TestValidate/rsa (0.00s)
    --- PASS: TestValidate/govcloud (0.00s)
=== RUN   TestEmbeddedRoots
--- PASS: TestEmbeddedRoots (0.00s)
=== RUN   TestExpiresSoon
--- SKIP: TestExpiresSoon (0.00s)
PASS
ok      github.com/coder/coder/v2/coderd/azureidentity 1.020s
```

The `test-go-pg` job on `macos-latest` in CI is the authoritative
confirmation of the fix on macOS; previously it would have failed
`TestValidate/regular` had the skip been removed.

<details>
<summary>Why this is the correct fix</summary>

From `/usr/local/go/src/crypto/x509/verify.go`:

```go
// Use platform verifiers, where available, if Roots is from SystemCertPool.
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
    systemPool := systemRootsPool()
    if opts.Roots == nil && (systemPool == nil || systemPool.systemPool) {
        return c.systemVerify(&opts)
    }
    ...
}
```

Setting `opts.Roots` to any non-nil, non-system pool deterministically
routes verification through Go's pure-Go verifier, bypassing Apple's
stricter compliance checks. The embedded roots are sufficient to
validate every chain we currently care about, since every intermediate
in `Certificates` ultimately issues to one of the three embedded roots.

</details>

> Generated by Coder Agents. Reviewed manually.
2026-05-11 13:53:33 -04:00
Asher 871ed128aa chore: update azure certs (#21265) 2025-12-15 13:44:44 -09:00
ケイラ fae30a00fd chore: remove unnecessary redeclarations in for loops (#18440) 2025-06-20 13:16:55 -06:00
Kyle Carberry 79d73f77f5 chore: skip Azure TestExpiresSoon (#13385)
Adds some context to the test skip so it can be removed or enabled in the future.
2024-05-28 16:45:41 +00:00
Kyle Carberry 1b3185c047 chore: lower azure expires soon (#13097)
They haven't provisioned new certificates yet.
2024-04-29 12:34:18 -04:00
Kyle Carberry 8d1220e0c8 chore: add generate script for azure instance identity (#13028)
* chore: add generate script for azure instance identity

This also adds new issuing certificates from:
https://learn.microsoft.com/en-us/azure/security/fundamentals/azure-ca-details?tabs=certificate-authority-chains

* Fix shell lint

* Fix shell fmt

* Fix RSA issuing certificate
2024-04-22 15:39:08 -04:00
Colin Adler 942e90270e fix: disable azureidentity test on darwin (#12979)
See https://github.com/coder/coder/issues/12978
2024-04-16 19:33:04 +00:00
Danny Kopping d734f3fb74 chore: reduce azure CA cert validity check period to 2 months (#12788)
Signed-off-by: Danny Kopping <danny@coder.com>
2024-03-28 11:17:02 +02:00
Spike Curtis f28f340c7b fix: test for expiry 3 months on Azure certs (#11362) 2024-01-02 09:30:36 +04:00
Kyle Carberry 22e781eced chore: add /v2 to import module path (#9072)
* chore: add /v2 to import module path

go mod requires semantic versioning with versions greater than 1.x

This was a mechanical update by running:
```
go install github.com/marwan-at-work/mod/cmd/mod@latest
mod upgrade
```

Migrate generated files to import /v2

* Fix gen
2023-08-18 18:55:43 +00:00
Kyle Carberry d67552f852 fix: add more cached certificates to azure instance identity (#6519)
This was failing for GovCloud. Now it falls back to fetch, and a test
has been added to notify when certificates are becoming outdated.
2023-03-08 19:32:10 -06:00
Kyle Carberry 9ea21bf8ee fix: hardcode azure instance identity intermediate certificates (#6402)
This was broken for an airgapped customer!
2023-03-01 17:39:24 +00:00
Mathias Fredriksson 2bb9b4ac80 test: Fix azureidentity verification test (#6284) 2023-02-20 15:50:39 +00:00
Kyle Carberry b0fe9bcdd1 chore: Upgrade to Go 1.19 (#3617)
This is required as part of #3505.
2022-08-21 22:32:53 +00:00
Kyle Carberry c8246e3e8a feat: Add Azure instance identitity authentication (#1064)
This enables zero-trust authentication for Azure instances. Now
we support the three major clouds: AWS, Azure, and GCP 😎.
2022-04-19 13:48:13 +00:00