Skip to content

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:

  1. 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.
  2. 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.100
    export FMC_USERNAME=admin
    export FMC_PASSWORD=password
  3. In a new project directory, create a file named fmc.nac.yaml with the following content:

    fmc:
    domains:
    - name: Global
    objects:
    hosts:
    - name: Server1
    ip: 10.1.2.3

    This file describes a single host object, nested under the Global domain. Every piece of FMC configuration lives under a domain — Global is the default domain present on every FMC.

  4. 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-fmc module reads the YAML file and maps its contents to the underlying FMC provider resources automatically.

  5. Run the following command to download the provider and module:

    Terminal window
    terraform init
  6. Preview and apply your changes:

    Terminal window
    terraform apply

    Review the plan and type yes to 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 objects below), 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.

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: outside

LAN 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 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: true

The 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.

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-ipv4

FTD1 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.

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-ipv4

Run 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.