# Debian / Ubuntu
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">install fish -y # Verify
fish --version
# Debian / Ubuntu
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">install fish -y # Verify
fish --version
# Debian / Ubuntu
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">install fish -y # Verify
fish --version
mkdir -p ~/.config/fish/functions
mkdir -p ~/.config/fish/functions
mkdir -p ~/.config/fish/functions
set -U INSTANCE_ID "i-your_instance_id_here"
set -U INSTANCE_ID "i-your_instance_id_here"
set -U INSTANCE_ID "i-your_instance_id_here"
function lab-login aws sso login --profile lab-sso
end
function lab-login aws sso login --profile lab-sso
end
function lab-login aws sso login --profile lab-sso
end
$ lab-login
# Browser opens → tap YubiKey → "Your credentials have been shared successfully"
$ lab-login
# Browser opens → tap YubiKey → "Your credentials have been shared successfully"
$ lab-login
# Browser opens → tap YubiKey → "Your credentials have been shared successfully"
function lab--weight: 500;">status aws ec2 describe-instances --instance-ids $INSTANCE_ID \ --profile lab-sso \ --query "Reservations[0].Instances[0].State.Name" \ --output text
end
function lab--weight: 500;">status aws ec2 describe-instances --instance-ids $INSTANCE_ID \ --profile lab-sso \ --query "Reservations[0].Instances[0].State.Name" \ --output text
end
function lab--weight: 500;">status aws ec2 describe-instances --instance-ids $INSTANCE_ID \ --profile lab-sso \ --query "Reservations[0].Instances[0].State.Name" \ --output text
end
function lab--weight: 500;">start aws ec2 -weight: 500;">start-instances --instance-ids $INSTANCE_ID --profile lab-sso echo "Starting... wait 60 seconds"
end
function lab--weight: 500;">start aws ec2 -weight: 500;">start-instances --instance-ids $INSTANCE_ID --profile lab-sso echo "Starting... wait 60 seconds"
end
function lab--weight: 500;">start aws ec2 -weight: 500;">start-instances --instance-ids $INSTANCE_ID --profile lab-sso echo "Starting... wait 60 seconds"
end
function lab--weight: 500;">stop aws ec2 -weight: 500;">stop-instances --instance-ids $INSTANCE_ID --profile lab-sso echo "Stopping..."
end
function lab--weight: 500;">stop aws ec2 -weight: 500;">stop-instances --instance-ids $INSTANCE_ID --profile lab-sso echo "Stopping..."
end
function lab--weight: 500;">stop aws ec2 -weight: 500;">stop-instances --instance-ids $INSTANCE_ID --profile lab-sso echo "Stopping..."
end
function lab-connect aws ssm -weight: 500;">start-session --target $INSTANCE_ID --profile lab-sso
end
function lab-connect aws ssm -weight: 500;">start-session --target $INSTANCE_ID --profile lab-sso
end
function lab-connect aws ssm -weight: 500;">start-session --target $INSTANCE_ID --profile lab-sso
end
$ lab-connect
Starting session with SessionId: your_username_here-...
$ whoami
ssm-user
$ lab-connect
Starting session with SessionId: your_username_here-...
$ whoami
ssm-user
$ lab-connect
Starting session with SessionId: your_username_here-...
$ whoami
ssm-user
echo $INSTANCE_ID # prints the instance ID it will terminate
lab--weight: 500;">status # confirms the instance is running
echo $INSTANCE_ID # prints the instance ID it will terminate
lab--weight: 500;">status # confirms the instance is running
echo $INSTANCE_ID # prints the instance ID it will terminate
lab--weight: 500;">status # confirms the instance is running
function lab-terminate echo "WARNING: This will permanently delete the instance and all data on it." echo "Instance: $INSTANCE_ID" read --prompt-str "Type YES to confirm: " confirm if test "$confirm" = "YES" aws ec2 terminate-instances \ --instance-ids $INSTANCE_ID --profile lab-sso echo "Instance terminated. Use lab-create to launch a fresh one." else echo "Cancelled." end
end
function lab-terminate echo "WARNING: This will permanently delete the instance and all data on it." echo "Instance: $INSTANCE_ID" read --prompt-str "Type YES to confirm: " confirm if test "$confirm" = "YES" aws ec2 terminate-instances \ --instance-ids $INSTANCE_ID --profile lab-sso echo "Instance terminated. Use lab-create to launch a fresh one." else echo "Cancelled." end
end
function lab-terminate echo "WARNING: This will permanently delete the instance and all data on it." echo "Instance: $INSTANCE_ID" read --prompt-str "Type YES to confirm: " confirm if test "$confirm" = "YES" aws ec2 terminate-instances \ --instance-ids $INSTANCE_ID --profile lab-sso echo "Instance terminated. Use lab-create to launch a fresh one." else echo "Cancelled." end
end
function lab-create echo "Launching new suricata-ids-lab instance..." set new_id (aws ec2 run-instances \ --launch-template LaunchTemplateName=suricata-lab-template \ --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=suricata-ids-lab}]" \ --profile lab-sso \ --query "Instances[0].InstanceId" \ --output text) if test -z "$new_id" echo "ERROR: Failed to launch instance." return 1 end echo "Instance launched: $new_id" echo "Updating INSTANCE_ID..." set -U INSTANCE_ID $new_id echo "Waiting for instance to reach running state..." aws ec2 wait instance-running \ --instance-ids $new_id \ --profile lab-sso echo "Instance is running." echo "Waiting 3 minutes for SSM Agent to initialize..." sleep 180 echo "Ready. Run lab-connect to -weight: 500;">start your session."
end
function lab-create echo "Launching new suricata-ids-lab instance..." set new_id (aws ec2 run-instances \ --launch-template LaunchTemplateName=suricata-lab-template \ --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=suricata-ids-lab}]" \ --profile lab-sso \ --query "Instances[0].InstanceId" \ --output text) if test -z "$new_id" echo "ERROR: Failed to launch instance." return 1 end echo "Instance launched: $new_id" echo "Updating INSTANCE_ID..." set -U INSTANCE_ID $new_id echo "Waiting for instance to reach running state..." aws ec2 wait instance-running \ --instance-ids $new_id \ --profile lab-sso echo "Instance is running." echo "Waiting 3 minutes for SSM Agent to initialize..." sleep 180 echo "Ready. Run lab-connect to -weight: 500;">start your session."
end
function lab-create echo "Launching new suricata-ids-lab instance..." set new_id (aws ec2 run-instances \ --launch-template LaunchTemplateName=suricata-lab-template \ --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=suricata-ids-lab}]" \ --profile lab-sso \ --query "Instances[0].InstanceId" \ --output text) if test -z "$new_id" echo "ERROR: Failed to launch instance." return 1 end echo "Instance launched: $new_id" echo "Updating INSTANCE_ID..." set -U INSTANCE_ID $new_id echo "Waiting for instance to reach running state..." aws ec2 wait instance-running \ --instance-ids $new_id \ --profile lab-sso echo "Instance is running." echo "Waiting 3 minutes for SSM Agent to initialize..." sleep 180 echo "Ready. Run lab-connect to -weight: 500;">start your session."
end
function lab-snapshot-list echo "Your saved AMIs:" aws ec2 describe-images \ --owners self \ --query "Images[*].[ImageId,Name,CreationDate]" \ --output table \ --profile lab-sso
end
function lab-snapshot-list echo "Your saved AMIs:" aws ec2 describe-images \ --owners self \ --query "Images[*].[ImageId,Name,CreationDate]" \ --output table \ --profile lab-sso
end
function lab-snapshot-list echo "Your saved AMIs:" aws ec2 describe-images \ --owners self \ --query "Images[*].[ImageId,Name,CreationDate]" \ --output table \ --profile lab-sso
end
$ lab-snapshot-list Your saved AMIs:
+------------------------+---------------------------+----------------------+
| ami-0xxxxxxxxxxxxxxxxx | suricata_setup-2026-03-15 | 2026-03-15T12:00:00Z |
+------------------------+---------------------------+----------------------+
$ lab-snapshot-list Your saved AMIs:
+------------------------+---------------------------+----------------------+
| ami-0xxxxxxxxxxxxxxxxx | suricata_setup-2026-03-15 | 2026-03-15T12:00:00Z |
+------------------------+---------------------------+----------------------+
$ lab-snapshot-list Your saved AMIs:
+------------------------+---------------------------+----------------------+
| ami-0xxxxxxxxxxxxxxxxx | suricata_setup-2026-03-15 | 2026-03-15T12:00:00Z |
+------------------------+---------------------------+----------------------+
function lab-snapshot echo "Your running instances:" aws ec2 describe-instances \ --filters "Name=instance-state-name,Values=running" \ --query "Reservations[*].Instances[*].[InstanceId,State.Name]" \ --output table \ --profile lab-sso read --prompt-str "Enter Instance ID to snapshot (i-...): " instance_id if test -z "$instance_id" echo "ERROR: No Instance ID entered. Cancelled." return 1 end read --prompt-str "Enter a name for this snapshot: " snapshot_name if test -z "$snapshot_name" echo "ERROR: No snapshot name entered. Cancelled." return 1 end set today (date +%Y-%m-%d) echo "Creating snapshot of $instance_id..." set ami_id (aws ec2 create-image \ --instance-id $instance_id \ --name "$snapshot_name-$today" \ --description "Lab snapshot: $snapshot_name" \ --no-reboot \ --profile lab-sso \ --query "ImageId" \ --output text) if test -z "$ami_id" echo "ERROR: Failed to create snapshot." return 1 end echo "Snapshot created: $ami_id" echo "Waiting for snapshot to become available..." aws ec2 wait image-available \ --image-ids $ami_id \ --profile lab-sso echo "Snapshot is ready: $ami_id" echo "Use this ID with lab-restore to launch from this state."
end
function lab-snapshot echo "Your running instances:" aws ec2 describe-instances \ --filters "Name=instance-state-name,Values=running" \ --query "Reservations[*].Instances[*].[InstanceId,State.Name]" \ --output table \ --profile lab-sso read --prompt-str "Enter Instance ID to snapshot (i-...): " instance_id if test -z "$instance_id" echo "ERROR: No Instance ID entered. Cancelled." return 1 end read --prompt-str "Enter a name for this snapshot: " snapshot_name if test -z "$snapshot_name" echo "ERROR: No snapshot name entered. Cancelled." return 1 end set today (date +%Y-%m-%d) echo "Creating snapshot of $instance_id..." set ami_id (aws ec2 create-image \ --instance-id $instance_id \ --name "$snapshot_name-$today" \ --description "Lab snapshot: $snapshot_name" \ --no-reboot \ --profile lab-sso \ --query "ImageId" \ --output text) if test -z "$ami_id" echo "ERROR: Failed to create snapshot." return 1 end echo "Snapshot created: $ami_id" echo "Waiting for snapshot to become available..." aws ec2 wait image-available \ --image-ids $ami_id \ --profile lab-sso echo "Snapshot is ready: $ami_id" echo "Use this ID with lab-restore to launch from this state."
end
function lab-snapshot echo "Your running instances:" aws ec2 describe-instances \ --filters "Name=instance-state-name,Values=running" \ --query "Reservations[*].Instances[*].[InstanceId,State.Name]" \ --output table \ --profile lab-sso read --prompt-str "Enter Instance ID to snapshot (i-...): " instance_id if test -z "$instance_id" echo "ERROR: No Instance ID entered. Cancelled." return 1 end read --prompt-str "Enter a name for this snapshot: " snapshot_name if test -z "$snapshot_name" echo "ERROR: No snapshot name entered. Cancelled." return 1 end set today (date +%Y-%m-%d) echo "Creating snapshot of $instance_id..." set ami_id (aws ec2 create-image \ --instance-id $instance_id \ --name "$snapshot_name-$today" \ --description "Lab snapshot: $snapshot_name" \ --no-reboot \ --profile lab-sso \ --query "ImageId" \ --output text) if test -z "$ami_id" echo "ERROR: Failed to create snapshot." return 1 end echo "Snapshot created: $ami_id" echo "Waiting for snapshot to become available..." aws ec2 wait image-available \ --image-ids $ami_id \ --profile lab-sso echo "Snapshot is ready: $ami_id" echo "Use this ID with lab-restore to launch from this state."
end
function lab-restore echo "Your saved AMIs:" aws ec2 describe-images \ --owners self \ --query "Images[*].[ImageId,Name,CreationDate]" \ --output table \ --profile lab-sso read --prompt-str "Enter AMI ID to restore from (ami-...): " ami_id if test -z "$ami_id" echo "ERROR: No AMI ID entered. Cancelled." return 1 end set sg_id (aws ec2 describe-security-groups \ --filters "Name=group-name,Values=suricata-lab-sg" \ --query "SecurityGroups[0].GroupId" \ --output text \ --profile lab-sso) if test -z "$sg_id" echo "ERROR: Could not find security group suricata-lab-sg." return 1 end echo "Launching from snapshot $ami_id..." set new_id (aws ec2 run-instances \ --image-id $ami_id \ --instance-type t2.micro \ --iam-instance-profile Name=suricata-lab-ssm-role \ --security-group-ids $sg_id \ --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=suricata-ids-lab}]" \ --profile lab-sso \ --query "Instances[0].InstanceId" \ --output text) if test -z "$new_id" echo "ERROR: Failed to launch instance. Check AMI ID and try again." return 1 end echo "Instance launched: $new_id" echo "Updating INSTANCE_ID..." set -U INSTANCE_ID $new_id echo "Waiting for instance to reach running state..." aws ec2 wait instance-running \ --instance-ids $new_id \ --profile lab-sso echo "Instance is running." echo "Waiting 60 seconds for SSM Agent to initialize..." sleep 60 echo "Ready. Run lab-connect to -weight: 500;">start your session."
end
function lab-restore echo "Your saved AMIs:" aws ec2 describe-images \ --owners self \ --query "Images[*].[ImageId,Name,CreationDate]" \ --output table \ --profile lab-sso read --prompt-str "Enter AMI ID to restore from (ami-...): " ami_id if test -z "$ami_id" echo "ERROR: No AMI ID entered. Cancelled." return 1 end set sg_id (aws ec2 describe-security-groups \ --filters "Name=group-name,Values=suricata-lab-sg" \ --query "SecurityGroups[0].GroupId" \ --output text \ --profile lab-sso) if test -z "$sg_id" echo "ERROR: Could not find security group suricata-lab-sg." return 1 end echo "Launching from snapshot $ami_id..." set new_id (aws ec2 run-instances \ --image-id $ami_id \ --instance-type t2.micro \ --iam-instance-profile Name=suricata-lab-ssm-role \ --security-group-ids $sg_id \ --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=suricata-ids-lab}]" \ --profile lab-sso \ --query "Instances[0].InstanceId" \ --output text) if test -z "$new_id" echo "ERROR: Failed to launch instance. Check AMI ID and try again." return 1 end echo "Instance launched: $new_id" echo "Updating INSTANCE_ID..." set -U INSTANCE_ID $new_id echo "Waiting for instance to reach running state..." aws ec2 wait instance-running \ --instance-ids $new_id \ --profile lab-sso echo "Instance is running." echo "Waiting 60 seconds for SSM Agent to initialize..." sleep 60 echo "Ready. Run lab-connect to -weight: 500;">start your session."
end
function lab-restore echo "Your saved AMIs:" aws ec2 describe-images \ --owners self \ --query "Images[*].[ImageId,Name,CreationDate]" \ --output table \ --profile lab-sso read --prompt-str "Enter AMI ID to restore from (ami-...): " ami_id if test -z "$ami_id" echo "ERROR: No AMI ID entered. Cancelled." return 1 end set sg_id (aws ec2 describe-security-groups \ --filters "Name=group-name,Values=suricata-lab-sg" \ --query "SecurityGroups[0].GroupId" \ --output text \ --profile lab-sso) if test -z "$sg_id" echo "ERROR: Could not find security group suricata-lab-sg." return 1 end echo "Launching from snapshot $ami_id..." set new_id (aws ec2 run-instances \ --image-id $ami_id \ --instance-type t2.micro \ --iam-instance-profile Name=suricata-lab-ssm-role \ --security-group-ids $sg_id \ --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=suricata-ids-lab}]" \ --profile lab-sso \ --query "Instances[0].InstanceId" \ --output text) if test -z "$new_id" echo "ERROR: Failed to launch instance. Check AMI ID and try again." return 1 end echo "Instance launched: $new_id" echo "Updating INSTANCE_ID..." set -U INSTANCE_ID $new_id echo "Waiting for instance to reach running state..." aws ec2 wait instance-running \ --instance-ids $new_id \ --profile lab-sso echo "Instance is running." echo "Waiting 60 seconds for SSM Agent to initialize..." sleep 60 echo "Ready. Run lab-connect to -weight: 500;">start your session."
end
function lab-snapshot-delete echo "Your saved AMIs:" aws ec2 describe-images \ --owners self \ --query "Images[*].[ImageId,Name,CreationDate]" \ --output table \ --profile lab-sso read --prompt-str "Enter AMI ID to delete (ami-...): " ami_id if test -z "$ami_id" echo "ERROR: No AMI ID entered. Cancelled." return 1 end set snapshot_id (aws ec2 describe-images \ --image-ids $ami_id \ --query "Images[0].BlockDeviceMappings[0].Ebs.SnapshotId" \ --output text \ --profile lab-sso) read --prompt-str "Delete $ami_id ($snapshot_id)? Type YES to confirm: " confirm if test "$confirm" != "YES" echo "Cancelled." return 0 end aws ec2 deregister-image \ --image-id $ami_id \ --profile lab-sso echo "AMI deregistered: $ami_id" aws ec2 delete-snapshot \ --snapshot-id $snapshot_id \ --profile lab-sso echo "Snapshot deleted: $snapshot_id" echo "Done. Storage charges for this snapshot will -weight: 500;">stop within the hour."
end
function lab-snapshot-delete echo "Your saved AMIs:" aws ec2 describe-images \ --owners self \ --query "Images[*].[ImageId,Name,CreationDate]" \ --output table \ --profile lab-sso read --prompt-str "Enter AMI ID to delete (ami-...): " ami_id if test -z "$ami_id" echo "ERROR: No AMI ID entered. Cancelled." return 1 end set snapshot_id (aws ec2 describe-images \ --image-ids $ami_id \ --query "Images[0].BlockDeviceMappings[0].Ebs.SnapshotId" \ --output text \ --profile lab-sso) read --prompt-str "Delete $ami_id ($snapshot_id)? Type YES to confirm: " confirm if test "$confirm" != "YES" echo "Cancelled." return 0 end aws ec2 deregister-image \ --image-id $ami_id \ --profile lab-sso echo "AMI deregistered: $ami_id" aws ec2 delete-snapshot \ --snapshot-id $snapshot_id \ --profile lab-sso echo "Snapshot deleted: $snapshot_id" echo "Done. Storage charges for this snapshot will -weight: 500;">stop within the hour."
end
function lab-snapshot-delete echo "Your saved AMIs:" aws ec2 describe-images \ --owners self \ --query "Images[*].[ImageId,Name,CreationDate]" \ --output table \ --profile lab-sso read --prompt-str "Enter AMI ID to delete (ami-...): " ami_id if test -z "$ami_id" echo "ERROR: No AMI ID entered. Cancelled." return 1 end set snapshot_id (aws ec2 describe-images \ --image-ids $ami_id \ --query "Images[0].BlockDeviceMappings[0].Ebs.SnapshotId" \ --output text \ --profile lab-sso) read --prompt-str "Delete $ami_id ($snapshot_id)? Type YES to confirm: " confirm if test "$confirm" != "YES" echo "Cancelled." return 0 end aws ec2 deregister-image \ --image-id $ami_id \ --profile lab-sso echo "AMI deregistered: $ami_id" aws ec2 delete-snapshot \ --snapshot-id $snapshot_id \ --profile lab-sso echo "Snapshot deleted: $snapshot_id" echo "Done. Storage charges for this snapshot will -weight: 500;">stop within the hour."
end
lab-login # tap YubiKey → 8hr credentials
lab-restore # launch from snapshot → wait → "Ready"
lab-connect # shell as ssm-user
lab-snapshot # save progress before ending session
lab-terminate # zero ongoing cost
lab-login # tap YubiKey → 8hr credentials
lab-restore # launch from snapshot → wait → "Ready"
lab-connect # shell as ssm-user
lab-snapshot # save progress before ending session
lab-terminate # zero ongoing cost
lab-login # tap YubiKey → 8hr credentials
lab-restore # launch from snapshot → wait → "Ready"
lab-connect # shell as ssm-user
lab-snapshot # save progress before ending session
lab-terminate # zero ongoing cost - Train developers to write secure code
- Prepare security engineers for technical interviews