The modern enterprise network landscape is characterized by increasing complexity and the proliferation of security appliances. FortiGate firewalls, engineered by Fortinet, serve as critical anchors in these environments, providing robust security and networking capabilities. However, as the number of managed devices grows, the traditional method of manual configuration via the FortiOS web user interface (UI) becomes an operational bottleneck. This manual approach is not only tedious and time-consuming but also prone to human error, which can lead to security vulnerabilities or network outages. To mitigate these risks and enhance operational efficiency, network engineers are pivoting toward Infrastructure as Code (IaC) principles.
Ansible emerges as the premier tool for this transition. By utilizing a well-maintained collection specifically designed for FortiOS, administrators can automate nearly every aspect of FortiGate management. This shift from a "click-and-configure" mentality to a "code-and-deploy" strategy allows for the simultaneous provisioning, configuration, and management of multiple FortiGate units. This ensures that security policies remain consistent across the entire fleet, reducing the "configuration drift" that often occurs when devices are updated individually.
The integration of Ansible with FortiGate relies on the fortinet.fortios collection, which abstracts the complex FortiOS API into manageable Ansible modules. By defining the desired state of the firewall in YAML files, engineers can execute changes across hundreds of devices with a single command. This comprehensive guide explores the technical implementation of this automation, from the initial installation of the Ansible environment to the advanced management of SSL certificates and the execution of complex playbooks.
The Technical Foundation of Ansible Installation
Before executing any automation, a properly configured control node is required. The control node is the Linux machine where Ansible is installed and from which the playbooks are pushed to the FortiGate devices.
The installation process begins with updating the local package index to ensure the latest software versions are retrieved from the repositories. This is achieved using the following command:
apt-get update
Once the package index is current, the Ansible core package is installed. The following command is utilized:
apt-get -y install ansible
From a technical and administrative perspective, these commands must be executed with root-level privileges. In Linux environments, the apt-get utility modifies system-level binaries and configuration files, which are protected by the operating system. If the current user is not the root user, they must be added to the sudoers list to grant elevated permissions. Failure to do so will result in a permission denied error, halting the installation process.
The impact of this setup is the creation of a centralized orchestration point. By consolidating the management logic on a single Linux host, the administrator eliminates the need to log into each firewall individually. This architectural shift connects the physical hardware of the FortiGate to the logical abstraction of the Ansible playbook, creating a streamlined pipeline for network changes.
FortiOS Collection Deployment and Dependency Management
The base Ansible installation provides the engine, but the specific "knowledge" required to interact with FortiGate devices is contained within the fortinet.fortios collection. This collection is distributed via Ansible Galaxy, the public hub for Ansible content.
To install the official Fortinet collection, the following command is executed:
ansible-galaxy collection install fortinet.fortios
For organizations requiring a more structured deployment, the collection can be defined within a requirements.yml file. This allows the infrastructure team to version-control their dependencies. The format for the requirements.yml file is as follows:
yaml
collections:
- name: fortinet.fortios
The installation from this file is then triggered using:
ansible-galaxy collection install -r requirements.yml
In addition to the collection, communication with the FortiOS API often requires specific Python libraries to handle the data exchange. The fortiosapi library is essential for these interactions and should be installed via the Python package manager:
pip install fortiosapi
Technical Requirements and Versioning
To ensure stability and compatibility, the environment must meet specific software prerequisites. The system requirements for the FortiOS collection are:
- Ansible-core 2.16 or above
- Python 3.12 or above
Managing these versions is critical because updates to the FortiOS API can occasionally break compatibility with older Ansible modules. To maintain the latest features and security patches, the collection should be upgraded regularly using the following command:
ansible-galaxy collection install fortinet.fortios --upgrade
Conversely, if a new release introduces a regression or a bug that disrupts production traffic, the administrator can downgrade to a specific, known-stable version. For example, to install version 2.3.9, the following syntax is used:
ansible-galaxy collection install fortinet.fortios:==2.3.9
This granular control over versioning prevents "breaking changes" from cascading through the network, ensuring that firewall updates are predictable and reversible.
Authentication Strategies and Connectivity
Establishing a secure connection between the Ansible control node and the FortiGate device is the most critical step in the automation pipeline. FortiOS provides two primary methods for authentication.
Username and Password Authentication
This method uses the standard administrative credentials of the FortiGate device. In the Ansible inventory or variable files, these are mapped to ansible_user and ansible_password. While common, this method is generally considered less secure because it involves passing passwords, which may be exposed if not handled via Ansible Vault.
Access Token Authentication
The recommended method for enhanced security is the use of an access token (fortios_access_token). Access tokens are unique strings generated within the FortiOS administrative settings that grant the holder specific API permissions without requiring the primary admin password. This minimizes the risk of credential theft and allows for easier auditing and revocation of access.
The technical implementation of these authentication methods occurs within the inventory file. The connectivity is typically established via the httpapi connection plugin, which allows Ansible to communicate directly with the FortiOS REST API rather than relying on a standard SSH shell.
Inventory Configuration and Variable Definition
The inventory file is the heart of the Ansible setup, mapping the logical groups of devices to their physical IP addresses and defining the parameters for the connection.
To create the inventory file, a Linux text editor such as nano or vim is used:
nano <file name>
The file must be structured to define the hosts and the variables required for the fortinet.fortios modules to function. The following table provides a detailed breakdown of the required inventory components.
| Section | Variable/Parameter | Description | Example Value |
|---|---|---|---|
| Host Group | [fortigates] |
Defines the group of managed firewalls | fgt |
| Connection | ansible_host |
The IP address of the FortiGate device | 192.168.1.1 |
| Credentials | ansible_user |
Admin username for authentication | admin |
| Credentials | ansible_password |
Admin password for authentication | password123 |
| Security | fortios_access_token |
API Token for secure access | abc123xyz |
| OS Module | ansible_network_os |
Specifies the target OS for modules | fortinet.fortios.fortios |
| Connection Type | ansible_connection |
Sets the protocol to HTTP API | httpapi |
| SSL Validation | ansible_httpapi_validate_certs |
Disables SSL certificate check | no |
| SSL Usage | ansible_httpapi_use_ssl |
Enables HTTPS communication | yes |
A practical example of a fully populated inventory file would look like this:
```text
FortiGate Host
[fortigates]
fgt ansiblehost=192.168.1.1 ansibleuser="admin" ansiblepassword="password123"
fortigate ansiblehost=192.168.1.2 fortiosaccesstoken=abc123xyz
FortiGate OS Modules
[fortigates:vars]
ansiblenetworkos=fortinet.fortios.fortios
Specify API connection with HTTP (default SSH)
[all:vars]
ansibleconnection=httpapi
ansiblehttpapivalidatecerts=no
ansiblehttpapiuse_ssl=yes
```
When using nano, the administrator must press Ctrl + X to save the file and exit. This file serves as the source of truth for Ansible, ensuring that the correct credentials and connection parameters are applied to each target device.
Playbook Architecture and YAML Standards
Ansible playbooks are written in YAML (YAML Ain't Markup Language), a human-readable data serialization language. Because YAML is strictly space-sensitive, the structural integrity of the file is paramount.
The Golden Rule of YAML Formatting
A critical requirement for FortiOS playbooks is the avoidance of the Tab key. In YAML, indentation is used to define hierarchy and nesting. Using a Tab character instead of spaces will result in a syntax error, causing the playbook to fail during the parsing phase. Every layer of the YAML file must be differentiated and separated using spaces.
Playbook Structure and Task Execution
A playbook typically consists of a series of tasks. For complex environments, it is a best practice to use include_tasks to modularize the configuration. This allows the administrator to separate different functional areas, such as firewall policies and address objects, into different files for better maintainability.
An example of a task list that includes external files would be:
yaml
tasks:
- include_tasks: file1_get_policy.yml
- include_tasks: file2_get_address.yml
Once the YAML configuration files are finalized, the playbook is executed using the ansible-playbook command. This command requires the path to the inventory file and the name of the playbook file:
ansible-playbook -i <variable text file name> < YAML file name>
The execution of this command triggers the Ansible engine to parse the inventory, establish an HTTP API connection to the FortiGate units, and apply the configurations defined in the YAML tasks.
Advanced Integration: SSL Certificate Management
Managing SSL certificates on FortiGate devices is a common yet complex task. In an automated environment, certificates must be rotated and updated regularly to avoid service interruptions.
One advanced method for handling this is through the use of a Secure Web Application Gateway (SWAG) instance. SWAG provides a bundled Certbot implementation, which automates the acquisition and renewal of Let's Encrypt certificates.
The workflow for this integration involves:
- The SWAG instance, running in a Docker container, manages the certificate renewal.
- The certificates are stored in a Docker mounted volume.
- Ansible is used to
rsyncthe generated certificates from the SWAG volume to a local folder on the Ansible control node. - Ansible then pushes these certificates to the FortiGate device using the appropriate FortiOS modules.
This process ensures that the firewall always possesses a valid, trusted certificate without requiring manual uploads through the web UI. Users can also choose to generate certificates using a standalone Certbot installation or pull them from any local storage accessible to the Ansible host.
Practical Implementation Examples and Troubleshooting
While official collections provide the framework, real-world application often requires adaptation. Example playbooks, such as those found in the ansible_fortios_examples repository, serve as templates. However, it is important to note that these examples are not designed to run "out of the box" and must be adapted to the specific network topology and naming conventions of the target environment.
Common Troubleshooting Steps
Establishing connectivity can be challenging for new users. The following steps are recommended to troubleshoot connection failures:
- Verify that the FortiGate device has the REST API feature enabled.
- Ensure that the administrative user has the correct permissions to access the API.
- Confirm that the Ansible control node can reach the FortiGate IP address over the network (typically via port 443 for HTTPS).
- Double-check the
ansible_httpapi_validate_certssetting. If the FortiGate is using a self-signed certificate, this must be set tonoto prevent the connection from being rejected due to an untrusted certificate chain.
Conclusion: The Impact of Automation on Network Security
The transition to Ansible-driven management for FortiGate firewalls represents a fundamental shift in network administration. By moving away from manual configuration, organizations can achieve a state of "Deterministic Networking," where the configuration of every device is known, documented, and reproducible.
The technical layer of this implementation—utilizing the fortinet.fortios collection, configuring httpapi connections, and adhering to strict YAML standards—creates a robust framework for scalability. The impact is a significant reduction in the time required to deploy global policy changes. For instance, updating a single blocked IP address across fifty firewalls, which would take hours via the web UI, can now be accomplished in seconds through a single playbook execution.
Furthermore, the integration of external certificate management tools like SWAG and Certbot demonstrates that Ansible can extend beyond simple configuration changes to full lifecycle management of security assets. By automating the rotation of SSL certificates, the risk of downtime due to expired credentials is virtually eliminated.
Ultimately, the use of Ansible with FortiGate is not merely about speed; it is about accuracy and security. The ability to version-control network configurations via Git and deploy them through a CI/CD pipeline ensures that every change is audited and tested. This level of control is essential for maintaining compliance in highly regulated industries and for ensuring the resilience of the enterprise perimeter.