diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 810520f..b065ac9 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -9,36 +9,45 @@ on: - closed permissions: - contents: write - pull-requests: write + contents: read + pages: write + id-token: write -concurrency: preview-${{ github.ref }} +concurrency: + group: "pr-preview" + cancel-in-progress: false jobs: - deploy-preview: + build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - + - name: Setup Ruby uses: ruby/setup-ruby@v1 with: ruby-version: '3.1' bundler-cache: true - - - name: Build Jekyll site - if: github.event.action != 'closed' - run: | - # Remove CNAME file for previews to avoid routing conflicts - rm -f CNAME - bundle exec jekyll build + + - name: Build with Jekyll + run: bundle exec jekyll build env: JEKYLL_ENV: production - - - name: Deploy preview - uses: rossjrw/pr-preview-action@v1 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 with: - source-dir: ./_site - preview-branch: gh-pages - umbrella-dir: pr-preview + path: ./_site + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + diff --git a/Gemfile b/Gemfile index 8cb2c31..20fae8a 100644 --- a/Gemfile +++ b/Gemfile @@ -5,6 +5,7 @@ gem 'jekyll-dash', '~> 2.0' gem 'jekyll-feed', '~> 0.17' gem 'jekyll-sitemap', '~> 1.4' gem 'jekyll-paginate', '~> 1.1' +gem 'jekyll-mermaid' # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem # and associated library. diff --git a/_config.yml b/_config.yml index de29662..462b37e 100644 --- a/_config.yml +++ b/_config.yml @@ -1,7 +1,7 @@ theme: jekyll-dash title: devnomadic -description: Software engineer and digital nomad currently exploring the world. I write about remote work, travel, and building software from anywhere. -url: "https://devnomadic.github.io" +description: ""Dev(Ops|SecOps)?|SRE" Engineer and digital nomad currently exploring the world. I write about remote work, travel, and building software from anywhere." +url: "https://devnomadic.com" baseurl: "" # Jekyll pagination (required for home page) @@ -12,7 +12,7 @@ author: name: devnomadic github: devnomadic email: drew@devnomadic.com - bio: "Software engineer and digital nomad currently exploring the world. I write about remote work, travel, and building software from anywhere." + bio: ""Dev(Ops|SecOps)?|SRE" Engineer and digital nomad currently exploring the world. I write about remote work, travel, and building software from anywhere." avatar: "/assets/avatar.gif" # Build settings @@ -21,6 +21,11 @@ plugins: - jekyll-feed - jekyll-sitemap - jekyll-paginate + - jekyll-mermaid + +# Mermaid configuration +mermaid: + src: 'https://unpkg.com/mermaid@10.6.1/dist/mermaid.min.js' # Theme settings dash: @@ -28,6 +33,14 @@ dash: show_author: true avatar_source: "local" avatar_path: "/assets/avatar.gif" + show_nav: true + nav_links: + - url: /about/ + title: About + - url: /archive/ + title: Archive + - url: /tags/ + title: Tags social_links: - url: https://github.com/devnomadic icon: github diff --git a/_config_preview.yml b/_config_preview.yml deleted file mode 100644 index 9103d2a..0000000 --- a/_config_preview.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Preview-specific configuration -# This extends the main _config.yml for preview builds - -# Collections for staging posts -collections: - staging: - output: true - permalink: /:collection/:name/ - -# Make staging posts appear in site.posts -defaults: - - scope: - path: "staging" - type: "staging" - values: - layout: "post" - -# Include staging directory in the build -include: - - staging diff --git a/_includes/head-custom.html b/_includes/head-custom.html index 8b6cfcb..d8037dd 100644 --- a/_includes/head-custom.html +++ b/_includes/head-custom.html @@ -15,4 +15,3 @@ background-color: #e8eaed; color: #202124; } - diff --git a/_includes/header.html b/_includes/header.html new file mode 100644 index 0000000..f1823ac --- /dev/null +++ b/_includes/header.html @@ -0,0 +1,20 @@ + diff --git a/_includes/mermaid.html b/_includes/mermaid.html new file mode 100644 index 0000000..e69de29 diff --git a/_layouts/page.html b/_layouts/page.html new file mode 100644 index 0000000..4e0d4eb --- /dev/null +++ b/_layouts/page.html @@ -0,0 +1,8 @@ +--- +layout: default +--- + +
+

{{ page.title }}

