12 de mai. de 2018

YAML e JINJA2 - Parte I

Olá Pessoal Boa Noite, hoje vamos falar um pouco sobre templates e criação automática de configurações.

YAML são as iniciais de Yet Another Markup Language, o objetivo inicial de YAML foi o de poder transformar estruturas de dados em um formato que possa ser armazenado em arquivos, ou enviado via rede para outras máquinas; da mesma forma que XML.

A diferença de XML, YAML é mais intuitivo fazendo que sua escrita e leitura sejam mais fáceis de entender.

Devido à essa facilidade na leitura e escrita, YAML é amplamente utilizado na definição de configurações. Por exemplo se eu quiser definir um roteador que vai precisar executar "bgp", eu posso colocar todas essas definições em um arquivo, YAML. Esse arquivo posteriormente pode se utilizado por outro software como JINJA2, para gerar arquivos de configurações, podendo inclusive, com ajuda de templates JINJA2, gerar configurações para diferentes fabricantes.



Os arquivos YAML precisam ser processados por um "parser", esse parser se encarrega de ler o arquivo YAM e criar uma estrutura de dados a qual possamos acessar. Em Python esse parser é feito pela livraria PyYAML

Antes de continuar com YAML, vou lhes mostrar alguns conceitos sobre estruturas de dados aninhados em python, isso vai ajudar no entendimento da sintaxes YAML.

Diccionarios Aninhados


Até agora conhecemos os diccionarios em python, porém nada impede ter diccionarios dentro de diccionarios. Exemplo:

Roteadores={'R1':{'hostname':'R1SP','ip':'1.1.1.1'},'R2':{'hostname':'R1SP','ip':'1.1.1.1'}}

O diccionario acima "Roteadores", tem duas chaves, a primeira chave 'R1' e a segunda 'R2'. O detalhe é que o valor associado à chave 'R1' é um outro diccionario, o mesmo para 'R2'.

Vamos testar no interpretador de python:


>>> Roteadores={'R1':{'hostname':'R1SP','ip':'1.1.1.1'},'R2':{'hostname':'R1SP','ip':'1.1.1.1'}}
>>> Roteadores
{'R1': {'ip': '1.1.1.1', 'hostname': 'R1SP'}, 'R2': {'ip': '1.1.1.1', 'hostname': 'R1SP'}}
>>> Roteadores['R1']
{'ip': '1.1.1.1', 'hostname': 'R1SP'}
>>> Roteadores['R2']
{'ip': '1.1.1.1', 'hostname': 'R1SP'}
>>> Roteadores['R1']['ip']
'1.1.1.1'
>>> Roteadores['R2']['ip']
'1.1.1.1'
>>> 

Para poder ir digamos assim acessando aos valores de diccionarios mais baixos podemos utilizar a notação Diccionario_Pai[chave-1][chave-2]...[chave-n].


Listas de Diccionarios

Ao igual que existem diccionarios aninhados, nada impede ter por exemplo uma lista de diccionarios. Vejamos:

>>> Roteadores=[{'hostname':'R1SP','ip':'1.1.1.1'},{'hostname':'R1SP','ip':'1.1.1.1'}]
>>> Roteadores
[{'ip': '1.1.1.1', 'hostname': 'R1SP'}, {'ip': '1.1.1.1', 'hostname': 'R1SP'}]
>>> Roteadores[0]
{'ip': '1.1.1.1', 'hostname': 'R1SP'}
>>> Roteadores[1]
{'ip': '1.1.1.1', 'hostname': 'R1SP'}
>>> Roteadores[0]['ip']
'1.1.1.1'
>>> Roteadores[1]['ip']
'1.1.1.1'
>>> 

Agora o acesso aos elementos do diccionario é um pouco diferente, utilizamos uma combinação do index da lista e a chave do diccionario.

Ao momento de processar um arquivo YAML para poder utilizar ele em JINJA2 p.e, vamos utilizar bastante as estruturas acima mostradas.

Instalação do módulo PyYAML para parseamento


Para parsear os arquivos YAML é preciso instalar o módulo pyyaml.

sudo pip install pyyaml

E para utilizar basta importar o módulo em nosso interpretador python

import yaml



Agora sim ...Continuando com YAML.....


Sintaxes em YAML


Inicio de um Documento

Se utiliza o string '---' para indicar o inicio de um documento YAML.

Fim de um Documento

Se utiliza o string '...' para indicar o fim de um documento YAML.

Podem ser inseridos vários documentos em um único arquivo YAML.

