Ƙirƙirar atomatik da cika abubuwan daidaitawar na'urar cibiyar sadarwa ta amfani da Nornir

Ƙirƙirar atomatik da cika abubuwan daidaitawar na'urar cibiyar sadarwa ta amfani da Nornir

Hai Habr!

Kwanan nan labarin ya fito nan Mikrotik da Linux. Na yau da kullun da aiki da kai inda aka magance irin wannan matsala ta hanyar amfani da burbushin halittu. Kuma ko da yake aikin gabaɗaya ne, babu wani abu makamancinsa game da shi akan Habré. Na kuskura in ba da babur na ga jama'ar IT da ake girmamawa.

Wannan ba shine keken farko na irin wannan aikin ba. An aiwatar da zaɓi na farko shekaru da yawa da suka gabata a baya m sigar 1.x.x. Ba a cika yin amfani da keken ba saboda haka kullum yana tsatsa. A cikin ma'anar cewa aikin da kansa ba ya tasowa sau da yawa yayin da aka sabunta sigogi m. Kuma duk lokacin da kuke buƙatar tuƙi, sarkar ta faɗi ko dabaran ta faɗi. Koyaya, ɓangaren farko, ƙirƙirar saiti, koyaushe yana aiki sosai a sarari, sa'a jinji 2 Injin ya daɗe yana kafawa. Amma kashi na biyu - mirgine fitar da configs - yawanci yakan kawo abubuwan mamaki. Kuma tunda dole ne in fitar da na'ura mai nisa zuwa rabin na'urori guda dari, wasu daga cikinsu suna da nisan dubban kilomita, yin amfani da wannan kayan aikin ya ɗan ban sha'awa.

Anan dole ne in yarda cewa rashin tabbas na ya ta'allaka ne ga rashin sanina mfiye da gazawarsa. Kuma wannan, ta hanyar, wani muhimmin batu ne. m wani yanki ne na musamman, yanki na ilimi tare da DSL (Domain Specific Language), wanda dole ne a kiyaye shi a matakin amincewa. To, wannan lokacin m Yana haɓakawa da sauri, kuma ba tare da la'akari na musamman don dacewa da baya ba, baya ƙara amincewa.

Saboda haka, ba da dadewa ba aka aiwatar da nau'in keke na biyu. A wannan karon python, ko kuma a kan tsarin da aka rubuta a ciki python kuma don python karkashin sunan Nornir

Don haka - Nornir microframework ne da aka rubuta a ciki python kuma don python kuma an tsara shi don sarrafa kansa. Kamar yadda yake a cikin lamarin m, don magance matsaloli a nan, ana buƙatar shirye-shiryen bayanai masu dacewa, watau. lissafin runduna da sigogin su, amma rubutun ba a rubuta su a cikin DSL daban ba, amma a cikin guda ba tsofaffi ba ne, amma p[i|i] mai kyau sosai.

Bari mu ga abin da yake amfani da misalin nan kai tsaye.

Ina da hanyar sadarwa na reshe da ofisoshin dozin da yawa a duk faɗin ƙasar. Kowane ofishi yana da na'ura mai ba da hanya tsakanin hanyoyin sadarwa WAN da ke katse hanyoyin sadarwa da yawa daga ma'aikata daban-daban. Ka'idar tuƙi shine BGP. WAN routers zo a iri biyu: Cisco ISG ko Juniper SRX.

Yanzu aikin: kuna buƙatar saita ƙaƙƙarfan ƙaƙƙarfan yanki don Kula da Bidiyo akan tashar tashar daban akan duk masu amfani da WAN na cibiyar sadarwar reshe - tallata wannan rukunin yanar gizon a cikin BGP - saita iyakar saurin tashar jiragen ruwa.

Da farko, muna buƙatar shirya nau'ikan samfura biyu, akan abin da za a samar da jeri daban-daban don Cisco da Juniper. Hakanan wajibi ne don shirya bayanai don kowane batu da sigogin haɗin kai, watau. tattara kaya iri ɗaya