+ {{ content }} +
diff --git a/_posts/2025-06-08-remote-development-environment.md b/_posts/2025-06-08-remote-development-environment.md index a9e0eb7..aa9ac07 100644 --- a/_posts/2025-06-08-remote-development-environment.md +++ b/_posts/2025-06-08-remote-development-environment.md @@ -3,11 +3,29 @@ layout: post title: "Setting Up the Perfect Remote Development Environment" description: "Essential tools and configurations for productive remote coding" date: 2025-06-08 -tags: remote-work development tools productivity vscode docker +tags: [remoteWork, development, tools, productivity, vsCode, docker] --- # Creating Your Remote Development Paradise +## 📝 TL;DR + +Complete guide to **setting up a productive remote development environment** for digital nomads: + +**Hardware Essentials:** +- 💻 **MacBook Pro M3** (16GB+ RAM) + portable monitor +- ⌨️ **Compact mechanical keyboard** + wireless mouse + +**Software Stack:** +- 🔧 **VS Code** with Remote Development extensions +- 🐳 **Docker** for consistent environments +- ☁️ **Cloud services** (GitHub Codespaces, AWS Cloud9) +- 🔒 **VPN** + secure backup solutions + +**Key Tips:** Prioritize battery life, internet reliability, and portable ergonomics! + +--- + Working remotely as a developer requires a carefully crafted environment that enables productivity from anywhere in the world. Here's my guide to setting up the perfect remote development setup. ## Essential Hardware @@ -22,6 +40,7 @@ Your laptop is your lifeline. I recommend: - **Portable monitor** - For dual-screen setups in coworking spaces - **Mechanical keyboard** - Compact 60% or TKL for travel - **Wireless mouse** - Better ergonomics than trackpad for long sessions +- **Physical Notebook** - Always handy to scribble thoughts and diagrams. I prefer an A5 Moleskine (Graph Paper) ## Software Stack @@ -104,6 +123,34 @@ git push --all origin # All branches to remote - Record video explanations for complex topics - Use collaborative coding tools (Live Share, CodeSandbox) +### Laptop Considerations for Remote Work + +#### Performance vs Portability Balance +- **Weight matters**: Aim for under 3 lbs if constantly traveling +- **Battery life**: Minimum 8 hours for reliable all-day work +- **Processing power**: M-series MacBooks or AMD Ryzen for efficiency + +#### Screen Quality +- **High resolution**: 1440p minimum for code readability +- **Color accuracy**: Important for UI/design work +- **Brightness**: 400+ nits for outdoor/bright environment work + +#### Port Selection +- **USB-C/Thunderbolt**: Future-proof and versatile +- **HDMI port**: Direct external monitor connection +- **SD card slot**: Useful for photographers/content creators +- **Headphone jack**: Backup for wireless audio issues + +#### Keyboard & Trackpad +- **Key travel**: Sufficient feedback for long typing sessions +- **Trackpad size**: Large enough for gesture navigation +- **Backlit keys**: Essential for low-light environments + +#### Repairability & Support +- **Global warranty**: Apple Care+ or manufacturer support worldwide +- **Parts availability**: Consider common models in your travel regions +- **Local service centers**: Research coverage in frequent destinations + ## Location-Specific Tips ### Coworking Spaces @@ -127,4 +174,9 @@ The perfect remote development environment is personal and evolves with your nee The key is having redundancy in everything - internet, power, workspace options. This ensures you can always deliver quality work regardless of where you are in the world. +## 📋 Changelog + +- **2025-06-08:** Initial publication +- **2025-06-15:** Updated tag format and added changelog + --- \ No newline at end of file diff --git a/_posts/2025-06-09-welcome-to-devnomadic.md b/_posts/2025-06-09-devnomadic.md similarity index 68% rename from _posts/2025-06-09-welcome-to-devnomadic.md rename to _posts/2025-06-09-devnomadic.md index 430fcb2..32ce7d6 100644 --- a/_posts/2025-06-09-welcome-to-devnomadic.md +++ b/_posts/2025-06-09-devnomadic.md @@ -1,13 +1,27 @@ --- layout: post -title: "Welcome to devnomadic" +title: "devnomadic" description: "Starting my journey as a digital nomad developer" date: 2025-06-09 -tags: introduction devnomad remote-work digital-nomad software-engineering travel lifestyle blogging +tags: [introduction, devNomad, remoteWork, digitalNomad, softwareEngineering, travel, lifestyle, blogging] --- # Welcome to my digital nomad journey! +## 📝 TL;DR + +🚀 **Starting devnomadic** - a blog documenting my journey as a software engineer embracing the digital nomad lifestyle. + +**What you'll find here:** +- 🔧 **Technical tutorials** & best practices +- 🌍 **Remote work insights** from distributed teams +- ✈️ **Travel stories** from a developer's perspective +- 📱 **Tool recommendations** for nomadic developers + +Join me as I explore the intersection of **code, travel, and remote work**! + +--- + Hello and welcome to devnomadic! This blog represents the beginning of documenting my journey as a software engineer embracing the digital nomad lifestyle. ## Why devnomadic? @@ -45,4 +59,9 @@ I'm excited to share this journey with you. Whether you're a fellow developer cu Let's build something amazing together, from anywhere in the world! 🚀 +## 📋 Changelog + +- **2025-06-09:** Initial publication +- **2025-06-15:** Updated tag format and added changelog + --- \ No newline at end of file diff --git a/_posts/2025-06-10-albatross.md b/_posts/2025-06-10-albatross.md index 097bcd0..9cb02e6 100644 --- a/_posts/2025-06-10-albatross.md +++ b/_posts/2025-06-10-albatross.md @@ -3,13 +3,37 @@ layout: post title: Albatross description: "Albatross Cloud IP maifest & reputation search" date: 2025-06-10 -tags: BlazorWebAssembly CloudflareWorkers DevSecOps WebDevelopment CyberSecurity +tags: [blazorWebAssembly, cloudflareWorkers, devSecOps, webDevelopment, cyberSecurity] --- # Building Albatross: A Secure IP Abuse Checker with Blazor WebAssembly and Cloudflare Workers *Published: June 9, 2025* +## 📝 TL;DR + +Built **Albatross**, a secure IP abuse checker using Blazor WebAssembly + Cloudflare Workers. Key features: +- 🔐 **Secure API proxy** with HMAC authentication (no exposed API keys) +- ⚡ **Fast client-side app** with server-side API protection +- �️ **Real-time IP reputation checking** via AbuseIPDB +- 🏗️ **Modern architecture** combining the best of client and edge computing + +This algorithm efficiently compares IP addresses against CIDR ranges by: +1. **Splitting the CIDR** notation (e.g., "10.0.0.0/8") +2. **Converting to bytes** for efficient comparison +3. **Comparing full bytes** first (faster than bit-by-bit) +4. **Handling remainder bits** with bitwise masking +5. **Early termination** on mismatch for performance + +## Security Implementationion (no exposed API keys) +- ⚡ **Fast client-side app** with server-side API protection +- 🛡️ **Real-time IP reputation checking** via AbuseIPDB +- 🏗️ **Modern architecture** combining the best of client and edge computing + +**Tech Stack:** Blazor WASM, Cloudflare Workers, HMAC-SHA256, AbuseIPDB API, Cloudflare Radar API + +--- + In an era where cybersecurity threats are constantly evolving, having reliable tools to check IP addresses for malicious activity has become essential. Today, I'm excited to share the journey of building **Albatross** - a secure, modern web application that leverages the AbuseIPDB API to provide real-time IP abuse checking through a sophisticated architecture combining Blazor WebAssembly and Cloudflare Workers. ## The Challenge: Secure API Proxy Architecture @@ -24,14 +48,13 @@ For Albatross, I chose a different path: **Cloudflare Workers as a secure API pr ## Architecture Overview -``` -┌─────────────────┐ HMAC Auth ┌─────────────────┐ API Key ┌─────────────────┐ -│ │ ──────────→ │ │ ──────────→ │ │ -│ Blazor WASM │ │ Cloudflare │ │ AbuseIPDB │ -│ Client │ ←────────── │ Worker │ ←────────── │ API │ -│ │ CORS + JSON │ │ JSON Data │ │ -└─────────────────┘ └─────────────────┘ └─────────────────┘ -``` +{% mermaid %} +graph LR + A[Blazor WASM
Client] -->|HMAC Auth| B[Cloudflare
Worker] + B -->|API Key| C[AbuseIPDB
API] + C -->|JSON Data| B + B -->|CORS + JSON| A +{% endmermaid %} ### Key Components: @@ -47,12 +70,20 @@ One of the most innovative aspects of Albatross is its build-time authentication ### PowerShell Key Generation Script ```powershell -# Generate-AuthKey.ps1 +# Generate-AuthKey.ps1 - Updated implementation function Generate-SecureKey { - $rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::Create() + # Generate a cryptographically secure random key $keyBytes = New-Object byte[] 32 # 256 bits + $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create() $rng.GetBytes($keyBytes) - return [Convert]::ToBase64String($keyBytes) + + # Convert to Base64 and make UTF-8 compatible + $randomBase64 = [System.Convert]::ToBase64String($keyBytes) + $authKeyString = $randomBase64.Substring(0, [Math]::Min(32, $randomBase64.Length)).Replace("/", "_").Replace("+", "-") + + # Convert UTF-8 string to base64 for storage + $authKeyBytes = [System.Text.Encoding]::UTF8.GetBytes($authKeyString) + return [System.Convert]::ToBase64String($authKeyBytes) } $authKey = Generate-SecureKey @@ -71,7 +102,7 @@ This approach provides several security benefits: The key generation is seamlessly integrated into the .NET build process using custom MSBuild targets: ```xml - + @@ -91,9 +122,35 @@ The authentication system uses HMAC-SHA256 to sign requests, ensuring both authe ```csharp private string GenerateHmacToken(string requestUrl) { - using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(BuildConstants.AuthKey)); - var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(requestUrl.ToLower())); - return Convert.ToBase64String(hash); + if (string.IsNullOrEmpty(_authKey)) + { + Console.WriteLine("Debug: Auth key is null or empty"); + return string.Empty; + } + + if (string.IsNullOrEmpty(requestUrl)) + { + Console.WriteLine("Debug: Request URL is null or empty"); + return string.Empty; + } + + try + { + Console.WriteLine($"Debug: Generating HMAC for URL: {requestUrl}"); + Console.WriteLine($"Debug: Using auth key: {_authKey}"); + + using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_authKey)); + var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(requestUrl)); + var token = Convert.ToBase64String(hash); + + Console.WriteLine($"Debug: Generated HMAC hash: {token}"); + return token; + } + catch (Exception ex) + { + Console.WriteLine($"Debug: Exception in GenerateHmacToken: {ex.Message}"); + return string.Empty; + } } ``` @@ -102,7 +159,7 @@ private string GenerateHmacToken(string requestUrl) ```javascript async function validateHmacToken(receivedToken, requestUrl) { const keyBytes = new TextEncoder().encode(AUTH_KEY); - const messageBytes = new TextEncoder().encode(requestUrl); + const messageBytes = new TextEncoder().encode(message); const cryptoKey = await crypto.subtle.importKey( 'raw', keyBytes, @@ -264,11 +321,20 @@ Response times are consistently under 100ms thanks to: Several exciting features are planned for future releases: +### Core Application Features 1. **Rate Limiting**: Implement per-IP rate limiting in the Worker 2. **Analytics Dashboard**: Track usage patterns and abuse attempts 3. **API Key Rotation**: Automated rotation of AbuseIPDB API keys 4. **Multi-Provider Support**: Integration with additional threat intelligence APIs -5. **Real-Time Notifications**: WebSocket-based alerts for high-risk IPs +5. **Gen-AI Search**: AI-powered search for IP reputation and abuse history +6. **Real-Time Notifications**: WebSocket-based alerts for high-risk IPs + +### Cloud IP Search Enhancements +1. **Additional Providers**: IBM Cloud, Alibaba Cloud, DigitalOcean support +2. **Historical Data**: Track IP range changes over time +3. **Geolocation Integration**: Combine cloud attribution with geographic data +4. **API Integration**: Programmatic access to cloud IP attribution +5. **Bulk Processing**: Upload and process IP lists ## Cloud IP Manifest Search: Identifying Cloud Infrastructure @@ -285,28 +351,15 @@ In today's cloud-first world, understanding which cloud provider owns a specific ### Architecture and Data Sources -The system maintains up-to-date IP range manifests from three major cloud providers: +The system maintains up-to-date IP range manifests from four major cloud providers: -``` -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ AWS IP Ranges │ │ Azure IP Ranges │ │ GCP IP Ranges │ -│ │ │ │ │ │ -│ • 76,000+ IPs │ │ • 135,000+ IPs │ │ • 3,100+ IPs │ -│ • Regional Data │ │ • Service Tags │ │ • Scope Data │ -│ • Service Info │ │ • Platform Info │ │ • Global Ranges │ -└─────────────────┘ └─────────────────┘ └─────────────────┘ - │ │ │ - └───────────────────────┼───────────────────────┘ - │ - ┌─────────────────┐ - │ Albatross │ - │ Search Engine │ - │ │ - │ • CIDR Matching │ - │ • IPv4 & IPv6 │ - │ • Real-time │ - └─────────────────┘ -``` +{% mermaid %} +graph TD + A[AWS IP Ranges
• 76,000+ IPs
• Regional Data
• Service Info] --> E[Albatross
Search Engine
• CIDR Matching
• IPv4 & IPv6
• Real-time
• Parallel Exec] + B[Azure IP Ranges
• 135,000+ IPs
• Service Tags
• Platform Info] --> E + C[GCP IP Ranges
• 3,100+ IPs
• Scope Data
• Global Ranges] --> E + D[OCI IP Ranges
• 2,800+ IPs
• Regional Tags
• Service Data] --> E +{% endmermaid %} ### Official Data Sources @@ -357,6 +410,31 @@ The system maintains up-to-date IP range manifests from three major cloud provid } ``` +#### Oracle Cloud Infrastructure IP Ranges +- **Source**: `https://docs.oracle.com/en-us/iaas/tools/public_ip_ranges.json` +- **Updates**: Regularly updated by Oracle +- **Contains**: Regional data, service tags, CIDR blocks +- **Format**: Regional structure with comprehensive metadata + +```json +{ + "region": "us-ashburn-1", + "cidr": "129.213.0.0/16", + "tags": ["OCI", "OracleServices", "us-ashburn-1"] +} +``` + +### Enhanced Cloud Provider Coverage + +With the recent addition of **Oracle Cloud Infrastructure (OCI)** support, Albatross now provides comprehensive coverage of the four major cloud providers: + +- **Amazon Web Services (AWS)**: 76,000+ IP ranges +- **Microsoft Azure**: 135,000+ IP ranges +- **Google Cloud Platform (GCP)**: 3,100+ IP ranges +- **Oracle Cloud Infrastructure (OCI)**: 2,800+ IP ranges + +This expansion significantly improves the tool's ability to identify cloud-hosted infrastructure across the enterprise landscape. + ### Smart Search Algorithm The cloud IP detection uses a sophisticated CIDR (Classless Inter-Domain Routing) matching algorithm: @@ -373,23 +451,38 @@ private bool IsIpInRange(IPAddress ipAddress, string cidrRange) var networkAddress = IPAddress.Parse(parts[0]); var prefixLength = int.Parse(parts[1]); - // Convert to bytes for bitwise operations var ipBytes = ipAddress.GetAddressBytes(); var networkBytes = networkAddress.GetAddressBytes(); - // Handle IPv4 vs IPv6 compatibility if (ipBytes.Length != networkBytes.Length) return false; - - // Calculate subnet mask - var totalBits = ipBytes.Length * 8; - var maskBits = prefixLength; - // Perform bitwise comparison - for (int byteIndex = 0; byteIndex < ipBytes.Length; byteIndex++) + var bytesToCheck = prefixLength / 8; + var remainderBits = prefixLength % 8; + + // Compare full bytes + for (int i = 0; i < bytesToCheck; i++) + { + if (ipBytes[i] != networkBytes[i]) + return false; + } + + // Check remainder bits if any + if (remainderBits > 0 && bytesToCheck < ipBytes.Length) { - var bitsInThisByte = Math.Min(8, Math.Max(0, maskBits - (byteIndex * 8))); - if (bitsInThisByte == 0) break; + var mask = (byte)(0xFF << (8 - remainderBits)); + if ((ipBytes[bytesToCheck] & mask) != (networkBytes[bytesToCheck] & mask)) + return false; + } + + return true; + } + catch + { + return false; + } +} +``` var mask = (byte)(0xFF << (8 - bitsInThisByte)); if ((ipBytes[byteIndex] & mask) != (networkBytes[byteIndex] & mask)) @@ -479,6 +572,10 @@ curl -sSL "https://ip-ranges.amazonaws.com/ip-ranges.json" \ curl -sSL "https://www.gstatic.com/ipranges/cloud.json" \ -o ./wwwroot/ip-manifests/GCP.json +# Fetch Oracle IP ranges +curl -sSL "https://docs.oracle.com/en-us/iaas/tools/public_ip_ranges.json" \ + -o ./wwwroot/ip-manifests/Oracle.json + # Fetch Azure IP ranges (dynamic URL discovery) curl -sSL "https://www.microsoft.com/en-us/download/confirmation.aspx?id=56519" \ > /tmp/azure_page.html @@ -489,12 +586,12 @@ curl -sSL "$AZURE_URL" -o ./wwwroot/ip-manifests/Azure.json ### Performance Optimizations -Despite searching through 200,000+ IP ranges, the system maintains excellent performance: +Despite searching through 217,000+ IP ranges across four cloud providers, the system maintains excellent performance: 1. **Client-Side Processing**: All searches run in the browser using WebAssembly 2. **Efficient Algorithms**: Optimized CIDR matching with early termination 3. **Cached Manifests**: Static JSON files served via CDN -4. **Parallel Processing**: Simultaneous searches across all three providers +4. **Parallel Processing**: Simultaneous searches across all four providers 5. **Smart Indexing**: Future enhancement for sub-second responses ### Example Search Results @@ -521,17 +618,210 @@ The cloud IP search functionality provides significant security value: 3. **Compliance Validation**: Verify that data flows through expected cloud regions 4. **Incident Response**: Rapidly classify IP addresses during security investigations -### Future Enhancements +The Cloud IP Manifest Search feature demonstrates how modern web applications can provide enterprise-grade functionality while maintaining simplicity and performance. By leveraging official cloud provider data and efficient client-side processing, Albatross delivers accurate, real-time cloud infrastructure attribution that's invaluable for security professionals and network administrators. -Several exciting improvements are planned: +## Recent Enhancements (July 2025) -1. **Additional Providers**: Oracle Cloud, IBM Cloud, Alibaba Cloud support -2. **Historical Data**: Track IP range changes over time -3. **Geolocation Integration**: Combine cloud attribution with geographic data -4. **API Integration**: Programmatic access to cloud IP attribution -5. **Bulk Processing**: Upload and process IP lists +Since the June updates, Albatross has received several critical improvements focused on deployment reliability, security hardening, and cross-browser compatibility: -The Cloud IP Manifest Search feature demonstrates how modern web applications can provide enterprise-grade functionality while maintaining simplicity and performance. By leveraging official cloud provider data and efficient client-side processing, Albatross delivers accurate, real-time cloud infrastructure attribution that's invaluable for security professionals and network administrators. +### Static Sitemap Implementation + +A significant architectural change was made to improve SEO and deployment reliability: + +- **Removed Dynamic Generation**: Eliminated all dynamic sitemap.xml generation from MSBuild targets and PowerShell scripts +- **Static SEO Optimization**: Implemented a manually-maintained sitemap.xml with fixed URLs and appropriate metadata +- **Improved Indexing**: Better search engine discoverability with consistent sitemap structure +- **Simplified Deployment**: Reduced build complexity by removing dynamic XML generation + +The static sitemap approach provides more reliable SEO benefits while simplifying the build process: + +```xml + + + + https://albatross.devnomadic.com/ + 2025-07-12 + weekly + 1.0 + + + + https://albatross.devnomadic.com/ip-manifests/AWS.json + 2025-07-12 + daily + 0.8 + + +``` + +### Cross-Browser ASCII Art Rendering + +Addressed significant rendering differences between Chrome and Firefox for ASCII art images: + +- **Pixel-Perfect Rendering**: Added comprehensive `image-rendering` CSS properties for consistent display across browsers +- **Cross-Browser Compatibility**: Implemented browser-specific rendering hints for Chrome, Firefox, Safari, and IE +- **Responsive Scaling**: Enhanced mobile responsiveness with proper pixel scaling for ASCII art +- **Performance Optimization**: Eliminated image interpolation artifacts that caused blurry ASCII art + +```css +img[alt="ascii-text-art-albatross"] { + width: 25% !important; + max-width: 40% !important; + /* Pixel-perfect rendering for ASCII art */ + image-rendering: pixelated !important; + image-rendering: -moz-crisp-edges !important; + image-rendering: crisp-edges !important; + image-rendering: -webkit-optimize-contrast !important; + -ms-interpolation-mode: nearest-neighbor !important; +} +``` + +### Production Deployment Security Hardening + +Major security improvements were implemented in the GitHub Actions deployment pipeline: + +#### **Fixed Script Injection Vulnerability** +The deployment pipeline was vulnerable to script injection through commit messages. This was resolved with comprehensive input sanitization: + +```bash +# Safely sanitize commit message to prevent injection +SAFE_COMMIT_MESSAGE="$( printf '%s' '${{ github.event.head_commit.message }}' | head -c 500 | tr -d '\0\r' | sed 's/[`$"\\]/\\&/g' )" +``` + +**Security Controls:** +- **Character Limiting**: Truncated to 500 characters to prevent excessive payloads +- **Dangerous Character Escaping**: Escaped backticks, dollar signs, quotes, and backslashes +- **Null Byte Removal**: Eliminated null characters and carriage returns +- **Command Injection Prevention**: Blocked all forms of command substitution and variable expansion + +#### **Enhanced Release Naming** +Improved GitHub release naming to match application build identifiers: + +- **Build Timestamp Format**: Uses the same `yyyyMMdd-HHmm` format displayed in the application +- **Short SHA Integration**: Includes 8-character commit SHA for unique identification +- **Consistent Versioning**: Release names now match internal build identifiers + +```yaml +RELEASE_NAME="${{ needs.build-and-deploy.outputs.build-timestamp }} (${{ needs.build-and-deploy.outputs.build-id }})" +# Example: "Albatross Build 20250719-1430 (a1b2c3d4)" +``` + +#### **Cloudflare Pages Production Deployment Fix** +Resolved deployment issues where builds were incorrectly deploying to preview environments: + +- **Removed Branch Parameters**: Eliminated `--branch` and `--production` flags that were causing deployment confusion +- **Default Production Behavior**: Leveraged Cloudflare Pages' default production deployment when no branch is specified +- **Simplified Command**: Streamlined deployment command for reliability + +```bash +# Simplified production deployment (deploys to production by default) +npx wrangler pages deploy ./dist/wwwroot --project-name ${{ secrets.CLOUDFLARE_PAGES_PROJECT }} +``` + +#### **Artifact Security Enhancement** +Improved release artifact handling to exclude sensitive files: + +- **Excluded Worker Files**: Prevented `cloudflare-worker.js` from being included in public releases +- **Security Logging**: Added clear audit trail showing which files are excluded and why +- **Compressed Archives**: Enhanced artifact upload with compressed directory archives +- **Selective Distribution**: Only includes safe artifacts (SPA files, build constants, version info) + +```bash +# Skip sensitive files during artifact upload +if [ -f "$file" ] && [ "$file" != "cloudflare-worker.js" ]; then + echo "Uploading file: $file" + gh release upload "${TAG_NAME}" "$file" +elif [ -f "$file" ] && [ "$file" = "cloudflare-worker.js" ]; then + echo "Skipping cloudflare-worker.js (contains sensitive data)" +fi +``` + +### Mobile Loading Screen Fix + +Addressed visual issues with the loading screen on mobile devices: + +- **Fixed Icon Stretching**: Resolved aspect ratio issues on mobile screens +- **Enhanced CSS Specificity**: Added `!important` declarations to prevent style conflicts +- **Responsive Sizing**: Proper scaling for different device sizes (80px desktop, 64px tablet, 48px mobile) +- **Conflict Resolution**: Changed alt text to prevent generic image style conflicts + +### Build System Reliability + +Multiple improvements to the build and deployment pipeline: + +- **Dependency Management**: Enhanced npm package handling in CI/CD +- **Error Handling**: Improved build script error detection and reporting +- **Version Consistency**: Aligned version numbering between application and releases +- **Deployment Validation**: Added verification steps for successful deployments + +## Recent Enhancements (June 2025) + +Since the initial release, Albatross has received several significant improvements that enhance both functionality and user experience: + +### Oracle Cloud Infrastructure (OCI) Support + +The most substantial addition is comprehensive **Oracle Cloud Infrastructure** support, making Albatross the first tool to provide unified IP range detection across all four major cloud providers: + +- **Complete Coverage**: Official OCI IP ranges from Oracle's public API +- **Regional Identification**: Detailed region and service tag information +- **Automatic Updates**: Integrated into the automated manifest update system +- **Enhanced Search**: Parallel searching across AWS, Azure, GCP, and OCI + +### Enhanced Data Structures + +The search functionality has been significantly improved with new **CloudMatch** objects: + +```csharp +public class CloudMatch +{ + public string ServiceName { get; set; } + public string Region { get; set; } + public string Provider { get; set; } + public string CidrRange { get; set; } + public List Tags { get; set; } +} +``` + +This structured approach provides: +- **Richer Metadata**: More detailed information about matched services +- **Consistent Interface**: Uniform data structure across all cloud providers +- **Better Performance**: Optimized search and display logic +- **Enhanced UX**: Improved visual presentation of results + +### ASN Integration with Cloudflare Radar + +New integration with **Cloudflare Radar API** provides Autonomous System Number (ASN) information: + +- **ASN Lookup**: Automatic ASN resolution for searched IP addresses +- **Organization Details**: Company and ISP information +- **Enhanced Context**: Additional intelligence for security analysis +- **Real-time Data**: Live ASN data from Cloudflare's global network + +### Improved User Interface + +The search results display has been enhanced with: +- **Visual Service Cards**: Better organized and styled result presentation +- **Provider Icons**: Clear visual identification of cloud providers +- **Enhanced Metadata**: More detailed service and regional information +- **Responsive Design**: Improved mobile and desktop experience + +### Build System Improvements + +Recent build system enhancements include: +- **Fixed Solution Build Issues**: Resolved `--output` parameter conflicts in CI/CD +- **Enhanced Logging**: Better debugging and deployment visibility +- **Improved Error Handling**: More robust build script error management +- **Streamlined Build Process**: Improved consistency across development and CI/CD environments + +### Enhanced Security and Input Validation (June 2025) + +Recent security and user experience improvements include: + +- **Public IP Validation**: Comprehensive validation that only accepts public routable IP addresses, blocking all private networks (10.x.x.x, 192.168.x.x, 172.16-31.x.x), loopback addresses (127.x.x.x), link-local, multicast, and other reserved ranges according to RFC standards +- **Improved Error Messaging**: Clear, user-friendly error messages explaining why certain IP addresses aren't accepted +- **Better UI Layout**: Fixed layout shifting issues during search operations with dedicated result containers +- **Enhanced User Guidance**: Updated placeholder text and help documentation to clarify IP address requirements +- **RFC Compliance**: Full compliance with RFC 1918 (Private Address Space), RFC 3927 (Link-Local), RFC 6598 (Carrier-Grade NAT), and other relevant networking standards ## Conclusion @@ -556,6 +846,14 @@ The complete source code for Albatross is available on GitHub, including: Whether you're building your own API proxy or exploring modern web security patterns, I hope Albatross serves as both inspiration and a practical reference for your next project. +## 📋 Changelog + +- **2025-07-19:** Major deployment and security update with static sitemap implementation, cross-browser ASCII art rendering fixes, script injection vulnerability patching, Cloudflare Pages production deployment fixes, mobile loading screen improvements, and enhanced release artifact security +- **2025-06-22:** Enhanced security with comprehensive public IP validation (RFC compliant), improved UI layout stability, better error messaging, and enhanced user guidance +- **2025-06-16:** Major update with Oracle Cloud Infrastructure support, enhanced CloudMatch data structures, ASN integration with Cloudflare Radar API, improved UI/UX, and build system fixes +- **2025-06-15:** Updated tag format and added changelog +- **2025-06-10:** Initial publication + --- -*Albatross is live at [https://albatross.devnomadic.com](https://albatross.devnomadic.com) and the source code is available on [GitHub](https://github.com/your-username/albatross).* \ No newline at end of file +**Albatross** is live at [https://albatross.devnomadic.com](https://albatross.devnomadic.com/) and the source code is available on [GitHub](https://github.com/devnomadic/albatross). \ No newline at end of file diff --git a/about.md b/about.md index 71b079d..fa320c8 100644 --- a/about.md +++ b/about.md @@ -26,8 +26,6 @@ This blog is where I share: Feel free to connect with me: - **GitHub**: [github.com/devnomadic](https://github.com/devnomadic) -- **Email**: hello@devnomadic.com +- **Email**: drew@devnomadic.com ---- - -*Currently coding from: [Current Location]* +--- \ No newline at end of file diff --git a/archive.md b/archive.md index aa99590..1f5d45f 100644 --- a/archive.md +++ b/archive.md @@ -6,14 +6,88 @@ permalink: /archive/ # Post Archive -{% for post in site.posts %} - {% assign currentdate = post.date | date: "%Y" %} - {% if currentdate != date %} - {% unless forloop.first %}{% endunless %} -