Indentação

YAML utiliza indentação para definir hierarquias, similar a indentação em python. Exemplo:

R1:
  hostname: R1SP

No exemplo acima a chave "hostname", com valor "R1SP" esta embaixo da chave "R1". Existe uma hierarquia em YAML.

Em python a configuração acima pode ser traduzida para o seguinte diccionario:

{'R1':{'hostname':'R1SP'}}

Separador

Em YAML somente se utiliza "espaço" como separador, nada de TAB.


Escalares

YAML, permite a definição de diferentes tipos de variavéis, inteiro, float, string boolean. A forma como é definido é do tipo "chave:valor". O tipo de variavél é reconhecido automáticamente.

myInteiro: 10
myFloat: 3.14
myString: "Post de YAML"

Em python a configuração acima se traduz para:

{'myInteiro': 10, 'myFloat': 3.14, 'myString': 'Post de YAML'}

Strings podem estar entre aspas simples o duplas. Se utilizam duplas quando precisamos utilizar caracteres especiais nesse caso também utilizamos o caractere "\"

myString: "Primeira Linha\nSegunda Linha" 

As vezes precisamos armazenar um string de forma literal nesse caso podemos utilizar o operador '|':

myString: |
  "Post de YAML
  exemplo de string.

  Novo paragrafo"

Em python a configuração acima se traduz em:   

{'myString': '"Post de YAML\n exemplo de string.\n Novo paragrafo"\n'}

é possivél também indicar em YAML para que sejam trocados os ENTERs por espaços (quem vai fazer isso é o parser), nesse caso utilizamos o operador '>'

myString: >
  "Post de YAML
  exemplo de string.

  Novo paragrafo"

Em python a configuração acima se traduz em:   

{'myString': '"Post de YAML exemplo de string. Novo paragrafo"\n'}

Listas

Para definir uma lista se utiliza o carater '-' por cada item da lista.

roteadores:
  - R1
  - R2
  - R3

A estrutura de dados acima pode ser lida como: "A chave 'roteadores' tem como valor a lista de valores R1,R2 e R3'.

Em python ficaria:

{'roteadores': ['R1', 'R2', 'R3']}
Inclusive posso ter valores duplicados na lista, isso não é um problema.

roteadores:
  - router
  - router

A estrutura acima pode ser lida como: "A chave 'roteadores' tem como valor uma lista, que a sua vez contem dois itens; item-0=router e item-1=router"

Em python ficaria:

{'roteadores': ['router', 'router']}

Diccionarios

Dicionarios são estruturas de dados com um conjunto de mapeamentos do tipo chave:valor

R1:
  hostname: 'R1SP'
  ip: '1.1.1.1'
  user: 'cisco'
  pass: 'cisco'

A estrutura de dados acima pode ser lida como: "A chave 'R1', tem como valor um outro conjunto de pares chave:valor hostname:'R1SP', ip:'1.1.1.1' etc.

Em Python ficaria:

{'R1': 

   {'hostname': 'R1SP', 
    'ip': '1.1.1.1', 
    'pass': 'cisco', 
    'user': 'cisco'}
}

No caso de diccionarios não é possivél ter chaves duplicadas. Exemplo:

R1:
  hostname: 'R1SP'
  ip: '1.1.1.1'
  user: 'cisco'
  pass: 'cisco'
  ip: '11.11.11.11'

No exemplo acima o valor para a chave 'ip' será '11.11.11.11'. Ao colocar a mesma chave, o valor para essa chave será sobreescrito.

Em python ficaria:

{'R1': 
   {'hostname': 'R1SP', 
    'ip': '11.11.11.11', 
    'pass': 'cisco', 
    'user': 'cisco'}
}


Existe a possibilidade de combinar diccionarios e listas.

Exemplo, preciso definir uma configuração para dois roteadores e tenho os seguintes dados:

Roteador1: Nome R1SP, ip de acesso 1.1.1.1

Roteador2: Nome R2SP ip de acesso 2.2.2.2

A configuração YAML poderia ficar:

roteadores:
 - router:
     hostname: 'R1SP'
     ip: '1.1.1.1'
 - router:
     hostname: 'R2SP'
     ip: '2.2.2.2'


Em Python ficaria:


{'roteadores': 
   [{'router': {'hostname': 'R1SP', 'ip': '1.1.1.1'}}, 
    {'router': {'hostname': 'R2SP', 'ip': '2.2.2.2'}}
   ]
}