Samfurin shirye don Cisco:

$ cat templates/ios/base.j2 
class-map match-all VIDEO_SURV
 match access-group 111

policy-map VIDEO_SURV
 class VIDEO_SURV
    police 1500000 conform-action transmit  exceed-action drop

interface {{ host.task_data.ifname }}
  description VIDEOSURV
  ip address 10.10.{{ host.task_data.ipsuffix }}.254 255.255.255.0
  service-policy input VIDEO_SURV

router bgp {{ host.task_data.asn }}
  network 10.40.{{ host.task_data.ipsuffix }}.0 mask 255.255.255.0

access-list 11 permit 10.10.{{ host.task_data.ipsuffix }}.0 0.0.0.255
access-list 111 permit ip 10.10.{{ host.task_data.ipsuffix }}.0 0.0.0.255 any

Samfurin Juniper:

$ cat templates/junos/base.j2 
set interfaces {{ host.task_data.ifname }} unit 0 description "Video surveillance"
set interfaces {{ host.task_data.ifname }} unit 0 family inet filter input limit-in
set interfaces {{ host.task_data.ifname }} unit 0 family inet address 10.10.{{ host.task_data.ipsuffix }}.254/24
set policy-options policy-statement export2bgp term 1 from route-filter 10.10.{{ host.task_data.ipsuffix }}.0/24 exact
set security zones security-zone WAN interfaces {{ host.task_data.ifname }}
set firewall policer policer-1m if-exceeding bandwidth-limit 1m
set firewall policer policer-1m if-exceeding burst-size-limit 187k
set firewall policer policer-1m then discard
set firewall policer policer-1.5m if-exceeding bandwidth-limit 1500000
set firewall policer policer-1.5m if-exceeding burst-size-limit 280k
set firewall policer policer-1.5m then discard
set firewall filter limit-in term 1 then policer policer-1.5m
set firewall filter limit-in term 1 then count limiter

Samfura, ba shakka, ba sa fitowa daga bakin ciki. Waɗannan su ne ainihin bambance-bambance tsakanin saitunan aiki waɗanda suka kasance kuma sun kasance bayan warware aikin akan takamaiman hanyoyin guda biyu na ƙira daban-daban.

Daga samfuranmu mun ga cewa don magance matsalar, muna buƙatar sigogi biyu kawai don Juniper da sigogi 3 don Cisco. Ga su:

  • idan suna
  • ipsuffix
  • asn

Yanzu muna buƙatar saita waɗannan sigogi don kowace na'ura, watau. yi haka kaya.

domin kaya Za mu bi takaddun takaddun Ƙaddamar da Nornir

wato, bari mu ƙirƙiri kwarangwal ɗin fayil iri ɗaya:

.
├── config.yaml
├── inventory
│   ├── defaults.yaml
│   ├── groups.yaml
│   └── hosts.yaml

Fayil ɗin config.yaml shine daidaitaccen fayil ɗin daidaitawar nornir

$ cat config.yaml 
---
core:
    num_workers: 10

inventory:
    plugin: nornir.plugins.inventory.simple.SimpleInventory
    options:
        host_file: "inventory/hosts.yaml"
        group_file: "inventory/groups.yaml"
        defaults_file: "inventory/defaults.yaml"

Za mu nuna manyan sigogi a cikin fayil ɗin runduna.yaml, group (a cikin yanayina waɗannan logins/passwords) a ciki kungiyoyin.yaml, kuma cikin gazawar.yaml Ba za mu nuna wani abu ba, amma kuna buƙatar shigar da minuses guda uku a can - yana nuna cewa haka ne yaml fayil ɗin fanko ne ko da yake.

Ga abin da hosts.yaml yayi kama:

---
srx-test:
    hostname: srx-test
    groups: 
        - juniper
    data:
        task_data:
            ifname: fe-0/0/2
            ipsuffix: 111

cisco-test:
    hostname: cisco-test
    groups: 
        - cisco
    data:
        task_data:
            ifname: GigabitEthernet0/1/1
            ipsuffix: 222
            asn: 65111