{{ currentdate }}

- {% endif %} +{% assign posts_by_year = site.posts | group_by_exp: "post", "post.date | date: '%Y'" %} +{% for year_group in posts_by_year %} +

{{ year_group.name }}

+ {% endfor %} + + diff --git a/assets/css/custom.css b/assets/css/custom.css index 7ce2dfa..add37db 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,47 +1,95 @@ /* Custom styles for devnomadic */ -/* Post tags styling */ +/* Keep theme's original green tag styling */ +.tag, .tag-cloud > a { + color: #50BD6A !important; + background-color: rgb(242.0163636364, 245.5254545455, 248.6836363636) !important; + padding: 0.3em 0.6em !important; + border-radius: 0.3em !important; + display: inline-block !important; + margin: 0.3em 0.3em 0.3em 0 !important; + text-decoration: none !important; +} + +.tag:hover, .tag-cloud > a:hover { + background-color: white !important; + color: rgb(154.0663900415, 216.9336099585, 169.0622406639) !important; + text-decoration: none !important; +} + +/* Keep Font Awesome icon for tags */ +.tag:before, .tag-cloud > a:before { + content: "\f02b" !important; + font-family: "Font Awesome 5 Free" !important; + font-weight: 900 !important; + margin-right: 0.5em !important; + display: inline !important; +} + +/* Post tags styling - also green */ .post-tags { margin: 0.5rem 0; } .post-tags .tag { - display: inline-block; - background-color: #f1f3f4; - color: #5f6368; - padding: 0.2rem 0.5rem; - margin: 0.1rem 0.2rem 0.1rem 0; - border-radius: 0.25rem; - font-size: 0.8rem; - text-decoration: none; - transition: background-color 0.2s ease; + color: #50BD6A !important; + background-color: rgb(242.0163636364, 245.5254545455, 248.6836363636) !important; + padding: 0.3em 0.6em !important; + border-radius: 0.3em !important; + display: inline-block !important; + margin: 0.3em 0.3em 0.3em 0 !important; + text-decoration: none !important; } .post-tags .tag:hover { - background-color: #e8eaed; - color: #202124; + background-color: white !important; + color: rgb(154.0663900415, 216.9336099585, 169.0622406639) !important; } -/* Tag cloud styling */ -.tag-cloud .tag-item { - display: inline-block; - margin: 0.2rem 0.5rem 0.2rem 0; +.post-tags .tag:before { + content: "\f02b" !important; + font-family: "Font Awesome 5 Free" !important; + font-weight: 900 !important; + margin-right: 0.5em !important; + display: inline !important; +} + +/* Tag posts styling for tags page */ +.tag-posts { + list-style: none; + padding: 0; + margin-bottom: 30px; } -.tag-cloud .tag-link { +.tag-posts li { + margin: 0.5rem 0; + padding: 0.75rem; background-color: #f8f9fa; - color: #5f6368; - padding: 0.3rem 0.6rem; - border-radius: 0.3rem; + border-radius: 0.25rem; + border-left: 3px solid #c94570; +} + +.tag-posts li a { + color: #c94570; text-decoration: none; + font-weight: 500; +} + +.tag-posts li a:hover { + text-decoration: underline; +} + +.post-date { + color: #5f6368; font-size: 0.9rem; - transition: all 0.2s ease; + display: block; + margin-top: 0.25rem; } -.tag-cloud .tag-link:hover { - background-color: #e8eaed; - color: #202124; - transform: translateY(-1px); +@media (max-width: 600px) { + .post-date { + font-size: 0.8em; + } } /* Post link wrapper styling */ @@ -66,3 +114,81 @@ color: #202124; line-height: 1.5; } + +/* TLDR section styling */ +.post-content h2:has(+ p):where(:contains("TL;DR"), :contains("TLDR")), +.post-content h2 + p:has-text("📝 TL;DR") { + background: linear-gradient(135deg, #f8f9ff 0%, #e8f2ff 100%); + border-left: 4px solid #4285f4; + padding: 1.5rem; + margin: 1.5rem 0; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +/* Alternative approach - target by content */ +.post-content > h2 + p:first-of-type, +.post-content h2 + p { + background: linear-gradient(135deg, #f8f9ff 0%, #e8f2ff 100%); + border-left: 4px solid #4285f4; + padding: 1.5rem; + margin: 1.5rem 0; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +/* TLDR heading style */ +.post-content h2:contains("TL;DR") { + color: #4285f4; + font-size: 1.1rem; + margin-bottom: 0.5rem; +} + +/* Navigation styling */ +.header-top { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1em; +} + +.site-nav { + display: block !important; + clear: both; + border-top: 1px solid rgba(255, 167, 196, 0.3); + padding-top: 0.75em; + margin-top: 0.5em; + width: 100%; +} + +.nav-link { + display: inline-block; + margin-right: 2em; + color: #ffa7c4 !important; + text-decoration: none; + font-size: 1em; + font-weight: 500; + transition: color 0.3s ease; +} + +.nav-link:hover { + color: #ffffff !important; + text-decoration: underline; +} + +@media (max-width: 768px) { + .header-top { + flex-direction: column; + align-items: flex-start; + } + + .social_links { + margin-top: 0.5em; + } + + .nav-link { + display: block; + margin-right: 0; + margin-bottom: 0.5em; + } +} diff --git a/mermaid-test.md b/mermaid-test.md new file mode 100644 index 0000000..e69de29 diff --git a/robots.txt b/robots.txt index edbfa90..0c2905f 100644 --- a/robots.txt +++ b/robots.txt @@ -11,4 +11,4 @@ Allow: /tag/ Allow: /blog/ # Sitemap location -Sitemap: https://devnomadic.github.io/sitemap.xml +Sitemap: https://devnomadic.com/sitemap.xml \ No newline at end of file diff --git a/staging/2025-06-10-test-staging-post.md b/staging/2025-06-10-test-staging-post.md new file mode 100644 index 0000000..21839e8 --- /dev/null +++ b/staging/2025-06-10-test-staging-post.md @@ -0,0 +1,34 @@ +--- +layout: post +title: "Test Staging Post" +date: 2025-06-10 12:00:00 -0500 +tags: [test, staging] +--- + +# Test Staging Post + +This is a test post that lives directly in the staging directory. + +## Purpose + +This post is used to test the staging preview system: + +- It's a real blog post with proper front matter +- It lives in the `staging/` directory +- It will be built as part of the staging collection +- It appears in the preview site + +## Content + +This is just sample content to verify that: + +1. Jekyll can build staging posts +2. The staging collection works +3. Posts appear in the preview deployment + +When this works, we know the staging system is functioning correctly! + +## 📋 Changelog + +- **2025-06-10:** Initial test post creation +- **2025-06-15:** Added changelog diff --git a/staging/index.md b/staging/index.md deleted file mode 100644 index cc07e6f..0000000 --- a/staging/index.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -layout: default -title: Staging Area -permalink: /staging/ ---- - -# 🚧 Staging Area - -This is where posts are staged for preview before going live. - -
- STAGING - Preview posts appear here before publication -
- -## Staged Posts - -
- {% if site.staging and site.staging.size > 0 %} - {% assign staging_posts = site.staging | sort: 'date' | reverse %} - {% for post in staging_posts %} -
- {{ post.title }} - -
- {% endfor %} - {% else %} -

No posts currently staged for preview.

- {% endif %} -
- -## Navigation - -- [← Back to main site](/) -- [About](/about/) -- [Archive](/archive/) - - diff --git a/tags.md b/tags.md index 77f1581..f699ba0 100644 --- a/tags.md +++ b/tags.md @@ -11,11 +11,9 @@ permalink: /tags/ {% for tag in tags %} {% assign tagname = tag[0] %} {% assign posts = tag[1] %} - - - {{ tagname }} ({{ posts.size }}) - - + + {{ tagname }} ({{ posts.size }}) + {% endfor %} @@ -38,59 +36,4 @@ permalink: /tags/ {% endfor %} - + \ No newline at end of file