Vamos asignar o valor do diccionario acima para a variável MyRouters em python, e ir acessando aos valores da estrutura na medida que nos aprondufamos na hierarquia.

>>> import yaml

>>> MyRouters={'roteadores': 
...    [{'router': {'hostname': 'R1SP', 'ip': '1.1.1.1'}}, 
...     {'router': {'hostname': 'R2SP', 'ip': '2.2.2.2'}}
...    ]
... }
>>> MyRouters['roteadores']
[{'router': {'ip': '1.1.1.1', 'hostname': 'R1SP'}}, {'router': {'ip': '2.2.2.2', 'hostname': 'R2SP'}}]

>>> MyRouters['roteadores'][0]
{'router': {'ip': '1.1.1.1', 'hostname': 'R1SP'}}

>>> MyRouters['roteadores'][1]
{'router': {'ip': '2.2.2.2', 'hostname': 'R2SP'}}

>>> MyRouters['roteadores'][0]['router']
{'ip': '1.1.1.1', 'hostname': 'R1SP'}

>>> MyRouters['roteadores'][1]['router']
{'ip': '2.2.2.2', 'hostname': 'R2SP'}

>>> MyRouters['roteadores'][0]['router']['ip']
'1.1.1.1'

>>> MyRouters['roteadores'][1]['router']['ip']
'2.2.2.2'
>>> 


Existe um site de parseamento online, onde vocês podem praticar http://yaml-online-parser.appspot.com/. No site vocês colocam sua configuração YAML e escolhem como saída Python. Ele vai lhes mostrar qual será a estrutura em python do seu arquivo YAML.

Um outro exemplo, um switch para o qual precisa ser gerado uma configuração para 3 VLANs, e OSPF.


SW1:
 router-id: "1.1.1.1"
 vlans:
    - vlan: 
       id: 100
       desc: "Vlan da rede 192.168.100.0"
    - vlan: 
       id: 200
       desc: "Vlan da rede 192.168.200.0"
    - vlan: 
       id: 300
       desc: "Vlan da rede 10.10.10.0"
    
 ospf:
    networks:
     - network:
        net: 192.168.100.0 
        netmask: "255.255.255.0"
        area: 0
     - network:
        net: 192.168.200.0 
        netmask: "255.255.255.128"
        area: 1
     - network:
        net: 10.10.10.0 
        netmask: "255.255.255.0"
        area: 2


Por hoje é isso Pessoal!!... Um Feliz Dia das Mais!!

Abçs
Jose

Agora sou... CCNA CYBER OPS


Ontem, sexta-feira, 11/05/2018, conquistei o titulo de CCNA Cyber OPS. Após ter concluído os Exames 210-250 SECFND e 210-255 SECOPS. A Cisco tem bancado, através do programa Cisco Global Cyber Ops Scholarship, não só os cursos online preparatórios para esses Exames, como também os vouchers (100% na faixa) para que os interessados no tema possam tirar essa certificação, a custo zero.

Com o constante aumento dos Cyber ataques e ameaças eletrônicas, eu creio que todo profissional de TI deveria passar por estes treinamentos, de forma a ficar antenado com os temas relacionados a Tratamento de Incidentes de Segurança na Web.

Agradeço ao Bruno Nunes, que montou um grupo de estudos no WhatsApp para os interessados no CCNA Cyber, pelas dicas e compartilhamento de material.

Fica a Dica!

5 de mai. de 2018

NAPALM - Parte III

Olá Pessoal Boa Tarde, hoje vamos utilizar NAPALM para mudar as configurações dos nossos roteadores.

A topologia física vai ser a mesma utilizada até agora. Dois roteadores R1-IOS e R2-JunOS, e um host representando pela nuvem Cloud1.



Ambos os roteadores estão rodando OSPF, e todas as suas interfaces estão na área 0.

O objetivo será, trocar de OSPF para BGP. Ficando R1 no AS100 e R2 no AS200.

Os novos arquivos de configuração podem ser baixados de:

https://github.com/JoseBalbuena/BlogNetFinders/blob/master/NAPALM_PARTEIII_R2.conf

https://github.com/JoseBalbuena/BlogNetFinders/blob/master/NAPALM_PARTEIII_R1.conf


Dessa vez vamos utilizar o método load_replace_candidate() da livraria NAPALM.

O único detalhe a ter em consideração é que eu preciso começar a configurar pelo roteador R2, isso porque quando faça a troca de configuração eu vou perder a conetividade com R2, porém quando configure R1 e o peer BGP fechar a conexão irá voltar.

