First Steps
This guide walks you through configuring Cisco Secure Firewall Management Center (FMC) using Network as Code — starting from a single YAML file and a one-line Terraform module, then progressively introducing FMC’s objects, access control policy, and device registration constructs that let you manage FMC’s full configuration as data.
Prerequisites:
- Terraform 1.8.0 or later
- Your preferred text editor / IDE (such as Visual Studio Code)
- An FMC (or cdFMC) instance reachable from your workstation, with REST API access enabled (see step 1)
-
Verify FMC API Access
Section titled “Verify FMC API Access”FMC’s REST API is enabled by default, so Terraform can typically communicate with it right away. If it has been disabled, log in to the FMC admin console and:
- Navigate to System -> Configuration -> REST API Preferences.
- Enable Enable REST API.
- Click Save.
-
Set Environment Variables
Section titled “Set Environment Variables”The FMC provider authenticates using environment variables. For a self-hosted FMC, set the following in your terminal:
Terminal window export FMC_URL=https://10.1.1.100export FMC_USERNAME=adminexport FMC_PASSWORD=password -
Create Your First Data File
Section titled “Create Your First Data File”In a new project directory, create a file named
fmc.nac.yamlwith the following content:fmc:domains:- name: Globalobjects:hosts:- name: Server1ip: 10.1.2.3This file describes a single host object, nested under the
Globaldomain. Every piece of FMC configuration lives under a domain —Globalis the default domain present on every FMC. -
Create the Terraform Configuration
Section titled “Create the Terraform Configuration”In the same directory, create a file named
main.tf:module "fmc" {source = "netascode/nac-fmc/fmc"version = "0.1.3"yaml_files = ["fmc.nac.yaml"]}This is the only Terraform configuration required. The
nac-fmcmodule reads the YAML file and maps its contents to the underlying FMC provider resources automatically. -
Initialize Terraform
Section titled “Initialize Terraform”Run the following command to download the provider and module:
Terminal window terraform init -
Apply the Configuration
Section titled “Apply the Configuration”Preview and apply your changes:
Terminal window terraform applyReview the plan and type
yesto confirm. Terraform pushes the configuration to FMC via its REST API.
Congratulations! You have created your first FMC object using Network as Code. The sections below show how to expand this foundation into FMC’s other configuration areas — network objects and security zones, access control policy, and device registration.
All of the sections below build on the same fmc.nac.yaml file — there is only ever one file, and every configuration item lives under the same Global domain entry, under the single root fmc: key. Each code block below is complete and paste-able as shown:
- When a block updates a section you already have (like
objectsbelow), it shows that section in full — replace what you had with it. - When a block adds a new section, a
# ...comment marks where your existing sections go; only the new section needs to be added to your file, alongside what is already there.
A “Putting It All Together” snippet at the end shows the complete file after all the sections have been added.
Going Further
Section titled “Going Further”Network Objects and Security Zones
Section titled “Network Objects and Security Zones”Beyond hosts, FMC objects include networks and security zones — the building blocks referenced by access control policy and device interfaces.
Update the objects block in fmc.nac.yaml — replacing what you added in step 3 — to add a network object and two security zones:
fmc: domains: - name: Global objects: hosts: - name: Server1 ip: 10.1.2.3 networks: - name: LAN prefix: 192.168.1.0/24 security_zones: - name: inside - name: outsideLAN is a network object representing the 192.168.1.0/24 prefix, and inside/outside are security zones that interfaces and access control rules can reference by name.
Access Control Policy
Section titled “Access Control Policy”Access control policy determines what traffic FMC-managed devices allow, and is built from a category (used to group and order rules), one or more access rules, and a default action for anything that doesn’t match a rule.
policies is a new section. Add it to fmc.nac.yaml alongside the objects block from the previous step, with an access control policy that has one category and one rule allowing traffic from outside to the Server1 host on the inside zone:
fmc: domains: - name: Global # ... objects from the previous step ...
policies: access_control_policies: - name: MyAccessControlPolicy default_action: BLOCK categories: - name: MyCategory section: mandatory access_rules: - name: Allow-Web action: ALLOW category: MyCategory source_zones: - outside destination_zones: - inside source_network_literals: - "0.0.0.0/0" destination_network_objects: - Server1 log_connection_end: true send_events_to_fmc: trueThe policy’s default_action blocks anything that isn’t explicitly allowed. The Allow-Web rule, in the mandatory MyCategory category, permits traffic from any source (a network literal rather than an object) to Server1, and logs the connection to FMC when it ends — log_connection_end requires a destination for the events, so send_events_to_fmc must also be set. This policy isn’t attached to a device yet — the next section registers a device and references it via access_control_policy.
Device Registration
Section titled “Device Registration”Registering a device tells FMC to manage a Firepower Threat Defense (FTD) appliance — assigning it a policy, its licenses, and its interface configuration. Interfaces, VRFs (virtual routers), and static routes are all nested under a device’s vrfs list; a device always has at least one, typically named Global.
devices is the last new top-level section. The static route below points at any-ipv4 — a network object that ships with every FMC. Since NaC doesn’t own it, it must be declared under a separate top-level existing key (a sibling of fmc in the same file) before anything can reference it; without that declaration, terraform apply fails to resolve the reference. Add both existing and the devices section to fmc.nac.yaml, alongside objects and policies, with one FTDv device that references the access control policy from the previous step, and maps its inside/outside security zones to two physical interfaces:
existing: fmc: domains: - name: Global objects: networks: - name: any-ipv4
fmc: domains: - name: Global # ... objects and policies from previous steps ...
devices: devices: - name: FTD1 host: 10.1.2.10 registration_key: cisco123 access_control_policy: MyAccessControlPolicy licenses: - BASE - THREAT performance_tier: FTDv5 vrfs: - name: Global physical_interfaces: - name: GigabitEthernet0/0 logical_name: outside security_zone: outside ipv4_static_address: 100.64.0.10 ipv4_static_netmask: 24 - name: GigabitEthernet0/1 logical_name: inside security_zone: inside ipv4_static_address: 192.168.1.254 ipv4_static_netmask: 24 ipv4_static_routes: - name: default gateway: literal: 100.64.0.1 interface_logical_name: outside selected_networks: - any-ipv4FTD1 registers with the registration_key set on the device during initial setup, and is immediately assigned MyAccessControlPolicy. Each physical interface gets a logical_name — used elsewhere in the configuration (like interface_logical_name on the static route) instead of the physical port name — and is tied to the outside/inside security zones created earlier. The default route’s any-ipv4 reference resolves against the existing declaration added above it.
Putting It All Together
Section titled “Putting It All Together”After working through the sections above, your fmc.nac.yaml should look like this in full — including the existing block that declares the built-in any-ipv4 object referenced by the device’s static route:
existing: fmc: domains: - name: Global objects: networks: - name: any-ipv4
fmc: domains: - name: Global objects: hosts: - name: Server1 ip: 10.1.2.3 networks: - name: LAN prefix: 192.168.1.0/24 security_zones: - name: inside - name: outside
policies: access_control_policies: - name: MyAccessControlPolicy default_action: BLOCK categories: - name: MyCategory section: mandatory access_rules: - name: Allow-Web action: ALLOW category: MyCategory source_zones: - outside destination_zones: - inside source_network_literals: - "0.0.0.0/0" destination_network_objects: - Server1 log_connection_end: true send_events_to_fmc: true
devices: devices: - name: FTD1 host: 10.1.2.10 registration_key: cisco123 access_control_policy: MyAccessControlPolicy licenses: - BASE - THREAT performance_tier: FTDv5 vrfs: - name: Global physical_interfaces: - name: GigabitEthernet0/0 logical_name: outside security_zone: outside ipv4_static_address: 100.64.0.10 ipv4_static_netmask: 24 - name: GigabitEthernet0/1 logical_name: inside security_zone: inside ipv4_static_address: 192.168.1.254 ipv4_static_netmask: 24 ipv4_static_routes: - name: default gateway: literal: 100.64.0.1 interface_logical_name: outside selected_networks: - any-ipv4Run terraform apply once more to apply everything in one pass.
You now have the full building blocks of a Network as Code FMC deployment. Explore the FMC Data Models section for the complete list of configurable attributes, and the simple example repository for a reference implementation.