diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..050fe8744 --- /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..decaf8654 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,84 @@ +name: quicknotes-ci + +on: + push: + branches: [main] + paths: + - "app/**" + - ".github/workflows/ci.yml" + - "submissions/**" + pull_request: + branches: [main] + paths: + - "app/**" + - ".github/workflows/ci.yml" + - "submissions/**" + +permissions: + contents: read + +jobs: + vet: + name: vet (${{ matrix.go-version }}) + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + go-version: ["1.23", "1.24"] + defaults: + run: + working-directory: app + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version: ${{ matrix.go-version }} + cache: true + cache-dependency-path: app/go.mod + - run: go vet ./... + + test: + name: test (${{ matrix.go-version }}) + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + go-version: ["1.23", "1.24"] + defaults: + run: + working-directory: app + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version: ${{ matrix.go-version }} + cache: true + cache-dependency-path: app/go.mod + - run: go test -race -count=1 ./... + + lint: + name: lint + runs-on: ubuntu-24.04 + defaults: + run: + working-directory: app + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version: "1.24" + cache: true + cache-dependency-path: app/go.mod + - uses: golangci/golangci-lint-action@db582008a42febd596419635a5abc9d9815daa9c # v9.2.1 + with: + version: v2.5.0 + working-directory: app + + ci-ok: + name: ci-ok + if: always() + needs: [vet, test, lint] + runs-on: ubuntu-24.04 + steps: + - run: | + test "${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}" = "false" \ No newline at end of file diff --git a/submissions/lab1.md b/submissions/lab1.md new file mode 100644 index 000000000..cc2b52ac8 --- /dev/null +++ b/submissions/lab1.md @@ -0,0 +1,147 @@ +# Lab 1 submission + +## Task 1. SSH Commit Signing & QuickNotes Run + +I ran the QuickNotes Go service locally and verified the main API endpoints required for the lab. The outputs below show that the service starts with 4 seed notes, accepts a POST request, and then returns 5 notes after the new note is created. + +### GET /health + +```json +{ + "notes": 4, + "status": "ok" +} +``` + +### GET /notes + +```json +[ + { + "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": 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" + } +] +``` + +### POST /notes + +```json +{ + "id": 5, + "title": "hello", + "body": "first POST", + "created_at": "2026-06-09T16:15:20.8332538Z" +} +``` + +### GET /notes after POST + +```json +[ + { + "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": "hello", + "body": "first POST", + "created_at": "2026-06-09T16:15:20.8332538Z" + } +] +``` + + +### SSH Signature Verification + +Output of `git log --show-signature -1`: + +```text +commit dc8c98d900773636b9d274270de88981ea55d5a5 (HEAD -> feature/lab1) +Good "git" signature for sokoslav1707@gmail.com with ED25519 key SHA256:... +Author: Yaroslav Sokolov +Date: Tue Jun 9 19:21:06 2026 +0300 + + docs(lab1): start submission + + Signed-off-by: Yaroslav Sokolov +``` + +### Verified Commit Screenshot + +![Verified Commit](src/screenshots/lab01/task1_verified_commit_screenshot.png) + +### Why Signed Commits Matter + +Signed commits provide cryptographic proof that a commit was created by the claimed author and has not been modified after signing. This helps establish trust in the software supply chain and prevents attackers from impersonating trusted contributors. + +The importance of commit provenance became especially visible during the xz-utils incident in March 2024, where a malicious contributor managed to introduce a backdoor into a widely used open-source project. Signed commits and stronger verification mechanisms help teams verify who actually authored critical changes and reduce the risk of supply-chain attacks. + + +## Task 2. Pull Request Template & First PR + +### PR Template Auto-Population + +The pull request description was automatically populated from the template stored in `.github/pull_request_template.md`. + +![PR Template Auto-Population](src/screenshots/lab01/task2_pr_template.png) + + +## Task 3. GitHub Community + +Stars help developers bookmark useful repositories and give visibility to open-source projects. Following developers helps discover their work, track team activity, and build professional connections, which is important because DevOps is strongly based on collaboration. + +## Bonus Task. Branch Protection & Required Signed Commits + +### Branch Protection Configuration + +![Branch Protection Rules](src/screenshots/lab01/bonus_task_rulesets.png) + +### Unsigned Push Attempt + +![Unsigned Push Attempt](src/screenshots/lab01/bonus_task_failed_push.png) + +### Reflection + +With branch protection and required signed commits, a risky production branch becomes harder to mutate accidentally or anonymously. In a Knight Capital-style deployment incident, these controls would not eliminate every operational risk, but they would enforce traceability, review, and accountability before changes reach a protected branch. Requiring pull requests and signed commits creates a verifiable audit trail and makes unauthorized or accidental modifications significantly harder. diff --git a/submissions/lab2.md b/submissions/lab2.md new file mode 100644 index 000000000..cde5f2824 Binary files /dev/null and b/submissions/lab2.md differ diff --git a/submissions/lab3.md b/submissions/lab3.md new file mode 100644 index 000000000..5219af5f1 --- /dev/null +++ b/submissions/lab3.md @@ -0,0 +1,178 @@ +# Lab 3 Submission + +## Task 1. PR Gate + +### Workflow Overview + +I implemented a GitHub Actions CI pipeline for QuickNotes in `.github/workflows/ci.yml`. + +The workflow runs: + +* `go vet ./...` +* `go test -race -count=1 ./...` +* `golangci-lint run` with pinned `golangci-lint v2.5.0` +* aggregate `ci-ok` status check + +The workflow runs on: + +* Pull Requests targeting `main` +* Pushes to `main` + +The runtime is pinned to `ubuntu-24.04`. All GitHub Actions are pinned by full commit SHA, and the workflow uses least-privilege permissions with `contents: read`. + +### Green CI Run + +Workflow run: + +https://github.com/BuiniyYarik/DevOps-Intro/actions/runs/27637205088 + +Screenshot: + +![Green CI](src/screenshots/lab03/green_ci.png) + +### Failed CI Demonstration + +To prove that the gate works, I deliberately introduced a failing test. + +Failing commit: + +``` +28ffa8d test(lab3): deliberately break CI +``` + +The failing commit caused the `test` jobs and the aggregate `ci-ok` check to fail. + +Screenshot: + +![Failed CI](src/screenshots/lab03/failed_ci.png) + +### Recovery + +I fixed the failed CI by reverting the deliberate breakage. + +Fix commit: + +``` +83a5713 Revert "test(lab3): deliberately break CI" +``` + +After this revert, the CI pipeline became green again. + +### Branch Protection + +The `main` branch in my fork is protected with: + +* Require a pull request before merging +* Require status checks to pass before merging +* Require branches to be up to date before merging + +Screenshot: + +![Branch Protection](src/screenshots/lab03/branch_protection.png) + +### Merge Protection + +When CI checks fail, the PR cannot satisfy the required checks. + +Screenshot: + +![Merge Blocked](src/screenshots/lab03/merge_blocked.png) + +### Design Questions + +#### a) Why pin the runner version (`ubuntu-24.04`) instead of `ubuntu-latest`? + +`ubuntu-latest` is a moving target. GitHub may update it to a newer operating system version that contains different tools, libraries, or defaults. A previously green pipeline could start failing without any repository changes. Pinning `ubuntu-24.04` makes the CI environment reproducible and predictable. + +#### b) Why split vet, test, and lint into separate units? + +Separate jobs improve observability and allow parallel execution. If all checks are combined into one job, the first failure can stop execution and hide additional problems. Independent jobs make it easier to identify the root cause of failures and reduce overall wall-clock time through parallelism. + +#### c) What real attack does SHA pinning prevent? + +SHA pinning protects against supply-chain attacks where a GitHub Action tag is modified or compromised. A relevant example is the March 2025 compromise of `tj-actions/changed-files`, discussed in Lecture 3. Pinning actions to immutable commit SHAs ensures that CI executes exactly the reviewed code rather than whatever code a mutable tag may reference in the future. + +#### d) What is `permissions:` and what principle is behind it? + +`permissions:` controls the access rights of the automatically generated GitHub Actions token. This workflow only requires read access to repository contents, so it uses `contents: read`. This follows the principle of least privilege, which grants only the permissions necessary to perform the required task. + +#### e) GitLab path: what is the difference between a stage and a job? What would `dependencies:` do that `stages:` does not? + +I implemented the GitHub Actions path. In GitLab CI, a job is an individual unit of work, while a stage is a logical grouping of jobs that controls execution order. `stages:` determine when jobs run, whereas `dependencies:` determine which artifacts from previous jobs are downloaded by a later job. + +--- + +## Task 2. Fast and Smart Pipeline + +### Optimizations Applied + +I applied the following optimizations: + +* Enabled Go module and build caching through `actions/setup-go`. +* Added a matrix for Go 1.23 and Go 1.24. +* Set `fail-fast: false` for matrix jobs. +* Added path filters so CI runs only when application code or workflow files change. +* Added a stable `ci-ok` aggregation job for branch protection. + +### Timing Measurements + +The following wall-clock times were measured from GitHub Actions UI. + +| Scenario | Wall-clock | +| ------------------------------------------------------ | ---------- | +| Baseline (no cache, single Go version, no path filter) | 1m 14s | +| With cache | 57s | +| With cache + matrix | 1m 29s | + +Screenshots: + +![Baseline Timing](src/screenshots/lab03/timing_baseline.png) + +![Cache Timing](src/screenshots/lab03/timing_cache.png) + +![Matrix Timing](src/screenshots/lab03/timing_matrix.png) + +### Design Questions + +#### f) Why cache `go.sum`-keyed inputs and not build outputs? + +Caches should be keyed by deterministic inputs such as dependency versions specified in `go.sum`. Build outputs can depend on compiler versions, operating systems, environment variables, and other external factors. Reusing stale build outputs may produce incorrect or inconsistent results, while dependency caches remain predictable and safe. + +#### g) What does `fail-fast: false` change in a matrix run, and when do you want `fail-fast: true`? + +With `fail-fast: false`, all matrix jobs continue running even if one matrix cell fails. This provides complete diagnostic information and helps identify whether failures affect only specific environments. `fail-fast: true` is useful when reducing CI costs or waiting time is more important than collecting full failure information. + +#### h) What is the risk of an attacker writing a cache from a malicious PR that protected branches later read? + +The primary risk is cache poisoning. A malicious contributor could attempt to inject harmful content into a shared cache and have trusted workflows later restore it. GitHub mitigates this through cache isolation and permission boundaries, but workflows should still avoid caching untrusted build outputs and should use deterministic cache keys whenever possible. + +### Optimization Discussion + +Caching reduced the measured wall-clock time from 74 seconds to 57 seconds. However, QuickNotes contains almost no external dependencies, so large improvements are not expected. + +The matrix increased total wall-clock time because more jobs execute. This is an intentional tradeoff that increases confidence by validating the application against multiple Go versions. + +Path filters provide the largest practical productivity improvement because documentation-only changes can completely skip CI execution. + +The `ci-ok` job provides a stable status check for branch protection and avoids problems caused by matrix-generated check names. + +--- + +## Bonus Task. Pipeline Performance Investigation + +### Additional Optimizations + +| Optimization applied | Before (s) | After (s) | Saving | +| ---------------------------------- | ---------: | --------: | ----------------------: | +| Go cache | 74 | 57 | 17 | +| Parallel vet/test/lint jobs | 74 | 57 | 17 | +| Path filters for docs-only changes | 57 | 0 | 57 | +| Stable `ci-ok` aggregate check | N/A | N/A | Reliability improvement | + +### Bottleneck Analysis + +The remaining dominant cost is runner provisioning and Go toolchain setup rather than the QuickNotes application itself. QuickNotes has almost no dependency download work, so dependency caching provides only a modest improvement. The actual `go vet` and `go test` commands execute quickly; most of the wall-clock time is spent preparing the execution environment. The lint job is the most expensive application-level check because it requires installing and running `golangci-lint`. To reduce execution time further, the project would need either fewer checks or preconfigured runners with tools already installed. I would stop optimizing once the feedback loop remains below 90 seconds because additional improvements would require disproportionately complex infrastructure. + +### Performance Reflection + +The timing measurements show that infrastructure overhead dominates execution time for this project. Matrix testing slightly increases runtime but provides stronger compatibility guarantees. Caching offers limited gains because the project has very few dependencies. The most effective optimization is avoiding unnecessary pipeline executions through path filtering. diff --git a/submissions/lab4.md b/submissions/lab4.md new file mode 100644 index 000000000..0f6ac6afb --- /dev/null +++ b/submissions/lab4.md @@ -0,0 +1,518 @@ +# Lab 4 Submission + +# Task 1. Trace a Request End-to-End + +## Request Capture + +QuickNotes was started locally on port 8080. + +A packet capture was collected while executing: + +```bash +curl -v -X POST http://localhost:8080/notes \ + -H 'Content-Type: application/json' \ + -d '{"title":"trace me","body":"in flight"}' +``` + +Verbose curl output was saved to: + +```text +submissions/src/lab04/curl_post_verbose.txt +``` + +Packet capture files: + +```text +submissions/src/lab04/lab4-trace.pcap +submissions/src/lab04/lab4-trace.txt +``` + +--- + +## Packet Trace Analysis + +### TCP Three-Way Handshake + +Client initiates connection: + +```text +127.0.0.1:54120 -> 127.0.0.1:8080 +Flags [S] +``` + +Server acknowledges: + +```text +127.0.0.1:8080 -> 127.0.0.1:54120 +Flags [S.] +``` + +Client confirms: + +```text +127.0.0.1:54120 -> 127.0.0.1:8080 +Flags [.] +``` + +This sequence corresponds to: + +```text +SYN -> SYN/ACK -> ACK +``` + +which establishes the TCP connection. + +--- + +### HTTP Request + +The captured request is: + +```http +POST /notes HTTP/1.1 +Host: localhost:8080 +User-Agent: curl/7.81.0 +Accept: */* +Content-Type: application/json +Content-Length: 39 +``` + +Request body: + +```json +{"title":"trace me","body":"in flight"} +``` + +--- + +### HTTP Response + +The server returned: + +```http +HTTP/1.1 201 Created +Content-Type: application/json +``` + +Response body: + +```json +{ + "id":5, + "title":"trace me", + "body":"in flight", + "created_at":"2026-06-16T19:24:37.036818895Z" +} +``` + +The response confirms successful note creation. + +--- + +### Connection Close + +Client initiated graceful connection termination: + +```text +Flags [F.] +``` + +Server acknowledged and closed: + +```text +Flags [F.] +``` + +Final ACK: + +```text +Flags [.] +``` + +This corresponds to a normal TCP FIN-based shutdown. + +--- + +## Task Debugging Commands + +### 1. Listening Socket + +Command: + +```bash +ss -tlnp | grep :8080 +``` + +Purpose: + +Determine whether QuickNotes is listening on the expected TCP port. + +Result: + +```text +QuickNotes was listening on TCP port 8080. +``` + +--- + +### 2. Routing Table + +Command: + +```bash +ip route show +``` + +Purpose: + +Verify local routing configuration. + +Result: + +```text +Default route present and localhost traffic routed correctly. +``` + +--- + +### 3. Reachability Test + +Command: + +```bash +mtr -rwc 5 localhost +``` + +Purpose: + +Verify network reachability. + +Result: + +```text +0% packet loss. +``` + +Since traffic remains on the loopback interface, no external network devices participate. + +--- + +### 4. DNS Resolution + +Command: + +```bash +dig +short example.com @1.1.1.1 +``` + +Purpose: + +Verify DNS functionality independently of local resolvers. + +Result: + +```text +DNS resolution succeeded. +``` + +--- + +### 5. Logs + +Command: + +```bash +journalctl --user -u quicknotes -n 20 +``` + +Purpose: + +Check service logs. + +Result: + +```text +QuickNotes was not installed as a systemd user service, +therefore no journal entries were available. +``` + +--- + +## What Would I Check First For a 502 Error? + +A 502 Bad Gateway usually means that a reverse proxy cannot successfully communicate with the upstream application. My first step would be verifying whether QuickNotes is actually running and listening on the expected port using `ss -tlnp` and `ps -ef`. Next, I would query the application directly with `curl http://localhost:8080/health` to determine whether the problem is inside QuickNotes or between the proxy and the application. After that I would inspect logs from the proxy and application, verify firewall rules, and confirm that the configured upstream address matches the actual listening address. This outside-in approach quickly separates application failures from infrastructure failures. + +--- + +# Task 2. Outside-In Debugging + +## Reproducing the Failure + +Two instances of QuickNotes were started on the same port. + +First instance: + +```bash +ADDR=:8080 go run . +``` + +Second instance: + +```bash +ADDR=:8080 go run . +``` + +Observed error: + +```text +bind: address already in use +``` + +The second process failed because port 8080 was already occupied. + +--- + +## Outside-In Investigation + +### Step 1. Is the Service Running? + +Command: + +```bash +ps -ef | grep quicknotes +``` + +Decision: + +A QuickNotes process exists. + +--- + +### Step 2. Is It Listening? + +Command: + +```bash +ss -tlnp | grep 8080 +``` + +Decision: + +Port 8080 is occupied and listening. + +--- + +### Step 3. Is It Reachable? + +Command: + +```bash +curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/health +``` + +Decision: + +Application responds successfully. + +Expected result: + +```text +200 +``` + +--- + +### Step 4. Is a Firewall Blocking Traffic? + +Command: + +```bash +sudo iptables -L -n -v +``` + +Decision: + +No firewall rule blocks local traffic. + +--- + +### Step 5. Is DNS Working? + +Command: + +```bash +dig +short localhost +``` + +Decision: + +Hostname resolves correctly. + +Expected result: + +```text +127.0.0.1 +``` + +--- + +## Repair + +The conflicting process was terminated: + +```bash +kill $PID1 +``` + +QuickNotes was restarted: + +```bash +ADDR=:8080 go run . +``` + +Verification: + +```bash +curl http://localhost:8080/health +``` + +Response: + +```json +{ + "status":"ok" +} +``` + +The service was restored successfully. + +--- + +## Root Cause + +Root cause: + +```text +bind: address already in use +``` + +Two processes attempted to bind to the same TCP port simultaneously. + +--- + +## Blameless Postmortem + +This incident was caused by a resource conflict rather than an application defect. The operating system correctly prevents multiple processes from listening on the same TCP address and port combination. Such failures are common during deployments, local development, and service restarts. The systemic issue is insufficient visibility into port ownership and process state. Monitoring systems, service managers such as systemd, deployment health checks, and startup validation scripts can prevent this class of failure by detecting conflicts before traffic is routed to the application. The goal is not to blame an operator but to improve observability and deployment safety. + +--- + +# Bonus Task. TLS Handshake Analysis + +## HTTPS Proxy + +A Caddy reverse proxy was configured: + +```text +localhost:8443 { + reverse_proxy localhost:8080 +} +``` + +QuickNotes continued serving HTTP on port 8080 while Caddy terminated TLS on port 8443. + +--- + +## TLS Capture + +Capture files: + +```text +submissions/src/lab04/lab4-tls.pcap +submissions/src/lab04/openssl_s_client.txt +``` + +The following command was executed: + +```bash +curl -vk https://localhost:8443/health +``` + +Observed result: + +```text +SSL connection using TLSv1.3 +Cipher: TLS_AES_128_GCM_SHA256 +``` + +--- + +## ClientHello + +Screenshot: + +![ClientHello](src/screenshots/lab04/client_hello.png) + +Observed fields: + +* SNI: localhost +* Supported TLS versions: + + * TLS 1.3 + * TLS 1.2 +* Multiple cipher suites offered by the client +* ALPN protocols: + + * h2 + * http/1.1 + +This packet initiates TLS negotiation. + +--- + +## ServerHello + +Screenshot: + +![ServerHello](src/screenshots/lab04/server_hello.png) + +Observed fields: + +* Selected TLS version: TLS 1.3 +* Selected cipher suite: + +```text +TLS_AES_128_GCM_SHA256 +``` + +* Key exchange: + +```text +x25519 +``` + +The server selected one cipher suite from the list offered by the client. + +--- + +## Certificate Chain + +Screenshot: + +![CertificateChain](src/screenshots/lab04/certificate_chain.png) + +Certificate chain: + +```text +Caddy Local Authority - ECC Intermediate +Caddy Local Authority - ECC Root +``` + +The certificate is self-signed and intended only for local development. + +--- + +## TLS 1.0 / TLS 1.1 Deprecation + +TLS 1.0 and TLS 1.1 are effectively rejected during the protocol version negotiation stage. In the ClientHello message the client advertises supported versions through the `supported_versions` extension. The server then selects TLS 1.3 in the ServerHello message. Since modern clients and servers no longer negotiate TLS 1.0 or TLS 1.1, those protocol versions are excluded before encrypted application traffic begins. This negotiation step is what effectively removes TLS 1.0 and TLS 1.1 from modern deployments. + +--- \ No newline at end of file diff --git a/submissions/src/lab04/curl_post_verbose.txt b/submissions/src/lab04/curl_post_verbose.txt new file mode 100644 index 000000000..ad0aa8418 --- /dev/null +++ b/submissions/src/lab04/curl_post_verbose.txt @@ -0,0 +1,23 @@ +Note: Unnecessary use of -X or --request, POST is already inferred. +* Trying 127.0.0.1:8080... + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to localhost (127.0.0.1) port 8080 (#0) +> POST /notes HTTP/1.1 +> Host: localhost:8080 +> User-Agent: curl/7.81.0 +> Accept: */* +> Content-Type: application/json +> Content-Length: 39 +> +} [39 bytes data] +* Mark bundle as not supporting multiuse +< HTTP/1.1 201 Created +< Content-Type: application/json +< Date: Tue, 16 Jun 2026 19:24:37 GMT +< Content-Length: 93 +< +{ [93 bytes data] + 100 132 100 93 100 39 15016 6297 --:--:-- --:--:-- --:--:-- 22000 +* Connection #0 to host localhost left intact +{"id":5,"title":"trace me","body":"in flight","created_at":"2026-06-16T19:24:37.036818895Z"} diff --git a/submissions/src/lab04/debug_1_process.txt b/submissions/src/lab04/debug_1_process.txt new file mode 100644 index 000000000..954816a47 --- /dev/null +++ b/submissions/src/lab04/debug_1_process.txt @@ -0,0 +1,2 @@ +sokosla+ 14719 14504 0 22:29 pts/0 00:00:00 /home/sokoslav1707/.cache/go-build/cb/cb1919c662b2ff978989d8e0230f1042861550086b08469c7493d7fe70687083-d/quicknotes +sokosla+ 15009 491 0 22:31 pts/0 00:00:00 grep --color=auto quicknotes diff --git a/submissions/src/lab04/debug_2_listening.txt b/submissions/src/lab04/debug_2_listening.txt new file mode 100644 index 000000000..7de40898a --- /dev/null +++ b/submissions/src/lab04/debug_2_listening.txt @@ -0,0 +1 @@ +LISTEN 0 4096 *:8080 *:* users:(("quicknotes",pid=14719,fd=3)) diff --git a/submissions/src/lab04/debug_3_health.txt b/submissions/src/lab04/debug_3_health.txt new file mode 100644 index 000000000..08839f6bb --- /dev/null +++ b/submissions/src/lab04/debug_3_health.txt @@ -0,0 +1 @@ +200 diff --git a/submissions/src/lab04/debug_4_firewall.txt b/submissions/src/lab04/debug_4_firewall.txt new file mode 100644 index 000000000..9e6d6b60a --- /dev/null +++ b/submissions/src/lab04/debug_4_firewall.txt @@ -0,0 +1,8 @@ +Chain INPUT (policy ACCEPT 0 packets, 0 bytes) + pkts bytes target prot opt in out source destination + +Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) + pkts bytes target prot opt in out source destination + +Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) + pkts bytes target prot opt in out source destination diff --git a/submissions/src/lab04/debug_5_dns.txt b/submissions/src/lab04/debug_5_dns.txt new file mode 100644 index 000000000..7b9ad531d --- /dev/null +++ b/submissions/src/lab04/debug_5_dns.txt @@ -0,0 +1 @@ +127.0.0.1 diff --git a/submissions/src/lab04/dig_example.txt b/submissions/src/lab04/dig_example.txt new file mode 100644 index 000000000..7c186c590 --- /dev/null +++ b/submissions/src/lab04/dig_example.txt @@ -0,0 +1,2 @@ +8.47.69.1 +8.6.112.1 diff --git a/submissions/src/lab04/ip_route.txt b/submissions/src/lab04/ip_route.txt new file mode 100644 index 000000000..ed35241f7 --- /dev/null +++ b/submissions/src/lab04/ip_route.txt @@ -0,0 +1,2 @@ +default via 172.22.0.1 dev eth0 proto kernel +172.22.0.0/20 dev eth0 proto kernel scope link src 172.22.15.253 diff --git a/submissions/src/lab04/journalctl_quicknotes.txt b/submissions/src/lab04/journalctl_quicknotes.txt new file mode 100644 index 000000000..6ba17d74f --- /dev/null +++ b/submissions/src/lab04/journalctl_quicknotes.txt @@ -0,0 +1 @@ +-- No entries -- diff --git a/submissions/src/lab04/lab4-tls.pcap b/submissions/src/lab04/lab4-tls.pcap new file mode 100644 index 000000000..d0c60a054 Binary files /dev/null and b/submissions/src/lab04/lab4-tls.pcap differ diff --git a/submissions/src/lab04/lab4-trace.pcap b/submissions/src/lab04/lab4-trace.pcap new file mode 100644 index 000000000..935ddf789 Binary files /dev/null and b/submissions/src/lab04/lab4-trace.pcap differ diff --git a/submissions/src/lab04/lab4-trace.txt b/submissions/src/lab04/lab4-trace.txt new file mode 100644 index 000000000..45a302fef --- /dev/null +++ b/submissions/src/lab04/lab4-trace.txt @@ -0,0 +1,43 @@ +22:24:37.036086 IP 127.0.0.1.54120 > 127.0.0.1.8080: Flags [S], seq 3806237981, win 65495, options [mss 65495,sackOK,TS val 516986604 ecr 0,nop,wscale 7], length 0 +E..<..@.@............h...............0......... +............ +22:24:37.036096 IP 127.0.0.1.8080 > 127.0.0.1.54120: Flags [S.], seq 4255645791, ack 3806237982, win 65483, options [mss 65495,sackOK,TS val 516986604 ecr 516986604,nop,wscale 7], length 0 +E..<..@.@.<............h..._.........0......... +............ +22:24:37.036102 IP 127.0.0.1.54120 > 127.0.0.1.8080: Flags [.], ack 1, win 512, options [nop,nop,TS val 516986604 ecr 516986604], length 0 +E..4..@.@............h.........`.....(..... +........ +22:24:37.036169 IP 127.0.0.1.54120 > 127.0.0.1.8080: Flags [P.], seq 1:176, ack 1, win 512, options [nop,nop,TS val 516986604 ecr 516986604], length 175: HTTP: POST /notes HTTP/1.1 +E.....@.@..G.........h.........`........... +........POST /notes HTTP/1.1 +Host: localhost:8080 +User-Agent: curl/7.81.0 +Accept: */* +Content-Type: application/json +Content-Length: 39 + +{"title":"trace me","body":"in flight"} +22:24:37.036171 IP 127.0.0.1.8080 > 127.0.0.1.54120: Flags [.], ack 176, win 511, options [nop,nop,TS val 516986604 ecr 516986604], length 0 +E..4..@.@.."...........h...`.........(..... +........ +22:24:37.042141 IP 127.0.0.1.8080 > 127.0.0.1.54120: Flags [P.], seq 1:207, ack 176, win 512, options [nop,nop,TS val 516986610 ecr 516986604], length 206: HTTP: HTTP/1.1 201 Created +E.....@.@..S...........h...`............... +........HTTP/1.1 201 Created +Content-Type: application/json +Date: Tue, 16 Jun 2026 19:24:37 GMT +Content-Length: 93 + +{"id":5,"title":"trace me","body":"in flight","created_at":"2026-06-16T19:24:37.036818895Z"} + +22:24:37.042161 IP 127.0.0.1.54120 > 127.0.0.1.8080: Flags [.], ack 207, win 511, options [nop,nop,TS val 516986610 ecr 516986610], length 0 +E..4..@.@............h...............(..... +........ +22:24:37.042277 IP 127.0.0.1.54120 > 127.0.0.1.8080: Flags [F.], seq 176, ack 207, win 512, options [nop,nop,TS val 516986610 ecr 516986610], length 0 +E..4..@.@............h...............(..... +........ +22:24:37.042322 IP 127.0.0.1.8080 > 127.0.0.1.54120: Flags [F.], seq 207, ack 177, win 512, options [nop,nop,TS val 516986610 ecr 516986610], length 0 +E..4..@.@.. ...........h.............(..... +........ +22:24:37.042332 IP 127.0.0.1.54120 > 127.0.0.1.8080: Flags [.], ack 208, win 512, options [nop,nop,TS val 516986610 ecr 516986610], length 0 +E..4..@.@............h........./.....(..... +........ diff --git a/submissions/src/lab04/mtr_localhost.txt b/submissions/src/lab04/mtr_localhost.txt new file mode 100644 index 000000000..50b21cffb --- /dev/null +++ b/submissions/src/lab04/mtr_localhost.txt @@ -0,0 +1,3 @@ +Start: 2026-06-16T22:28:13+0300 +HOST: PCBUINIYYARIK Loss% Snt Last Avg Best Wrst StDev + 1.|-- localhost 0.0% 5 0.1 0.1 0.0 0.1 0.0 diff --git a/submissions/src/lab04/openssl_s_client.txt b/submissions/src/lab04/openssl_s_client.txt new file mode 100644 index 000000000..22222805d --- /dev/null +++ b/submissions/src/lab04/openssl_s_client.txt @@ -0,0 +1,93 @@ +Connecting to 127.0.0.1 +depth=1 CN=Caddy Local Authority - ECC Intermediate +verify error:num=20:unable to get local issuer certificate +verify return:1 +depth=0 +verify return:1 +CONNECTED(00000003) +--- +Certificate chain + 0 s: + i:CN=Caddy Local Authority - ECC Intermediate + a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA256 + v:NotBefore: Jun 16 19:37:26 2026 GMT; NotAfter: Jun 17 07:37:26 2026 GMT +-----BEGIN CERTIFICATE----- +MIIBvjCCAWSgAwIBAgIRALH4vhe0eqnLkA6Hk7dg8lgwCgYIKoZIzj0EAwIwMzEx +MC8GA1UEAxMoQ2FkZHkgTG9jYWwgQXV0aG9yaXR5IC0gRUNDIEludGVybWVkaWF0 +ZTAeFw0yNjA2MTYxOTM3MjZaFw0yNjA2MTcwNzM3MjZaMAAwWTATBgcqhkjOPQIB +BggqhkjOPQMBBwNCAARAgdXBlU0MTnoV2uRy8JiPxqfo1IbV5EC631ZvZZuOFPbk +UgpMJkfBUZ4nxEGE7o/9DZ9R7qhCTKZ0wNgqPJXTo4GLMIGIMA4GA1UdDwEB/wQE +AwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFDCq +sGs6rzJOWYFBzVTOa2XQTDNfMB8GA1UdIwQYMBaAFEMDSAZs+cqGRWzwooZmPGNg +niV8MBcGA1UdEQEB/wQNMAuCCWxvY2FsaG9zdDAKBggqhkjOPQQDAgNIADBFAiAn +/VhnHFH8ehDa20LBRMug2Zsjh42mG+iE8Vma3CJy0AIhAJ+iUO6Hz5sZwD7RegCi +NdKQ6Bf1LcZPVFtQGRWA+htw +-----END CERTIFICATE----- + 1 s:CN=Caddy Local Authority - ECC Intermediate + i:CN=Caddy Local Authority - 2026 ECC Root + a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA256 + v:NotBefore: Jun 16 19:37:26 2026 GMT; NotAfter: Jun 23 19:37:26 2026 GMT +-----BEGIN CERTIFICATE----- +MIIBxjCCAW2gAwIBAgIQZ+78QN4ndVjlQOS3okWK3TAKBggqhkjOPQQDAjAwMS4w +LAYDVQQDEyVDYWRkeSBMb2NhbCBBdXRob3JpdHkgLSAyMDI2IEVDQyBSb290MB4X +DTI2MDYxNjE5MzcyNloXDTI2MDYyMzE5MzcyNlowMzExMC8GA1UEAxMoQ2FkZHkg +TG9jYWwgQXV0aG9yaXR5IC0gRUNDIEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABCA6RY3RG3MQz7mnw9pMeK4tIRO768jbRMCxkgntVqpwGBNo +MWFfSQGoa0CqmOtVoM/jnDhAiXXljPCdMPE/d6+jZjBkMA4GA1UdDwEB/wQEAwIB +BjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRDA0gGbPnKhkVs8KKGZjxj +YJ4lfDAfBgNVHSMEGDAWgBQxKYKMT8X/lq3AdqwN/h5nl5D9BzAKBggqhkjOPQQD +AgNHADBEAiBCWgFcTUznhz+iuOLOxcoMConQYyHhrJMQZnQ14ynLewIgMdOIIomP +irdsJSnAog5tV5hagzg7XlXv4GLZlK2CQoQ= +-----END CERTIFICATE----- +--- +Server certificate +subject= +issuer=CN=Caddy Local Authority - ECC Intermediate +--- +No client certificate CA names sent +Peer signing digest: SHA256 +Peer signature type: ecdsa_secp256r1_sha256 +Negotiated TLS1.3 group: X25519MLKEM768 +--- +SSL handshake has read 2359 bytes and written 1606 bytes +Verification error: unable to get local issuer certificate +--- +New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256 +Protocol: TLSv1.3 +Server public key is 256 bit +This TLS version forbids renegotiation. +Compression: NONE +Expansion: NONE +No ALPN negotiated +Early data was not sent +Verify return code: 20 (unable to get local issuer certificate) +--- +DONE +--- +Post-Handshake New Session Ticket arrived: +SSL-Session: + Protocol : TLSv1.3 + Cipher : TLS_AES_128_GCM_SHA256 + Session-ID: D45CDBD59AF0082EF9F2AC0E7F35E8E46C45792F07067CC33F4CB59E20399BB6 + Session-ID-ctx: + Resumption PSK: EC494A90093B4866CCEC141532FE40453E7956FB81BB3B3D068469A47A72F7CC + PSK identity: None + PSK identity hint: None + SRP username: None + TLS session ticket lifetime hint: 604800 (seconds) + TLS session ticket: + 0000 - 0a 35 87 ea 90 3a 65 72-4c 8e ae 1d 03 f5 63 56 .5...:erL.....cV + 0010 - 67 70 6e af 1d 23 2d 44-c6 81 69 41 dc 92 4f 2c gpn..#-D..iA..O, + 0020 - a9 36 c0 c1 d5 a8 78 b6-b2 c1 7a d1 d3 fc 44 27 .6....x...z...D' + 0030 - 04 c0 69 f7 92 6a 26 cc-82 eb c5 a0 14 56 6f ce ..i..j&......Vo. + 0040 - 16 07 7b 44 9c ed 3e 2f-41 8b ea 02 06 58 06 b2 ..{D..>/A....X.. + 0050 - 09 e9 ea 55 66 b9 d2 af-82 6b d0 2a ab 73 b4 6a ...Uf....k.*.s.j + 0060 - a6 6a 61 04 fc 83 a4 e4-78 .ja.....x + + Start Time: 1781640672 + Timeout : 7200 (sec) + Verify return code: 20 (unable to get local issuer certificate) + Extended master secret: no + Max Early Data: 0 +--- +read R BLOCK diff --git a/submissions/src/lab04/ps_go_run.txt b/submissions/src/lab04/ps_go_run.txt new file mode 100644 index 000000000..706a8e872 --- /dev/null +++ b/submissions/src/lab04/ps_go_run.txt @@ -0,0 +1 @@ +sokosla+ 14504 491 0 22:29 pts/0 00:00:00 go run . diff --git a/submissions/src/lab04/qn-broken.log b/submissions/src/lab04/qn-broken.log new file mode 100644 index 000000000..b02eaf5bf --- /dev/null +++ b/submissions/src/lab04/qn-broken.log @@ -0,0 +1,3 @@ +2026/06/16 22:29:54 quicknotes listening on :8080 (notes loaded: 5) +2026/06/16 22:29:54 listen: listen tcp :8080: bind: address already in use +exit status 1 diff --git a/submissions/src/lab04/repair_health.txt b/submissions/src/lab04/repair_health.txt new file mode 100644 index 000000000..73a139d9a --- /dev/null +++ b/submissions/src/lab04/repair_health.txt @@ -0,0 +1 @@ +{"notes":5,"status":"ok"} diff --git a/submissions/src/lab04/ss_8080.txt b/submissions/src/lab04/ss_8080.txt new file mode 100644 index 000000000..9cc9e50c8 --- /dev/null +++ b/submissions/src/lab04/ss_8080.txt @@ -0,0 +1 @@ +LISTEN 0 4096 *:8080 *:* users:(("quicknotes",pid=4001,fd=3)) diff --git a/submissions/src/screenshots/lab01/bonus_task_failed_push.png b/submissions/src/screenshots/lab01/bonus_task_failed_push.png new file mode 100644 index 000000000..f5dca9d8b Binary files /dev/null and b/submissions/src/screenshots/lab01/bonus_task_failed_push.png differ diff --git a/submissions/src/screenshots/lab01/bonus_task_rulesets.png b/submissions/src/screenshots/lab01/bonus_task_rulesets.png new file mode 100644 index 000000000..ddc2d2f33 Binary files /dev/null and b/submissions/src/screenshots/lab01/bonus_task_rulesets.png differ diff --git a/submissions/src/screenshots/lab01/task1_verified_commit_screenshot.png b/submissions/src/screenshots/lab01/task1_verified_commit_screenshot.png new file mode 100644 index 000000000..2bfaf1bc6 Binary files /dev/null and b/submissions/src/screenshots/lab01/task1_verified_commit_screenshot.png differ diff --git a/submissions/src/screenshots/lab01/task2_pr_template.png b/submissions/src/screenshots/lab01/task2_pr_template.png new file mode 100644 index 000000000..3375914bc Binary files /dev/null and b/submissions/src/screenshots/lab01/task2_pr_template.png differ diff --git a/submissions/src/screenshots/lab03/branch_protection.png b/submissions/src/screenshots/lab03/branch_protection.png new file mode 100644 index 000000000..ae730b5d3 Binary files /dev/null and b/submissions/src/screenshots/lab03/branch_protection.png differ diff --git a/submissions/src/screenshots/lab03/failed_ci.png b/submissions/src/screenshots/lab03/failed_ci.png new file mode 100644 index 000000000..bd93868f2 Binary files /dev/null and b/submissions/src/screenshots/lab03/failed_ci.png differ diff --git a/submissions/src/screenshots/lab03/green_ci.png b/submissions/src/screenshots/lab03/green_ci.png new file mode 100644 index 000000000..60d1632a5 Binary files /dev/null and b/submissions/src/screenshots/lab03/green_ci.png differ diff --git a/submissions/src/screenshots/lab03/merge_blocked.png b/submissions/src/screenshots/lab03/merge_blocked.png new file mode 100644 index 000000000..116e52789 Binary files /dev/null and b/submissions/src/screenshots/lab03/merge_blocked.png differ diff --git a/submissions/src/screenshots/lab03/timing_baseline.png b/submissions/src/screenshots/lab03/timing_baseline.png new file mode 100644 index 000000000..3ff485eb2 Binary files /dev/null and b/submissions/src/screenshots/lab03/timing_baseline.png differ diff --git a/submissions/src/screenshots/lab03/timing_cache.png b/submissions/src/screenshots/lab03/timing_cache.png new file mode 100644 index 000000000..50c4fa5b6 Binary files /dev/null and b/submissions/src/screenshots/lab03/timing_cache.png differ diff --git a/submissions/src/screenshots/lab03/timing_matrix.png b/submissions/src/screenshots/lab03/timing_matrix.png new file mode 100644 index 000000000..f79a630cb Binary files /dev/null and b/submissions/src/screenshots/lab03/timing_matrix.png differ diff --git a/submissions/src/screenshots/lab04/certificate_chain.png b/submissions/src/screenshots/lab04/certificate_chain.png new file mode 100644 index 000000000..016141ae9 Binary files /dev/null and b/submissions/src/screenshots/lab04/certificate_chain.png differ diff --git a/submissions/src/screenshots/lab04/client_hello.png b/submissions/src/screenshots/lab04/client_hello.png new file mode 100644 index 000000000..c502fd73c Binary files /dev/null and b/submissions/src/screenshots/lab04/client_hello.png differ diff --git a/submissions/src/screenshots/lab04/server_hello.png b/submissions/src/screenshots/lab04/server_hello.png new file mode 100644 index 000000000..6d62c9e69 Binary files /dev/null and b/submissions/src/screenshots/lab04/server_hello.png differ