Skip to content

Commit

Permalink
Merge branch 'develop' into fix_list_devices
Browse files Browse the repository at this point in the history
  • Loading branch information
ktbyers authored Oct 31, 2024
2 parents 7a84e9c + 43da87b commit e942bb0
Show file tree
Hide file tree
Showing 9 changed files with 418 additions and 13 deletions.
1 change: 1 addition & 0 deletions netmiko/cli_tools/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def obtain_devices(device_or_group: str) -> Dict[str, Dict[str, Any]]:


def update_device_params(params, username=None, password=None, secret=None):
"""Add username, password, and secret fields to params dictionary"""
if username:
params["username"] = username
if password:
Expand Down
2 changes: 2 additions & 0 deletions netmiko/cli_tools/netmiko_bulk_encrypt.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env python3
# FIX: would be better to have it read the __meta__ field for the encryption type
# if no encryption type is specified.
import argparse
import sys
from pathlib import Path
Expand Down
25 changes: 12 additions & 13 deletions netmiko/encryption_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Dict, Any, Union

from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import hashes, padding
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

Expand Down Expand Up @@ -46,7 +46,8 @@ def decrypt_value(encrypted_value: str, key: bytes, encryption_type: str) -> str
cipher = Cipher(algorithms.AES(derived_key[:16]), modes.CBC(iv))
decryptor = cipher.decryptor()
padded: bytes = decryptor.update(ciphertext) + decryptor.finalize()
unpadded: bytes = padded[: -padded[-1]]
unpadder = padding.PKCS7(128).unpadder()
unpadded: bytes = unpadder.update(padded) + unpadder.finalize()
return unpadded.decode()
else:
raise ValueError(f"Unsupported encryption type: {encryption_type}")
Expand All @@ -66,7 +67,7 @@ def decrypt_config(


def encrypt_value(value: str, key: bytes, encryption_type: str) -> str:
salt: bytes = os.urandom(16)
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
Expand All @@ -77,19 +78,17 @@ def encrypt_value(value: str, key: bytes, encryption_type: str) -> str:

if encryption_type == "fernet":
f = Fernet(base64.urlsafe_b64encode(derived_key))
fernet_encrypted: bytes = f.encrypt(value.encode())
encrypted_data = fernet_encrypted
encrypted = f.encrypt(value.encode())
elif encryption_type == "aes128":
iv: bytes = os.urandom(16)
iv = os.urandom(16)
padder = padding.PKCS7(128).padder()
padded_data = padder.update(value.encode()) + padder.finalize()
cipher = Cipher(algorithms.AES(derived_key[:16]), modes.CBC(iv))
encryptor = cipher.encryptor()
padded: bytes = value.encode() + b"\0" * (16 - len(value) % 16)
aes_encrypted: bytes = iv + encryptor.update(padded) + encryptor.finalize()
encrypted_data = aes_encrypted
encrypted = iv + encryptor.update(padded_data) + encryptor.finalize()
else:
raise ValueError(f"Unsupported encryption type: {encryption_type}")

# Combine salt and encrypted data, and add prefix
b64_salt: str = base64.b64encode(salt).decode()
b64_encrypted: str = base64.b64encode(encrypted_data).decode()
return f"{ENCRYPTION_PREFIX}{b64_salt}:{b64_encrypted}"
# Combine salt and encrypted data
b64_salt = base64.b64encode(salt).decode()
return f"{ENCRYPTION_PREFIX}{b64_salt}:{base64.b64encode(encrypted).decode()}"
61 changes: 61 additions & 0 deletions tests/unit/NETMIKO_YAML/netmiko-cleartext.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
__meta__:
encryption: true
encryption_type: fernet

sf1:
device_type: cisco_xe
host: sf-rtr1.bogus.com
username: admin
password: cisco123

sf2:
device_type: cisco_xe
host: sf-rtr2.bogus.com
username: admin
password: cisco123

den-asa:
device_type: cisco_asa
ip: 10.1.1.1
username: admin
password: secretpass
secret: supersecretpass

den1:
device_type: arista_eos
host: den-sw1.bogus.com
username: admin
password: eospass

den2:
device_type: arista_eos
host: den-sw2.bogus.com
username: admin
password: eospass

nyc1:
device_type: juniper_junos
host: nyc-vmx1.lasthop.io
username: admin
password: junos123

nyc2:
device_type: juniper_junos
host: nyc-vmx2.lasthop.io
username: admin
password: junos123


sf:
- sf1
- sf2

denver:
- den-asa
- den1
- den2

nyc:
- nyc1
- nyc2

61 changes: 61 additions & 0 deletions tests/unit/NETMIKO_YAML/netmiko-encr-aes128.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
__meta__:
encryption: true
encryption_type: aes128

sf1:
device_type: cisco_xe
host: sf-rtr1.bogus.com
username: admin
password: __encrypt__yFOcJAvns8+JhQK+5/epzw==:txdHCA3C3xriWWFPnOvPjyMVwOdBtuhWDzQv0+TovFU=

sf2:
device_type: cisco_xe
host: sf-rtr2.bogus.com
username: admin
password: __encrypt__NMygaF1Vbxc1rT6jjVNO7A==:GOrWTKZPaYZIXcG/uKvchW523hQmXuI+w9arjELzAdo=

den-asa:
device_type: cisco_asa
ip: 10.1.1.1
username: admin
password: __encrypt__sILzphFAkXclAXzy9OM8EQ==:UI8Mu+mAL8qCyd0MOz/77XnY9ZNY9Q7L8Lg8KQ6pTQ0=
secret: __encrypt__HwvT4RviwnFuzNz+zM4Feg==:f+Yh/Z0t6qtDkW+Cn2LEhg/IBmSTkuMBwEqI931MRso=

den1:
device_type: arista_eos
host: den-sw1.bogus.com
username: admin
password: __encrypt__818vfy+HawwWxTLwJ/iemQ==:tp5m1y4qIAiIwxYbswCGgUKU4YVeCGiJhifBcwO0ujs=

den2:
device_type: arista_eos
host: den-sw2.bogus.com
username: admin
password: __encrypt__jksKL5km3mt1IzjkgkQolQ==:Y6+FGEsf5p6/G4g5Bl+jugKF2i9THnw7BoQgFhaGVp8=

nyc1:
device_type: juniper_junos
host: nyc-vmx1.lasthop.io
username: admin
password: __encrypt__t/Oz00uBfsweZR7t3wcAvg==:dQuCvAQvy/mApnXcnz3HlfJWYYu7UKur1i0sChqajdI=

nyc2:
device_type: juniper_junos
host: nyc-vmx2.lasthop.io
username: admin
password: __encrypt__XmXUrKrYKm/GwVn5Tv6+Hg==:XQMrSUhKMIWkjo1q0FYrEhgvjZYc5yobt97B1sN30qg=


sf:
- sf1
- sf2

denver:
- den-asa
- den1
- den2

nyc:
- nyc1
- nyc2

69 changes: 69 additions & 0 deletions tests/unit/NETMIKO_YAML/netmiko-encr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
__meta__:
encryption: true
encryption_type: fernet

sf1:
device_type: cisco_xe
host: sf-rtr1.bogus.com
username: admin
password:
__encrypt__eimmzMumJna+Gb+sJaZVNA==:Z0FBQUFBQm5CdWV0ZEMtS1VCcWNfZ2hPUjVpdkhVeHVXRHZnVkFQcmluQ0FjWXVFcjk3b1VQMDhUbVdrUjdiQmtnWlNHaWV1aTVQZi1POG1UdDJWZjRCc3R4UWtjSGRqSnc9PQ==

sf2:
device_type: cisco_xe
host: sf-rtr2.bogus.com
username: admin
password:
__encrypt__y5kL3jcKoskqxg/uYNuQ8Q==:Z0FBQUFBQm5CdWV0cHBXZG9PX0dOdXczRFhkbVZmMGE1YjFSUWh4aHhkSHFTd1k2Yy03WkJtcXV1T0FJTzEzdFlNU2d1Z2lyd3luTzRTbTFJWVhlYmY3d3h2S29fNmx6Z1E9PQ==

den-asa:
device_type: cisco_asa
ip: 10.1.1.1
username: admin
password:
__encrypt__VuoXrdmj2aAXgeyUgvXzcg==:Z0FBQUFBQm5CdWV0dGQxSkJFVVFlZ3gwbzhpZ0Z5UTg3cTMyWnI4NnAyLXFTMHRwaGNsY0FJMEV3TEhTeGdOT0ZpaVpHUXNuMjM4TmgzYlIzVHlYZERIem9wd0dHQ1JvM0E9PQ==
secret:
__encrypt__W+XpxyjtEubh9N/t+pojIA==:Z0FBQUFBQm5CdWV0Z2hwY3FJRzE4eGd2R2RxNHEyaHJYM2ZqVUxYQkRQOTBKVlF2eXlYZlR5Undvb2I1dENoSmQ1RFZBUkNYQ0JjVnNxQldzUmNfZU1iNHRRN3ZjeFVmbGc9PQ==

den1:
device_type: arista_eos
host: den-sw1.bogus.com
username: admin
password:
__encrypt__7heDC/COKDgR9CIMcW2hrg==:Z0FBQUFBQm5CdWV0YkJDZUN6blRzelVNM1RrWjk0ZE9zX0JiNnhnUjB5eE1JaEw4SEs5eEZlYkZZUTdBRkdtTXpEY3M4MWp2RmtRS1MtQWxYbk1jcUt1QTNYbUF0VG5wOXc9PQ==

den2:
device_type: arista_eos
host: den-sw2.bogus.com
username: admin
password:
__encrypt__GmyLR/e+Xfjs3zNP/5gkWA==:Z0FBQUFBQm5CdWV0OHk5bllITWF1T1EtMENvem9GNEJDRWdhQU9MYmExTTJYeVJmMEJ4TTQxTE5ZMDhEMVR0a09JdGpFUzFTakF2UlpXYmdrekE1VmpyTURaNWVuenpYMEE9PQ==

nyc1:
device_type: juniper_junos
host: nyc-vmx1.lasthop.io
username: admin
password:
__encrypt__LU5txtsDreQzJygejVRvKQ==:Z0FBQUFBQm5CdWV0eTVELUpQSWxBa1lWSUt3WVhRYjhIeklBV25qbll6QVR2Qml2XzdpNjJXNUUzUkl4dXUxaGlLSmVGNW1DNGFDcDdCbkY1dzFIOUNnOXFfS1BwOEc0N3c9PQ==

nyc2:
device_type: juniper_junos
host: nyc-vmx2.lasthop.io
username: admin
password:
__encrypt__35npOuncqKVwQPHdL/3/fQ==:Z0FBQUFBQm5CdWV0Mjh4VHZwNmtIaWFLTXpMdTlONkp6U211bFdDdTZxMXByM2cyVzZGQi1hanB5d1pfNmhTRDI0RFdPdjVtenVvWndVNlpRRHVWRldSX1dQOEN6b1ZXblE9PQ==


sf:
- sf1
- sf2

denver:
- den-asa
- den1
- den2

nyc:
- nyc1
- nyc2

15 changes: 15 additions & 0 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import pytest

TEST_ENCRYPTION_KEY = "boguskey"


@pytest.fixture
def set_encryption_key(monkeypatch):
"""Fixture to set a test encryption key"""

def _set_key(key=TEST_ENCRYPTION_KEY):
"""Inner function to set a test encryption key"""
monkeypatch.setenv("NETMIKO_TOOLS_KEY", key)
return key

return _set_key
Loading

0 comments on commit e942bb0

Please sign in to comment.