Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/429.changed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Raised the minimum supported netmiko version to 4.4.
1 change: 1 addition & 0 deletions changes/429.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed FTP, HTTP and HTTPS file transfers to Cisco IOS devices failing to authenticate.
1 change: 1 addition & 0 deletions changes/429.fixed.1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed remote file copy failures on Cisco IOS, NX-OS, ASA and IOS-XR reporting a generic message instead of the error the device returned.
1 change: 1 addition & 0 deletions changes/429.fixed.2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed remote file copy hanging on Cisco IOS and NX-OS when a device returned output the driver did not recognize.
1 change: 1 addition & 0 deletions changes/429.security
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Stopped the source server password appearing in the logs during an FTP, HTTP or HTTPS file copy to Cisco IOS devices.
13 changes: 10 additions & 3 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 17 additions & 5 deletions pyntc/devices/asa_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,11 @@ def reboot_standby(self, acceptable_states: Optional[Iterable[str]] = None, time

log.debug("Host %s: reboot standby with timeout %s.", self.host, timeout)

@staticmethod
def _mask_token(output: str, src: FileCopyModel) -> str:
"""Replace the token in device output, so it is safe to log or raise."""
return output.replace(src.token, "*****") if src.token else output

def remote_file_copy(self, src: FileCopyModel = None, dest=None, **kwargs: Any):
"""Copy a file from a remote server to the device.

Expand Down Expand Up @@ -1104,8 +1109,9 @@ def remote_file_copy(self, src: FileCopyModel = None, dest=None, **kwargs: Any):
break

if re.search(r"(Error|Invalid|Failed|Aborted|denied)", output, re.IGNORECASE):
log.error("Host %s: File transfer error for %s: %s", self.host, src.file_name, output)
raise FileTransferError
masked_output = self._mask_token(output, src)
log.error("Host %s: File transfer error for %s: %s", self.host, src.file_name, masked_output)
raise FileTransferError(f"Error detected in copy command output: {masked_output}")

for prompt, answer in prompt_answers.items():
if re.search(prompt, output, re.IGNORECASE):
Expand All @@ -1117,16 +1123,22 @@ def remote_file_copy(self, src: FileCopyModel = None, dest=None, **kwargs: Any):
)
break
else:
masked_output = self._mask_token(output, src)
log.error(
"Host %s: Unexpected output during file transfer of %s: %s", self.host, src.file_name, output
"Host %s: Unexpected output during file transfer of %s: %s",
self.host,
src.file_name,
masked_output,
)
raise FileTransferError
raise FileTransferError(f"Unexpected output during file transfer: {masked_output}")

if not self.verify_file(
src.checksum, dest, hashing_algorithm=src.hashing_algorithm, file_system=file_system
):
log.error("Host %s: File %s could not be verified after transfer.", self.host, src.file_name)
raise FileTransferError
raise FileTransferError(
f"Could not validate {src.file_name} existed and matched the expected checksum after transfer."
)

@property
def redundancy_mode(self):
Expand Down
Loading
Loading