Ga kuma groups.yaml:

---
cisco:
    platform: ios
    username: admin1
    password: cisco1

juniper:
    platform: junos
    username: admin2
    password: juniper2

Abin da ya faru ke nan kaya domin aikin mu. Lokacin farawa, ana tsara sigogi daga fayilolin ƙira zuwa ƙirar abu Kayayyakin Kayayyaki.

A ƙasa mai ɓarna akwai zane na ƙirar InventoryElement

print(json.dumps(InventoryElement.schema(), indent=4))
{
    "title": "InventoryElement",
    "type": "object",
    "properties": {
        "hostname": {
            "title": "Hostname",
            "type": "string"
        },
        "port": {
            "title": "Port",
            "type": "integer"
        },
        "username": {
            "title": "Username",
            "type": "string"
        },
        "password": {
            "title": "Password",
            "type": "string"
        },
        "platform": {
            "title": "Platform",
            "type": "string"
        },
        "groups": {
            "title": "Groups",
            "default": [],
            "type": "array",
            "items": {
                "type": "string"
            }
        },
        "data": {
            "title": "Data",
            "default": {},
            "type": "object"
        },
        "connection_options": {
            "title": "Connection_Options",
            "default": {},
            "type": "object",
            "additionalProperties": {
                "$ref": "#/definitions/ConnectionOptions"
            }
        }
    },
    "definitions": {
        "ConnectionOptions": {
            "title": "ConnectionOptions",
            "type": "object",
            "properties": {
                "hostname": {
                    "title": "Hostname",
                    "type": "string"
                },
                "port": {
                    "title": "Port",
                    "type": "integer"
                },
                "username": {
                    "title": "Username",
                    "type": "string"
                },
                "password": {
                    "title": "Password",
                    "type": "string"
                },
                "platform": {
                    "title": "Platform",
                    "type": "string"
                },
                "extras": {
                    "title": "Extras",
                    "type": "object"
                }
            }
        }
    }
}

Wannan samfurin na iya kallon ɗan rikicewa, musamman a farkon. Don gano shi, yanayin hulɗa yana cikin ipython.

 $ ipython3
Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from nornir import InitNornir                                                                           

In [2]: nr = InitNornir(config_file="config.yaml", dry_run=True)                                                

In [3]: nr.inventory.hosts                                                                                      
Out[3]: 
{'srx-test': Host: srx-test, 'cisco-test': Host: cisco-test}

In [4]: nr.inventory.hosts['srx-test'].data                                                                                    
Out[4]: {'task_data': {'ifname': 'fe-0/0/2', 'ipsuffix': 111}}

In [5]: nr.inventory.hosts['srx-test']['task_data']                                                     
Out[5]: {'ifname': 'fe-0/0/2', 'ipsuffix': 111}

In [6]: nr.inventory.hosts['srx-test'].platform                                                                                
Out[6]: 'junos'

Kuma a ƙarshe, bari mu matsa zuwa rubutun kanta. Ba ni da wani abin alfahari musamman a nan. Na ɗauki misali da aka shirya daga koyawa kuma yayi amfani dashi kusan baya canzawa. Wannan shine yadda rubutun aikin da aka gama yayi kama:

from nornir import InitNornir
from nornir.plugins.tasks import networking, text
from nornir.plugins.functions.text import print_title, print_result

def config_and_deploy(task):
    # Transform inventory data to configuration via a template file
    r = task.run(task=text.template_file,
                 name="Base Configuration",
                 template="base.j2",
                 path=f"templates/{task.host.platform}")

    # Save the compiled configuration into a host variable
    task.host["config"] = r.result

    # Save the compiled configuration into a file
    with open(f"configs/{task.host.hostname}", "w") as f:
        f.write(r.result)

    # Deploy that configuration to the device using NAPALM
    task.run(task=networking.napalm_configure,
             name="Loading Configuration on the device",
             replace=False,
             configuration=task.host["config"])

