For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Using Ansible to Manage BGP on BIG-IP

So, if you've ever wanted to manage BGP (Border Gateway Protocol) Settings for your BIG-IP with Ansible, you may have run into an issue with not having an ansible module for advanced routing. You could maybe use bigip_command, but not all tmsh is created equal, with respect to advanced routing commands. Functionality is version dependent.  I present to you, a way to manage BIG-IP's BGP configuration via imish. This particular example was used by a service provider as part of a configuration process for BIG-IP VE in a CI/CD pipeline, created by OpenStack HEAT.

Since we cannot rely on BIG-IP Ansible modules, we must use native ansible, which uses ssh as a default transport, versus https. To accomodate for this, I made an adjustment in my hosts file (password can be keyed also.. it was a Proof of Concept):

[test]
192.168.197.131

[test-ssh]
192.168.197.131 ansible_connection=ssh ansible_ssh_user=root ansible_ssh_pass=default

Since the customer wanted to be able to make changes on the fly, I used the blockinfile module from Ansible, which denotes a block of code with a # character, and the lineinfile module, which adds a line in a specified file, to update a bash script on the box in /tmp, which we apply with imish. To finish it off, we use the shell module to simply run the script. All this can be done w/ one playbook:

---
- name: BGP File Creation
  hosts: test-ssh
  gather_facts: false
  vars_files:
    - var.yml

  tasks:

  - name: "Write out BGP Config"
    blockinfile:
      create: yes
      path: /var/tmp/bgp_conf.sh
      content: |

        CE_V4_1=192.168.13.3
        CE_V4_2=192.168.13.4
        CE_V6_1=2001:1890:e00f:f3c:192:168:13:3
        CE_V6_2=2001:1890:e00f:f3c:192:168:13:4
        SVC1_V4_VIP=xxx.xxx.xxx.xxx
        SVC2_V6_VIP=2001:1890:e00f:xxx::xxx
        SVC2_V4_VIP=xxx.xxx.xxx.xxx

        imish << EOF > /dev/null

        en
        conf t

        no service password-encryption

        router bgp 65003
         bgp graceful-restart restart-time 2
         bgp log-neighbor-changes
         redistribute kernel route-map ANYCAST_ROUTES_CE
         neighbor $CE_V4_1 remote-as 4466
         neighbor $CE_V4_1 timers 15 45
         neighbor $CE_V4_1 next-hop-self
         neighbor $CE_V4_1 soft-reconfiguration inbound
         neighbor $CE_V4_2 remote-as 4466
         neighbor $CE_V4_2 timers 15 45
         neighbor $CE_V4_2 next-hop-self
         neighbor $CE_V4_2 soft-reconfiguration inbound
         neighbor $CE_V6_1 remote-as 4466
         neighbor $CE_V6_1 timers 15 45
         neighbor $CE_V6_1 next-hop-self
         neighbor $CE_V6_1 soft-reconfiguration inbound
         neighbor $CE_V6_2 remote-as 4466
         neighbor $CE_V6_2 timers 15 45
         neighbor $CE_V6_2 next-hop-self
         neighbor $CE_V6_2 soft-reconfiguration inbound

         address-family ipv6
         redistribute kernel route-map ANYCAST_ROUTES_CE_IPV6
         no neighbor $CE_V4_1 activate
         no neighbor $CE_V4_1 capability graceful-restart
         no neighbor $CE_V4_2 activate
         no neighbor $CE_V4_2 capability graceful-restart
         neighbor  $CE_V6_1 activate
         neighbor  $CE_V6_1 soft-reconfiguration inbound
         neighbor  $CE_V6_1 route-map
         neighbor  $CE_V6_2 activate
         neighbor  $CE_V6_2 soft-reconfiguration inbound
         neighbor  $CE_V6_2
         exit-address-family

        ip prefix-list ADD_ANYCAST_VIP_CE seq 5 permit $SVC1_V4_VIP/32
        ip prefix-list ADD_ANYCAST_VIP_CE seq 6 permit $SVC2_V4_VIP/32
        ip prefix-list ADD_ANYCAST_VIP_CE seq 20 deny any

        ipv6 prefix-list Anycast_VIP_IPV6 seq 5 permit $SVC_V6_VIP/128
        ipv6 prefix-list Anycast_VIP_IPV6 seq 10 deny any

        route-map ANYCAST_ROUTES_CCE_IPV6 permit 20
        match ipv6 address prefix-list Anycast_VIP_IPV6
        set origin igp
        set community 4466:21 4466:100
        set as-path prepend 65003

        route-map ANYCAST_ROUTES_CE permit 10
         match ip address prefix-list ADD_ANYCAST_VIP_CE
         set origin igp
         set community 4466:21 4466:100
         set as-path prepend 65003

        line con 0
         login
        line vty 0 39
         login

        end
        wr
        clear ip bgp * soft
        EOF

  - name: "Correct BGP bash path"
    lineinfile:
      path: /var/tmp/bgp_conf.sh
      insertbefore: '^# BEGIN ANSIBLE MANAGED BLOCK'
      line: '#!/bin/bash'

  - name: "Apply BGP Config"
    shell: sh /var/tmp/bgp_conf.sh

For context, this was created when TMOS 14.1 was released, so it's a bit dated, but none of the elements listed here have changed much in BIG-IP. As always, YMMV, but this is part of a production deployment that supports millions of people every day. Make any adjustments neccessary for your environment.

Here's a video which shows the code with a bit more explained:

Published Jun 13, 2022
Version 1.0

2 Comments