Ho hlahisa le ho tlatsa lisebelisoa tsa lisebelisoa tsa marang-rang ho sebelisa Nornir

Ho hlahisa le ho tlatsa lisebelisoa tsa lisebelisoa tsa marang-rang ho sebelisa Nornir

Hey Habr!

Haufinyane tjena ho hlahile sengoloa mona Mikrotik le Linux. Tloaelo le boiketsetso moo bothata bo tshoanang le bona bo ileng ba rarollwa ka ho sebedisa mesaletsa ya mesaletsa. 'Me leha mosebetsi ona o tloaelehile, ha ho letho le tšoanang le lona ho Habré. Ke iteta sefuba ho fana ka baesekele ea ka ho sechaba se hlomphehang sa IT.

Ena hase baesekele ea pele bakeng sa mosebetsi o joalo. Khetho ea pele e ile ea sebelisoa lilemong tse 'maloa tse fetileng e phetoloang mofuta 1.x.x. Baesekele e ne e sebelisoa ka seoelo, kahoo e lula e rusa. Ka kutloisiso ea hore mosebetsi ka boeona ha o hlahe hangata ha liphetolelo li nchafatsoa e phetoloang. 'Me nako le nako ha u hloka ho khanna, ketane ea oa kapa lebili lea oa. Leha ho le joalo, karolo ea pele, e hlahisang li-configs, e lula e sebetsa ka mokhoa o hlakileng haholo, ka lehlohonolo jinja2 Enjene e thehiloe nako e telele. Empa karolo ea bobeli - ho hlahisa li-configs - hangata ho tlisa lintho tse makatsang. 'Me kaha ke tlameha ho ntša config ka thōko ho lisebelisoa tse halofo ea lekholo, tse ling tsa tsona li fumaneha lik'hilomithara tse likete, ho sebelisa sesebelisoa sena e ne e le ntho e tenang.

Mona ke tlameha ho lumela hore ho se ts'oanehe ha ka ho ka bakoa ke ho se tsebe ha ka e phetoloangho feta mefokolong ea eona. 'Me sena, ka tsela, ke ntlha ea bohlokoa. e phetoloang ke sebaka se arohaneng ka ho felletseng, sebaka sa eona sa tsebo se nang le DSL (Puo e Khethehileng ea Domain), e tlamehang ho bolokoa ka boits'epo. Be, motsotso oo e phetoloang E ntse e tsoela pele ka potlako, 'me ntle le tlhokomelo e khethehileng bakeng sa ho lumellana ha morao, ha e ekelle kholiseho.

Ka hona, eseng khale ho ile ha sebelisoa mofuta oa bobeli oa baesekele. Lekhetlong lena ho ea pele python, kapa ho fapana le moralo o ngotsoeng ka python le bakeng sa python tlasa lebitso Nornir

Kahoo - Nornir ke microframework e ngotsoeng ka python le bakeng sa python mme e etselitsoe ho iketsetsa. Hoa tšoana le tabeng ea e phetoloang, ho rarolla mathata mona, ho lokisoa ha data ho hlokahalang hoa hlokahala, i.e. lethathamo la mabotho le liparamente tsa bona, empa lingoloa ha lia ngoloa ka DSL e arohaneng, empa ka ho ts'oana eseng ea khale haholo, empa e ntle haholo p[i|i]ton.

Ha re shebeng hore na e sebelisa mohlala o latelang o phelang.

Ke na le marang-rang a makala a nang le liofisi tse ngata ho pholletsa le naha. Ofisi e 'ngoe le e' ngoe e na le router ea WAN e felisang litsela tse 'maloa tsa puisano ho tsoa ho basebetsi ba fapaneng. Protocol ea ho tsamaisa ke BGP. Li-routers tsa WAN li tla ka mefuta e 'meli: Cisco ISG kapa Juniper SRX.

Hona joale mosebetsi: o hloka ho lokisa subnet e inehetseng bakeng sa Boikoetliso ba Video boema-kepeng bo fapaneng ho li-routers tsohle tsa WAN tsa marang-rang a lekala - phatlalatsa subnet ena ho BGP - lokisa moeli oa lebelo la boema-kepe bo inehetseng.

Taba ea pele, re hloka ho lokisa litempele tse 'maloa, motheong oa hore na litlhophiso li tla hlahisoa ka thoko bakeng sa Cisco le Juniper. Hape hoa hlokahala ho lokisetsa lintlha bakeng sa ntlha e 'ngoe le e' ngoe le litekanyetso tsa ho hokahanya, i.e. bokella thepa e tšoanang

Setšoantšo se loketseng bakeng sa 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

Setšoantšo sa 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

