<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Vietnamese Professional - CCNA Automation</title>
		<link>https://www.forum.vnpro.org/</link>
		<description />
		<language>vi</language>
		<lastBuildDate>Wed, 22 Jul 2026 13:30:41 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>60</ttl>
		<image>
			<url>images/misc/rss.png</url>
			<title>Vietnamese Professional - CCNA Automation</title>
			<link>https://www.forum.vnpro.org/</link>
		</image>
		<item>
			<title>Làm quen với Meraki Dashboard API bằng Postman</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/443121-làm-quen-với-meraki-dashboard-api-bằng-postman</link>
			<pubDate>Wed, 22 Jul 2026 10:21:36 GMT</pubDate>
			<description>Lần đầu tìm hiểu Cisco DevNet, từng nghĩ muốn tự động hóa hệ thống mạng thì phải học Python trước. 
 
Nhưng thực tế không hẳn như vậy. 
 
Trước khi...</description>
			<content:encoded><![CDATA[Lần đầu tìm hiểu Cisco DevNet, từng nghĩ muốn tự động hóa hệ thống mạng thì phải học Python trước.<br />
<br />
Nhưng thực tế không hẳn như vậy.<br />
<br />
Trước khi viết một dòng code, điều quan trọng là hiểu REST API hoạt động ra sao. Một chương trình Python cũng chỉ là gửi Request, nhận Response và xử lý dữ liệu trả về. Vì vậy, nếu thành thạo API với Postman, việc chuyển sang lập trình sẽ dễ dàng hơn rất nhiều.<br />
<br />
Trong bài lab này, sẽ sử dụng Postman để làm việc với Cisco Meraki Dashboard API, lần lượt truy xuất thông tin Organization → Network → Device → SSID, qua đó hiểu rõ cách các ứng dụng DevNet giao tiếp với hạ tầng Meraki Cloud.<br />
<br />
🛠 Các bước thực hiện<br />
<br />
Trước tiên, mình tạo một Environment trong Postman để lưu các biến dùng chung như:<br />
<br />
X-Cisco-Meraki-API-Key<br />
<br />
baseURL<br />
<br />
Việc sử dụng Environment giúp không phải nhập lại API Key cho từng Request và cũng là cách làm phổ biến trong các dự án thực tế.<br />
<br />
Tiếp theo, mình thực hiện lần lượt các API:<br />
<br />
Lấy danh sách Organization<br />
<br />
GET {{baseURL}}/organizations<br />
<br />
Nhận về danh sách Organization và lưu organizationId.<br />
<br />
Lấy danh sách Network<br />
<br />
GET {{baseURL}}/organizations/{{organizationId}}/networks<br />
<br />
Lưu tiếp networkId để sử dụng cho các Request sau.<br />
<br />
Lấy danh sách Device<br />
<br />
GET {{baseURL}}/networks/{{networkId}}/devices<br />
<br />
Response trả về gồm tên thiết bị, model, serial, MAC, firmware... Sau đó lưu serial của thiết bị.<br />
<br />
Truy xuất thông tin SSID<br />
<br />
Sử dụng serial để lấy danh sách SSID trên Access Point.<br />
<br />
Kết quả cho thấy gần như mọi thông tin hiển thị trên Meraki Dashboard đều có thể truy xuất thông qua REST API.<br />
<br />
✅ Kết quả đạt được<br />
<br />
Sau bài lab, mình đã:<br />
<br />
Kết nối thành công Postman với Cisco Meraki Dashboard API.<br />
<br />
Thực hiện các REST API Request theo tài liệu Cisco.<br />
<br />
Sử dụng Environment Variables để quản lý dữ liệu giữa các Request.<br />
<br />
Hiểu quy trình truy xuất dữ liệu theo mô hình Organization → Network → Device → SSID.<br />
<br />
Có nền tảng để tiếp tục tự động hóa bằng Python và các ứng dụng Cisco DevNet.<br />
<br />
💡 Tổng kết<br />
<br />
Điều mình thích nhất ở bài lab này là nó thay đổi cách nhìn về Network Automation. Tự động hóa không bắt đầu từ việc viết code, mà bắt đầu từ việc hiểu API. Khi đã biết cách gửi Request, đọc Response và khai thác dữ liệu từ Meraki Dashboard bằng Postman, việc chuyển sang Python chỉ còn là tự động hóa những thao tác đã thực hiện.<br />
<br />
Nếu đang bắt đầu với Cisco DevNet, mình nghĩ đây là một trong những bài lab đầu tiên rất đáng để trải nghiệm.<br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>ThanhTho</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/443121-làm-quen-với-meraki-dashboard-api-bằng-postman</guid>
		</item>
		<item>
			<title>Microservices và Container: Bộ đôi nền tảng của ứng dụng hiện đại</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442919-microservices-và-container-bộ-đôi-nền-tảng-của-ứng-dụng-hiện-đại</link>
			<pubDate>Mon, 20 Jul 2026 01:17:11 GMT</pubDate>
			<description>Microservices và Container: Bộ đôi nền tảng của ứng dụng hiện đại 
 
 
Muốn phát hành tính năng mới nhanh hơn? Muốn mở rộng hệ thống mà không phải...</description>
			<content:encoded><![CDATA[<b>Microservices và Container: Bộ đôi nền tảng của ứng dụng hiện đại</b><br />
<br />
<br />
Muốn phát hành tính năng mới nhanh hơn? Muốn mở rộng hệ thống mà không phải nâng cấp cả ứng dụng? Đây chính là lý do <b>Microservices</b> và <b>Container</b> trở thành nền tảng của hầu hết các hệ thống Cloud Native hiện nay.<br />
<br />
Từ Netflix, Amazon, Spotify cho đến các nền tảng thương mại điện tử lớn, hầu hết đều xây dựng hệ thống theo kiến trúc Microservices và triển khai bằng Container.<br />
<br />
<b>Microservice là gì?</b><br />
<br />
<br />
<b>Microservice</b> là một dịch vụ nhỏ, độc lập và liên kết lỏng lẻo (loosely coupled), thực hiện một chức năng nghiệp vụ cụ thể. Các dịch vụ giao tiếp với nhau thông qua mạng, phổ biến nhất là sử dụng <b>API</b>.<br />
<br />
Thay vì xây dựng toàn bộ ứng dụng thành một khối lớn (Monolith), hệ thống được chia thành nhiều dịch vụ nhỏ, mỗi dịch vụ đảm nhiệm một nhiệm vụ riêng.<br />
<br />
Ví dụ trong một website bán hàng:<ul><li>Search Service: Tìm kiếm sản phẩm.</li>
<li>Product Catalog Service: Quản lý danh mục sản phẩm.</li>
<li>Payment Service: Xử lý thanh toán.</li>
<li>Authentication Service: Xác thực người dùng.</li>
<li>Review Service: Quản lý đánh giá sản phẩm.</li>
</ul><br />
Nếu cần nâng cấp chức năng tìm kiếm, chỉ cần triển khai lại <b>Search Service</b> mà không ảnh hưởng đến các dịch vụ còn lại.  <hr /> <b>Ba đặc điểm nổi bật của Microservices</b><br />
<br />
<b>Modular</b><br />
<br />
<br />
Mỗi service chỉ tập trung giải quyết một chức năng nghiệp vụ cụ thể.<br />
<br />
Nhờ vậy code dễ đọc, dễ bảo trì và dễ phân chia công việc cho nhiều nhóm phát triển.<br />
<br />
<b>Independent</b><br />
<br />
<br />
Các service có thể:<ul><li>Phát triển độc lập.</li>
<li>Build độc lập.</li>
<li>Deploy độc lập.</li>
<li>Scale độc lập.</li>
</ul><br />
Đây là lợi thế rất lớn so với Monolith, nơi một thay đổi nhỏ thường yêu cầu build và triển khai lại toàn bộ ứng dụng.<br />
<br />
<b>Resilient</b><br />
<br />
<br />
Một lỗi trong một service không đồng nghĩa toàn bộ hệ thống sẽ ngừng hoạt động.<br />
<br />
Ví dụ, nếu <b>Review Service</b> gặp sự cố, khách hàng vẫn có thể:<ul><li>Đăng nhập.</li>
<li>Tìm kiếm sản phẩm.</li>
<li>Đặt hàng.</li>
<li>Thanh toán.</li>
</ul><br />
Hệ thống chỉ mất chức năng xem đánh giá sản phẩm thay vì dừng toàn bộ website. <hr /> <b>Vai trò của Container</b><br />
<br />
<br />
Microservices và Container gần như luôn đi cùng nhau.<br />
<br />
Container (Docker, Podman...) cung cấp môi trường chạy ứng dụng thống nhất, giúp mỗi service mang theo đầy đủ:<ul><li>Runtime</li>
<li>Library</li>
<li>Dependency</li>
<li>Cấu hình cần thiết</li>
</ul><br />
Điều này giúp service có thể chạy giống nhau trên:<ul><li>Máy lập trình viên</li>
<li>Môi trường kiểm thử</li>
<li>Máy chủ On-Premises</li>
<li>Cloud (AWS, Azure, Google Cloud)</li>
</ul><br />
Nhờ đó, bài toán &quot;chạy trên máy tôi thì bình thường&quot; (It works on my machine) được giảm thiểu đáng kể. <hr /> <b>Những ứng dụng phổ biến của Microservices</b><br />
<br />
<b>Cloud-native Applications</b><br />
<br />
<br />
Các ứng dụng được thiết kế ngay từ đầu để hoạt động trên nền tảng Cloud như:<ul><li>AWS</li>
<li>Microsoft Azure</li>
<li>Google Cloud Platform (GCP)</li>
</ul><br />
Mỗi service có thể mở rộng độc lập theo nhu cầu thực tế.<br />
<br />
<b>Enterprise Applications</b><br />
<br />
<br />
Các hệ thống doanh nghiệp lớn thường được chia thành nhiều dịch vụ như:<ul><li>Billing</li>
<li>Authentication</li>
<li>Inventory</li>
<li>Product Catalog</li>
<li>Customer Management</li>
</ul><br />
Việc tách nhỏ giúp các nhóm phát triển làm việc song song và giảm rủi ro khi triển khai.<br />
<br />
<b>E-commerce</b><br />
<br />
<br />
Đây là lĩnh vực ứng dụng Microservices phổ biến nhất.<br />
<br />
Một website thương mại điện tử có thể bao gồm:<ul><li>Search Service</li>
<li>Shopping Cart</li>
<li>Payment Service</li>
<li>Recommendation Engine</li>
<li>Review Service</li>
<li>Order Service</li>
</ul><br />
Mỗi thành phần có thể được nâng cấp hoặc mở rộng mà không ảnh hưởng đến toàn bộ hệ thống.<br />
<br />
<b>Streaming Platform</b><br />
<br />
<br />
Các nền tảng như <b>Netflix</b> là ví dụ điển hình.<br />
<br />
Những chức năng như:<ul><li>Video Playback</li>
<li>User Account</li>
<li>Recommendation Engine</li>
<li>Subtitle Service</li>
<li>Billing</li>
</ul><br />
đều vận hành dưới dạng các Microservice độc lập, cho phép cập nhật và mở rộng linh hoạt theo lượng người dùng. <hr /> <b>Góc nhìn DevOps</b><br />
<br />
<br />
Microservices không chỉ thay đổi cách viết phần mềm mà còn thay đổi toàn bộ cách triển khai và vận hành hệ thống.<br />
<br />
Một service nhỏ được đóng gói trong Container có thể được:<ul><li>Build tự động bằng CI/CD.</li>
<li>Triển khai lên Kubernetes.</li>
<li>Tự động mở rộng (Auto Scaling).</li>
<li>Tự động khôi phục khi gặp lỗi (Self-Healing).</li>
<li>Giám sát bằng Prometheus, Grafana hoặc các nền tảng quan sát (Observability) khác.</li>
</ul><br />
Đây chính là nền tảng của mô hình <b>Cloud Native</b>, nơi ứng dụng được thiết kế để tận dụng tối đa khả năng tự động hóa, mở rộng linh hoạt và tính sẵn sàng cao.<br />
<br />
📌 <b>Điểm cần nhớ:</b> Microservices giúp chia nhỏ ứng dụng theo chức năng nghiệp vụ, còn Container cung cấp môi trường chạy nhất quán cho từng service. Khi kết hợp với Kubernetes và CI/CD, chúng tạo nên một nền tảng hiện đại giúp doanh nghiệp phát triển phần mềm nhanh hơn, triển khai an toàn hơn và mở rộng hệ thống hiệu quả hơn.<br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>dangquangminh</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442919-microservices-và-container-bộ-đôi-nền-tảng-của-ứng-dụng-hiện-đại</guid>
		</item>
		<item>
			<title><![CDATA[CCNA Automation: Lộ trình Network Automation bằng Python &amp;amp; Cisco DevNet]]></title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442791-ccna-automation-lộ-trình-network-automation-bằng-python-cisco-devnet</link>
			<pubDate>Thu, 16 Jul 2026 07:57:30 GMT</pubDate>
			<description><![CDATA[CCNA Automation: Lộ trình Network Automation bằng Python &amp; Cisco DevNet  
 
Nếu anh em đã xong CCNA 200-301 hoặc có nền mạng Cisco rồi, bước tiếp...]]></description>
			<content:encoded><![CDATA[<b><b><b>CCNA Automation</b></b>: Lộ trình <b><b>Network Automation</b></b> bằng <b><b>Python &amp; Cisco DevNet </b></b></b><br />
<br />
Nếu anh em đã xong<b><b> CCNA 200-301 </b></b>hoặc có <b><b>nền mạng Cisco</b></b> rồi, bước tiếp theo không nên là <b><b>“học thêm lệnh”</b></b>. Thứ cần là <b><b>biến kiến thức mạng thành quy trình tự động</b></b>.<br />
<br />
<b><b>Lộ trình CCNA Automation</b></b> (Network Automation with Python &amp; Cisco DevNet) được thiết kế đúng hướng:<div style="margin-left:40px"><b><b>API → Python → lab → automation hạ tầng → testing/security</b></b>.</div> <b>1) API và dữ liệu: học để “nói chuyện đúng ngôn ngữ”:</b><br />
<br />
Trong schedule có các phần như:<ul><li>Rise of API in Software Design + <b><b>API Data Format</b></b></li>
<li><b><b>Serialization / De-Serialization</b></b></li>
</ul>Nghe lý thuyết nhưng thực tế là:<b><b> automation</b></b> bắt đầu từ việc gửi/nhận dữ liệu.<br />
<br />
<b><b>Ví dụ thực tế:</b></b><br />
Anh em viết script để lấy thông tin thiết bị qua API. Nếu <b><b>payload</b></b> gửi lên <b><b>sai format</b></b> hoặc<b><b> response</b></b> không parse đúng kiểu dữ liệu thì:<ul><li>Request có thể “vẫn chạy” nhưng không đúng dữ liệu</li>
<li>Hoặc trả về response mà code không đọc được</li>
</ul>Nắm phần<b><b> Data Format + serialization</b></b> là để tránh lỗi kiểu đó ngay từ đầu. <b>2) Linux + Git + quy trình làm phần mềm: để code có thể vận hành thật:</b><br />
<br />
Schedule có:<ul><li>Linux cơ bản (LT + thực hành)</li>
<li>Git (version control + lab Git/GitHub)</li>
<li>Methodologies + Modular Design + <b><b>Test-Driven Development</b></b> + Code Review</li>
</ul><b><b>Ví dụ thực tế:</b></b><br />
Anh em đang sửa automation, chạy lỗi. Nếu không có Git:<ul><li>không biết thay đổi nào làm hỏng</li>
<li>không revert nhanh được</li>
</ul>Git giúp anh em “quản trị code” như quản trị cấu hình: có lịch sử, có rollback. <b>3) Python “đúng phần việc” của network automation: từ file dữ liệu đến NETMIKO:</b><br />
<br />
Schedule có:<ul><li>Python cơ bản (variables, syntax, <b><b>data formats</b></b>, files)</li>
<li>Lab: <b><b>Python netmiko</b></b></li>
</ul><b><b>Ví dụ thực tế:</b></b><br />
Thay vì đăng nhập SSH thủ công mỗi lần kiểm tra trạng thái interface, anh em làm script:<ul><li>Đọc danh sách thiết bị từ file</li>
<li>Chạy show command theo chuẩn</li>
<li>Gom output thành dạng dễ báo cáo</li>
</ul>Đúng kiểu automation mà đi làm mới dùng liên tục. <b>4) HTTP/REST + Postman + Webhook: test nhanh trước khi code</b><br />
<br />
Schedule gồm:<ul><li>HTTP Protocol Overview + inspect HTTP messages</li>
<li>REST API, RPC-style</li>
<li>Postman for REST-API (Lab)</li>
<li>Webhook (Lab)</li>
</ul><b><b>Ví dụ thực tế:</b></b><br />
Trước khi viết <b><b>Python call REST API</b></b>, anh em test bằng Postman:<ul><li>Đúng endpoint chưa</li>
<li>Đúng payload chưa</li>
<li>Response có đúng structure để parse không</li>
</ul>Webhook thì dùng khi cần<b><b> “event-driven”</b></b> (hệ thống có thay đổi thì gửi callback để automation xử lý). <b>5) Ansible, CI/CD, Unit Test và Security: để automation không chỉ chạy mà còn an toàn</b><br />
<br />
Schedule có:<ul><li>Dockers (lab)</li>
<li>Ansible (Infrastructure as Code, system management, playbook)</li>
<li>Lab vlan trunking / HSRP / VxLAN + variables</li>
<li>Lab <b><b>CI/CD với Ansible và Jenkins</b></b></li>
<li>Unit Test + Application Security (input sanitization, SQL security)</li>
<li>Final lab/test</li>
</ul><b><b>Ví dụ thực tế:</b></b><br />
<b><b>Playbook Ansible</b></b> triển khai <b><b>VLAN/HSRP/VxLAN</b></b> xong mà không test: lần sau sửa nhỏ có thể gây lỗi dây chuyền. <b><b>Unit test + CI/CD</b></b> giúp pipeline kiểm tra trước khi deploy.<br />
<br />
👇Anh em nào quan tâm lộ trình này thì <b><b>tranh thủ đăng ký để kịp lớp khai giảng sắp tới</b></b>.<br />
<br />
Liên hệ: Hotline/zalo: <b><b>076 5944 386 (Ms. Như Ngọc)</b></b><br />
Email: <a href="mailto:nhungoc@vnpro.org"><b><b>nhungoc@vnpro.org</b></b></a><br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>Cẩm Thanh</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442791-ccna-automation-lộ-trình-network-automation-bằng-python-cisco-devnet</guid>
		</item>
		<item>
			<title>🚀 Sử dụng Postman lấy Token và danh sách thiết bị từ Cisco DNA Center</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442722-🚀-sử-dụng-postman-lấy-token-và-danh-sách-thiết-bị-từ-cisco-dna-center</link>
			<pubDate>Wed, 15 Jul 2026 03:33:49 GMT</pubDate>
			<description>Làm sao để lấy danh sách toàn bộ thiết bị trong hệ thống mà không cần SSH vào từng Router hoặc Switch? 
 
Đó chính là lúc API và Cisco DNA Center...</description>
			<content:encoded><![CDATA[Làm sao để lấy danh sách toàn bộ thiết bị trong hệ thống mà không cần SSH vào từng Router hoặc Switch?<br />
<br />
Đó chính là lúc API và Cisco DNA Center phát huy sức mạnh.<br />
<br />
Trong bài lab này, mình sử dụng Postman để kết nối đến Cisco DNA Center Sandbox, thực hiện lấy Token xác thực và truy vấn danh sách thiết bị đang được quản lý trên hệ thống thông qua REST API. <b>Bước 1: Lấy Authentication Token</b><br />
<br />
<br />
Đầu tiên tạo một Request mới trên Postman với các thông số:<br />
<br />
<b><b>Method</b></b><br />
<br />
POST<br />
<br />
<b><b>URL</b></b><br />
<br />
<a href="https://sandboxdnac.cisco.com/dna/system/api/v1/auth/token" target="_blank">https://sandboxdnac.cisco.com/dna/sy.../v1/auth/token</a><br />
<br />
<br />
<b><b>Authentication</b></b><br />
<br />
Username: devnetuser<br />
Password: Cisco123!<br />
<br />
<br />
Sau khi nhấn <b><b>Send</b></b>, nếu gặp lỗi SSL có thể vào:<br />
<br />
Settings -&gt; Disable SSL Certificate Verification<br />
<br />
<br />
Khi xác thực thành công, DNA Center sẽ trả về Token dưới dạng JSON:<br />
<br />
{<br />
&quot;Token&quot;: &quot;eyJhbGciOi...&quot;<br />
}<br />
<br />
<br />
Đây sẽ là thông tin xác thực được sử dụng cho tất cả các API tiếp theo. <b>Bước 2: Lấy danh sách thiết bị từ DNA Center</b><br />
<br />
<br />
Tiếp tục tạo một Request mới với các thông số:<br />
<br />
<b><b>Method</b></b><br />
<br />
GET<br />
<br />
<b><b>URL</b></b><br />
<br />
<a href="https://sandboxdnac.cisco.com/dna/intent/api/v1/network-device" target="_blank">https://sandboxdnac.cisco.com/dna/in...network-device</a><br />
<br />
<br />
Thêm Header:<br />
<br />
Key:<br />
X-Auth-Token<br />
<br />
Value:<br />
&lt;Token lấy được ở bước trước&gt;<br />
<br />
<br />
Ví dụ:<br />
<br />
X-Auth-Token: eyJhbGciOi...<br />
<br />
<br />
Sau đó nhấn <b><b>Send</b></b> để thực hiện truy vấn. <b>Kết quả nhận được</b><br />
<br />
<br />
DNA Center sẽ trả về danh sách các thiết bị đang được quản lý dưới dạng JSON:<br />
<br />
{<br />
&quot;response&quot;: [<br />
{<br />
&quot;hostname&quot;: &quot;leaf1&quot;,<br />
&quot;managementIpAddress&quot;: &quot;10.10.20.81&quot;,<br />
&quot;platformId&quot;: &quot;C9300&quot;,<br />
&quot;softwareVersion&quot;: &quot;17.3.3&quot;<br />
},<br />
{<br />
&quot;hostname&quot;: &quot;leaf2&quot;,<br />
&quot;managementIpAddress&quot;: &quot;10.10.20.82&quot;,<br />
&quot;platformId&quot;: &quot;C9300&quot;,<br />
&quot;softwareVersion&quot;: &quot;17.3.3&quot;<br />
}<br />
]<br />
}<br />
<br />
<br />
Từ dữ liệu này chúng ta có thể dễ dàng lấy được:<br />
<br />
✅ Hostname thiết bị<br />
✅ Địa chỉ IP quản trị<br />
✅ Model thiết bị<br />
✅ Phiên bản IOS-XE đang sử dụng<br />
✅ Thông tin phục vụ Inventory và Automation<br />
<br />
Đây cũng chính là nền tảng cho các bài lab DevNet nâng cao hơn như sử dụng Python Requests để gọi API, tự động thu thập thông tin thiết bị hoặc xây dựng các workflow Network Automation trong môi trường doanh nghiệp.<br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>ThanhTho</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442722-🚀-sử-dụng-postman-lấy-token-và-danh-sách-thiết-bị-từ-cisco-dna-center</guid>
		</item>
		<item>
			<title>Lab - Kết nối Cisco APIC-EM bằng Postman để lấy Ticket và danh sách thiết bị</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442632-lab-kết-nối-cisco-apic-em-bằng-postman-để-lấy-ticket-và-danh-sách-thiết-bị</link>
			<pubDate>Mon, 13 Jul 2026 02:18:06 GMT</pubDate>
			<description>Trong bài lab này sẽ thực hiện việc kết nối tới Cisco APIC-EM thông qua REST API bằng công cụ Postman. Mục tiêu là xác thực với hệ thống để lấy...</description>
			<content:encoded><![CDATA[Trong bài lab này sẽ thực hiện việc kết nối tới Cisco APIC-EM thông qua REST API bằng công cụ Postman. Mục tiêu là xác thực với hệ thống để lấy Authentication Token (Ticket), sau đó sử dụng Ticket này để gọi API và lấy danh sách các thiết bị đang được APIC-EM quản lý.<br />
<br />
Đây là một trong những bài lab nền tảng của DevNet giúp làm quen với quy trình làm việc phổ biến của REST API:<br />
<br />
<b><b>Authentication → Nhận Token → Gọi API → Xử lý dữ liệu trả về</b></b> <b>Mô hình sử dụng</b><ul><li>Cisco APIC-EM Server</li>
<li>Máy tính cài Postman</li>
<li>Kết nối mạng giữa Postman và APIC-EM</li>
</ul><b>Bước 1: Tạo Workspace và Collection trên Postman</b><br />
<br />
Sau khi mở Postman, mình tạo một Workspace riêng để quản lý các API của APIC-EM.<br />
<br />
Tiếp theo tạo một Collection mới với tên:<br />
<br />
APIC_EM<br />
<br />
Việc sử dụng Collection giúp quản lý các request dễ dàng hơn khi số lượng API ngày càng nhiều trong các bài lab DevNet sau này. <b>Bước 2: Lấy Ticket xác thực từ APIC-EM</b><br />
<br />
<br />
Tạo một Request mới với phương thức:<br />
<br />
POST<br />
<br />
URL sử dụng:<br />
<br />
http://&lt;IP_APIC_EM&gt;/api/v1/ticket<br />
<br />
Trong tab <b><b>Headers</b></b>, thêm:<br />
<br />
Key : Content-Type<br />
<br />
Value : application/json<br />
<br />
Trong tab <b><b>Body</b></b>, chọn:<br />
<br />
raw -&gt; JSON<br />
<br />
Sau đó nhập thông tin đăng nhập:<br />
<br />
{<br />
&quot;username&quot;: &quot;admin&quot;,<br />
&quot;password&quot;: &quot;Cisco123!&quot;<br />
}<br />
<br />
Nhấn <b><b>Send</b></b> để gửi request.<br />
<br />
Nếu mọi thứ chính xác, APIC-EM sẽ trả về:<br />
<br />
{<br />
&quot;response&quot;: {<br />
&quot;serviceTicket&quot;: &quot;ST-xxxxxxxxxxxxxxxx&quot;<br />
}<br />
}<br />
<br />
Giá trị serviceTicket chính là Token dùng để xác thực các API tiếp theo. <b>Kinh nghiệm thực tế</b><br />
<br />
<br />
Trong quá trình làm lab mình từng gặp lỗi SSL khiến Postman không gửi được request. Nếu gặp tình huống này có thể vào:<br />
<br />
File -&gt; Settings -&gt; General<br />
<br />
và tắt:<br />
<br />
SSL certificate verification<br />
<br />
Sau đó gửi lại request sẽ hoạt động bình thường. <b>Bước 3: Lấy danh sách thiết bị từ APIC-EM</b><br />
<br />
<br />
Sau khi đã có Ticket, tạo thêm một request mới với tên:<br />
<br />
Get_list_device<br />
<br />
Đổi phương thức sang:<br />
<br />
GET<br />
<br />
URL:<br />
<br />
http://&lt;IP_APIC_EM&gt;/api/v1/network-device<br />
<br />
Trong phần <b><b>Headers</b></b>, thêm:<br />
<br />
Key : X-Auth-Token<br />
<br />
Value : Giá trị serviceTicket vừa lấy<br />
<br />
Ví dụ:<br />
<br />
X-Auth-Token: ST-1099-xxxxxxxxxxxxxxxx<br />
<br />
Nhấn <b><b>Send</b></b>.<br />
<br />
Nếu Ticket còn hiệu lực, APIC-EM sẽ trả về danh sách toàn bộ thiết bị đang được quản lý bao gồm:<ul><li>Hostname</li>
<li>Địa chỉ IP</li>
<li>Platform</li>
<li>Phiên bản IOS</li>
<li>Trạng thái hoạt động</li>
<li>Serial Number</li>
</ul>Dữ liệu trả về ở định dạng JSON nên rất thuận tiện để xử lý bằng Python trong các bài DevNet Automation tiếp theo.<br />
<br />
Đây là một bài lab cơ bản nhưng cực kỳ quan trọng vì gần như mọi nền tảng quản trị mạng hiện đại như Cisco DNA Center, Meraki Dashboard hay Cisco SD-WAN vManage đều sử dụng cơ chế xác thực và gọi API tương tự.<br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>ThanhTho</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442632-lab-kết-nối-cisco-apic-em-bằng-postman-để-lấy-ticket-và-danh-sách-thiết-bị</guid>
		</item>
		<item>
			<title>Lab - Phát hiện và xử lý các lỗi liên quan đến HTTP Request bằng Postman</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442568-lab-phát-hiện-và-xử-lý-các-lỗi-liên-quan-đến-http-request-bằng-postman</link>
			<pubDate>Sat, 11 Jul 2026 02:44:17 GMT</pubDate>
			<description>Mục tiêu bài lab 
 
 
Sau khi hoàn thành bài thực hành này, bạn sẽ có khả năng: 
 
 Sử dụng lại Collection và Environment trong Postman. 
 Đọc và...</description>
			<content:encoded><![CDATA[<br />
<b>Mục tiêu bài lab</b><br />
<br />
<br />
Sau khi hoàn thành bài thực hành này, bạn sẽ có khả năng:<ul><li>Sử dụng lại Collection và Environment trong Postman.</li>
<li>Đọc và phân tích thông tin lỗi từ API Response.</li>
<li>Xác định nguyên nhân khiến HTTP Request thất bại.</li>
<li>Khắc phục các lỗi phổ biến khi làm việc với REST API.</li>
</ul><br />
Đây là kỹ năng gần như bắt buộc đối với một kỹ sư DevNet bởi trong môi trường thực tế, lỗi API xảy ra hàng ngày và việc đọc được thông báo lỗi sẽ giúp tiết kiệm rất nhiều thời gian troubleshooting.<br />
<br />
<br />
<b>Mô hình bài lab</b><br />
<br />
<br />
Trong bài lab này chúng ta tiếp tục sử dụng:<ul><li>Postman Client</li>
<li>API Server đã sử dụng ở Lab 8</li>
<li>Collection và Environment đã tạo trước đó</li>
</ul><br />
Luồng hoạt động:<br />
<br />
Postman<br />
|<br />
HTTP Request<br />
|<br />
API Server<br />
|<br />
HTTP Response (Success hoặc Error)<br />
<br />
<b><b>Bước 1: Import Collection và Environment</b></b><br />
<br />
Trong thực tế, kỹ sư DevNet rất ít khi tạo request từ đầu cho từng API.<br />
<br />
Thông thường đội dự án sẽ chia sẻ sẵn:<ul><li>Collection</li>
<li>Environment</li>
<li>API Documentation</li>
</ul><br />
Do đó việc đầu tiên là import các file này vào Postman.<br />
<br />
Chọn:<br />
<br />
Import<br />
<br />
sau đó import:<ul><li>Collection JSON</li>
<li>Environment JSON</li>
</ul><br />
<b><b>Tại sao phải sử dụng Environment?</b></b><br />
<br />
Khi làm việc với API chúng ta thường phải sử dụng nhiều giá trị như:<br />
<br />
IP Address<br />
Username<br />
Password<br />
Token<br />
Base URL<br />
Port<br />
<br />
Nếu phải gõ thủ công mỗi lần sẽ rất dễ sai.<br />
<br />
Ví dụ:<br />
<br />
{{base_url}}<br />
{{token}}<br />
{{username}}<br />
<br />
Khi cần thay đổi IP hoặc Token chúng ta chỉ sửa trong Environment thay vì sửa hàng chục request khác nhau.<br />
<br />
Đây là cách mà hầu hết các dự án DevNet thực tế đều triển khai.<br />
<br />
<b><b>Tại sao phải sử dụng Collection?</b></b><br />
<br />
Collection giúp:<ul><li>Gom nhóm các API cùng chức năng.</li>
<li>Tái sử dụng request.</li>
<li>Chạy automation test.</li>
<li>Chia sẻ giữa các thành viên trong nhóm.</li>
</ul><br />
Ví dụ:<br />
<br />
Authentication<br />
Get Devices<br />
Get Interfaces<br />
Create VLAN<br />
Delete VLAN<br />
<br />
Tất cả đều có thể đặt trong cùng một Collection.<br />
<br />
<b><b>Bước 2: Thực hiện Request có lỗi</b></b><br />
<br />
Tiến hành gửi request chứa dữ liệu JSON sai cú pháp.<br />
<br />
Ví dụ:<br />
<br />
{<br />
&quot;name&quot; = &quot;VNPRO&quot;<br />
}<br />
<br />
Sau khi nhấn:<br />
<br />
Send<br />
<br />
API Server sẽ trả về lỗi.<br />
<br />
<b><b>Bước 3: Phân tích Response trả về</b></b><br />
<br />
Đây là phần quan trọng nhất của bài lab.<br />
<br />
Khi request thất bại, điều đầu tiên cần làm là đọc phần:<br />
<br />
Response Body<br />
Status Code<br />
Details<br />
<br />
Trong bài lab này Postman sẽ hiển thị thông báo lỗi chỉ ra vị trí sai cú pháp.<br />
<br />
Thông thường bạn sẽ thấy dạng:<br />
<br />
JSON parse error<br />
Unexpected token '='<br />
<br />
hoặc:<br />
<br />
Expecting ':' delimiter <b>Nguyên nhân lỗi</b><br />
<br />
<br />
JSON sử dụng:<br />
<br />
:<br />
<br />
để phân tách giữa:<br />
<br />
key và value<br />
<br />
Ví dụ đúng:<br />
<br />
{<br />
&quot;name&quot;: &quot;VNPRO&quot;<br />
}<br />
<br />
Ví dụ sai:<br />
<br />
{<br />
&quot;name&quot; = &quot;VNPRO&quot;<br />
}<br />
<br />
Đây là lỗi mà hầu như ai mới học API cũng từng gặp.<br />
<br />
<b><b>Bước 4: Kiểm tra vị trí lỗi trong Body</b></b><br />
<br />
Một điểm rất hữu ích của Postman là nó sẽ đánh dấu chính xác dòng bị lỗi.<br />
<br />
Ví dụ:<br />
<br />
Line 3<br />
<br />
sẽ xuất hiện dấu:<br />
<br />
X<br />
<br />
ở bên trái.<br />
<br />
Điều này giúp chúng ta không phải dò toàn bộ JSON.<br />
<br />
<b><b>Các lỗi HTTP Request thường gặp trong DevNet</b></b> <b>1. Thiếu dấu phẩy giữa các cặp key-value</b><br />
<br />
Sai:<br />
<br />
{<br />
&quot;name&quot;: &quot;VNPRO&quot;<br />
&quot;city&quot;: &quot;HCM&quot;<br />
}<br />
<br />
Đúng:<br />
<br />
{<br />
&quot;name&quot;: &quot;VNPRO&quot;,<br />
&quot;city&quot;: &quot;HCM&quot;<br />
}<br />
<br />
<br />
<b>2. URL bị dư dấu &quot;/&quot;</b><br />
<br />
Sai:<br />
<br />
<a href="http://10.10.20.50//api/v1/device" target="_blank">http://10.10.20.50//api/v1/device</a><br />
<br />
Đúng:<br />
<br />
<a href="http://10.10.20.50/api/v1/device" target="_blank">http://10.10.20.50/api/v1/device</a><br />
<br />
Một số API Server vẫn chấp nhận lỗi này nhưng nhiều hệ thống sẽ trả về:<br />
<br />
404 Not Found<br />
<br />
<b>3. Sử dụng sai HTTP Method</b><br />
<br />
Ví dụ:<br />
<br />
API yêu cầu:<br />
<br />
POST<br />
<br />
nhưng lại gửi:<br />
<br />
GET<br />
<br />
hoặc:<br />
<br />
PUT<br />
<br />
Kết quả thường nhận được:<br />
<br />
405 Method Not Allowed<br />
<br />
Ví dụ:<br />
<br />
GET /api/users<br />
<br />
trong khi API chỉ hỗ trợ:<br />
<br />
POST /api/users<br />
<br />
<b>4. Thiếu Authentication Token</b><br />
<br />
Đây là lỗi xảy ra nhiều nhất khi làm việc với Cisco DNA Center API.<br />
<br />
Ví dụ:<br />
<br />
401 Unauthorized<br />
<br />
Nguyên nhân:<ul><li>Token hết hạn.</li>
<li>Chưa truyền Header Authorization.</li>
<li>Sai Bearer Token.</li>
</ul><b>5. Sai Header Content-Type</b><br />
<br />
<br />
Ví dụ API yêu cầu:<br />
<br />
Content-Type: application/json<br />
<br />
nhưng request gửi:<br />
<br />
text/plain<br />
<br />
Kết quả:<br />
<br />
415 Unsupported Media Type<br />
<br />
<b><b>Bước 5: Khắc phục lỗi</b></b><br />
<br />
Sau khi xác định được nguyên nhân, sửa lại request theo đúng cú pháp JSON và gửi lại.<br />
<br />
Ví dụ:<br />
<br />
{<br />
&quot;name&quot;: &quot;VNPRO&quot;<br />
}<br />
<br />
Khi thực hiện thành công, Postman sẽ trả về:<br />
<br />
200 OK<br />
<br />
hoặc:<br />
<br />
201 Created <b>Kinh nghiệm thực tế khi làm DevNet</b><br />
<br />
<br />
Kiểm tra theo thứ tự sau khi request bị lỗi:<ol class="decimal"><li>Kiểm tra URL.</li>
<li>Kiểm tra HTTP Method.</li>
<li>Kiểm tra Header.</li>
<li>Kiểm tra Token.</li>
<li>Kiểm tra Body JSON.</li>
<li>Đọc kỹ Response trả về.</li>
</ol><br />
Khoảng 80% lỗi API thường nằm trong các nguyên nhân trên.<br />
<br />
<br />
<br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>ThanhTho</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442568-lab-phát-hiện-và-xử-lý-các-lỗi-liên-quan-đến-http-request-bằng-postman</guid>
		</item>
		<item>
			<title>LAB Khai thác điểm yếu thông số đầu vào để truy cập dữ liệu nhạy cảm trong Flask Python</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442545-lab-khai-thác-điểm-yếu-thông-số-đầu-vào-để-truy-cập-dữ-liệu-nhạy-cảm-trong-flask-python</link>
			<pubDate>Fri, 10 Jul 2026 08:27:15 GMT</pubDate>
			<description>Mục tiêu bài lab 
 
Trong quá trình phát triển API và ứng dụng Web bằng Python Flask, việc tin tưởng hoàn toàn vào dữ liệu đầu vào từ người dùng là...</description>
			<content:encoded><![CDATA[Mục tiêu bài lab<br />
<br />
Trong quá trình phát triển API và ứng dụng Web bằng Python Flask, việc tin tưởng hoàn toàn vào dữ liệu đầu vào từ người dùng là một trong những nguyên nhân phổ biến dẫn đến các lỗ hổng bảo mật nghiêm trọng.<br />
<br />
<br />
Trong bài lab sẽ xây dựng một API đơn giản cho phép người dùng đọc nội dung của file thông qua tham số filename. Sau đó tiến hành khai thác lỗ hổng để truy cập trái phép vào dữ liệu nhạy cảm và cuối cùng triển khai cơ chế kiểm tra đầu vào nhằm ngăn chặn tấn công.<br />
<br />
Sau khi hoàn thành bài lab, chúng ta sẽ hiểu rõ:<br />
<br />
Nguyên nhân gây ra lỗ hổng Directory Traversal.<br />
<br />
Cách hacker khai thác tham số đầu vào không được kiểm tra.<br />
<br />
Cách bảo vệ ứng dụng Flask bằng Input Validation.<br />
<br />
Tư duy Secure Coding trong quá trình phát triển API.<br />
<br />
<br />
Mô hình bài lab<br />
<br />
User Browser<br />
<br />
|<br />
<br />
HTTP Request<br />
<br />
|<br />
<br />
Flask API Server<br />
<br />
|<br />
<br />
+--- welcome.txt<br />
<br />
|<br />
<br />
+--- passwords.txt<br />
<br />
<br />
Ứng dụng Flask cung cấp API:<br />
<br />
http://127.0.0.1:5000/get_file?filename=&lt;ten_file&gt;<br />
<br />
API sẽ đọc nội dung file và trả kết quả trực tiếp lên trình duyệt.<br />
<br />
<b><b>Bước 1: Cài đặt Flask</b></b><br />
<br />
Mở CMD hoặc Terminal:<br />
<br />
py -m pip install flask<br />
<br />
Kiểm tra cài đặt:<br />
<br />
pip show flask<br />
<br />
Nếu hiển thị thông tin package nghĩa là Flask đã được cài đặt thành công.<br />
<br />
<b><b>Bước 2: Tạo ứng dụng Flask đầu tiên</b></b><br />
<br />
Tạo thư mục:<br />
<br />
Flask-Lab<br />
<br />
Tạo file:<br />
<br />
app.py<br />
<br />
Nội dung:<br />
<br />
from flask import Flask<br />
<br />
app = Flask(__name__)<br />
<br />
@app.route('/')<br />
<br />
def home():<br />
<br />
return &quot;Home Page&quot;<br />
<br />
if __name__ == &quot;__main__&quot;:<br />
<br />
app.run(host=&quot;127.0.0.1&quot;, port=5000)<br />
<br />
Khởi động ứng dụng:<br />
<br />
python app.py<br />
<br />
Truy cập:<br />
<br />
<a href="http://127.0.0.1:5000" target="_blank">http://127.0.0.1:5000</a><br />
<br />
Nếu trình duyệt hiển thị:<br />
<br />
Home Page<br />
<br />
thì môi trường lab đã sẵn sàng.<br />
<br />
<b><b>Bước 3: Xây dựng API đọc file</b></b><br />
<br />
Sửa file app.py:<br />
<br />
from flask import Flask, request<br />
<br />
app = Flask(__name__)<br />
<br />
@app.route('/get_file', methods=['GET'])<br />
<br />
def get_file():<br />
<br />
filename = request.args['filename']<br />
<br />
return '''<br />
<br />
Content of file {}:<br />
<br />
{}<br />
<br />
'''.format(filename, cat(filename))<br />
<br />
def cat(filename):<br />
<br />
with open(filename) as file:<br />
<br />
data = file.read()<br />
<br />
return data<br />
<br />
if __name__ == &quot;__main__&quot;:<br />
<br />
app.run(host=&quot;127.0.0.1&quot;, port=5000)<br />
<br />
Bước 4: Chuẩn bị dữ liệu cho bài lab<br />
<br />
Trong thư mục chứa app.py, tạo file:<br />
<br />
welcome.txt<br />
<br />
Hello student<br />
<br />
Đây là dữ liệu bình thường được phép truy cập.<br />
<br />
Tạo tiếp file:<br />
<br />
passwords.txt<br />
<br />
username=cisco<br />
<br />
password=cisco<br />
<br />
Đây là dữ liệu nhạy cảm và không được phép công khai cho người dùng cuối.<br />
<br />
<b><b>Bước 5: Kiểm tra hoạt động của API</b></b><br />
<br />
Đọc file welcome:<br />
<br />
<a href="http://127.0.0.1:5000/get_file?filename=welcome.txt" target="_blank">http://127.0.0.1:5000/get_file?filename=welcome.txt</a><br />
<br />
<br />
Kết quả:<br />
<br />
Content of file welcome.txt:<br />
<br />
Hello student<br />
<br />
API hoạt động đúng như thiết kế.<br />
<br />
<b><b>Bước 6: Thử truy cập dữ liệu nhạy cảm</b></b><br />
<br />
Thay đổi URL:<br />
<br />
<a href="http://127.0.0.1:5000/get_file?filename=passwords.txt" target="_blank">http://127.0.0.1:5000/get_file?filename=passwords.txt</a><br />
<br />
<br />
Kết quả:<br />
<br />
username=cisco<br />
<br />
password=cisco<br />
<br />
Lúc này chúng ta phát hiện ứng dụng không kiểm tra dữ liệu đầu vào và cho phép người dùng đọc bất kỳ file nào mà tiến trình Flask có quyền truy cập.<br />
<br />
Đây chính là dấu hiệu đầu tiên của lỗ hổng bảo mật.<br />
<br />
<b><b>Bước 7: Khai thác Directory Traversal</b></b><br />
<br />
Để mô phỏng tình huống thực tế hơn, di chuyển file:<br />
<br />
passwords.txt<br />
<br />
ra thư mục cha của ứng dụng Flask.<br />
<br />
Ví dụ:<br />
<br />
Lab<br />
<br />
│<br />
<br />
├── passwords.txt<br />
<br />
│<br />
<br />
└── Flask-Lab<br />
<br />
├── app.py<br />
<br />
└── welcome.txt<br />
<br />
Thông thường lập trình viên sẽ nghĩ rằng việc đặt file ra ngoài thư mục ứng dụng là đủ an toàn.<br />
<br />
Tuy nhiên thực tế không phải vậy.<br />
<br />
Thử truy cập:<br />
<br />
<a href="http://127.0.0.1:5000/get_file?filename=../passwords.txt" target="_blank">http://127.0.0.1:5000/get_file?filen.../passwords.txt</a><br />
<br />
Kết quả:<br />
<br />
username=cisco<br />
<br />
password=cisco<br />
<br />
Ứng dụng vẫn đọc được file.<br />
<br />
Nguyên nhân là Python xử lý:<br />
<br />
../<br />
<br />
như một lệnh di chuyển lên thư mục cha.<br />
<br />
Đây chính là kỹ thuật khai thác:<br />
<br />
Path Traversal hoặc Directory Traversal<br />
<br />
Đây là một trong những lỗ hổng phổ biến thuộc nhóm OWASP Top 10 và thường xuất hiện trong các API đọc file, upload file hoặc export dữ liệu.<br />
<br />
<b><b>Bước 8: Triển khai Input Validation</b></b><br />
<br />
Import thêm thư viện:<br />
<br />
import re<br />
<br />
Tạo hàm kiểm tra đầu vào:<br />
<br />
def sanitize_string(filename):<br />
<br />
if re.search(r'^[\w\-\.]+$', filename):<br />
<br />
pass<br />
<br />
else:<br />
<br />
raise ValueError(<br />
<br />
&quot;Can not use special characters&quot;<br />
<br />
)<br />
<br />
Sửa lại hàm đọc file:<br />
<br />
def cat(filename):<br />
<br />
sanitize_string(filename)<br />
<br />
with open(filename) as file:<br />
<br />
data = file.read()<br />
<br />
return data<br />
<br />
Bước 9: Kiểm tra lại lỗ hổng<br />
<br />
Thực hiện lại yêu cầu:<br />
<br />
<a href="http://127.0.0.1:5000/get_file?filename=../passwords.txt" target="_blank">http://127.0.0.1:5000/get_file?filen.../passwords.txt</a><br />
<br />
Lần này Flask trả về lỗi:<br />
<br />
ValueError<br />
<br />
Can not use special characters<br />
<br />
Như vậy ứng dụng đã ngăn chặn thành công cuộc tấn công Path Traversal.<br />
<br />
Kiến thức DevSecOps rút ra từ bài lab<br />
<br />
Sau khi hoàn thành bài lab này, tôi nhận thấy có ba nguyên tắc quan trọng trong phát triển API:<br />
<br />
<b><b>1. Never Trust User Input</b></b><br />
<br />
Không bao giờ tin tưởng dữ liệu đầu vào từ người dùng.<br />
<br />
Mọi tham số nhận từ:<br />
<br />
URL Parameters<br />
<br />
Form Data<br />
<br />
JSON Payload<br />
<br />
Header<br />
<br />
Cookies<br />
<br />
đều phải được kiểm tra.<br />
<br />
<b><b>2. Allow List tốt hơn Deny List</b></b><br />
<br />
<br />
Thay vì cố gắng chặn tất cả ký tự nguy hiểm, hãy chỉ cho phép những ký tự thực sự cần thiết.<br />
<br />
Ví dụ:<br />
<br />
a-z<br />
<br />
A-Z<br />
<br />
0-9<br />
<br />
_<br />
<br />
<br />
Đây là phương pháp đang được sử dụng rộng rãi trong Secure Coding.<br />
<br />
<b><b>3. Không lưu Secret dưới dạng Plain Text</b></b><br />
<br />
Trong thực tế không nên lưu:<br />
<br />
password=cisco<br />
<br />
trong file text.<br />
<br />
Thay vào đó nên sử dụng:<br />
<br />
Hash Password<br />
<br />
Secret Manager<br />
<br />
Vault<br />
<br />
Environment Variables<br />
<br />
Kubernetes Secret<br />
<br />
<b>Kết luận</b><br />
<br />
Đây là một bài lab khá đơn giản nhưng phản ánh chính xác những sai lầm mà rất nhiều lập trình viên mắc phải khi phát triển API nội bộ hoặc công cụ automation.<br />
<br />
Chỉ với một tham số:<br />
<br />
filename<br />
<br />
và việc thiếu kiểm tra dữ liệu đầu vào, kẻ tấn công có thể đọc được:<br />
<br />
file cấu hình<br />
<br />
mật khẩu database<br />
<br />
SSH Key<br />
<br />
API Token<br />
<br />
Source Code<br />
<br />
<br />
<br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>ThanhTho</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442545-lab-khai-thác-điểm-yếu-thông-số-đầu-vào-để-truy-cập-dữ-liệu-nhạy-cảm-trong-flask-python</guid>
		</item>
		<item>
			<title>Lab - Chuyển đổi dữ liệu API giữa YAML, JSON và XML bằng Python</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442470-lab-chuyển-đổi-dữ-liệu-api-giữa-yaml-json-và-xml-bằng-python</link>
			<pubDate>Thu, 09 Jul 2026 13:57:31 GMT</pubDate>
			<description>Khi bắt đầu học DevNet hoặc Network Automation, nhiều người thường tập trung vào Python hoặc API mà quên mất một kỹ năng quan trọng khác: làm việc...</description>
			<content:encoded><![CDATA[Khi bắt đầu học DevNet hoặc Network Automation, nhiều người thường tập trung vào Python hoặc API mà quên mất một kỹ năng quan trọng khác: làm việc với dữ liệu.<br />
Trên thực tế, một kỹ sư DevNet gần như phải làm việc hàng ngày với ba định dạng dữ liệu phổ biến nhất hiện nay là <b>JSON, XML và YAML</b>.<ul><li>REST API và RESTCONF sử dụng JSON.</li>
</ul><ul><li>NETCONF sử dụng XML.</li>
</ul><ul><li>Ansible Playbook sử dụng YAML.</li>
</ul>Vì vậy trước khi đi sâu vào Automation hay lập trình mạng, việc hiểu cách đọc, xử lý và chuyển đổi dữ liệu giữa các định dạng này là một kỹ năng gần như bắt buộc. <b>Mục tiêu bài lab</b><br />
<br />
<br />
Sau khi hoàn thành bài lab này, bạn có thể:<ul><li>Đọc dữ liệu YAML bằng Python.</li>
</ul><ul><li>Chuyển đổi dữ liệu YAML thành đối tượng Python.</li>
</ul><ul><li>Serialize dữ liệu sang JSON.</li>
</ul><ul><li>Đọc và phân tích XML bằng ElementTree.</li>
</ul><ul><li>Đọc XML bằng MiniDOM.</li>
</ul><ul><li>Làm việc với XML Namespace.</li>
</ul><ul><li>Hiểu được vai trò của XML, JSON và YAML trong các giải pháp Automation hiện nay.</li>
</ul><b>Phần 1: Đọc dữ liệu YAML bằng Python</b> <b>Bước 1: Cài đặt thư viện xử lý YAML</b><br />
<br />
<br />
Mở CMD hoặc Terminal và thực hiện:<br />
py -m pip install ruamel.yaml<br />
ruamel.yaml là thư viện phổ biến được sử dụng để đọc và xử lý file YAML trong môi trường Automation.<br />
Trong thực tế, Ansible cũng sử dụng YAML để lưu trữ:<ul><li>Playbook</li>
</ul><ul><li>Inventory</li>
</ul><ul><li>Variables</li>
</ul><ul><li>Template cấu hình</li>
</ul><b>Bước 2: Import các thư viện cần thiết</b><br />
<br />
<br />
import sys<br />
from helper import *<br />
from ruamel import yaml<br />
Trong đó:<ul><li>helper.py chứa class User và các hàm hỗ trợ.</li>
</ul><ul><li>ruamel.yaml dùng để xử lý dữ liệu YAML.</li>
</ul><b>Bước 3: Mở file YAML</b><br />
<br />
<br />
with open('user.yaml','r') as stream:<br />
Trong môi trường DevNet, việc đọc file cấu hình hoặc file inventory là thao tác diễn ra thường xuyên trong các hệ thống Automation. <b>Bước 4: Chuyển YAML sang đối tượng Python</b><br />
<br />
<br />
user_yaml = yaml.safe_load(stream)<br />
Sau khi thực hiện lệnh này, toàn bộ nội dung trong file YAML sẽ được chuyển thành đối tượng Python. <b>Bước 5: Kiểm tra kiểu dữ liệu</b><br />
<br />
<br />
print(type(user_yaml))<br />
Kết quả:<br />
&lt;class 'dict'&gt;<br />
Điều này cho thấy dữ liệu YAML sau khi được đọc sẽ trở thành Dictionary trong Python.<br />
Đây cũng chính là cách Ansible xử lý Playbook và Inventory ở phía bên trong. <b>Bước 6: Kiểm tra các trường dữ liệu</b><br />
<br />
<br />
for key in user_yaml:<br />
print(key)<br />
Ví dụ kết quả:<br />
id<br />
first_name<br />
last_name<br />
birth_date<br />
address<br />
score<br />
Các trường này chính là các key được định nghĩa trong file YAML. <b>Bước 7: Tạo đối tượng User</b><br />
<br />
<br />
user = User()<br />
Trong thực tế, các hệ thống API thường không làm việc trực tiếp với Dictionary mà sẽ chuyển dữ liệu thành Object để dễ quản lý và xử lý hơn. <b>Bước 8: Mapping dữ liệu từ YAML sang Object</b><br />
<br />
<br />
user.id = user_yaml['id']<br />
user.first_name = user_yaml['first_name']<br />
user.last_name = user_yaml['last_name']<br />
user.birth_date = user_yaml['birth_date']<br />
user.address = user_yaml['address']<br />
user.score = user_yaml['score']<br />
Đây được gọi là quá trình <b>Data Mapping</b>.<br />
Trong các nền tảng như Cisco DNA Center, Cisco NSO hoặc Meraki Dashboard API, dữ liệu nhận được từ API cũng thường được chuyển thành Object để xử lý theo cách tương tự. <b>Bước 9: Kiểm tra kết quả</b><br />
<br />
<br />
print(user)<br />
Lúc này dữ liệu đã được chuyển hoàn toàn từ YAML sang đối tượng Python.<br />
<b>Phần 2: Chuyển đổi dữ liệu sang JSON</b><br />
JSON hiện nay là định dạng dữ liệu phổ biến nhất trong thế giới API.<br />
Hầu hết các API của Cisco hiện nay đều sử dụng JSON, chẳng hạn như:<ul><li>Cisco DNA Center API</li>
</ul><ul><li>Meraki Dashboard API</li>
</ul><ul><li>Webex API</li>
</ul><ul><li>FMC API</li>
</ul><ul><li>RESTCONF API</li>
</ul><b>Import thư viện JSON</b><br />
<br />
<br />
import json <b>Chuyển Object sang JSON</b><br />
<br />
<br />
user_json = json.dumps(<br />
user,<br />
default=serializeUser<br />
)<br />
Do đối tượng User không phải kiểu dữ liệu mà JSON có thể xử lý trực tiếp nên cần sử dụng hàm serializeUser() để thực hiện quá trình chuyển đổi. <b>Hiển thị dữ liệu JSON</b><br />
<br />
<br />
print(user_json)<br />
Ví dụ:<br />
{<br />
&quot;id&quot;:1,<br />
&quot;first_name&quot;:&quot;John&quot;,<br />
&quot;last_name&quot;:&quot;Doe&quot;<br />
} <b>Format JSON cho dễ đọc</b><br />
<br />
<br />
user_json = json.dumps(<br />
user,<br />
default=serializeUser,<br />
indent=4,<br />
sort_keys=True<br />
)<br />
Ý nghĩa:<ul><li>indent=4: tạo cấu trúc thụt lề dễ đọc.</li>
</ul><ul><li>sort_keys=True: sắp xếp key theo thứ tự alphabet.</li>
</ul>Đây là kỹ thuật mà các kỹ sư DevNet thường sử dụng khi debug API hoặc phân tích dữ liệu trả về từ thiết bị. <b>Ghi dữ liệu ra file JSON</b><br />
<br />
<br />
file = open(&quot;user.json&quot;,&quot;w&quot;)<br />
file.write(user_json)<br />
file.close()<br />
Sau khi thực hiện, hệ thống sẽ tạo file:<br />
user.json<br />
Trong thực tế, phương pháp này thường được sử dụng để:<ul><li>Backup dữ liệu API.</li>
</ul><ul><li>Tạo inventory động.</li>
</ul><ul><li>Lưu trạng thái thiết bị phục vụ Automation.</li>
</ul><b>Phần 3: Phân tích XML bằng ElementTree</b><br />
Mặc dù JSON ngày càng phổ biến, XML vẫn đóng vai trò rất quan trọng trong môi trường Enterprise.<br />
Một số công nghệ vẫn sử dụng XML:<ul><li>NETCONF</li>
</ul><ul><li>SOAP API</li>
</ul><ul><li>Cisco NSO</li>
</ul><ul><li>Cisco Prime Infrastructure</li>
</ul><b>Import thư viện</b><br />
<br />
<br />
import xml.etree.ElementTree as ET <b>Parse file XML</b><br />
<br />
<br />
tree = ET.parse('user.xml')<br />
root = tree.getroot()<br />
Toàn bộ cấu trúc XML lúc này đã được nạp vào bộ nhớ. <b>Hiển thị các tag trong XML</b><br />
<br />
<br />
for element in root:<br />
print(element.tag)<br />
Ví dụ:<br />
id<br />
first_name<br />
last_name<br />
address<br />
score <b>Truy cập giá trị của tag id</b><br />
<br />
<br />
print(root.find('id').text)<br />
Kết quả:<br />
1001 <b>Tìm toàn bộ phần tử address</b><br />
<br />
<br />
addresses = root.findall('address')<br />
Sau đó:<br />
for address in addresses:<br />
for i in address:<br />
print(i.tag + ':' + i.text) <b>Hiển thị toàn bộ cấu trúc XML</b><br />
<br />
<br />
for k in root.iter():<br />
print(k.tag + ':' + k.text)<br />
Đây là kỹ thuật thường được sử dụng khi phân tích dữ liệu XML trả về từ NETCONF Server.<br />
<b>Phần 4: Phân tích XML bằng MiniDOM</b><br />
MiniDOM là một phương pháp khác để xử lý XML trong Python. <b>Import thư viện</b><br />
<br />
<br />
import xml.dom.minidom as MD <b>Parse XML</b><br />
<br />
<br />
dom = MD.parse('user.xml') <b>Hiển thị các tag</b><br />
<br />
<br />
for node in dom.childNodes:<br />
printTags(node.childNodes) <b>Lấy giá trị của id</b><br />
<br />
<br />
idElements = dom.getElementsByTagName('id')<br />
<br />
elementId = idElements.item(0)<br />
<br />
idValue = elementId.firstChild.data<br />
<br />
print(idValue) <b>Hiển thị các phần tử address</b><br />
<br />
<br />
for node in dom.getElementsByTagName('address'):<br />
printNodes(node.childNodes)<br />
Trong quá trình xử lý XML bằng Python, chúng ta có thể sử dụng cả ElementTree và MiniDOM.<ul><li>ElementTree có ưu điểm là đơn giản, dễ sử dụng và xử lý nhanh đối với các file XML lớn.</li>
</ul><ul><li>MiniDOM cung cấp khả năng thao tác theo mô hình DOM truyền thống, phù hợp khi cần làm việc với cấu trúc XML phức tạp hoặc cần truy cập sâu vào các node.</li>
</ul>Trong thực tế triển khai DevNet và Network Automation, phần lớn kỹ sư sẽ ưu tiên sử dụng ElementTree nhờ cú pháp ngắn gọn và hiệu năng tốt hơn khi xử lý dữ liệu XML trả về từ các hệ thống như NETCONF hoặc Cisco NSO.<br />
<b>Phần 5: Làm việc với XML Namespace</b><br />
Namespace thường xuất hiện trong các công nghệ như:<ul><li>NETCONF</li>
</ul><ul><li>YANG Model</li>
</ul><ul><li>SOAP API</li>
</ul><b>Định nghĩa Namespace</b><br />
<br />
<br />
namespaces = {<br />
'a':'https://www.example.com/network',<br />
'b':'https://www.example.com/furniture'<br />
} <b>Tìm dữ liệu theo Namespace</b><br />
<br />
<br />
elementsInNSa = root.findall('a:table',namespaces)<br />
<br />
elementsInNSb = root.findall('b:table',namespaces) <b>Hiển thị dữ liệu trong Namespace a</b><br />
<br />
<br />
for e in elementsInNSa:<br />
for i in e.iter():<br />
print(i.tag + ':' + i.text) <b>Hiển thị dữ liệu trong Namespace b</b><br />
<br />
<br />
for element in list(elementsInNSb[0]):<br />
print(element.tag + &quot;:&quot; + element.text)<br />
<b>Kết luận</b><br />
Đây là một trong những bài lab nền tảng nhất của DevNet và Network Automation.<br />
Nếu nắm vững bài lab này, bạn sẽ dễ dàng tiếp cận các công nghệ hiện đại như: REST API/RESTCONF/Cisco DNA Center API/Meraki API/NETCONF/YANG Model/Cisco NSO/Ansible Automation​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>ThanhTho</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442470-lab-chuyển-đổi-dữ-liệu-api-giữa-yaml-json-và-xml-bằng-python</guid>
		</item>
		<item>
			<title>Lab- Sử dụng Netmiko và NTC Templates để kiểm tra VLAN và Access Port trên Switch Cisco</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442359-lab-sử-dụng-netmiko-và-ntc-templates-để-kiểm-tra-vlan-và-access-port-trên-switch-cisco</link>
			<pubDate>Wed, 08 Jul 2026 04:09:39 GMT</pubDate>
			<description>Trong bài Lab trước, chúng ta đã sử dụng thư viện Netmiko để tự động cấu hình thiết bị mạng bằng Python. 
 
Tiếp nối nội dung đó, bài Lab này sẽ...</description>
			<content:encoded><![CDATA[Trong bài Lab trước, chúng ta đã sử dụng thư viện <b><b>Netmiko</b></b> để tự động cấu hình thiết bị mạng bằng Python.<br />
<br />
Tiếp nối nội dung đó, bài Lab này sẽ hướng dẫn cách sử dụng <b><b>Netmiko</b></b> kết hợp với <b><b>NTC Templates</b></b> để tự động kiểm tra VLAN và Access Port trên Switch Cisco, từ đó xây dựng nền tảng cho các bài toán Network Automation trong thực tế.<br />
<b>1. Mục tiêu của bài Lab</b><br />
<br />
Chương trình Python sau khi hoàn thành sẽ có khả năng:<ul><li>Kết nối SSH tới Switch Cisco.</li>
<li>Thu thập thông tin VLAN hiện có trên thiết bị.</li>
<li>Kiểm tra VLAN 10 đã tồn tại hay chưa.</li>
<li>Kiểm tra các Access Port e0/1 và e0/2 đã được gán vào VLAN 10 hay chưa.</li>
<li>Tự động thực hiện cấu hình nếu phát hiện thiếu VLAN hoặc thiếu cấu hình Access Port.</li>
<li>Hiển thị kết quả kiểm tra để phục vụ công tác vận hành và kiểm tra hệ thống.</li>
</ul><b>2. Tại sao cần NTC Templates?</b><br />
<br />
Nếu chỉ sử dụng Netmiko, khi thực hiện lệnh:<br />
<br />
show vlan<br />
<br />
Switch sẽ trả về dữ liệu dưới dạng text:<br />
1 default active Et0/1,Et0/2<br />
10 SALES active<br />
20 SERVER active<br />
<br />
Việc xử lý dữ liệu dạng text trong Python khá phức tạp và dễ phát sinh lỗi khi Cisco thay đổi định dạng hiển thị giữa các phiên bản IOS.<br />
<br />
Đây là lúc thư viện NTC Templates phát huy tác dụng.<br />
<br />
NTC Templates sẽ chuyển dữ liệu CLI sang dữ liệu có cấu trúc:<br />
<br />
[<br />
{<br />
'vlan_id': '1',<br />
'interfaces': ['Et0/1','Et0/2']<br />
},<br />
{<br />
'vlan_id': '10',<br />
'interfaces': []<br />
}<br />
]<br />
<br />
Khi dữ liệu đã được chuyển đổi sang Dictionary hoặc JSON, việc kiểm tra VLAN hay Access Port chỉ còn là các thao tác xử lý dữ liệu thông thường của Python. <b>3. Chuẩn bị môi trường</b><br />
<br />
<b>Cài đặt thư viện</b><br />
<br />
Trên máy Linux hoặc WSL thực hiện:<br />
<br />
pip3 install netmiko ntc_templates<br />
<br />
Kiểm tra cài đặt thành công:<br />
<br />
pip3 list | grep netmiko<br />
pip3 list | grep ntc<br />
<br />
<b>4. Chuẩn bị thiết bị mạng</b><br />
<br />
Trước khi viết code cần đảm bảo Switch đã hỗ trợ SSH.<br />
<b>Cấu hình địa chỉ IP quản trị</b><br />
<br />
<br />
interface e0/0<br />
no switchport<br />
ip address <a href="https://192.168.1.1" target="_blank">192.168.1.1</a> <a href="https://255.255.255.0" target="_blank">255.255.255.0</a><br />
no shutdown<br />
<b>Cấu hình SSH</b><br />
<br />
<br />
username admin password 123<br />
ip domain-name vnpro.local<br />
crypto key generate rsa<br />
1024<br />
ip ssh version 2<br />
line vty 0 4<br />
login local<br />
transport input ssh<br />
<br />
Kiểm tra lại bằng lệnh:<br />
show ip ssh<br />
show run | section vty<br />
<br />
Nếu SSH bằng PuTTY hoặc Terminal chưa thành công thì Netmiko cũng sẽ không thể kết nối được.<br />
<br />
<b>5. Tách riêng thông tin thiết bị</b><br />
<br />
File device_list.py<br />
<br />
from getpass import getpass<br />
passwd = getpass(&quot;Nhap mat khau SSH: &quot;)<br />
sw1 = {<br />
&quot;device_type&quot;: &quot;cisco_ios&quot;,<br />
&quot;ip&quot;: &quot;192.168.1.1&quot;,<br />
&quot;username&quot;: &quot;admin&quot;,<br />
&quot;password&quot;: passwd,<br />
&quot;secret&quot;: &quot;321&quot;<br />
}<br />
device_list = [sw1]<br />
<br />
Việc tách riêng thông tin thiết bị giúp chương trình dễ mở rộng lên nhiều Switch trong tương lai mà không cần sửa code chính.<br />
<br />
<b>6. Kết nối SSH bằng Netmiko</b><br />
<br />
ssh = ConnectHandler(**device)<br />
ssh.enable()<br />
<br />
Sau khi kết nối thành công, Python có thể thực hiện bất kỳ lệnh CLI nào trên Switch.<br />
<br />
Ví dụ:<br />
<br />
data = ssh.send_command(&quot;show vlan&quot;)<br />
<br />
<b>7. Chuyển đổi dữ liệu bằng NTC Templates</b><br />
<br />
data_parse = parse_output(<br />
platform=&quot;cisco_ios&quot;,<br />
command=&quot;show vlan&quot;,<br />
data=data<br />
)<br />
<br />
Kết quả nhận được:<br />
<br />
[<br />
{'vlan_id': '1', 'interfaces': ['Et0/1','Et0/2']},<br />
{'vlan_id': '10', 'interfaces': []}<br />
]<br />
<br />
Đây chính là bước quan trọng nhất của bài Lab vì từ thời điểm này chương trình sẽ xử lý dữ liệu có cấu trúc thay vì xử lý chuỗi text.<br />
<br />
<b>8. Xây dựng Dictionary VLAN</b><br />
<br />
vlan = {}<br />
for i in data_parse:<br />
vlan[i[&quot;vlan_id&quot;]] = i[&quot;interfaces&quot;]<br />
<br />
Kết quả:<br />
<br />
{<br />
'1': ['Et0/1', 'Et0/2'],<br />
'10': []<br />
}<br />
<br />
Việc chuyển sang Dictionary giúp tốc độ tìm kiếm và kiểm tra trạng thái nhanh hơn rất nhiều.<br />
<br />
<b>9. Kiểm tra VLAN tồn tại</b><br />
<br />
if &quot;10&quot; in vlan:<br />
print(&quot;VLAN 10 da ton tai&quot;)<br />
else:<br />
print(&quot;Dang tao VLAN 10&quot;)<br />
<br />
Đây được gọi là kiểm tra trạng thái hiện tại trước khi thực hiện thay đổi.<br />
<br />
Trong tự động hóa hạ tầng, nguyên tắc này được gọi là <b><b>Idempotent Configuration</b></b>. <b>10. Kiểm tra Access Port</b><br />
<br />
<br />
required_ports = [&quot;Et0/1&quot;, &quot;Et0/2&quot;]<br />
for port in required_ports:<br />
if port in vlan[&quot;10&quot;]:<br />
print(f&quot;{port} da thuoc VLAN 10&quot;)<br />
else:<br />
print(f&quot;{port} chua thuoc VLAN 10&quot;)<br />
<br />
Đây là mô hình thường được sử dụng trong các hệ thống kiểm tra cấu hình và audit hệ thống mạng.<br />
<br />
<b>11. Tự động cấu hình nếu phát hiện sai lệch</b><br />
<br />
Nếu VLAN chưa tồn tại:<br />
<br />
ssh.send_config_set([<br />
&quot;vlan 10&quot;,<br />
&quot;name USERS&quot;<br />
])<br />
<br />
Nếu Access Port chưa được cấu hình:<br />
<br />
ssh.send_config_set([<br />
&quot;interface e0/1&quot;,<br />
&quot;switchport mode access&quot;,<br />
&quot;switchport access vlan 10&quot;<br />
])<br />
<br />
Như vậy chương trình không chỉ dừng lại ở việc giám sát mà đã bắt đầu chuyển sang hướng tự động khắc phục cấu hình.<br />
<br />
<b>Kết luận</b><br />
<br />
<br />
Giá trị lớn nhất của bài Lab không nằm ở việc tạo VLAN hay gán Access Port.<br />
<br />
Điều quan trọng hơn là giúp kỹ sư mạng thay đổi tư duy vận hành:<ul><li>Không cấu hình trước rồi mới kiểm tra.</li>
<li>Hãy kiểm tra trạng thái hiện tại của hệ thống trước, phát hiện sai lệch và chỉ thực hiện thay đổi khi thật sự cần thiết.</li>
</ul>​<br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>ThanhTho</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442359-lab-sử-dụng-netmiko-và-ntc-templates-để-kiểm-tra-vlan-và-access-port-trên-switch-cisco</guid>
		</item>
		<item>
			<title>Làm quen với Network Automation bằng Python, Netmiko và ntc_templates</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442351-làm-quen-với-network-automation-bằng-python-netmiko-và-ntc_templates</link>
			<pubDate>Wed, 08 Jul 2026 01:43:58 GMT</pubDate>
			<description>Hôm nay mình hoàn thành 1 bài lab cơ bản  về Network Automation sử dụng Python để quản lý thiết bị Cisco thông qua SSH. Mục tiêu của bài lab không...</description>
			<content:encoded><![CDATA[<br />
Hôm nay mình hoàn thành 1 bài lab cơ bản  về <b>Network Automation</b> sử dụng Python để quản lý thiết bị Cisco thông qua SSH. Mục tiêu của bài lab không phải cấu hình mạng phức tạp mà là làm quen với quy trình tự động hóa việc kiểm tra và thu thập thông tin từ thiết bị. <b>Mô hình lab</b><ul><li>01 Cisco IOS Layer 3 Switch chạy trên EVE-NG.</li>
<li>Cổng Ethernet0/0 được cấu hình ở chế độ Layer 3 (no switchport) và nhận địa chỉ IP từ DHCP để có thể kết nối trực tiếp với máy tính thật.</li>
<li>Máy tính sử dụng macOS, Python và Homebrew.</li>
</ul>Switch được cấu hình SSH với các thông số cơ bản:<ul><li>Tạo tài khoản đăng nhập cục bộ.</li>
<li>Cấu hình domain-name.</li>
<li>Sinh RSA Key.</li>
<li>Cho phép truy cập SSH trên VTY.</li>
<li>Thiết lập Enable Password.</li>
</ul><br />
Sau khi hoàn thành cấu hình, mình kiểm tra bằng Terminal:<br />
ssh vnpro@&lt;IP_Switch&gt;<br />
<br />
<br />
Kết nối SSH thành công trước khi bắt đầu viết chương trình Python. <b>Chuẩn bị môi trường Python</b><br />
Cài đặt các thư viện cần thiết:<br />
pip install netmiko ntc_templates<br />
<br />
Trong đó:<ul><li><b>Netmiko</b> được sử dụng để thiết lập kết nối SSH tới thiết bị Cisco.</li>
<li><b>ntc_templates</b> dùng TextFSM để chuyển kết quả các lệnh CLI sang dữ liệu có cấu trúc (JSON/List/Dictionary), giúp chương trình dễ dàng xử lý hơn.</li>
</ul><b>Tổ chức chương trình</b><br />
Project được chia thành hai file:<br />
<br />
device_list.py<br />
Lưu thông tin thiết bị cần kết nối:<ul><li>Device Type</li>
<li>Địa chỉ IP</li>
<li>Username</li>
<li>Password</li>
<li>Enable Secret</li>
</ul>Password SSH được nhập bằng getpass() để tránh hiển thị trực tiếp trên màn hình.<br />
<br />
main.py<br />
Chương trình thực hiện các bước:<ul><li>Kết nối SSH bằng Netmiko.</li>
<li>Vào Enable Mode.</li>
<li>Thực hiện lệnh:</li>
</ul>show vlan<ul><li>Parse kết quả bằng ntc_templates.</li>
<li>Chuyển dữ liệu về Dictionary.</li>
<li>Kiểm tra trạng thái VLAN.</li>
<li>Kiểm tra các Access Port đang thuộc VLAN nào.</li>
<li>Hiển thị kết quả ra màn hình.</li>
<li>Đóng phiên SSH.</li>
</ul><b>Điểm mình học được</b><br />
Thay vì xử lý chuỗi ký tự trả về từ CLI, ntc_templates giúp chuyển đổi trực tiếp sang dữ liệu có cấu trúc. Ví dụ sau khi parse, chương trình có thể làm việc với dữ liệu như:<br />
{<br />
&quot;1&quot;: [&quot;Et0/1&quot;, &quot;Et0/2&quot;],<br />
&quot;10&quot;: [&quot;Et0/3&quot;]<br />
}<br />
<br />
Nhờ đó việc kiểm tra:<ul><li>VLAN đã tồn tại hay chưa.</li>
<li>Port đã thuộc VLAN mong muốn hay chưa.</li>
</ul>chỉ còn là các thao tác trên Dictionary của Python thay vì phải xử lý chuỗi thủ công. <b>Một số vấn đề gặp phải</b><br />
<br />
<b>Kết quả</b><br />
Sau khi hoàn thành bài lab, chương trình có thể:<ul><li>Kết nối SSH tới Switch.</li>
<li>Thu thập thông tin VLAN.</li>
<li>Phân tích kết quả bằng ntc_templates.</li>
<li>Kiểm tra trạng thái VLAN và Access Port hoàn toàn tự động.</li>
</ul><br />
Đây là một bài lab cơ bản nhưng là bước nền quan trọng trước khi triển khai các tác vụ Network Automation nâng cao như tự động tạo VLAN, cấu hình Interface, kiểm tra Trunk, ACL, Backup cấu hình hoặc quản lý đồng thời nhiều thiết bị bằng Python.<br />
<img title="image.png" data-attachmentid="442352" data-align="none" data-size="full" border="0" src="filedata/fetch?id=442352&amp;d=1783474912" alt="Click image for larger version

Name:	image.png
Views:	19
Size:	31.7 KB
ID:	442352" data-fullsize-url="filedata/fetch?id=442352&amp;d=1783474912" data-thumb-url="filedata/fetch?id=442352&amp;d=1783474912&amp;type=thumb" data-title="Click on the image to see the original version" data-caption="image.png" class="bbcode-attachment thumbnail js-lightbox bbcode-attachment--lightbox" />​<br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>vuphutruong</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442351-làm-quen-với-network-automation-bằng-python-netmiko-và-ntc_templates</guid>
		</item>
		<item>
			<title>Viết chương trình sử dụng thư viện netmiko của ngôn ngữ Python để cấu hình các thiết bị mạng.</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442341-viết-chương-trình-sử-dụng-thư-viện-netmiko-của-ngôn-ngữ-python-để-cấu-hình-các-thiết-bị-mạng</link>
			<pubDate>Tue, 07 Jul 2026 13:41:35 GMT</pubDate>
			<description>Hôm nay mình muốn chia sẻ một chút về Network Automation với Python Netmiko — một chủ đề khá thú vị cho những bạn đang học Network, DevOps hoặc...</description>
			<content:encoded><![CDATA[<span style="font-family:Aptos">Hôm nay mình muốn chia sẻ một chút về <b>Network Automation với Python Netmiko</b> — một chủ đề khá thú vị cho những bạn đang học Network, DevOps hoặc Automation.</span><br />
<span style="font-family:Aptos">Trước đây khi cấu hình thiết bị mạng, mình thường làm theo cách truyền thống: SSH vào switch/router, sau đó gõ từng dòng lệnh cấu hình. Cách này dễ hiểu và phù hợp khi hệ thống nhỏ. Nhưng khi số lượng thiết bị nhiều hơn, hoặc cấu hình có tính lặp lại, việc làm thủ công bắt đầu có nhiều vấn đề.</span><br />
<span style="font-family:Aptos">Ví dụ đơn giản: cần tạo nhiều VLAN trên switch.</span><br />
<span style="font-family:Aptos">Nếu làm tay, mình phải tạo từng VLAN, vào từng interface VLAN, gán IP, bật interface, rồi kiểm tra lại kết quả. Với vài VLAN thì ổn, nhưng nếu phải làm cho hàng chục VLAN hoặc nhiều switch khác nhau thì rất dễ mất thời gian và dễ sai sót.</span><br />
<span style="font-family:Aptos">Đây là lúc <b>Network Automation</b> trở nên hữu ích.</span><br />
<span style="font-family:Aptos">Thay vì ngồi gõ từng dòng lệnh, mình có thể viết một script Python để tự động SSH vào thiết bị và gửi các lệnh cấu hình cần thiết.</span><br />
<span style="font-family:Aptos">Một thư viện khá phổ biến để làm việc này là <b>Netmiko</b>.</span><br />
<span style="font-family:Aptos"><b>Netmiko là gì?</b></span><br />
<span style="font-family:Aptos">Netmiko là thư viện Python hỗ trợ kết nối SSH tới các thiết bị mạng như Cisco, Juniper, Huawei, MikroTik… Sau khi kết nối thành công, Python có thể gửi lệnh cấu hình hoặc lệnh kiểm tra trạng thái thiết bị.</span><br />
<span style="font-family:Aptos">Nói đơn giản hơn, Netmiko giúp mình biến những thao tác cấu hình thủ công trên CLI thành một đoạn script có thể chạy tự động.</span><br />
<span style="font-family:Aptos">Ví dụ luồng xử lý sẽ như sau:</span><br />
<span style="font-family:Aptos">Máy tính chạy Python<br />
→ Kết nối SSH tới switch<br />
→ Gửi danh sách lệnh cấu hình<br />
→ Switch thực thi lệnh<br />
→ Python lấy kết quả kiểm tra và in ra màn hình</span><br />
<span style="font-family:Aptos">Một ví dụ rất đơn giản về ý tưởng:</span><br />
<span style="font-family:Aptos">from netmiko import ConnectHandler</span><br />
<span style="font-family:Aptos">device = {</span><br />
<span style="font-family:Aptos">&quot;device_type&quot;: &quot;cisco_ios&quot;,</span><br />
<span style="font-family:Aptos">&quot;ip&quot;: &quot;&lt;SWITCH_IP&gt;&quot;,</span><br />
<span style="font-family:Aptos">&quot;username&quot;: &quot;&lt;USERNAME&gt;&quot;,</span><br />
<span style="font-family:Aptos">&quot;password&quot;: &quot;&lt;PASSWORD&gt;&quot;,</span><br />
<span style="font-family:Aptos">&quot;secret&quot;: &quot;&lt;ENABLE_SECRET&gt;&quot;,</span><br />
<span style="font-family:Aptos">}</span><br />
<span style="font-family:Aptos">connect = ConnectHandler(**device)</span><br />
<span style="font-family:Aptos">connect.enable()</span><br />
<span style="font-family:Aptos">for vlan_id in range(10, 31):</span><br />
<span style="font-family:Aptos">commands = [</span><br />
<span style="font-family:Aptos">f&quot;vlan {vlan_id}&quot;,</span><br />
<span style="font-family:Aptos">f&quot;interface vlan {vlan_id}&quot;,</span><br />
<span style="font-family:Aptos">f&quot;ip address 172.16.{vlan_id}.1 255.255.255.0&quot;,</span><br />
<span style="font-family:Aptos">&quot;no shutdown&quot;</span><br />
<span style="font-family:Aptos">]</span><br />
<span style="font-family:Aptos">connect.send_config_set(commands)</span><br />
<span style="font-family:Aptos">result = connect.send_command(&quot;show ip interface brief&quot;)</span><br />
<span style="font-family:Aptos">print(result)</span><br />
<span style="font-family:Aptos">connect.disconnect()</span><br />
<span style="font-family:Aptos">Điểm hay ở đây nằm ở vòng lặp:</span><br />
<span style="font-family:Aptos">for vlan_id in range(10, 31):</span><br />
<span style="font-family:Aptos">Thay vì phải viết lệnh cho từng VLAN một cách thủ công, vòng lặp sẽ tự động chạy từ VLAN 10 đến VLAN 30. Với mỗi VLAN, script sẽ tự tạo ra nhóm lệnh tương ứng và gửi xuống switch.</span><br />
<span style="font-family:Aptos">Ví dụ khi vlan_id = 10, script sẽ hiểu là cần tạo VLAN 10 và gán IP tương ứng cho interface VLAN 10.</span><br />
<span style="font-family:Aptos">Khi vlan_id = 11, script tiếp tục làm tương tự cho VLAN 11.</span><br />
<span style="font-family:Aptos">Cứ như vậy cho đến VLAN cuối cùng.</span><br />
<span style="font-family:Aptos">Nhờ cách làm này, những công việc có tính lặp lại cao sẽ được xử lý nhanh hơn, đồng nhất hơn và ít bị lỗi do thao tác thủ công.</span><br />
<span style="font-family:Aptos"><b>Mình rút ra được gì từ bài lab này?</b></span><br />
<span style="font-family:Aptos">Điều đầu tiên là automation không phải thứ gì quá xa vời. Chỉ cần hiểu cơ bản về Python, SSH và cách thiết bị mạng nhận lệnh CLI là đã có thể bắt đầu tự động hóa các tác vụ đơn giản.</span><br />
<span style="font-family:Aptos">Điều thứ hai là Netmiko rất phù hợp cho người mới học Network Automation. Cú pháp khá dễ tiếp cận, cách kết nối rõ ràng và có thể thấy kết quả trực tiếp trên thiết bị sau khi chạy script.</span><br />
<span style="font-family:Aptos">Bài lab này tuy nhỏ nhưng giúp mình hiểu rõ hơn cách Python có thể hỗ trợ công việc của Network Engineer hoặc DevOps Engineer. Những thao tác lặp đi lặp lại trên thiết bị mạng hoàn toàn có thể được tự động hóa bằng script, giúp tiết kiệm thời gian và giảm lỗi cấu hình.</span><br />
<span style="font-family:Aptos">Nói ngắn gọn, <b>Netmiko là một bước khởi đầu rất tốt để tiếp cận Network Automation</b>.</span><br />
<br />
​<img title="image.png" data-attachmentid="442342" data-align="none" data-size="full" border="0" src="filedata/fetch?id=442342&amp;d=1783431670" alt="Click image for larger version

Name:	image.png
Views:	17
Size:	39.1 KB
ID:	442342" data-fullsize-url="filedata/fetch?id=442342&amp;d=1783431670" data-thumb-url="filedata/fetch?id=442342&amp;d=1783431670&amp;type=thumb" data-title="Click on the image to see the original version" data-caption="image.png" class="bbcode-attachment thumbnail js-lightbox bbcode-attachment--lightbox" />​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>HoangPhuc</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442341-viết-chương-trình-sử-dụng-thư-viện-netmiko-của-ngôn-ngữ-python-để-cấu-hình-các-thiết-bị-mạng</guid>
		</item>
		<item>
			<title>Lab - Tự động cấu hình Switch Cisco bằng Python và Netmiko</title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442333-lab-tự-động-cấu-hình-switch-cisco-bằng-python-và-netmiko</link>
			<pubDate>Tue, 07 Jul 2026 09:55:07 GMT</pubDate>
			<description>Nếu phải tạo 20 VLAN trên một Switch, chắc chắn bạn sẽ không thấy đây là việc khó. 
 
Nhưng nếu là... 
 
100 Switch. 
 
Mỗi Switch cần tạo 20 VLAN. 
...</description>
			<content:encoded><![CDATA[Nếu phải tạo 20 VLAN trên một Switch, chắc chắn bạn sẽ không thấy đây là việc khó.<br />
<br />
Nhưng nếu là...<br />
<br />
100 Switch.<br />
<br />
Mỗi Switch cần tạo 20 VLAN.<br />
<br />
Mỗi VLAN phải gán IP khác nhau.<br />
<br />
Mọi cấu hình phải giống nhau.<br />
<br />
Lúc này câu chuyện không còn là biết cấu hình Cisco IOS nữa.<br />
<br />
Mà là...<br />
<br />
Làm sao để máy tính cấu hình thay mình?<br />
<br />
Đó chính là lúc Network Automation bắt đầu.<br />
<br />
Trong bài Lab này chúng ta sẽ sử dụng Python kết hợp thư viện Netmiko để SSH vào Switch Cisco và tự động thực hiện toàn bộ quá trình cấu hình.<br />
<br />
Mục tiêu bài Lab<br />
<br />
Sau khi hoàn thành bài thực hành, chương trình Python sẽ tự động:<br />
<br />
Kết nối SSH đến Switch Cisco.<br />
<br />
Đăng nhập vào chế độ Privileged EXEC.<br />
<br />
Tạo VLAN từ 10 đến VLAN 30.<br />
<br />
Cấu hình địa chỉ IP cho từng Interface VLAN.<br />
<br />
Hiển thị kết quả cấu hình cuối cùng.<br />
<br />
Toàn bộ công việc vốn phải nhập hàng chục dòng lệnh sẽ được thực hiện chỉ bằng một lần chạy chương trình.<br />
<br />
Mô hình Lab<br />
<br />
PC- Python-Netmiko------------&gt;Cisco Switch - IOS -192.168.1.1<br />
<br />
PC đóng vai trò Automation Host.<br />
<br />
Switch Cisco là thiết bị được điều khiển thông qua giao thức SSH.<br />
<br />
Bước 1 - Chuẩn bị môi trường Python<br />
<br />
Trước tiên cần cài đặt thư viện Netmiko.<br />
<br />
pip install netmiko<br />
<br />
Hoặc với Python 3:<br />
<br />
pip3 install netmiko --user<br />
<br />
Netmiko thực chất là một thư viện được xây dựng trên Paramiko nhằm đơn giản hóa việc kết nối SSH tới các thiết bị mạng như Cisco, Juniper, Arista, Huawei...<br />
<br />
Điểm mạnh của Netmiko là:<br />
<br />
Không phải tự xử lý SSH.<br />
<br />
Không phải chờ Prompt.<br />
<br />
Không phải tự gửi từng ký tự.<br />
<br />
Chỉ cần truyền danh sách câu lệnh cấu hình.<br />
<br />
Bước 2 - Chuẩn bị Switch<br />
<br />
Switch cần được cấu hình cơ bản trước khi có thể Automation.<br />
<br />
Ví dụ:<br />
<br />
interface vlan 1<br />
<br />
ip address 192.168.1.1 255.255.255.0<br />
<br />
no shutdown<br />
<br />
Sau đó bật SSH.<br />
<br />
username admin password 123<br />
<br />
ip domain-name vnpro.local<br />
<br />
crypto key generate rsa<br />
<br />
ip ssh version 2<br />
<br />
line vty 0 4<br />
<br />
login local<br />
<br />
transport input ssh<br />
<br />
Đây là bước mà khá nhiều người mới học DevNet thường bỏ sót.<br />
<br />
Python không thể điều khiển Switch nếu thiết bị chưa cho phép SSH.<br />
<br />
Bước 3 - Khai báo thông tin thiết bị<br />
<br />
Trong Netmiko, thiết bị thường được khai báo dưới dạng Dictionary.<br />
<br />
from netmiko import ConnectHandler<br />
<br />
SW1 = {<br />
<br />
&quot;device_type&quot;:&quot;cisco_ios&quot;,<br />
<br />
&quot;ip&quot;:&quot;192.168.1.1&quot;,<br />
<br />
&quot;username&quot;:&quot;admin&quot;,<br />
<br />
&quot;password&quot;:&quot;123&quot;,<br />
<br />
&quot;secret&quot;:&quot;password&quot;<br />
<br />
}<br />
<br />
Mỗi khóa trong Dictionary đều mang ý nghĩa riêng:<br />
<br />
device_type xác định loại hệ điều hành.<br />
<br />
ip là địa chỉ quản trị.<br />
<br />
username/password dùng để SSH.<br />
<br />
secret là Enable Password.<br />
<br />
Sau đó kết nối:<br />
<br />
net_connect = ConnectHandler(**SW1)<br />
<br />
net_connect.enable()<br />
<br />
Dấu ** dùng để giải nén Dictionary thành các tham số truyền vào hàm ConnectHandler.<br />
<br />
Đây là cú pháp rất phổ biến trong Python và xuất hiện thường xuyên khi làm Automation.<br />
<br />
Bước 4 - Tự động tạo VLAN<br />
<br />
Thay vì viết:<br />
<br />
vlan 10<br />
<br />
vlan 11<br />
<br />
...<br />
<br />
vlan 30<br />
<br />
Python chỉ cần một vòng lặp.<br />
<br />
for n in range(10,31):<br />
<br />
taoVlan = [<br />
<br />
&quot;vlan &quot; + str(n)<br />
<br />
]<br />
<br />
net_connect.send_config_set(taoVlan)<br />
<br />
Ở đây:<br />
<br />
range(10,31)<br />
<br />
sẽ sinh ra:<br />
<br />
10<br />
<br />
11<br />
<br />
12<br />
<br />
...<br />
<br />
30<br />
<br />
Mỗi lần lặp chương trình sẽ gửi một lệnh cấu hình xuống Switch.<br />
<br />
Bước 5 - Tự động gán IP cho Interface VLAN<br />
<br />
Sau khi VLAN được tạo, tiếp tục cấu hình Interface VLAN.<br />
<br />
ipVlan = [<br />
<br />
&quot;interface vlan &quot; + str(n),<br />
<br />
&quot;ip address 172.16.&quot;+str(n)+&quot;.1 255.255.255.0&quot;,<br />
<br />
&quot;no shutdown&quot;<br />
<br />
]<br />
<br />
<br />
<br />
net_connect.send_config_set(ipVlan)<br />
<br />
Ví dụ khi n = 20, Python sẽ sinh ra:<br />
<br />
interface vlan 20<br />
<br />
ip address 172.16.20.1 255.255.255.0<br />
<br />
no shutdown<br />
<br />
Điều đặc biệt ở đây là lập trình viên không cần viết riêng từng VLAN.<br />
<br />
Chương trình sẽ tự sinh câu lệnh dựa trên giá trị của biến n.<br />
<br />
Đây chính là tư duy cốt lõi của Network Automation.<br />
<br />
Bước 6 - Kiểm tra kết quả<br />
<br />
Sau khi cấu hình xong, Netmiko còn có thể thực thi các lệnh Show.<br />
<br />
output = net_connect.send_command(<br />
<br />
&quot;show ip interface brief | include Vlan&quot;<br />
<br />
)<br />
<br />
print(output)<br />
<br />
Kết quả trả về sẽ hiển thị toàn bộ các Interface VLAN vừa được tạo.<br />
<br />
Ví dụ:<br />
<br />
Vlan10<br />
<br />
Vlan11<br />
<br />
Vlan12<br />
<br />
...<br />
<br />
Vlan30<br />
<br />
Điều này giúp chương trình vừa cấu hình vừa tự xác minh kết quả mà không cần người quản trị đăng nhập kiểm tra thủ công.<br />
<br />
Chương trình hoàn chỉnh<br />
<br />
from netmiko import ConnectHandler<br />
<br />
<br />
<br />
SW1 = {<br />
<br />
&quot;device_type&quot;:&quot;cisco_ios&quot;,<br />
<br />
&quot;ip&quot;:&quot;192.168.1.1&quot;,<br />
<br />
&quot;username&quot;:&quot;admin&quot;,<br />
<br />
&quot;password&quot;:&quot;123&quot;,<br />
<br />
&quot;secret&quot;:&quot;password&quot;<br />
<br />
}<br />
<br />
net_connect = ConnectHandler(**SW1)<br />
<br />
net_connect.enable()<br />
<br />
<br />
<br />
for n in range(10,31):<br />
<br />
taoVlan = [<br />
<br />
&quot;vlan &quot; + str(n)<br />
<br />
]<br />
<br />
ipVlan = [<br />
<br />
&quot;interface vlan &quot; + str(n),<br />
<br />
&quot;ip address 172.16.&quot;+str(n)+&quot;.1 255.255.255.0&quot;,<br />
<br />
&quot;no shutdown&quot;<br />
<br />
]<br />
<br />
net_connect.send_config_set(taoVlan)<br />
<br />
net_connect.send_config_set(ipVlan)<br />
<br />
<br />
<br />
output = net_connect.send_command(<br />
<br />
&quot;show ip interface brief | include Vlan&quot;<br />
<br />
)<br />
<br />
print(output)<br />
<br />
Kết luận<br />
<br />
Bài Lab này tuy đơn giản nhưng lại là một trong những bài thực hành quan trọng nhất khi bắt đầu học Cisco DevNet.<br />
<br />
Qua bài Lab, chúng ta hiểu được quy trình làm việc của một chương trình Automation:<br />
<br />
Kết nối tới thiết bị.<br />
<br />
Xác thực thông tin đăng nhập.<br />
<br />
Gửi lệnh cấu hình.<br />
<br />
Thu thập kết quả.<br />
<br />
Kiểm tra trạng thái sau cấu hình.<br />
<br />
Đây cũng chính là nền tảng để phát triển các hệ thống tự động hóa lớn hơn như:<br />
<br />
Triển khai cấu hình hàng trăm thiết bị cùng lúc.<br />
<br />
Backup cấu hình định kỳ.<br />
<br />
Kiểm tra tính tuân thủ (Compliance).<br />
<br />
Audit cấu hình.<br />
<br />
Zero Touch Provisioning.<br />
<br />
Tích hợp với Ansible, REST API, Nornir hoặc Cisco DNA Center.<br />
<br />
Khi đã nắm vững Netmiko, bước tiếp theo của DevNet sẽ là xây dựng các chương trình Automation có khả năng tương tác với API và quản lý hạ tầng mạng ở quy mô doanh nghiệp.LAB ]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>ThanhTho</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442333-lab-tự-động-cấu-hình-switch-cisco-bằng-python-và-netmiko</guid>
		</item>
		<item>
			<title><![CDATA[Static Code Analysis – &amp;quot;Kiểm tra mã nguồn mà không cần chạy chương trình&amp;quot;]]></title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442188-static-code-analysis-–-kiểm-tra-mã-nguồn-mà-không-cần-chạy-chương-trình</link>
			<pubDate>Thu, 02 Jul 2026 11:34:16 GMT</pubDate>
			<description><![CDATA[DevSecOps (Phần 3): Static Code Analysis – &quot;Kiểm tra mã nguồn mà không cần chạy chương trình&quot; 
 
 
Bạn có thể phát hiện bug mà không cần chạy ứng...]]></description>
			<content:encoded><![CDATA[<b>DevSecOps (Phần 3): Static Code Analysis – &quot;Kiểm tra mã nguồn mà không cần chạy chương trình&quot;</b><br />
<br />
<br />
Bạn có thể phát hiện bug mà <b>không cần chạy ứng dụng</b> hay không?<br />
<br />
Câu trả lời là <b>có</b>.<br />
<br />
Đó chính là nhiệm vụ của <b>Static Code Analysis</b> – một trong những bước quan trọng nhất trong CI/CD Pipeline và cũng là &quot;tuyến phòng thủ đầu tiên&quot; của DevSecOps. <hr /> <b>Static Code Analysis là gì?</b><br />
<br />
<br />
Thông thường, khi kiểm thử phần mềm, chúng ta sẽ chạy chương trình, cung cấp dữ liệu đầu vào và kiểm tra kết quả đầu ra. Đây là cách hoạt động của các bài <b>Unit Test</b>, <b>Integration Test</b> hay <b>Functional Test</b>.<br />
<br />
Ngược lại, <b>Static Code Analysis</b> không chạy chương trình.<br />
<br />
Thay vào đó, các công cụ sẽ <b>đọc trực tiếp source code</b>, phân tích cấu trúc, cú pháp và các quy tắc lập trình để tìm ra lỗi, lỗ hổng bảo mật hoặc những đoạn mã có chất lượng kém ngay từ khi developer vừa commit code.<br />
<br />
Chính vì không cần build hay thực thi ứng dụng nên Static Analysis có tốc độ rất nhanh và thường là bước đầu tiên trong CI Pipeline. <hr /> <b>Static Analysis kiểm tra những gì?</b><br />
<br />
<br />
Các công cụ Static Analysis hiện nay có thể phát hiện rất nhiều vấn đề trước khi phần mềm được biên dịch hoặc triển khai. <b>1. Phát hiện bug tiềm ẩn</b><br />
<br />
<br />
Nhiều lỗi không được Unit Test bao phủ vẫn có thể được phát hiện thông qua việc phân tích mã nguồn.<br />
<br />
Ví dụ:<ul><li>Biến chưa được khởi tạo</li>
<li>Hàm không bao giờ được gọi</li>
<li>Sai cú pháp</li>
<li>Logic dễ gây lỗi</li>
</ul><br />
Một số công cụ phổ biến:<ul><li><b>Prospector</b></li>
<li><b>Pyflakes</b></li>
</ul><hr /> <b>2. Đo độ phức tạp của mã nguồn</b><br />
<br />
<br />
Một hàm dài hàng trăm dòng thường rất khó đọc, khó bảo trì và dễ phát sinh lỗi.<br />
<br />
<b>McCabe</b> sẽ tính toán <b>Cyclomatic Complexity</b> để đánh giá mức độ phức tạp của từng hàm hoặc module.<br />
<br />
Độ phức tạp càng cao thì càng nên được refactor thành các thành phần nhỏ hơn. <hr /> <b>3. Phát hiện Dead Code</b><br />
<br />
<br />
Trong quá trình phát triển, rất nhiều đoạn code cũ không còn được sử dụng nhưng vẫn tồn tại trong repository.<br />
<br />
Những đoạn mã này:<ul><li>làm tăng kích thước dự án</li>
<li>gây khó đọc</li>
<li>tạo thêm bề mặt tấn công nếu chứa lỗ hổng</li>
</ul><br />
<b>Vulture</b> là công cụ chuyên dùng để tìm và loại bỏ những đoạn <b>Unused Code</b> này.  <hr /> <b>4. Kiểm tra lỗ hổng bảo mật</b><br />
<br />
<br />
Đây là phần quan trọng nhất đối với DevSecOps.<br />
<br />
Các công cụ như <b>Bandit</b> sẽ rà soát source code để phát hiện:<ul><li>Insecure Coding Practices</li>
<li>Hardcoded Password</li>
<li>Insecure Random Number</li>
<li>Command Injection</li>
<li>SQL Injection tiềm ẩn</li>
<li>Unsafe Deserialization</li>
<li>Các lỗi thường gặp thuộc <b>OWASP Top 10</b></li>
</ul><br />
Việc phát hiện ngay trong giai đoạn CI giúp giảm đáng kể chi phí khắc phục sau này. <hr /> <b>5. Phát hiện Credentials bị lộ</b><br />
<br />
<br />
Một sai lầm rất phổ biến là đưa trực tiếp vào Git:<ul><li>Password</li>
<li>API Key</li>
<li>Access Token</li>
<li>SSH Private Key</li>
</ul><br />
Một khi đã commit lên repository, việc xóa commit không đồng nghĩa với việc bí mật đã an toàn.<br />
<br />
<b>Dodgy</b> giúp phát hiện các credentials bị hard-code trước khi chúng được merge vào branch chính.  <hr /> <b>6. Kiểm tra kiểu dữ liệu</b><br />
<br />
<br />
Python là ngôn ngữ linh hoạt về kiểu dữ liệu nhưng điều đó cũng dễ dẫn đến các lỗi khó phát hiện.<br />
<br />
<b>Mypy</b> kiểm tra <b>Type Hint</b> để phát hiện:<ul><li>truyền sai kiểu tham số</li>
<li>trả về sai kiểu dữ liệu</li>
<li>sử dụng object không đúng cách</li>
</ul><br />
Điều này đặc biệt hữu ích đối với các dự án lớn có nhiều lập trình viên cùng tham gia. <hr /> <b>7. Chuẩn hóa Coding Style</b><br />
<br />
<br />
Một dự án có hàng chục developer sẽ rất khó bảo trì nếu mỗi người viết theo một phong cách khác nhau.<br />
<br />
Các công cụ như:<ul><li><b>Pylint</b></li>
<li><b>pycodestyle</b></li>
</ul><br />
giúp đảm bảo toàn bộ source code tuân thủ cùng một chuẩn, chẳng hạn <b>PEP 8</b> trong Python Community. Nhờ đó mã nguồn dễ đọc, dễ review và giảm đáng kể các lỗi do thiếu tính nhất quán.  <hr /> <b>Đừng chạy thủ công, hãy để CI/CD làm việc đó</b><br />
<br />
<br />
Mặc dù các công cụ Static Analysis có thể được chạy trực tiếp trên máy của developer, nhưng cách làm hiệu quả nhất là tích hợp chúng vào <b>CI/CD Pipeline</b>.<br />
<br />
Mỗi lần có commit mới:<ul><li>Pipeline tự động chạy Static Analysis.</li>
<li>Nếu phát hiện lỗi hoặc vi phạm chính sách, pipeline sẽ dừng ngay.</li>
<li>Developer nhận phản hồi chỉ sau vài chục giây và sửa lỗi trước khi mã nguồn được merge.</li>
</ul><br />
Đây là một trong những nguyên tắc cốt lõi của DevSecOps:<div style="margin-left:40px"><b>Shift Left Security</b> – đưa các hoạt động kiểm thử và bảo mật về sớm nhất có thể trong vòng đời phát triển phần mềm.</div>  <hr /> <b>CI/CD Pipeline được cấu tạo như thế nào?</b><br />
<br />
<br />
Để tự động hóa toàn bộ quá trình Build – Test – Deploy, mọi hệ thống CI/CD hiện đại đều dựa trên ba thành phần cốt lõi:<ul><li><b>Pipeline</b></li>
<li><b>Stage</b></li>
<li><b>Job</b></li>
</ul><b>Job</b><br />
<br />
<br />
<b>Job</b> là đơn vị nhỏ nhất trong CI/CD.<br />
<br />
Một Job có thể thực hiện một công việc cụ thể như:<ul><li>Build source code</li>
<li>Tạo Docker Image</li>
<li>Chạy Unit Test</li>
<li>Thực hiện Static Code Analysis</li>
<li>Deploy ứng dụng</li>
</ul><br />
Mỗi Job chỉ có hai trạng thái:<ul><li>Success</li>
<li>Failed</li>
</ul><hr /> <b>Stage</b><br />
<br />
<br />
Nhiều Job có cùng mục tiêu sẽ được nhóm thành một <b>Stage</b>.<br />
<br />
Ví dụ:<br />
<br />
<b>Build Stage</b><ul><li>Compile source code</li>
<li>Build Docker Image</li>
<li>Kiểm tra dependency</li>
</ul><br />
<b>Test Stage</b><ul><li>Unit Test</li>
<li>Static Analysis</li>
<li>Security Scan</li>
<li>Code Coverage</li>
</ul><br />
Các Job trong cùng một Stage thường chạy <b>song song (parallel)</b> để rút ngắn thời gian xử lý.<br />
<br />
Nếu <b>chỉ một Job thất bại</b>, toàn bộ Stage sẽ được đánh dấu là <b>Failed</b> và Pipeline dừng ngay lập tức.  <hr /> <b>Pipeline</b><br />
<br />
<br />
<b>Pipeline</b> là thành phần cao nhất, điều phối toàn bộ quá trình Build → Test → Deploy.<br />
<br />
Pipeline thường được khai báo bằng các tệp cấu hình như:<ul><li>.gitlab-ci.yml</li>
<li>GitHub Actions Workflow</li>
<li>Azure Pipelines YAML</li>
<li>Jenkinsfile (Groovy DSL)</li>
</ul><br />
Mỗi khi developer <b>push code</b> lên repository, Pipeline sẽ tự động kích hoạt và thực hiện lần lượt các Stage đã được định nghĩa.<br />
<br />
Một quy trình CI/CD điển hình đối với ứng dụng container hóa sẽ gồm:<ol class="decimal"><li>Tạo Docker Image từ source code.</li>
<li>Chạy các bài kiểm thử trên image vừa tạo.</li>
<li>Đẩy image lên Container Registry.</li>
<li>Triển khai image mới lên máy chủ hoặc môi trường Staging/Production.</li>
</ol><hr /><br />
Static Code Analysis không thay thế Unit Test hay Integration Test, nhưng nó giúp phát hiện rất nhiều lỗi ngay từ khi mã nguồn còn &quot;nằm trên giấy&quot;. Kết hợp Static Analysis với Automated Testing trong CI/CD chính là nền tảng để xây dựng các hệ thống <b>DevSecOps</b> hiện đại: phát hiện lỗi sớm, giảm rủi ro và tăng tốc phát hành phần mềm mà vẫn đảm bảo chất lượng.<br />
​]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>dangquangminh</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/442188-static-code-analysis-–-kiểm-tra-mã-nguồn-mà-không-cần-chạy-chương-trình</guid>
		</item>
		<item>
			<title><![CDATA[TỪ DÂY MẠNG ĐẾN NGUỒN ĐIỆN: &amp;quot;BẮT MẠCH&amp;quot; SWITCH POE &amp;amp; XU HƯỚNG MẠNG THÔNG MINH]]></title>
			<link>https://www.forum.vnpro.org/forum/ccna®/devnet-associate/441885-từ-dây-mạng-đến-nguồn-điện-bắt-mạch-switch-poe-xu-hướng-mạng-thông-minh</link>
			<pubDate>Tue, 23 Jun 2026 10:16:37 GMT</pubDate>
			<description><![CDATA[Khi bạn phải hì hục leo trần thạch cao lắp con Access Point (AP) hay chui rúc kéo dây cho dàn Camera an ninh ngoài xưởng, rồi &quot;tá hỏa&quot; nhận ra......]]></description>
			<content:encoded><![CDATA[<b>Khi bạn phải hì hục leo trần thạch cao lắp con Access Point (AP) hay chui rúc kéo dây cho dàn Camera an ninh ngoài xưởng, rồi &quot;tá hỏa&quot; nhận ra... xung quanh không có cái ổ cắm điện nào ? Kéo thêm một tuyến cáp điện thì vừa xấu, vừa tốn chi phí thi công, lại tăng rủi ro chập cháy.</b><br />
<br />
<br />
<b>Đó chính là lúc &quot;vị cứu tinh&quot; PoE (Power over Ethernet) xuất hiện – truyền luôn nguồn điện DC qua sợi cáp mạng UTP bé tí! </b><br />
<br />
<br />
<b>Nhưng làm sao để nhận diện một con Switch có PoE ở ngoài đời thực, và làm sao để &quot;soi&quot; xem nó đang cấp nguồn cho thiết bị nào bằng lệnh? Cùng mình ôn lại và cập nhật những công nghệ PoE mới nhất nhé!</b><br />
<b><b>1. Nhìn &quot;Mặt&quot; Bắt Hình Dong: Sao Biết Switch Có PoE?</b></b><br />
<br />
<br />
<b>Nếu đi onsite và đứng trước một tủ Rack bạt ngàn thiết bị, anh em có thể nhận diện Switch PoE qua 3 dấu hiệu &quot;vật lý&quot; sau:</b><ul><li><b>Mã sản phẩm (Model Name): Với dân làm Cisco, anh em cứ nhìn vào mã sản phẩm. Thường các dòng Switch có hậu tố P (PoE), FP (Full PoE) hoặc U (UPoE) ở cuối cụm cổng. Ví dụ: C9200L-48P-4G thì chắc chắn 48 cổng đó có PoE.</b></li>
<li><b>Đèn LED Mode &quot;PoE&quot;: Trên mặt trước của Switch Cisco thường có nút nhấn Mode. Anh em bấm chuyển sang mode PoE, nếu đèn ở các port sáng lên (thường là màu xanh lá) thì port đó đang cấp nguồn.</b></li>
<li><b>Ký hiệu trên mặt nạ: Nhiều dòng Switch có in thẳng chữ PoE hoặc có dải vạch màu vàng gạch dưới các port có khả năng cấp điện.</b></li>
<li><b>Nguồn (Power Supply): Switch PoE thường đi kèm với bộ nguồn công suất rất lớn (từ 350W, 715W đến hơn 1000W) và nặng hơn hẳn switch thường.</b></li>
</ul><b><b>2. Dùng Lệnh &quot;Khám Bệnh&quot;: Sao Biết Switch Đang Nuôi Ai?</b></b><br />
<br />
<br />
<b>Để kiểm tra xem Switch (đặc biệt là các dòng Switch Cisco) có hỗ trợ và đang cấp nguồn PoE hay không, câu lệnh quan trọng nhất bạn cần dùng là:</b><br />
<br />
<br />
<b>#show power inline</b><br />
<br />
<b>Các cách dùng chi tiết với câu lệnh này:</b><ul><li><b>show power inline: Sẽ hiển thị bức tranh tổng thể. </b></li>
</ul><br />
<b>Bạn cần chú ý các thông số:</b><ul><li><b>Available / Used / Remaining: Tổng công suất Switch có / Đang xài bao nhiêu / Còn dư bao nhiêu.</b></li>
<li><b>Interface: Cổng mạng nào đang cắm thiết bị.</b></li>
<li><b>Admin / Oper (Status): Trạng thái cổng (Đang Auto cấp nguồn hay bị tắt Off). Nếu hiện On/Powering tức là thiết bị đầu cuối đang &quot;ăn&quot; điện.</b></li>
<li><b>Power (Watts): Thiết bị đang tiêu thụ bao nhiêu Watt.</b></li>
<li><b>Device / Class: Chuẩn PoE và tên thiết bị nhận diện (ví dụ: IEE PD, Class 3, Class 4...).</b></li>
<li><b>show power inline &lt;tên_cổng&gt; (Ví dụ: show power inline gi1/0/1): Dùng khi bạn muốn soi chi tiết trạng thái PoE của riêng một cổng cụ thể (rất hữu ích khi cần chẩn đoán lỗi một con Camera hay AP cắm vào cổng đó mà không lên nguồn).</b></li>
<li><b>show power inline police: Xem các chính sách cấu hình bảo vệ và giới hạn công suất trên các cổng.</b></li>
</ul><br />
<b>Mẹo nhận biết nhanh: Nếu bạn gõ lệnh show power inline mà Switch báo lỗi không nhận diện được lệnh (Unrecognized command), thì khả năng rất cao là hệ điều hành hoặc dòng Switch đó không hỗ trợ phần cứng PoE.</b><br />
<b><b>3. Tại Sao Doanh Nghiệp Lại &quot;Ghiền&quot; PoE Đến Vậy?</b></b><br />
<br />
<br />
<b>Nhiều người nghĩ PoE chỉ để tiện cắm Camera, nhưng bài toán tài chính và quản lý đối với doanh nghiệp lớn hơn thế nhiều:</b><ul><li><b>Tiết kiệm chi phí triển khai (CAPEX): Bỏ qua hoàn toàn chi phí mua dây điện, ống ghen, và tiền nhân công thợ điện. Kéo 1 sợi cáp mạng là xong cả Data lẫn Power.</b></li>
<li><b>Độ tin cậy &amp; An toàn (An toàn điện): Nguồn DC qua cáp mạng (&lt; 60V) an toàn hơn rất nhiều so với điện AC 220V.</b></li>
<li><b>Quản lý nguồn tập trung (Quyền năng của UPS): Tưởng tượng công ty cúp điện. Nếu Camera/AP dùng nguồn adapter rời cắm ở tường thì sập toàn bộ. Nhưng nếu dùng Switch PoE, anh em chỉ cần gắn 1 bộ lưu điện (UPS) khủng cho tủ Rack chứa Switch là hệ thống Wi-Fi, Camera an ninh vẫn &quot;sống nhăn răng&quot; hoạt động bình thường!</b></li>
</ul><b><b>4. PoE Không Chỉ Có Một Loại (Các Chuẩn Cần Nhớ)</b></b><br />
<br />
<br />
<b>Cắm nhầm thiết bị công suất cao vào Switch công suất thấp thì thiết bị sẽ không chạy. Anh em cần phân biệt:</b><ul><li><b>PoE (802.3af): Cấp tối đa 15.4W mỗi cổng. Đủ xài cho IP Phone cơ bản, Camera IP loại nhỏ.</b></li>
<li><b>PoE+ (802.3at): Cấp tới 30W. Xài ngon cho Camera PTZ (có xoay), Wi-Fi AP chuẩn băng tần kép.</b></li>
<li><b>UPoE / PoE++ (802.3bt): &quot;Quái vật&quot; cấp điện từ 60W đến 90W!</b></li>
</ul><b><b>5. Tương Lai Của PoE: Không Chỉ Là Mạng, Mà Là &quot;Smart Building&quot;</b></b><br />
<br />
<br />
<b>Tính năng mới của chuẩn UPoE (802.3bt) hiện nay chính là khả năng tích hợp vào hệ thống bóng đèn chiếu sáng (Smart Lighting).</b><br />
<br />
<b>Anh em không nghe nhầm đâu! Giờ đây, thay vì hệ thống đèn LED trong tòa nhà văn phòng chạy bằng điện 220V AC, người ta nối dây mạng trực tiếp từ Switch Cisco đến thẳng bóng đèn trần.</b><ul><li><b>Bóng đèn dùng điện DC từ Switch để thắp sáng.</b></li>
<li><b>Đồng thời dùng luôn kết nối Data để lập trình bật/tắt qua phần mềm quản lý, tự động giảm sáng khi không có người, hoặc nháy đèn báo động khi có sự cố. Quản trị viên mạng giờ quản lý luôn cả... hệ thống điện tòa nhà!</b></li>
</ul><br />
<br />
​<a href="filedata/fetch?id=441886&amp;d=1782209553" class="bbcode-attachment"  ><img title="poe.jpg" data-attachmentid="441886" width="232" data-align="none" border="0" src="filedata/fetch?id=441886&amp;d=1782209553&amp;type=medium" alt="Click image for larger version

Name:	poe.jpg
Views:	54
Size:	933.5 KB
ID:	441886" data-fullsize-url="filedata/fetch?id=441886&amp;d=1782209553" data-thumb-url="filedata/fetch?id=441886&amp;d=1782209553&amp;type=thumb" data-title="Click on the image to see the original version" data-caption="poe.jpg" class="bbcode-attachment thumbnail js-lightbox bbcode-attachment--lightbox" /></a>]]></content:encoded>
			<category domain="https://www.forum.vnpro.org/forum/ccna®/devnet-associate">CCNA Automation</category>
			<dc:creator>Lương Thị Thùy</dc:creator>
			<guid isPermaLink="true">https://www.forum.vnpro.org/forum/ccna®/devnet-associate/441885-từ-dây-mạng-đến-nguồn-điện-bắt-mạch-switch-poe-xu-hướng-mạng-thông-minh</guid>
		</item>
	</channel>
</rss>
