TLS and transport trust
For installers connecting devices and network operators changing certificates
or image sources. Choose trust independently for each connection; a working
RESTCONF connection does not establish gNOI or kubelet trust. Keep the chart,
CRDs and worker image matched. The public-CA Secret projection below is
introduced in v2026.11.1; October v2026.10.0 installations need the matching
CRD, admission-policy, manager and worker upgrade before using it.
| Connection | Configure and verify |
|---|---|
| Worker to device HTTPS | spec.tls: verified system trust, or an explicitly configured CA |
| Worker to IOS-XE gNOI | Dedicated TLS/provisioning: one trust source and explicit secure transport |
| API server or collector to worker | Kubelet serving certificate: client trust and matching address SANs |
| Worker/device to image source | Image transport: server trust as well as content integrity |
| NETCONF diagnostic probe over SSH | Host-key pinning: a separately mounted known_hosts file |
Use the credential guide for passwords. The sections below describe the trust and key-handling contract; linked runbooks own the full device-command and operation sequence.
Device HTTPS
Device-side TLS is configured under spec.tls. With verified TLS and no custom
CA, the device certificate must chain to the worker's system trust store and
match spec.address.
For controller-managed workers using a private CA, v2026.11.1 supports a
same-namespace public-CA Secret:
kubectl -n default create secret generic switch-https-public-ca \
--from-file=ca.crt=/path/to/trusted-device-ca.crt
Introduced in v2026.11.1; upgrade October installations together
Upgrade the CRD, native admission contract, manager and workers together
before using caSecretRef. The controller validates and projects only
public CA certificates; it does not install a certificate on the switch
or replace dedicated gNOI trust. Read the projection, rotation and rollback
requirements. October deployments need a
system-trusted device certificate or a custom Deployment with mounted CA
files.
For a custom Deployment with explicit mounts, the CiscoDevice fragment is
below. In a standalone configuration file, put these same TLS fields under
device.tls, not spec.tls.
spec:
tls:
enabled: true
insecureSkipVerify: false
caFile: /etc/ssl/certs/corp-ca.crt
certFile: /etc/ssl/cvk/client.crt
keyFile: /etc/ssl/cvk/client.key
| Field | Notes |
|---|---|
enabled |
Turn on HTTPS. Required in production. |
insecureSkipVerify |
true disables certificate verification. Acceptable for lab devices with self-signed certs; do not use in production. |
caSecretRef.name |
Projects the same-namespace Secret's validated public ca.crt; introduced in v2026.11.1, mutually exclusive with caFile, and requires verified TLS. |
caFile |
Trust anchor for verifying the device certificate. |
certFile, keyFile |
Optional client certificate — required only if the device enforces mutual TLS. |
The certFile / keyFile / caFile paths refer to files inside the VK pod.
Mount private certificates and keys from a Secret-backed volume; public CA
material may come from a Secret or ConfigMap. The controller does not currently
auto-mount these shared paths—you need a custom Deployment or chart extension.
The configdriver transports, MDT-over-gNMI telemetry, and the NX-API client on
NX-OS honour the full spec.tls block through one shared builder. IOS-XE
app-hosting RESTCONF constructs its TLS client separately. gNOI resolves port,
authentication, and exactly one trust source together: the system root pool,
verified shared spec.tls, dedicated spec.gnoi.tls, or IOS-XE provisioning
trust. Shared and gNOI-specific file configurations reject a certFile or
keyFile without its matching pair. During migration, remove an obsolete
orphan path or supply the complete pair: a lone shared certFile or keyFile
that an older release silently ignored now fails startup for every consumer of
the shared TLS builder.
Secure IOS-XE gNOI
Choose the gNOI trust source
With explicit gnoi.transportSecurity: tls, CVK sends the device username and
password as separate per-RPC metadata fields over verified TLS. Pre-existing
configurations that do not opt in retain their legacy HTTP Basic metadata
behavior, including on plaintext listeners, solely for compatibility. Migrate
them to explicit secure gNOI. Avoid metadata logging and limit access to the
credential Secret.
Kubernetes-specific spec.gnoi.tls accepts only a same-namespace secretRef.
Its Secret requires ca.crt; optional mutual TLS requires both tls.crt and
tls.key. The controller validates the PEM material, projects only those fixed
keys read-only, and rolls the worker after a valid Secret change when gNOI is
enabled in per-device topology. With global gNOI disablement, the per-device
worker remains but omits the trust projection and does not roll for trust-Secret
changes. Aggregated config-only topology has no per-device worker. Direct local
configuration uses caFile and an optional certFile/keyFile pair instead;
paths are rejected by the Kubernetes API. There is intentionally no gNOI
enabled or insecureSkipVerify field.
The controller manager watches these Secrets through its cached Kubernetes
client. Complete Secret objects—including unrecognized keys and provisioning
ca.key material—may therefore remain in the manager cache and process memory
for its lifetime, even though reconciliation acts only on the documented keys.
Manager RBAC, logs, debugging access, and pod exec are part of the trust
boundary. Secret bytes are never copied into the worker ConfigMap, status,
events, or logs. Restrict Secret reads and access to both the manager and the
per-device worker, where private keys are mounted only when required.
Provisioning and signer retirement
The dedicated provisioning Secret referenced by
spec.xe.gnoi.certificateProvisioning.secretRef always supplies tls.crt and
ca.crt. It automatically becomes the isolated gNOI bootstrap and
steady-state trust source, so it cannot be combined with spec.gnoi.tls.
An insecure top-level spec.tls may remain for an unrelated legacy transport
only because gNOI never inherits it in this mode. bootstrap.crt is an
optional exact pin for the temporary IOS-XE leaf, and
ca.key is used only by the gated ProvisionCertificate action. The key is
kept separate from the read-only trust bundle behind a CertificateSigner
boundary. The included local PEM signer is transitional and can sign a new CSR
for a corrected immutable action after a definitive pre-Install failure;
create-only device Install remains at-most-once per action. The parsed key stays
in worker process memory until exit or a completed key-free rollout. No
external CA, KMS, or HSM signer backend is included. Each action must bind the
configured certificate ID and the lowercase
SHA-256 of the exact tls.crt || ca.crt bytes; a stale or mismatched public
intent is rejected before the worker acquires a gNOI client or marks the action
Running. ca.key and bootstrap.crt are projected only while write-class gNOI
is enabled and a non-empty ca.key is present. The signing key must belong to
a dedicated intermediate CA; root keys are rejected. Enable Secret
encryption at rest, restrict Secret reads and pod exec, and audit both.
Secret projection is not an authorization boundary: the standard VK
ClusterRole can read Secrets cluster-wide so VK nodes can serve pod volumes.
After provisioning is verified, promptly remove ca.key and bootstrap.crt;
disable the write-class gate too unless other write actions are still needed.
Never create or update a signer-bearing Secret with client-side
kubectl apply: its last-applied annotation retains the submitted key even
after .data.ca.key is removed. Use a secret manager, direct create, or
server-side apply, and follow the
key-free cleanup procedure
to remove any legacy annotation and prove the replacement worker is key-free.
Keep the public certificate and CA bundle for read-only gNOI trust. Deployments
use a non-overlapping Recreate strategy while a signer may be resident, for
the first key-free cleanup rollout, and whenever write-class gNOI actions or
IOS-XE software upgrades are enabled. This prevents two worker generations
from concurrently acting on the same durable mutation claim. Normal rolling
updates resume only after signer cleanup is complete and both mutation gates,
or gNOI globally, are disabled. Disabling gNOI entirely suppresses the
provisioning Secret mount and its rollout annotation.
The installed identity and CA bundle are scoped to gNOI in CVK, but IOS-XE shares them with gNMI. Installation can restart gNXI, replace peer trust, and change the server certificate seen by other clients; schedule it as a device change. CVK does not reconfigure RESTCONF, NETCONF, app-hosting, or telemetry client settings, so ensure every gNMI client already trusts the new issuer.
See the secure gNOI and CSR provisioning workflow for the complete Secret contract, one-shot action, trust-bundle warning, and verification sequence.
Hosted application image input
On NX-OS, a pod's image value is treated as untrusted CLI input. CVK accepts
only a single validated bootflash: path or HTTP(S) URL token before issuing
an app-hosting install command; whitespace, control characters, command
separators, user information, and other unsafe syntax are rejected before any
NX-API request. Prefer pre-staged bootflash: packages for production use.
The IOS XE cisco.io/apphost-package-dest annotation accepts only
bootflash:, harddisk:, flash:, nvram:, or usb: followed by path
segments using ASCII letters, digits, -, ., _, or ~. Empty, . and
.. segments are rejected. Rename existing destination paths containing
spaces, +, control characters, or other punctuation before upgrading.
Software-upgrade image transport
URL image resolution is capped at 8 GiB by default and uses private-mode files
inside the worker's /tmp emptyDir; symlink and non-regular cache entries are
rejected. Configure the cap with gnoi.softwareUpgrade.maxImageBytes, budget
ephemeral storage for one full image plus normal pod and filesystem overhead,
and remember that SHA-256 integrity does not make plaintext HTTP, FTP, or TFTP
confidential or authenticate their servers. CVK verifies a private temporary
file and atomically promotes that same file to its digest cache, avoiding a
second full-image copy. Prefer HTTPS or host-key-verified SFTP/SCP for
production image repositories. Pod exec and node-root access remain inside the
image-file trust boundary.
SSH host keys
NETCONF and the CLI side-channel ride SSH, not TLS. Pinning uses a standard
OpenSSH known_hosts file (multi-host files cover a fleet). Ship it into the
VK pod with a Secret- or ConfigMap-backed volume and point
CONFIG_SSH_KNOWN_HOSTS at the mounted path; the NETCONF diagnostic probe
(CONFIG_NETCONF_PROBE) then pins its dials against it and refuses to dial
unpinned if the file fails to load. Without the variable the probe keeps the
historical lab default of accepting any presented key — as with
insecureSkipVerify, do not rely on that in production.
Kubelet-side TLS
The VK runs its own HTTPS listener on :10250. It first uses the configured
serving certificate/key, defaulting to /etc/virtual-kubelet/tls/tls.crt and
tls.key. If both are absent, it generates a self-signed pair under
/var/lib/virtual-kubelet/tls/; exactly one configured file being present is an
error. Supply a pair trusted by the connecting client, with matching address
SANs, using:
Configure the API server or metrics collector's trust for this serving
certificate as appropriate to its connection path. Avoid disabling kubelet
certificate verification cluster-wide for one virtual Node. TLS trust alone
does not provide hosted-application streaming: logs, exec, attach and
port-forward return HTTP 501. Use kubectl logs on the worker Pod, which
runs on an ordinary Kubernetes node, for CVK diagnostics. Device/Node metrics
also do not provide per-Pod resource usage for HPA/VPA; see
Observability.
Verify each connection separately
A Ready app-hosting worker confirms neither dedicated gNOI trust nor a metrics collector's trust of the kubelet listener. Check the relevant worker's sanitized connection errors, perform the read-only probe documented for that transport, and confirm the certificate matches the address being used. After gNOI provisioning, complete the key-free cleanup and verification before treating the change as finished.
For field definitions use Configuration; for operation procedures use the gNOI runbook. Continue with authorization or return to the security overview.