Li-templates, ha e le hantle, ha li tsoe moeeng o mosesaane. Tsena ke liphapang lipakeng tsa litlhophiso tsa ts'ebetso tse neng li le teng le ka mor'a ho rarolla mosebetsi ho li-routers tse peli tse ikhethileng tsa mefuta e fapaneng.

Ho tsoa ho litempele tsa rona re bona hore ho rarolla bothata, re hloka feela li-parameter tse peli tsa Juniper le li-parameter tse 3 tsa Cisco. ke tsena:

  • ifname
  • ipsuffix
  • asn

Hona joale re hloka ho beha li-parameter tsena bakeng sa sesebelisoa ka seng, i.e. etsa yona ntho eo inventory.

etsoe inventory Re tla latela ka tieo litokomane Ho qala Nornir

ke hore, ha re theheng skeleton ea faele e tšoanang:

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

Faele ea config.yaml ke faele e tloaelehileng ea litlhophiso tsa 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"

Re tla bontša li-parameter tse ka sehloohong faeleng mabotho.yaml, sehlopha (tabeng ea ka tsena ke li-logins/passwords) ho lihlopha.yamlle ho defaults.yaml Ha re na ho bontša letho, empa o hloka ho kenya metsotsoana e meraro moo - ho bonts'a hore ho joalo yaml faele ha e na letho.

Sena ke tsela eo hosts.yaml e shebahalang ka eona:

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

'Me ke tsena lihlopha.yaml:

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

juniper:
    platform: junos
    username: admin2
    password: juniper2

Sena ke se ileng sa etsahala inventory bakeng sa mosebetsi oa rona. Nakong ea ho qala, li-parameter tse tsoang ho lifaele tsa inventory li etsoa 'mapa ho ea ho mohlala oa ntho InventoryElement.

Ka tlase ho senya ke setšoantšo sa mohlala oa 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"
                }
            }
        }
    }
}

Mohlala ona o ka shebahala o ferekanya, haholo-holo qalong. E le ho e utloisisa, mokhoa oa ho sebelisana o kena python.

 $ 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'

'Me qetellong, a re feteleng pele ho script ka boeona. Ha ke na letho leo nka ithorisang ka lona mona. Ke sa tsoa nka mohlala o itokiselitseng ho tloha thuto mme a e sebelisa e batla e sa fetohe. Sena ke seo script e phethiloeng e shebahalang ka eona:

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)

Ela hloko parameter dry_run=Nnete moleng oa ho qala ntho nr.
Mona ho tšoana le ho e phetoloang teko ea teko e kentsoe ts'ebetsong eo ho eona ho etsoang khokahanyo ho router, ho lokisetsoa tlhophiso e ncha e fetotsoeng, e tiisitsoeng ke sesebelisoa (empa sena ha se na bonnete; ho itšetlehile ka tšehetso ea sesebelisoa le ts'ebetsong ea mokhanni ho NAPALM) , empa tlhophiso e ncha ha e sebelisoe ka kotloloho. Bakeng sa tšebeliso ea ntoa, o tlameha ho tlosa parameter omisa_matha kapa fetola boleng ba eona ho ba bohata.

Ha sengoloa se phethiloe, Nornir o hlahisa lintlha tse qaqileng ho khomphutha.

Ka tlase ho spoiler ke tlhahiso ea ntoa ea li-routers tse peli tsa liteko:

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

E pata li-password ho ansible_vault

Qalong ea sehlooho seo ke ile ka tsamaea hanyane e phetoloang, empa ha se ntho e mpe hakaalo. Ke ba rata haholo sekepe joalo ka, e etselitsoeng ho pata litaba tsa bohlokoa hore li se ke tsa bonoa. 'Me mohlomong ba bangata ba hlokometse hore re na le li-logins / li-passwords bakeng sa li-routers tsohle tsa ntoa tse phatsimang ka mokhoa o bulehileng faeleng. gorups.yaml. Ha e ntle, ehlile. Ha re sireletseng data ena ka sekepe.

Ha re fetiseng liparamente ho tloha ho groups.yaml ho ea creds.yaml, 'me re e kenye ka AES256 ka password ea linomoro tse 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

Ho bonolo hakaalo. E sala ho ruta rona Nornir-script ho fumana le ho sebelisa data ena.
Ho etsa sena, ho script ea rona ka mor'a mohala oa ho qala nr = InitNornir(config_file=... kenya khoutu e latelang:

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

Ehlile, vault.passwd ha ea lokela ho ba haufi le creds.yaml joalo ka mohlala oa ka. Empa ho lokile bakeng sa ho bapala.

Ke phetho bakeng sa jwale. Ho na le lingoloa tse ling tse 'maloa mabapi le Cisco + Zabbix e tlang, empa sena ha se letho ka boits'oaro. 'Me haufinyane ke rera ho ngola ka RESTCONF ho Cisco.

Source: www.habr.com

Eketsa ka tlhaloso