Se eu começar por R1, vou perder conetividade com R2 e nunca mais vou ter acesso.

O meu script ficaria assim:


#!/usr/bin/python

import napalm

#Router diccionario
R1={'so':'ios','hostname':'R1','ip':'1.1.1.1','username':'napalm','password':'napalm','secret':'cisco','newfile':'/home/jose/Automatizacao/R1_new.conf'}
R2={'so':'junos','hostname':'R2','ip':'2.2.2.2','username':'napalm','password':'napalm123','newfile':'/home/jose/Automatizacao/R2_new.conf'}

#Listado dos meus roteadores
routers=[R2,R1] #R2 primeiro na lista


#BEGIN


#Loop para fazer varredura
for router in routers:
 #Caso seja um roteador IOS, utilizar o parametro optional_args com a senha de enable
 if router['so'] == 'ios':
  optional_args={'secret':router['secret']}
 else:
  optional_args={}
 #Selecctiona o driver
 driver = napalm.get_network_driver(router['so'])
 #Coneta ao roteador, dentro de um try..execpt, caso de algum erro o erro eh printado
 try:
  device = driver (hostname=router['ip'], username=router['username'], password=router['password'],optional_args=optional_args)
  device.open()
  #Carrega o arquivo das atualizacoes a serem feitas
  device.load_replace_candidate(filename=router['newfile'])
  #Faz o commit
  device.commit_config()
  #Fecha a conexao
  device.close()
 except Exception as error:
  print "Problemas com driver/sessao do roteador %s" % router['ip']
  print error

#FIM


Quando executamos o script:

jose@rejane:~/Automatizacao$ ./napalm_newconf_ex3.py 
Problemas com driver/sessao do roteador 2.2.2.2
RpcTimeoutError(host: 2.2.2.2, cmd: commit-configuration, timeout: 60)
jose@rejane:~/Automatizacao$ 

Podemos apreciar que ao executar o script,  NAPALM atacha um erro no "commit_config()" para R2, esse erro acontece pelo fato de que quando o commit é executado em R2, automaticamente a nossa conexão ao roteador é perdida. O NAPALM não recebe a resposta do "commit" em R2 e atacha o erro acima. Mas a configuração foi aplicada em R2, a única coisa que falto foi o NAPALM receber a resposta. Resumindo o erro é na livraria do NAPALM e não no "commit" em R2.

O ideal é não perder a conetividade, quem sabe manter o OSPF rodando, mas para própositos de testes e de saber como funcionam as coisas, esta tudo OK.

Verificando em R1:

R1#sh ip bgp summary 
BGP router identifier 1.1.1.1, local AS number 100
BGP table version is 5, main routing table version 5
4 network entries using 592 bytes of memory
4 path entries using 256 bytes of memory
2/2 BGP path/bestpath attribute entries using 272 bytes of memory
1 BGP AS-PATH entries using 24 bytes of memory
0 BGP route-map cache entries using 0 bytes of memory
0 BGP filter-list cache entries using 0 bytes of memory
BGP using 1144 total bytes of memory
BGP activity 4/0 prefixes, 4/0 paths, scan interval 60 secs

Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
10.10.10.2      4          200      45      45        5    0    0 00:18:38        2
R1#sh ip bgp
BGP table version is 5, local router ID is 1.1.1.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, 
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, 
              x best-external, a additional-path, c RIB-compressed, 
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
 *>  1.1.1.0/24       0.0.0.0                  0         32768 i
 *>  2.2.2.0/24       10.10.10.2                             0 200 i
 r>  10.10.10.0/24    10.10.10.2                             0 200 i
 *>  192.168.200.0    0.0.0.0                  0         32768 i
R1#



Verificando em R2:

napalm@JunOS-R2> show bgp summary 
Groups: 1 Peers: 1 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0                 2          2          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
10.10.10.1              100         43         43       0       0       17:57 2/2/2/0              0/0/0/0

napalm@JunOS-R2> 

napalm@JunOS-R2> show route          

inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1.1.1.0/24         *[BGP/170] 00:18:18, MED 0, localpref 100
                      AS path: 100 I
                    > to 10.10.10.1 via em0.0
2.2.2.0/24         *[Direct/0] 01:00:02
                    > via lo0.0
2.2.2.2/32         *[Local/0] 01:00:02
                      Local via lo0.0
10.10.10.0/24      *[Direct/0] 01:00:03
                    > via em0.0
10.10.10.2/32      *[Local/0] 01:00:03
                      Local via em0.0
192.168.200.0/24   *[BGP/170] 00:05:38, MED 0, localpref 100
                      AS path: 100 I
                    > to 10.10.10.1 via em0.0

napalm@JunOS-R2> 


Podemos ver que o BGP foi estabelecido e as rotas tb estão OK.

Desde o host conseguimos pingar tanto para R1 e R2.

jose@rejane:~$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=255 time=11.4 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=255 time=9.09 ms
^C
--- 1.1.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 9.090/10.258/11.427/1.172 ms
jose@rejane:~$ ping 2.2.2.2
PING 2.2.2.2 (2.2.2.2) 56(84) bytes of data.
64 bytes from 2.2.2.2: icmp_seq=1 ttl=63 time=11.6 ms
64 bytes from 2.2.2.2: icmp_seq=2 ttl=63 time=20.1 ms
^C
--- 2.2.2.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 11.603/15.891/20.180/4.290 ms
jose@rejane:~$ 


Bom é isso ai pessoal, nesse três últimos post aprendimos como "coletar informação", "Atualizar a configuração" e "Reemplazar a configuração", utilizando a livraria NAPALM.

Os script são simples, visto que o próposito deles é o ensino, mas vocês podem incluir muitas coisas neles, como logs, entrada de teclado quem sabe ler as configurações dos roteadores de algum banco de dados etc etc..

O próximo post iremos falar de YAML e JINJA2..

Abçs e um ótimo final de semana!!
Jose



2 de mai. de 2018

ISP Express - Produtos e Serviços Cisco com até 70% de desconto e Financiado em 60 X


O NetfindersBrasil, em parceria com a AINET - Associação dos Instrutores do NetAcad - passa agora a oferecer Produtos e Serviços da Cisco Syste para Provedores de Acesso Internet interessados.

Conheça o QuickSupport:

“O QuickSupport foi idealizado para oferecer com exclusividade aos Provedores de Serviços de Internet regionais (iSPs) uma série de serviços executados remotamente ou em loco por especialistas certificados pela Cisco, proporcionando recursos de suporte e manutenção durante a vida útil operacional dos equipamentos CISCO ”


• Através do contrato QuickSupport a AINET , Fornece:
• Monitoramento on-line ( snmp – noc) itens básicos do roteador e ou customizados em conjunto com o cliente
• Acesso por parte do Cliente de nossas ferramentas de monitoração (opcional)
• Cisco TotalCare proporciona recursos de suporte técnico premiados com qualificação para recursos inteligentes. Ele soluciona problemas com mais rapidez, aprimora a eficiência operacional e reduz seu risco de período de inatividade, aumentar a eficiência operacional
• Através de gerenciamento proativo
• Ferramentas e automatizadas
• Gerenciamento SmartNet (*)
• Suporte para Softwares de sistemas autorizados, Cisco IOS , incluindo manutenção e novos lançamentos.
• Gerenciamento ao TAC L3 24 horas por dia, 7 dias por semana
• Substituição avançada de hardware, 24 x 7 x 2 – com ou sem um engenheiro de campo ou – Próximo dia útil (NBD - Next Business Day)
• Equipe de suporte técnico para consultas e soluções de problemas
• Treinamento através de cursos presenciais ou on line a seus colaboradores para toda linha de roteadores CISCO ASR .
• Configuração e/ou acompanhamento das ativações das features e serviços agregados as plataformas ASR
• Administração , supervisão e manutenção
• Relatórios periódicos ou de Alerta de performance e Segurança de seu equipamento
A) Gerenciamento de Incidentes
B) Alertas de segurança de produto
C) Ciclo de vida dos produtos
D) Recomendações para correção de problemas
E) Vulnerabilidades de segurança associadas ao dispositivo
F) Registros de ameaças exibe a identificação da ameaça, a aplicação e a data e a hora e a origem
G) Localizações e IP de host de origem de ameaças
H) Tipo de ameaça por gravidade. Descreve o número de ameaças, classificado por gravidade
I) Consumo de largura de banda (bytes) . Exibe a largura de banda dos sistemas tornando fácil ver quais sistemas estão consumindo a maior largura de banda.

• Ações proativas por nossa equipe técnica
• Suporte remoto e local L1 –L2 –L3
• Aplicação de atualizações sempre que necessário


Quer adquirir Produtos e Soluções Cisco com os melhores preços do Mercado? Consulte-nos: isp.express@ainet.com.br