mirror of
https://github.com/azaion/admin.git
synced 2026-06-21 18:11:09 +00:00
c7b297de83
- Deleted the deploy.cmd script as it was no longer needed. - Updated Dockerfile to include curl for health checks and added a non-root user for improved security. - Modified health check command to use curl for better reliability. - Adjusted docker-compose.test.yml to reflect changes in health check configuration. - Cleaned up appsettings.json and removed unused configuration properties. - Removed Resource entity and related requests from the codebase as part of the architectural shift. - Updated documentation to reflect the removal of hardware binding and related endpoints. Co-authored-by: Cursor <cursoragent@cursor.com>
103 lines
7.1 KiB
Markdown
103 lines
7.1 KiB
Markdown
# Infrastructure & Configuration Review
|
|
|
|
**Date**: 2026-05-13
|
|
**Scope**: `Dockerfile`, `docker.test/Dockerfile`, `e2e/Dockerfile`, `docker-compose.test.yml`, `appsettings*.json`, `env/db/*.sql`, `.gitignore`, `.dockerignore`. No CI/CD pipeline files (`.github/workflows/`, `.gitlab-ci.yml`, `azure-pipelines.yml`) are present in this workspace.
|
|
|
|
## Container Security
|
|
|
|
### Production image (`Dockerfile`)
|
|
|
|
| Check | Result | Notes |
|
|
|-------|--------|-------|
|
|
| Non-root user | **FAIL** | No `USER` directive — runs as root. See F-6. |
|
|
| Minimal base image | PASS | `mcr.microsoft.com/dotnet/aspnet:10.0` (runtime-only) for the final stage; SDK image used only for build. |
|
|
| Multi-stage build | PASS | Build / publish / runtime stages cleanly separated. |
|
|
| No secrets in build args | PASS | Only `CI_COMMIT_SHA` (passed as `AZAION_REVISION` env at runtime) — non-sensitive. |
|
|
| Health check defined | PASS (compose layer) | `docker-compose.test.yml:42-51` defines a TCP health check; the production deployment must define an equivalent. **Not verified in this audit** because no production compose file exists in this workspace. |
|
|
| Image pinned by digest | **WARN** | Base images use `:10.0` tag, not `@sha256:...` digest. Tag floats — a poisoned upstream tag would be picked up on the next rebuild. Acceptable if the build runs from a controlled cache; otherwise pin. |
|
|
| `EXPOSE` matches Kestrel binding | PASS | `EXPOSE 8080`, `ASPNETCORE_URLS=http://+:8080`. |
|
|
|
|
### Test sidecar image (`docker.test/Dockerfile`)
|
|
|
|
```
|
|
FROM alpine:latest
|
|
CMD echo hello
|
|
```
|
|
|
|
This image is essentially a no-op stub. It's referenced from somewhere in the test/CI tooling but contributes nothing functional. **Recommendation**: either remove it (if nothing references it) or document its purpose. From a security standpoint it's inert — `alpine:latest` is fine for an `echo` and the floating tag is irrelevant for a stub. Flag as **operational hygiene, not a security finding**.
|
|
|
|
### E2E runner image (`e2e/Dockerfile`)
|
|
|
|
| Check | Result | Notes |
|
|
|-------|--------|-------|
|
|
| Non-root | **FAIL** (test-only) | Same root-by-default behavior. Test runner only — no exposed network, runs in an ephemeral container per CI run. **Acceptable.** |
|
|
| Uses SDK image as final | **WARN** (test-only) | Final stage is `mcr.microsoft.com/dotnet/sdk:10.0` — needed for `dotnet test`. SDK images carry more attack surface than runtime images, but this container is only reachable on the internal `e2e-net` bridge. **Acceptable for test-only.** |
|
|
|
|
## docker-compose.test.yml
|
|
|
|
| Check | Result | Notes |
|
|
|-------|--------|-------|
|
|
| Secrets via env vars (not committed prod secrets) | PASS (test-only) | The DB password, JWT secret, and master key are committed because this is the e2e harness only. F-10 captures the rule: these literals must never appear in a production compose file. |
|
|
| No port leaks | PASS | Only `8080:8080` is published from `system-under-test`; `test-db` is internal to the bridge. |
|
|
| Healthcheck for the API | PASS | TCP probe on `127.0.0.1:8080`. |
|
|
| Network isolation | PASS | All three services share `e2e-net` only; no `host` network mode. |
|
|
| Image lock | **WARN** (test-only) | `postgres:16-alpine` floats. For test reproducibility consider pinning a digest, but not security-critical for an ephemeral test stack. |
|
|
|
|
There is **no production `docker-compose.yml`** in this workspace. Any production deployment must:
|
|
- Inject `JwtConfig__Secret` and both `ConnectionStrings__*` values from a secret manager (Vault, AWS Secrets Manager, Azure Key Vault). (`ResourcesConfig__EncryptionMasterKey` was the third item here pre-revert; that field has since been deleted along with the OTA feature.)
|
|
- NOT carry over the `ASPNETCORE_ENVIRONMENT=Development` value used in the test compose — that environment value enables Swagger at the root path.
|
|
|
|
## Environment Configuration
|
|
|
|
### `Azaion.AdminApi/appsettings.json`
|
|
|
|
| Field | Value committed | Risk |
|
|
|-------|----------------|------|
|
|
| `Logging.LogLevel.*` | `Information` / `Warning` | OK |
|
|
| `AllowedHosts` | `"*"` | OK at the framework level — host filtering is normally enforced upstream by the reverse proxy. |
|
|
| `ResourcesConfig.ResourcesFolder` | `"Content"` | Relative path; resolves under the working directory inside the container. OK. |
|
|
| ~~`ResourcesConfig.EncryptionMasterKey`~~ | — | **Removed in the post-cycle-1 revert** along with the OTA feature; field no longer exists in `ResourcesConfig`, `appsettings.json`, or `docker-compose.test.yml`. Closes F-5 automatically. |
|
|
| `JwtConfig.{Issuer, Audience, TokenLifetimeHours}` | committed | Public-by-design (not secrets). |
|
|
| `JwtConfig.Secret` | **NOT committed** | Correct. Supplied via env var. |
|
|
| `ConnectionStrings.*` | **NOT committed** | Correct. Supplied via env var. |
|
|
|
|
### `Azaion.AdminApi/appsettings.Development.json`
|
|
|
|
Empty except for log levels — fine.
|
|
|
|
### `e2e/Azaion.E2E/appsettings.test.json`
|
|
|
|
Test-only. F-10 captures this; not a production concern.
|
|
|
|
## Secrets Hygiene
|
|
|
|
| Pattern | Where | Disposition |
|
|
|---------|-------|-------------|
|
|
| Plaintext DB passwords | `env/db/01_permissions.sql` | F-11 — operator template, not runtime. Add a header comment. |
|
|
| Plaintext DB / JWT / master-key in `docker-compose.test.yml` | `docker-compose.test.yml:31-37` | F-10 — test-only. CI guard recommended. |
|
|
| Plaintext admin/uploader passwords in `e2e/Azaion.E2E/appsettings.test.json` | as above | F-10 — test-only. |
|
|
| `.env` ignored | `.gitignore:10` | PASS |
|
|
| `bin/`, `obj/`, `logs/`, `Content/` ignored | `.gitignore:2-3, 7, 9` | PASS — keeps build artifacts and runtime data out of git. |
|
|
|
|
## CI/CD
|
|
|
|
No CI configuration files were found in the workspace (`.github/workflows/`, `.gitlab-ci.yml`, `azure-pipelines.yml`, `Jenkinsfile` — none present). Either:
|
|
- CI is configured outside this repo (e.g., upstream meta-repo), in which case the security guardrails (`dotnet list package --vulnerable`, secret-scanning, dependency-review) need to be verified there.
|
|
- Or there is no automated CI today, in which case this is a meta-finding: the dependency-bump (D-1) and the test suite have no automated gate. **Recommend**: introduce at least a `dotnet build && dotnet test && dotnet list package --vulnerable` job before deploy.
|
|
|
|
## Network Security
|
|
|
|
| Check | Status | Notes |
|
|
|-------|--------|-------|
|
|
| HTTPS enforcement in code | **FAIL** | F-13 — assumed at reverse proxy. |
|
|
| HSTS | not configured | Acceptable if reverse proxy injects it. |
|
|
| CORS | tight | `AdminCorsPolicy` whitelist-only (`https://admin.azaion.com`, `http://admin.azaion.com`). The plaintext `http://` origin can be removed once the SaaS UI is HTTPS-only. |
|
|
| Security headers | not configured in app | `X-Frame-Options`, `X-Content-Type-Options`, `Content-Security-Policy` not set in code. Reverse proxy responsibility today; document the assumption. |
|
|
|
|
## Self-verification
|
|
|
|
- [x] All Dockerfiles reviewed (`Dockerfile`, `docker.test/Dockerfile`, `e2e/Dockerfile`)
|
|
- [x] All compose files reviewed (`docker-compose.test.yml` — only one in repo)
|
|
- [x] All environment / config files reviewed (3 `appsettings*.json`)
|
|
- [x] CI/CD reviewed (none present in repo — surfaced as meta-finding)
|