Automating Post-Quantum IPsec on Cisco Routers – IPsec Series, Part 12 Cisco IOS XE 26.2 exposes post-quantum IPsec configuration as real YANG models, but the Cisco-IOS-XE-crypto.yang module contains zero rpc statements, so actions like 'crypto key generate mldsa', 'crypto pki enroll', and 'clear crypto ikev2 sa' must still run over CLI, according to a DevNet-focused blog post by Julio Gomez. The post details four Ansible-over-NETCONF playbooks for a three-router hub-and-spoke lab that push ML-KEM-768, optional or required, and ML-DSA-65 authentication, with playbooks published on GitHub. The author argues automation matters because a single missed 'pqc mlkem768 optional' line leaves one spoke tunnel classical while the others go hybrid, and because changing a proposal does not renegotiate an already-established SA. I know, I know… I said I was done with the IPsec series, BUT what would this series say about me if I did not automate everything?? In the last few blog posts we reviewed the CLI story: classical baseline, PPK, ML-KEM hybrid, ML-DSA certificates, the atomic cutover. That’s how you LEARN a platform. But that is not how you RUN a fabric. And if you’ve been hanging around DevNet https://developer.cisco.com/ for a while, you already know the next move. That was the point the whole time: enable the community on programmability so you can stop typing at boxes and start driving them through APIs. YANG, NETCONF, RESTCONF, Ansible: years of that work. API-driven automation was one of the main goals. Let’s now use those habits to configure Post-quantum IPsec Type the same IKEv2 profile on three boxes, change two addresses, and you’ll get two routers agreeing and one that doesn’t. You’ll find out a week later. The post-quantum posture is a decision : ML-KEM-768, optional or required, ML-DSA-65. You want to state it once, push it, and prove the live SA actually used it. DONE. This post is that layer. Same lab, same RFCs, same two pillars. The interface is Ansible over NETCONF instead of three consoles. All docs and Ansible playbooks are available in my GitHub https://github.com/juliogomez/pqc/blob/main/deploy/c8000/automation/README.md for your own testing, but if you don’t have three routers in your lab you can still follow. You won’t be typing along unless you’ve got the boxes. What you’ll see is the playbooks we ran, the XML that actually landed, and the show output that came back. Why this is worth automating Go back to Part 9’s hub-and-spoke. The hub needs one IKEv2 profile per spoke. Each spoke needs one toward the hub. The proposal, the transform set, the tunnel, the fragmentation MTU: same lines, two addresses flipped. Then add PQC and the cost of a typo goes up. Forget “pqc mlkem768 optional” on one spoke and that tunnel stays classical while the others go hybrid. Forget fragmentation and the handshake never completes. Flip authentication on one end of a pair and, as Part 11 showed, the tunnel dies until the other end follows. Automation is not about saving keystrokes. It’s about stating the posture in one place and refusing to move on until the box agrees. Config is modelled. Actions are not. Here’s the load-bearing fact about IOS XE 26.2, and it shapes everything below. The post-quantum configuration is real YANG. Not CLI strings shipped over a fancier wire. Named leaves, typed, validated at the edit. If you’ve consumed a Cisco IOS XE model before, this is the same muscle. The leaf names are new e.g. mlkem768 or mldsa-sig . The pattern is not: read the model, send structured data, check what came back. | Intent | Where it lives | |---|---| | ML-KEM group | /native/crypto/ikev2/proposal name /pqc/mlkem768 | | PPK RFC 8784 | /native/crypto/ikev2/keyring name /peer name /ppk/manual/... | | ML-DSA auth | trustpoint mldsakeypair + authentication/{local,remote}/mldsa-sig | What YANG will not do is ask the box to do something. Cisco-IOS-XE-crypto.yang has zero rpc statements. So these still go over CLI: - crypto key generate mldsa - crypto pki enroll - clear crypto ikev2 sa “This proposal should offer ML-KEM-768” is expressible. “Renegotiate now” is not. And you need both, because changing a proposal does not touch an SA that is already up. Push ML-KEM, read the operational data, see no PQC, and you’ll conclude the feature is broken when it simply hasn’t renegotiated. That’s the whole design in one paragraph. Desired state over NETCONF. The handful of actions over CLI, marked as escape hatches, not buried. Four playbooks, same progression Three routers in hub-and-spoke. One playbook per unit. Each one tears itself down with -e state=absent . Every apply ends by reporting the resulting posture. ┌─ PPK ────────────┐ baseline ───────────┼─ ML-KEM ─────────┼─────────► ML-DSA └─ neither ────────┘ ▲ pick one | Playbook | What it is | Maps to | |---|---|---| | ipsec-baseline.yml | classical Diffie-Hellman | Part 9, the IKEv2 baseline | | ipsec-pq-ppk.yml | RFC 8784 PPK | Part 9, the PPK section | | ipsec-pq-mlkem.yml | native ML-KEM-768 hybrid | Part 9, native ML-KEM | | ipsec-pq-mldsa.yml | authentication swaps to ML-DSA certificates | Parts 10 and 11 | PPK and ML-KEM are alternatives, not steps . Same rule as Part 9: we never stack them. ML-DSA is orthogonal. It swaps how identity is proved and does not care whether you chose PPK, ML-KEM, or neither for keying. The posture itself lives in one file, “pqc.yml”. Two lines decide the IPsec half of the lab: pq key exchange: mlkem768 pq key exchange optional: true pq signature param set: 65 Change a value, re-run, every proposal on the fabric moves. You should never have to open an XML template. Before any of that, “bootstrap.yml” turns NETCONF on. That one still runs over SSH CLI, because you can’t configure the transport over the transport. 🙂 First run waits for the subsystem on these boxes, a bit over two minutes . Second run diffs against the running config, pushes nothing, and reports changed=false . ML-KEM is two leaves “ipsec-pq-mlkem.yml” adds two YANG leaves to the existing proposal and nothing else. The payload that lands on the box looks like this: