diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..1a68db5e5 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ +## Goal + + +## Changes +- + +## Testing + + +## Checklist +- [ ] Title is a clear sentence (≀ 70 chars) +- [ ] Commits are signed (`git log --show-signature`) +- [ ] `submissions/labN.md` updated diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..4b8c3f89f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,128 @@ +name: ci + +on: + push: + branches: [main] + paths: + - 'app/**' + - '.github/workflows/**' + pull_request: + branches: [main] + paths: + - 'app/**' + - '.github/workflows/**' + +permissions: + contents: read + +env: + GOFLAGS: -buildvcs=false + +jobs: + changes: + name: changes + runs-on: ubuntu-24.04 + outputs: + app-go: ${{ steps.filter.outputs.app-go }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: filter + with: + filters: | + app-go: + - 'app/**/*.go' + - 'app/go.mod' + - 'app/go.sum' + - 'app/.golangci.yml' + + vet: + name: vet + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + go: ['1.23', '1.24'] + defaults: + run: + working-directory: app + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2 + with: + fetch-depth: 1 + - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + with: + go-version: ${{ matrix.go }} + cache: true + cache-dependency-path: app/go.mod + - run: go vet ./... + + test: + name: test + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + go: ['1.23', '1.24'] + defaults: + run: + working-directory: app + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2 + with: + fetch-depth: 1 + - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + with: + go-version: ${{ matrix.go }} + cache: true + cache-dependency-path: app/go.mod + - run: go test -race -count=1 ./... + + lint: + name: lint + needs: changes + if: needs.changes.outputs.app-go == 'true' + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2 + with: + fetch-depth: 1 + - uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 + with: + path: | + ~/.cache/golangci-lint + ~/go/bin + key: golangci-lint-${{ runner.os }}-v2.5.0-${{ hashFiles('app/.golangci.yml') }} + restore-keys: | + golangci-lint-${{ runner.os }}-v2.5.0- + - uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd # v7.0.0 + with: + version: v2.5.0 + working-directory: app + + govulncheck: + name: govulncheck + runs-on: ubuntu-24.04 + defaults: + run: + working-directory: app + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2 + with: + fetch-depth: 1 + - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + with: + go-version: '1.25.12' + cache: true + cache-dependency-path: app/go.mod + - run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4 + - run: govulncheck ./... + + ci-ok: + name: ci-ok + if: always() + needs: [vet, test, lint, govulncheck] + runs-on: ubuntu-24.04 + steps: + - run: | + test "${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}" = "false" diff --git a/.github/workflows/nix-repro.yml b/.github/workflows/nix-repro.yml new file mode 100644 index 000000000..6df539adf --- /dev/null +++ b/.github/workflows/nix-repro.yml @@ -0,0 +1,53 @@ +name: nix-repro + +on: + push: + branches: ['**'] + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + build-a: + name: nix-build-a + runs-on: ubuntu-24.04 + outputs: + digest: ${{ steps.hash.outputs.digest }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2 + + - uses: DeterminateSystems/nix-installer-action@90bb610b90bf290cad97484ba341453bd1cbefea # v19 + + - id: build + run: nix build .#docker --print-build-logs --print-out-paths > out-path.txt + + - id: hash + run: echo "digest=$(sha256sum "$(cat out-path.txt)" | awk '{print $1}')" >> "$GITHUB_OUTPUT" + + build-b: + name: nix-build-b + runs-on: ubuntu-24.04 + outputs: + digest: ${{ steps.hash.outputs.digest }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2 + + - uses: DeterminateSystems/nix-installer-action@90bb610b90bf290cad97484ba341453bd1cbefea # v19 + + - id: build + run: nix build .#docker --print-build-logs --print-out-paths > out-path.txt + + - id: hash + run: echo "digest=$(sha256sum "$(cat out-path.txt)" | awk '{print $1}')" >> "$GITHUB_OUTPUT" + + compare: + name: nix-repro-ok + needs: [build-a, build-b] + runs-on: ubuntu-24.04 + steps: + - run: | + echo "build-a: ${{ needs.build-a.outputs.digest }}" + echo "build-b: ${{ needs.build-b.outputs.digest }}" + test "${{ needs.build-a.outputs.digest }}" = "${{ needs.build-b.outputs.digest }}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..743757265 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,43 @@ +name: release + +on: + push: + tags: + - 'v*' + +permissions: + contents: read + packages: write + +env: + REGISTRY: ghcr.io + +jobs: + release: + name: release + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2 + + - id: image + run: | + repo="$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" + echo "name=ghcr.io/${repo}/quicknotes" >> "$GITHUB_OUTPUT" + + - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 + + - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: app + file: app/Dockerfile + platforms: linux/amd64 + push: true + tags: | + ${{ steps.image.outputs.name }}:${{ github.ref_name }} + ${{ steps.image.outputs.name }}:latest diff --git a/app/Dockerfile b/app/Dockerfile new file mode 100644 index 000000000..6580d2af1 --- /dev/null +++ b/app/Dockerfile @@ -0,0 +1,21 @@ +# syntax=docker/dockerfile:1 + +FROM golang:1.24-alpine AS builder +WORKDIR /src +COPY go.mod ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build \ + -trimpath \ + -ldflags='-s -w' \ + -o /quicknotes . + +FROM busybox:1.36-musl AS busybox + +FROM gcr.io/distroless/static-debian12:nonroot +COPY --from=builder /quicknotes /quicknotes +COPY --from=builder /src/seed.json /seed.json +COPY --from=busybox /bin/busybox /busybox +USER nonroot:nonroot +EXPOSE 8080 +ENTRYPOINT ["/quicknotes"] diff --git a/app/handlers.go b/app/handlers.go index c534979c5..5c5907a77 100644 --- a/app/handlers.go +++ b/app/handlers.go @@ -26,6 +26,10 @@ func NewServer(store *Store) *Server { return &Server{store: store, requestsByCode: by} } +func (s *Server) Handler() http.Handler { + return securityHeaders(s.Routes()) +} + func (s *Server) Routes() *http.ServeMux { mux := http.NewServeMux() mux.HandleFunc("GET /health", s.wrap(s.handleHealth)) diff --git a/app/handlers_test.go b/app/handlers_test.go index 9dff2e3e5..0919ddb71 100644 --- a/app/handlers_test.go +++ b/app/handlers_test.go @@ -31,7 +31,7 @@ func do(t *testing.T, srv *Server, method, target string, body any) *httptest.Re } req := httptest.NewRequest(method, target, &buf) rec := httptest.NewRecorder() - srv.Routes().ServeHTTP(rec, req) + srv.Handler().ServeHTTP(rec, req) return rec } @@ -131,3 +131,26 @@ func TestMetrics_ExposesPrometheusFormat(t *testing.T) { } } +func TestSecurityHeaders_PresentOnAllRoutes(t *testing.T) { + srv := newTestServer(t) + rec := do(t, srv, http.MethodGet, "/health", nil) + for _, key := range []string{ + "X-Content-Type-Options", + "X-Frame-Options", + "Content-Security-Policy", + "Referrer-Policy", + "Permissions-Policy", + "Cache-Control", + } { + if got := rec.Header().Get(key); got == "" { + t.Errorf("missing %s header", key) + } + } + if got := rec.Header().Get("X-Frame-Options"); got != "DENY" { + t.Errorf("X-Frame-Options: got %q want DENY", got) + } + if got := rec.Header().Get("Content-Security-Policy"); got != "default-src 'none'" { + t.Errorf("CSP: got %q want default-src 'none'", got) + } +} + diff --git a/app/main.go b/app/main.go index e258ffcfe..aa3dd9e7c 100644 --- a/app/main.go +++ b/app/main.go @@ -28,7 +28,7 @@ func main() { server := NewServer(store) srv := &http.Server{ Addr: addr, - Handler: server.Routes(), + Handler: server.Handler(), ReadHeaderTimeout: 5 * time.Second, } diff --git a/app/security.go b/app/security.go new file mode 100644 index 000000000..8efd5d537 --- /dev/null +++ b/app/security.go @@ -0,0 +1,18 @@ +package main + +import "net/http" + +// securityHeaders applies baseline HTTP security headers to every response. +func securityHeaders(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + h := w.Header() + h.Set("X-Content-Type-Options", "nosniff") + h.Set("X-Frame-Options", "DENY") + h.Set("Content-Security-Policy", "default-src 'none'") + h.Set("Referrer-Policy", "no-referrer") + h.Set("Permissions-Policy", "geolocation=(), microphone=(), camera=()") + h.Set("Cache-Control", "no-cache, no-store, must-revalidate, private") + h.Set("Pragma", "no-cache") + next.ServeHTTP(w, r) + }) +} diff --git a/cloud/hf-space/Dockerfile b/cloud/hf-space/Dockerfile new file mode 100644 index 000000000..661cbf272 --- /dev/null +++ b/cloud/hf-space/Dockerfile @@ -0,0 +1,4 @@ +# Pull the CI-built image (linux/amd64) instead of rebuilding in HF. +# Trade-off: faster Space builds and identical artifact to ghcr.io release; +# requires public package visibility on first push. +FROM ghcr.io/markovav-official/devops-intro/quicknotes:v0.1.0 diff --git a/cloud/hf-space/README.md b/cloud/hf-space/README.md new file mode 100644 index 000000000..db04154fe --- /dev/null +++ b/cloud/hf-space/README.md @@ -0,0 +1,19 @@ +--- +title: QuickNotes Lab 10 +emoji: πŸ“ +colorFrom: blue +colorTo: green +sdk: docker +app_port: 8080 +pinned: false +license: mit +--- + +# QuickNotes on Hugging Face Spaces + +DevOps Intro Lab 10 β€” same container image as [`ghcr.io/markovav-official/devops-intro/quicknotes`](https://github.com/markovav-official/DevOps-Intro/pkgs/container/devops-intro%2Fquicknotes). + +- `/health` β€” liveness +- `/notes` β€” JSON API + +Built from the course fork; image pushed by `.github/workflows/release.yml` on `v*` tags. diff --git a/cloud/scripts/lab12-vm-bench.sh b/cloud/scripts/lab12-vm-bench.sh new file mode 100644 index 000000000..d462650f8 --- /dev/null +++ b/cloud/scripts/lab12-vm-bench.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="${1:-/root/lab12-work/DevOps-Intro}" +OUT="${ROOT}/submissions/attachments/lab12" +export PATH="${HOME}/.nix-profile/bin:${HOME}/.wasmtime/bin:${PATH}" + +mkdir -p "${OUT}" + +cd "${ROOT}" + +# --- Lab 6 Docker baseline --- +if ! docker image inspect quicknotes:lab6 >/dev/null 2>&1; then + docker build -t quicknotes:lab6 ./app +fi +docker rm -f qn-lab6 2>/dev/null || true +docker run -d --name qn-lab6 -p 18080:8080 quicknotes:lab6 +trap 'docker rm -f qn-lab6 2>/dev/null; pkill -f "spin up" 2>/dev/null || true' EXIT + +for i in $(seq 1 30); do + if curl -fsS http://127.0.0.1:18080/health >/dev/null 2>&1; then break; fi + sleep 1 +done +curl -fsS http://127.0.0.1:18080/health | tee "${OUT}/docker-health.json" + +# --- Spin WASM --- +cd "${ROOT}/wasm" +if [[ ! -f main.wasm ]]; then + GOMAXPROCS=1 spin build 2>&1 | tee "${OUT}/spin-build.log" +else + echo "Reusing existing main.wasm" | tee "${OUT}/spin-build.log" +fi +ls -la main.wasm | tee "${OUT}/wasm-size.txt" +pkill -f "spin up" 2>/dev/null || true +sleep 1 +spin up --listen 127.0.0.1:3000 >/tmp/spin.log 2>&1 & +SPIN_PID=$! +sleep 2 +curl -fsS http://127.0.0.1:3000/time | python3 -m json.tool | tee "${OUT}/spin-time.json" + +# --- wasm-cli bonus --- +cd "${ROOT}/wasm-cli" +if [[ ! -f main.wasm ]]; then + GOMAXPROCS=1 tinygo build -o main.wasm -target=wasi -no-debug ./main.go 2>&1 | tee "${OUT}/wasm-cli-build.log" +else + echo "Reusing existing wasm-cli main.wasm" | tee "${OUT}/wasm-cli-build.log" +fi +ls -la main.wasm | tee -a "${OUT}/wasm-size.txt" +wasmtime run --env REQUEST_METHOD=GET --env PATH_INFO=/time main.wasm \ + | tee "${OUT}/wasm-cli-raw.txt" \ + | awk 'BEGIN{body=0} /^\r?$/ {body=1; next} body' \ + | python3 -m json.tool | tee "${OUT}/wasm-cli-time.json" + +# --- Sizes --- +{ + echo "=== Artifact sizes ===" + echo -n "main.wasm (spin): " + stat -c%s "${ROOT}/wasm/main.wasm" + echo -n "main.wasm (wasm-cli): " + stat -c%s "${ROOT}/wasm-cli/main.wasm" + echo -n "docker image: " + docker image inspect quicknotes:lab6 --format='{{.Size}}' +} | tee "${OUT}/sizes.txt" + +# --- Warm latency --- +hyperfine --warmup 5 --runs 50 --export-json "${OUT}/warm-spin.json" \ + 'curl -fsS http://127.0.0.1:3000/time >/dev/null' 2>&1 | tee "${OUT}/warm-spin.txt" + +hyperfine --warmup 5 --runs 50 --export-json "${OUT}/warm-docker.json" \ + 'curl -fsS http://127.0.0.1:18080/health >/dev/null' 2>&1 | tee "${OUT}/warm-docker.txt" + +# --- Cold start: Spin --- +{ + echo "=== Spin cold start (5 samples) ===" + for n in 1 2 3 4 5; do + pkill -f "spin up" 2>/dev/null || true + sleep 1 + start=$(date +%s%3N) + spin up --listen 127.0.0.1:3000 >/tmp/spin.log 2>&1 & + SPIN_PID=$! + for _ in $(seq 1 200); do + if curl -fsS http://127.0.0.1:3000/time >/dev/null 2>&1; then break; fi + sleep 0.05 + done + end=$(date +%s%3N) + echo "sample${n}: $((end - start)) ms" + done +} | tee "${OUT}/cold-spin.txt" + +# --- Cold start: Docker --- +{ + echo "=== Docker cold start (5 samples) ===" + for n in 1 2 3 4 5; do + docker rm -f qn-lab6 2>/dev/null || true + sleep 1 + start=$(date +%s%3N) + docker run -d --name qn-lab6 -p 18080:8080 quicknotes:lab6 >/dev/null + until curl -fsS http://127.0.0.1:18080/health >/dev/null 2>&1; do sleep 0.05; done + end=$(date +%s%3N) + echo "sample${n}: $((end - start)) ms" + done +} | tee "${OUT}/cold-docker.txt" + +# --- Cold start: wasmtime run (bonus) --- +{ + echo "=== wasmtime run cold (5 samples) ===" + cd "${ROOT}/wasm-cli" + for n in 1 2 3 4 5; do + start=$(date +%s%3N) + wasmtime run --env REQUEST_METHOD=GET --env PATH_INFO=/time main.wasm >/dev/null + end=$(date +%s%3N) + echo "sample${n}: $((end - start)) ms" + done +} | tee "${OUT}/cold-wasmtime.txt" + +echo "Benchmark artifacts written to ${OUT}" diff --git a/cloud/scripts/lab12-vm-cold.sh b/cloud/scripts/lab12-vm-cold.sh new file mode 100644 index 000000000..9847e8d31 --- /dev/null +++ b/cloud/scripts/lab12-vm-cold.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +set -euo pipefail +export PATH="${HOME}/.nix-profile/bin:${HOME}/.wasmtime/bin:${PATH}" +ROOT="${1:-/root/lab12-work/DevOps-Intro}" +OUT="${ROOT}/submissions/attachments/lab12" +mkdir -p "${OUT}" + +{ + echo "=== Spin cold start (5 samples) ===" + for n in 1 2 3 4 5; do + pkill -f "spin up" 2>/dev/null || true + sleep 1 + start=$(date +%s%3N) + spin up --listen 127.0.0.1:3000 >/tmp/spin.log 2>&1 & + for _ in $(seq 1 200); do + curl -fsS http://127.0.0.1:3000/time >/dev/null 2>&1 && break + sleep 0.05 + done + end=$(date +%s%3N) + echo "sample${n}: $((end - start)) ms" + done +} | tee "${OUT}/cold-spin.txt" + +{ + echo "=== Docker cold start (5 samples) ===" + for n in 1 2 3 4 5; do + docker rm -f qn-lab6 2>/dev/null || true + sleep 1 + start=$(date +%s%3N) + docker run -d --name qn-lab6 -p 18080:8080 quicknotes:lab6 >/dev/null + for _ in $(seq 1 200); do + curl -fsS http://127.0.0.1:18080/health >/dev/null 2>&1 && break + sleep 0.05 + done + end=$(date +%s%3N) + echo "sample${n}: $((end - start)) ms" + done +} | tee "${OUT}/cold-docker.txt" + +{ + echo "=== wasmtime run cold (5 samples) ===" + cd "${ROOT}/wasm-cli" + for n in 1 2 3 4 5; do + start=$(date +%s%3N) + wasmtime run --env REQUEST_METHOD=GET --env PATH_INFO=/time main.wasm >/dev/null + end=$(date +%s%3N) + echo "sample${n}: $((end - start)) ms" + done +} | tee "${OUT}/cold-wasmtime.txt" diff --git a/cloud/scripts/lab12-vm-setup.sh b/cloud/scripts/lab12-vm-setup.sh new file mode 100644 index 000000000..ac8b9a758 --- /dev/null +++ b/cloud/scripts/lab12-vm-setup.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +set -euo pipefail + +export DEBIAN_FRONTEND=noninteractive + +apt-get update -qq +apt-get install -y -qq curl wget hyperfine docker.io python3 git + +systemctl enable --now docker 2>/dev/null || service docker start + +if ! command -v spin >/dev/null; then + curl -fsSL https://github.com/spinframework/spin/releases/download/v3.4.0/spin-v3.4.0-linux-amd64.tar.gz \ + | tar -xz -C /usr/local/bin spin +fi + +if ! command -v tinygo >/dev/null; then + wget -q -O /tmp/tinygo.deb https://github.com/tinygo-org/tinygo/releases/download/v0.41.0/tinygo_0.41.0_amd64.deb + dpkg -i /tmp/tinygo.deb || apt-get install -f -y -qq +fi + +if ! command -v wasmtime >/dev/null; then + curl -fsSL https://wasmtime.dev/install.sh | bash -s -- --version v29.0.0 +fi + +export PATH="${HOME}/.wasmtime/bin:${PATH}" + +spin --version +tinygo version +wasmtime --version +hyperfine --version +docker --version diff --git a/cloud/scripts/measure-cold.sh b/cloud/scripts/measure-cold.sh new file mode 100755 index 000000000..6189435e5 --- /dev/null +++ b/cloud/scripts/measure-cold.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Single request after idle sleep β€” use between runs when Space is sleeping. +set -euo pipefail + +URL="${1:?usage: $0 }" +PATH_SUFFIX="${2:-/health}" +TARGET="${URL%/}${PATH_SUFFIX}" + +curl -w 'time_total=%{time_total}s http_code=%{http_code}\n' -o /dev/null -s "$TARGET" diff --git a/cloud/scripts/measure-warm.sh b/cloud/scripts/measure-warm.sh new file mode 100755 index 000000000..b592dcae4 --- /dev/null +++ b/cloud/scripts/measure-warm.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# Warm latency: 5 consecutive requests, print times and p50 (median). +set -euo pipefail + +URL="${1:?usage: $0 }" +PATH_SUFFIX="${2:-/health}" +TARGET="${URL%/}${PATH_SUFFIX}" + +times=() +for _ in 1 2 3 4 5; do + t=$(curl -w '%{time_total}' -o /dev/null -s "$TARGET") + times+=("$t") + printf '%s\n' "$t" +done + +python3 - <<'PY' "${times[@]}" +import statistics, sys +vals = [float(x) for x in sys.argv[1:]] +print(f"p50: {statistics.median(vals):.4f}s") +PY diff --git a/cloud/scripts/tunnel-hyperfine.sh b/cloud/scripts/tunnel-hyperfine.sh new file mode 100755 index 000000000..62032703d --- /dev/null +++ b/cloud/scripts/tunnel-hyperfine.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Bonus: warm p50/p95 via hyperfine (50 runs) against a public tunnel URL. +set -euo pipefail + +URL="${1:?usage: $0 }" +TARGET="${URL%/}/health" + +command -v hyperfine >/dev/null || { echo "install hyperfine: brew install hyperfine"; exit 1; } + +hyperfine --warmup 5 --runs 50 --export-json /dev/stdout \ + "curl -fsS -o /dev/null $TARGET" | python3 -c " +import json, sys, statistics +d = json.load(sys.stdin) +t = [r['times'][0] for r in d['results']] +t.sort() +n = len(t) +p50 = t[n//2] +p95 = t[int(n*0.95)-1] +print(f'p50: {p50:.4f}s') +print(f'p95: {p95:.4f}s') +" diff --git a/cloud/teardown.md b/cloud/teardown.md new file mode 100644 index 000000000..5a0200d74 --- /dev/null +++ b/cloud/teardown.md @@ -0,0 +1,22 @@ +# Teardown + +## Hugging Face Space + +1. Open [huggingface.co/spaces](https://huggingface.co/spaces) β†’ your Space β†’ **Settings**. +2. Scroll to **Delete this Space** β†’ confirm. + +## ghcr.io package + +The image stays in GitHub Packages (free). To remove: + +1. Repo β†’ **Packages** β†’ `devops-intro/quicknotes` β†’ **Package settings** β†’ **Delete package**. + +## Cloudflare quick tunnel + +Stop the `cloudflared` process (`Ctrl+C`). The `*.trycloudflare.com` URL is discarded automatically. + +## Local containers + +```bash +docker compose down +``` diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 000000000..2d226ca15 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,72 @@ +services: + volume-init: + image: busybox:1.36-musl + volumes: + - quicknotes-data:/data + command: ["sh", "-c", "chown 65532:65532 /data"] + restart: "no" + + quicknotes: + build: + context: ./app + dockerfile: Dockerfile + image: quicknotes:lab6 + depends_on: + volume-init: + condition: service_completed_successfully + ports: + - "8080:8080" + environment: + ADDR: ":8080" + DATA_PATH: "/data/notes.json" + SEED_PATH: "/seed.json" + volumes: + - quicknotes-data:/data + restart: unless-stopped + healthcheck: + test: ["CMD", "/busybox", "wget", "-qO-", "http://127.0.0.1:8080/health"] + interval: 5s + timeout: 3s + retries: 3 + start_period: 10s + read_only: true + cap_drop: + - ALL + security_opt: + - no-new-privileges:true + tmpfs: + - /tmp + + prometheus: + image: prom/prometheus:v3.2.1 + ports: + - "9090:9090" + volumes: + - ./monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro + - ./monitoring/prometheus/alert.rules.yml:/etc/prometheus/alert.rules.yml:ro + command: + - --config.file=/etc/prometheus/prometheus.yml + - --storage.tsdb.path=/prometheus + - --web.enable-lifecycle + depends_on: + quicknotes: + condition: service_healthy + restart: unless-stopped + + grafana: + image: grafana/grafana:13.0.2 + ports: + - "3000:3000" + environment: + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: lab8-grafana-dev + GF_USERS_ALLOW_SIGN_UP: "false" + volumes: + - ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro + - ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards:ro + depends_on: + - prometheus + restart: unless-stopped + +volumes: + quicknotes-data: diff --git a/docs/runbook/high-error-rate.md b/docs/runbook/high-error-rate.md new file mode 100644 index 000000000..28d467208 --- /dev/null +++ b/docs/runbook/high-error-rate.md @@ -0,0 +1,26 @@ +# High HTTP Error Rate + +## What this alert means + +More than 5% of QuickNotes HTTP responses are 4xx or 5xx for at least five minutes β€” users are seeing failures at a rate worth paging on. + +## Triage steps + +1. **Confirm the alert** β€” open Grafana dashboard *QuickNotes Golden Signals* (or Prometheus `/alerts`) and verify the error panel is elevated, not a scrape glitch. Check `curl -s http://localhost:9090/api/v1/targets` shows `quicknotes` target `up`. +2. **Check QuickNotes health** β€” `curl -s http://localhost:8080/health | jq` and `docker compose logs quicknotes --tail=50` for panics, permission errors on `/data/notes.json`, or OOM kills. +3. **Identify error type** β€” in Prometheus/Grafana, break down `quicknotes_http_responses_by_code_total` by `code` label. Dominant `400` suggests bad client payloads; `500` suggests application or storage failure. +4. **Check recent changes** β€” `docker compose ps`, recent deploys, volume mount issues, or config/env drift (`ADDR`, `DATA_PATH`, `SEED_PATH`). + +## Mitigations + +1. **Restart the service** β€” `docker compose restart quicknotes` (fastest way to clear a wedged process; data persists on the named volume). +2. **Roll back bad traffic** β€” if a client or load script is sending malformed requests, stop or fix it; scale down the offending job. +3. **Restore from known-good state** β€” if data corruption is suspected, stop QuickNotes, restore `/data/notes.json` from backup or re-seed, then `docker compose up -d quicknotes`. + +## Post-incident + +After the error rate returns to normal and the alert clears: + +- Write a blameless postmortem using the [Lecture 1 postmortem template](https://github.com/inno-devops-labs/DevOps-Intro/blob/main/lectures/lec1.md) (timeline, root cause, action items). +- Add or tune alerts/runbooks if the failure mode was not covered. +- Track follow-up tasks (fix validation, add integration test, improve dashboard panel) in your issue tracker. diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..032fb8b8e --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1751274312, + "narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..d64035ccd --- /dev/null +++ b/flake.nix @@ -0,0 +1,69 @@ +{ + description = "QuickNotes β€” reproducible Go binary and OCI image (Lab 11)"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + quicknotes = pkgs.buildGoModule { + pname = "quicknotes"; + version = "0.1.0"; + src = ./app; + + vendorHash = null; + + # nixos-24.11 ships Go 1.23; patch only inside the Nix sandbox. + postPatch = '' + substituteInPlace go.mod --replace-fail 'go 1.24' 'go 1.23' + ''; + + CGO_ENABLED = 0; + ldflags = [ "-s" "-w" ]; + }; + + imageRoot = pkgs.runCommand "quicknotes-image-root" {} '' + mkdir -p $out/data + cp ${quicknotes}/bin/quicknotes $out/quicknotes + cp ${./app/seed.json} $out/seed.json + ''; + in { + packages.quicknotes = quicknotes; + packages.default = quicknotes; + + packages.docker = pkgs.dockerTools.buildImage { + name = "quicknotes"; + tag = "nix"; + # CI red demo: job A sets SOURCE_DATE_EPOCH=0 and runs `nix build --impure`. + # Pure builds (green) ignore host env and keep the nixpkgs default second. + created = + if builtins.getEnv "SOURCE_DATE_EPOCH" == "0" then + "1970-01-01T00:00:00Z" + else + "1970-01-01T00:00:01Z"; + copyToRoot = imageRoot; + config = { + Entrypoint = [ "/quicknotes" ]; + ExposedPorts = { "8080/tcp" = {}; }; + User = "65532:65532"; + Env = [ + "ADDR=:8080" + "DATA_PATH=/data/notes.json" + "SEED_PATH=/seed.json" + ]; + }; + }; + + devShells.default = pkgs.mkShell { + packages = with pkgs; [ + go_1_24 + gopls + golangci-lint + ]; + }; + }); +} diff --git a/monitoring/grafana/dashboards/golden-signals.json b/monitoring/grafana/dashboards/golden-signals.json new file mode 100644 index 000000000..03339efab --- /dev/null +++ b/monitoring/grafana/dashboards/golden-signals.json @@ -0,0 +1,188 @@ +{ + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "expr": "rate(quicknotes_http_requests_total[5m])", + "legendFormat": "req/s (latency proxy β€” no histogram exposed)", + "refId": "A" + } + ], + "title": "Latency (request-rate proxy)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "expr": "sum(rate(quicknotes_http_requests_total[5m]))", + "legendFormat": "total req/s", + "refId": "A" + } + ], + "title": "Traffic", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "max": 100, + "min": 0, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 3, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "expr": "100 * sum(rate(quicknotes_http_responses_by_code_total{code=~\"4..|5..\"}[5m])) / clamp_min(sum(rate(quicknotes_http_requests_total[5m])), 0.001)", + "legendFormat": "error %", + "refId": "A" + } + ], + "title": "Errors", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 4, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "expr": "quicknotes_notes_total", + "legendFormat": "notes stored", + "refId": "A" + } + ], + "title": "Saturation (notes stored)", + "type": "timeseries" + } + ], + "refresh": "10s", + "schemaVersion": 39, + "tags": [ + "quicknotes", + "golden-signals" + ], + "time": { + "from": "now-15m", + "to": "now" + }, + "timezone": "browser", + "title": "QuickNotes Golden Signals", + "uid": "quicknotes-golden-signals", + "version": 1 +} diff --git a/monitoring/grafana/provisioning/dashboards/dashboard.yml b/monitoring/grafana/provisioning/dashboards/dashboard.yml new file mode 100644 index 000000000..9df61ce46 --- /dev/null +++ b/monitoring/grafana/provisioning/dashboards/dashboard.yml @@ -0,0 +1,12 @@ +apiVersion: 1 + +providers: + - name: golden-signals + orgId: 1 + folder: QuickNotes + type: file + disableDeletion: false + updateIntervalSeconds: 30 + allowUiUpdates: true + options: + path: /var/lib/grafana/dashboards diff --git a/monitoring/grafana/provisioning/datasources/datasource.yml b/monitoring/grafana/provisioning/datasources/datasource.yml new file mode 100644 index 000000000..8704d9e54 --- /dev/null +++ b/monitoring/grafana/provisioning/datasources/datasource.yml @@ -0,0 +1,10 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + uid: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + editable: false diff --git a/monitoring/prometheus/alert.rules.yml b/monitoring/prometheus/alert.rules.yml new file mode 100644 index 000000000..98610db38 --- /dev/null +++ b/monitoring/prometheus/alert.rules.yml @@ -0,0 +1,17 @@ +groups: + - name: quicknotes + rules: + - alert: HighHTTPErrorRate + expr: | + ( + sum(rate(quicknotes_http_responses_by_code_total{code=~"4..|5.."}[5m])) + / + clamp_min(sum(rate(quicknotes_http_requests_total[5m])), 0.001) + ) > 0.05 + for: 5m + labels: + severity: page + annotations: + summary: QuickNotes HTTP error ratio exceeds 5% + runbook_url: docs/runbook/high-error-rate.md + description: More than 5% of HTTP responses are 4xx/5xx for 5 minutes. diff --git a/monitoring/prometheus/prometheus.yml b/monitoring/prometheus/prometheus.yml new file mode 100644 index 000000000..96bc747d4 --- /dev/null +++ b/monitoring/prometheus/prometheus.yml @@ -0,0 +1,13 @@ +global: + scrape_interval: 15s + evaluation_interval: 15s + +rule_files: + - /etc/prometheus/alert.rules.yml + +scrape_configs: + - job_name: quicknotes + static_configs: + - targets: + - quicknotes:8080 + metrics_path: /metrics diff --git a/scripts/lab8-capture-evidence.sh b/scripts/lab8-capture-evidence.sh new file mode 100755 index 000000000..f8e32bac7 --- /dev/null +++ b/scripts/lab8-capture-evidence.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Capture Lab 8 evidence after `docker compose up -d`. +set -euo pipefail +cd "$(dirname "$0")/.." +ATT=submissions/attachments/lab8 +mkdir -p "$ATT" + +docker compose ps | tee "$ATT/compose-ps.txt" +curl -s http://localhost:9090/api/v1/targets | python3 -m json.tool | tee "$ATT/prometheus-targets.json" +curl -s http://localhost:9090/api/v1/targets | python3 -c "import sys,json; d=json.load(sys.stdin); print([t['health'] for t in d['data']['activeTargets']])" | tee "$ATT/targets-health.txt" +curl -s -u admin:lab8-grafana-dev http://localhost:3000/api/search?query=Golden | tee "$ATT/grafana-dashboard-search.json" +curl -s http://localhost:9090/api/v1/alerts | python3 -m json.tool | tee "$ATT/prometheus-alerts.json" +echo "Evidence captured in $ATT" diff --git a/scripts/lab8-generate-traffic.sh b/scripts/lab8-generate-traffic.sh new file mode 100755 index 000000000..b7c6b37d7 --- /dev/null +++ b/scripts/lab8-generate-traffic.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Generate ~200 mixed requests for Lab 8 Task 1 dashboard traffic. +set -euo pipefail +BASE="${1:-http://localhost:8080}" +OUT="${2:-submissions/attachments/lab8/traffic-gen.log}" + +echo "Generating traffic against $BASE" | tee "$OUT" +for i in $(seq 1 200); do + case $((i % 5)) in + 0) curl -s "$BASE/health" >>"$OUT" ;; + 1) curl -s "$BASE/notes" >>"$OUT" ;; + 2) curl -s -X POST "$BASE/notes" -H 'Content-Type: application/json' \ + -d '{"title":"load","body":"traffic"}' >>"$OUT" ;; + 3) curl -s "$BASE/notes/1" >>"$OUT" ;; + 4) curl -s -X POST "$BASE/notes" -H 'Content-Type: application/json' -d '{"bad":true}' >>"$OUT" ;; + esac +done +echo "done 200 requests" | tee -a "$OUT" diff --git a/scripts/lab8-trigger-alert.sh b/scripts/lab8-trigger-alert.sh new file mode 100755 index 000000000..6a3a05578 --- /dev/null +++ b/scripts/lab8-trigger-alert.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Sustained error injection for Lab 8 Task 2 (run β‰₯6 minutes for 5m alert). +set -euo pipefail +BASE="${1:-http://localhost:8080}" +DURATION="${2:-360}" +OUT="${3:-submissions/attachments/lab8/alert-trigger.log}" + +echo "Error injection started $(date -u +%Y-%m-%dT%H:%M:%SZ)" | tee "$OUT" +end=$((SECONDS + DURATION)) +while [ "$SECONDS" -lt "$end" ]; do + curl -s "$BASE/health" >/dev/null + curl -s "$BASE/notes" >/dev/null + curl -s -X POST "$BASE/notes" -H 'Content-Type: application/json' -d '{"bad":true}' >/dev/null + sleep 0.5 +done +echo "Error injection finished $(date -u +%Y-%m-%dT%H:%M:%SZ)" | tee -a "$OUT" diff --git a/submissions/attachments/lab10/comparison-vm.txt b/submissions/attachments/lab10/comparison-vm.txt new file mode 100644 index 000000000..f49f31f38 --- /dev/null +++ b/submissions/attachments/lab10/comparison-vm.txt @@ -0,0 +1,21 @@ +# Warm latency β€” 5 consecutive curl requests from University VM + +## HF Spaces (https://markovav-devops-intro.hf.space/health) +0.721615 +0.648529 +0.650473 +0.752180 +0.587449 +p50: 0.6505s +p95: 0.7216s + +## Cloudflare Tunnel (https://tenant-voting-composer-highly.trycloudflare.com/health) +0.565016 +0.342548 +0.391951 +0.370219 +60.530293 +p50: 0.3920s +p95: 0.5650s + +# Tunnel run #5 spike (~60s) β€” likely cloudflared/Mac uplink blip; p50/p95 use all 5 samples. diff --git a/submissions/attachments/lab10/docker-pull.txt b/submissions/attachments/lab10/docker-pull.txt new file mode 100644 index 000000000..5b264a247 --- /dev/null +++ b/submissions/attachments/lab10/docker-pull.txt @@ -0,0 +1,12 @@ +$ docker rmi ghcr.io/markovav-official/devops-intro/quicknotes:v0.1.0 2>/dev/null || true +$ docker pull --platform linux/amd64 ghcr.io/markovav-official/devops-intro/quicknotes:v0.1.0 +v0.1.0: Pulling from markovav-official/devops-intro/quicknotes +2baffef0768b: Pull complete +561e2a537016: Pull complete +15d4e2e513f5: Pull complete +Digest: sha256:f540e365de05543453674d4cdc48e61111e1c2459da295a258ea9b7a63010544 +Status: Downloaded newer image for ghcr.io/markovav-official/devops-intro/quicknotes:v0.1.0 +ghcr.io/markovav-official/devops-intro/quicknotes:v0.1.0 + +# Image is linux/amd64 only (CI release workflow). On arm64 host use --platform linux/amd64 +# (matches HF Spaces builders). diff --git a/submissions/attachments/lab10/hf-cold.txt b/submissions/attachments/lab10/hf-cold.txt new file mode 100644 index 000000000..5da449b72 --- /dev/null +++ b/submissions/attachments/lab10/hf-cold.txt @@ -0,0 +1,5 @@ +time_total=1.238s http_code=200 +time_total=2.084s http_code=200 +time_total=1.871s http_code=200 + +# avg: 1.73s (after ~40 min idle; image cached on HF builders) diff --git a/submissions/attachments/lab10/hf-health.txt b/submissions/attachments/lab10/hf-health.txt new file mode 100644 index 000000000..02fef8939 --- /dev/null +++ b/submissions/attachments/lab10/hf-health.txt @@ -0,0 +1,10 @@ +* Connected to markovav-devops-intro.hf.space (52.48.128.222) port 443 +> GET /health HTTP/2 +> Host: markovav-devops-intro.hf.space +< HTTP/2 200 +< content-type: application/json +< cache-control: no-cache, no-store, must-revalidate, private +< content-security-policy: default-src 'none' +< x-content-type-options: nosniff +< x-frame-options: DENY +{"notes":0,"status":"ok"} diff --git a/submissions/attachments/lab10/hf-warm.txt b/submissions/attachments/lab10/hf-warm.txt new file mode 100644 index 000000000..7218eff43 --- /dev/null +++ b/submissions/attachments/lab10/hf-warm.txt @@ -0,0 +1,6 @@ +0.970229 +1.039932 +0.773275 +0.900680 +0.812027 +p50: 0.9007s diff --git a/submissions/attachments/lab10/tunnel-curl.txt b/submissions/attachments/lab10/tunnel-curl.txt new file mode 100644 index 000000000..3f35a3e3a --- /dev/null +++ b/submissions/attachments/lab10/tunnel-curl.txt @@ -0,0 +1,17 @@ +# curl from University VM β€” different network than Mac running cloudflared +# URL: https://tenant-voting-composer-highly.trycloudflare.com/health + +* Connected to tenant-voting-composer-highly.trycloudflare.com (104.16.231.132) port 443 +> GET /health HTTP/2 +> Host: tenant-voting-composer-highly.trycloudflare.com +< HTTP/2 200 +< server: cloudflare +< cf-ray: a179ed132c12bb02-ARN +< content-type: application/json +< cache-control: no-cache, no-store, must-revalidate, private +< content-security-policy: default-src 'none' +< x-content-type-options: nosniff +< x-frame-options: DENY +{"notes":44,"status":"ok"} + +# Total time (first request, includes TLS + cold path): ~15s diff --git a/submissions/attachments/lab11/docker-lab6-compare.txt b/submissions/attachments/lab11/docker-lab6-compare.txt new file mode 100644 index 000000000..6ad6931f2 --- /dev/null +++ b/submissions/attachments/lab11/docker-lab6-compare.txt @@ -0,0 +1,7 @@ +$ docker build --no-cache -t qn-lab6:run1 ./app +$ docker build --no-cache -t qn-lab6:run2 ./app +$ docker images --no-trunc qn-lab6 + +REPOSITORY TAG IMAGE ID SIZE +qn-lab6 run2 sha256:fbcdbd2e78cedf9b7e904f11b561c388b28abd5f75e396baa851a102aca0df12 16MB +qn-lab6 run1 sha256:01073da0688e9b8a22df65b857da54bf64d4b7fda60234cc7d821485e8da3ce8 16MB diff --git a/submissions/attachments/lab11/nix-build-quicknotes.log b/submissions/attachments/lab11/nix-build-quicknotes.log new file mode 100644 index 000000000..15ca2f3fa --- /dev/null +++ b/submissions/attachments/lab11/nix-build-quicknotes.log @@ -0,0 +1,13 @@ +building '/nix/store/c2084xfai8pv8zylc209398qg136ly09-quicknotes-0.1.0.drv'... +quicknotes> Running phase: buildPhase +quicknotes> Building subPackage . +quicknotes> Running phase: checkPhase +quicknotes> ok quicknotes 0.009s +quicknotes> Running phase: installPhase +quicknotes> Running phase: fixupPhase + +# store hash (env A & B identical): +sha256:1xh9z7n1ax8hbissdcr7ivj2zcx56fhb1aj4i1l7hs5axq29xrym + +# health: +curl http://127.0.0.1:18080/health -> {"notes":4,"status":"ok"} diff --git a/submissions/attachments/lab11/nix-docker-digests.txt b/submissions/attachments/lab11/nix-docker-digests.txt new file mode 100644 index 000000000..b0a6be745 --- /dev/null +++ b/submissions/attachments/lab11/nix-docker-digests.txt @@ -0,0 +1,6 @@ +# nix build .#docker (University VM, two independent checkouts) + +env A: 28db2a32677bb3eb3c133ec33072ff4ad4350ea67d4445b30c422a349bd24874 +env B: 28db2a32677bb3eb3c133ec33072ff4ad4350ea67d4445b30c422a349bd24874 + +image size: 2.9M (docker-image-quicknotes.tar.gz) diff --git a/submissions/attachments/lab12/.gitkeep b/submissions/attachments/lab12/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/submissions/attachments/lab12/cold-docker.txt b/submissions/attachments/lab12/cold-docker.txt new file mode 100644 index 000000000..8fcb34c01 --- /dev/null +++ b/submissions/attachments/lab12/cold-docker.txt @@ -0,0 +1,10 @@ +=== Docker cold start (5 samples) === +sample1: 1429 ms +qn-lab6 +sample2: 1411 ms +qn-lab6 +sample3: 1246 ms +qn-lab6 +sample4: 1443 ms +qn-lab6 +sample5: 1564 ms diff --git a/submissions/attachments/lab12/cold-spin.txt b/submissions/attachments/lab12/cold-spin.txt new file mode 100644 index 000000000..4a1a4c32f --- /dev/null +++ b/submissions/attachments/lab12/cold-spin.txt @@ -0,0 +1,6 @@ +=== Spin cold start (5 samples) === +sample1: 12936 ms +sample2: 12975 ms +sample3: 12779 ms +sample4: 13008 ms +sample5: 12954 ms diff --git a/submissions/attachments/lab12/cold-wasmtime.txt b/submissions/attachments/lab12/cold-wasmtime.txt new file mode 100644 index 000000000..2a1ee2537 --- /dev/null +++ b/submissions/attachments/lab12/cold-wasmtime.txt @@ -0,0 +1,6 @@ +=== wasmtime run cold (5 samples) === +sample1: 16 ms +sample2: 12 ms +sample3: 12 ms +sample4: 11 ms +sample5: 12 ms diff --git a/submissions/attachments/lab12/docker-health.json b/submissions/attachments/lab12/docker-health.json new file mode 100644 index 000000000..6a54507f9 --- /dev/null +++ b/submissions/attachments/lab12/docker-health.json @@ -0,0 +1 @@ +{"notes":0,"status":"ok"} diff --git a/submissions/attachments/lab12/sizes.txt b/submissions/attachments/lab12/sizes.txt new file mode 100644 index 000000000..2c2eaeb07 --- /dev/null +++ b/submissions/attachments/lab12/sizes.txt @@ -0,0 +1,4 @@ +=== Artifact sizes === +main.wasm (spin): 362115 +main.wasm (wasm-cli): 196781 +docker image: 3979676 diff --git a/submissions/attachments/lab12/spin-build.log b/submissions/attachments/lab12/spin-build.log new file mode 100644 index 000000000..ae6738fb8 --- /dev/null +++ b/submissions/attachments/lab12/spin-build.log @@ -0,0 +1 @@ +Reusing existing main.wasm diff --git a/submissions/attachments/lab12/spin-time.json b/submissions/attachments/lab12/spin-time.json new file mode 100644 index 000000000..c0248f106 --- /dev/null +++ b/submissions/attachments/lab12/spin-time.json @@ -0,0 +1,7 @@ +{ + "unix": 1783548307, + "iso": "2026-07-08T22:05:07Z", + "hour_minute": "22:05", + "moscow": "2026-07-08 22:05:07", + "tz": "UTC+3" +} diff --git a/submissions/attachments/lab12/warm-docker.json b/submissions/attachments/lab12/warm-docker.json new file mode 100644 index 000000000..6e251f069 --- /dev/null +++ b/submissions/attachments/lab12/warm-docker.json @@ -0,0 +1,118 @@ +{ + "results": [ + { + "command": "curl -fsS http://127.0.0.1:18080/health >/dev/null", + "mean": 0.007140602180000002, + "stddev": 0.00035904002724406733, + "median": 0.00705450644, + "user": 0.0032540800000000003, + "system": 0.00331162, + "min": 0.006568857440000001, + "max": 0.00813835544, + "times": [ + 0.00784885644, + 0.007340655440000001, + 0.00787775644, + 0.00739185544, + 0.007295756440000001, + 0.0073276554400000015, + 0.00776035644, + 0.007162755440000001, + 0.007158556440000001, + 0.00716515644, + 0.007019256440000001, + 0.007217955440000001, + 0.00723255644, + 0.00763315544, + 0.00727845644, + 0.00682095644, + 0.00698865644, + 0.00690545544, + 0.00691895644, + 0.006912056440000001, + 0.00703335644, + 0.006664156440000001, + 0.007273256440000001, + 0.0072787554400000004, + 0.00685265644, + 0.006956256440000001, + 0.00712365644, + 0.00686515544, + 0.00699105644, + 0.0071121564400000005, + 0.00783125544, + 0.00813835544, + 0.00804045644, + 0.00726155544, + 0.006944856440000001, + 0.006833456440000001, + 0.007230356440000001, + 0.00716105544, + 0.0069031564400000005, + 0.006809456440000001, + 0.00670705644, + 0.006807856440000001, + 0.00678825644, + 0.006975256440000001, + 0.006568857440000001, + 0.006794655440000001, + 0.006966356440000001, + 0.0070756564400000005, + 0.00686785644, + 0.00691705644 + ], + "exit_codes": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ] +} diff --git a/submissions/attachments/lab12/warm-docker.txt b/submissions/attachments/lab12/warm-docker.txt new file mode 100644 index 000000000..4edf8dab1 --- /dev/null +++ b/submissions/attachments/lab12/warm-docker.txt @@ -0,0 +1,4 @@ +Benchmark 1: curl -fsS http://127.0.0.1:18080/health >/dev/null + Time (mean Β± Οƒ): 7.1 ms Β± 0.4 ms [User: 3.3 ms, System: 3.3 ms] + Range (min … max): 6.6 ms … 8.1 ms 50 runs + diff --git a/submissions/attachments/lab12/warm-spin.json b/submissions/attachments/lab12/warm-spin.json new file mode 100644 index 000000000..57b07cbfc --- /dev/null +++ b/submissions/attachments/lab12/warm-spin.json @@ -0,0 +1,118 @@ +{ + "results": [ + { + "command": "curl -fsS http://127.0.0.1:3000/time >/dev/null", + "mean": 0.009473932899999999, + "stddev": 0.0012700844782855428, + "median": 0.00938455266, + "user": 0.00325314, + "system": 0.0040676919999999995, + "min": 0.00788580466, + "max": 0.01647019966, + "times": [ + 0.009161802660000001, + 0.008994303660000001, + 0.009651902660000001, + 0.009443902660000001, + 0.00954540266, + 0.00955420266, + 0.00959030366, + 0.00936850266, + 0.009398102660000001, + 0.00982910266, + 0.00932840366, + 0.00970820266, + 0.00968300266, + 0.010544401660000001, + 0.01053790266, + 0.01027080266, + 0.00984460266, + 0.00987840266, + 0.01028150266, + 0.010020202660000001, + 0.01046010166, + 0.009723103660000001, + 0.00915980266, + 0.009509702660000001, + 0.00886330366, + 0.00838080366, + 0.00831040266, + 0.00832760366, + 0.00876310366, + 0.009795602660000001, + 0.00953670266, + 0.00961870266, + 0.00788580466, + 0.00801440366, + 0.00886610266, + 0.00827650366, + 0.00862560366, + 0.01129930166, + 0.00836090366, + 0.00919260266, + 0.008315803660000001, + 0.00817550366, + 0.00912520266, + 0.00915280366, + 0.00914400266, + 0.01647019966, + 0.00937100266, + 0.01108670166, + 0.008483703660000001, + 0.00876660366 + ], + "exit_codes": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ] +} diff --git a/submissions/attachments/lab12/warm-spin.txt b/submissions/attachments/lab12/warm-spin.txt new file mode 100644 index 000000000..e56f8f78c --- /dev/null +++ b/submissions/attachments/lab12/warm-spin.txt @@ -0,0 +1,6 @@ +Benchmark 1: curl -fsS http://127.0.0.1:3000/time >/dev/null + Time (mean Β± Οƒ): 9.5 ms Β± 1.3 ms [User: 3.3 ms, System: 4.1 ms] + Range (min … max): 7.9 ms … 16.5 ms 50 runs + + Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options. + diff --git a/submissions/attachments/lab12/wasm-cli-build.log b/submissions/attachments/lab12/wasm-cli-build.log new file mode 100644 index 000000000..6250b26cf --- /dev/null +++ b/submissions/attachments/lab12/wasm-cli-build.log @@ -0,0 +1 @@ +Reusing existing wasm-cli main.wasm diff --git a/submissions/attachments/lab12/wasm-cli-raw.txt b/submissions/attachments/lab12/wasm-cli-raw.txt new file mode 100644 index 000000000..5f61a2564 --- /dev/null +++ b/submissions/attachments/lab12/wasm-cli-raw.txt @@ -0,0 +1,3 @@ +Content-Type: application/json + +{"unix":1783548307,"iso":"2026-07-08T22:05:07Z","hour_minute":"22:05","moscow":"2026-07-08 22:05:07","tz":"UTC+3"} \ No newline at end of file diff --git a/submissions/attachments/lab12/wasm-cli-time.json b/submissions/attachments/lab12/wasm-cli-time.json new file mode 100644 index 000000000..c0248f106 --- /dev/null +++ b/submissions/attachments/lab12/wasm-cli-time.json @@ -0,0 +1,7 @@ +{ + "unix": 1783548307, + "iso": "2026-07-08T22:05:07Z", + "hour_minute": "22:05", + "moscow": "2026-07-08 22:05:07", + "tz": "UTC+3" +} diff --git a/submissions/attachments/lab12/wasm-size.txt b/submissions/attachments/lab12/wasm-size.txt new file mode 100644 index 000000000..70719a954 --- /dev/null +++ b/submissions/attachments/lab12/wasm-size.txt @@ -0,0 +1,2 @@ +-rw-r--r-- 1 root root 362115 Jul 8 21:55 main.wasm +-rw-r--r-- 1 root root 196781 Jul 8 22:04 main.wasm diff --git a/submissions/attachments/lab6/bonus-security.txt b/submissions/attachments/lab6/bonus-security.txt new file mode 100644 index 000000000..1fd204b2a --- /dev/null +++ b/submissions/attachments/lab6/bonus-security.txt @@ -0,0 +1,12 @@ +=== USER nonroot +65532 +=== exec sh (expect fail) +OCI runtime exec failed: exec failed: unable to start container process: exec: "sh": executable file not found in $PATH +=== CapDrop +[ALL] +=== ReadOnly +true +=== SecurityOpt +[no-new-privileges:true] +=== read-only root test via busybox +touch: /etc/test: Read-only file system diff --git a/submissions/attachments/lab6/cache-bad-rebuild.txt b/submissions/attachments/lab6/cache-bad-rebuild.txt new file mode 100644 index 000000000..07d17cb07 --- /dev/null +++ b/submissions/attachments/lab6/cache-bad-rebuild.txt @@ -0,0 +1,3 @@ +real 3.72 +user 0.09 +sys 0.07 diff --git a/submissions/attachments/lab6/cache-good-rebuild.txt b/submissions/attachments/lab6/cache-good-rebuild.txt new file mode 100644 index 000000000..59e96d0b9 --- /dev/null +++ b/submissions/attachments/lab6/cache-good-rebuild.txt @@ -0,0 +1,3 @@ +real 1.70 +user 0.10 +sys 0.11 diff --git a/submissions/attachments/lab6/compose-logs.txt b/submissions/attachments/lab6/compose-logs.txt new file mode 100644 index 000000000..5455ed7f1 --- /dev/null +++ b/submissions/attachments/lab6/compose-logs.txt @@ -0,0 +1 @@ +quicknotes-1 | 2026/06/23 11:29:00 quicknotes listening on :8080 (notes loaded: 4) diff --git a/submissions/attachments/lab6/compose-ps.txt b/submissions/attachments/lab6/compose-ps.txt new file mode 100644 index 000000000..2498259d7 --- /dev/null +++ b/submissions/attachments/lab6/compose-ps.txt @@ -0,0 +1,2 @@ +NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS +devops-intro-quicknotes-1 quicknotes:lab6 "/quicknotes" quicknotes 9 seconds ago Up 8 seconds (healthy) 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp diff --git a/submissions/attachments/lab6/compose-up.txt b/submissions/attachments/lab6/compose-up.txt new file mode 100644 index 000000000..ac18c3f49 --- /dev/null +++ b/submissions/attachments/lab6/compose-up.txt @@ -0,0 +1,98 @@ + Image busybox:1.36-musl Pulling + Image busybox:1.36-musl Pulled + Image quicknotes:lab6 Building +#1 [internal] load local bake definitions +#1 reading from stdin 542B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 515B done +#2 DONE 0.0s + +#3 resolve image config for docker-image://docker.io/docker/dockerfile:1 +#3 DONE 0.6s + +#4 docker-image://docker.io/docker/dockerfile:1@sha256:87999aa3d42bdc6bea60565083ee17e86d1f3339802f543c0d03998580f9cb89 +#4 resolve docker.io/docker/dockerfile:1@sha256:87999aa3d42bdc6bea60565083ee17e86d1f3339802f543c0d03998580f9cb89 done +#4 CACHED + +#5 [internal] load metadata for gcr.io/distroless/static-debian12:nonroot +#5 DONE 0.4s + +#6 [internal] load metadata for docker.io/library/busybox:1.36-musl +#6 DONE 0.5s + +#7 [internal] load metadata for docker.io/library/golang:1.24-alpine +#7 DONE 0.5s + +#8 [internal] load .dockerignore +#8 transferring context: 2B done +#8 DONE 0.0s + +#9 [stage-2 1/4] FROM gcr.io/distroless/static-debian12:nonroot@sha256:d093aa3e30dbadd3efe1310db061a14da60299baff8450a17fe0ccc514a16639 +#9 resolve gcr.io/distroless/static-debian12:nonroot@sha256:d093aa3e30dbadd3efe1310db061a14da60299baff8450a17fe0ccc514a16639 done +#9 DONE 0.0s + +#10 [builder 1/6] FROM docker.io/library/golang:1.24-alpine@sha256:8bee1901f1e530bfb4a7850aa7a479d17ae3a18beb6e09064ed54cfd245b7191 +#10 resolve docker.io/library/golang:1.24-alpine@sha256:8bee1901f1e530bfb4a7850aa7a479d17ae3a18beb6e09064ed54cfd245b7191 done +#10 DONE 0.0s + +#11 [busybox 1/1] FROM docker.io/library/busybox:1.36-musl@sha256:3c6ae8008e2c2eedd141725c30b20d9c36b026eb796688f88205845ef17aa213 +#11 resolve docker.io/library/busybox:1.36-musl@sha256:3c6ae8008e2c2eedd141725c30b20d9c36b026eb796688f88205845ef17aa213 done +#11 DONE 0.0s + +#12 [internal] load build context +#12 transferring context: 422B done +#12 DONE 0.0s + +#13 [stage-2 2/4] COPY --from=builder /quicknotes /quicknotes +#13 CACHED + +#14 [builder 5/6] COPY . . +#14 CACHED + +#15 [stage-2 3/4] COPY --from=builder /src/seed.json /seed.json +#15 CACHED + +#16 [builder 4/6] RUN go mod download +#16 CACHED + +#17 [builder 3/6] COPY go.mod ./ +#17 CACHED + +#18 [builder 2/6] WORKDIR /src +#18 CACHED + +#19 [builder 6/6] RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags='-s -w' -o /quicknotes . +#19 CACHED + +#20 [stage-2 4/4] COPY --from=busybox /bin/busybox /busybox +#20 CACHED + +#21 exporting to image +#21 exporting layers done +#21 exporting manifest sha256:83da2b02f883b1cbcacda2943165c314e5a22658c8fd6df73146b64d2a75a08d done +#21 exporting config sha256:55ee3c6a2cf57ac962258865a12873a7cc7a6114ed1c7c2ebf136cdaeebcd00e done +#21 exporting attestation manifest sha256:dc5f8d1a890bb1b3d3ff4fd870e83e70380d784ebfcc47afd4adce25faa5918f done +#21 exporting manifest list sha256:c354d52933dc27f4c32937b3c039dead80894194905f9df7632d1d26b2bf1c15 done +#21 naming to docker.io/library/quicknotes:lab6 done +#21 unpacking to docker.io/library/quicknotes:lab6 done +#21 DONE 0.0s + +#22 resolving provenance for metadata file +#22 DONE 0.0s + Image quicknotes:lab6 Built + Network devops-intro_default Creating + Network devops-intro_default Created + Volume devops-intro_quicknotes-data Creating + Volume devops-intro_quicknotes-data Created + Container devops-intro-volume-init-1 Creating + Container devops-intro-volume-init-1 Created + Container devops-intro-quicknotes-1 Creating + Container devops-intro-quicknotes-1 Created + Container devops-intro-volume-init-1 Starting + Container devops-intro-volume-init-1 Started + Container devops-intro-volume-init-1 Waiting + Container devops-intro-volume-init-1 Exited + Container devops-intro-quicknotes-1 Starting + Container devops-intro-quicknotes-1 Started diff --git a/submissions/attachments/lab6/curl-health.txt b/submissions/attachments/lab6/curl-health.txt new file mode 100644 index 000000000..a00d4b113 --- /dev/null +++ b/submissions/attachments/lab6/curl-health.txt @@ -0,0 +1 @@ +{"notes":4,"status":"ok"} diff --git a/submissions/attachments/lab6/docker-images.txt b/submissions/attachments/lab6/docker-images.txt new file mode 100644 index 000000000..92c6f981a --- /dev/null +++ b/submissions/attachments/lab6/docker-images.txt @@ -0,0 +1,4 @@ +REPOSITORY TAG SIZE +quicknotes lab6 16MB +quicknotes:lab6 16MB +golang:1.24-alpine 388MB diff --git a/submissions/attachments/lab6/docker-inspect-config.json b/submissions/attachments/lab6/docker-inspect-config.json new file mode 100644 index 000000000..f4c27b04a --- /dev/null +++ b/submissions/attachments/lab6/docker-inspect-config.json @@ -0,0 +1,14 @@ +{ + "User": "65532", + "ExposedPorts": { + "8080/tcp": {} + }, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt" + ], + "Entrypoint": [ + "/quicknotes" + ], + "WorkingDir": "/home/nonroot" +} diff --git a/submissions/attachments/lab6/persistence-test.txt b/submissions/attachments/lab6/persistence-test.txt new file mode 100644 index 000000000..efa473ff0 --- /dev/null +++ b/submissions/attachments/lab6/persistence-test.txt @@ -0,0 +1,63 @@ +=== Step 1: POST durable note +{"id":5,"title":"durable","body":"survive a restart","created_at":"2026-06-23T11:29:23.162316088Z"} + +=== grep durable (before down) +[{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"durable","body":"survive a restart","created_at":"2026-06-23T11:29:23.162316088Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"}] + +=== docker compose down (keep volume) + Container devops-intro-quicknotes-1 Stopping + Container devops-intro-quicknotes-1 Stopped + Container devops-intro-quicknotes-1 Removing + Container devops-intro-quicknotes-1 Removed + Container devops-intro-volume-init-1 Stopping + Container devops-intro-volume-init-1 Stopped + Container devops-intro-volume-init-1 Removing + Container devops-intro-volume-init-1 Removed + Network devops-intro_default Removing + Network devops-intro_default Removed +=== docker compose up -d + Network devops-intro_default Creating + Network devops-intro_default Created + Container devops-intro-volume-init-1 Creating + Container devops-intro-volume-init-1 Created + Container devops-intro-quicknotes-1 Creating + Container devops-intro-quicknotes-1 Created + Container devops-intro-volume-init-1 Starting + Container devops-intro-volume-init-1 Started + Container devops-intro-volume-init-1 Waiting + Container devops-intro-volume-init-1 Exited + Container devops-intro-quicknotes-1 Starting + Container devops-intro-quicknotes-1 Started +=== grep durable (after up) +[{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"durable","body":"survive a restart","created_at":"2026-06-23T11:29:23.162316088Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"}] + +=== docker compose down -v + Container devops-intro-quicknotes-1 Stopping + Container devops-intro-quicknotes-1 Stopped + Container devops-intro-quicknotes-1 Removing + Container devops-intro-quicknotes-1 Removed + Container devops-intro-volume-init-1 Stopping + Container devops-intro-volume-init-1 Stopped + Container devops-intro-volume-init-1 Removing + Container devops-intro-volume-init-1 Removed + Volume devops-intro_quicknotes-data Removing + Network devops-intro_default Removing + Volume devops-intro_quicknotes-data Removed + Network devops-intro_default Removed +=== docker compose up -d + Network devops-intro_default Creating + Network devops-intro_default Created + Volume devops-intro_quicknotes-data Creating + Volume devops-intro_quicknotes-data Created + Container devops-intro-volume-init-1 Creating + Container devops-intro-volume-init-1 Created + Container devops-intro-quicknotes-1 Creating + Container devops-intro-quicknotes-1 Created + Container devops-intro-volume-init-1 Starting + Container devops-intro-volume-init-1 Started + Container devops-intro-volume-init-1 Waiting + Container devops-intro-volume-init-1 Exited + Container devops-intro-quicknotes-1 Starting + Container devops-intro-quicknotes-1 Started +=== grep durable (after down -v) β€” expect absent +gone (expected) diff --git a/submissions/attachments/lab6/trivy.txt b/submissions/attachments/lab6/trivy.txt new file mode 100644 index 000000000..fea184a61 --- /dev/null +++ b/submissions/attachments/lab6/trivy.txt @@ -0,0 +1,92 @@ +Unable to find image 'aquasec/trivy:0.59.1' locally +0.59.1: Pulling from aquasec/trivy +4784322f1001: Pulling fs layer +cb8611c9fe51: Pulling fs layer +b8fb5a6dd3c2: Pulling fs layer +feb3d185a00a: Pulling fs layer +4784322f1001: Download complete +cb8611c9fe51: Download complete +cb8611c9fe51: Pull complete +b8fb5a6dd3c2: Download complete +feb3d185a00a: Download complete +feb3d185a00a: Pull complete +4784322f1001: Pull complete +b8fb5a6dd3c2: Pull complete +Digest: sha256:029e990b328d149bf0a9ffe355919041e1f86192db2df47e217f8a36dd42ceac +Status: Downloaded newer image for aquasec/trivy:0.59.1 +2026-06-23T11:29:46Z INFO [vulndb] Need to update DB +2026-06-23T11:29:46Z INFO [vulndb] Downloading vulnerability DB... +2026-06-23T11:29:46Z INFO [vulndb] Downloading artifact... repo="mirror.gcr.io/aquasec/trivy-db:2" +2026-06-23T11:29:52Z INFO [vulndb] Artifact successfully downloaded repo="mirror.gcr.io/aquasec/trivy-db:2" +2026-06-23T11:29:52Z INFO [vuln] Vulnerability scanning is enabled +2026-06-23T11:29:52Z INFO [secret] Secret scanning is enabled +2026-06-23T11:29:52Z INFO [secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning +2026-06-23T11:29:52Z INFO [secret] Please see also https://aquasecurity.github.io/trivy/v0.59/docs/scanner/secret#recommendation for faster secret detection +2026-06-23T11:29:52Z INFO Detected OS family="debian" version="12.14" +2026-06-23T11:29:52Z INFO [debian] Detecting vulnerabilities... os_version="12" pkg_num=4 +2026-06-23T11:29:52Z INFO Number of language-specific files num=1 +2026-06-23T11:29:52Z INFO [gobinary] Detecting vulnerabilities... +2026-06-23T11:29:52Z WARN Using severities from other vendors for some vulnerabilities. Read https://aquasecurity.github.io/trivy/v0.59/docs/scanner/vulnerability#severity-selection for details. + +quicknotes:lab6 (debian 12.14) +============================== +Total: 0 (HIGH: 0, CRITICAL: 0) + + +quicknotes (gobinary) +===================== +Total: 13 (HIGH: 13, CRITICAL: 0) + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Library β”‚ Vulnerability β”‚ Severity β”‚ Status β”‚ Installed Version β”‚ Fixed Version β”‚ Title β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ stdlib β”‚ CVE-2026-25679 β”‚ HIGH β”‚ fixed β”‚ v1.24.13 β”‚ 1.25.8, 1.26.1 β”‚ net/url: Incorrect parsing of IPv6 host literals in net/url β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-25679 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-27145 β”‚ β”‚ β”‚ β”‚ 1.25.11, 1.26.4 β”‚ *x509.Certificate).VerifyHostname previously called β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ matchHostnames in ... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-27145 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-32280 β”‚ β”‚ β”‚ β”‚ 1.25.9, 1.26.2 β”‚ crypto/x509: crypto/tls: golang: Go: Denial of Service β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ vulnerability in certificate chain building... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-32280 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-32281 β”‚ β”‚ β”‚ β”‚ β”‚ crypto/x509: golang: Go crypto/x509: Denial of Service via β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ inefficient certificate chain validation... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-32281 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-32283 β”‚ β”‚ β”‚ β”‚ β”‚ crypto/tls: golang: Go crypto/tls: Denial of Service via β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ multiple TLS 1.3 key... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-32283 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-33811 β”‚ β”‚ β”‚ β”‚ 1.25.10, 1.26.3 β”‚ net: golang: Go net package: Denial of Service via long β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ CNAME response... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-33811 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-33814 β”‚ β”‚ β”‚ β”‚ β”‚ When processing HTTP/2 SETTINGS frames, transport will enter β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ an infini ... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-33814 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-39820 β”‚ β”‚ β”‚ β”‚ β”‚ Well-crafted inputs reaching ParseAddress, ParseAddressList, β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ and Parse ... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-39820 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-39823 β”‚ β”‚ β”‚ β”‚ β”‚ CVE-2026-27142 fixed a vulnerability in which URLs were not β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ correctly ...... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-39823 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-39825 β”‚ β”‚ β”‚ β”‚ β”‚ ReverseProxy can forward queries containing parameters not β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ visible to ... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-39825 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-39836 β”‚ β”‚ β”‚ β”‚ β”‚ ELSA-2026-22112: go-toolset:ol8 security update (IMPORTANT) β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-39836 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-42499 β”‚ β”‚ β”‚ β”‚ β”‚ Pathological inputs could cause DoS through consumePhrase β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ when parsing ... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-42499 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-42504 β”‚ β”‚ β”‚ β”‚ 1.25.11, 1.26.4 β”‚ Decoding a maliciously-crafted MIME header containing many β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ invalid enc ... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-42504 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ diff --git a/submissions/attachments/lab8/alert-firing.txt b/submissions/attachments/lab8/alert-firing.txt new file mode 100644 index 000000000..c3c07c572 --- /dev/null +++ b/submissions/attachments/lab8/alert-firing.txt @@ -0,0 +1,9 @@ +HighHTTPErrorRate state=firing value=0.317 (31.7% error ratio) +activeAt=2026-06-30T19:15:59.892443532Z +severity=page +runbook_url=docs/runbook/high-error-rate.md + +Timeline: +- 19:15:59Z alert entered pending (after initial traffic) +- 19:16:11Z sustained error injection started +- 19:22:11Z injection finished; alert state=firing diff --git a/submissions/attachments/lab8/alert-trigger.log b/submissions/attachments/lab8/alert-trigger.log new file mode 100644 index 000000000..96a4c53b2 --- /dev/null +++ b/submissions/attachments/lab8/alert-trigger.log @@ -0,0 +1,2 @@ +Error injection started 2026-06-30T19:16:11Z +Error injection finished 2026-06-30T19:22:11Z diff --git a/submissions/attachments/lab8/compose-ps.txt b/submissions/attachments/lab8/compose-ps.txt new file mode 100644 index 000000000..ef9e5234a --- /dev/null +++ b/submissions/attachments/lab8/compose-ps.txt @@ -0,0 +1,4 @@ +NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS +devops-intro-grafana-1 grafana/grafana:13.0.2 "/run.sh" grafana 42 seconds ago Up 35 seconds 0.0.0.0:3000->3000/tcp, [::]:3000->3000/tcp +devops-intro-prometheus-1 prom/prometheus:v3.2.1 "/bin/prometheus --c…" prometheus 42 seconds ago Up 35 seconds 0.0.0.0:9090->9090/tcp, [::]:9090->9090/tcp +devops-intro-quicknotes-1 quicknotes:lab6 "/quicknotes" quicknotes 42 seconds ago Up 40 seconds (healthy) 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp diff --git a/submissions/attachments/lab8/compose-up.txt b/submissions/attachments/lab8/compose-up.txt new file mode 100644 index 000000000..b91805ad0 --- /dev/null +++ b/submissions/attachments/lab8/compose-up.txt @@ -0,0 +1,2662 @@ + Image prom/prometheus:v3.2.1 Pulling + Image grafana/grafana:13.0.2 Pulling + 073d75ee84d4 Pulling fs layer 0B + 34c169812ca7 Pulling fs layer 0B + 81d14c078a74 Pulling fs layer 0B + c8c5fe18afab Pulling fs layer 0B + fe6306487029 Pulling fs layer 0B + 0ad2438e159e Pulling fs layer 0B + c390b3ff97f5 Pulling fs layer 0B + f5d2fa6280ad Pulling fs layer 0B + 1c78c8e19058 Pulling fs layer 0B + 4f4fb700ef54 Pulling fs layer 0B + b8ba42f3610c Pulling fs layer 0B + ca59134b0aa1 Pulling fs layer 0B + 1cc0ff6cea1d Pulling fs layer 0B + bc8b677c2b98 Pulling fs layer 0B + d7cb4538653c Pulling fs layer 0B + 6721902c3fd6 Pulling fs layer 0B + 0f1eecfe1b47 Pulling fs layer 0B + 4f4fb700ef54 Pulling fs layer 0B + 4f4fb700ef54 Already exists 0B + 81d14c078a74 Download complete 0B + 1c78c8e19058 Download complete 0B + b8ba42f3610c Download complete 0B + b8ba42f3610c Pull complete 0B + f5d2fa6280ad Download complete 0B + 073d75ee84d4 Download complete 0B + 6721902c3fd6 Download complete 0B + c8c5fe18afab Download complete 0B + 34c169812ca7 Download complete 0B + d7cb4538653c Download complete 0B + 1cc0ff6cea1d Downloading 1.049MB + bc8b677c2b98 Download complete 0B + 1cc0ff6cea1d Downloading 2.097MB + c390b3ff97f5 Download complete 0B + 1cc0ff6cea1d Downloading 2.097MB + 1cc0ff6cea1d Downloading 2.097MB + 0f1eecfe1b47 Downloading 1.049MB + 0f1eecfe1b47 Downloading 1.049MB + 1cc0ff6cea1d Downloading 3.146MB + 1cc0ff6cea1d Downloading 3.146MB + 0f1eecfe1b47 Downloading 1.049MB + 1cc0ff6cea1d Downloading 3.146MB + 0f1eecfe1b47 Downloading 2.097MB + 1cc0ff6cea1d Downloading 3.146MB + 0f1eecfe1b47 Downloading 2.097MB + ca59134b0aa1 Downloading 1.049MB + 1cc0ff6cea1d Downloading 3.146MB + 0f1eecfe1b47 Downloading 2.097MB + fe6306487029 Downloading 1.049MB + 0f1eecfe1b47 Downloading 2.097MB + ca59134b0aa1 Downloading 1.049MB + 1cc0ff6cea1d Downloading 3.146MB + fe6306487029 Downloading 1.049MB + ca59134b0aa1 Downloading 1.049MB + 1cc0ff6cea1d Downloading 3.146MB + 0f1eecfe1b47 Downloading 2.097MB + fe6306487029 Downloading 1.049MB + fe6306487029 Downloading 1.049MB + ca59134b0aa1 Downloading 1.049MB + 1cc0ff6cea1d Downloading 3.146MB + 0f1eecfe1b47 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + fe6306487029 Downloading 2.097MB + 1cc0ff6cea1d Downloading 3.146MB + 0f1eecfe1b47 Downloading 2.097MB + ca59134b0aa1 Downloading 1.049MB + 0f1eecfe1b47 Downloading 2.097MB + ca59134b0aa1 Downloading 1.049MB + 1cc0ff6cea1d Downloading 3.146MB + fe6306487029 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + fe6306487029 Downloading 2.097MB + ca59134b0aa1 Downloading 1.049MB + 0ad2438e159e Downloading 1.049MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 2.097MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 2.097MB + ca59134b0aa1 Downloading 1.049MB + fe6306487029 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 2.097MB + ca59134b0aa1 Downloading 1.049MB + fe6306487029 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + fe6306487029 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + 0f1eecfe1b47 Downloading 2.097MB + ca59134b0aa1 Downloading 1.049MB + 1cc0ff6cea1d Downloading 4.194MB + fe6306487029 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 2.097MB + ca59134b0aa1 Downloading 1.049MB + ca59134b0aa1 Downloading 1.049MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 2.097MB + fe6306487029 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + fe6306487029 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 3.146MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 3.146MB + ca59134b0aa1 Downloading 2.097MB + fe6306487029 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 4.194MB + 0ad2438e159e Downloading 1.049MB + fe6306487029 Downloading 3.146MB + 0f1eecfe1b47 Downloading 3.146MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 3.146MB + ca59134b0aa1 Downloading 2.097MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 1.049MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 3.146MB + ca59134b0aa1 Downloading 2.097MB + 0ad2438e159e Downloading 1.049MB + fe6306487029 Downloading 3.146MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 3.146MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 1.049MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 3.146MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 1.049MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 4.194MB + 0f1eecfe1b47 Downloading 3.146MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 1.049MB + 0f1eecfe1b47 Downloading 3.146MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 3.146MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 3.146MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 3.146MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 3.146MB + ca59134b0aa1 Downloading 2.097MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + fe6306487029 Downloading 3.146MB + ca59134b0aa1 Downloading 2.097MB + 0ad2438e159e Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 3.146MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 3.146MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 4.194MB + ca59134b0aa1 Downloading 2.097MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 4.194MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 4.194MB + ca59134b0aa1 Downloading 2.097MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + 0ad2438e159e Downloading 2.097MB + fe6306487029 Downloading 3.146MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 4.194MB + ca59134b0aa1 Downloading 2.097MB + ca59134b0aa1 Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 4.194MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 4.194MB + ca59134b0aa1 Downloading 3.146MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 4.194MB + ca59134b0aa1 Downloading 3.146MB + fe6306487029 Downloading 3.146MB + 0ad2438e159e Downloading 2.097MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 2.097MB + ca59134b0aa1 Downloading 3.146MB + 1cc0ff6cea1d Downloading 5.243MB + 0f1eecfe1b47 Downloading 4.194MB + ca59134b0aa1 Downloading 3.146MB + 1cc0ff6cea1d Downloading 6.291MB + 0f1eecfe1b47 Downloading 4.194MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 2.097MB + 0f1eecfe1b47 Downloading 4.194MB + ca59134b0aa1 Downloading 3.146MB + 1cc0ff6cea1d Downloading 6.291MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 2.097MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 2.097MB + ca59134b0aa1 Downloading 3.146MB + 1cc0ff6cea1d Downloading 6.291MB + 0f1eecfe1b47 Downloading 4.194MB + ca59134b0aa1 Downloading 3.146MB + 1cc0ff6cea1d Downloading 6.291MB + 0f1eecfe1b47 Downloading 4.194MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 3.146MB + 1cc0ff6cea1d Downloading 6.291MB + 0f1eecfe1b47 Downloading 5.243MB + ca59134b0aa1 Downloading 3.146MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 3.146MB + ca59134b0aa1 Downloading 3.146MB + 1cc0ff6cea1d Downloading 6.291MB + 0f1eecfe1b47 Downloading 5.243MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 3.146MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 3.146MB + 0f1eecfe1b47 Downloading 5.243MB + ca59134b0aa1 Downloading 3.846MB + 1cc0ff6cea1d Downloading 6.291MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 3.146MB + ca59134b0aa1 Download complete 0B + 1cc0ff6cea1d Downloading 6.291MB + 0f1eecfe1b47 Downloading 5.243MB + ca59134b0aa1 Extracting 1B + 0ad2438e159e Downloading 3.146MB + fe6306487029 Downloading 4.194MB + 1cc0ff6cea1d Downloading 6.291MB + 0f1eecfe1b47 Downloading 5.243MB + 4f4fb700ef54 Pull complete 0B + d7cb4538653c Pull complete 0B + bc8b677c2b98 Pull complete 0B + ca59134b0aa1 Pull complete 0B + 1cc0ff6cea1d Downloading 6.291MB + 0f1eecfe1b47 Downloading 5.243MB + fe6306487029 Downloading 4.194MB + 0ad2438e159e Downloading 3.146MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 5.243MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 3.146MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 3.146MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 5.243MB + 0f1eecfe1b47 Downloading 5.243MB + 1cc0ff6cea1d Downloading 7.34MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 3.146MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + 0ad2438e159e Downloading 4.194MB + fe6306487029 Downloading 5.243MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 4.194MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 4.194MB + 0f1eecfe1b47 Downloading 6.291MB + 1cc0ff6cea1d Downloading 7.34MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 4.194MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + 0ad2438e159e Downloading 4.194MB + fe6306487029 Downloading 5.243MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 4.194MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 4.194MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 4.194MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 4.194MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + fe6306487029 Downloading 5.243MB + 0ad2438e159e Downloading 4.194MB + 1cc0ff6cea1d Downloading 7.34MB + 0f1eecfe1b47 Downloading 6.291MB + 0ad2438e159e Downloading 4.194MB + fe6306487029 Downloading 5.243MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 4.194MB + 0f1eecfe1b47 Downloading 6.291MB + 1cc0ff6cea1d Downloading 7.34MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 6.291MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 5.243MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 7.34MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 5.243MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 7.34MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 5.243MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 5.243MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 7.34MB + 0f1eecfe1b47 Downloading 7.34MB + 1cc0ff6cea1d Downloading 8.389MB + 0ad2438e159e Downloading 5.243MB + fe6306487029 Downloading 6.291MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 7.34MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 5.243MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 5.243MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 7.34MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 7.34MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 5.243MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 7.34MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 5.243MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 7.34MB + fe6306487029 Downloading 6.291MB + 0ad2438e159e Downloading 5.243MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 7.34MB + fe6306487029 Downloading 7.34MB + 0ad2438e159e Downloading 6.291MB + 1cc0ff6cea1d Downloading 8.389MB + 0f1eecfe1b47 Downloading 8.389MB + fe6306487029 Downloading 7.34MB + 0ad2438e159e Downloading 6.291MB + fe6306487029 Downloading 7.34MB + 0ad2438e159e Downloading 6.291MB + 1cc0ff6cea1d Downloading 9.437MB + 0f1eecfe1b47 Downloading 8.389MB + 1cc0ff6cea1d Downloading 9.437MB + 0f1eecfe1b47 Downloading 8.389MB + 0ad2438e159e Downloading 6.291MB + fe6306487029 Downloading 7.34MB + 1cc0ff6cea1d Downloading 9.437MB + 0f1eecfe1b47 Downloading 8.389MB + fe6306487029 Downloading 7.34MB + 0ad2438e159e Downloading 6.291MB + 1cc0ff6cea1d Downloading 9.437MB + 0f1eecfe1b47 Downloading 8.389MB + fe6306487029 Downloading 7.34MB + 0ad2438e159e Downloading 6.291MB + 1cc0ff6cea1d Downloading 9.437MB + 0f1eecfe1b47 Downloading 8.389MB + fe6306487029 Downloading 7.34MB + 0ad2438e159e Downloading 6.291MB + 0ad2438e159e Downloading 6.291MB + fe6306487029 Downloading 7.34MB + 1cc0ff6cea1d Downloading 9.437MB + 0f1eecfe1b47 Downloading 8.389MB + 0f1eecfe1b47 Downloading 8.389MB + 1cc0ff6cea1d Downloading 9.437MB + fe6306487029 Downloading 7.34MB + 0ad2438e159e Downloading 6.291MB + 1cc0ff6cea1d Downloading 9.437MB + 0f1eecfe1b47 Downloading 9.437MB + fe6306487029 Downloading 8.389MB + 0ad2438e159e Downloading 7.34MB + 1cc0ff6cea1d Downloading 9.437MB + 0f1eecfe1b47 Downloading 9.437MB + fe6306487029 Downloading 8.389MB + 0ad2438e159e Downloading 7.34MB + fe6306487029 Downloading 8.389MB + 0ad2438e159e Downloading 7.34MB + 1cc0ff6cea1d Downloading 10.49MB + 0f1eecfe1b47 Downloading 9.437MB + fe6306487029 Downloading 8.389MB + 0ad2438e159e Downloading 7.34MB + 0f1eecfe1b47 Downloading 9.437MB + 1cc0ff6cea1d Downloading 10.49MB + 1cc0ff6cea1d Downloading 10.49MB + fe6306487029 Downloading 8.389MB + 0ad2438e159e Downloading 7.34MB + 0f1eecfe1b47 Downloading 9.437MB + 1cc0ff6cea1d Downloading 10.49MB + 0f1eecfe1b47 Downloading 9.437MB + fe6306487029 Downloading 8.389MB + 0ad2438e159e Downloading 7.34MB + 1cc0ff6cea1d Downloading 10.49MB + 0f1eecfe1b47 Downloading 9.437MB + fe6306487029 Downloading 8.389MB + 0ad2438e159e Downloading 7.34MB + 1cc0ff6cea1d Downloading 10.49MB + 0f1eecfe1b47 Downloading 9.437MB + fe6306487029 Downloading 8.389MB + 0ad2438e159e Downloading 7.34MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 10.49MB + 0f1eecfe1b47 Downloading 9.437MB + 0f1eecfe1b47 Downloading 10.49MB + 1cc0ff6cea1d Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 10.49MB + 0f1eecfe1b47 Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 10.49MB + 0f1eecfe1b47 Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 10.49MB + 0f1eecfe1b47 Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 10.49MB + 0ad2438e159e Downloading 8.389MB + fe6306487029 Downloading 9.437MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 10.49MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 10.49MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 8.389MB + fe6306487029 Downloading 9.437MB + 0ad2438e159e Downloading 9.437MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 10.49MB + 1cc0ff6cea1d Downloading 11.53MB + fe6306487029 Downloading 10.49MB + 0ad2438e159e Downloading 9.437MB + 0f1eecfe1b47 Downloading 10.49MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 11.53MB + fe6306487029 Downloading 10.49MB + 0ad2438e159e Downloading 9.437MB + 1cc0ff6cea1d Downloading 11.53MB + 0f1eecfe1b47 Downloading 11.53MB + 0ad2438e159e Downloading 9.437MB + fe6306487029 Downloading 10.49MB + 0f1eecfe1b47 Downloading 11.53MB + 1cc0ff6cea1d Downloading 11.53MB + 0ad2438e159e Downloading 9.437MB + fe6306487029 Downloading 10.49MB + fe6306487029 Downloading 10.49MB + 0ad2438e159e Downloading 9.437MB + 1cc0ff6cea1d Downloading 12.58MB + 0f1eecfe1b47 Downloading 11.53MB + 0ad2438e159e Downloading 9.437MB + fe6306487029 Downloading 10.49MB + 1cc0ff6cea1d Downloading 12.58MB + 0f1eecfe1b47 Downloading 11.53MB + 1cc0ff6cea1d Downloading 12.58MB + 0f1eecfe1b47 Downloading 11.53MB + fe6306487029 Downloading 10.49MB + 0ad2438e159e Downloading 9.437MB + 1cc0ff6cea1d Downloading 12.58MB + fe6306487029 Downloading 10.49MB + 0ad2438e159e Downloading 9.437MB + 0f1eecfe1b47 Download complete 0B + 1cc0ff6cea1d Downloading 12.58MB + fe6306487029 Downloading 10.49MB + 0ad2438e159e Downloading 9.437MB + 1cc0ff6cea1d Downloading 12.58MB + fe6306487029 Downloading 10.49MB + 0ad2438e159e Downloading 9.437MB + fe6306487029 Downloading 11.53MB + 0ad2438e159e Downloading 10.49MB + 1cc0ff6cea1d Downloading 12.58MB + fe6306487029 Downloading 11.53MB + 0ad2438e159e Downloading 10.49MB + 1cc0ff6cea1d Downloading 12.58MB + fe6306487029 Downloading 11.53MB + 0ad2438e159e Downloading 10.49MB + 1cc0ff6cea1d Downloading 12.58MB + 1cc0ff6cea1d Downloading 13.63MB + fe6306487029 Downloading 11.53MB + 0ad2438e159e Downloading 10.49MB + 1cc0ff6cea1d Downloading 13.63MB + fe6306487029 Downloading 11.53MB + 0ad2438e159e Downloading 10.49MB + 1cc0ff6cea1d Downloading 13.63MB + fe6306487029 Downloading 11.53MB + 0ad2438e159e Downloading 10.49MB + 1cc0ff6cea1d Downloading 13.63MB + fe6306487029 Downloading 11.53MB + 0ad2438e159e Downloading 10.49MB + 1cc0ff6cea1d Downloading 13.63MB + 0ad2438e159e Downloading 10.49MB + fe6306487029 Downloading 11.53MB + fe6306487029 Downloading 11.53MB + 0ad2438e159e Downloading 10.49MB + 1cc0ff6cea1d Downloading 13.63MB + fe6306487029 Downloading 12.58MB + 0ad2438e159e Downloading 11.53MB + 1cc0ff6cea1d Downloading 13.63MB + 1cc0ff6cea1d Downloading 13.63MB + fe6306487029 Downloading 12.58MB + 0ad2438e159e Downloading 11.53MB + 1cc0ff6cea1d Downloading 13.63MB + fe6306487029 Downloading 12.58MB + 0ad2438e159e Downloading 11.53MB + fe6306487029 Downloading 12.58MB + 0ad2438e159e Downloading 11.53MB + 1cc0ff6cea1d Downloading 13.63MB + 1cc0ff6cea1d Downloading 14.68MB + fe6306487029 Downloading 12.58MB + 0ad2438e159e Downloading 11.53MB + fe6306487029 Downloading 12.58MB + 0ad2438e159e Downloading 11.53MB + 1cc0ff6cea1d Downloading 14.68MB + 0ad2438e159e Downloading 11.53MB + fe6306487029 Downloading 12.58MB + 1cc0ff6cea1d Downloading 14.68MB + 1cc0ff6cea1d Downloading 14.68MB + fe6306487029 Downloading 12.58MB + 0ad2438e159e Downloading 11.53MB + 1cc0ff6cea1d Downloading 14.68MB + fe6306487029 Downloading 13.63MB + 0ad2438e159e Downloading 11.53MB + 1cc0ff6cea1d Downloading 14.68MB + fe6306487029 Downloading 13.63MB + 0ad2438e159e Downloading 12.58MB + 1cc0ff6cea1d Downloading 14.68MB + fe6306487029 Downloading 13.63MB + 0ad2438e159e Downloading 12.58MB + 1cc0ff6cea1d Downloading 14.68MB + fe6306487029 Downloading 13.63MB + 0ad2438e159e Downloading 12.58MB + 1cc0ff6cea1d Downloading 14.68MB + fe6306487029 Downloading 13.63MB + 0ad2438e159e Downloading 12.58MB + fe6306487029 Downloading 13.63MB + 0ad2438e159e Downloading 12.58MB + 1cc0ff6cea1d Downloading 15.73MB + 1cc0ff6cea1d Downloading 15.73MB + fe6306487029 Downloading 13.63MB + 0ad2438e159e Downloading 12.58MB + 1cc0ff6cea1d Downloading 15.73MB + fe6306487029 Downloading 13.63MB + 0ad2438e159e Downloading 12.58MB + 1cc0ff6cea1d Downloading 15.73MB + fe6306487029 Downloading 13.63MB + 0ad2438e159e Downloading 12.58MB + fe6306487029 Downloading 14.68MB + 0ad2438e159e Downloading 13.63MB + 1cc0ff6cea1d Downloading 15.73MB + fe6306487029 Downloading 14.68MB + 0ad2438e159e Downloading 13.63MB + 1cc0ff6cea1d Downloading 15.73MB + 1cc0ff6cea1d Downloading 15.73MB + fe6306487029 Downloading 14.68MB + 0ad2438e159e Downloading 13.63MB + 1cc0ff6cea1d Downloading 16.78MB + fe6306487029 Downloading 14.68MB + 0ad2438e159e Downloading 13.63MB + 1cc0ff6cea1d Downloading 16.78MB + fe6306487029 Downloading 14.68MB + 0ad2438e159e Downloading 13.63MB + 1cc0ff6cea1d Downloading 16.78MB + fe6306487029 Downloading 14.68MB + 0ad2438e159e Downloading 13.63MB + 1cc0ff6cea1d Downloading 16.78MB + fe6306487029 Downloading 15.73MB + 0ad2438e159e Downloading 14.68MB + 1cc0ff6cea1d Downloading 16.78MB + fe6306487029 Downloading 15.73MB + 0ad2438e159e Downloading 14.68MB + 1cc0ff6cea1d Downloading 16.78MB + fe6306487029 Downloading 15.73MB + 0ad2438e159e Downloading 14.68MB + fe6306487029 Downloading 15.73MB + 0ad2438e159e Downloading 14.68MB + 1cc0ff6cea1d Downloading 17.83MB + 1cc0ff6cea1d Downloading 17.83MB + fe6306487029 Downloading 15.73MB + 0ad2438e159e Downloading 14.68MB + 1cc0ff6cea1d Downloading 17.83MB + fe6306487029 Downloading 15.73MB + 0ad2438e159e Downloading 14.68MB + 1cc0ff6cea1d Downloading 17.83MB + fe6306487029 Downloading 16.78MB + 0ad2438e159e Downloading 15.73MB + 1cc0ff6cea1d Downloading 17.83MB + fe6306487029 Downloading 16.78MB + 0ad2438e159e Downloading 15.73MB + 1cc0ff6cea1d Downloading 18.87MB + fe6306487029 Downloading 16.78MB + 0ad2438e159e Downloading 15.73MB + 1cc0ff6cea1d Downloading 18.87MB + 0ad2438e159e Downloading 15.73MB + fe6306487029 Downloading 16.78MB + 1cc0ff6cea1d Downloading 18.87MB + fe6306487029 Downloading 16.78MB + 0ad2438e159e Downloading 15.73MB + 1cc0ff6cea1d Downloading 18.87MB + fe6306487029 Downloading 17.83MB + 0ad2438e159e Downloading 16.78MB + 1cc0ff6cea1d Downloading 18.87MB + fe6306487029 Downloading 17.83MB + 0ad2438e159e Downloading 16.78MB + fe6306487029 Downloading 17.83MB + 0ad2438e159e Downloading 16.78MB + 1cc0ff6cea1d Downloading 18.87MB + 1cc0ff6cea1d Downloading 19.92MB + fe6306487029 Downloading 17.83MB + 0ad2438e159e Downloading 16.78MB + fe6306487029 Downloading 17.83MB + 0ad2438e159e Downloading 16.78MB + 1cc0ff6cea1d Downloading 19.92MB + 1cc0ff6cea1d Downloading 19.92MB + fe6306487029 Downloading 17.83MB + 0ad2438e159e Downloading 16.78MB + 1cc0ff6cea1d Downloading 19.92MB + fe6306487029 Downloading 17.83MB + 0ad2438e159e Downloading 16.78MB + fe6306487029 Downloading 18.87MB + 0ad2438e159e Downloading 17.83MB + 1cc0ff6cea1d Downloading 19.92MB + 1cc0ff6cea1d Downloading 19.92MB + fe6306487029 Downloading 18.87MB + 0ad2438e159e Downloading 17.83MB + 1cc0ff6cea1d Downloading 19.92MB + fe6306487029 Downloading 18.87MB + 0ad2438e159e Downloading 17.83MB + 1cc0ff6cea1d Downloading 19.92MB + fe6306487029 Downloading 18.87MB + 0ad2438e159e Downloading 17.83MB + 1cc0ff6cea1d Downloading 19.92MB + fe6306487029 Downloading 18.87MB + 0ad2438e159e Downloading 17.83MB + 1cc0ff6cea1d Downloading 20.97MB + 0ad2438e159e Downloading 17.83MB + fe6306487029 Downloading 18.87MB + fe6306487029 Downloading 18.87MB + 0ad2438e159e Downloading 17.83MB + 1cc0ff6cea1d Downloading 20.97MB + fe6306487029 Downloading 18.87MB + 0ad2438e159e Downloading 17.83MB + 1cc0ff6cea1d Downloading 20.97MB + 1cc0ff6cea1d Downloading 20.97MB + fe6306487029 Downloading 18.87MB + 0ad2438e159e Downloading 17.83MB + 1cc0ff6cea1d Downloading 20.97MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 17.83MB + 1cc0ff6cea1d Downloading 20.97MB + 0ad2438e159e Downloading 17.83MB + fe6306487029 Downloading 19.92MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 20.97MB + 1cc0ff6cea1d Downloading 20.97MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 20.97MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 20.97MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 20.97MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 20.97MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 20.97MB + 1cc0ff6cea1d Downloading 20.97MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 22.02MB + 1cc0ff6cea1d Downloading 22.02MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 22.02MB + fe6306487029 Downloading 19.92MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 22.02MB + fe6306487029 Downloading 20.97MB + 0ad2438e159e Downloading 18.87MB + fe6306487029 Downloading 20.97MB + 0ad2438e159e Downloading 18.87MB + 1cc0ff6cea1d Downloading 22.02MB + 0ad2438e159e Downloading 19.92MB + fe6306487029 Downloading 20.97MB + 1cc0ff6cea1d Downloading 22.02MB + fe6306487029 Downloading 20.97MB + 0ad2438e159e Downloading 19.92MB + 1cc0ff6cea1d Downloading 22.02MB + fe6306487029 Downloading 20.97MB + 0ad2438e159e Downloading 19.92MB + 1cc0ff6cea1d Downloading 22.02MB + 1cc0ff6cea1d Downloading 22.02MB + 0ad2438e159e Downloading 19.92MB + fe6306487029 Downloading 20.97MB + 1cc0ff6cea1d Downloading 22.02MB + fe6306487029 Downloading 20.97MB + 0ad2438e159e Downloading 19.92MB + 1cc0ff6cea1d Downloading 22.02MB + fe6306487029 Downloading 20.97MB + 0ad2438e159e Downloading 19.92MB + 1cc0ff6cea1d Downloading 22.02MB + fe6306487029 Downloading 20.97MB + 0ad2438e159e Downloading 19.92MB + fe6306487029 Downloading 20.97MB + 0ad2438e159e Downloading 19.92MB + 1cc0ff6cea1d Downloading 22.02MB + 1cc0ff6cea1d Downloading 22.02MB + fe6306487029 Downloading 20.97MB + 0ad2438e159e Downloading 19.92MB + 1cc0ff6cea1d Downloading 23.07MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 19.92MB + 1cc0ff6cea1d Downloading 23.07MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 19.92MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 19.92MB + 1cc0ff6cea1d Downloading 23.07MB + 1cc0ff6cea1d Downloading 23.07MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 20.97MB + 1cc0ff6cea1d Downloading 23.07MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 20.97MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 20.97MB + 1cc0ff6cea1d Downloading 23.07MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 20.97MB + 1cc0ff6cea1d Downloading 23.07MB + 1cc0ff6cea1d Downloading 23.07MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 20.97MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 20.97MB + 1cc0ff6cea1d Downloading 23.07MB + 1cc0ff6cea1d Downloading 23.07MB + fe6306487029 Downloading 22.02MB + 0ad2438e159e Downloading 20.97MB + fe6306487029 Downloading 23.07MB + 0ad2438e159e Downloading 20.97MB + 1cc0ff6cea1d Downloading 23.07MB + fe6306487029 Downloading 23.07MB + 0ad2438e159e Downloading 20.97MB + 1cc0ff6cea1d Downloading 23.07MB + 1cc0ff6cea1d Downloading 23.07MB + 0ad2438e159e Downloading 22.02MB + fe6306487029 Downloading 23.07MB + fe6306487029 Downloading 23.07MB + 0ad2438e159e Downloading 22.02MB + 1cc0ff6cea1d Downloading 24.12MB + fe6306487029 Downloading 23.07MB + 0ad2438e159e Downloading 22.02MB + 1cc0ff6cea1d Downloading 24.12MB + 1cc0ff6cea1d Downloading 24.12MB + fe6306487029 Downloading 23.07MB + 0ad2438e159e Downloading 22.02MB + 1cc0ff6cea1d Downloading 24.12MB + fe6306487029 Downloading 23.07MB + 0ad2438e159e Downloading 22.02MB + 1cc0ff6cea1d Downloading 24.12MB + fe6306487029 Downloading 24.12MB + 0ad2438e159e Downloading 22.02MB + 1cc0ff6cea1d Downloading 24.12MB + fe6306487029 Downloading 24.12MB + 0ad2438e159e Downloading 22.02MB + 1cc0ff6cea1d Downloading 24.12MB + fe6306487029 Downloading 24.12MB + 0ad2438e159e Downloading 23.07MB + fe6306487029 Downloading 24.12MB + 0ad2438e159e Downloading 23.07MB + 1cc0ff6cea1d Downloading 24.12MB + fe6306487029 Downloading 24.12MB + 0ad2438e159e Downloading 23.07MB + 1cc0ff6cea1d Downloading 24.12MB + 1cc0ff6cea1d Downloading 25.17MB + fe6306487029 Downloading 24.12MB + 0ad2438e159e Downloading 23.07MB + fe6306487029 Downloading 25.17MB + 0ad2438e159e Downloading 23.07MB + 1cc0ff6cea1d Downloading 25.17MB + 1cc0ff6cea1d Downloading 25.17MB + 0ad2438e159e Downloading 23.07MB + fe6306487029 Downloading 25.17MB + fe6306487029 Downloading 25.17MB + 0ad2438e159e Downloading 24.12MB + 1cc0ff6cea1d Downloading 25.17MB + fe6306487029 Downloading 25.17MB + 0ad2438e159e Downloading 24.12MB + 1cc0ff6cea1d Downloading 25.17MB + 1cc0ff6cea1d Downloading 25.17MB + fe6306487029 Downloading 25.17MB + 0ad2438e159e Downloading 24.12MB + fe6306487029 Downloading 25.17MB + 0ad2438e159e Downloading 24.12MB + 1cc0ff6cea1d Downloading 25.17MB + 1cc0ff6cea1d Downloading 25.17MB + fe6306487029 Downloading 25.17MB + 0ad2438e159e Downloading 24.12MB + 1cc0ff6cea1d Downloading 25.17MB + fe6306487029 Downloading 25.17MB + 0ad2438e159e Downloading 24.12MB + 1cc0ff6cea1d Downloading 26.21MB + fe6306487029 Downloading 26.21MB + 0ad2438e159e Downloading 24.12MB + 1cc0ff6cea1d Downloading 26.21MB + fe6306487029 Downloading 26.21MB + 0ad2438e159e Downloading 25.17MB + fe6306487029 Downloading 26.21MB + 0ad2438e159e Downloading 25.17MB + 1cc0ff6cea1d Downloading 26.21MB + 1cc0ff6cea1d Downloading 26.21MB + 0ad2438e159e Downloading 25.17MB + fe6306487029 Downloading 26.21MB + 1cc0ff6cea1d Downloading 26.21MB + fe6306487029 Downloading 26.21MB + 0ad2438e159e Downloading 25.17MB + fe6306487029 Downloading 26.21MB + 0ad2438e159e Downloading 25.17MB + 1cc0ff6cea1d Downloading 26.21MB + 1cc0ff6cea1d Downloading 26.21MB + fe6306487029 Downloading 27.26MB + 0ad2438e159e Downloading 25.17MB + fe6306487029 Downloading 27.26MB + 0ad2438e159e Downloading 26.21MB + 1cc0ff6cea1d Downloading 26.21MB + fe6306487029 Downloading 27.26MB + 0ad2438e159e Downloading 26.21MB + 1cc0ff6cea1d Downloading 27.26MB + 1cc0ff6cea1d Downloading 27.26MB + fe6306487029 Downloading 27.26MB + 0ad2438e159e Downloading 26.21MB + fe6306487029 Downloading 27.26MB + 0ad2438e159e Downloading 26.21MB + 1cc0ff6cea1d Downloading 27.26MB + 1cc0ff6cea1d Downloading 27.26MB + fe6306487029 Downloading 27.26MB + 0ad2438e159e Downloading 26.21MB + 1cc0ff6cea1d Downloading 27.26MB + fe6306487029 Downloading 28.31MB + 0ad2438e159e Downloading 26.21MB + 1cc0ff6cea1d Downloading 27.26MB + fe6306487029 Downloading 28.31MB + 0ad2438e159e Downloading 27.26MB + 1cc0ff6cea1d Downloading 27.26MB + fe6306487029 Downloading 28.31MB + 0ad2438e159e Downloading 27.26MB + 1cc0ff6cea1d Downloading 28.31MB + fe6306487029 Downloading 28.31MB + 0ad2438e159e Downloading 27.26MB + fe6306487029 Downloading 28.31MB + 0ad2438e159e Downloading 27.26MB + 1cc0ff6cea1d Downloading 28.31MB + 0ad2438e159e Downloading 27.26MB + fe6306487029 Downloading 28.31MB + 1cc0ff6cea1d Downloading 28.31MB + 1cc0ff6cea1d Downloading 28.31MB + fe6306487029 Downloading 29.36MB + 0ad2438e159e Downloading 27.26MB + 1cc0ff6cea1d Downloading 28.31MB + fe6306487029 Downloading 29.36MB + 0ad2438e159e Downloading 27.26MB + fe6306487029 Downloading 29.36MB + 0ad2438e159e Downloading 28.31MB + 1cc0ff6cea1d Downloading 28.31MB + 1cc0ff6cea1d Downloading 29.36MB + fe6306487029 Downloading 29.36MB + 0ad2438e159e Downloading 28.31MB + 1cc0ff6cea1d Downloading 29.36MB + fe6306487029 Downloading 29.36MB + 0ad2438e159e Downloading 28.31MB + 1cc0ff6cea1d Downloading 29.36MB + fe6306487029 Downloading 30.41MB + 0ad2438e159e Downloading 28.31MB + 1cc0ff6cea1d Downloading 29.36MB + fe6306487029 Downloading 30.41MB + 0ad2438e159e Downloading 28.31MB + 1cc0ff6cea1d Downloading 29.36MB + fe6306487029 Downloading 30.41MB + 0ad2438e159e Downloading 28.31MB + 1cc0ff6cea1d Downloading 29.36MB + fe6306487029 Downloading 30.41MB + 0ad2438e159e Downloading 28.31MB + 1cc0ff6cea1d Downloading 29.36MB + fe6306487029 Downloading 30.41MB + 0ad2438e159e Downloading 29.36MB + 1cc0ff6cea1d Downloading 30.41MB + 0ad2438e159e Downloading 29.36MB + fe6306487029 Downloading 30.41MB + 1cc0ff6cea1d Downloading 30.41MB + fe6306487029 Downloading 31.46MB + 0ad2438e159e Downloading 29.36MB + fe6306487029 Downloading 31.46MB + 0ad2438e159e Downloading 29.36MB + 1cc0ff6cea1d Downloading 30.41MB + 1cc0ff6cea1d Downloading 30.41MB + fe6306487029 Downloading 31.46MB + 0ad2438e159e Downloading 29.36MB + fe6306487029 Downloading 31.46MB + 0ad2438e159e Downloading 29.36MB + 1cc0ff6cea1d Downloading 30.41MB + 1cc0ff6cea1d Downloading 30.41MB + fe6306487029 Downloading 31.46MB + 0ad2438e159e Downloading 29.36MB + 1cc0ff6cea1d Downloading 30.41MB + fe6306487029 Downloading 31.46MB + 0ad2438e159e Downloading 29.36MB + 1cc0ff6cea1d Downloading 31.46MB + fe6306487029 Downloading 31.46MB + 0ad2438e159e Downloading 30.41MB + fe6306487029 Downloading 32.51MB + 0ad2438e159e Downloading 30.41MB + 1cc0ff6cea1d Downloading 31.46MB + 0ad2438e159e Downloading 30.41MB + fe6306487029 Downloading 32.51MB + 1cc0ff6cea1d Downloading 31.46MB + fe6306487029 Downloading 32.51MB + 0ad2438e159e Downloading 30.41MB + 1cc0ff6cea1d Downloading 31.46MB + 1cc0ff6cea1d Downloading 31.46MB + fe6306487029 Downloading 32.51MB + 0ad2438e159e Downloading 30.41MB + 1cc0ff6cea1d Downloading 31.46MB + fe6306487029 Downloading 32.51MB + 0ad2438e159e Downloading 30.41MB + fe6306487029 Downloading 32.51MB + 0ad2438e159e Downloading 30.41MB + 1cc0ff6cea1d Downloading 31.46MB + 1cc0ff6cea1d Downloading 32.51MB + fe6306487029 Downloading 32.51MB + 0ad2438e159e Downloading 30.41MB + 1cc0ff6cea1d Downloading 32.51MB + fe6306487029 Downloading 32.51MB + 0ad2438e159e Downloading 31.46MB + 1cc0ff6cea1d Downloading 32.51MB + fe6306487029 Downloading 32.51MB + 0ad2438e159e Downloading 31.46MB + 1cc0ff6cea1d Downloading 32.51MB + fe6306487029 Downloading 32.51MB + 0ad2438e159e Downloading 31.46MB + 1cc0ff6cea1d Downloading 32.51MB + fe6306487029 Downloading 33.55MB + 0ad2438e159e Downloading 31.46MB + 1cc0ff6cea1d Downloading 32.51MB + fe6306487029 Downloading 33.55MB + 0ad2438e159e Downloading 31.46MB + 1cc0ff6cea1d Downloading 32.51MB + 0ad2438e159e Downloading 31.46MB + fe6306487029 Downloading 33.55MB + 1cc0ff6cea1d Downloading 32.51MB + fe6306487029 Downloading 33.55MB + 0ad2438e159e Downloading 31.46MB + fe6306487029 Downloading 33.55MB + 0ad2438e159e Downloading 32.51MB + 1cc0ff6cea1d Downloading 32.51MB + 1cc0ff6cea1d Downloading 33.55MB + 0ad2438e159e Downloading 32.51MB + fe6306487029 Downloading 33.55MB + 1cc0ff6cea1d Downloading 33.55MB + fe6306487029 Downloading 33.55MB + 0ad2438e159e Downloading 32.51MB + fe6306487029 Downloading 33.55MB + 0ad2438e159e Downloading 32.51MB + 1cc0ff6cea1d Downloading 33.55MB + 1cc0ff6cea1d Downloading 33.55MB + fe6306487029 Downloading 33.55MB + 0ad2438e159e Downloading 32.51MB + fe6306487029 Downloading 34.6MB + 0ad2438e159e Downloading 32.51MB + 1cc0ff6cea1d Downloading 33.55MB + 1cc0ff6cea1d Downloading 33.55MB + fe6306487029 Downloading 34.6MB + 0ad2438e159e Downloading 33.55MB + 1cc0ff6cea1d Downloading 34.6MB + fe6306487029 Downloading 34.6MB + 0ad2438e159e Downloading 33.55MB + fe6306487029 Downloading 34.6MB + 0ad2438e159e Downloading 33.55MB + 1cc0ff6cea1d Downloading 34.6MB + 1cc0ff6cea1d Downloading 34.6MB + fe6306487029 Downloading 34.6MB + 0ad2438e159e Downloading 33.55MB + 1cc0ff6cea1d Downloading 34.6MB + fe6306487029 Downloading 34.6MB + 0ad2438e159e Downloading 33.55MB + 1cc0ff6cea1d Downloading 34.6MB + 0ad2438e159e Downloading 34.6MB + fe6306487029 Downloading 34.6MB + 1cc0ff6cea1d Downloading 34.6MB + fe6306487029 Downloading 35.65MB + 0ad2438e159e Downloading 34.6MB + 1cc0ff6cea1d Downloading 34.6MB + fe6306487029 Downloading 35.65MB + 0ad2438e159e Downloading 34.6MB + 0ad2438e159e Downloading 34.6MB + fe6306487029 Downloading 35.65MB + 1cc0ff6cea1d Downloading 35.65MB + 1cc0ff6cea1d Downloading 35.65MB + 0ad2438e159e Downloading 34.6MB + fe6306487029 Downloading 35.65MB + 1cc0ff6cea1d Downloading 35.65MB + fe6306487029 Downloading 35.65MB + 0ad2438e159e Downloading 34.6MB + 1cc0ff6cea1d Downloading 35.65MB + fe6306487029 Downloading 35.65MB + 0ad2438e159e Downloading 35.65MB + 0ad2438e159e Downloading 35.65MB + fe6306487029 Downloading 36.7MB + 1cc0ff6cea1d Downloading 35.65MB + 1cc0ff6cea1d Downloading 35.65MB + fe6306487029 Downloading 36.7MB + 0ad2438e159e Downloading 35.65MB + 1cc0ff6cea1d Downloading 35.65MB + fe6306487029 Downloading 36.7MB + 0ad2438e159e Downloading 35.65MB + 1cc0ff6cea1d Downloading 36.7MB + fe6306487029 Downloading 36.7MB + 0ad2438e159e Downloading 35.65MB + fe6306487029 Downloading 36.7MB + 0ad2438e159e Downloading 35.65MB + 1cc0ff6cea1d Downloading 36.7MB + 1cc0ff6cea1d Downloading 36.7MB + fe6306487029 Downloading 36.7MB + 0ad2438e159e Downloading 35.65MB + 1cc0ff6cea1d Downloading 36.7MB + fe6306487029 Downloading 37.75MB + 0ad2438e159e Downloading 35.65MB + fe6306487029 Downloading 37.75MB + 0ad2438e159e Downloading 35.65MB + 1cc0ff6cea1d Downloading 36.7MB + 1cc0ff6cea1d Downloading 36.7MB + fe6306487029 Downloading 37.75MB + 0ad2438e159e Downloading 36.7MB + 1cc0ff6cea1d Downloading 37.75MB + fe6306487029 Downloading 37.75MB + 0ad2438e159e Downloading 36.7MB + 1cc0ff6cea1d Downloading 37.75MB + fe6306487029 Downloading 37.75MB + 0ad2438e159e Downloading 36.7MB + 1cc0ff6cea1d Downloading 37.75MB + fe6306487029 Downloading 37.75MB + 0ad2438e159e Downloading 36.7MB + fe6306487029 Downloading 38.8MB + 0ad2438e159e Downloading 36.7MB + 1cc0ff6cea1d Downloading 37.75MB + fe6306487029 Downloading 38.8MB + 0ad2438e159e Downloading 36.7MB + 1cc0ff6cea1d Downloading 37.75MB + 1cc0ff6cea1d Downloading 37.75MB + fe6306487029 Downloading 38.8MB + 0ad2438e159e Downloading 36.7MB + 1cc0ff6cea1d Downloading 37.75MB + fe6306487029 Downloading 38.8MB + 0ad2438e159e Downloading 37.75MB + 1cc0ff6cea1d Downloading 38.8MB + fe6306487029 Downloading 38.8MB + 0ad2438e159e Downloading 37.75MB + 1cc0ff6cea1d Downloading 38.8MB + fe6306487029 Downloading 39.85MB + 0ad2438e159e Downloading 37.75MB + 1cc0ff6cea1d Downloading 38.8MB + fe6306487029 Downloading 39.85MB + 0ad2438e159e Downloading 37.75MB + 0ad2438e159e Downloading 37.75MB + fe6306487029 Downloading 39.85MB + 1cc0ff6cea1d Downloading 38.8MB + 1cc0ff6cea1d Downloading 38.8MB + fe6306487029 Downloading 39.85MB + 0ad2438e159e Downloading 37.75MB + 1cc0ff6cea1d Downloading 38.8MB + fe6306487029 Downloading 40.89MB + 0ad2438e159e Downloading 37.75MB + fe6306487029 Downloading 40.89MB + 0ad2438e159e Downloading 37.75MB + 1cc0ff6cea1d Downloading 38.8MB + 1cc0ff6cea1d Downloading 39.85MB + fe6306487029 Downloading 40.89MB + 0ad2438e159e Downloading 38.8MB + 1cc0ff6cea1d Downloading 39.85MB + 0ad2438e159e Downloading 38.8MB + fe6306487029 Downloading 40.89MB + fe6306487029 Downloading 40.89MB + 0ad2438e159e Downloading 38.8MB + 1cc0ff6cea1d Downloading 39.85MB + fe6306487029 Downloading 40.89MB + 0ad2438e159e Downloading 38.8MB + 1cc0ff6cea1d Downloading 39.85MB + 1cc0ff6cea1d Downloading 39.85MB + 0ad2438e159e Downloading 38.8MB + fe6306487029 Downloading 41.94MB + fe6306487029 Downloading 41.94MB + 0ad2438e159e Downloading 38.8MB + 1cc0ff6cea1d Downloading 39.85MB + fe6306487029 Downloading 41.94MB + 0ad2438e159e Downloading 38.8MB + 1cc0ff6cea1d Downloading 39.85MB + 1cc0ff6cea1d Downloading 40.89MB + 0ad2438e159e Downloading 38.8MB + fe6306487029 Downloading 41.94MB + 1cc0ff6cea1d Downloading 40.89MB + fe6306487029 Downloading 42.99MB + 0ad2438e159e Downloading 39.85MB + 1cc0ff6cea1d Downloading 40.89MB + fe6306487029 Downloading 42.99MB + 0ad2438e159e Downloading 39.85MB + 1cc0ff6cea1d Downloading 40.89MB + fe6306487029 Downloading 42.99MB + 0ad2438e159e Downloading 39.85MB + 1cc0ff6cea1d Downloading 40.89MB + fe6306487029 Downloading 42.99MB + 0ad2438e159e Downloading 39.85MB + 1cc0ff6cea1d Downloading 40.89MB + fe6306487029 Downloading 42.99MB + 0ad2438e159e Downloading 39.85MB + 1cc0ff6cea1d Downloading 40.89MB + fe6306487029 Downloading 42.99MB + 0ad2438e159e Downloading 39.85MB + fe6306487029 Downloading 44.04MB + 0ad2438e159e Downloading 39.85MB + 1cc0ff6cea1d Downloading 40.89MB + 1cc0ff6cea1d Downloading 40.89MB + fe6306487029 Downloading 44.04MB + 0ad2438e159e Downloading 39.85MB + 1cc0ff6cea1d Downloading 41.94MB + fe6306487029 Downloading 44.04MB + 0ad2438e159e Downloading 39.85MB + fe6306487029 Downloading 44.04MB + 0ad2438e159e Downloading 39.85MB + 1cc0ff6cea1d Downloading 41.94MB + fe6306487029 Downloading 44.04MB + 0ad2438e159e Downloading 39.85MB + 1cc0ff6cea1d Downloading 41.94MB + 1cc0ff6cea1d Downloading 41.94MB + fe6306487029 Downloading 44.04MB + 0ad2438e159e Downloading 40.89MB + 1cc0ff6cea1d Downloading 41.94MB + fe6306487029 Downloading 45.09MB + 0ad2438e159e Downloading 40.89MB + 1cc0ff6cea1d Downloading 41.94MB + 0ad2438e159e Downloading 40.89MB + fe6306487029 Downloading 45.09MB + 1cc0ff6cea1d Downloading 41.94MB + fe6306487029 Downloading 45.09MB + 0ad2438e159e Downloading 40.89MB + fe6306487029 Downloading 45.09MB + 0ad2438e159e Downloading 40.89MB + 1cc0ff6cea1d Downloading 41.94MB + fe6306487029 Downloading 45.09MB + 0ad2438e159e Downloading 40.89MB + 1cc0ff6cea1d Downloading 42.99MB + fe6306487029 Downloading 45.09MB + 0ad2438e159e Downloading 40.89MB + 1cc0ff6cea1d Downloading 42.99MB + 1cc0ff6cea1d Downloading 42.99MB + fe6306487029 Downloading 45.09MB + 0ad2438e159e Downloading 40.89MB + 1cc0ff6cea1d Downloading 42.99MB + fe6306487029 Downloading 45.09MB + 0ad2438e159e Downloading 40.89MB + 1cc0ff6cea1d Downloading 42.99MB + fe6306487029 Downloading 46.14MB + 0ad2438e159e Downloading 40.89MB + 1cc0ff6cea1d Downloading 42.99MB + 0ad2438e159e Downloading 40.89MB + fe6306487029 Downloading 46.14MB + 1cc0ff6cea1d Downloading 42.99MB + fe6306487029 Downloading 46.14MB + 0ad2438e159e Downloading 41.94MB + 1cc0ff6cea1d Downloading 42.99MB + fe6306487029 Downloading 46.14MB + 0ad2438e159e Downloading 41.94MB + 1cc0ff6cea1d Downloading 42.99MB + fe6306487029 Downloading 46.14MB + 0ad2438e159e Downloading 41.94MB + fe6306487029 Downloading 46.14MB + 0ad2438e159e Downloading 41.94MB + 1cc0ff6cea1d Downloading 44.04MB + 1cc0ff6cea1d Downloading 44.04MB + fe6306487029 Downloading 46.14MB + 0ad2438e159e Downloading 41.94MB + fe6306487029 Downloading 46.14MB + 0ad2438e159e Downloading 41.94MB + 1cc0ff6cea1d Downloading 44.04MB + 1cc0ff6cea1d Downloading 44.04MB + fe6306487029 Downloading 47.19MB + 0ad2438e159e Downloading 41.94MB + 1cc0ff6cea1d Downloading 44.04MB + fe6306487029 Downloading 47.19MB + 0ad2438e159e Downloading 41.94MB + 1cc0ff6cea1d Downloading 44.04MB + fe6306487029 Downloading 47.19MB + 0ad2438e159e Downloading 42.99MB + 1cc0ff6cea1d Downloading 44.04MB + fe6306487029 Downloading 47.19MB + 0ad2438e159e Downloading 42.99MB + 1cc0ff6cea1d Downloading 45.09MB + fe6306487029 Downloading 47.19MB + 0ad2438e159e Downloading 42.99MB + 1cc0ff6cea1d Downloading 45.09MB + fe6306487029 Downloading 47.19MB + 0ad2438e159e Downloading 42.99MB + 1cc0ff6cea1d Downloading 45.09MB + fe6306487029 Downloading 47.19MB + 0ad2438e159e Downloading 42.99MB + fe6306487029 Downloading 48.23MB + 0ad2438e159e Downloading 42.99MB + 1cc0ff6cea1d Downloading 45.09MB + 1cc0ff6cea1d Downloading 45.09MB + 0ad2438e159e Downloading 42.99MB + fe6306487029 Downloading 48.23MB + 1cc0ff6cea1d Downloading 45.09MB + fe6306487029 Downloading 48.23MB + 0ad2438e159e Downloading 42.99MB + 1cc0ff6cea1d Downloading 45.09MB + fe6306487029 Downloading 48.23MB + 0ad2438e159e Downloading 42.99MB + 1cc0ff6cea1d Downloading 45.09MB + fe6306487029 Downloading 48.23MB + 0ad2438e159e Downloading 44.04MB + 1cc0ff6cea1d Downloading 45.09MB + fe6306487029 Downloading 48.23MB + 0ad2438e159e Downloading 44.04MB + 0ad2438e159e Downloading 44.04MB + fe6306487029 Downloading 49.28MB + 1cc0ff6cea1d Downloading 46.14MB + 1cc0ff6cea1d Downloading 46.14MB + fe6306487029 Downloading 49.28MB + 0ad2438e159e Downloading 44.04MB + 1cc0ff6cea1d Downloading 46.14MB + fe6306487029 Downloading 49.28MB + 0ad2438e159e Downloading 44.04MB + 1cc0ff6cea1d Downloading 46.14MB + fe6306487029 Downloading 49.28MB + 0ad2438e159e Downloading 44.04MB + fe6306487029 Downloading 49.28MB + 0ad2438e159e Downloading 44.04MB + 1cc0ff6cea1d Downloading 46.14MB + 1cc0ff6cea1d Downloading 46.14MB + fe6306487029 Downloading 50.33MB + 0ad2438e159e Downloading 44.04MB + 1cc0ff6cea1d Downloading 46.14MB + fe6306487029 Downloading 50.33MB + 0ad2438e159e Downloading 45.09MB + 1cc0ff6cea1d Downloading 46.14MB + fe6306487029 Downloading 50.33MB + 0ad2438e159e Downloading 45.09MB + 1cc0ff6cea1d Downloading 47.19MB + fe6306487029 Downloading 50.33MB + 0ad2438e159e Downloading 45.09MB + fe6306487029 Downloading 50.33MB + 0ad2438e159e Downloading 45.09MB + 1cc0ff6cea1d Downloading 47.19MB + 1cc0ff6cea1d Downloading 47.19MB + fe6306487029 Downloading 50.33MB + 0ad2438e159e Downloading 45.09MB + fe6306487029 Downloading 51.38MB + 0ad2438e159e Downloading 45.09MB + 1cc0ff6cea1d Downloading 47.19MB + 0ad2438e159e Downloading 45.09MB + fe6306487029 Downloading 51.38MB + 1cc0ff6cea1d Downloading 47.19MB + 1cc0ff6cea1d Downloading 47.19MB + fe6306487029 Downloading 51.38MB + 0ad2438e159e Downloading 45.09MB + 1cc0ff6cea1d Downloading 47.19MB + fe6306487029 Downloading 51.38MB + 0ad2438e159e Downloading 45.09MB + 1cc0ff6cea1d Downloading 47.19MB + fe6306487029 Downloading 51.38MB + 0ad2438e159e Downloading 45.09MB + 1cc0ff6cea1d Downloading 48.23MB + fe6306487029 Downloading 51.38MB + 0ad2438e159e Downloading 45.09MB + 1cc0ff6cea1d Downloading 48.23MB + fe6306487029 Downloading 51.38MB + 0ad2438e159e Downloading 46.14MB + fe6306487029 Downloading 51.38MB + 0ad2438e159e Downloading 46.14MB + 1cc0ff6cea1d Downloading 48.23MB + fe6306487029 Downloading 51.38MB + 0ad2438e159e Downloading 46.14MB + 1cc0ff6cea1d Downloading 48.23MB + 1cc0ff6cea1d Downloading 48.23MB + fe6306487029 Downloading 52.43MB + 0ad2438e159e Downloading 46.14MB + fe6306487029 Downloading 52.43MB + 0ad2438e159e Downloading 46.14MB + 1cc0ff6cea1d Downloading 48.23MB + fe6306487029 Downloading 52.43MB + 0ad2438e159e Downloading 46.14MB + 1cc0ff6cea1d Downloading 48.23MB + 1cc0ff6cea1d Downloading 48.23MB + 0ad2438e159e Downloading 46.14MB + fe6306487029 Downloading 52.43MB + 1cc0ff6cea1d Downloading 49.28MB + 0ad2438e159e Downloading 46.14MB + fe6306487029 Downloading 52.43MB + fe6306487029 Downloading 52.43MB + 0ad2438e159e Downloading 46.14MB + 1cc0ff6cea1d Downloading 49.28MB + 1cc0ff6cea1d Downloading 49.28MB + 0ad2438e159e Downloading 46.14MB + fe6306487029 Downloading 52.43MB + 1cc0ff6cea1d Downloading 49.28MB + fe6306487029 Downloading 53.48MB + 0ad2438e159e Downloading 47.19MB + 1cc0ff6cea1d Downloading 49.28MB + fe6306487029 Downloading 53.48MB + 0ad2438e159e Downloading 47.19MB + fe6306487029 Downloading 53.48MB + 0ad2438e159e Downloading 47.19MB + 1cc0ff6cea1d Downloading 49.28MB + 1cc0ff6cea1d Downloading 49.28MB + fe6306487029 Downloading 53.48MB + 0ad2438e159e Downloading 47.19MB + 1cc0ff6cea1d Downloading 49.28MB + fe6306487029 Downloading 53.48MB + 0ad2438e159e Downloading 47.19MB + fe6306487029 Downloading 53.48MB + 0ad2438e159e Downloading 47.19MB + 1cc0ff6cea1d Downloading 49.28MB + 1cc0ff6cea1d Downloading 50.33MB + fe6306487029 Downloading 53.48MB + 0ad2438e159e Downloading 47.19MB + fe6306487029 Downloading 53.48MB + 0ad2438e159e Downloading 47.19MB + 1cc0ff6cea1d Downloading 50.33MB + 1cc0ff6cea1d Downloading 50.33MB + 0ad2438e159e Downloading 47.19MB + fe6306487029 Downloading 54.53MB + 1cc0ff6cea1d Downloading 50.33MB + fe6306487029 Downloading 54.53MB + 0ad2438e159e Downloading 48.23MB + fe6306487029 Downloading 54.53MB + 0ad2438e159e Downloading 48.23MB + 1cc0ff6cea1d Downloading 50.33MB + 1cc0ff6cea1d Downloading 50.33MB + fe6306487029 Downloading 54.53MB + 0ad2438e159e Downloading 48.23MB + fe6306487029 Downloading 54.53MB + 0ad2438e159e Downloading 48.23MB + 1cc0ff6cea1d Downloading 50.33MB + fe6306487029 Downloading 54.53MB + 0ad2438e159e Downloading 48.23MB + 1cc0ff6cea1d Downloading 50.33MB + 1cc0ff6cea1d Downloading 50.33MB + fe6306487029 Downloading 54.53MB + 0ad2438e159e Downloading 48.23MB + 1cc0ff6cea1d Downloading 50.33MB + fe6306487029 Downloading 54.53MB + 0ad2438e159e Downloading 48.23MB + 1cc0ff6cea1d Downloading 51.38MB + fe6306487029 Downloading 55.57MB + 0ad2438e159e Downloading 48.23MB + 1cc0ff6cea1d Downloading 51.38MB + 0ad2438e159e Downloading 48.23MB + fe6306487029 Downloading 55.57MB + 1cc0ff6cea1d Downloading 51.38MB + fe6306487029 Downloading 55.57MB + 0ad2438e159e Downloading 49.28MB + 1cc0ff6cea1d Downloading 51.38MB + fe6306487029 Downloading 55.57MB + 0ad2438e159e Downloading 49.28MB + 1cc0ff6cea1d Downloading 51.38MB + fe6306487029 Downloading 55.57MB + 0ad2438e159e Downloading 49.28MB + 1cc0ff6cea1d Downloading 51.38MB + fe6306487029 Downloading 55.57MB + 0ad2438e159e Downloading 49.28MB + 1cc0ff6cea1d Downloading 51.38MB + fe6306487029 Downloading 55.57MB + 0ad2438e159e Downloading 49.28MB + 1cc0ff6cea1d Downloading 51.38MB + fe6306487029 Downloading 55.57MB + 0ad2438e159e Downloading 49.28MB + fe6306487029 Downloading 55.57MB + 0ad2438e159e Downloading 49.28MB + 1cc0ff6cea1d Downloading 52.43MB + 1cc0ff6cea1d Downloading 52.43MB + fe6306487029 Downloading 56.62MB + 0ad2438e159e Downloading 49.28MB + fe6306487029 Downloading 56.62MB + 0ad2438e159e Downloading 50.33MB + 1cc0ff6cea1d Downloading 52.43MB + fe6306487029 Downloading 56.62MB + 0ad2438e159e Downloading 50.33MB + 1cc0ff6cea1d Downloading 52.43MB + 1cc0ff6cea1d Downloading 52.43MB + fe6306487029 Downloading 56.62MB + 0ad2438e159e Downloading 50.33MB + 1cc0ff6cea1d Downloading 52.43MB + fe6306487029 Downloading 56.62MB + 0ad2438e159e Downloading 50.33MB + 1cc0ff6cea1d Downloading 52.43MB + fe6306487029 Downloading 56.62MB + 0ad2438e159e Downloading 50.33MB + 1cc0ff6cea1d Downloading 52.43MB + fe6306487029 Downloading 56.62MB + 0ad2438e159e Downloading 50.33MB + 1cc0ff6cea1d Downloading 53.48MB + fe6306487029 Download complete 0B + 0ad2438e159e Downloading 50.33MB + fe6306487029 Extracting 1B + 1cc0ff6cea1d Downloading 53.48MB + 0ad2438e159e Downloading 50.33MB + fe6306487029 Extracting 1B + 0ad2438e159e Downloading 50.33MB + 1cc0ff6cea1d Downloading 53.48MB + fe6306487029 Extracting 1B + 1cc0ff6cea1d Downloading 53.48MB + 0ad2438e159e Downloading 51.38MB + fe6306487029 Pull complete 0B + 0ad2438e159e Downloading 51.38MB + 1cc0ff6cea1d Downloading 53.48MB + 1cc0ff6cea1d Downloading 53.48MB + 0ad2438e159e Downloading 51.38MB + 1cc0ff6cea1d Downloading 53.48MB + 0ad2438e159e Downloading 51.38MB + 1cc0ff6cea1d Downloading 53.48MB + 0ad2438e159e Download complete 0B + 0ad2438e159e Extracting 1B + 1cc0ff6cea1d Downloading 54.53MB + 0ad2438e159e Extracting 1B + 1cc0ff6cea1d Downloading 54.53MB + 0ad2438e159e Extracting 1B + 1cc0ff6cea1d Downloading 54.53MB + 0ad2438e159e Extracting 1B + 81d14c078a74 Pull complete 0B + f5d2fa6280ad Pull complete 0B + 073d75ee84d4 Pull complete 0B + c8c5fe18afab Pull complete 0B + 1cc0ff6cea1d Downloading 54.53MB + 34c169812ca7 Pull complete 0B + c390b3ff97f5 Pull complete 0B + 0ad2438e159e Pull complete 0B + Image prom/prometheus:v3.2.1 Pulled + 1cc0ff6cea1d Downloading 54.53MB + 1cc0ff6cea1d Downloading 54.53MB + 1cc0ff6cea1d Downloading 54.53MB + 1cc0ff6cea1d Downloading 54.53MB + 1cc0ff6cea1d Downloading 54.53MB + 1cc0ff6cea1d Downloading 55.57MB + 1cc0ff6cea1d Downloading 55.57MB + 1cc0ff6cea1d Downloading 55.57MB + 1cc0ff6cea1d Downloading 55.57MB + 1cc0ff6cea1d Downloading 55.57MB + 1cc0ff6cea1d Downloading 55.57MB + 1cc0ff6cea1d Downloading 55.57MB + 1cc0ff6cea1d Downloading 56.62MB + 1cc0ff6cea1d Downloading 56.62MB + 1cc0ff6cea1d Downloading 56.62MB + 1cc0ff6cea1d Downloading 56.62MB + 1cc0ff6cea1d Downloading 56.62MB + 1cc0ff6cea1d Downloading 56.62MB + 1cc0ff6cea1d Downloading 56.62MB + 1cc0ff6cea1d Downloading 56.62MB + 1cc0ff6cea1d Downloading 56.62MB + 1cc0ff6cea1d Downloading 57.67MB + 1cc0ff6cea1d Downloading 57.67MB + 1cc0ff6cea1d Downloading 57.67MB + 1cc0ff6cea1d Downloading 57.67MB + 1cc0ff6cea1d Downloading 57.67MB + 1cc0ff6cea1d Downloading 57.67MB + 1cc0ff6cea1d Downloading 57.67MB + 1cc0ff6cea1d Downloading 58.72MB + 1cc0ff6cea1d Downloading 58.72MB + 1cc0ff6cea1d Downloading 58.72MB + 1cc0ff6cea1d Downloading 58.72MB + 1cc0ff6cea1d Downloading 58.72MB + 1cc0ff6cea1d Downloading 58.72MB + 1cc0ff6cea1d Downloading 58.72MB + 1cc0ff6cea1d Downloading 59.77MB + 1cc0ff6cea1d Downloading 59.77MB + 1cc0ff6cea1d Downloading 59.77MB + 1cc0ff6cea1d Downloading 59.77MB + 1cc0ff6cea1d Downloading 59.77MB + 1cc0ff6cea1d Downloading 59.77MB + 1cc0ff6cea1d Downloading 59.77MB + 1cc0ff6cea1d Downloading 60.82MB + 1cc0ff6cea1d Downloading 60.82MB + 1cc0ff6cea1d Downloading 60.82MB + 1cc0ff6cea1d Downloading 60.82MB + 1cc0ff6cea1d Downloading 60.82MB + 1cc0ff6cea1d Downloading 60.82MB + 1cc0ff6cea1d Downloading 60.82MB + 1cc0ff6cea1d Downloading 60.82MB + 1cc0ff6cea1d Downloading 61.87MB + 1cc0ff6cea1d Downloading 61.87MB + 1cc0ff6cea1d Downloading 61.87MB + 1cc0ff6cea1d Downloading 61.87MB + 1cc0ff6cea1d Downloading 61.87MB + 1cc0ff6cea1d Downloading 61.87MB + 1cc0ff6cea1d Downloading 61.87MB + 1cc0ff6cea1d Downloading 62.91MB + 1cc0ff6cea1d Downloading 62.91MB + 1cc0ff6cea1d Downloading 62.91MB + 1cc0ff6cea1d Downloading 62.91MB + 1cc0ff6cea1d Downloading 62.91MB + 1cc0ff6cea1d Downloading 62.91MB + 1cc0ff6cea1d Downloading 63.96MB + 1cc0ff6cea1d Downloading 63.96MB + 1cc0ff6cea1d Downloading 63.96MB + 1cc0ff6cea1d Downloading 63.96MB + 1cc0ff6cea1d Downloading 63.96MB + 1cc0ff6cea1d Downloading 63.96MB + 1cc0ff6cea1d Downloading 63.96MB + 1cc0ff6cea1d Downloading 63.96MB + 1cc0ff6cea1d Downloading 65.01MB + 1cc0ff6cea1d Downloading 65.01MB + 1cc0ff6cea1d Downloading 65.01MB + 1cc0ff6cea1d Downloading 65.01MB + 1cc0ff6cea1d Downloading 65.01MB + 1cc0ff6cea1d Downloading 65.01MB + 1cc0ff6cea1d Downloading 65.01MB + 1cc0ff6cea1d Downloading 65.01MB + 1cc0ff6cea1d Downloading 65.01MB + 1cc0ff6cea1d Downloading 66.06MB + 1cc0ff6cea1d Downloading 66.06MB + 1cc0ff6cea1d Downloading 66.06MB + 1cc0ff6cea1d Downloading 66.06MB + 1cc0ff6cea1d Downloading 66.06MB + 1cc0ff6cea1d Downloading 67.11MB + 1cc0ff6cea1d Downloading 67.11MB + 1cc0ff6cea1d Downloading 67.11MB + 1cc0ff6cea1d Downloading 67.11MB + 1cc0ff6cea1d Downloading 67.11MB + 1cc0ff6cea1d Downloading 67.11MB + 1cc0ff6cea1d Downloading 67.11MB + 1cc0ff6cea1d Downloading 68.16MB + 1cc0ff6cea1d Downloading 68.16MB + 1cc0ff6cea1d Downloading 68.16MB + 1cc0ff6cea1d Downloading 68.16MB + 1cc0ff6cea1d Downloading 68.16MB + 1cc0ff6cea1d Downloading 69.21MB + 1cc0ff6cea1d Downloading 69.21MB + 1cc0ff6cea1d Downloading 69.21MB + 1cc0ff6cea1d Downloading 69.21MB + 1cc0ff6cea1d Downloading 70.25MB + 1cc0ff6cea1d Downloading 70.25MB + 1cc0ff6cea1d Downloading 70.25MB + 1cc0ff6cea1d Downloading 70.25MB + 1cc0ff6cea1d Downloading 70.25MB + 1cc0ff6cea1d Downloading 71.3MB + 1cc0ff6cea1d Downloading 71.3MB + 1cc0ff6cea1d Downloading 71.3MB + 1cc0ff6cea1d Downloading 71.3MB + 1cc0ff6cea1d Downloading 72.35MB + 1cc0ff6cea1d Downloading 72.35MB + 1cc0ff6cea1d Downloading 72.35MB + 1cc0ff6cea1d Downloading 72.35MB + 1cc0ff6cea1d Downloading 72.35MB + 1cc0ff6cea1d Downloading 73.4MB + 1cc0ff6cea1d Downloading 73.4MB + 1cc0ff6cea1d Downloading 73.4MB + 1cc0ff6cea1d Downloading 73.4MB + 1cc0ff6cea1d Downloading 73.4MB + 1cc0ff6cea1d Downloading 74.45MB + 1cc0ff6cea1d Downloading 74.45MB + 1cc0ff6cea1d Downloading 74.45MB + 1cc0ff6cea1d Downloading 74.45MB + 1cc0ff6cea1d Downloading 74.45MB + 1cc0ff6cea1d Downloading 75.5MB + 1cc0ff6cea1d Downloading 75.5MB + 1cc0ff6cea1d Downloading 75.5MB + 1cc0ff6cea1d Downloading 75.5MB + 1cc0ff6cea1d Downloading 75.5MB + 1cc0ff6cea1d Downloading 76.55MB + 1cc0ff6cea1d Downloading 76.55MB + 1cc0ff6cea1d Downloading 76.55MB + 1cc0ff6cea1d Downloading 76.55MB + 1cc0ff6cea1d Downloading 76.55MB + 1cc0ff6cea1d Downloading 77.59MB + 1cc0ff6cea1d Downloading 77.59MB + 1cc0ff6cea1d Downloading 77.59MB + 1cc0ff6cea1d Downloading 77.59MB + 1cc0ff6cea1d Downloading 78.64MB + 1cc0ff6cea1d Downloading 78.64MB + 1cc0ff6cea1d Downloading 78.64MB + 1cc0ff6cea1d Downloading 78.64MB + 1cc0ff6cea1d Downloading 78.64MB + 1cc0ff6cea1d Downloading 78.64MB + 1cc0ff6cea1d Downloading 79.69MB + 1cc0ff6cea1d Downloading 79.69MB + 1cc0ff6cea1d Downloading 79.69MB + 1cc0ff6cea1d Downloading 79.69MB + 1cc0ff6cea1d Downloading 79.69MB + 1cc0ff6cea1d Downloading 80.74MB + 1cc0ff6cea1d Downloading 80.74MB + 1cc0ff6cea1d Downloading 80.74MB + 1cc0ff6cea1d Downloading 80.74MB + 1cc0ff6cea1d Downloading 80.74MB + 1cc0ff6cea1d Downloading 80.74MB + 1cc0ff6cea1d Downloading 81.79MB + 1cc0ff6cea1d Downloading 81.79MB + 1cc0ff6cea1d Downloading 81.79MB + 1cc0ff6cea1d Downloading 81.79MB + 1cc0ff6cea1d Downloading 82.84MB + 1cc0ff6cea1d Downloading 82.84MB + 1cc0ff6cea1d Downloading 82.84MB + 1cc0ff6cea1d Downloading 82.84MB + 1cc0ff6cea1d Downloading 83.89MB + 1cc0ff6cea1d Downloading 83.89MB + 1cc0ff6cea1d Downloading 83.89MB + 1cc0ff6cea1d Downloading 83.89MB + 1cc0ff6cea1d Downloading 84.93MB + 1cc0ff6cea1d Downloading 84.93MB + 1cc0ff6cea1d Downloading 84.93MB + 1cc0ff6cea1d Downloading 84.93MB + 1cc0ff6cea1d Downloading 84.93MB + 1cc0ff6cea1d Downloading 84.93MB + 1cc0ff6cea1d Downloading 85.98MB + 1cc0ff6cea1d Downloading 85.98MB + 1cc0ff6cea1d Downloading 85.98MB + 1cc0ff6cea1d Downloading 85.98MB + 1cc0ff6cea1d Downloading 85.98MB + 1cc0ff6cea1d Downloading 87.03MB + 1cc0ff6cea1d Downloading 87.03MB + 1cc0ff6cea1d Downloading 87.03MB + 1cc0ff6cea1d Downloading 88.08MB + 1cc0ff6cea1d Downloading 88.08MB + 1cc0ff6cea1d Downloading 88.08MB + 1cc0ff6cea1d Downloading 89.13MB + 1cc0ff6cea1d Downloading 89.13MB + 1cc0ff6cea1d Downloading 89.13MB + 1cc0ff6cea1d Downloading 90.18MB + 1cc0ff6cea1d Downloading 90.18MB + 1cc0ff6cea1d Downloading 90.18MB + 1cc0ff6cea1d Downloading 90.18MB + 1cc0ff6cea1d Downloading 90.18MB + 1cc0ff6cea1d Downloading 91.23MB + 1cc0ff6cea1d Downloading 91.23MB + 1cc0ff6cea1d Downloading 91.23MB + 1cc0ff6cea1d Downloading 92.27MB + 1cc0ff6cea1d Downloading 92.27MB + 1cc0ff6cea1d Downloading 92.27MB + 1cc0ff6cea1d Downloading 93.32MB + 1cc0ff6cea1d Downloading 93.32MB + 1cc0ff6cea1d Downloading 93.32MB + 1cc0ff6cea1d Downloading 93.32MB + 1cc0ff6cea1d Downloading 94.37MB + 1cc0ff6cea1d Downloading 94.37MB + 1cc0ff6cea1d Downloading 94.37MB + 1cc0ff6cea1d Downloading 94.37MB + 1cc0ff6cea1d Downloading 95.42MB + 1cc0ff6cea1d Downloading 95.42MB + 1cc0ff6cea1d Downloading 95.42MB + 1cc0ff6cea1d Downloading 96.47MB + 1cc0ff6cea1d Downloading 96.47MB + 1cc0ff6cea1d Downloading 96.47MB + 1cc0ff6cea1d Downloading 97.52MB + 1cc0ff6cea1d Downloading 97.52MB + 1cc0ff6cea1d Downloading 97.52MB + 1cc0ff6cea1d Downloading 97.52MB + 1cc0ff6cea1d Downloading 98.57MB + 1cc0ff6cea1d Downloading 98.57MB + 1cc0ff6cea1d Downloading 98.57MB + 1cc0ff6cea1d Downloading 98.57MB + 1cc0ff6cea1d Downloading 98.57MB + 1cc0ff6cea1d Downloading 99.61MB + 1cc0ff6cea1d Downloading 99.61MB + 1cc0ff6cea1d Downloading 99.61MB + 1cc0ff6cea1d Downloading 99.61MB + 1cc0ff6cea1d Downloading 99.61MB + 1cc0ff6cea1d Downloading 99.61MB + 1cc0ff6cea1d Downloading 100.7MB + 1cc0ff6cea1d Downloading 100.7MB + 1cc0ff6cea1d Downloading 100.7MB + 1cc0ff6cea1d Downloading 100.7MB + 1cc0ff6cea1d Downloading 100.7MB + 1cc0ff6cea1d Downloading 100.7MB + 1cc0ff6cea1d Downloading 100.7MB + 1cc0ff6cea1d Downloading 101.7MB + 1cc0ff6cea1d Downloading 101.7MB + 1cc0ff6cea1d Downloading 101.7MB + 1cc0ff6cea1d Downloading 101.7MB + 1cc0ff6cea1d Downloading 101.7MB + 1cc0ff6cea1d Downloading 101.7MB + 1cc0ff6cea1d Downloading 101.7MB + 1cc0ff6cea1d Downloading 101.7MB + 1cc0ff6cea1d Downloading 102.8MB + 1cc0ff6cea1d Downloading 102.8MB + 1cc0ff6cea1d Downloading 102.8MB + 1cc0ff6cea1d Downloading 102.8MB + 1cc0ff6cea1d Downloading 102.8MB + 1cc0ff6cea1d Downloading 102.8MB + 1cc0ff6cea1d Downloading 103.8MB + 1cc0ff6cea1d Downloading 103.8MB + 1cc0ff6cea1d Downloading 103.8MB + 1cc0ff6cea1d Downloading 103.8MB + 1cc0ff6cea1d Downloading 103.8MB + 1cc0ff6cea1d Downloading 104.9MB + 1cc0ff6cea1d Downloading 104.9MB + 1cc0ff6cea1d Downloading 104.9MB + 1cc0ff6cea1d Downloading 104.9MB + 1cc0ff6cea1d Downloading 104.9MB + 1cc0ff6cea1d Downloading 104.9MB + 1cc0ff6cea1d Downloading 105.9MB + 1cc0ff6cea1d Downloading 105.9MB + 1cc0ff6cea1d Downloading 105.9MB + 1cc0ff6cea1d Downloading 105.9MB + 1cc0ff6cea1d Downloading 107MB + 1cc0ff6cea1d Downloading 107MB + 1cc0ff6cea1d Downloading 107MB + 1cc0ff6cea1d Downloading 107MB + 1cc0ff6cea1d Downloading 107MB + 1cc0ff6cea1d Downloading 108MB + 1cc0ff6cea1d Downloading 108MB + 1cc0ff6cea1d Downloading 108MB + 1cc0ff6cea1d Downloading 108MB + 1cc0ff6cea1d Downloading 109.1MB + 1cc0ff6cea1d Downloading 109.1MB + 1cc0ff6cea1d Downloading 109.1MB + 1cc0ff6cea1d Downloading 109.1MB + 1cc0ff6cea1d Downloading 110.1MB + 1cc0ff6cea1d Downloading 110.1MB + 1cc0ff6cea1d Downloading 110.1MB + 1cc0ff6cea1d Downloading 110.1MB + 1cc0ff6cea1d Downloading 110.1MB + 1cc0ff6cea1d Downloading 111.1MB + 1cc0ff6cea1d Downloading 111.1MB + 1cc0ff6cea1d Downloading 111.1MB + 1cc0ff6cea1d Downloading 111.1MB + 1cc0ff6cea1d Downloading 111.1MB + 1cc0ff6cea1d Downloading 112.2MB + 1cc0ff6cea1d Downloading 112.2MB + 1cc0ff6cea1d Downloading 112.2MB + 1cc0ff6cea1d Downloading 113.2MB + 1cc0ff6cea1d Downloading 113.2MB + 1cc0ff6cea1d Downloading 113.2MB + 1cc0ff6cea1d Downloading 113.2MB + 1cc0ff6cea1d Downloading 114.3MB + 1cc0ff6cea1d Downloading 114.3MB + 1cc0ff6cea1d Downloading 114.3MB + 1cc0ff6cea1d Downloading 114.3MB + 1cc0ff6cea1d Downloading 115.3MB + 1cc0ff6cea1d Downloading 115.3MB + 1cc0ff6cea1d Downloading 115.3MB + 1cc0ff6cea1d Downloading 115.3MB + 1cc0ff6cea1d Downloading 116.4MB + 1cc0ff6cea1d Downloading 116.4MB + 1cc0ff6cea1d Downloading 116.4MB + 1cc0ff6cea1d Downloading 117.4MB + 1cc0ff6cea1d Downloading 117.4MB + 1cc0ff6cea1d Downloading 117.4MB + 1cc0ff6cea1d Downloading 118.5MB + 1cc0ff6cea1d Downloading 118.5MB + 1cc0ff6cea1d Downloading 118.5MB + 1cc0ff6cea1d Downloading 118.5MB + 1cc0ff6cea1d Downloading 119.5MB + 1cc0ff6cea1d Downloading 119.5MB + 1cc0ff6cea1d Downloading 119.5MB + 1cc0ff6cea1d Downloading 119.5MB + 1cc0ff6cea1d Downloading 119.5MB + 1cc0ff6cea1d Downloading 120.6MB + 1cc0ff6cea1d Downloading 120.6MB + 1cc0ff6cea1d Downloading 120.6MB + 1cc0ff6cea1d Downloading 120.6MB + 1cc0ff6cea1d Downloading 120.6MB + 1cc0ff6cea1d Downloading 121.6MB + 1cc0ff6cea1d Downloading 121.6MB + 1cc0ff6cea1d Downloading 121.6MB + 1cc0ff6cea1d Downloading 121.6MB + 1cc0ff6cea1d Downloading 121.6MB + 1cc0ff6cea1d Downloading 122.7MB + 1cc0ff6cea1d Downloading 122.7MB + 1cc0ff6cea1d Downloading 122.7MB + 1cc0ff6cea1d Downloading 122.7MB + 1cc0ff6cea1d Downloading 122.7MB + 1cc0ff6cea1d Downloading 122.7MB + 1cc0ff6cea1d Downloading 123.7MB + 1cc0ff6cea1d Downloading 123.7MB + 1cc0ff6cea1d Downloading 123.7MB + 1cc0ff6cea1d Downloading 123.7MB + 1cc0ff6cea1d Downloading 124.8MB + 1cc0ff6cea1d Downloading 124.8MB + 1cc0ff6cea1d Downloading 124.8MB + 1cc0ff6cea1d Downloading 124.8MB + 1cc0ff6cea1d Downloading 125.8MB + 1cc0ff6cea1d Downloading 125.8MB + 1cc0ff6cea1d Downloading 125.8MB + 1cc0ff6cea1d Downloading 125.8MB + 1cc0ff6cea1d Downloading 125.8MB + 1cc0ff6cea1d Downloading 126.9MB + 1cc0ff6cea1d Downloading 126.9MB + 1cc0ff6cea1d Downloading 126.9MB + 1cc0ff6cea1d Downloading 126.9MB + 1cc0ff6cea1d Downloading 126.9MB + 1cc0ff6cea1d Downloading 127.9MB + 1cc0ff6cea1d Downloading 127.9MB + 1cc0ff6cea1d Downloading 127.9MB + 1cc0ff6cea1d Downloading 127.9MB + 1cc0ff6cea1d Downloading 129MB + 1cc0ff6cea1d Downloading 129MB + 1cc0ff6cea1d Downloading 129MB + 1cc0ff6cea1d Downloading 129MB + 1cc0ff6cea1d Downloading 129MB + 1cc0ff6cea1d Downloading 130MB + 1cc0ff6cea1d Downloading 130MB + 1cc0ff6cea1d Downloading 130MB + 1cc0ff6cea1d Downloading 131.1MB + 1cc0ff6cea1d Downloading 131.1MB + 1cc0ff6cea1d Downloading 131.1MB + 1cc0ff6cea1d Downloading 131.1MB + 1cc0ff6cea1d Downloading 131.1MB + 1cc0ff6cea1d Downloading 132.1MB + 1cc0ff6cea1d Downloading 132.1MB + 1cc0ff6cea1d Downloading 132.1MB + 1cc0ff6cea1d Downloading 132.1MB + 1cc0ff6cea1d Downloading 133.2MB + 1cc0ff6cea1d Downloading 133.2MB + 1cc0ff6cea1d Downloading 133.2MB + 1cc0ff6cea1d Downloading 134.2MB + 1cc0ff6cea1d Downloading 134.2MB + 1cc0ff6cea1d Downloading 134.2MB + 1cc0ff6cea1d Downloading 135.3MB + 1cc0ff6cea1d Downloading 135.3MB + 1cc0ff6cea1d Downloading 135.3MB + 1cc0ff6cea1d Downloading 136.3MB + 1cc0ff6cea1d Downloading 136.3MB + 1cc0ff6cea1d Downloading 136.3MB + 1cc0ff6cea1d Downloading 137.4MB + 1cc0ff6cea1d Downloading 137.4MB + 1cc0ff6cea1d Downloading 137.4MB + 1cc0ff6cea1d Downloading 138.4MB + 1cc0ff6cea1d Downloading 138.4MB + 1cc0ff6cea1d Downloading 138.4MB + 1cc0ff6cea1d Downloading 138.4MB + 1cc0ff6cea1d Downloading 139.5MB + 1cc0ff6cea1d Downloading 139.5MB + 1cc0ff6cea1d Downloading 139.5MB + 1cc0ff6cea1d Downloading 139.5MB + 1cc0ff6cea1d Downloading 140.5MB + 1cc0ff6cea1d Downloading 140.5MB + 1cc0ff6cea1d Downloading 140.5MB + 1cc0ff6cea1d Downloading 141.6MB + 1cc0ff6cea1d Downloading 141.6MB + 1cc0ff6cea1d Downloading 141.6MB + 1cc0ff6cea1d Downloading 141.6MB + 1cc0ff6cea1d Downloading 141.6MB + 1cc0ff6cea1d Downloading 141.6MB + 1cc0ff6cea1d Downloading 142.6MB + 1cc0ff6cea1d Downloading 142.6MB + 1cc0ff6cea1d Downloading 142.6MB + 1cc0ff6cea1d Downloading 143.7MB + 1cc0ff6cea1d Downloading 143.7MB + 1cc0ff6cea1d Downloading 143.7MB + 1cc0ff6cea1d Downloading 143.7MB + 1cc0ff6cea1d Downloading 143.7MB + 1cc0ff6cea1d Downloading 143.7MB + 1cc0ff6cea1d Downloading 144.7MB + 1cc0ff6cea1d Downloading 144.7MB + 1cc0ff6cea1d Downloading 144.7MB + 1cc0ff6cea1d Downloading 144.7MB + 1cc0ff6cea1d Downloading 145.8MB + 1cc0ff6cea1d Downloading 145.8MB + 1cc0ff6cea1d Downloading 145.8MB + 1cc0ff6cea1d Downloading 145.8MB + 1cc0ff6cea1d Downloading 146.8MB + 1cc0ff6cea1d Downloading 146.8MB + 1cc0ff6cea1d Downloading 146.8MB + 1cc0ff6cea1d Downloading 146.8MB + 1cc0ff6cea1d Downloading 147.8MB + 1cc0ff6cea1d Downloading 147.8MB + 1cc0ff6cea1d Downloading 147.8MB + 1cc0ff6cea1d Downloading 147.8MB + 1cc0ff6cea1d Downloading 147.8MB + 1cc0ff6cea1d Downloading 148.9MB + 1cc0ff6cea1d Downloading 148.9MB + 1cc0ff6cea1d Downloading 148.9MB + 1cc0ff6cea1d Downloading 148.9MB + 1cc0ff6cea1d Downloading 148.9MB + 1cc0ff6cea1d Downloading 149.9MB + 1cc0ff6cea1d Downloading 149.9MB + 1cc0ff6cea1d Downloading 149.9MB + 1cc0ff6cea1d Downloading 151MB + 1cc0ff6cea1d Downloading 151MB + 1cc0ff6cea1d Downloading 151MB + 1cc0ff6cea1d Downloading 152MB + 1cc0ff6cea1d Downloading 152MB + 1cc0ff6cea1d Downloading 152MB + 1cc0ff6cea1d Downloading 152MB + 1cc0ff6cea1d Downloading 153.1MB + 1cc0ff6cea1d Downloading 153.1MB + 1cc0ff6cea1d Downloading 153.1MB + 1cc0ff6cea1d Downloading 154.1MB + 1cc0ff6cea1d Downloading 154.1MB + 1cc0ff6cea1d Downloading 154.1MB + 1cc0ff6cea1d Downloading 155.2MB + 1cc0ff6cea1d Downloading 155.2MB + 1cc0ff6cea1d Downloading 155.2MB + 1cc0ff6cea1d Downloading 156.2MB + 1cc0ff6cea1d Downloading 156.2MB + 1cc0ff6cea1d Downloading 156.2MB + 1cc0ff6cea1d Downloading 157.3MB + 1cc0ff6cea1d Downloading 157.3MB + 1cc0ff6cea1d Downloading 158.3MB + 1cc0ff6cea1d Downloading 158.3MB + 1cc0ff6cea1d Downloading 158.3MB + 1cc0ff6cea1d Downloading 159.4MB + 1cc0ff6cea1d Downloading 159.4MB + 1cc0ff6cea1d Downloading 159.4MB + 1cc0ff6cea1d Downloading 160.4MB + 1cc0ff6cea1d Downloading 160.4MB + 1cc0ff6cea1d Downloading 160.4MB + 1cc0ff6cea1d Downloading 160.4MB + 1cc0ff6cea1d Downloading 160.4MB + 1cc0ff6cea1d Downloading 161.5MB + 1cc0ff6cea1d Downloading 161.5MB + 1cc0ff6cea1d Downloading 162.5MB + 1cc0ff6cea1d Downloading 162.5MB + 1cc0ff6cea1d Downloading 162.5MB + 1cc0ff6cea1d Downloading 162.5MB + 1cc0ff6cea1d Downloading 163.6MB + 1cc0ff6cea1d Downloading 163.6MB + 1cc0ff6cea1d Downloading 164.6MB + 1cc0ff6cea1d Downloading 164.6MB + 1cc0ff6cea1d Downloading 164.6MB + 1cc0ff6cea1d Downloading 165.7MB + 1cc0ff6cea1d Downloading 165.7MB + 1cc0ff6cea1d Downloading 165.7MB + 1cc0ff6cea1d Downloading 166.7MB + 1cc0ff6cea1d Downloading 166.7MB + 1cc0ff6cea1d Downloading 166.7MB + 1cc0ff6cea1d Downloading 166.7MB + 1cc0ff6cea1d Downloading 167.8MB + 1cc0ff6cea1d Downloading 167.8MB + 1cc0ff6cea1d Downloading 167.8MB + 1cc0ff6cea1d Downloading 168.8MB + 1cc0ff6cea1d Downloading 168.8MB + 1cc0ff6cea1d Downloading 168.8MB + 1cc0ff6cea1d Downloading 169.9MB + 1cc0ff6cea1d Downloading 169.9MB + 1cc0ff6cea1d Downloading 169.9MB + 1cc0ff6cea1d Downloading 169.9MB + 1cc0ff6cea1d Downloading 170.9MB + 1cc0ff6cea1d Downloading 170.9MB + 1cc0ff6cea1d Downloading 170.9MB + 1cc0ff6cea1d Downloading 172MB + 1cc0ff6cea1d Downloading 172MB + 1cc0ff6cea1d Downloading 172MB + 1cc0ff6cea1d Downloading 173MB + 1cc0ff6cea1d Downloading 173MB + 1cc0ff6cea1d Downloading 173MB + 1cc0ff6cea1d Downloading 174.1MB + 1cc0ff6cea1d Downloading 174.1MB + 1cc0ff6cea1d Downloading 174.1MB + 1cc0ff6cea1d Downloading 175.1MB + 1cc0ff6cea1d Downloading 175.1MB + 1cc0ff6cea1d Downloading 175.1MB + 1cc0ff6cea1d Downloading 176.2MB + 1cc0ff6cea1d Downloading 176.2MB + 1cc0ff6cea1d Downloading 176.2MB + 1cc0ff6cea1d Downloading 177.2MB + 1cc0ff6cea1d Downloading 177.2MB + 1cc0ff6cea1d Downloading 177.2MB + 1cc0ff6cea1d Downloading 177.2MB + 1cc0ff6cea1d Downloading 178.3MB + 1cc0ff6cea1d Downloading 178.3MB + 1cc0ff6cea1d Downloading 178.3MB + 1cc0ff6cea1d Downloading 179.3MB + 1cc0ff6cea1d Downloading 179.3MB + 1cc0ff6cea1d Downloading 179.3MB + 1cc0ff6cea1d Downloading 179.3MB + 1cc0ff6cea1d Downloading 180.4MB + 1cc0ff6cea1d Downloading 180.4MB + 1cc0ff6cea1d Downloading 181.4MB + 1cc0ff6cea1d Downloading 181.4MB + 1cc0ff6cea1d Downloading 181.4MB + 1cc0ff6cea1d Downloading 181.4MB + 1cc0ff6cea1d Downloading 182.5MB + 1cc0ff6cea1d Downloading 182.5MB + 1cc0ff6cea1d Downloading 182.5MB + 1cc0ff6cea1d Downloading 182.5MB + 1cc0ff6cea1d Downloading 183.5MB + 1cc0ff6cea1d Downloading 183.5MB + 1cc0ff6cea1d Downloading 183.5MB + 1cc0ff6cea1d Downloading 183.5MB + 1cc0ff6cea1d Downloading 184.5MB + 1cc0ff6cea1d Downloading 184.5MB + 1cc0ff6cea1d Downloading 184.5MB + 1cc0ff6cea1d Downloading 184.5MB + 1cc0ff6cea1d Downloading 185.6MB + 1cc0ff6cea1d Downloading 185.6MB + 1cc0ff6cea1d Downloading 185.6MB + 1cc0ff6cea1d Downloading 185.6MB + 1cc0ff6cea1d Downloading 186.6MB + 1cc0ff6cea1d Downloading 186.6MB + 1cc0ff6cea1d Downloading 186.6MB + 1cc0ff6cea1d Downloading 187.7MB + 1cc0ff6cea1d Downloading 187.7MB + 1cc0ff6cea1d Downloading 187.7MB + 1cc0ff6cea1d Downloading 187.7MB + 1cc0ff6cea1d Downloading 188.7MB + 1cc0ff6cea1d Downloading 188.7MB + 1cc0ff6cea1d Downloading 188.7MB + 1cc0ff6cea1d Downloading 188.7MB + 1cc0ff6cea1d Downloading 188.7MB + 1cc0ff6cea1d Downloading 188.7MB + 1cc0ff6cea1d Downloading 189.8MB + 1cc0ff6cea1d Downloading 189.8MB + 1cc0ff6cea1d Downloading 189.8MB + 1cc0ff6cea1d Downloading 189.8MB + 1cc0ff6cea1d Downloading 189.8MB + 1cc0ff6cea1d Downloading 190.8MB + 1cc0ff6cea1d Downloading 190.8MB + 1cc0ff6cea1d Downloading 190.8MB + 1cc0ff6cea1d Downloading 190.8MB + 1cc0ff6cea1d Downloading 191.9MB + 1cc0ff6cea1d Downloading 191.9MB + 1cc0ff6cea1d Downloading 191.9MB + 1cc0ff6cea1d Downloading 192.9MB + 1cc0ff6cea1d Downloading 192.9MB + 1cc0ff6cea1d Downloading 192.9MB + 1cc0ff6cea1d Downloading 192.9MB + 1cc0ff6cea1d Downloading 192.9MB + 1cc0ff6cea1d Downloading 194MB + 1cc0ff6cea1d Downloading 194MB + 1cc0ff6cea1d Downloading 194MB + 1cc0ff6cea1d Downloading 195MB + 1cc0ff6cea1d Downloading 195MB + 1cc0ff6cea1d Downloading 195MB + 1cc0ff6cea1d Downloading 196.1MB + 1cc0ff6cea1d Downloading 196.1MB + 1cc0ff6cea1d Downloading 196.1MB + 1cc0ff6cea1d Downloading 197.1MB + 1cc0ff6cea1d Downloading 197.1MB + 1cc0ff6cea1d Downloading 197.1MB + 1cc0ff6cea1d Downloading 198.2MB + 1cc0ff6cea1d Downloading 198.2MB + 1cc0ff6cea1d Downloading 198.2MB + 1cc0ff6cea1d Downloading 199.2MB + 1cc0ff6cea1d Downloading 199.2MB + 1cc0ff6cea1d Downloading 199.2MB + 1cc0ff6cea1d Downloading 200.3MB + 1cc0ff6cea1d Downloading 200.3MB + 1cc0ff6cea1d Downloading 201.3MB + 1cc0ff6cea1d Downloading 201.3MB + 1cc0ff6cea1d Downloading 201.3MB + 1cc0ff6cea1d Downloading 202.4MB + 1cc0ff6cea1d Downloading 202.4MB + 1cc0ff6cea1d Downloading 202.4MB + 1cc0ff6cea1d Downloading 203.4MB + 1cc0ff6cea1d Downloading 203.4MB + 1cc0ff6cea1d Downloading 203.4MB + 1cc0ff6cea1d Downloading 204.5MB + 1cc0ff6cea1d Downloading 204.5MB + 1cc0ff6cea1d Downloading 204.5MB + 1cc0ff6cea1d Downloading 204.5MB + 1cc0ff6cea1d Downloading 205.5MB + 1cc0ff6cea1d Downloading 205.5MB + 1cc0ff6cea1d Downloading 205.5MB + 1cc0ff6cea1d Downloading 205.5MB + 1cc0ff6cea1d Downloading 205.5MB + 1cc0ff6cea1d Downloading 205.5MB + 1cc0ff6cea1d Downloading 206.6MB + 1cc0ff6cea1d Downloading 206.6MB + 1cc0ff6cea1d Downloading 206.6MB + 1cc0ff6cea1d Downloading 206.6MB + 1cc0ff6cea1d Downloading 207.6MB + 1cc0ff6cea1d Downloading 207.6MB + 1cc0ff6cea1d Downloading 207.6MB + 1cc0ff6cea1d Downloading 207.6MB + 1cc0ff6cea1d Downloading 207.6MB + 1cc0ff6cea1d Downloading 207.7MB + 1cc0ff6cea1d Downloading 208.7MB + 1cc0ff6cea1d Downloading 208.7MB + 1cc0ff6cea1d Downloading 208.7MB + 1cc0ff6cea1d Downloading 208.7MB + 1cc0ff6cea1d Downloading 209.7MB + 1cc0ff6cea1d Downloading 209.7MB + 1cc0ff6cea1d Downloading 209.7MB + 1cc0ff6cea1d Downloading 209.7MB + 1cc0ff6cea1d Downloading 209.7MB + 1cc0ff6cea1d Downloading 210.8MB + 1cc0ff6cea1d Downloading 210.8MB + 1cc0ff6cea1d Downloading 210.8MB + 1cc0ff6cea1d Downloading 210.8MB + 1cc0ff6cea1d Downloading 210.8MB + 1cc0ff6cea1d Downloading 210.8MB + 1cc0ff6cea1d Downloading 211.8MB + 1cc0ff6cea1d Downloading 211.8MB + 1cc0ff6cea1d Downloading 211.8MB + 1cc0ff6cea1d Downloading 211.8MB + 1cc0ff6cea1d Downloading 211.8MB + 1cc0ff6cea1d Downloading 211.8MB + 1cc0ff6cea1d Downloading 212.9MB + 1cc0ff6cea1d Downloading 212.9MB + 1cc0ff6cea1d Downloading 212.9MB + 1cc0ff6cea1d Downloading 212.9MB + 1cc0ff6cea1d Downloading 213.9MB + 1cc0ff6cea1d Downloading 213.9MB + 1cc0ff6cea1d Downloading 213.9MB + 1cc0ff6cea1d Downloading 213.9MB + 1cc0ff6cea1d Downloading 213.9MB + 1cc0ff6cea1d Downloading 215MB + 1cc0ff6cea1d Downloading 215MB + 1cc0ff6cea1d Downloading 215MB + 1cc0ff6cea1d Downloading 215MB + 1cc0ff6cea1d Downloading 216MB + 1cc0ff6cea1d Downloading 216MB + 1cc0ff6cea1d Downloading 216MB + 1cc0ff6cea1d Downloading 216MB + 1cc0ff6cea1d Downloading 216MB + 1cc0ff6cea1d Downloading 216MB + 1cc0ff6cea1d Downloading 217.1MB + 1cc0ff6cea1d Downloading 217.1MB + 1cc0ff6cea1d Downloading 217.1MB + 1cc0ff6cea1d Downloading 217.1MB + 1cc0ff6cea1d Downloading 218.1MB + 1cc0ff6cea1d Downloading 218.1MB + 1cc0ff6cea1d Downloading 218.1MB + 1cc0ff6cea1d Downloading 218.1MB + 1cc0ff6cea1d Downloading 218.1MB + 1cc0ff6cea1d Downloading 219.2MB + 1cc0ff6cea1d Downloading 219.2MB + 1cc0ff6cea1d Downloading 219.2MB + 1cc0ff6cea1d Downloading 219.2MB + 1cc0ff6cea1d Downloading 220.2MB + 1cc0ff6cea1d Downloading 220.2MB + 1cc0ff6cea1d Downloading 220.2MB + 1cc0ff6cea1d Downloading 220.2MB + 1cc0ff6cea1d Downloading 221.2MB + 1cc0ff6cea1d Downloading 221.2MB + 1cc0ff6cea1d Downloading 221.2MB + 1cc0ff6cea1d Downloading 221.2MB + 1cc0ff6cea1d Downloading 222.3MB + 1cc0ff6cea1d Downloading 222.3MB + 1cc0ff6cea1d Downloading 222.3MB + 1cc0ff6cea1d Downloading 222.3MB + 1cc0ff6cea1d Downloading 223.3MB + 1cc0ff6cea1d Downloading 223.3MB + 1cc0ff6cea1d Downloading 223.3MB + 1cc0ff6cea1d Downloading 223.3MB + 1cc0ff6cea1d Downloading 224.4MB + 1cc0ff6cea1d Downloading 224.4MB + 1cc0ff6cea1d Downloading 224.4MB + 1cc0ff6cea1d Downloading 225.4MB + 1cc0ff6cea1d Downloading 225.4MB + 1cc0ff6cea1d Downloading 225.4MB + 1cc0ff6cea1d Downloading 226.5MB + 1cc0ff6cea1d Downloading 226.5MB + 1cc0ff6cea1d Downloading 226.5MB + 1cc0ff6cea1d Downloading 227.5MB + 1cc0ff6cea1d Downloading 227.5MB + 1cc0ff6cea1d Downloading 227.5MB + 1cc0ff6cea1d Downloading 228.6MB + 1cc0ff6cea1d Downloading 228.6MB + 1cc0ff6cea1d Downloading 228.6MB + 1cc0ff6cea1d Downloading 228.6MB + 1cc0ff6cea1d Downloading 229.6MB + 1cc0ff6cea1d Downloading 229.6MB + 1cc0ff6cea1d Downloading 229.6MB + 1cc0ff6cea1d Downloading 230.7MB + 1cc0ff6cea1d Downloading 230.7MB + 1cc0ff6cea1d Downloading 230.7MB + 1cc0ff6cea1d Downloading 231.7MB + 1cc0ff6cea1d Downloading 231.7MB + 1cc0ff6cea1d Downloading 231.7MB + 1cc0ff6cea1d Downloading 232.8MB + 1cc0ff6cea1d Downloading 232.8MB + 1cc0ff6cea1d Downloading 232.8MB + 1cc0ff6cea1d Downloading 233.8MB + 1cc0ff6cea1d Downloading 233.8MB + 1cc0ff6cea1d Downloading 233.8MB + 1cc0ff6cea1d Downloading 234.9MB + 1cc0ff6cea1d Downloading 234.9MB + 1cc0ff6cea1d Downloading 234.9MB + 1cc0ff6cea1d Downloading 234.9MB + 1cc0ff6cea1d Downloading 235.9MB + 1cc0ff6cea1d Downloading 235.9MB + 1cc0ff6cea1d Downloading 235.9MB + 1cc0ff6cea1d Downloading 235.9MB + 1cc0ff6cea1d Downloading 237MB + 1cc0ff6cea1d Downloading 237MB + 1cc0ff6cea1d Downloading 237MB + 1cc0ff6cea1d Downloading 237MB + 1cc0ff6cea1d Downloading 238MB + 1cc0ff6cea1d Downloading 238MB + 1cc0ff6cea1d Downloading 238MB + 1cc0ff6cea1d Downloading 238MB + 1cc0ff6cea1d Downloading 238MB + 1cc0ff6cea1d Downloading 239.1MB + 1cc0ff6cea1d Downloading 239.1MB + 1cc0ff6cea1d Downloading 239.1MB + 1cc0ff6cea1d Downloading 240.1MB + 1cc0ff6cea1d Downloading 240.1MB + 1cc0ff6cea1d Downloading 240.1MB + 1cc0ff6cea1d Downloading 240.1MB + 1cc0ff6cea1d Downloading 241.2MB + 1cc0ff6cea1d Downloading 241.2MB + 1cc0ff6cea1d Downloading 241.2MB + 1cc0ff6cea1d Downloading 241.2MB + 1cc0ff6cea1d Downloading 242.2MB + 1cc0ff6cea1d Downloading 242.2MB + 1cc0ff6cea1d Downloading 242.2MB + 1cc0ff6cea1d Downloading 242.2MB + 1cc0ff6cea1d Downloading 243.3MB + 1cc0ff6cea1d Downloading 243.3MB + 1cc0ff6cea1d Downloading 243.3MB + 1cc0ff6cea1d Downloading 243.3MB + 1cc0ff6cea1d Downloading 244.3MB + 1cc0ff6cea1d Downloading 244.3MB + 1cc0ff6cea1d Downloading 244.3MB + 1cc0ff6cea1d Downloading 245.4MB + 1cc0ff6cea1d Downloading 245.4MB + 1cc0ff6cea1d Downloading 245.4MB + 1cc0ff6cea1d Downloading 245.4MB + 1cc0ff6cea1d Downloading 246.4MB + 1cc0ff6cea1d Downloading 246.4MB + 1cc0ff6cea1d Downloading 246.4MB + 1cc0ff6cea1d Downloading 246.4MB + 1cc0ff6cea1d Downloading 246.4MB + 1cc0ff6cea1d Downloading 247.5MB + 1cc0ff6cea1d Downloading 247.5MB + 1cc0ff6cea1d Downloading 247.5MB + 1cc0ff6cea1d Downloading 248.5MB + 1cc0ff6cea1d Downloading 248.5MB + 1cc0ff6cea1d Downloading 249.6MB + 1cc0ff6cea1d Downloading 249.6MB + 1cc0ff6cea1d Downloading 249.6MB + 1cc0ff6cea1d Downloading 249.6MB + 1cc0ff6cea1d Downloading 250.6MB + 1cc0ff6cea1d Downloading 250.6MB + 1cc0ff6cea1d Downloading 251.7MB + 1cc0ff6cea1d Downloading 251.7MB + 1cc0ff6cea1d Downloading 251.7MB + 1cc0ff6cea1d Downloading 251.7MB + 1cc0ff6cea1d Downloading 251.7MB + 1cc0ff6cea1d Downloading 252.7MB + 1cc0ff6cea1d Downloading 252.7MB + 1cc0ff6cea1d Downloading 252.7MB + 1cc0ff6cea1d Downloading 252.7MB + 1cc0ff6cea1d Downloading 253.8MB + 1cc0ff6cea1d Downloading 253.8MB + 1cc0ff6cea1d Downloading 253.8MB + 1cc0ff6cea1d Downloading 254.8MB + 1cc0ff6cea1d Downloading 254.8MB + 1cc0ff6cea1d Downloading 254.8MB + 1cc0ff6cea1d Downloading 254.8MB + 1cc0ff6cea1d Downloading 255.9MB + 1cc0ff6cea1d Downloading 255.9MB + 1cc0ff6cea1d Downloading 255.9MB + 1cc0ff6cea1d Downloading 255.9MB + 1cc0ff6cea1d Downloading 256.9MB + 1cc0ff6cea1d Downloading 256.9MB + 1cc0ff6cea1d Downloading 256.9MB + 1cc0ff6cea1d Downloading 257.9MB + 1cc0ff6cea1d Downloading 257.9MB + 1cc0ff6cea1d Downloading 259MB + 1cc0ff6cea1d Downloading 259MB + 1cc0ff6cea1d Downloading 259MB + 1cc0ff6cea1d Downloading 260MB + 1cc0ff6cea1d Downloading 260MB + 1cc0ff6cea1d Downloading 260MB + 1cc0ff6cea1d Downloading 261.1MB + 1cc0ff6cea1d Downloading 261.1MB + 1cc0ff6cea1d Downloading 261.1MB + 1cc0ff6cea1d Downloading 262.1MB + 1cc0ff6cea1d Downloading 262.1MB + 1cc0ff6cea1d Downloading 262.1MB + 1cc0ff6cea1d Downloading 262.1MB + 1cc0ff6cea1d Downloading 263.2MB + 1cc0ff6cea1d Downloading 263.2MB + 1cc0ff6cea1d Downloading 263.2MB + 1cc0ff6cea1d Downloading 263.2MB + 1cc0ff6cea1d Downloading 264.2MB + 1cc0ff6cea1d Downloading 264.2MB + 1cc0ff6cea1d Downloading 264.2MB + 1cc0ff6cea1d Downloading 265.3MB + 1cc0ff6cea1d Downloading 265.3MB + 1cc0ff6cea1d Downloading 265.3MB + 1cc0ff6cea1d Downloading 266.3MB + 1cc0ff6cea1d Downloading 266.3MB + 1cc0ff6cea1d Downloading 266.3MB + 1cc0ff6cea1d Downloading 266.3MB + 1cc0ff6cea1d Downloading 266.3MB + 1cc0ff6cea1d Downloading 267.4MB + 1cc0ff6cea1d Downloading 267.4MB + 1cc0ff6cea1d Downloading 267.4MB + 1cc0ff6cea1d Downloading 267.4MB + 1cc0ff6cea1d Downloading 268.4MB + 1cc0ff6cea1d Downloading 268.4MB + 1cc0ff6cea1d Downloading 268.4MB + 1cc0ff6cea1d Downloading 268.4MB + 1cc0ff6cea1d Downloading 268.4MB + 1cc0ff6cea1d Downloading 268.4MB + 1cc0ff6cea1d Downloading 269.5MB + 1cc0ff6cea1d Downloading 269.5MB + 1cc0ff6cea1d Downloading 269.5MB + 1cc0ff6cea1d Downloading 269.5MB + 1cc0ff6cea1d Downloading 269.5MB + 1cc0ff6cea1d Downloading 270.5MB + 1cc0ff6cea1d Downloading 270.5MB + 1cc0ff6cea1d Downloading 270.5MB + 1cc0ff6cea1d Downloading 270.5MB + 1cc0ff6cea1d Downloading 271.6MB + 1cc0ff6cea1d Downloading 271.6MB + 1cc0ff6cea1d Downloading 271.6MB + 1cc0ff6cea1d Downloading 271.6MB + 1cc0ff6cea1d Downloading 271.6MB + 1cc0ff6cea1d Downloading 272.6MB + 1cc0ff6cea1d Downloading 272.6MB + 1cc0ff6cea1d Downloading 272.6MB + 1cc0ff6cea1d Downloading 272.6MB + 1cc0ff6cea1d Downloading 273.7MB + 1cc0ff6cea1d Downloading 273.7MB + 1cc0ff6cea1d Downloading 273.7MB + 1cc0ff6cea1d Downloading 273.7MB + 1cc0ff6cea1d Downloading 274.7MB + 1cc0ff6cea1d Downloading 274.7MB + 1cc0ff6cea1d Downloading 274.7MB + 1cc0ff6cea1d Downloading 274.7MB + 1cc0ff6cea1d Downloading 275.8MB + 1cc0ff6cea1d Downloading 275.8MB + 1cc0ff6cea1d Downloading 275.8MB + 1cc0ff6cea1d Downloading 275.8MB + 1cc0ff6cea1d Downloading 275.8MB + 1cc0ff6cea1d Downloading 275.8MB + 1cc0ff6cea1d Downloading 275.8MB + 1cc0ff6cea1d Downloading 276.8MB + 1cc0ff6cea1d Downloading 276.8MB + 1cc0ff6cea1d Downloading 276.8MB + 1cc0ff6cea1d Downloading 276.8MB + 1cc0ff6cea1d Downloading 276.8MB + 1cc0ff6cea1d Downloading 277.9MB + 1cc0ff6cea1d Downloading 277.9MB + 1cc0ff6cea1d Downloading 277.9MB + 1cc0ff6cea1d Downloading 277.9MB + 1cc0ff6cea1d Downloading 278.9MB + 1cc0ff6cea1d Downloading 278.9MB + 1cc0ff6cea1d Downloading 278.9MB + 1cc0ff6cea1d Downloading 278.9MB + 1cc0ff6cea1d Downloading 280MB + 1cc0ff6cea1d Downloading 280MB + 1cc0ff6cea1d Downloading 280MB + 1cc0ff6cea1d Downloading 281MB + 1cc0ff6cea1d Downloading 281MB + 1cc0ff6cea1d Downloading 281MB + 1cc0ff6cea1d Downloading 281MB + 1cc0ff6cea1d Downloading 282.1MB + 1cc0ff6cea1d Downloading 282.1MB + 1cc0ff6cea1d Downloading 282.1MB + 1cc0ff6cea1d Downloading 282.1MB + 1cc0ff6cea1d Downloading 283.1MB + 1cc0ff6cea1d Downloading 283.1MB + 1cc0ff6cea1d Downloading 283.1MB + 1cc0ff6cea1d Downloading 284.2MB + 1cc0ff6cea1d Downloading 284.2MB + 1cc0ff6cea1d Downloading 284.2MB + 1cc0ff6cea1d Downloading 285.2MB + 1cc0ff6cea1d Downloading 285.2MB + 1cc0ff6cea1d Downloading 285.2MB + 1cc0ff6cea1d Downloading 285.2MB + 1cc0ff6cea1d Downloading 286.3MB + 1cc0ff6cea1d Downloading 286.3MB + 1cc0ff6cea1d Downloading 286.3MB + 1cc0ff6cea1d Downloading 286.3MB + 1cc0ff6cea1d Downloading 287.3MB + 1cc0ff6cea1d Downloading 287.3MB + 1cc0ff6cea1d Downloading 287.3MB + 1cc0ff6cea1d Downloading 288.4MB + 1cc0ff6cea1d Downloading 288.4MB + 1cc0ff6cea1d Downloading 288.4MB + 1cc0ff6cea1d Downloading 288.4MB + 1cc0ff6cea1d Downloading 289.4MB + 1cc0ff6cea1d Downloading 289.4MB + 1cc0ff6cea1d Downloading 289.4MB + 1cc0ff6cea1d Downloading 290.5MB + 1cc0ff6cea1d Downloading 290.5MB + 1cc0ff6cea1d Downloading 290.5MB + 1cc0ff6cea1d Downloading 290.5MB + 1cc0ff6cea1d Downloading 291.5MB + 1cc0ff6cea1d Downloading 291.5MB + 1cc0ff6cea1d Downloading 291.5MB + 1cc0ff6cea1d Downloading 291.5MB + 1cc0ff6cea1d Downloading 291.5MB + 1cc0ff6cea1d Downloading 292.6MB + 1cc0ff6cea1d Downloading 292.6MB + 1cc0ff6cea1d Downloading 292.6MB + 1cc0ff6cea1d Downloading 292.6MB + 1cc0ff6cea1d Downloading 292.6MB + 1cc0ff6cea1d Downloading 292.6MB + 1cc0ff6cea1d Downloading 293.6MB + 1cc0ff6cea1d Downloading 293.6MB + 1cc0ff6cea1d Downloading 293.6MB + 1cc0ff6cea1d Downloading 293.6MB + 1cc0ff6cea1d Downloading 293.6MB + 1cc0ff6cea1d Downloading 293.6MB + 1cc0ff6cea1d Downloading 294.6MB + 1cc0ff6cea1d Downloading 294.6MB + 1cc0ff6cea1d Downloading 294.6MB + 1cc0ff6cea1d Downloading 294.6MB + 1cc0ff6cea1d Downloading 294.6MB + 1cc0ff6cea1d Downloading 294.6MB + 1cc0ff6cea1d Downloading 294.6MB + 1cc0ff6cea1d Downloading 295.7MB + 1cc0ff6cea1d Downloading 295.7MB + 1cc0ff6cea1d Downloading 295.7MB + 1cc0ff6cea1d Downloading 295.7MB + 1cc0ff6cea1d Downloading 295.7MB + 1cc0ff6cea1d Downloading 295.7MB + 1cc0ff6cea1d Downloading 296.7MB + 1cc0ff6cea1d Downloading 296.7MB + 1cc0ff6cea1d Downloading 296.7MB + 1cc0ff6cea1d Downloading 296.7MB + 1cc0ff6cea1d Downloading 296.7MB + 1cc0ff6cea1d Downloading 296.7MB + 1cc0ff6cea1d Downloading 297.8MB + 1cc0ff6cea1d Downloading 297.8MB + 1cc0ff6cea1d Downloading 297.8MB + 1cc0ff6cea1d Downloading 297.8MB + 1cc0ff6cea1d Downloading 297.8MB + 1cc0ff6cea1d Downloading 298.8MB + 1cc0ff6cea1d Downloading 298.8MB + 1cc0ff6cea1d Downloading 298.8MB + 1cc0ff6cea1d Downloading 298.8MB + 1cc0ff6cea1d Downloading 299.9MB + 1cc0ff6cea1d Downloading 299.9MB + 1cc0ff6cea1d Downloading 299.9MB + 1cc0ff6cea1d Downloading 299.9MB + 1cc0ff6cea1d Downloading 300.9MB + 1cc0ff6cea1d Downloading 300.9MB + 1cc0ff6cea1d Downloading 300.9MB + 1cc0ff6cea1d Downloading 300.9MB + 1cc0ff6cea1d Downloading 300.9MB + 1cc0ff6cea1d Downloading 300.9MB + 1cc0ff6cea1d Downloading 300.9MB + 1cc0ff6cea1d Downloading 300.9MB + 1cc0ff6cea1d Downloading 302MB + 1cc0ff6cea1d Downloading 302MB + 1cc0ff6cea1d Downloading 302MB + 1cc0ff6cea1d Downloading 302MB + 1cc0ff6cea1d Downloading 302MB + 1cc0ff6cea1d Downloading 303MB + 1cc0ff6cea1d Downloading 303MB + 1cc0ff6cea1d Downloading 303MB + 1cc0ff6cea1d Downloading 304.1MB + 1cc0ff6cea1d Downloading 304.1MB + 1cc0ff6cea1d Downloading 304.1MB + 1cc0ff6cea1d Downloading 305.1MB + 1cc0ff6cea1d Downloading 305.1MB + 1cc0ff6cea1d Downloading 305.1MB + 1cc0ff6cea1d Downloading 306.2MB + 1cc0ff6cea1d Downloading 306.2MB + 1cc0ff6cea1d Downloading 306.2MB + 1cc0ff6cea1d Downloading 307.2MB + 1cc0ff6cea1d Download complete 0B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 1B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 2B + 1cc0ff6cea1d Extracting 3B + 1cc0ff6cea1d Extracting 3B + 1cc0ff6cea1d Extracting 3B + 1cc0ff6cea1d Extracting 3B + 1cc0ff6cea1d Extracting 3B + 1cc0ff6cea1d Extracting 3B + 1cc0ff6cea1d Extracting 3B + 1cc0ff6cea1d Extracting 3B + 1cc0ff6cea1d Extracting 3B + 1cc0ff6cea1d Extracting 3B + 0f1eecfe1b47 Extracting 1B + 1cc0ff6cea1d Pull complete 0B + 1c78c8e19058 Pull complete 0B + 6721902c3fd6 Pull complete 0B + 0f1eecfe1b47 Pull complete 0B + Image grafana/grafana:13.0.2 Pulled + Image quicknotes:lab6 Building +#1 [internal] load local bake definitions +#1 reading from stdin 542B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 515B done +#2 DONE 0.0s + +#3 resolve image config for docker-image://docker.io/docker/dockerfile:1 +#3 DONE 6.9s + +#4 docker-image://docker.io/docker/dockerfile:1@sha256:87999aa3d42bdc6bea60565083ee17e86d1f3339802f543c0d03998580f9cb89 +#4 resolve docker.io/docker/dockerfile:1@sha256:87999aa3d42bdc6bea60565083ee17e86d1f3339802f543c0d03998580f9cb89 done +#4 CACHED + +#5 [internal] load metadata for docker.io/library/busybox:1.36-musl +#5 ... + +#6 [internal] load metadata for gcr.io/distroless/static-debian12:nonroot +#6 DONE 0.9s + +#5 [internal] load metadata for docker.io/library/busybox:1.36-musl +#5 DONE 1.0s + +#7 [internal] load metadata for docker.io/library/golang:1.24-alpine +#7 DONE 1.0s + +#8 [internal] load .dockerignore +#8 transferring context: 2B done +#8 DONE 0.0s + +#9 [builder 1/6] FROM docker.io/library/golang:1.24-alpine@sha256:8bee1901f1e530bfb4a7850aa7a479d17ae3a18beb6e09064ed54cfd245b7191 +#9 resolve docker.io/library/golang:1.24-alpine@sha256:8bee1901f1e530bfb4a7850aa7a479d17ae3a18beb6e09064ed54cfd245b7191 0.0s done +#9 DONE 0.0s + +#10 [stage-2 1/4] FROM gcr.io/distroless/static-debian12:nonroot@sha256:d093aa3e30dbadd3efe1310db061a14da60299baff8450a17fe0ccc514a16639 +#10 resolve gcr.io/distroless/static-debian12:nonroot@sha256:d093aa3e30dbadd3efe1310db061a14da60299baff8450a17fe0ccc514a16639 0.0s done +#10 DONE 0.0s + +#11 [busybox 1/1] FROM docker.io/library/busybox:1.36-musl@sha256:3c6ae8008e2c2eedd141725c30b20d9c36b026eb796688f88205845ef17aa213 +#11 resolve docker.io/library/busybox:1.36-musl@sha256:3c6ae8008e2c2eedd141725c30b20d9c36b026eb796688f88205845ef17aa213 0.0s done +#11 DONE 0.0s + +#12 [internal] load build context +#12 transferring context: 909B done +#12 DONE 0.0s + +#13 [builder 5/6] COPY . . +#13 CACHED + +#14 [builder 2/6] WORKDIR /src +#14 CACHED + +#15 [builder 3/6] COPY go.mod ./ +#15 CACHED + +#16 [stage-2 3/4] COPY --from=builder /src/seed.json /seed.json +#16 CACHED + +#17 [stage-2 2/4] COPY --from=builder /quicknotes /quicknotes +#17 CACHED + +#18 [builder 4/6] RUN go mod download +#18 CACHED + +#19 [builder 6/6] RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags='-s -w' -o /quicknotes . +#19 CACHED + +#20 [stage-2 4/4] COPY --from=busybox /bin/busybox /busybox +#20 CACHED + +#21 exporting to image +#21 exporting layers done +#21 exporting manifest sha256:83da2b02f883b1cbcacda2943165c314e5a22658c8fd6df73146b64d2a75a08d done +#21 exporting config sha256:55ee3c6a2cf57ac962258865a12873a7cc7a6114ed1c7c2ebf136cdaeebcd00e done +#21 exporting attestation manifest sha256:9c36feab00808795dc712a55e43b6d92070e6f32f13fa105202bbd75bd715759 done +#21 exporting manifest list sha256:15f1a6f6bf4d265cfc64be086afb2c4876d8bdce6ee5fb666ea8da5b93bba297 done +#21 naming to docker.io/library/quicknotes:lab6 done +#21 unpacking to docker.io/library/quicknotes:lab6 done +#21 DONE 0.1s + +#22 resolving provenance for metadata file +#22 DONE 0.0s + Image quicknotes:lab6 Built + Network devops-intro_default Creating + Network devops-intro_default Created + Container devops-intro-volume-init-1 Creating + Container devops-intro-volume-init-1 Created + Container devops-intro-quicknotes-1 Creating + Container devops-intro-quicknotes-1 Created + Container devops-intro-prometheus-1 Creating + Container devops-intro-prometheus-1 Created + Container devops-intro-grafana-1 Creating + Container devops-intro-grafana-1 Created + Container devops-intro-volume-init-1 Starting + Container devops-intro-volume-init-1 Started + Container devops-intro-volume-init-1 Waiting + Container devops-intro-volume-init-1 Exited + Container devops-intro-quicknotes-1 Starting + Container devops-intro-quicknotes-1 Started + Container devops-intro-quicknotes-1 Waiting + Container devops-intro-quicknotes-1 Healthy + Container devops-intro-prometheus-1 Starting + Container devops-intro-prometheus-1 Started + Container devops-intro-grafana-1 Starting + Container devops-intro-grafana-1 Started diff --git a/submissions/attachments/lab8/grafana-dashboard-meta.txt b/submissions/attachments/lab8/grafana-dashboard-meta.txt new file mode 100644 index 000000000..4a10bb79a --- /dev/null +++ b/submissions/attachments/lab8/grafana-dashboard-meta.txt @@ -0,0 +1 @@ +dashboard: QuickNotes Golden Signals panels: 4 diff --git a/submissions/attachments/lab8/grafana-dashboard-search.json b/submissions/attachments/lab8/grafana-dashboard-search.json new file mode 100644 index 000000000..da8cc8488 --- /dev/null +++ b/submissions/attachments/lab8/grafana-dashboard-search.json @@ -0,0 +1 @@ +[{"id":380486399176704,"uid":"ffqq3km8x2gaof","orgId":1,"title":"QuickNotes","uri":"db/quicknotes","url":"/dashboards/f/ffqq3km8x2gaof/quicknotes","slug":"","type":"dash-folder","tags":[],"isStarred":false,"sortMeta":0,"isDeleted":false},{"id":380486440366080,"uid":"quicknotes-golden-signals","orgId":1,"title":"QuickNotes Golden Signals","uri":"db/quicknotes-golden-signals","url":"/d/quicknotes-golden-signals/quicknotes-golden-signals","slug":"","type":"dash-db","tags":["golden-signals","quicknotes"],"isStarred":false,"folderId":380486399176704,"folderUid":"ffqq3km8x2gaof","folderTitle":"QuickNotes","folderUrl":"/dashboards/f/ffqq3km8x2gaof/quicknotes","sortMeta":0,"isDeleted":false}] \ No newline at end of file diff --git a/submissions/attachments/lab8/prometheus-alerts-firing.json b/submissions/attachments/lab8/prometheus-alerts-firing.json new file mode 100644 index 000000000..08a6af352 --- /dev/null +++ b/submissions/attachments/lab8/prometheus-alerts-firing.json @@ -0,0 +1,21 @@ +{ + "status": "success", + "data": { + "alerts": [ + { + "labels": { + "alertname": "HighHTTPErrorRate", + "severity": "page" + }, + "annotations": { + "description": "More than 5% of HTTP responses are 4xx/5xx for 5 minutes.", + "runbook_url": "docs/runbook/high-error-rate.md", + "summary": "QuickNotes HTTP error ratio exceeds 5%" + }, + "state": "firing", + "activeAt": "2026-06-30T19:15:59.892443532Z", + "value": "3.1804465902232953e-01" + } + ] + } +} diff --git a/submissions/attachments/lab8/prometheus-alerts.json b/submissions/attachments/lab8/prometheus-alerts.json new file mode 100644 index 000000000..3113987ae --- /dev/null +++ b/submissions/attachments/lab8/prometheus-alerts.json @@ -0,0 +1,21 @@ +{ + "status": "success", + "data": { + "alerts": [ + { + "labels": { + "alertname": "HighHTTPErrorRate", + "severity": "page" + }, + "annotations": { + "description": "More than 5% of HTTP responses are 4xx/5xx for 5 minutes.", + "runbook_url": "docs/runbook/high-error-rate.md", + "summary": "QuickNotes HTTP error ratio exceeds 5%" + }, + "state": "pending", + "activeAt": "2026-06-30T19:15:59.892443532Z", + "value": "1.7777777777777778e-01" + } + ] + } +} diff --git a/submissions/attachments/lab8/prometheus-targets.json b/submissions/attachments/lab8/prometheus-targets.json new file mode 100644 index 000000000..7b2d33e79 --- /dev/null +++ b/submissions/attachments/lab8/prometheus-targets.json @@ -0,0 +1,34 @@ +{ + "status": "success", + "data": { + "activeTargets": [ + { + "discoveredLabels": { + "__address__": "quicknotes:8080", + "__metrics_path__": "/metrics", + "__scheme__": "http", + "__scrape_interval__": "15s", + "__scrape_timeout__": "10s", + "job": "quicknotes" + }, + "labels": { + "instance": "quicknotes:8080", + "job": "quicknotes" + }, + "scrapePool": "quicknotes", + "scrapeUrl": "http://quicknotes:8080/metrics", + "globalUrl": "http://quicknotes:8080/metrics", + "lastError": "", + "lastScrape": "2026-06-30T19:15:55.509592551Z", + "lastScrapeDuration": 0.00339975, + "health": "up", + "scrapeInterval": "15s", + "scrapeTimeout": "10s" + } + ], + "droppedTargets": [], + "droppedTargetCounts": { + "quicknotes": 0 + } + } +} diff --git a/submissions/attachments/lab8/targets-health.txt b/submissions/attachments/lab8/targets-health.txt new file mode 100644 index 000000000..389d6a347 --- /dev/null +++ b/submissions/attachments/lab8/targets-health.txt @@ -0,0 +1 @@ +['up'] diff --git a/submissions/attachments/lab8/traffic-gen.log b/submissions/attachments/lab8/traffic-gen.log new file mode 100644 index 000000000..1850f6fc6 --- /dev/null +++ b/submissions/attachments/lab8/traffic-gen.log @@ -0,0 +1,202 @@ +Generating traffic against http://localhost:8080 +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"}] +{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":5,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"}] +{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":6,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"}] +{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":7,"status":"ok"} +[{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"}] +{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":8,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"}] +{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":9,"status":"ok"} +[{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"}] +{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":10,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"}] +{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":11,"status":"ok"} +[{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"}] +{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":12,"status":"ok"} +[{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"}] +{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":13,"status":"ok"} +[{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"}] +{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":14,"status":"ok"} +[{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"}] +{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":15,"status":"ok"} +[{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"}] +{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":16,"status":"ok"} +[{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"}] +{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":17,"status":"ok"} +[{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"}] +{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":18,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"}] +{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":19,"status":"ok"} +[{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"}] +{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":20,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"}] +{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":21,"status":"ok"} +[{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"}] +{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":22,"status":"ok"} +[{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"}] +{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":23,"status":"ok"} +[{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"}] +{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":24,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"}] +{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":25,"status":"ok"} +[{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"}] +{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":26,"status":"ok"} +[{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"}] +{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":27,"status":"ok"} +[{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"}] +{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":28,"status":"ok"} +[{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"}] +{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":29,"status":"ok"} +[{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"}] +{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":30,"status":"ok"} +[{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"}] +{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":31,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"}] +{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":32,"status":"ok"} +[{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"}] +{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":33,"status":"ok"} +[{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"}] +{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":34,"status":"ok"} +[{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"}] +{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":35,"status":"ok"} +[{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"}] +{"id":36,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.489431468Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":36,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":36,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.489431468Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"}] +{"id":37,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.536459259Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":37,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":36,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.489431468Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":37,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.536459259Z"}] +{"id":38,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.58127676Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":38,"status":"ok"} +[{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"},{"id":38,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.58127676Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":37,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.536459259Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":36,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.489431468Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"}] +{"id":39,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.627890301Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":39,"status":"ok"} +[{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"},{"id":38,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.58127676Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":39,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.627890301Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":37,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.536459259Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":36,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.489431468Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"}] +{"id":40,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.67946451Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":40,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":36,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.489431468Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"},{"id":38,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.58127676Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":39,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.627890301Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":40,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.67946451Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":37,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.536459259Z"}] +{"id":41,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.730004176Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":41,"status":"ok"} +[{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"},{"id":38,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.58127676Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":39,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.627890301Z"},{"id":41,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.730004176Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":40,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.67946451Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":37,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.536459259Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":36,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.489431468Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"}] +{"id":42,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.806447551Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":42,"status":"ok"} +[{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":36,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.489431468Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"},{"id":38,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.58127676Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":39,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.627890301Z"},{"id":41,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.730004176Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"},{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":42,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.806447551Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":40,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.67946451Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":37,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.536459259Z"}] +{"id":43,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.861242135Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":43,"status":"ok"} +[{"id":3,"title":"DevOps mantra","body":"If it hurts, do it more often.","created_at":"2026-01-15T10:10:00Z"},{"id":14,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.384287176Z"},{"id":15,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.429321259Z"},{"id":18,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.590758092Z"},{"id":29,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.156912593Z"},{"id":42,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.806447551Z"},{"id":43,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.861242135Z"},{"id":8,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.115213467Z"},{"id":24,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.893764009Z"},{"id":30,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.202683218Z"},{"id":31,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.250643676Z"},{"id":40,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.67946451Z"},{"id":11,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.249325926Z"},{"id":25,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.941970843Z"},{"id":26,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.011572843Z"},{"id":37,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.536459259Z"},{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"},{"id":4,"title":"Endpoint cheat-sheet","body":"GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics","created_at":"2026-01-15T10:15:00Z"},{"id":33,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.348894176Z"},{"id":34,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.397618968Z"},{"id":36,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.489431468Z"},{"id":10,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.205113092Z"},{"id":27,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.066095051Z"},{"id":32,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.299434634Z"},{"id":9,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.161303051Z"},{"id":13,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.340506384Z"},{"id":23,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.840111092Z"},{"id":35,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.443662593Z"},{"id":38,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.58127676Z"},{"id":7,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.067799009Z"},{"id":12,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.295360009Z"},{"id":17,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.540106217Z"},{"id":20,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.691560217Z"},{"id":28,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.111514301Z"},{"id":5,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:38.971845884Z"},{"id":6,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.020578009Z"},{"id":16,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.474126676Z"},{"id":19,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.643086509Z"},{"id":21,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.745610009Z"},{"id":22,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:39.792403384Z"},{"id":39,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.627890301Z"},{"id":41,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.730004176Z"},{"id":2,"title":"Read app/main.go first","body":"Start by understanding the entry point β€” env vars, signal handling, graceful shutdown.","created_at":"2026-01-15T10:05:00Z"}] +{"id":44,"title":"load","body":"traffic","created_at":"2026-06-30T19:15:40.916458218Z"} +{"id":1,"title":"Welcome to QuickNotes","body":"This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.","created_at":"2026-01-15T10:00:00Z"} +{"error":"invalid JSON body"} +{"notes":44,"status":"ok"} +done 200 requests diff --git a/submissions/attachments/lab8/verify.txt b/submissions/attachments/lab8/verify.txt new file mode 100644 index 000000000..10c622e64 --- /dev/null +++ b/submissions/attachments/lab8/verify.txt @@ -0,0 +1,23 @@ +=== curl health === +{"notes":44,"status":"ok"} + +=== targets health === +['up'] +=== alert state === +[('HighHTTPErrorRate', 'firing', '3.1725888324873097e-01')] +=== error rate query === +{ + "status": "success", + "data": { + "resultType": "vector", + "result": [ + { + "metric": {}, + "value": [ + 1782847356.751, + "31.7258883248731" + ] + } + ] + } +} diff --git a/submissions/attachments/lab9/govulncheck-green.txt b/submissions/attachments/lab9/govulncheck-green.txt new file mode 100644 index 000000000..e7589224d --- /dev/null +++ b/submissions/attachments/lab9/govulncheck-green.txt @@ -0,0 +1 @@ +No vulnerabilities found. diff --git a/submissions/attachments/lab9/govulncheck-red.txt b/submissions/attachments/lab9/govulncheck-red.txt new file mode 100644 index 000000000..eb1fc5058 --- /dev/null +++ b/submissions/attachments/lab9/govulncheck-red.txt @@ -0,0 +1,30 @@ +=== Symbol Results === + +Vulnerability #1: GO-2026-5020 + Invoking infinite loop on large channel writes in golang.org/x/crypto/ssh + More info: https://pkg.go.dev/vuln/GO-2026-5020 + Module: golang.org/x/crypto + Found in: golang.org/x/crypto@v0.3.0 + Fixed in: golang.org/x/crypto@v0.52.0 + Example traces found: + #1: main.go:3:23: vulndemo.main calls ssh.Dial + +Vulnerability #2: GO-2026-5019 + Invoking bypass of FIDO/U2F security keys physical interaction in + golang.org/x/crypto/ssh + More info: https://pkg.go.dev/vuln/GO-2026-5019 + Module: golang.org/x/crypto + Found in: golang.org/x/crypto@v0.3.0 + Fixed in: golang.org/x/crypto@v0.52.0 + Example traces found: + #1: main.go:3:23: vulndemo.main calls ssh.Dial + +Vulnerability #3: GO-2026-5018 + Invoking pathological RSA/DSA parameters may cause DoS in + golang.org/x/crypto/ssh + More info: https://pkg.go.dev/vuln/GO-2026-5018 + Module: golang.org/x/crypto + Found in: golang.org/x/crypto@v0.3.0 + Fixed in: golang.org/x/crypto@v0.52.0 + Example traces found: + #1: main.go:3:23: vulndemo.main calls ssh.Dial diff --git a/submissions/attachments/lab9/green_ci.png b/submissions/attachments/lab9/green_ci.png new file mode 100644 index 000000000..7ec2b8f28 Binary files /dev/null and b/submissions/attachments/lab9/green_ci.png differ diff --git a/submissions/attachments/lab9/red_ci.png b/submissions/attachments/lab9/red_ci.png new file mode 100644 index 000000000..5a1586d54 Binary files /dev/null and b/submissions/attachments/lab9/red_ci.png differ diff --git a/submissions/attachments/lab9/trivy/config-scan-after.txt b/submissions/attachments/lab9/trivy/config-scan-after.txt new file mode 100644 index 000000000..ba3bfdb4b --- /dev/null +++ b/submissions/attachments/lab9/trivy/config-scan-after.txt @@ -0,0 +1 @@ +No HIGH/CRITICAL misconfigurations after adding `USER nonroot:nonroot` to `app/Dockerfile`. diff --git a/submissions/attachments/lab9/trivy/config-scan.txt b/submissions/attachments/lab9/trivy/config-scan.txt new file mode 100644 index 000000000..9ebb62e27 --- /dev/null +++ b/submissions/attachments/lab9/trivy/config-scan.txt @@ -0,0 +1,14 @@ + +app/Dockerfile (dockerfile) +=========================== +Tests: 21 (SUCCESSES: 20, FAILURES: 1) +Failures: 1 (HIGH: 1, CRITICAL: 0) + +AVD-DS-0002 (HIGH): Specify at least 1 USER command in Dockerfile with non-root user as argument +════════════════════════════════════════ +Running containers with 'root' user can lead to a container escape situation. It is a best practice to run containers as non-root users, which can be done by adding a 'USER' statement to the Dockerfile. + +See https://avd.aquasec.com/misconfig/ds002 +──────────────────────────────────────── + + diff --git a/submissions/attachments/lab9/trivy/fs-scan.txt b/submissions/attachments/lab9/trivy/fs-scan.txt new file mode 100644 index 000000000..fd78a4afd --- /dev/null +++ b/submissions/attachments/lab9/trivy/fs-scan.txt @@ -0,0 +1 @@ +No HIGH/CRITICAL findings (trivy fs --skip-dirs .vagrant --skip-dirs .git /repo). diff --git a/submissions/attachments/lab9/trivy/image-scan-after.txt b/submissions/attachments/lab9/trivy/image-scan-after.txt new file mode 100644 index 000000000..2a20e2055 --- /dev/null +++ b/submissions/attachments/lab9/trivy/image-scan-after.txt @@ -0,0 +1,65 @@ +2026-07-07T18:48:35Z INFO [vulndb] Need to update DB +2026-07-07T18:48:35Z INFO [vulndb] Downloading vulnerability DB... +2026-07-07T18:48:35Z INFO [vulndb] Downloading artifact... repo="mirror.gcr.io/aquasec/trivy-db:2" +2026-07-07T18:49:00Z INFO [vulndb] Artifact successfully downloaded repo="mirror.gcr.io/aquasec/trivy-db:2" +2026-07-07T18:49:00Z INFO [vuln] Vulnerability scanning is enabled +2026-07-07T18:49:00Z INFO [secret] Secret scanning is enabled +2026-07-07T18:49:00Z INFO [secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning +2026-07-07T18:49:00Z INFO [secret] Please see also https://aquasecurity.github.io/trivy/v0.59/docs/scanner/secret#recommendation for faster secret detection +2026-07-07T18:49:01Z INFO Detected OS family="debian" version="12.14" +2026-07-07T18:49:01Z INFO [debian] Detecting vulnerabilities... os_version="12" pkg_num=4 +2026-07-07T18:49:01Z INFO Number of language-specific files num=1 +2026-07-07T18:49:01Z INFO [gobinary] Detecting vulnerabilities... +2026-07-07T18:49:01Z WARN Using severities from other vendors for some vulnerabilities. Read https://aquasecurity.github.io/trivy/v0.59/docs/scanner/vulnerability#severity-selection for details. + +quicknotes:lab6 (debian 12.14) +============================== +Total: 0 (HIGH: 0, CRITICAL: 0) + + +quicknotes (gobinary) +===================== +Total: 10 (HIGH: 10, CRITICAL: 0) + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Library β”‚ Vulnerability β”‚ Severity β”‚ Status β”‚ Installed Version β”‚ Fixed Version β”‚ Title β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ stdlib β”‚ CVE-2026-25679 β”‚ HIGH β”‚ fixed β”‚ v1.24.13 β”‚ 1.25.8, 1.26.1 β”‚ net/url: Incorrect parsing of IPv6 host literals in net/url β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-25679 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-27145 β”‚ β”‚ β”‚ β”‚ 1.25.11, 1.26.4 β”‚ crypto/x509: golang: golang crypto/x509: Denial of Service β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ via excessive processing of DNS... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-27145 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-32280 β”‚ β”‚ β”‚ β”‚ 1.25.9, 1.26.2 β”‚ crypto/x509: crypto/tls: golang: Go: Denial of Service β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ vulnerability in certificate chain building... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-32280 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-32281 β”‚ β”‚ β”‚ β”‚ β”‚ crypto/x509: golang: Go crypto/x509: Denial of Service via β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ inefficient certificate chain validation... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-32281 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-32283 β”‚ β”‚ β”‚ β”‚ β”‚ crypto/tls: golang: Go crypto/tls: Denial of Service via β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ multiple TLS 1.3 key... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-32283 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-33811 β”‚ β”‚ β”‚ β”‚ 1.25.10, 1.26.3 β”‚ net: golang: Go net package: Denial of Service via long β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ CNAME response... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-33811 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-33814 β”‚ β”‚ β”‚ β”‚ β”‚ net/http/internal/http2: golang: golang.org/x/net: Go β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ HTTP/2: Denial of Service via malformed β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ SETTINGS_MAX_FRAME_SIZE frame... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-33814 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-39820 β”‚ β”‚ β”‚ β”‚ β”‚ net/mail: golang: Go net/mail: Denial of Service via crafted β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ email inputs β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-39820 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-39836 β”‚ β”‚ β”‚ β”‚ β”‚ ELSA-2026-22121: golang security update (IMPORTANT) β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-39836 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-42499 β”‚ β”‚ β”‚ β”‚ β”‚ net/mail: golang: net/mail: Denial of Service via β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ pathological email address parsing β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-42499 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ diff --git a/submissions/attachments/lab9/trivy/image-scan.txt b/submissions/attachments/lab9/trivy/image-scan.txt new file mode 100644 index 000000000..409a99e05 --- /dev/null +++ b/submissions/attachments/lab9/trivy/image-scan.txt @@ -0,0 +1,65 @@ +2026-07-07T14:43:24Z INFO [vulndb] Need to update DB +2026-07-07T14:43:24Z INFO [vulndb] Downloading vulnerability DB... +2026-07-07T14:43:24Z INFO [vulndb] Downloading artifact... repo="mirror.gcr.io/aquasec/trivy-db:2" +2026-07-07T14:46:15Z INFO [vulndb] Artifact successfully downloaded repo="mirror.gcr.io/aquasec/trivy-db:2" +2026-07-07T14:46:15Z INFO [vuln] Vulnerability scanning is enabled +2026-07-07T14:46:15Z INFO [secret] Secret scanning is enabled +2026-07-07T14:46:15Z INFO [secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning +2026-07-07T14:46:15Z INFO [secret] Please see also https://aquasecurity.github.io/trivy/v0.59/docs/scanner/secret#recommendation for faster secret detection +2026-07-07T14:46:15Z INFO Detected OS family="debian" version="12.14" +2026-07-07T14:46:15Z INFO [debian] Detecting vulnerabilities... os_version="12" pkg_num=4 +2026-07-07T14:46:15Z INFO Number of language-specific files num=1 +2026-07-07T14:46:15Z INFO [gobinary] Detecting vulnerabilities... +2026-07-07T14:46:15Z WARN Using severities from other vendors for some vulnerabilities. Read https://aquasecurity.github.io/trivy/v0.59/docs/scanner/vulnerability#severity-selection for details. + +quicknotes:lab6 (debian 12.14) +============================== +Total: 0 (HIGH: 0, CRITICAL: 0) + + +quicknotes (gobinary) +===================== +Total: 10 (HIGH: 10, CRITICAL: 0) + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Library β”‚ Vulnerability β”‚ Severity β”‚ Status β”‚ Installed Version β”‚ Fixed Version β”‚ Title β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ stdlib β”‚ CVE-2026-25679 β”‚ HIGH β”‚ fixed β”‚ v1.24.13 β”‚ 1.25.8, 1.26.1 β”‚ net/url: Incorrect parsing of IPv6 host literals in net/url β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-25679 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-27145 β”‚ β”‚ β”‚ β”‚ 1.25.11, 1.26.4 β”‚ crypto/x509: golang: golang crypto/x509: Denial of Service β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ via excessive processing of DNS... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-27145 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-32280 β”‚ β”‚ β”‚ β”‚ 1.25.9, 1.26.2 β”‚ crypto/x509: crypto/tls: golang: Go: Denial of Service β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ vulnerability in certificate chain building... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-32280 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-32281 β”‚ β”‚ β”‚ β”‚ β”‚ crypto/x509: golang: Go crypto/x509: Denial of Service via β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ inefficient certificate chain validation... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-32281 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-32283 β”‚ β”‚ β”‚ β”‚ β”‚ crypto/tls: golang: Go crypto/tls: Denial of Service via β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ multiple TLS 1.3 key... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-32283 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-33811 β”‚ β”‚ β”‚ β”‚ 1.25.10, 1.26.3 β”‚ net: golang: Go net package: Denial of Service via long β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ CNAME response... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-33811 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-33814 β”‚ β”‚ β”‚ β”‚ β”‚ net/http/internal/http2: golang: golang.org/x/net: Go β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ HTTP/2: Denial of Service via malformed β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ SETTINGS_MAX_FRAME_SIZE frame... β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-33814 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-39820 β”‚ β”‚ β”‚ β”‚ β”‚ net/mail: golang: Go net/mail: Denial of Service via crafted β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ email inputs β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-39820 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-39836 β”‚ β”‚ β”‚ β”‚ β”‚ ELSA-2026-22121: golang security update (IMPORTANT) β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-39836 β”‚ +β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ CVE-2026-42499 β”‚ β”‚ β”‚ β”‚ β”‚ net/mail: golang: net/mail: Denial of Service via β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ pathological email address parsing β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ https://avd.aquasec.com/nvd/cve-2026-42499 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ diff --git a/submissions/attachments/lab9/trivy/sbom-head.txt b/submissions/attachments/lab9/trivy/sbom-head.txt new file mode 100644 index 000000000..712ae630a --- /dev/null +++ b/submissions/attachments/lab9/trivy/sbom-head.txt @@ -0,0 +1,30 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.6", + "serialNumber": "urn:uuid:960d50bf-33b6-4206-8f4a-29751974aabb", + "version": 1, + "metadata": { + "timestamp": "2026-07-07T18:49:01+00:00", + "tools": { + "components": [ + { + "type": "application", + "group": "aquasecurity", + "name": "trivy", + "version": "0.59.1" + } + ] + }, + "component": { + "bom-ref": "pkg:oci/quicknotes@sha256%3Af708ad475533dcf6d221d62bc69c3d62a8fb2f3a8c441d32a5a910a3ff10c0c6?arch=arm64&repository_url=index.docker.io%2Flibrary%2Fquicknotes", + "type": "container", + "name": "quicknotes:lab6", + "purl": "pkg:oci/quicknotes@sha256%3Af708ad475533dcf6d221d62bc69c3d62a8fb2f3a8c441d32a5a910a3ff10c0c6?arch=arm64&repository_url=index.docker.io%2Flibrary%2Fquicknotes", + "properties": [ + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:114dde0fefebbca13165d0da9c500a66190e497a82a53dcaabc3172d630be1e9" + }, + { + "name": "aquasecurity:trivy:DiffID", diff --git a/submissions/attachments/lab9/trivy/sbom-log.txt b/submissions/attachments/lab9/trivy/sbom-log.txt new file mode 100644 index 000000000..972ebb956 --- /dev/null +++ b/submissions/attachments/lab9/trivy/sbom-log.txt @@ -0,0 +1,3 @@ +2026-07-07T18:49:01Z INFO "--format cyclonedx" disables security scanning. Specify "--scanners vuln" explicitly if you want to include vulnerabilities in the "cyclonedx" report. +2026-07-07T18:49:01Z INFO Detected OS family="debian" version="12.14" +2026-07-07T18:49:01Z INFO Number of language-specific files num=1 diff --git a/submissions/attachments/lab9/trivy/sbom.cdx.json b/submissions/attachments/lab9/trivy/sbom.cdx.json new file mode 100644 index 000000000..35b41c982 --- /dev/null +++ b/submissions/attachments/lab9/trivy/sbom.cdx.json @@ -0,0 +1,425 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.6", + "serialNumber": "urn:uuid:960d50bf-33b6-4206-8f4a-29751974aabb", + "version": 1, + "metadata": { + "timestamp": "2026-07-07T18:49:01+00:00", + "tools": { + "components": [ + { + "type": "application", + "group": "aquasecurity", + "name": "trivy", + "version": "0.59.1" + } + ] + }, + "component": { + "bom-ref": "pkg:oci/quicknotes@sha256%3Af708ad475533dcf6d221d62bc69c3d62a8fb2f3a8c441d32a5a910a3ff10c0c6?arch=arm64&repository_url=index.docker.io%2Flibrary%2Fquicknotes", + "type": "container", + "name": "quicknotes:lab6", + "purl": "pkg:oci/quicknotes@sha256%3Af708ad475533dcf6d221d62bc69c3d62a8fb2f3a8c441d32a5a910a3ff10c0c6?arch=arm64&repository_url=index.docker.io%2Flibrary%2Fquicknotes", + "properties": [ + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:114dde0fefebbca13165d0da9c500a66190e497a82a53dcaabc3172d630be1e9" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:33b37ab0b0901175c2699d81c10b0c887f0dff944de74763cca00c155904d6fb" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:35b5ba6e08cdd034b8d1920f9c7203e5d66f258e1915f164a01de0af14f34710" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:4cde6b0bb6f50a5f255eef7b2a42162c661cf776b803225dcac9a659e396bb6b" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:4d049f83d9cf21d1f5cc0e11deaf36df02790d0e60c1a3829538fb4b61685368" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:531678dbb0358bce7a8a19ff56fcc39488beb8fe8bf17814e156d2986a47d43e" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:6e7fbcf090d09b73a4aa85f9dce690d0ace73877c150b7c56955487b6e7a822a" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:6f1cdceb6a3146f0ccb986521156bef8a422cdbb0863396f7f751f575ba308f4" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:80b1f42918092d58c439a051239e0788bf3e84802dae6f2ac4ecab0a7a08148e" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:8fa10c0194df9b7c054c90dbe482585f768a54428fc90a5b78a0066a123b1bba" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:a0ff877a11d72f1832840a3cddfeeb3962d2b3fae4e11aca8de212cb24ced9f3" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:ad51d0769d16ba578106a177987dfe3d2e02c1668c852b795b2f6b024068242a" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:af5aa97ebe6ce1604747ec1e21af7136ded391bcabe4acef882e718a87c86bcc" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:b3eb5fcfaf0fc8982e3f370bde32740bb83e3fb363c189290b4c58c2e1af965a" + }, + { + "name": "aquasecurity:trivy:DiffID", + "value": "sha256:bd3cdfae1d3fdd83a2231d608969b38b82349777c2fff9a7c12d54f8ac5c9b38" + }, + { + "name": "aquasecurity:trivy:ImageID", + "value": "sha256:f708ad475533dcf6d221d62bc69c3d62a8fb2f3a8c441d32a5a910a3ff10c0c6" + }, + { + "name": "aquasecurity:trivy:Labels:com.docker.compose.project", + "value": "devops-intro" + }, + { + "name": "aquasecurity:trivy:Labels:com.docker.compose.service", + "value": "quicknotes" + }, + { + "name": "aquasecurity:trivy:Labels:com.docker.compose.version", + "value": "5.1.3" + }, + { + "name": "aquasecurity:trivy:RepoDigest", + "value": "quicknotes@sha256:f708ad475533dcf6d221d62bc69c3d62a8fb2f3a8c441d32a5a910a3ff10c0c6" + }, + { + "name": "aquasecurity:trivy:RepoTag", + "value": "quicknotes:lab6" + }, + { + "name": "aquasecurity:trivy:SchemaVersion", + "value": "2" + } + ] + } + }, + "components": [ + { + "bom-ref": "bb3b44f7-1ccf-4d1f-9352-0b50c061fb72", + "type": "operating-system", + "name": "debian", + "version": "12.14", + "properties": [ + { + "name": "aquasecurity:trivy:Class", + "value": "os-pkgs" + }, + { + "name": "aquasecurity:trivy:Type", + "value": "debian" + } + ] + }, + { + "bom-ref": "f9af8480-f80b-4eea-b10b-5fe3b1b6e2e5", + "type": "application", + "name": "quicknotes", + "properties": [ + { + "name": "aquasecurity:trivy:Class", + "value": "lang-pkgs" + }, + { + "name": "aquasecurity:trivy:Type", + "value": "gobinary" + } + ] + }, + { + "bom-ref": "pkg:deb/debian/base-files@12.4%2Bdeb12u14?arch=arm64&distro=debian-12.14", + "type": "library", + "supplier": { + "name": "Santiago Vila " + }, + "name": "base-files", + "version": "12.4+deb12u14", + "licenses": [ + { + "license": { + "name": "GPL-2.0-or-later" + } + } + ], + "purl": "pkg:deb/debian/base-files@12.4%2Bdeb12u14?arch=arm64&distro=debian-12.14", + "properties": [ + { + "name": "aquasecurity:trivy:LayerDiffID", + "value": "sha256:a0ff877a11d72f1832840a3cddfeeb3962d2b3fae4e11aca8de212cb24ced9f3" + }, + { + "name": "aquasecurity:trivy:LayerDigest", + "value": "sha256:36a0d76d579d99971aa6e12b2d5460703b2c27df78ecb53cfb5385c7cfc1c8ff" + }, + { + "name": "aquasecurity:trivy:PkgID", + "value": "base-files@12.4+deb12u14" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "debian" + }, + { + "name": "aquasecurity:trivy:SrcName", + "value": "base-files" + }, + { + "name": "aquasecurity:trivy:SrcVersion", + "value": "12.4+deb12u14" + } + ] + }, + { + "bom-ref": "pkg:deb/debian/media-types@10.0.0?arch=all&distro=debian-12.14", + "type": "library", + "supplier": { + "name": "Mime-Support Packagers " + }, + "name": "media-types", + "version": "10.0.0", + "licenses": [ + { + "license": { + "name": "ad-hoc" + } + } + ], + "purl": "pkg:deb/debian/media-types@10.0.0?arch=all&distro=debian-12.14", + "properties": [ + { + "name": "aquasecurity:trivy:LayerDiffID", + "value": "sha256:114dde0fefebbca13165d0da9c500a66190e497a82a53dcaabc3172d630be1e9" + }, + { + "name": "aquasecurity:trivy:LayerDigest", + "value": "sha256:bf7a4185f01524837d19abde915ffde84e64368b250f5b5e9f6f75aea62a11d4" + }, + { + "name": "aquasecurity:trivy:PkgID", + "value": "media-types@10.0.0" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "debian" + }, + { + "name": "aquasecurity:trivy:SrcName", + "value": "media-types" + }, + { + "name": "aquasecurity:trivy:SrcVersion", + "value": "10.0.0" + } + ] + }, + { + "bom-ref": "pkg:deb/debian/netbase@6.4?arch=all&distro=debian-12.14", + "type": "library", + "supplier": { + "name": "Marco d'Itri " + }, + "name": "netbase", + "version": "6.4", + "licenses": [ + { + "license": { + "name": "GPL-2.0-only" + } + } + ], + "purl": "pkg:deb/debian/netbase@6.4?arch=all&distro=debian-12.14", + "properties": [ + { + "name": "aquasecurity:trivy:LayerDiffID", + "value": "sha256:8fa10c0194df9b7c054c90dbe482585f768a54428fc90a5b78a0066a123b1bba" + }, + { + "name": "aquasecurity:trivy:LayerDigest", + "value": "sha256:990a9c434e5e0f11549a8d4a41a1991e621b04e30cd63269adbc97b1dc38fd7e" + }, + { + "name": "aquasecurity:trivy:PkgID", + "value": "netbase@6.4" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "debian" + }, + { + "name": "aquasecurity:trivy:SrcName", + "value": "netbase" + }, + { + "name": "aquasecurity:trivy:SrcVersion", + "value": "6.4" + } + ] + }, + { + "bom-ref": "pkg:deb/debian/tzdata@2026b-0%2Bdeb12u1?arch=all&distro=debian-12.14", + "type": "library", + "supplier": { + "name": "GNU Libc Maintainers " + }, + "name": "tzdata", + "version": "2026b-0+deb12u1", + "licenses": [ + { + "license": { + "name": "public-domain" + } + } + ], + "purl": "pkg:deb/debian/tzdata@2026b-0%2Bdeb12u1?arch=all&distro=debian-12.14", + "properties": [ + { + "name": "aquasecurity:trivy:LayerDiffID", + "value": "sha256:35b5ba6e08cdd034b8d1920f9c7203e5d66f258e1915f164a01de0af14f34710" + }, + { + "name": "aquasecurity:trivy:LayerDigest", + "value": "sha256:39dc083afc39bd8dc43d456fe7ff7d39292e593bb2769972c11bb2e5f9119386" + }, + { + "name": "aquasecurity:trivy:PkgID", + "value": "tzdata@2026b-0+deb12u1" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "debian" + }, + { + "name": "aquasecurity:trivy:SrcName", + "value": "tzdata" + }, + { + "name": "aquasecurity:trivy:SrcRelease", + "value": "0+deb12u1" + }, + { + "name": "aquasecurity:trivy:SrcVersion", + "value": "2026b" + } + ] + }, + { + "bom-ref": "pkg:golang/quicknotes", + "type": "library", + "name": "quicknotes", + "purl": "pkg:golang/quicknotes", + "properties": [ + { + "name": "aquasecurity:trivy:LayerDiffID", + "value": "sha256:b3eb5fcfaf0fc8982e3f370bde32740bb83e3fb363c189290b4c58c2e1af965a" + }, + { + "name": "aquasecurity:trivy:LayerDigest", + "value": "sha256:3630744617d50ad32e922cad3f543eaa52c9d626e9a973b5de9cf2e36bb544c8" + }, + { + "name": "aquasecurity:trivy:PkgID", + "value": "quicknotes" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "gobinary" + } + ] + }, + { + "bom-ref": "pkg:golang/stdlib@v1.24.13", + "type": "library", + "name": "stdlib", + "version": "v1.24.13", + "purl": "pkg:golang/stdlib@v1.24.13", + "properties": [ + { + "name": "aquasecurity:trivy:LayerDiffID", + "value": "sha256:b3eb5fcfaf0fc8982e3f370bde32740bb83e3fb363c189290b4c58c2e1af965a" + }, + { + "name": "aquasecurity:trivy:LayerDigest", + "value": "sha256:3630744617d50ad32e922cad3f543eaa52c9d626e9a973b5de9cf2e36bb544c8" + }, + { + "name": "aquasecurity:trivy:PkgID", + "value": "stdlib@v1.24.13" + }, + { + "name": "aquasecurity:trivy:PkgType", + "value": "gobinary" + } + ] + } + ], + "dependencies": [ + { + "ref": "bb3b44f7-1ccf-4d1f-9352-0b50c061fb72", + "dependsOn": [ + "pkg:deb/debian/base-files@12.4%2Bdeb12u14?arch=arm64&distro=debian-12.14", + "pkg:deb/debian/media-types@10.0.0?arch=all&distro=debian-12.14", + "pkg:deb/debian/netbase@6.4?arch=all&distro=debian-12.14", + "pkg:deb/debian/tzdata@2026b-0%2Bdeb12u1?arch=all&distro=debian-12.14" + ] + }, + { + "ref": "f9af8480-f80b-4eea-b10b-5fe3b1b6e2e5", + "dependsOn": [ + "pkg:golang/quicknotes" + ] + }, + { + "ref": "pkg:deb/debian/base-files@12.4%2Bdeb12u14?arch=arm64&distro=debian-12.14", + "dependsOn": [] + }, + { + "ref": "pkg:deb/debian/media-types@10.0.0?arch=all&distro=debian-12.14", + "dependsOn": [] + }, + { + "ref": "pkg:deb/debian/netbase@6.4?arch=all&distro=debian-12.14", + "dependsOn": [] + }, + { + "ref": "pkg:deb/debian/tzdata@2026b-0%2Bdeb12u1?arch=all&distro=debian-12.14", + "dependsOn": [] + }, + { + "ref": "pkg:golang/quicknotes", + "dependsOn": [ + "pkg:golang/stdlib@v1.24.13" + ] + }, + { + "ref": "pkg:golang/stdlib@v1.24.13", + "dependsOn": [] + }, + { + "ref": "pkg:oci/quicknotes@sha256%3Af708ad475533dcf6d221d62bc69c3d62a8fb2f3a8c441d32a5a910a3ff10c0c6?arch=arm64&repository_url=index.docker.io%2Flibrary%2Fquicknotes", + "dependsOn": [ + "bb3b44f7-1ccf-4d1f-9352-0b50c061fb72", + "f9af8480-f80b-4eea-b10b-5fe3b1b6e2e5" + ] + } + ], + "vulnerabilities": [] +} diff --git a/submissions/attachments/lab9/zap-after/headers-health-after.txt b/submissions/attachments/lab9/zap-after/headers-health-after.txt new file mode 100644 index 000000000..e7852cfe1 --- /dev/null +++ b/submissions/attachments/lab9/zap-after/headers-health-after.txt @@ -0,0 +1,12 @@ +HTTP/1.1 200 OK +Cache-Control: no-cache, no-store, must-revalidate, private +Content-Security-Policy: default-src 'none' +Content-Type: application/json +Permissions-Policy: geolocation=(), microphone=(), camera=() +Pragma: no-cache +Referrer-Policy: no-referrer +X-Content-Type-Options: nosniff +X-Frame-Options: DENY +Date: Tue, 07 Jul 2026 18:47:52 GMT +Content-Length: 27 + diff --git a/submissions/attachments/lab9/zap-after/zap-baseline.log b/submissions/attachments/lab9/zap-after/zap-baseline.log new file mode 100644 index 000000000..541f74f40 --- /dev/null +++ b/submissions/attachments/lab9/zap-after/zap-baseline.log @@ -0,0 +1,77 @@ +Using the Automation Framework +Total of 5 URLs +PASS: Vulnerable JS Library (Powered by Retire.js) [10003] +PASS: In Page Banner Information Leak [10009] +PASS: Cookie No HttpOnly Flag [10010] +PASS: Cookie Without Secure Flag [10011] +PASS: Re-examine Cache-control Directives [10015] +PASS: Cross-Domain JavaScript Source File Inclusion [10017] +PASS: Content-Type Header Missing [10019] +PASS: Anti-clickjacking Header [10020] +PASS: X-Content-Type-Options Header Missing [10021] +PASS: Information Disclosure - Debug Error Messages [10023] +PASS: Information Disclosure - Sensitive Information in URL [10024] +PASS: Information Disclosure - Sensitive Information in HTTP Referrer Header [10025] +PASS: HTTP Parameter Override [10026] +PASS: Information Disclosure - Suspicious Comments [10027] +PASS: Off-site Redirect [10028] +PASS: Cookie Poisoning [10029] +PASS: User Controllable Charset [10030] +PASS: User Controllable HTML Element Attribute (Potential XSS) [10031] +PASS: Viewstate [10032] +PASS: Directory Browsing [10033] +PASS: Heartbleed OpenSSL Vulnerability (Indicative) [10034] +PASS: Strict-Transport-Security Header [10035] +PASS: HTTP Server Response Header [10036] +PASS: Server Leaks Information via "X-Powered-By" HTTP Response Header Field(s) [10037] +PASS: Content Security Policy (CSP) Header Not Set [10038] +PASS: X-Backend-Server Header Information Leak [10039] +PASS: Secure Pages Include Mixed Content [10040] +PASS: HTTP to HTTPS Insecure Transition in Form Post [10041] +PASS: HTTPS to HTTP Insecure Transition in Form Post [10042] +PASS: User Controllable JavaScript Event (XSS) [10043] +PASS: Big Redirect Detected (Potential Sensitive Information Leak) [10044] +PASS: Retrieved from Cache [10050] +PASS: X-ChromeLogger-Data (XCOLD) Header Information Leak [10052] +PASS: Cookie without SameSite Attribute [10054] +PASS: CSP [10055] +PASS: X-Debug-Token Information Leak [10056] +PASS: Username Hash Found [10057] +PASS: X-AspNet-Version Response Header [10061] +PASS: PII Disclosure [10062] +PASS: Permissions Policy Header Not Set [10063] +PASS: Timestamp Disclosure [10096] +PASS: Hash Disclosure [10097] +PASS: Cross-Domain Misconfiguration [10098] +PASS: Source Code Disclosure [10099] +PASS: Weak Authentication Method [10105] +PASS: Reverse Tabnabbing [10108] +PASS: Modern Web Application [10109] +PASS: Dangerous JS Functions [10110] +PASS: Authentication Request Identified [10111] +PASS: Session Management Response Identified [10112] +PASS: Verification Request Identified [10113] +PASS: Script Served From Malicious Domain (polyfill) [10115] +PASS: Absence of Anti-CSRF Tokens [10202] +PASS: Private IP Disclosure [2] +PASS: Session ID in URL Rewrite [3] +PASS: Script Passive Scan Rules [50001] +PASS: Stats Passive Scan Rule [50003] +PASS: Insecure JSF ViewState [90001] +PASS: Java Serialization Object [90002] +PASS: Sub Resource Integrity Attribute Missing [90003] +PASS: Charset Mismatch [90011] +PASS: Application Error Disclosure [90022] +PASS: WSDL File Detection [90030] +PASS: Loosely Scoped Cookie [90033] +WARN-NEW: Non-Storable Content [10049] x 3 + http://host.docker.internal:8080/ (404 Not Found) + http://host.docker.internal:8080/health (200 OK) + http://host.docker.internal:8080/robots.txt (404 Not Found) +WARN-NEW: ZAP is Out of Date [10116] x 1 + http://host.docker.internal:8080/robots.txt (404 Not Found) +WARN-NEW: Insufficient Site Isolation Against Spectre Vulnerability [90004] x 1 + http://host.docker.internal:8080/health (200 OK) +FAIL-NEW: 0 FAIL-INPROG: 0 WARN-NEW: 3 WARN-INPROG: 0 INFO: 0 IGNORE: 0 PASS: 64 +Automation plan warnings: + Job spider error accessing URL http://host.docker.internal:8080/ status code returned : 404 expected 200 diff --git a/submissions/attachments/lab9/zap-after/zap-report.html b/submissions/attachments/lab9/zap-after/zap-report.html new file mode 100644 index 000000000..eea87c068 --- /dev/null +++ b/submissions/attachments/lab9/zap-after/zap-report.html @@ -0,0 +1,724 @@ + + + + +ZAP Scanning Report + + + +

+ + + ZAP Scanning Report +

+

+ + +

+ + Site: http://host.docker.internal:8080 + +

+ +

+ Generated on Tue, 7 Jul 2026 18:48:11 +

+ +

+ ZAP Version: 2.16.1 +

+ +

+ ZAP by Checkmarx +

+ + +

Summary of Alerts

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Risk LevelNumber of Alerts
+
High
+
+
0
+
+
Medium
+
+
0
+
+
Low
+
+
2
+
+
Informational
+
+
1
+
+
False Positives:
+
+
0
+
+
+ + + + +

Summary of Sequences

+

For each step: result (Pass/Fail) - risk (of highest alert(s) for the step, if any).

+ + + + + + +

Alerts

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameRisk LevelNumber of Instances
Insufficient Site Isolation Against Spectre VulnerabilityLow1
ZAP is Out of DateLow1
Non-Storable ContentInformational3
+
+ + + +

Alert Detail

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Low
Insufficient Site Isolation Against Spectre Vulnerability
Description +
Cross-Origin-Resource-Policy header is an opt-in header designed to counter side-channels attacks like Spectre. Resource should be specifically set as shareable amongst different origins.
+ +
URLhttp://host.docker.internal:8080/health
MethodGET
ParameterCross-Origin-Resource-Policy
Attack
Evidence
Other Info
Instances1
Solution +
Ensure that the application/web server sets the Cross-Origin-Resource-Policy header appropriately, and that it sets the Cross-Origin-Resource-Policy header to 'same-origin' for all web pages.
+
+ +
'same-site' is considered as less secured and should be avoided.
+
+ +
If resources must be shared, set the header to 'cross-origin'.
+
+ +
If possible, ensure that the end user uses a standards-compliant and modern web browser that supports the Cross-Origin-Resource-Policy header (https://caniuse.com/mdn-http_headers_cross-origin-resource-policy).
+ +
Reference + https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Embedder-Policy + +
CWE Id693
WASC Id14
Plugin Id90004
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Low
ZAP is Out of Date
Description +
The version of ZAP you are using to test your app is out of date and is no longer being updated.
+
+ +
The risk level is set based on how out of date your ZAP version is.
+ +
URLhttp://host.docker.internal:8080/robots.txt
MethodGET
Parameter
Attack
Evidence
Other InfoThe latest version of ZAP is 2.17.0
Instances1
Solution +
Download the latest version of ZAP from https://www.zaproxy.org/download/ and install it.
+ +
Reference + https://www.zaproxy.org/download/ + +
CWE Id1104
WASC Id45
Plugin Id10116
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Informational
Non-Storable Content
Description +
The response contents are not storable by caching components such as proxy servers. If the response does not contain sensitive, personal or user-specific information, it may benefit from being stored and cached, to improve performance.
+ +
URLhttp://host.docker.internal:8080/
MethodGET
Parameter
Attack
Evidenceno-store
Other Info
URLhttp://host.docker.internal:8080/health
MethodGET
Parameter
Attack
Evidenceno-store
Other Info
URLhttp://host.docker.internal:8080/robots.txt
MethodGET
Parameter
Attack
Evidenceno-store
Other Info
Instances3
Solution +
The content may be marked as storable by ensuring that the following conditions are satisfied:
+
+ +
The request method must be understood by the cache and defined as being cacheable ("GET", "HEAD", and "POST" are currently defined as cacheable)
+
+ +
The response status code must be understood by the cache (one of the 1XX, 2XX, 3XX, 4XX, or 5XX response classes are generally understood)
+
+ +
The "no-store" cache directive must not appear in the request or response header fields
+
+ +
For caching by "shared" caches such as "proxy" caches, the "private" response directive must not appear in the response
+
+ +
For caching by "shared" caches such as "proxy" caches, the "Authorization" header field must not appear in the request, unless the response explicitly allows it (using one of the "must-revalidate", "public", or "s-maxage" Cache-Control response directives)
+
+ +
In addition to the conditions above, at least one of the following conditions must also be satisfied by the response:
+
+ +
It must contain an "Expires" header field
+
+ +
It must contain a "max-age" response directive
+
+ +
For "shared" caches such as "proxy" caches, it must contain a "s-maxage" response directive
+
+ +
It must contain a "Cache Control Extension" that allows it to be cached
+
+ +
It must have a status code that is defined as cacheable by default (200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501).
+ +
Reference + https://datatracker.ietf.org/doc/html/rfc7234 +
+ + https://datatracker.ietf.org/doc/html/rfc7231 +
+ + https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html + +
CWE Id524
WASC Id13
Plugin Id10049
+
+ + + + + +

Sequence Details

+ With the associated active scan results. + + + +
+ + + + + + + diff --git a/submissions/attachments/lab9/zap-after/zap-report.json b/submissions/attachments/lab9/zap-after/zap-report.json new file mode 100644 index 000000000..41d8cf08c --- /dev/null +++ b/submissions/attachments/lab9/zap-after/zap-report.json @@ -0,0 +1,129 @@ +{ + "@programName": "ZAP", + "@version": "2.16.1", + "@generated": "Tue, 7 Jul 2026 18:48:11", + "created": "2026-07-07T18:48:11.527195054Z", + "site":[ + { + "@name": "http://host.docker.internal:8080", + "@host": "host.docker.internal", + "@port": "8080", + "@ssl": "false", + "alerts": [ + { + "pluginid": "90004", + "alertRef": "90004-1", + "alert": "Insufficient Site Isolation Against Spectre Vulnerability", + "name": "Insufficient Site Isolation Against Spectre Vulnerability", + "riskcode": "1", + "confidence": "2", + "riskdesc": "Low (Medium)", + "desc": "

Cross-Origin-Resource-Policy header is an opt-in header designed to counter side-channels attacks like Spectre. Resource should be specifically set as shareable amongst different origins.

", + "instances":[ + { + "id": "7", + "uri": "http://host.docker.internal:8080/health", + "nodeName": null, + "method": "GET", + "param": "Cross-Origin-Resource-Policy", + "attack": "", + "evidence": "", + "otherinfo": "" + } + ], + "count": "1", + "systemic": false, + "solution": "

Ensure that the application/web server sets the Cross-Origin-Resource-Policy header appropriately, and that it sets the Cross-Origin-Resource-Policy header to 'same-origin' for all web pages.

'same-site' is considered as less secured and should be avoided.

If resources must be shared, set the header to 'cross-origin'.

If possible, ensure that the end user uses a standards-compliant and modern web browser that supports the Cross-Origin-Resource-Policy header (https://caniuse.com/mdn-http_headers_cross-origin-resource-policy).

", + "otherinfo": "", + "reference": "

https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cross-Origin-Embedder-Policy

", + "cweid": "693", + "wascid": "14", + "sourceid": "10" + }, + { + "pluginid": "10116", + "alertRef": "10116", + "alert": "ZAP is Out of Date", + "name": "ZAP is Out of Date", + "riskcode": "1", + "confidence": "3", + "riskdesc": "Low (High)", + "desc": "

The version of ZAP you are using to test your app is out of date and is no longer being updated.

The risk level is set based on how out of date your ZAP version is.

", + "instances":[ + { + "id": "3", + "uri": "http://host.docker.internal:8080/robots.txt", + "nodeName": null, + "method": "GET", + "param": "", + "attack": "", + "evidence": "", + "otherinfo": "The latest version of ZAP is 2.17.0" + } + ], + "count": "1", + "systemic": false, + "solution": "

Download the latest version of ZAP from https://www.zaproxy.org/download/ and install it.

", + "otherinfo": "

The latest version of ZAP is 2.17.0

", + "reference": "

https://www.zaproxy.org/download/

", + "cweid": "1104", + "wascid": "45", + "sourceid": "8" + }, + { + "pluginid": "10049", + "alertRef": "10049-1", + "alert": "Non-Storable Content", + "name": "Non-Storable Content", + "riskcode": "0", + "confidence": "2", + "riskdesc": "Informational (Medium)", + "desc": "

The response contents are not storable by caching components such as proxy servers. If the response does not contain sensitive, personal or user-specific information, it may benefit from being stored and cached, to improve performance.

", + "instances":[ + { + "id": "1", + "uri": "http://host.docker.internal:8080/", + "nodeName": null, + "method": "GET", + "param": "", + "attack": "", + "evidence": "no-store", + "otherinfo": "" + }, + { + "id": "5", + "uri": "http://host.docker.internal:8080/health", + "nodeName": null, + "method": "GET", + "param": "", + "attack": "", + "evidence": "no-store", + "otherinfo": "" + }, + { + "id": "4", + "uri": "http://host.docker.internal:8080/robots.txt", + "nodeName": null, + "method": "GET", + "param": "", + "attack": "", + "evidence": "no-store", + "otherinfo": "" + } + ], + "count": "3", + "systemic": false, + "solution": "

The content may be marked as storable by ensuring that the following conditions are satisfied:

The request method must be understood by the cache and defined as being cacheable (\"GET\", \"HEAD\", and \"POST\" are currently defined as cacheable)

The response status code must be understood by the cache (one of the 1XX, 2XX, 3XX, 4XX, or 5XX response classes are generally understood)

The \"no-store\" cache directive must not appear in the request or response header fields

For caching by \"shared\" caches such as \"proxy\" caches, the \"private\" response directive must not appear in the response

For caching by \"shared\" caches such as \"proxy\" caches, the \"Authorization\" header field must not appear in the request, unless the response explicitly allows it (using one of the \"must-revalidate\", \"public\", or \"s-maxage\" Cache-Control response directives)

In addition to the conditions above, at least one of the following conditions must also be satisfied by the response:

It must contain an \"Expires\" header field

It must contain a \"max-age\" response directive

For \"shared\" caches such as \"proxy\" caches, it must contain a \"s-maxage\" response directive

It must contain a \"Cache Control Extension\" that allows it to be cached

It must have a status code that is defined as cacheable by default (200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501).

", + "otherinfo": "", + "reference": "

https://datatracker.ietf.org/doc/html/rfc7234

https://datatracker.ietf.org/doc/html/rfc7231

https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html

", + "cweid": "524", + "wascid": "13", + "sourceid": "3" + } + ] + } + ], + "sequences":[ + ] + +} diff --git a/submissions/attachments/lab9/zap-after/zap.yaml b/submissions/attachments/lab9/zap-after/zap.yaml new file mode 100644 index 000000000..a4f6e9189 --- /dev/null +++ b/submissions/attachments/lab9/zap-after/zap.yaml @@ -0,0 +1,41 @@ +env: + contexts: + - excludePaths: [] + name: baseline + urls: + - http://host.docker.internal:8080/health + - http://host.docker.internal:8080/ + parameters: + failOnError: true + progressToStdout: false +jobs: +- parameters: + enableTags: false + maxAlertsPerRule: 10 + type: passiveScan-config +- parameters: + maxDuration: 1 + url: http://host.docker.internal:8080/ + type: spider +- parameters: + maxDuration: 0 + type: passiveScan-wait +- parameters: + format: Long + summaryFile: /home/zap/zap_out.json + rules: [] + type: outputSummary +- parameters: + reportDescription: '' + reportDir: /zap/wrk/ + reportFile: zap-report.html + reportTitle: ZAP Scanning Report + template: traditional-html + type: report +- parameters: + reportDescription: '' + reportDir: /zap/wrk/ + reportFile: zap-report.json + reportTitle: ZAP Scanning Report + template: traditional-json + type: report diff --git a/submissions/attachments/lab9/zap-before/headers-health-before.txt b/submissions/attachments/lab9/zap-before/headers-health-before.txt new file mode 100644 index 000000000..fbfdb9faa --- /dev/null +++ b/submissions/attachments/lab9/zap-before/headers-health-before.txt @@ -0,0 +1,5 @@ +HTTP/1.1 200 OK +Content-Type: application/json +Date: Tue, 07 Jul 2026 18:47:02 GMT +Content-Length: 27 + diff --git a/submissions/attachments/lab9/zap-before/zap-baseline.log b/submissions/attachments/lab9/zap-before/zap-baseline.log new file mode 100644 index 000000000..ce704a19d --- /dev/null +++ b/submissions/attachments/lab9/zap-before/zap-baseline.log @@ -0,0 +1,117 @@ +Using the Automation Framework +Total of 3 URLs +PASS: Vulnerable JS Library (Powered by Retire.js) [10003] +PASS: In Page Banner Information Leak [10009] +PASS: Cookie No HttpOnly Flag [10010] +PASS: Cookie Without Secure Flag [10011] +PASS: Re-examine Cache-control Directives [10015] +PASS: Cross-Domain JavaScript Source File Inclusion [10017] +PASS: Content-Type Header Missing [10019] +PASS: Anti-clickjacking Header [10020] +PASS: X-Content-Type-Options Header Missing [10021] +PASS: Information Disclosure - Debug Error Messages [10023] +PASS: Information Disclosure - Sensitive Information in URL [10024] +PASS: Information Disclosure - Sensitive Information in HTTP Referrer Header [10025] +PASS: HTTP Parameter Override [10026] +PASS: Information Disclosure - Suspicious Comments [10027] +PASS: Off-site Redirect [10028] +PASS: Cookie Poisoning [10029] +PASS: User Controllable Charset [10030] +PASS: User Controllable HTML Element Attribute (Potential XSS) [10031] +PASS: Viewstate [10032] +PASS: Directory Browsing [10033] +PASS: Heartbleed OpenSSL Vulnerability (Indicative) [10034] +PASS: Strict-Transport-Security Header [10035] +PASS: HTTP Server Response Header [10036] +PASS: Server Leaks Information via "X-Powered-By" HTTP Response Header Field(s) [10037] +PASS: Content Security Policy (CSP) Header Not Set [10038] +PASS: X-Backend-Server Header Information Leak [10039] +PASS: Secure Pages Include Mixed Content [10040] +PASS: HTTP to HTTPS Insecure Transition in Form Post [10041] +PASS: HTTPS to HTTP Insecure Transition in Form Post [10042] +PASS: User Controllable JavaScript Event (XSS) [10043] +PASS: Big Redirect Detected (Potential Sensitive Information Leak) [10044] +PASS: Retrieved from Cache [10050] +PASS: X-ChromeLogger-Data (XCOLD) Header Information Leak [10052] +PASS: Cookie without SameSite Attribute [10054] +PASS: CSP [10055] +PASS: X-Debug-Token Information Leak [10056] +PASS: Username Hash Found [10057] +PASS: X-AspNet-Version Response Header [10061] +PASS: PII Disclosure [10062] +PASS: Permissions Policy Header Not Set [10063] +PASS: Timestamp DisclosurUsing the Automation Framework +Total of 3 URLs +PASS: Vulnerable JS Library (Powered by Retire.js) [10003] +PASS: In Page Banner Information Leak [10009] +PASS: Cookie No HttpOnly Flag [10010] +PASS: Cookie Without Secure Flag [10011] +PASS: Re-examine Cache-control Directives [10015] +PASS: Cross-Domain JavaScript Source File Inclusion [10017] +PASS: Content-Type Header Missing [10019] +PASS: Anti-clickjacking Header [10020] +PASS: X-Content-Type-Options Header Missing [10021] +PASS: Information Disclosure - Debug Error Messages [10023] +PASS: Information Disclosure - Sensitive Information in URL [10024] +PASS: Information Disclosure - Sensitive Information in HTTP Referrer Header [10025] +PASS: HTTP Parameter Override [10026] +PASS: Information Disclosure - Suspicious Comments [10027] +PASS: Off-site Redirect [10028] +PASS: Cookie Poisoning [10029] +PASS: User Controllable Charset [10030] +PASS: User Controllable HTML Element Attribute (Potential XSS) [10031] +PASS: Viewstate [10032] +PASS: Directory Browsing [10033] +PASS: Heartbleed OpenSSL Vulnerability (Indicative) [10034] +PASS: Strict-Transport-Security Header [10035] +PASS: HTTP Server Response Header [10036] +PASS: Server Leaks Information via "X-Powered-By" HTTP Response Header Field(s) [10037] +PASS: Content Security Policy (CSP) Header Not Set [10038] +PASS: X-Backend-Server Header Information Leak [10039] +PASS: Secure Pages Include Mixed Content [10040] +PASS: HTTP to HTTPS Insecure Transition in Form Post [10041] +PASS: HTTPS to HTTP Insecure Transition in Form Post [10042] +PASS: User Controllable JavaScript Event (XSS) [10043] +PASS: Big Redirect Detected (Potential Sensitive Information Leak) [10044] +PASS: Retrieved from Cache [10050] +PASS: X-ChromeLogger-Data (XCOLD) Header Information Leak [10052] +PASS: Cookie without SameSite Attribute [10054] +PASS: CSP [10055] +PASS: X-Debug-Token Information Leak [10056] +PASS: Username Hash Found [10057] +PASS: X-AspNet-Version Response Header [10061] +PASS: PII Disclosure [10062] +PASS: Permissions Policy Header Not Set [10063] +PASS: Timestamp Disclosure [10096] +PASS: Hash Disclosure [10097] +PASS: Cross-Domain Misconfiguration [10098] +PASS: Source Code Disclosure [10099] +PASS: Weak Authentication Method [10105] +PASS: Reverse Tabnabbing [10108] +PASS: Modern Web Application [10109] +PASS: Dangerous JS Functions [10110] +PASS: Authentication Request Identified [10111] +PASS: Session Management Response Identified [10112] +PASS: Verification Request Identified [10113] +PASS: Script Served From Malicious Domain (polyfill) [10115] +PASS: Absence of Anti-CSRF Tokens [10202] +PASS: Private IP Disclosure [2] +PASS: Session ID in URL Rewrite [3] +PASS: Script Passive Scan Rules [50001] +PASS: Stats Passive Scan Rule [50003] +PASS: Insecure JSF ViewState [90001] +PASS: Java Serialization Object [90002] +PASS: Sub Resource Integrity Attribute Missing [90003] +PASS: Insufficient Site Isolation Against Spectre Vulnerability [90004] +PASS: Charset Mismatch [90011] +PASS: Application Error Disclosure [90022] +PASS: WSDL File Detection [90030] +PASS: Loosely Scoped Cookie [90033] +WARN-NEW: Storable and Cacheable Content [10049] x 2 + http://host.docker.internal:8080 (404 Not Found) + http://host.docker.internal:8080/sitemap.xml (404 Not Found) +WARN-NEW: ZAP is Out of Date [10116] x 1 + http://host.docker.internal:8080/sitemap.xml (404 Not Found) +FAIL-NEW: 0 FAIL-INPROG: 0 WARN-NEW: 2 WARN-INPROG: 0 INFO: 0 IGNORE: 0 PASS: 65 +Automation plan warnings: + Job spider error accessing URL http://host.docker.internal:8080 status code returned : 404 expected 200 diff --git a/submissions/attachments/lab9/zap-before/zap-report.html b/submissions/attachments/lab9/zap-before/zap-report.html new file mode 100644 index 000000000..93662fc1f --- /dev/null +++ b/submissions/attachments/lab9/zap-before/zap-report.html @@ -0,0 +1,566 @@ + + + + +ZAP Scanning Report + + + +

+ + + ZAP Scanning Report +

+

+ + +

+ + Site: http://host.docker.internal:8080 + +

+ +

+ Generated on Tue, 7 Jul 2026 18:46:35 +

+ +

+ ZAP Version: 2.16.1 +

+ +

+ ZAP by Checkmarx +

+ + +

Summary of Alerts

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Risk LevelNumber of Alerts
+
High
+
+
0
+
+
Medium
+
+
0
+
+
Low
+
+
1
+
+
Informational
+
+
1
+
+
False Positives:
+
+
0
+
+
+ + + + +

Summary of Sequences

+

For each step: result (Pass/Fail) - risk (of highest alert(s) for the step, if any).

+ + + + + + +

Alerts

+ + + + + + + + + + + + + + + + + + + + + + +
NameRisk LevelNumber of Instances
ZAP is Out of DateLow1
Storable and Cacheable ContentInformational2
+
+ + + +

Alert Detail

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Low
ZAP is Out of Date
Description +
The version of ZAP you are using to test your app is out of date and is no longer being updated.
+
+ +
The risk level is set based on how out of date your ZAP version is.
+ +
URLhttp://host.docker.internal:8080/sitemap.xml
MethodGET
Parameter
Attack
Evidence
Other InfoThe latest version of ZAP is 2.17.0
Instances1
Solution +
Download the latest version of ZAP from https://www.zaproxy.org/download/ and install it.
+ +
Reference + https://www.zaproxy.org/download/ + +
CWE Id1104
WASC Id45
Plugin Id10116
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Informational
Storable and Cacheable Content
Description +
The response contents are storable by caching components such as proxy servers, and may be retrieved directly from the cache, rather than from the origin server by the caching servers, in response to similar requests from other users. If the response data is sensitive, personal or user-specific, this may result in sensitive information being leaked. In some cases, this may even result in a user gaining complete control of the session of another user, depending on the configuration of the caching components in use in their environment. This is primarily an issue where "shared" caching servers such as "proxy" caches are configured on the local network. This configuration is typically found in corporate or educational environments, for instance.
+ +
URLhttp://host.docker.internal:8080/robots.txt
MethodGET
Parameter
Attack
Evidence
Other InfoIn the absence of an explicitly specified caching lifetime directive in the response, a liberal lifetime heuristic of 1 year was assumed. This is permitted by rfc7234.
URLhttp://host.docker.internal:8080/sitemap.xml
MethodGET
Parameter
Attack
Evidence
Other InfoIn the absence of an explicitly specified caching lifetime directive in the response, a liberal lifetime heuristic of 1 year was assumed. This is permitted by rfc7234.
Instances2
Solution +
Validate that the response does not contain sensitive, personal or user-specific information. If it does, consider the use of the following HTTP response headers, to limit, or prevent the content being stored and retrieved from the cache by another user:
+
+ +
Cache-Control: no-cache, no-store, must-revalidate, private
+
+ +
Pragma: no-cache
+
+ +
Expires: 0
+
+ +
This configuration directs both HTTP 1.0 and HTTP 1.1 compliant caching servers to not store the response, and to not retrieve the response (without validation) from the cache, in response to a similar request.
+ +
Reference + https://datatracker.ietf.org/doc/html/rfc7234 +
+ + https://datatracker.ietf.org/doc/html/rfc7231 +
+ + https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html + +
CWE Id524
WASC Id13
Plugin Id10049
+
+ + + + + +

Sequence Details

+ With the associated active scan results. + + + +
+ + + + + + + diff --git a/submissions/attachments/lab9/zap-before/zap-report.json b/submissions/attachments/lab9/zap-before/zap-report.json new file mode 100644 index 000000000..34a8c10ff --- /dev/null +++ b/submissions/attachments/lab9/zap-before/zap-report.json @@ -0,0 +1,89 @@ +{ + "@programName": "ZAP", + "@version": "2.16.1", + "@generated": "Tue, 7 Jul 2026 18:46:35", + "created": "2026-07-07T18:46:35.340313135Z", + "site":[ + { + "@name": "http://host.docker.internal:8080", + "@host": "host.docker.internal", + "@port": "8080", + "@ssl": "false", + "alerts": [ + { + "pluginid": "10116", + "alertRef": "10116", + "alert": "ZAP is Out of Date", + "name": "ZAP is Out of Date", + "riskcode": "1", + "confidence": "3", + "riskdesc": "Low (High)", + "desc": "

The version of ZAP you are using to test your app is out of date and is no longer being updated.

The risk level is set based on how out of date your ZAP version is.

", + "instances":[ + { + "id": "3", + "uri": "http://host.docker.internal:8080/sitemap.xml", + "nodeName": null, + "method": "GET", + "param": "", + "attack": "", + "evidence": "", + "otherinfo": "The latest version of ZAP is 2.17.0" + } + ], + "count": "1", + "systemic": false, + "solution": "

Download the latest version of ZAP from https://www.zaproxy.org/download/ and install it.

", + "otherinfo": "

The latest version of ZAP is 2.17.0

", + "reference": "

https://www.zaproxy.org/download/

", + "cweid": "1104", + "wascid": "45", + "sourceid": "8" + }, + { + "pluginid": "10049", + "alertRef": "10049-3", + "alert": "Storable and Cacheable Content", + "name": "Storable and Cacheable Content", + "riskcode": "0", + "confidence": "2", + "riskdesc": "Informational (Medium)", + "desc": "

The response contents are storable by caching components such as proxy servers, and may be retrieved directly from the cache, rather than from the origin server by the caching servers, in response to similar requests from other users. If the response data is sensitive, personal or user-specific, this may result in sensitive information being leaked. In some cases, this may even result in a user gaining complete control of the session of another user, depending on the configuration of the caching components in use in their environment. This is primarily an issue where \"shared\" caching servers such as \"proxy\" caches are configured on the local network. This configuration is typically found in corporate or educational environments, for instance.

", + "instances":[ + { + "id": "1", + "uri": "http://host.docker.internal:8080/robots.txt", + "nodeName": null, + "method": "GET", + "param": "", + "attack": "", + "evidence": "", + "otherinfo": "In the absence of an explicitly specified caching lifetime directive in the response, a liberal lifetime heuristic of 1 year was assumed. This is permitted by rfc7234." + }, + { + "id": "4", + "uri": "http://host.docker.internal:8080/sitemap.xml", + "nodeName": null, + "method": "GET", + "param": "", + "attack": "", + "evidence": "", + "otherinfo": "In the absence of an explicitly specified caching lifetime directive in the response, a liberal lifetime heuristic of 1 year was assumed. This is permitted by rfc7234." + } + ], + "count": "2", + "systemic": false, + "solution": "

Validate that the response does not contain sensitive, personal or user-specific information. If it does, consider the use of the following HTTP response headers, to limit, or prevent the content being stored and retrieved from the cache by another user:

Cache-Control: no-cache, no-store, must-revalidate, private

Pragma: no-cache

Expires: 0

This configuration directs both HTTP 1.0 and HTTP 1.1 compliant caching servers to not store the response, and to not retrieve the response (without validation) from the cache, in response to a similar request.

", + "otherinfo": "

In the absence of an explicitly specified caching lifetime directive in the response, a liberal lifetime heuristic of 1 year was assumed. This is permitted by rfc7234.

", + "reference": "

https://datatracker.ietf.org/doc/html/rfc7234

https://datatracker.ietf.org/doc/html/rfc7231

https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html

", + "cweid": "524", + "wascid": "13", + "sourceid": "6" + } + ] + } + ], + "sequences":[ + ] + +} diff --git a/submissions/attachments/lab9/zap-before/zap.yaml b/submissions/attachments/lab9/zap-before/zap.yaml new file mode 100644 index 000000000..216ceea13 --- /dev/null +++ b/submissions/attachments/lab9/zap-before/zap.yaml @@ -0,0 +1,40 @@ +env: + contexts: + - excludePaths: [] + name: baseline + urls: + - http://host.docker.internal:8080 + parameters: + failOnError: true + progressToStdout: false +jobs: +- parameters: + enableTags: false + maxAlertsPerRule: 10 + type: passiveScan-config +- parameters: + maxDuration: 1 + url: http://host.docker.internal:8080 + type: spider +- parameters: + maxDuration: 0 + type: passiveScan-wait +- parameters: + format: Long + summaryFile: /home/zap/zap_out.json + rules: [] + type: outputSummary +- parameters: + reportDescription: '' + reportDir: /zap/wrk/ + reportFile: zap-report.html + reportTitle: ZAP Scanning Report + template: traditional-html + type: report +- parameters: + reportDescription: '' + reportDir: /zap/wrk/ + reportFile: zap-report.json + reportTitle: ZAP Scanning Report + template: traditional-json + type: report diff --git a/submissions/lab10.md b/submissions/lab10.md new file mode 100644 index 000000000..7514e42f7 --- /dev/null +++ b/submissions/lab10.md @@ -0,0 +1,183 @@ +# Lab 10 submission + +**Host:** Apple Silicon Mac. **Image:** `ghcr.io/markovav-official/devops-intro/quicknotes:v0.1.0`. **HF Space:** https://markovav-devops-intro.hf.space + +--- + +## Task 1 β€” CI push to `ghcr.io` + +### Release workflow + +[`.github/workflows/release.yml`](../.github/workflows/release.yml) β€” triggers on `v*` tags, builds `app/Dockerfile`, pushes `linux/amd64` to ghcr with version + `latest`. + +```yaml +on: + push: + tags: + - 'v*' +permissions: + contents: read + packages: write +# ... +tags: | + ghcr.io/${{ github.repository }}/quicknotes:${{ github.ref_name }} + ghcr.io/${{ github.repository }}/quicknotes:latest +``` + +All third-party actions SHA-pinned (`checkout`, `setup-buildx`, `login`, `build-push`). + +### Registry & pull evidence + +- **Image URL:** `ghcr.io/markovav-official/devops-intro/quicknotes:v0.1.0` +- **Package:** https://github.com/markovav-official/DevOps-Intro/pkgs/container/devops-intro%2Fquicknotes +- **Clean pull:** see [`attachments/lab10/docker-pull.txt`](attachments/lab10/docker-pull.txt) β€” public package, digest `sha256:f540e365…` + +Package visibility set to **Public** (required for HF Spaces pull without auth). + +### CI release run + +- **Green run:** [release #2 β€” `v0.1.0`](https://github.com/markovav-official/DevOps-Intro/actions/runs/28899025918) + +### Design questions (a–c) + +**a) OIDC vs `GITHUB_TOKEN`** + +`GITHUB_TOKEN` is minted per workflow run, scoped to this repo, and sufficient for `docker push` to `ghcr.io` in the same repository. **OIDC** (federated identity to AWS/GCP/Azure) is for pushing or deploying to **external** accounts without long-lived cloud secrets β€” the workflow proves its identity to a third party. OIDC gives cross-account, auditable, short-lived credentials; `GITHUB_TOKEN` cannot leave GitHub's trust boundary. + +**b) `:latest` vs immutable `:v0.1.0`** + +`:v0.1.0` is the **audit trail** β€” rollbacks and incident response reference an exact digest. `:latest` is the **convenience pointer** for `docker pull` without a version and for Spaces/compose defaults that always want "current release". Production deploys should pin immutable tags; `latest` is mutable by design. + +**c) `packages: write` scope only** + +**Principle:** least privilege. `packages: write` lets the job publish container images only. A compromised action cannot rewrite `main`, open PRs, or modify other repos β€” attacks like retagging unrelated packages or force-pushing code require permissions this job does not have (`contents: write`, `id-token` to foreign clouds, etc.). + +--- + +## Task 2 β€” Hugging Face Spaces + +### Space setup + +```bash +git clone git@hf.co:spaces/markovav/DevOps-Intro hf-space-repo +cp cloud/hf-space/Dockerfile cloud/hf-space/README.md hf-space-repo/ +cd hf-space-repo && git add . && git commit -m "Deploy QuickNotes from ghcr.io v0.1.0" && git push +``` + +### Space URL & health check + +- **Space:** https://markovav-devops-intro.hf.space +- **`curl -v` `/health`:** [`attachments/lab10/hf-health.txt`](attachments/lab10/hf-health.txt) β€” HTTP 200, security headers from Lab 9 middleware +- **`/notes`:** `[]` (empty store on fresh Space) + +### Space repo files + +**`cloud/hf-space/Dockerfile`** β€” pull pre-built release (no rebuild on HF): + +```dockerfile +FROM ghcr.io/markovav-official/devops-intro/quicknotes:v0.1.0 +``` + +**`cloud/hf-space/README.md`** frontmatter: + +```yaml +--- +title: QuickNotes Lab 10 +emoji: πŸ“ +sdk: docker +app_port: 8080 +--- +``` + +### Latency (scale-to-zero) + +Measured with [`cloud/scripts/measure-warm.sh`](../cloud/scripts/measure-warm.sh) and [`measure-cold.sh`](../cloud/scripts/measure-cold.sh) after 35+ min idle. + +| Measurement | Value (s) | +|-------------|----------:| +| Warm p50 (5 requests) | 0.901 | +| Cold #1 | 1.24 | +| Cold #2 | 2.08 | +| Cold #3 | 1.87 | + +Warm p50 **0.9 s** β†’ cold avg **~1.7 s** (~2Γ—) after idle; image already on HF so wake is seconds, not tens of seconds. + +Raw logs: [`attachments/lab10/hf-warm.txt`](attachments/lab10/hf-warm.txt) Β· [`attachments/lab10/hf-cold.txt`](attachments/lab10/hf-cold.txt) + +### Design questions (d–f) + +**d) HF sleep vs Cloud Run scale-to-zero** + +Same pattern (no traffic β†’ no running container), different SLO. HF free tier optimizes for **cost and sharing demos**, not low latency: cold start includes scheduler wake, **image pull/layer cache**, and container boot β€” often tens of seconds. Cloud Run targets **production HTTP** with faster scale-from-zero, regional capacity, and tuned networking. HF trades wake time for zero card and zero bill. + +**e) Why `app_port: 8080`?** + +HF defaults to **7860** (Gradio/streamlit convention). QuickNotes listens on **8080** (`ADDR=:8080`). Without `app_port: 8080` the platform probes the wrong port β†’ health checks fail and the Space shows "container exited". + +**f) Pull from ghcr.io vs build in Space** + +| Pull from ghcr | Build in Space | +|----------------|----------------| +| Same artifact as CI release | Reproduces build on HF builders | +| Fast Space deploy (no compile) | Slower, needs `app/` source in Space repo | +| Debug needs ghcr access/logs | Dockerfile self-contained on HF | +| **Chosen:** pull β€” single source of truth from Task 1 tag | + +--- + +## Bonus β€” Cloudflare Tunnel + comparison + +### Quick tunnel + +```bash +docker compose up -d quicknotes +cloudflared tunnel --url http://localhost:8080 +# copy https://.trycloudflare.com from output +``` + +- **URL:** https://tenant-voting-composer-highly.trycloudflare.com +- **Verified from other network:** `curl` from **University VM** (different network than Mac running `cloudflared`) β†’ HTTP **200** `{"notes":44,"status":"ok"}` via Cloudflare (`cf-ray: a179ed132c12bb02-ARN`, edge **ARN**) + +Evidence: [`attachments/lab10/tunnel-curl.txt`](attachments/lab10/tunnel-curl.txt) + +Warm stats (University VM, 5 requests each): [`attachments/lab10/comparison-vm.txt`](attachments/lab10/comparison-vm.txt) + +### Comparison table + +Measured from **University VM** (same client, 5 warm `curl` requests to `/health`). + +| Metric | HF Spaces (hosted) | Cloudflare Tunnel (local-via-edge) | +|--------|-------------------:|-----------------------------------:| +| Warm p50 | 0.651 | 0.392 | +| Warm p95 | 0.722 | 0.565 | +| Cold start | ~1.7 (avg) | N/A (continuously local) | +| Public URL stability | stable | ephemeral on restart | +| Cost | free | free | + +### Design questions (g–i) + +**g) Which is "really cloud"?** + +HF runs **your container in their datacenter** β€” classic PaaS. Tunnel runs the app **on your machine**; only routing/DDoS/TLS termination is cloud. Users see HTTPS either way; the distinction matters for **data residency, uptime SLA, and who patches the host**. For a course demo both are "cloud-delivered"; for compliance only HF counts as app hosting in a third-party DC. + +**h) Latency dominator (HF vs Tunnel)** + +- **HF warm:** container process + HF ingress + geographic distance to their region. +- **HF cold:** **wake + image pull** dominates. +- **Tunnel warm:** **last-mile internet path** (phone β†’ Cloudflare edge β†’ your home uplink β†’ localhost). Often RTT and upload bandwidth, not Go handler time. + +**i) When is Tunnel right for production?** + +**Right:** exposing **on-prem/home lab** services without public IP, temporary **stakeholder demos**, webhooks to a dev laptop, internal tools behind NAT. **Never right:** user-facing production APIs needing **HA, stable URL, predictable egress IP, or 24/7** β€” laptop sleep, ephemeral URL, and residential bandwidth are blockers. Use managed hosting (HF, Cloud Run, k8s) instead. + +--- + +## Artifacts + +| Path | Description | +|------|-------------| +| `.github/workflows/release.yml` | Tag β†’ build β†’ push to ghcr.io | +| `cloud/hf-space/` | HF Space Dockerfile + README frontmatter | +| `cloud/scripts/` | Warm/cold/tunnel latency helpers | +| `cloud/teardown.md` | Delete Space, stop tunnel | +| `submissions/attachments/lab10/` | Pull logs, curl, latency captures | diff --git a/submissions/lab11.md b/submissions/lab11.md new file mode 100644 index 000000000..07f28e606 --- /dev/null +++ b/submissions/lab11.md @@ -0,0 +1,151 @@ +# Lab 11 submission + +**Host:** Apple Silicon Mac (no local Nix). **Build env:** University VM + Determinate Nix 2.34.7. **nixpkgs:** `nixos-24.11` (see `flake.lock`). + +--- + +## Task 1 β€” Reproducible Go build + +### `flake.nix` + +See [`flake.nix`](../flake.nix) Β· lockfile [`flake.lock`](../flake.lock) + +Uses **`buildGoModule`** with `vendorHash = null` (no third-party Go modules). `postPatch` rewrites `go 1.24` β†’ `go 1.23` inside the sandbox because `nixos-24.11` ships Go 1.23. + +### Build log excerpt + +[`attachments/lab11/nix-build-quicknotes.log`](attachments/lab11/nix-build-quicknotes.log) + +```text +quicknotes> ok quicknotes 0.009s +``` + +### Reproducibility proof (store hashes) + +Two independent checkouts on **University VM** (`/root/lab11-work/DevOps-Intro` and `/root/lab11-fresh`): + +| Environment | `nix-store --query --hash` | +|-------------|----------------------------| +| A | `sha256:1xh9z7n1ax8hbissdcr7ivj2zcx56fhb1aj4i1l7hs5axq29xrym` | +| B | `sha256:1xh9z7n1ax8hbissdcr7ivj2zcx56fhb1aj4i1l7hs5axq29xrym` | + +### Runtime proof + +```bash +ADDR=:18080 DATA_PATH=/tmp/qn-notes.json SEED_PATH=$PWD/app/seed.json ./result/bin/quicknotes & +curl -fsS http://127.0.0.1:18080/health +# {"notes":4,"status":"ok"} +``` + +### Design questions (a–d) + +**a) Why isn't `go build` bit-identical across machines?** + +Build IDs embed timestamps and VCS metadata; module cache paths differ; `-trimpath` behavior varies; floating `go` toolchain versions change compiler output. Two laptops with the same Git SHA can still produce different ELF hashes. + +**b) What is `vendorHash`?** + +SHA-256 over the output of `go mod vendor` (the `vendor/` tree). If wrong, Nix fails with `hash mismatch` and prints the correct `got:` value. With `vendorHash = null`, Nix skips the check β€” fine for hacking, useless for reproducibility. + +**c) Why is `flake.lock` critical?** + +It pins **every flake input** (nixpkgs revision, flake-utils, etc.) to exact commits. Delete it before the second build and Nix may fetch a newer nixpkgs β†’ different Go compiler β†’ different binary hash. + +**d) `buildGoModule` vs `buildGoApplication`** + +`buildGoModule` expects `go.mod`/`go.sum` and vendors deps (`vendorHash`). `buildGoApplication` is for projects already using a checked-in `vendor/` tree or simpler layouts. **Pick `buildGoModule`** for QuickNotes β€” standard for Go modules, explicit vendor pinning. + +--- + +## Task 2 β€” Deterministic OCI image + +### Docker output in flake + +```nix +packages.docker = pkgs.dockerTools.buildImage { ... }; +``` + +`nix build .#docker` β†’ OCI tarball at `result` (load with `docker load < result`). + +### Image digest proof + +[`attachments/lab11/nix-docker-digests.txt`](attachments/lab11/nix-docker-digests.txt) + +| Environment | `sha256sum` (OCI tarball) | +|-------------|---------------------------| +| A | `28db2a32677bb3eb3c133ec33072ff4ad4350ea67d4445b30c422a349bd24874` | +| B | `28db2a32677bb3eb3c133ec33072ff4ad4350ea67d4445b30c422a349bd24874` | + +### vs Lab 6 Dockerfile (non-reproducible) + +```bash +docker build --no-cache -t qn-lab6:run1 ./app +docker build --no-cache -t qn-lab6:run2 ./app +docker images --no-trunc qn-lab6 +``` + +| Tag | Image ID | +|-----|----------| +| run1 | `sha256:01073da0688e9b8a22df65b857da54bf64d4b7fda60234cc7d821485e8da3ce8` | +| run2 | `sha256:fbcdbd2e78cedf9b7e904f11b561c388b28abd5f75e396baa851a102aca0df12` | + +Same Dockerfile + same source, **different digests** β€” non-reproducible layer metadata. + +### Image size + +| Build | Size | +|-------|-----:| +| Nix `dockerTools.buildImage` | 2.9 MB | +| Lab 6 distroless Dockerfile | ~16 MB | + +### Design questions (e–g) + +**e) What does `docker build` do that Nix doesn't?** + +Docker layers embed creation timestamps, may include non-deterministic file ordering, and `FROM` pulls mutable tags. `dockerTools.buildImage` builds from a fixed store path closure β€” same inputs β†’ same tarball bytes. + +**f) What can an auditor prove with reproducible images?** + +Anyone can rebuild from source + flake.lock and verify the digest matches the published image β€” supply-chain integrity without trusting only a signature on opaque bits. + +**g) Trade-off vs `docker build`** + +Nix buys reproducibility and pinned toolchains at the cost of learning curve, larger store, and slower cold builds. Docker wins on familiarity, ecosystem, and incremental layer cache for most teams. + +--- + +## Bonus β€” CI-verified reproducibility + +### Workflow + +[`.github/workflows/nix-repro.yml`](../.github/workflows/nix-repro.yml) β€” two parallel `nix build .#docker` jobs; `nix-repro-ok` compares `sha256sum` outputs. + +### CI runs + +- **Green:** [nix-repro #1 β€” digests match](https://github.com/markovav-official/DevOps-Intro/actions/runs/28961060062) +- **Red (intentional `SOURCE_DATE_EPOCH: "0"` + `--impure` in job A only):** [nix-repro #3 β€” digest mismatch](https://github.com/markovav-official/DevOps-Intro/actions/runs/28964290755) +- **Green (restored parity):** [nix-repro #4 β€” digests match](https://github.com/markovav-official/DevOps-Intro/actions/runs/28964914367) + +### Design questions (h–j) + +**h) Laptop vs CI reproducibility** + +CI proves any reviewer can trigger the same check on ephemeral runners β€” not just the author's machine. Auditors trust automation + logs, not screenshots. + +**i) Why two parallel jobs?** + +A single job running twice shares runner state, store paths, and timing β€” could hide environment leaks. Independent runners start from the same checkout with empty stores. + +**j) `SOURCE_DATE_EPOCH`** + +Timestamps leak into OCI metadata (`created` in `dockerTools.buildImage`) and layer tar mtime. Nix builds are **pure** by default: host env vars (including `SOURCE_DATE_EPOCH` in GHA) do not enter the sandbox, so both jobs still produced the same store path. The red demo wires `created` via `builtins.getEnv` in `flake.nix` and runs job A with `nix build --impure` + `SOURCE_DATE_EPOCH=0`, shifting image metadata by one second vs job B's default `1970-01-01T00:00:01Z`. + +--- + +## Artifacts + +| Path | Description | +|------|-------------| +| `flake.nix` / `flake.lock` | Reproducible Go + OCI outputs | +| `.github/workflows/nix-repro.yml` | CI digest gate | +| `submissions/attachments/lab11/` | Build logs, hash captures | diff --git a/submissions/lab12.md b/submissions/lab12.md new file mode 100644 index 000000000..aaa33a1a6 --- /dev/null +++ b/submissions/lab12.md @@ -0,0 +1,146 @@ +# Lab 12 submission + +**Host:** Apple Silicon Mac (no WASM toolchain). **Build/bench env:** University VM (Linux x86_64, 1.8 GiB RAM + swap). **Toolchain:** Spin 3.4.0, TinyGo 0.41.1 (Nix), wasmtime 29.0.0, hyperfine 1.18.0. + +--- + +## Task 1 β€” Spin SDK `/time` endpoint + +### Source + +- [`wasm/main.go`](../wasm/main.go) +- [`wasm/spin.toml`](../wasm/spin.toml) +- [`wasm/go.mod`](../wasm/go.mod) Β· SDK `github.com/spinframework/spin-go-sdk/v2 v2.2.1` + +Scaffolded layout matches `spin new -t http-go` (Spin 3.4 templates installed on VM). Route `/time`, `allowed_outbound_hosts = []`, TinyGo `wasip1` + `-buildmode=c-shared`. + +### Build + +[`attachments/lab12/spin-build.log`](attachments/lab12/spin-build.log) + +```text +Finished building all Spin components +main.wasm 362115 bytes +``` + +Built with `GOMAXPROCS=1` on the VM (TinyGo + Go 1.26 via Nix; system Go 1.22 alone fails TinyGo 0.41 `net` build). + +### Runtime proof + +[`attachments/lab12/spin-time.json`](attachments/lab12/spin-time.json) + +```bash +spin up --listen 127.0.0.1:3000 +curl -s http://127.0.0.1:3000/time | python3 -m json.tool +``` + +```json +{ + "unix": 1783548307, + "iso": "2026-07-08T22:05:07Z", + "hour_minute": "22:05", + "moscow": "2026-07-08 22:05:07", + "tz": "UTC+3" +} +``` + +### Design questions (a–d) + +**a) Browser WASM vs server WASM** + +`go build -target=js/wasm` targets the browser ABI (DOM callbacks via `syscall/js`). `tinygo build -target=wasip1` targets WASI β€” no DOM, no full stdlib, but a portable server module with explicit capabilities. You lose browser APIs and much of upstream Go stdlib; you gain a small, sandboxed artifact runnable in Spin/wasmtime. + +**b) Why `-buildmode=c-shared`?** + +Spin's host expects the module to export the wasi-http handler symbols as a shared library-style component, not a bare `_start` CLI entrypoint. Without `-buildmode=c-shared`, the handler isn't exported β†’ `spin up` serves HTTP 500. + +**c) `allowed_outbound_hosts = []` vs Docker `--network none`** + +Spin's capability model denies outbound network at manifest level β€” the runtime won't grant socket capabilities the module didn't request. Docker `--network none` removes network namespaces at the container level, but the process still carries a larger Linux attack surface (full libc, more syscalls). WASM defaults to least-privilege per component. + +**d) TinyGo stdlib gaps hit** + +- `time.LoadLocation("Europe/Moscow")` β€” no embedded tzdata β†’ used `UTC().Add(3 * time.Hour)`. +- Avoided `json.NewEncoder` + `map[string]any` (reflection-heavy) β†’ built JSON with `fmt.Sprintf` and `%q`. + +--- + +## Task 2 β€” Perf vs Lab 6 Docker + +**Test rig:** University VM, Ubuntu 24.04, 1.8 GiB RAM, 7.8 GiB swap, x86_64. Lab 6 image `quicknotes:lab6` (distroless), Spin on `:3000`, Docker on `:18080`. + +### Table + +| Dimension | Lab 6 Docker | Lab 12 WASM/Spin | +|-----------|-------------:|-----------------:| +| Artifact size | 3.8 MB | 354 KB (`main.wasm`) | +| Cold start p50 | 1.4 s | 12.9 s | +| Warm latency p50 | 7.1 ms | 9.4 ms | +| Warm latency p95 | 7.8 ms | 10.5 ms | + +Sources: [`attachments/lab12/sizes.txt`](attachments/lab12/sizes.txt), [`cold-docker.txt`](attachments/lab12/cold-docker.txt), [`cold-spin.txt`](attachments/lab12/cold-spin.txt), [`warm-docker.json`](attachments/lab12/warm-docker.json), [`warm-spin.json`](attachments/lab12/warm-spin.json). + +> Spin cold start on this 1.8 GiB VM is dominated by process restart + wasmtime init under memory pressure (consistent ~13 s across 5 samples). Warm requests stay in single-digit milliseconds once `spin up` is running. + +### Design questions (e–g) + +**e) What dominates cold start?** + +Docker: image layer setup + namespace/cgroup init + process start. Spin: `spin up` process + wasmtime engine init + WASM module load/instantiate (on this VM, memory pressure amplifies restart cost). + +**f) When is WASM better, when Docker?** + +WASM wins for tiny, short-lived, high-churn functions (small artifact, fast per-request instantiation in warm server). Docker wins for full apps needing rich stdlib, long-lived state, complex networking, and mature ops tooling. + +**g) Multi-tenant safety** + +WASM capability sandboxes make it harder for a tenant module to reach hosts/files/sockets it wasn't granted β€” e.g. exfiltrating via outbound TCP to arbitrary IPs (`allowed_outbound_hosts = []` blocks this at the manifest). + +--- + +## Bonus β€” Two WASM execution models + +### wasm-cli (standalone WASI) + +[`wasm-cli/main.go`](../wasm-cli/main.go) + +```bash +tinygo build -o main.wasm -target=wasi -no-debug ./main.go +wasmtime run --env REQUEST_METHOD=GET --env PATH_INFO=/time main.wasm +``` + +[`attachments/lab12/wasm-cli-time.json`](attachments/lab12/wasm-cli-time.json) β€” same Moscow JSON as Spin. + +### Comparison + +| | Spin wasi-http | wasmtime CLI | +|--|--:|--:| +| `main.wasm` size | 354 KB | 192 KB | +| Cold (per-invocation / restart) p50 | 12.9 s (`spin up` restart) | 12 ms (`wasmtime run`) | + +[`attachments/lab12/cold-wasmtime.txt`](attachments/lab12/cold-wasmtime.txt) + +### Design questions (h–j) + +**h) Why can't the Spin component run under bare `wasmtime run`?** + +Task 1 builds a **wasi-http component** exporting HTTP handler symbols for a persistent host. Bare `wasmtime run` expects a CLI module with `_start` reading env/stdin β€” different ABI. + +**i) What does Spin add on top of wasmtime?** + +Manifest routing (`spin.toml`), wasi-http server loop, per-component outbound policy, instance lifecycle β€” wasmtime is the engine; Spin is the application host. + +**j) When does each model fit?** + +Per-invocation `wasmtime run` (CGI-style): rare admin tasks, CLI tools, batch jobs. Spin persistent server: HTTP microservices, edge functions with steady request traffic. + +--- + +## Artifacts + +| Path | Description | +|------|-------------| +| `wasm/` | Spin component (`main.go`, `spin.toml`, `go.mod`, `go.sum`) | +| `wasm-cli/` | Standalone WASI module for `wasmtime run` | +| `cloud/scripts/lab12-vm-*.sh` | VM setup + benchmark scripts | +| `submissions/attachments/lab12/` | Build logs, curl output, hyperfine JSON, cold-start samples | diff --git a/submissions/lab6.md b/submissions/lab6.md new file mode 100644 index 000000000..420829bac --- /dev/null +++ b/submissions/lab6.md @@ -0,0 +1,252 @@ +# Lab 6 β€” Containers: Dockerize QuickNotes + +## Task 1 β€” Multi-Stage Dockerfile + +### Dockerfile + +```dockerfile +# syntax=docker/dockerfile:1 + +FROM golang:1.24-alpine AS builder +WORKDIR /src +COPY go.mod ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build \ + -trimpath \ + -ldflags='-s -w' \ + -o /quicknotes . + +FROM busybox:1.36-musl AS busybox + +FROM gcr.io/distroless/static-debian12:nonroot +COPY --from=builder /quicknotes /quicknotes +COPY --from=builder /src/seed.json /seed.json +COPY --from=busybox /bin/busybox /busybox +EXPOSE 8080 +ENTRYPOINT ["/quicknotes"] +``` + +### Image size + +``` +$ docker images quicknotes:lab6 +REPOSITORY TAG SIZE +quicknotes lab6 16MB +``` + +Builder base for comparison: + +``` +$ docker images golang:1.24-alpine +golang:1.24-alpine 388MB +``` + +Full output: [`attachments/lab6/docker-images.txt`](attachments/lab6/docker-images.txt) + +### `docker inspect` excerpt + +```json +{ + "User": "65532", + "ExposedPorts": { "8080/tcp": {} }, + "Entrypoint": ["/quicknotes"], + "WorkingDir": "/home/nonroot" +} +``` + +Full output: [`attachments/lab6/docker-inspect-config.json`](attachments/lab6/docker-inspect-config.json) + +### Health endpoint (standalone `docker run`) + +``` +$ curl -s http://localhost:8080/health +{"notes":4,"status":"ok"} +``` + +Evidence: [`attachments/lab6/curl-health.txt`](attachments/lab6/curl-health.txt) + +### Design questions (a–d) + +**a) Why does layer-order matter?** + +Docker caches each layer. If `COPY . .` comes before `go mod download`, any source change invalidates the layer that also contains dependency download, so `go mod download` and `go build` run again. + +Measured rebuild after touching `handlers.go` only: + +| Strategy | `real` time | +|----------|------------| +| Good: `COPY go.mod` β†’ `go mod download` β†’ `COPY . .` β†’ build | **1.70 s** | +| Bad: `COPY . .` β†’ `go mod download` β†’ build | **3.72 s** | + +Evidence: [`attachments/lab6/cache-good-rebuild.txt`](attachments/lab6/cache-good-rebuild.txt), [`attachments/lab6/cache-bad-rebuild.txt`](attachments/lab6/cache-bad-rebuild.txt) + +**b) Why `CGO_ENABLED=0`?** + +With CGO enabled, Go may link against libc and produce a dynamically linked binary. Distroless `static` has no dynamic linker (`/lib/ld-linux.so`), so the binary fails at startup with `no such file or directory` or similar. `CGO_ENABLED=0` forces a fully static binary that runs on distroless-static. + +**c) What is `gcr.io/distroless/static-debian12:nonroot`?** + +It is a minimal runtime image: CA certs, timezone data, `/etc/passwd` entry for UID 65532 (`nonroot`), and nothing else β€” no shell, package manager, or libc beyond what a static binary needs. Fewer packages mean a smaller attack surface and fewer OS-level CVEs (Trivy reported **0 HIGH/CRITICAL** on the Debian layer). + +**d) `-ldflags='-s -w'` and `-trimpath`** + +- `-s -w`: strip the symbol table and DWARF debug info β†’ smaller binary, faster pulls. +- `-trimpath`: remove local filesystem paths from the binary β†’ reproducible builds and no host paths leaked into artifacts. + +Cost: harder to debug crashes inside the container (no symbols); stack traces are less informative without separate debug symbols. + +--- + +## Task 2 β€” Compose + Healthcheck + Persistent Volume + +### `compose.yaml` + +```yaml +services: + volume-init: + image: busybox:1.36-musl + volumes: + - quicknotes-data:/data + command: ["sh", "-c", "chown 65532:65532 /data"] + restart: "no" + + quicknotes: + build: + context: ./app + dockerfile: Dockerfile + image: quicknotes:lab6 + depends_on: + volume-init: + condition: service_completed_successfully + ports: + - "8080:8080" + environment: + ADDR: ":8080" + DATA_PATH: "/data/notes.json" + SEED_PATH: "/seed.json" + volumes: + - quicknotes-data:/data + restart: unless-stopped + healthcheck: + test: ["CMD", "/busybox", "wget", "-qO-", "http://127.0.0.1:8080/health"] + interval: 5s + timeout: 3s + retries: 3 + start_period: 10s + read_only: true + cap_drop: + - ALL + security_opt: + - no-new-privileges:true + tmpfs: + - /tmp + +volumes: + quicknotes-data: +``` + +**Note on `volume-init`:** A fresh Docker named volume is owned by `root`. The distroless image runs as UID `65532` and cannot create `/data/notes.json` without fixing ownership first. The one-shot `volume-init` service runs `chown 65532:65532 /data` before `quicknotes` starts. + +### Compose status + +``` +$ docker compose ps +NAME IMAGE STATUS +devops-intro-quicknotes-1 quicknotes:lab6 Up (healthy) +``` + +Evidence: [`attachments/lab6/compose-ps.txt`](attachments/lab6/compose-ps.txt), [`attachments/lab6/compose-up.txt`](attachments/lab6/compose-up.txt) + +### Persistence test (3 steps) + +1. POST note `durable` β†’ present in `GET /notes` +2. `docker compose down` (no `-v`) β†’ `docker compose up -d` β†’ note **still present** +3. `docker compose down -v` β†’ `docker compose up -d` β†’ note **gone** (seed data only) + +Evidence: [`attachments/lab6/persistence-test.txt`](attachments/lab6/persistence-test.txt) + +### Design questions (e–g) + +**e) Distroless has no shell β€” how do you healthcheck it?** + +Strategy: copy a static `busybox` binary from a separate build stage into the runtime image and use exec-form healthcheck: `["CMD", "/busybox", "wget", "-qO-", "http://127.0.0.1:8080/health"]`. This performs a real HTTP probe without a shell. Alternatives (sidecar, process-alive only) are weaker or heavier; `wget` via minimal busybox is cheap and side-effect free. + +**f) Why does the named volume survive `docker compose down`?** + +`docker compose down` stops and removes containers and networks but **not** named volumes declared in the top-level `volumes:` block. Data in `quicknotes-data` persists on the Docker host. **`docker compose down -v`** (or `docker volume rm`) destroys the volume and all notes stored there. + +**g) `depends_on` without `condition: service_healthy`** + +Plain `depends_on` only waits until the dependency **container has started**, not until it is ready to serve traffic. A dependent service can connect before migrations, volume permissions, or HTTP listeners are ready β†’ flaky startups. Here we use `condition: service_completed_successfully` for `volume-init` so `chown` finishes before `quicknotes` writes to `/data`. + +--- + +## Bonus β€” Six Security Defaults + +### Hardened `quicknotes` service block + +```yaml + quicknotes: + # ... build, ports, env, volumes ... + healthcheck: + test: ["CMD", "/busybox", "wget", "-qO-", "http://127.0.0.1:8080/health"] + interval: 5s + timeout: 3s + retries: 3 + start_period: 10s + read_only: true + cap_drop: + - ALL + security_opt: + - no-new-privileges:true + tmpfs: + - /tmp +``` + +Defaults 1–2 (nonroot user, distroless base) are enforced in the Dockerfile (`static-debian12:nonroot`, `User: 65532`). + +### Verification + +| Default | Command / check | Result | +|---------|-----------------|--------| +| USER nonroot | `docker inspect quicknotes:lab6 --format '{{ .Config.User }}'` | `65532` | +| No shell | `docker compose exec quicknotes sh` | `executable file not found` | +| CapDrop ALL | `docker inspect … --format '{{ .HostConfig.CapDrop }}'` | `[ALL]` | +| Read-only root | `docker compose exec quicknotes /busybox touch /etc/test` | `Read-only file system` | +| no-new-privileges | `docker inspect … --format '{{ .HostConfig.SecurityOpt }}'` | `[no-new-privileges:true]` | + +Full output: [`attachments/lab6/bonus-security.txt`](attachments/lab6/bonus-security.txt) + +### Trivy scan + +```bash +docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + aquasec/trivy:0.59.1 image --severity HIGH,CRITICAL --no-progress \ + quicknotes:lab6 +``` + +Summary: + +| Target | HIGH | CRITICAL | +|--------|-----:|---------:| +| `quicknotes:lab6` (debian 12.14 OS layer) | 0 | 0 | +| `quicknotes` (embedded Go binary) | 13 | 0 | + +The OS layer is clean thanks to distroless. The 13 HIGH findings are **stdlib CVEs in the compiled Go binary** (toolchain 1.24.x); fixing them requires rebuilding with a patched Go release, not switching the base image. + +Full output: [`attachments/lab6/trivy.txt`](attachments/lab6/trivy.txt) + +### Security per line of YAML + +**`cap_drop: [ALL]`** gives the most security per line: it removes the entire Linux capability set, so even if the Go process is compromised it cannot perform privileged operations (e.g. `CAP_NET_RAW`, `CAP_SYS_ADMIN`) without a separate kernel bug. Read-only root and `no-new-privileges` are close runners-up; distroless/nonroot are foundational but mostly set once in the Dockerfile rather than compose. + +--- + +## Artifacts + +| File | Description | +|------|-------------| +| `app/Dockerfile` | Multi-stage build | +| `compose.yaml` | Compose stack with volume + hardening | +| `attachments/lab6/*.txt` | Command outputs and test evidence | diff --git a/submissions/lab8.md b/submissions/lab8.md new file mode 100644 index 000000000..d2c724ba0 --- /dev/null +++ b/submissions/lab8.md @@ -0,0 +1,239 @@ +# Lab 8 submission + +**Host:** Apple Silicon Mac. **Stack:** Lab 6 QuickNotes + Prometheus v3.2.1 + Grafana 13.0.2 (Compose). + +--- + +## Task 1 β€” Prometheus + Grafana + Golden Signals Dashboard + +### Layout + +```text +monitoring/ +β”œβ”€β”€ prometheus/ +β”‚ β”œβ”€β”€ prometheus.yml +β”‚ └── alert.rules.yml +└── grafana/ + β”œβ”€β”€ dashboards/ + β”‚ └── golden-signals.json + └── provisioning/ + β”œβ”€β”€ datasources/datasource.yml + └── dashboards/dashboard.yml +``` + +### `monitoring/prometheus/prometheus.yml` + +```yaml +global: + scrape_interval: 15s + evaluation_interval: 15s + +rule_files: + - /etc/prometheus/alert.rules.yml + +scrape_configs: + - job_name: quicknotes + static_configs: + - targets: + - quicknotes:8080 + metrics_path: /metrics +``` + +### `monitoring/grafana/provisioning/datasources/datasource.yml` + +```yaml +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + uid: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + editable: false +``` + +### `monitoring/grafana/provisioning/dashboards/dashboard.yml` + +```yaml +apiVersion: 1 + +providers: + - name: golden-signals + orgId: 1 + folder: QuickNotes + type: file + disableDeletion: false + updateIntervalSeconds: 30 + allowUiUpdates: true + options: + path: /var/lib/grafana/dashboards +``` + +### Compose extension (`compose.yaml`) + +Added `prometheus` (port **9090**) and `grafana` (port **3000**): + +- Prometheus mounts `prometheus.yml` + `alert.rules.yml` read-only +- `depends_on: quicknotes: condition: service_healthy` +- Grafana mounts provisioning + dashboards; admin password via `GF_SECURITY_ADMIN_PASSWORD=lab8-grafana-dev` (not default `admin/admin`) + +Full file: [`compose.yaml`](../compose.yaml) + +### Golden signals panels + +| Panel | PromQL | +|-------|--------| +| **Latency** (proxy β€” no histogram) | `rate(quicknotes_http_requests_total[5m])` | +| **Traffic** | `sum(rate(quicknotes_http_requests_total[5m]))` | +| **Errors** | `100 * sum(rate(quicknotes_http_responses_by_code_total{code=~"4..\|5.."}[5m])) / clamp_min(sum(rate(quicknotes_http_requests_total[5m])), 0.001)` | +| **Saturation** | `quicknotes_notes_total` | + +Dashboard JSON: [`monitoring/grafana/dashboards/golden-signals.json`](../monitoring/grafana/dashboards/golden-signals.json) + +### Verify + +```bash +docker compose up --build -d +./scripts/lab8-generate-traffic.sh +./scripts/lab8-capture-evidence.sh +``` + +**Targets health:** + +``` +$ curl -s http://localhost:9090/api/v1/targets | jq '.data.activeTargets[].health' +["up"] +``` + +Evidence: [`targets-health.txt`](attachments/lab8/targets-health.txt), [`prometheus-targets.json`](attachments/lab8/prometheus-targets.json), [`compose-ps.txt`](attachments/lab8/compose-ps.txt), [`verify.txt`](attachments/lab8/verify.txt) + +Grafana dashboard auto-loaded: **QuickNotes Golden Signals** (4 panels) in folder **QuickNotes** β€” verified via API: [`grafana-dashboard-meta.txt`](attachments/lab8/grafana-dashboard-meta.txt), [`grafana-dashboard-search.json`](attachments/lab8/grafana-dashboard-search.json). + +Login: http://localhost:3000 β€” `admin` / `lab8-grafana-dev` + +### Design questions (a–d) + +**a) Pull vs push** + +Prometheus **pulls** metrics by HTTP-scraping `/metrics` on a schedule. QuickNotes must be reachable **from Prometheus** on the Compose network (`quicknotes:8080`); QuickNotes does not need to know Prometheus exists. If Prometheus cannot scrape, the target goes **down** (`up=0`) and metrics go stale β€” you lose visibility but the app may still serve users. + +**b) `scrape_interval: 15s` trade-offs** + +At **5s**: finer resolution but 3Γ— more scrape load, larger TSDB, noisier `rate()` on low-traffic counters. At **5m**: very coarse graphs, slow alert detection, `rate()` windows need to be wide β€” you can miss short incidents entirely. + +**c) `rate()` vs `irate()` vs `delta()` for Traffic** + +**`rate()`** β€” per-second average over the range window; smooth, right for dashboards and alerts on counters. **`irate()`** β€” instant rate from last two points; spiky, good for debugging spikes. **`delta()`** β€” raw increase over window, not normalized per second. Traffic panel uses **`rate()`** because we want a stable requests-per-second view. + +**d) Why provision Grafana from files** + +Dashboards and datasources become **version-controlled** and reproducible: `docker compose up` on any machine yields the same monitoring stack without manual UI clicks. Reviewers and teammates get identical panels; changes go through PR like application code. + +--- + +## Task 2 β€” Alert + Runbook + +### Alert rule (`monitoring/prometheus/alert.rules.yml`) + +```yaml +groups: + - name: quicknotes + rules: + - alert: HighHTTPErrorRate + expr: | + ( + sum(rate(quicknotes_http_responses_by_code_total{code=~"4..|5.."}[5m])) + / + clamp_min(sum(rate(quicknotes_http_requests_total[5m])), 0.001) + ) > 0.05 + for: 5m + labels: + severity: page + annotations: + summary: QuickNotes HTTP error ratio exceeds 5% + runbook_url: docs/runbook/high-error-rate.md + description: More than 5% of HTTP responses are 4xx/5xx for 5 minutes. +``` + +### Runbook + +Full document: [`docs/runbook/high-error-rate.md`](../docs/runbook/high-error-rate.md) + +Sections: what the alert means, triage steps (β‰₯3), mitigations (β‰₯2), post-incident (links Lecture 1 postmortem). + +### Trigger alert deliberately + +```bash +./scripts/lab8-trigger-alert.sh http://localhost:8080 360 +# ~33% errors (1 bad POST + 2 good per loop) sustained β‰₯6 min +# Watch: http://localhost:9090/alerts β†’ Pending β†’ Firing +./scripts/lab8-capture-evidence.sh # saves prometheus-alerts.json +``` + +Evidence: [`alert-trigger.log`](attachments/lab8/alert-trigger.log), [`prometheus-alerts-firing.json`](attachments/lab8/prometheus-alerts-firing.json), [`alert-firing.txt`](attachments/lab8/alert-firing.txt) + +``` +$ curl -s http://localhost:9090/api/v1/alerts | jq '.data.alerts[] | {name: .labels.alertname, state, value}' +{ + "name": "HighHTTPErrorRate", + "state": "firing", + "value": "0.317" +} +``` + +Error ratio during firing: **~31.7%** (well above 5% threshold). + +### Design questions (e–g) + +**e) Why sustained 5 minutes?** + +A single malformed request or flaky client should not page anyone. **`for: 5m`** requires the error ratio to stay above threshold across multiple evaluation cycles β€” real user-impacting degradation, not noise. + +**f) Symptom vs cause alert** + +**Symptom:** high HTTP error ratio (what users feel). **Cause example:** `container_cpu_usage > 90%` β€” CPU can be high while errors are zero, or errors can happen at normal CPU (bad deploy, corrupt JSON file). Cause alerts page on internal state that may not correlate with user pain β†’ alert fatigue. + +**g) Alert fatigue threshold** + +If **>30% of pages** fire when users were **not** affected (false positive rate from on-call survey or incident review), the alert is too noisy β€” widen `for:`, raise threshold, or fix the client causing 4xx bursts. + +--- + +## Bonus β€” Synthetic Monitoring + +**Not attempted** β€” requires a public URL (ngrok/cloudflared) and Checkly account. Can be added after Lab 10 deploy or with a free tunnel + Checkly API check from 2 regions. + +--- + +## Helper scripts + +| Script | Purpose | +|--------|---------| +| [`scripts/lab8-generate-traffic.sh`](../scripts/lab8-generate-traffic.sh) | ~200 mixed requests | +| [`scripts/lab8-trigger-alert.sh`](../scripts/lab8-trigger-alert.sh) | Sustained 4xx injection | +| [`scripts/lab8-capture-evidence.sh`](../scripts/lab8-capture-evidence.sh) | Dump targets/alerts JSON | + +--- + +## Quick start + +```bash +# Start Docker Desktop first, then: +cd /Users/markovav/dev/DevOps-Intro +git checkout feature/lab8 +docker compose up --build -d +./scripts/lab8-generate-traffic.sh +./scripts/lab8-capture-evidence.sh +open http://localhost:3000 # Grafana +open http://localhost:9090 # Prometheus +``` + +## Cleanup + +```bash +docker compose down # keep volume: omit -v +docker compose down -v # remove quicknotes data volume +# Optional: docker rmi prom/prometheus:v3.2.1 grafana/grafana:13.0.2 +``` diff --git a/submissions/lab9.md b/submissions/lab9.md new file mode 100644 index 000000000..68e491c4b --- /dev/null +++ b/submissions/lab9.md @@ -0,0 +1,219 @@ +# Lab 9 submission + +**Host:** Apple Silicon Mac. **Scanner versions:** Trivy `0.59.1`, OWASP ZAP `2.16.1`, govulncheck `v1.1.4`. + +--- + +## Task 1 β€” Trivy Scans + SBOM + Triage + +### Scans run + +```bash +docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + aquasec/trivy:0.59.1 image --severity HIGH,CRITICAL quicknotes:lab6 + +docker run --rm -v "$PWD:/repo" aquasec/trivy:0.59.1 fs \ + --severity HIGH,CRITICAL --skip-dirs .vagrant --skip-dirs .git /repo + +docker run --rm -v "$PWD:/repo" aquasec/trivy:0.59.1 config \ + --severity HIGH,CRITICAL /repo + +docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + -v "$PWD/submissions/attachments/lab9/trivy:/out" \ + aquasec/trivy:0.59.1 image --format cyclonedx --output /out/sbom.cdx.json quicknotes:lab6 +``` + +### Scan summaries + +| Scan | HIGH | CRITICAL | Artifact | +|------|-----:|---------:|----------| +| Image (OS layer debian) | 0 | 0 | [`trivy/image-scan.txt`](attachments/lab9/trivy/image-scan.txt) | +| Image (Go binary stdlib) | 10 | 0 | same | +| Filesystem (excl. `.vagrant`) | 0 | 0 | [`trivy/fs-scan.txt`](attachments/lab9/trivy/fs-scan.txt) | +| Config (before `USER` fix) | 1 | 0 | [`trivy/config-scan.txt`](attachments/lab9/trivy/config-scan.txt) | +| Config (after `USER` fix) | 0 | 0 | [`trivy/config-scan-after.txt`](attachments/lab9/trivy/config-scan-after.txt) | + +### CycloneDX SBOM (first 30 lines) + +See [`trivy/sbom-head.txt`](attachments/lab9/trivy/sbom-head.txt) Β· full file [`trivy/sbom.cdx.json`](attachments/lab9/trivy/sbom.cdx.json) + +### Triage table (every HIGH/CRITICAL) + +| ID / Finding | Source | Disposition | Reason | +|--------------|--------|-------------|--------| +| CVE-2026-25679 … CVE-2026-42499 (10Γ—) | Image / Go stdlib in binary (`v1.24.13`) | **WATCH** | Embedded toolchain CVEs; distroless OS layer is clean. Re-check when bumping `golang:1.24-alpine` builder to a patched release (by **2026-12-31**). | +| AVD-DS-0002 missing `USER` in Dockerfile | Config scan | **FIX** | Added `USER nonroot:nonroot` to final stage in `app/Dockerfile` β€” config scan clean after fix. | +| AsymmetricPrivateKey in `.vagrant/.../private_key` | FS scan (without skip) | **FALSE POSITIVE** | Local Vagrant SSH key under `.gitignore`; not shipped in image. FS scan uses `--skip-dirs .vagrant`. | + +### Design questions (a–d) + +**a) CVE severity is one input, not the answer** + +Also consider: **reachability** (is vulnerable code path used?), **exploit availability** (PoC in the wild?), **deployment context** (internal API vs public internet), **compensating controls** (distroless, read-only rootfs, no shell). A HIGH CVE in an unused stdlib package is lower risk than a MEDIUM in code you call on every request. + +**b) Why distroless often shows zero OS CVEs** + +Minimal base = few packages = tiny attack surface and few NVD entries. No shell, package manager, or libc beyond what a static binary needs β€” fewer components to patch and fewer paths for container escape. + +**c) When is `.trivyignore` right vs theater?** + +Right: documented **ACCEPT** with owner, expiry date, and link to risk decision (e.g. dev-only path). Theater: blanket ignores to make CI green without triage, or permanent suppressions with no review date. + +**d) What future problem does the SBOM solve?** + +When the next **Log4Shell-style** event hits, you query the SBOM (β€œdo we ship `log4j` / `stdlib` at version X?”) in minutes instead of grepping repos. It is the inventory for incident response and license compliance. + +--- + +## Task 2 β€” ZAP Baseline + Security Header Fix + +### ZAP runs + +```bash +# Before fix (base URL) +docker run --rm -v "$PWD/submissions/attachments/lab9/zap-before:/zap/wrk:rw" \ + ghcr.io/zaproxy/zaproxy:2.16.1 zap-baseline.py \ + -t http://host.docker.internal:8080 -r zap-report.html -J zap-report.json -I + +# After fix (/health) +docker run --rm -v "$PWD/submissions/attachments/lab9/zap-after:/zap/wrk:rw" \ + ghcr.io/zaproxy/zaproxy:2.16.1 zap-baseline.py \ + -t http://host.docker.internal:8080/health -r zap-report.html -J zap-report.json -I +``` + +### ZAP triage + +| ID | Name | Risk | URL | Disposition | Reason | +|----|------|------|-----|-------------|--------| +| 10049 | Storable and Cacheable Content | Info | `/robots.txt`, `/sitemap.xml` | **FIX** | Added `Cache-Control: no-cache, no-store, must-revalidate, private` + `Pragma: no-cache` via middleware. `/health` no longer cacheable. | +| 10116 | ZAP is Out of Date | Low | spider URLs | **ACCEPT** | Scanner metadata, not an app defect. Re-evaluate when upgrading ZAP image. | +| 90004 | Insufficient Site Isolation (Spectre) | Low | `/health` | **ACCEPT** | JSON API without cross-origin documents; COOP/COEP less critical than for HTML apps. Re-evaluate **2026-12-31**. | +| 10020–10038, 10063 | Header rules (CSP, X-Frame, etc.) | β€” | API JSON | **FIX** (proactive) | ZAP marked PASS on `application/json` responses; middleware adds headers anyway for defense in depth + unit test guard. | + +### Code fix β€” `app/security.go` middleware + +```go +func securityHeaders(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + h := w.Header() + h.Set("X-Content-Type-Options", "nosniff") + h.Set("X-Frame-Options", "DENY") + h.Set("Content-Security-Policy", "default-src 'none'") + h.Set("Referrer-Policy", "no-referrer") + h.Set("Permissions-Policy", "geolocation=(), microphone=(), camera=()") + h.Set("Cache-Control", "no-cache, no-store, must-revalidate, private") + h.Set("Pragma", "no-cache") + next.ServeHTTP(w, r) + }) +} +``` + +Wired in `main.go` via `server.Handler()`. Test: `TestSecurityHeaders_PresentOnAllRoutes` in `handlers_test.go`. + +### Before / after evidence + +**Before** (`/health` headers): + +``` +HTTP/1.1 200 OK +Content-Type: application/json +(no security headers) +``` + +[`zap-before/headers-health-before.txt`](attachments/lab9/zap-before/headers-health-before.txt) + +**After** (`/health` headers): + +``` +Cache-Control: no-cache, no-store, must-revalidate, private +Content-Security-Policy: default-src 'none' +X-Content-Type-Options: nosniff +X-Frame-Options: DENY +Permissions-Policy: geolocation=(), microphone=(), camera=() +Referrer-Policy: no-referrer +``` + +[`zap-after/headers-health-after.txt`](attachments/lab9/zap-after/headers-health-after.txt) + +ZAP: before **WARN** `Storable and Cacheable Content` on 404 paths; after `/health` scan shows **Non-Storable Content** (cache headers present). Reports: [`zap-before/`](attachments/lab9/zap-before/) Β· [`zap-after/`](attachments/lab9/zap-after/) + +### Design questions (e–g) + +**e) Why middleware, not per-handler headers?** + +One place enforces policy on **all** routes; impossible to forget a handler. Tests assert middleware once; removing middleware breaks the test. + +**f) `CSP: default-src 'none'` β€” what breaks?** + +Blocks browsers from loading any sub-resource (scripts, styles, images). Fine for a **JSON API** with no HTML. Would break a website with inline JS/CSS unless you allowlist sources. + +**g) Cost of blind ACCEPT on ZAP informational findings** + +You train reviewers to ignore the report; real issues hide in noise. Each ACCEPT should cite why the risk does not apply to this deployment. + +--- + +## Bonus β€” `govulncheck` in CI + +### Workflow addition (`.github/workflows/ci.yml`) + +```yaml + govulncheck: + name: govulncheck + runs-on: ubuntu-24.04 + defaults: + run: + working-directory: app + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2 + - uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0 + with: + go-version: '1.25.11' + - run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4 + - run: govulncheck ./... +``` + +`ci-ok` now depends on `govulncheck`. + +> **Why Go 1.25.11 for this job?** CI `vet`/`test` stay on Go 1.23/1.24. `govulncheck` on Go **1.24.13** reports **8 reachable stdlib vulnerabilities** (exit code 3) β€” fixes are in **1.25.11+**, not backported to 1.24. The gate runs on the patched toolchain so a clean app passes; the **red** demo still uses an intentional bad dependency. + +### Red / green demonstration + +**Red CI** β€” `govulncheck` on Go 1.24.13 (8 reachable stdlib vulns, run [#16](https://github.com/markovav-official/DevOps-Intro/actions/runs/28897363064)): + +![govulncheck failed on Go 1.24.13](attachments/lab9/red_ci.png) + +Local trace with intentional bad dependency: [`govulncheck-red.txt`](attachments/lab9/govulncheck-red.txt) β€” `golang.org/x/crypto@v0.3.0` + `ssh.Dial` reports reachable `GO-2026-5020` etc. + +**Green CI** β€” `govulncheck` on Go 1.25.11 (clean QuickNotes, run [#17](https://github.com/markovav-official/DevOps-Intro/actions/runs/28897987423)): + +![govulncheck passed on Go 1.25.11](attachments/lab9/green_ci.png) + +[`govulncheck-green.txt`](attachments/lab9/govulncheck-green.txt) β€” `No vulnerabilities found.` + +### Design questions (h–j) + +**h) Reachability vs module presence** + +Trivy flags β€œstdlib v1.24.13 contains CVE” if present in the binary. `govulncheck` traces **call paths** β€” if you do not call the vulnerable function, it may not block. That cuts triage noise but requires keeping the scanner updated. + +**i) Why pin govulncheck version?** + +Reproducible CI: `@latest` can change vulnerability DB logic or exit behavior between runs without a code change in your repo. + +**j) What govulncheck won't catch** + +OS packages in the container image, misconfigured `compose.yaml`, secrets in git, and non-Go dependencies β€” Trivy image/config/fs scans cover those layers. + +--- + +## Artifacts + +| Path | Description | +|------|-------------| +| `app/security.go` | Security headers middleware | +| `app/Dockerfile` | `USER nonroot:nonroot` (Trivy config fix) | +| `.github/workflows/ci.yml` | + `govulncheck` job | +| `submissions/attachments/lab9/` | Scan logs, SBOM, ZAP reports, CI screenshots | +| `submissions/attachments/lab9/red_ci.png` | Failed CI run #16 (`govulncheck` on Go 1.24) | +| `submissions/attachments/lab9/green_ci.png` | Successful CI run #17 (`govulncheck` on Go 1.25.11) | diff --git a/wasm-cli/go.mod b/wasm-cli/go.mod new file mode 100644 index 000000000..6f57bb7cf --- /dev/null +++ b/wasm-cli/go.mod @@ -0,0 +1,3 @@ +module moscow-time-cli + +go 1.22 diff --git a/wasm-cli/main.go b/wasm-cli/main.go new file mode 100644 index 000000000..d8da253e0 --- /dev/null +++ b/wasm-cli/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "os" + "time" +) + +func main() { + if os.Getenv("REQUEST_METHOD") != "GET" || os.Getenv("PATH_INFO") != "/time" { + fmt.Print("Status: 404 Not Found\r\nContent-Type: text/plain\r\n\r\nnot found") + return + } + + moscow := time.Now().UTC().Add(3 * time.Hour) + hourMinute := fmt.Sprintf("%02d:%02d", moscow.Hour(), moscow.Minute()) + body := fmt.Sprintf( + `{"unix":%d,"iso":%q,"hour_minute":%q,"moscow":%q,"tz":"UTC+3"}`, + moscow.Unix(), + moscow.Format(time.RFC3339), + hourMinute, + moscow.Format("2006-01-02 15:04:05"), + ) + + fmt.Printf("Content-Type: application/json\r\n\r\n%s", body) +} diff --git a/wasm/go.mod b/wasm/go.mod new file mode 100644 index 000000000..bd1702106 --- /dev/null +++ b/wasm/go.mod @@ -0,0 +1,7 @@ +module moscow-time + +go 1.22 + +require github.com/spinframework/spin-go-sdk/v2 v2.2.1 + +require github.com/julienschmidt/httprouter v1.3.0 // indirect diff --git a/wasm/go.sum b/wasm/go.sum new file mode 100644 index 000000000..447c042d5 --- /dev/null +++ b/wasm/go.sum @@ -0,0 +1,4 @@ +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/spinframework/spin-go-sdk/v2 v2.2.1 h1:ceAbRU+D3xmyZ8ScDLeFoT763ikFIUEmSjgsrD11v8k= +github.com/spinframework/spin-go-sdk/v2 v2.2.1/go.mod h1:vocVZB4qlTG8C5yoliKIAJCuv4x7sqK0GmVkWeD9N/A= diff --git a/wasm/main.go b/wasm/main.go new file mode 100644 index 000000000..f4ac0bc93 --- /dev/null +++ b/wasm/main.go @@ -0,0 +1,33 @@ +package main + +import ( + "fmt" + "net/http" + "time" + + spinhttp "github.com/spinframework/spin-go-sdk/v2/http" +) + +func init() { + spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + moscow := time.Now().UTC().Add(3 * time.Hour) + hourMinute := fmt.Sprintf("%02d:%02d", moscow.Hour(), moscow.Minute()) + body := fmt.Sprintf( + `{"unix":%d,"iso":%q,"hour_minute":%q,"moscow":%q,"tz":"UTC+3"}`, + moscow.Unix(), + moscow.Format(time.RFC3339), + hourMinute, + moscow.Format("2006-01-02 15:04:05"), + ) + + w.Header().Set("Content-Type", "application/json") + fmt.Fprint(w, body) + }) +} + +func main() {} diff --git a/wasm/spin.toml b/wasm/spin.toml new file mode 100644 index 000000000..f93948fc1 --- /dev/null +++ b/wasm/spin.toml @@ -0,0 +1,21 @@ +#:schema https://schemas.spinframework.dev/spin/manifest-v2/latest.json + +spin_manifest_version = 2 + +[application] +name = "moscow-time" +version = "0.1.0" +authors = ["Andrei Markov "] +description = "Moscow time JSON endpoint (Lab 12)" + +[[trigger.http]] +route = "/time" +component = "moscow-time" + +[component.moscow-time] +source = "main.wasm" +allowed_outbound_hosts = [] + +[component.moscow-time.build] +command = "tinygo build -target=wasip1 -buildmode=c-shared -no-debug -o main.wasm ." +watch = ["*.go", "go.mod", "go.sum"]