CSAI2026 labs: Lab-2..Lab-6 (Practical + Solution, data), Module-2..Module-6 notebooks and datasets

This commit is contained in:
mikrotik
2026-10-12 19:16:14 +07:00
commit 2fefa615cc
184 changed files with 1016761 additions and 0 deletions
@@ -0,0 +1,234 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "e58bd80a",
"metadata": {},
"source": [
"# Module 2 — Lab 3: Data Structures and Raw Log Analysis\n",
"\n",
"**Topics:** list, tuple, dictionary, set, parsing\n",
"\n",
"\n",
"> **Instructions:** Run the cells in order. Complete every `TODO`, then run the **Self-check** cell. Do not open the Solution notebook before attempting the tasks yourself.\n"
]
},
{
"cell_type": "markdown",
"id": "53230dd3",
"metadata": {},
"source": [
"## Input data\n",
"\n",
"Each log line contains four comma-separated fields: `timestamp,source_ip,username,status`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ad6600dc",
"metadata": {},
"outputs": [],
"source": [
"raw_logs = [\n",
" \"2026-09-01T08:00:00Z,203.0.113.55,alice,SUCCESS\",\n",
" \"2026-09-01T08:01:00Z,198.51.100.14,admin,FAILED\",\n",
" \"2026-09-01T08:01:20Z,198.51.100.14,root,FAILED\",\n",
" \"2026-09-01T08:02:00Z,192.0.2.88,bob,SUCCESS\",\n",
" \"2026-09-01T08:02:30Z,198.51.100.14,guest,FAILED\",\n",
" \"2026-09-01T08:03:00Z,192.0.2.99,carol,FAILED\",\n",
"]\n",
"\n",
"critical_fields = (\"timestamp\", \"source_ip\", \"username\", \"status\")\n",
"blocked_ips = {\"198.51.100.14\", \"203.0.113.200\"}\n",
"\n",
"print(f\"Rows: {len(raw_logs)}\")\n",
"print(\"Critical fields:\", critical_fields)\n"
]
},
{
"cell_type": "markdown",
"id": "b99fcf3b",
"metadata": {
"tags": [
"exercise"
]
},
"source": [
"## 1. Convert one log line into a dictionary\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a7f7c548",
"metadata": {
"tags": [
"exercise"
]
},
"outputs": [],
"source": [
"def parse_log_line(line):\n",
" # TODO 1: split the line into four variables\n",
" # TODO 2: return a dictionary with the four keys in critical_fields\n",
" # Normalize username to lowercase and status to uppercase.\n",
" pass\n",
"\n",
"\n",
"sample_event = parse_log_line(raw_logs[0])\n",
"print(sample_event)\n"
]
},
{
"cell_type": "markdown",
"id": "0d95749d",
"metadata": {
"tags": [
"exercise"
]
},
"source": [
"## 2. Create an event list and a set of unique IP addresses\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "809d56f4",
"metadata": {
"tags": [
"exercise"
]
},
"outputs": [],
"source": [
"# TODO 3: create the events list by parsing each raw log line\n",
"events = []\n",
"\n",
"# TODO 4: create the unique_ips set from events\n",
"unique_ips = set()\n",
"\n",
"print(\"Unique IPs:\", sorted(unique_ips))\n",
"print(\"Number of unique IPs:\", len(unique_ips))\n"
]
},
{
"cell_type": "markdown",
"id": "f97d6524",
"metadata": {
"tags": [
"exercise"
]
},
"source": [
"## 3. Count failed logins with a dictionary\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7bb93fd8",
"metadata": {
"tags": [
"exercise"
]
},
"outputs": [],
"source": [
"failed_by_ip = {}\n",
"\n",
"# TODO 5: count FAILED events for each source_ip.\n",
"# Hint: dictionary.get(ip, 0)\n",
"\n",
"print(failed_by_ip)\n"
]
},
{
"cell_type": "markdown",
"id": "1b67dd02",
"metadata": {
"tags": [
"exercise"
]
},
"source": [
"## 4. Combine dictionaries and sets to create alerts\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7a77c94f",
"metadata": {
"tags": [
"exercise"
]
},
"outputs": [],
"source": [
"alerts = []\n",
"\n",
"# TODO 6: create an alert when count >= 3 OR the IP is in blocked_ips.\n",
"# Each alert is a dictionary containing source_ip, failed_attempts, and blocked.\n",
"\n",
"print(alerts)\n"
]
},
{
"cell_type": "markdown",
"id": "9f495105",
"metadata": {},
"source": [
"## Self-check\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "487170fc",
"metadata": {},
"outputs": [],
"source": [
"assert sample_event[\"username\"] == \"alice\"\n",
"assert len(events) == 6\n",
"assert unique_ips == {\"203.0.113.55\", \"198.51.100.14\", \"192.0.2.88\", \"192.0.2.99\"}\n",
"assert failed_by_ip[\"198.51.100.14\"] == 3\n",
"assert alerts == [{\"source_ip\": \"198.51.100.14\", \"failed_attempts\": 3, \"blocked\": True}]\n",
"print(\"✓ Lab 3 completed\")\n"
]
},
{
"cell_type": "markdown",
"id": "f634dc9c",
"metadata": {},
"source": [
"## Reflection questions\n",
"\n",
"- Why is a `set` suitable for storing unique IP addresses or a blocklist?\n",
"- Why is a `tuple` suitable for field names that should not change?\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}