Files
DECSEraser/erase_drive.sh
T

581 lines
18 KiB
Bash

#!/bin/bash
#!/usr/bin/env bash
## Start logging
## Get NetID
### Auth
## Mount \\reinstallbackup
## Get Ticket Number (optional)
### Check if Directory with Ticket Number exists
#### Warn User if it doesn't
##
start_time="$(date '+%Y-%m-%d_%H:%M:%S')"
log="/tmp/log_$start_time"
log_x="/tmp/log_x_$start_time"
exec 3>&1 1>"$log_x" 2>&1
set -x
loginput() {
echo "$*" >&3;
echo "[INPUT] $(date '+%H:%M:%S') $*" >> "$log";
}
loginfo() {
echo "$*" >&3;
echo "[INFO] $(date '+%H:%M:%S') $*" >> "$log";
}
logwarn() {
echo "$*" >&3;
echo "[WARNING] $(date '+%H:%M:%S') $*" >> "$log";
}
logerror() {
echo "$*" >&3;
echo "[ERROR] $(date '+%H:%M:%S') $*" >> "$log";
}
confirm_message () {
local typed=
while [[ ! $typed = "$2" ]];
do
loginput "$1"
read -r typed
done
}
catch_sigint () {
logwarn "Signal Interrupt initiated. Stopping script."
cleanup
trap - INT
kill -INT "$$"
}
cleanup () {
loginfo "Cleaning up."
pcie_disable
if [[ ! $dirname =~ ^\s*$ ]];
then
loginfo "Unmounting drives."
umount "/mnt/reinstallbackups"
#rmdir "/mnt/reinstallbackups"
umount "/mnt/decs"
#rmdir "/mnt/decs"
fi
}
trap catch_sigint SIGINT
get_netid () {
netid=
while [[ $netid =~ ^\s*$ ]];
do
loginfo "Enter netid: "
read -r netid
if [[ $netid =~ ^\s*$ ]];
then
logwarn "Your netid cannot be blank."
loginfo "Enter netid: "
else
authenticate_egr "$netid"
fi
done
clear
}
authenticate_egr (){
kinit "$1"
local ret_value=$(kinit "$1" &> /dev/null; echo $?)
if [[ ! $ret_value = "0" ]]
then
netid=
case $ret_value in
"1")
logwarn "Error when authenticating. Please see above issue, and try again."
;;
*)
logerror "Unspecified error."
cleanup
;;
esac
fi
}
get_ticket () {
ticket_number=
loginfo "Enter ticket number: "
read -r ticket_number
if [[ ! $ticket_number =~ ^\s*$ ]];
then
mkdir /mnt/reinstallbackups
mount -t cifs -o user="$netid",sec=krb5i "//reinstallbackups/reinstallbackups" /mnt/reinstallbackups
local ret_value=$(ls /mnt/reinstallbackups | grep -q -E "^$ticket_number" &> /dev/null; echo $?)
if [[ ! $ret_value = "0" ]];
then
logwarn "WARNING: Backup does not exist in //reinstallbackups/reinstallbackups/$ticket_number!"
fi
umount "/mnt/reinstallbackups"
#rmdir "/mnt/reinstallbackups"
else
ticket_number="UNKNWN"
logwarn "Starting with no ticket number specified."
logwarn "Cannot check for backup in //reinstallbackups/reinstallbackups."
fi
}
mount_remote () {
mkdir /mnt/decs
{
mount -t cifs -o user="$netid",sec=krb5i "//decs/decs/support/dban_logs" /mnt/decs
dirname=
if [[ ! $ticket_number =~ ^\s*$ ]];
then
dirname="UNKNWN-$start_time"
else
dirname="$ticket_number"
fi
if [ ! -e "/mnt/decs/$dirname" ];
then
mkdir "/mnt/decs/$dirname"
fi
mv "$log" "/mnt/decs/$dirname/log_$ticket_number\_$start_time"
mv "$log_x" "/mnt/decs/$dirname/log_$ticket_number\_$start_time"
log="/mnt/decs/$dirname/log_$ticket_number\_$start_time"
log_x="/mnt/decs/$dirname/log_$ticket_number\_$start_time"
rm "/tmp/log_$start_time"
rm "/tmp/log_x_$start_time"
} || {
logerror "Failed to mount remote DECS drive. Stopping"
cleanup
}
}
get_eraselevel () {
eraselevel=
loginfo "What level of erase are you performing on the drive? (0 = baseline, 1 = secure erase, 2 = decommission):"
loginfo "Type 'help' for an explanation of each level."
read -r eraselevel
while [[ ! $eraselevel = "0" ]] && [[ ! $eraselevel = "1" ]] && [[ ! $eraselevel = "2" ]];
do
if [[ $eraselevel = "help" ]];
then
loginfo "Level 0 / Baseline: clears the partitions of the drive. Data can still be recovered but this is the optimal level for simple reuse."
loginfo "Level 1 / Secure Erase: HDD: Scrambles the data on the drive over 3 passes. SSD: Sends a signal to the drive to forget the encryption key, making it unreadrable."
loginfo "Level 2 / decommission: Scrambles the data on the drive over 7 passes. Afterward, put the drive in the bin near the Hardware office to have it destroyed."
else
logwarn "Invalid level, correct values can be 0, 1, or 2"
fi
read -r eraselevel
done
}
get_devicetype () {
devicetype=
loginfo "What is the device type? (0 = HDD_SATA, 1 = SSD_NVME, 2 = SSD_SATA):"
loginfo "Type 'help' for an explanation of each type."
read -r devicetype
while [[ ! $devicetype = "0" ]] && [[ ! $devicetype = "1" ]] && [[ ! $devicetype = "2" ]];
do
if [[ $devicetype = "help" ]];
then
loginfo "HDD_SATA: Spinning disk platters on a SATA connection. Typically 3.5 in or 2.5 in."
loginfo "SSD_SATA: Solid State drive on a SATA connection. Typically 2.5 in."
loginfo "SSD_NVME: Solid State drive on a M.2 connection. Looks like a small PCB."
else
logwarn "Invalid type, correct values can be 0 = HDD_SATA, 1 = SSD_NVME, 2 = SSD_SATA."
fi
read -r devicetype
done
case $devicetype in
"0")
devicetype="HDD_SATA"
;;
"1")
devicetype="SSD_NVME"
;;
"2")
devicetype="SSD_SATA"
;;
*)
logerror "Unspecified error when getting device."
cleanup
;;
esac
}
get_device () {
device=
pcie_enable
loginfo "loginfoing current attached devices..."
loginfo ""
if [[ $devicetype = "HDD_SATA" ]] || [[ $devicetype = "SSD_SATA" ]];
then
loginfo "$(lsblk | grep -E '^NAME|^sd')"
elif [[ $devicetype = "SSD_NVME" ]];
then
loginfo "$(lsblk | grep -E '^NAME|^nvme')"
fi
loginfo ""
loginfo "Which is the device from this list? (Type 'help' for help.)"
while [[ $device =~ ^\s*$ ]];
do
verify_device
done
}
verify_device (){
read -r device
while [[ ! $device =~ ^sd[a-z]$ ]] && [[ ! $device =~ ^nvme0n[0-9]$ ]];
do
if [[ $device = "help" ]];
then
loginfo "The UNIX filesystem thinks of storage devices as directories, which are under /dev/"
loginfo "If you have a SATA connection, you will be looking for sd{a-z}."
loginfo "If you have a NVME connection, you will be looking for nvme0n{0-9}."
else
logwarn "Invalid format, device should follow naming conventions. (i.e. sd{a-z}, nvme0n{0-9})"
fi
read -r device
done
if [[ $devicetype = "HDD_SATA" ]] || [[ $devicetype = "SSD_SATA" ]];
then
if [[ $device =~ ^nvme0n[0-9]$ ]];
then
logwarn "Device was specified to be a SATA HDD or SSD, but a NVME device was chosen."
device=
fi
elif [[ $devicetype = "SSD_NVME" ]];
then
if [[ $device =~ ^sd[a-z]$ ]];
then
logwarn "Device was specified to be a NVME SSD, but a SATA device was chosen. Please ensure the device is plugged into the motherboard via PCIe slot and not SATA."
device=
fi
fi
if [ -e "/dev/$device" ]; then
loginfo "Picking device /dev/$device."
else
logwarn "/dev/$device does not exist, please ensure you are typing the device name correctly."
device=
fi
}
make_infolog () {
infolog="/mnt/decs/$dirname/info_$ticket_number\_$start_time"
{
echo "DETAILS"
echo "Start Time: $start_time"
echo "NetID: $netid"
echo "Ticket number: $ticket_number"
echo ""
echo "ERASE DETAILS"
echo "Type/Device: $devicetype : $device"
echo "Erase Level: $eraselevel"
echo ""
echo "DEVICE DETAILS"
lsblk -O | grep "NAME\|$device"
echo ""
sudo smartctl -i /dev/nvme0n1
echo ""
} >> "$infolog"
while [ -e "/mnt/wintmnt" ];
do
Sleep 5
done
mkdir "/mnt/winmnt"
local ret_value=$(mount -t ntfs "/dev/$device" /mnt/winmt &> /dev/null; echo $?)
if [[ $ret_value = "0" ]]
then
mount -t ntfs "/dev/$device" /mnt/winmt
local ret_value2=$(find /mnt/winmnt/ -ipath "*System32/config" -not -ipath "*Windows.old*" &> /dev/null; echo $?)
if [[ $ret_value2 = "0" ]]
then
winpath=$(find /mnt/winmnt/ -ipath "*System32/config" -not -ipath "*Windows.old*")
{
echo "WINDOWS DETAILS"
echo ""
echo "HOSTNAME"
hivexregedit --export --unsafe-printable-strings --prefix \\HKEY_LOCAL_MACHINE\\SOFTWARE "$winpath/SYSTEM" '\Microsoft\Windows\ControlSet001\Control\ComputerName\ComputerName'
echo ""
echo "DOMAIN"
hivexregedit --export --unsafe-printable-strings --prefix \\HKEY_LOCAL_MACHINE\\SOFTWARE "$winpath/SYSTEM" '\Microsoft\Windows\ControlSet001\Services\Tcpip\Parameters'
echo ""
echo "LOGON DETAILS"
hivexregedit --export --unsafe-printable-strings --prefix \\HKEY_LOCAL_MACHINE\\SOFTWARE "$winpath/SOFTWARE" '\Microsoft\Windows\CurrentVersion\Authentication\LogonUI'
echo ""
hivexregedit --export --unsafe-printable-strings --prefix \\HKEY_LOCAL_MACHINE\\SOFTWARE "$winpath/SOFTWARE" '\Microsoft\Windows NT\CurrentVersion\ProfileList'
echo ""
ls "$(find /mnt/winmnt/ -type d -ipath "*Windows/Users")"
echo ""
} >> "$infolog"
fi
else
logerror "Failed to mount local Windows directory."
cleanup
fi
echo "END OF LOG" >> "$infolog"
}
erase_device_lv0 () {
loginfo "Wiping partition tables of $devicetype : $device."
local ret_value=$(sgdisk -g -Z /dev/"$device" &> /dev/null; echo $?)
if [[ ! $ret_value = "0" ]]
then
case $ret_value in
"1")
logerror "There was an issue with the argument. Ensure you typed the drive name correctly."
;;
"2")
logerror "An error occurred while reading the partition table."
;;
"3")
logerror "Non-GPT disk detected and no -g option, but operation requires a write action."
;;
"4")
logerror "An error prevented saving changes."
;;
"5")
logerror "An error occurred while readring standard input."
;;
"8")
logerror "Disk replication operation (-R) failed."
;;
*)
logerror "Unspecified error."
;;
esac
cleanup
else
loginfo "Partition tables wiped. Device is readry for reuse."
fi
}
erase_device_lv1 () {
#HDD = 3-Pass DOD Short
#SSD Sata = hdparm secure erase
#SSD NVMe = nvme secure erase
if [[ $devicetype = "HDD_SATA" ]] && [[ ! $eraselevel = "2" ]];
then
loginfo "Running 3-Pass DOD Short on ${devicetype} : ${device}."
loginfo "This may take a while!"
local ret_value=$(nwipe -m dodshort --autonuke --nogui /dev/"$device" &> /dev/null; echo $?)
if [[ ! $ret_value = "0" ]]
then
case $ret_value in
"-1")
logerror "Unspecified error while nwiping disk."
;;
*)
logerror "Unspecified error while nwiping disk."
;;
esac
cleanup
else
loginfo "Finished wiping data with nwipe."
fi
elif [[ $devicetype = "SSD_SATA" ]];
then
loginfo "Running hdparm format on $devicetype : $device."
loginfo "Setting security pass to NULL."
#Set the password of the drive to NULL
local ret_value=$(hdparm --user-master m --security-set-pass NULL /dev/"$device" &> /dev/null; echo $?)
if [[ ! $ret_value = "0" ]];
then
hdparm_check_error "$ret_value"
logwarn "Failed to set password of drive. Attempting to continue."
else
loginfo "Set password of drive to NULL."
fi
#Attempt a secure erase.
local ret_value=$(hdparm --user-master m --security-erase-enhanced NULL /dev/"$device" &> /dev/null; echo $?)
if [[ ! $ret_value = "0" ]];
then
hdparm_check_error "$ret_value"
logwarn "Enhanced Secure Erase failed. This is not unexpected depending on the drive type."
loginfo "Attempting Secure Erase instead."
#Attempt a secure erase, less enhanced.
local ret_value2=$(hdparm --user-master m --security-erase NULL /dev/"$device" &> /dev/null; echo $?)
if [[ ! $ret_value2 = "0" ]];
then
hdparm_check_error "$ret_value2"
logerror "Failed to Secure Erase. Please contact your supervisor."
cleanup
else
loginfo "Secure Erase success."
fi
else
loginfo "Enhanced Secure Erase success."
fi
elif [[ $devicetype = "SSD_NVME" ]];
then
loginfo "Running nvme_cli format on $devicetype : $device."
#Erase using nvme cli to send secure erase command to drop the crypto stuff.
local ret_value=$(nvme format --force -r -s 2 /dev/"$device" &> /dev/null; echo $?)
if [[ ! $ret_value = "0" ]]
then
logwarn "Failed to cryptographically erase drive, blanket erasing instead."
#Sad, can't do it. Blank out drive instead using the drive controller.
local ret_value=$(nvme format --force -r -s 1 /dev/"$device" &> /dev/null; echo $?)
if [[ ! $ret_value = "0" ]]
then
logerror "Failed to cryptographically erase or blanket erase. Please contact your supervisor."
cleanup
else
loginfo "Blanket erased drive."
fi
else
loginfo "Cryptographically erased drive."
fi
else
logerror "There was an issue with the device type: $devicetype. Ensure you typed the drive name correctly."
cleanup
fi
}
erase_device_lv2 () {
#7-Pass DOD Wipe through nwipe.
loginfo "Running 7-Pass DOD on $devicetype : $device."
loginfo "This may take a while!"
local ret_value=$(nwipe -m dod --autonuke --nogui /dev/"$device" &> /dev/null; echo $?)
if [[ ! $ret_value = "0" ]]
then
case $ret_value in
"-1")
logerror "Unspecified error while nwiping disk."
;;
*)
logerror "Unspecified error while nwiping disk."
;;
esac
cleanup
else
loginfo "Finished wiping data with nwipe."
loginfo "Please put device in decommission bin in the hardware room."
fi
}
hdparm_check_error () {
case $1 in
"1")
logerror "Operation not permitted."
;;
"2")
logerror "No such file or directory."
;;
"5")
logerror "I/O error."
;;
"16")
logerror "Device or resource busy."
;;
"22")
logerror "Invalid argument."
;;
*)
logerror "Unspecified error."
;;
esac
}
#Rescan for PCIe devices
pcie_enable (){
echo 1 > /sys/bus/pci/rescan
loginfo "Enabled PCIe card, sleeping for 5 seconds."
sleep 5
}
#Remove the PCIe NVMe readrer
pcie_disable (){
echo 1 > /sys/bus/pci/devices/0000:02:00.0/remove
loginfo "Disabled PCIe card."
}
main (){
get_netid
get_ticket
mount_remote
loginfo "By running this script, you are confirming that it has been two weeks past the date written on the slip attached to the storage device. DO NOT erase the device before two weeks have passed."
confirm_message "Please type 'confirm' to acknowledge you have read this and that it has been two weeks." "confirm"
get_eraselevel #sets $eraselevel to 0-2 based on how to erase. Higher levels include lower levels.
get_devicetype #sets $devicetype to HDD_SATA/SSD_SATA/SSD_NVME
get_device #sets $device to one of the /dev/xyz devices.
make_infolog #Logs a bunch of details to a info log file from the system.
loginfo "Starting process for erasing $devicetype : $device with erase level $eraselevel."
if [[ $eraselevel = "1" ]] || [[ $eraselevel = "2" ]];
then
local randomconf=$(shuf -i 10000-99999 -n 1)
confirm_message "This level is destructive and irreversible. Please type $randomconf to continue" "$randomconf"
else
confirm_message "Please type 'confirm' to begin." "confirm"
fi
case $eraselevel in
"0")
erase_device_lv0 #Wipe partition
;;
"1")
erase_device_lv1 #Secure Erase
erase_device_lv0 #Wipe partition
;;
"2")
erase_device_lv1 #Secure Erase (skips nwipe for HDDs)
erase_device_lv2 #7-Pass nwipe
erase_device_lv0 #Wipe partition
;;
*)
logerror "Invalid Erase Level"
cleanup
;;
esac
sleep 3
loginfo "Finished erasing $devicetype : $device with erase level $eraselevel."
cleanup
}
main