nr = InitNornir(config_file="config.yaml", dry_run=True) # set dry_run=False, cross your fingers and run again

# run tasks
result = nr.run(task=config_and_deploy)
print_result(result)

Kula da siga dry_run=Gaskiya a layin farawa abu nr.
A nan daidai da in m An aiwatar da gwajin gwaji wanda aka haɗa haɗin kai zuwa na'ura mai ba da hanya tsakanin hanyoyin sadarwa, an shirya sabon tsarin daidaitawa, wanda na'urar ta inganta (amma wannan ba tabbas ba; ya dogara da tallafin na'urar da aiwatar da direba a NAPALM) , amma ba a aiwatar da sabon tsarin kai tsaye ba. Don amfani da yaƙi, dole ne ku cire siga bushe_gudu ko canza darajarsa zuwa arya.

Lokacin da aka aiwatar da rubutun, Nornir yana fitar da cikakken rajistan ayyukan zuwa na'ura wasan bidiyo.

A ƙasa mai ɓarna akwai fitowar yaƙi da ke gudana akan hanyoyin gwaji guda biyu:

config_and_deploy***************************************************************
* cisco-test ** changed : True *******************************************
vvvv config_and_deploy ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- Base Configuration ** changed : True ------------------------------------- INFO
class-map match-all VIDEO_SURV
 match access-group 111

policy-map VIDEO_SURV
 class VIDEO_SURV
    police 1500000 conform-action transmit  exceed-action drop

interface GigabitEthernet0/1/1
  description VIDEOSURV
  ip address 10.10.222.254 255.255.255.0
  service-policy input VIDEO_SURV

router bgp 65001
  network 10.10.222.0 mask 255.255.255.0

access-list 11 permit 10.10.222.0 0.0.0.255
access-list 111 permit ip 10.10.222.0 0.0.0.255 any
---- Loading Configuration on the device ** changed : True --------------------- INFO
+class-map match-all VIDEO_SURV
+ match access-group 111
+policy-map VIDEO_SURV
+ class VIDEO_SURV
+interface GigabitEthernet0/1/1
+  description VIDEOSURV
+  ip address 10.10.222.254 255.255.255.0
+  service-policy input VIDEO_SURV
+router bgp 65001
+  network 10.10.222.0 mask 255.255.255.0
+access-list 11 permit 10.10.222.0 0.0.0.255
+access-list 111 permit ip 10.10.222.0 0.0.0.255 any
^^^^ END config_and_deploy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* srx-test ** changed : True *******************************************
vvvv config_and_deploy ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- Base Configuration ** changed : True ------------------------------------- INFO
set interfaces fe-0/0/2 unit 0 description "Video surveillance"
set interfaces fe-0/0/2 unit 0 family inet filter input limit-in
set interfaces fe-0/0/2 unit 0 family inet address 10.10.111.254/24
set policy-options policy-statement export2bgp term 1 from route-filter 10.10.111.0/24 exact
set security zones security-zone WAN interfaces fe-0/0/2
set firewall policer policer-1m if-exceeding bandwidth-limit 1m
set firewall policer policer-1m if-exceeding burst-size-limit 187k
set firewall policer policer-1m then discard
set firewall policer policer-1.5m if-exceeding bandwidth-limit 1500000
set firewall policer policer-1.5m if-exceeding burst-size-limit 280k
set firewall policer policer-1.5m then discard
set firewall filter limit-in term 1 then policer policer-1.5m
set firewall filter limit-in term 1 then count limiter
---- Loading Configuration on the device ** changed : True --------------------- INFO
[edit interfaces]
+   fe-0/0/2 {
+       unit 0 {
+           description "Video surveillance";
+           family inet {
+               filter {
+                   input limit-in;
+               }
+               address 10.10.111.254/24;
+           }
+       }
+   }
[edit]
+  policy-options {
+      policy-statement export2bgp {
+          term 1 {
+              from {
+                  route-filter 10.10.111.0/24 exact;
+              }
+          }
+      }
+  }
[edit security zones]
     security-zone test-vpn { ... }
+    security-zone WAN {
+        interfaces {
+            fe-0/0/2.0;
+        }
+    }
[edit]
+  firewall {
+      policer policer-1m {
+          if-exceeding {
+              bandwidth-limit 1m;
+              burst-size-limit 187k;
+          }
+          then discard;
+      }
+      policer policer-1.5m {
+          if-exceeding {
+              bandwidth-limit 1500000;
+              burst-size-limit 280k;
+          }
+          then discard;
+      }
+      filter limit-in {
+          term 1 {
+              then {
+                  policer policer-1.5m;
+                  count limiter;
+              }
+          }
+      }
+  }
^^^^ END config_and_deploy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Boye kalmomin shiga cikin ansible_vault

A farkon labarin na ɗan yi gudu m, amma ba duka ba ne. Ina son su sosai vault kamar, wanda aka ƙera don ɓoye mahimman bayanai daga gani. Kuma tabbas mutane da yawa sun lura cewa muna da duk login / kalmomin shiga don duk hanyoyin sadarwa na yaƙi da ke haskakawa a cikin buɗaɗɗen tsari a cikin fayil. gorups.yaml. Ba kyakkyawa ba ne, ba shakka. Mu kare wannan bayanan da vault.

Bari mu canja wurin sigogi daga groups.yaml zuwa creds.yaml, kuma mu ɓoye shi da AES256 tare da kalmar sirri mai lamba 20:

$ cd inventory
$ cat creds.yaml
---
cisco:
    username: admin1
    password: cisco1

juniper:
    username: admin2
    password: juniper2

$ pwgen 20 -N 1 > vault.passwd
ansible-vault encrypt creds.yaml --vault-password-file vault.passwd  
Encryption successful
$ cat creds.yaml 
$ANSIBLE_VAULT;1.1;AES256
39656463353437333337356361633737383464383231366233386636333965306662323534626131
3964396534396333363939373539393662623164373539620a346565373439646436356438653965
39643266333639356564663961303535353364383163633232366138643132313530346661316533
6236306435613132610a656163653065633866626639613537326233653765353661613337393839
62376662303061353963383330323164633162386336643832376263343634356230613562643533
30363436343465306638653932366166306562393061323636636163373164613630643965636361
34343936323066393763323633336366366566393236613737326530346234393735306261363239
35663430623934323632616161636330353134393435396632663530373932383532316161353963
31393434653165613432326636616636383665316465623036376631313162646435

Yana da sauki haka. Ya rage don koyar da mu Nornir- rubutun don dawo da amfani da wannan bayanan.
Don yin wannan, a cikin rubutun mu bayan layin farawa nr = InitNornir (config_file =… ƙara lambar mai zuwa:

...
nr = InitNornir(config_file="config.yaml", dry_run=True) # set dry_run=False, cross your fingers and run again

# enrich Inventory with the encrypted vault data
from ansible_vault import Vault
vault_password_file="inventory/vault.passwd"
vault_file="inventory/creds.yaml"
with open(vault_password_file, "r") as fp:
    password = fp.readline().strip()   
    vault = Vault(password)
    vaultdata = vault.load(open(vault_file).read())

for a in nr.inventory.hosts.keys():
    item = nr.inventory.hosts[a]
    item.username = vaultdata[item.groups[0]]['username']
    item.password = vaultdata[item.groups[0]]['password']
    #print("hostname={}, username={}, password={}n".format(item.hostname, item.username, item.password))

# run tasks
...

Tabbas, vault.passwd bai kamata ya kasance kusa da creds.yaml kamar yadda yake cikin misali na ba. Amma babu laifi don yin wasa.

Shi ke nan a yanzu. Akwai ƙarin labarai guda biyu game da Cisco + Zabbix masu zuwa, amma wannan ba kaɗan ba ne game da aiki da kai. Kuma nan gaba kadan na shirya rubuta game da RESTCONF a cikin Cisco.

source: www.habr.com

Add a comment