diff --git a/.gitignore b/.gitignore index 9773ff1..b2be92b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -.venv -.ruff_cache +result diff --git a/README.md b/README.md deleted file mode 100644 index 05636c3..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Calliope - -A monorepo for QoL stuff for Adaptation diff --git a/calliope.nix b/calliope.nix new file mode 100644 index 0000000..2c203c8 --- /dev/null +++ b/calliope.nix @@ -0,0 +1,17 @@ +# Consumes user.nix, configuration.nix +{ config, pkgs, lib, ... }: +{ config, pkgs, lib, ...}: +{ + imports = [ + ./configuration.nix + ./user.nix + ]; + calliope = { + hostName = "marcille"; + ipv4Address = "172.18.154.50"; + cec = "akristip"; + username = "mira"; + shell = pkgs.xonsh; + #password = ""; + } +} diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..c93d478 --- /dev/null +++ b/configuration.nix @@ -0,0 +1,135 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, lib, ... }: + +{ +# imports = +# [ # Include the results of the hardware scan. +# ./user.nix +# ]; + + networking.nameservers = [ "64.102.6.247" ]; + networking.search = [ "cisco.com" ]; + + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + nix.package = pkgs.lix; + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + + # Set your time zone. + time.timeZone = "America/New_York"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "en_US.UTF-8"; + LC_IDENTIFICATION = "en_US.UTF-8"; + LC_MEASUREMENT = "en_US.UTF-8"; + LC_MONETARY = "en_US.UTF-8"; + LC_NAME = "en_US.UTF-8"; + LC_NUMERIC = "en_US.UTF-8"; + LC_PAPER = "en_US.UTF-8"; + LC_TELEPHONE = "en_US.UTF-8"; + LC_TIME = "en_US.UTF-8"; + }; + + # Configure keymap in X11 + services.xserver.xkb = { + layout = "us"; + variant = ""; + }; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.mira = { + isNormalUser = true; + description = "Mira"; + extraGroups = [ "networkmanager" "wheel" ]; + packages = with pkgs; []; + }; + + users.users.chris = { + isNormalUser = true; + description = "Chris"; + extraGroups = [ "networkmanager" "wheel" ]; + packages = with pkgs; []; + }; + # Enable automatic login for the user. + services.getty.autologinUser = lib.mkDefault "mira"; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + # wget + lsd + fd + ripgrep + thefuck + nh + hyfetch + fastfetch + uv + edit + ]; + + programs.neovim = { + enable = true; + defaultEditor = true; + }; + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + programs.gnupg.agent = { + enable = true; + enableSSHSupport = true; + }; + + programs.tmux = { + enable = true; + shortcut = "a"; + keyMode = "vi"; + + }; + + # TODO: copy git config here + + # TODO: configure git-delta + + # TODO: set aliases (eg ls to lsd) + + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + networking.firewall.enable = true; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "24.11"; # Did you read the comment? + virtualisation.vmware.guest.enable = true; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..913881d --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1747825515, + "narHash": "sha256-BWpMQymVI73QoKZdcVCxUCCK3GNvr/xa2Dc4DM1o2BE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cd2812de55cf87df88a9e09bf3be1ce63d50c1a6", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..e9e94c9 --- /dev/null +++ b/flake.nix @@ -0,0 +1,27 @@ +{ + inputs = { + # NOTE: Replace "nixos-23.11" with that which is in system.stateVersion of + # configuration.nix. You can also use latter versions if you wish to + # upgrade. + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + }; + outputs = inputs@{ self, nixpkgs, ... }: { + # NOTE: 'nixos' is the default hostname set by the installer + nixosConfigurations.marcille = nixpkgs.lib.nixosSystem { + # NOTE: Change this to aarch64-linux if you are on ARM + system = "x86_64-linux"; + modules = [ + ./configuration.nix + ./hardware-configuration.nix + ]; + + }; + nixosConfigurations.live = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + (nixpkgs + "/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix") + ./configuration.nix + ]; + }; + }; +} diff --git a/hardware-configuration.nix b/hardware-configuration.nix new file mode 100644 index 0000000..ca532d4 --- /dev/null +++ b/hardware-configuration.nix @@ -0,0 +1,51 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = [ ]; + + boot.initrd.availableKernelModules = [ "ata_piix" "vmw_pvscsi" "ahci" "sd_mod" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/2135c59d-9c2d-487c-9c4e-0f566fa9d316"; + fsType = "btrfs"; + options = [ "subvol=@" ]; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/7E60-8E0B"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault false; + # networking.interfaces.ens33.useDHCP = lib.mkDefault true; + networking.interfaces.ens33 = { + ipv4.addresses = [{ + address = "172.18.154.50"; + prefixLength = 24; + }]; + }; + + # Enable networking + networking.networkmanager.enable = true; + + networking.defaultGateway = { + address = "172.18.154.1"; + interface = "ens33"; + }; + networking.nameservers = [ "64.102.6.247" ]; + networking.search = [ "cisco.com" ]; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/ise/ISE-bash-scripts/.gitignore b/ise/ISE-bash-scripts/.gitignore deleted file mode 100644 index 3d10c82..0000000 --- a/ise/ISE-bash-scripts/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.tar.gz - diff --git a/ise/ISE-bash-scripts/README.md b/ise/ISE-bash-scripts/README.md deleted file mode 100644 index 3d2b303..0000000 --- a/ise/ISE-bash-scripts/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# ISE Utility Bash Scripts - -Currently these set of scripts are able to: -- Login to ISE -- Logout of ISE -- Enable/Disable ERS API -- Create new OCSP Profile -- Disable admin password requirements such as expiration and complexity - -## Usage -1. Change `HOSTNAME` in `login.bash` to the IP address/FQDN of your ISE server. -2. Read the script to understand what it is doing and modify any variables that you need to. - 1. For example, `create_new_ocsp_profile.bash` requires you to modify the following: - - CRUD="Create" - - OCSP_PRIMARY_URL="[2001:420:27ff:fff9::7]:5000" - - OCSP_SERVICE_NAME="ggg" - - SELECTED_ITEM_NAME="ggg" -2. Execute any of the scripts that you want to modify settings on. - diff --git a/ise/ISE-bash-scripts/create_new_ocsp_profile.bash b/ise/ISE-bash-scripts/create_new_ocsp_profile.bash deleted file mode 100755 index cd93314..0000000 --- a/ise/ISE-bash-scripts/create_new_ocsp_profile.bash +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -source ./login.bash - -# Make OCSP request -echo -e "Updating OCSP Client Profile" -CRUD="Create" # This can be Create or Edit -OCSP_PRIMARY_URL="[2001:420:27ff:fff9::7]:5000" -OCSP_SERVICE_NAME="ggg" -SELECTED_ITEM_NAME="ggg" # This one is needed when you edit an existing OCSP service -curl -k 'https://diorite.cisco.com/admin/ocspServicesAction.do' -X POST \ - -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0' \ - -H 'Accept: */*' -H 'Accept-Language: en-US,en;q=0.5' \ - -H 'Accept-Encoding: gzip, deflate, br, zstd' \ - -H '_QPH_: Y29tbWFuZD1zYXZl' -H 'Content-Type: application/x-www-form-urlencoded' \ - -H 'X-Requested-With: XMLHttpRequest, XMLHttpRequest' \ - -H "OWASP_CSRFTOKEN: ${CSRFTOKEN}" \ - -H 'Connection: keep-alive' \ - -H "Cookie: APPSESSIONID=${APPSESSIONID}; MNTLA_JWT_TOKEN=${JWT_TOKEN}" \ - --data-raw "crud=$CRUD&selectedItemName=$SELECTED_ITEM_NAME&ocspServicesStub.failoverToSecondary=false&ocspServicesStub.alwaysAccessPrimaryFirst=true&ocspServicesStub.primaryNonceExtensions=true&ocspServicesStub.primaryValidateResponseSignature=true&ocspServicesStub.secondaryNonceExtensions=true&ocspServicesStub.secondaryValidateResponseSignature=true&ocspServicesStub.selectedOCSPConfig=OCSP_RESPONDER&ocspServicesStub.enableNonceExtensionSupportAia=true&ocspServicesStub.validateResponseSignatureAia=true&ocspServicesStub.name=$OCSP_SERVICE_NAME&ocspServicesStub.description=&ocspServicesStub.primaryURL=$OCSP_PRIMARY_URL&primaryNonceExtensionsCB=on&primaryValidateResponseSignatureCB=on&ocspServicesStub.cacheTimeout=1440" 2>/dev/null | jq - -source ./logout.bash - diff --git a/ise/ISE-bash-scripts/disable_admin_annoyances.bash b/ise/ISE-bash-scripts/disable_admin_annoyances.bash deleted file mode 100755 index 3c7962e..0000000 --- a/ise/ISE-bash-scripts/disable_admin_annoyances.bash +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -source ./login.bash - -# _QPC_ is a base64 encoded string that contains the CSRF token -QPC=$(printf "command=editAuthSubmit&OWASP_CSRFTOKEN=$CSRFTOKEN" | $BASE64 -w0) - -curl "https://$HOSTNAME/admin/adminAuthSettingsAction.do" --compressed --insecure -X POST \ - -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:128.0) Gecko/20100101 Firefox/128.0' \ - -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8' \ - -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br, zstd' \ - -H 'Content-Type: multipart/form-data; boundary=---------------------------1799742068132450087154255035' \ - -H "Cookie: APPSESSIONID=$APPSESSIONID; _QPC_=$QPC; MNTLA_JWT_TOKEN=$JWT_TOKEN" \ - --data-binary $'-----------------------------1799742068132450087154255035\r\nContent-Disposition: form-data; name="adminAuthSettingsStub.passwordLengthTxt"\r\n\r\n4\r\n-----------------------------1799742068132450087154255035\r\nContent-Disposition: form-data; name="adminAuthSettingsStub.passwordNotUserCharsTxt"\r\n\r\n\r\n-----------------------------1799742068132450087154255035\r\nContent-Disposition: form-data; name="adminAuthSettingsStub.isNewDictFile"\r\n\r\nfalse\r\n-----------------------------1799742068132450087154255035\r\nContent-Disposition: form-data; name="adminAuthSettingsStub.passwordHistoryTxt"\r\n\r\n3\r\n-----------------------------1799742068132450087154255035\r\nContent-Disposition: form-data; name="adminAuthSettingsStub.passwordReuse"\r\n\r\n15\r\n-----------------------------1799742068132450087154255035\r\nContent-Disposition: form-data; name="adminAuthSettingsStub.passwordDisableUserAccountTxt"\r\n\r\n45\r\n-----------------------------1799742068132450087154255035\r\nContent-Disposition: form-data; name="adminAuthSettingsStub.passwordDisplayReminderTxt"\r\n\r\n30\r\n-----------------------------1799742068132450087154255035\r\nContent-Disposition: form-data; name="OWASP_CSRFTOKEN"\r\n\r\n""\r\n-----------------------------1799742068132450087154255035--\r\n' - -source ./logout.bash - diff --git a/ise/ISE-bash-scripts/enable_ers_api.bash b/ise/ISE-bash-scripts/enable_ers_api.bash deleted file mode 100755 index b5730d9..0000000 --- a/ise/ISE-bash-scripts/enable_ers_api.bash +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -source ./login.bash - -# Make the API call to enable ERS API -ENABLE_ERS_API='true' -curl -k "https://$HOSTNAME/admin/ersSettingsAction.do" -X POST \ - -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:128.0) Gecko/20100101 Firefox/128.0' \ - -H 'Accept: */*' \ - -H 'Accept-Language: en-US,en;q=0.5' \ - -H 'Accept-Encoding: gzip, deflate, br, zstd' \ - -H '_QPH_: Y29tbWFuZD1zdWJtaXRBUElTZXJ2aWNlU2V0dGluZ3M=' \ - -H 'Content-Type: application/x-www-form-urlencoded' \ - -H 'X-Requested-With: XMLHttpRequest, XMLHttpRequest' \ - -H "OWASP_CSRFTOKEN: $CSRFTOKEN" \ - -H "Origin: https://$HOSTNAME" \ - -H 'Connection: keep-alive' \ - -H 'Referer: https://diorite.cisco.com/admin/' \ - -H "Cookie: APPSESSIONID=$APPSESSIONID; MNTLA_JWT_TOKEN=$JWT_TOKEN" \ - -H 'Sec-Fetch-Dest: empty' \ - -H 'Sec-Fetch-Mode: cors' \ - -H 'Sec-Fetch-Site: same-origin' \ - -H 'Priority: u=0' \ - --data-raw "PAPEnabled=$ENABLE_ERS_API&OWASP_CSRFTOKEN=$CSRFTOKEN" 2>/dev/null | awk '{$1=$1};1' | awk '{printf "%s",$0} END {print ""}' | awk '{gsub(/'\''/, "\""); print}' | jq - -source ./logout.bash - diff --git a/ise/ISE-bash-scripts/execute_jenkins_job.bash b/ise/ISE-bash-scripts/execute_jenkins_job.bash deleted file mode 100755 index 3474010..0000000 --- a/ise/ISE-bash-scripts/execute_jenkins_job.bash +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -JOB_NAME=STO_Sparta_sysdevST02 -JOB_SCRIPT=ipv6_policy_set_radius_attributes.py -BRANCH_NAME=radius_ipv6_ise_1971 - -curl -k -X POST https://spotlight-jenkins.cisco.com/job/STO_Sparta/job/$JOB_NAME/buildWithParameters \ - --user iuser:11cdf2ceeab4fd7bd0e3d3bca18066ad2a \ - --data jobname=$JOB_SCRIPT \ - --data branch=$BRANCH_NAME \ - --data revert=true \ - --data revert_option=init/standalone \ - --data build=3.4.0.379 - diff --git a/ise/ISE-bash-scripts/login.bash b/ise/ISE-bash-scripts/login.bash deleted file mode 100755 index 56a3ee4..0000000 --- a/ise/ISE-bash-scripts/login.bash +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash - -HOSTNAME="sto-sparta-ise-3.cisco.com" -USERNAME="admin" -PASSWORD="Lab@12345" -APPSESSIONID=0 -CSRFTOKEN=0 -JWT_TOKEN=0 -QPC=0 - -GREP="grep" -BASE64="base64" -if [[ "$OSTYPE" == "darwin"* ]]; then - echo -e "Using g* tools because of course macOS" - GREP="ggrep" - BASE64="gbase64" -fi - -# Get the CSRF token and APPSESSIONID -echo -e "Getting CSRF token and initial APPSESSIONID" -output=$(curl -c - -k -L -s --compressed --request POST \ - --url https://$HOSTNAME/admin/JavaScriptServlet \ - --header 'Accept: */*' \ - --header 'Accept-Encoding: gzip, deflate, br, zstd' \ - --header 'Accept-Language: en-US,en;q=0.5' \ - --header 'Connection: keep-alive' \ - --header 'Content-Length: 0' \ - --header 'DNT: 1' \ - --header 'FETCH-CSRF-TOKEN: 1' \ - --header 'Origin: CWILLIA5-M-WJ2C' \ - --header 'Sec-Fetch-Dest: empty' \ - --header 'Sec-GPC: 1' \ - --header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0' 2>/dev/null ) - -CSRFTOKEN=$(echo $output | $GREP -oP '(?<=OWASP_CSRFTOKEN:)[^#]*') -APPSESSIONID=$(echo $output | awk '{print $NF}') -echo -e "CSRFTOKEN: $CSRFTOKEN" -echo -e "APPSESSIONID: $APPSESSIONID" - -# Get the JWT token -echo -e "Logging in, getting JWT token and updating APPSESSIONID" -output=$(curl -k -c - --request POST \ - --cookie "APPSESSIONID=$APPSESSIONID" \ - --url https://$HOSTNAME/admin/LoginAction.do \ - --header 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' \ - --header 'Accept-Encoding: gzip, deflate, br, zstd' \ - --header 'Accept-Language: en-US,en;q=0.5' \ - --header 'Connection: keep-alive' \ - --header 'Content-Type: application/x-www-form-urlencoded' \ - --header 'DNT: 1' \ - --header 'Priority: u=1' \ - --header 'Sec-Fetch-Dest: document' \ - --header 'Sec-Fetch-Mode: navigate' \ - --header 'Sec-Fetch-User: ?1' \ - --header 'Sec-GPC: 1' \ - --header 'Upgrade-Insecure-Requests: 1' \ - --header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0' \ - --data username=$USERNAME \ - --data password=$PASSWORD \ - --data samlLogin=false \ - --data rememberme=off \ - --data name=$USERNAME \ - --data password=$PASSWORD \ - --data authType=Internal \ - --data CSRFTokenNameValue=OWASP_CSRFTOKEN=$CSRFTOKEN \ - --data OWASP_CSRFTOKEN=$CSRFTOKEN \ - --data locale=en \ - --data hasSelectedLocale=false 2>/dev/null) - -# APPSESSIONID Gets updated here so we need to reassign APPSESSIONID -APPSESSIONID=$(echo -e "$output" | awk '/APPSESSIONID/ {print $7}') -JWT_TOKEN=$(echo -e "$output" | awk '/MNTLA_JWT_TOKEN/ {print $7}') -echo -e "JWT_TOKEN: $JWT_TOKEN" - diff --git a/ise/ISE-bash-scripts/logout.bash b/ise/ISE-bash-scripts/logout.bash deleted file mode 100755 index 81440dc..0000000 --- a/ise/ISE-bash-scripts/logout.bash +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -# Logging out -echo -e "Logging out" -curl -k "https://$HOSTNAME/admin/logout.jsp" \ - -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:128.0) Gecko/20100101 Firefox/128.0' \ - -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8' \ - -H 'Accept-Language: en-US,en;q=0.5' \ - -H 'Accept-Encoding: gzip, deflate, br, zstd' \ - -H 'Connection: keep-alive' \ - -H "Cookie: APPSESSIONID=$APPSESSIONID; MNTLA_JWT_TOKEN=$JWT_TOKEN" \ - -H 'Upgrade-Insecure-Requests: 1' \ - -H 'Sec-Fetch-Dest: document' \ - -H 'Sec-Fetch-Mode: navigate' \ - -H 'Sec-Fetch-Site: same-origin' \ - -H 'Sec-Fetch-User: ?1' \ - -H 'Priority: u=0, i' diff --git a/ise/ise_logparser/.gitignore b/ise/ise_logparser/.gitignore deleted file mode 100644 index 1a4595e..0000000 --- a/ise/ise_logparser/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -*.log diff --git a/ise/ise_logparser/.python-version b/ise/ise_logparser/.python-version deleted file mode 100644 index 39f773d..0000000 --- a/ise/ise_logparser/.python-version +++ /dev/null @@ -1 +0,0 @@ -pypy@3.10.14 diff --git a/ise/ise_logparser/Cargo.lock b/ise/ise_logparser/Cargo.lock deleted file mode 100644 index a6a6736..0000000 --- a/ise/ise_logparser/Cargo.lock +++ /dev/null @@ -1,140 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "const_format" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" -dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "ise_logparser" -version = "0.1.0" -dependencies = [ - "const_format", - "lazy_static", - "nom", - "nom-regex", - "regex", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nom-regex" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e5c7731c4c1370b61604ed52a2475e861aac9e08dec9f23903d4ddfdc91c18" -dependencies = [ - "nom", - "regex", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" diff --git a/ise/ise_logparser/Cargo.toml b/ise/ise_logparser/Cargo.toml deleted file mode 100644 index e59afac..0000000 --- a/ise/ise_logparser/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "ise_logparser" -version = "0.1.0" -edition = "2021" - -[dependencies] -const_format = "0.2.32" -lazy_static = "1.5.0" -nom = "7.1.3" -nom-regex = "0.2.0" -regex = "1.10.6" diff --git a/ise/ise_logparser/README.md b/ise/ise_logparser/README.md deleted file mode 100644 index fc426ae..0000000 --- a/ise/ise_logparser/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ise-logparser - -Describe your project here. diff --git a/ise/ise_logparser/notes.md b/ise/ise_logparser/notes.md deleted file mode 100644 index a98c9d5..0000000 --- a/ise/ise_logparser/notes.md +++ /dev/null @@ -1,13 +0,0 @@ -``` -pre_test_output := .* -start_marker := 'JOB START' -test_output := .* -end_marker := 'JOB END' -post_test_output := .* -report_marker := 'Report' -report := .* -summary_marker := 'Result Summary' -summary := .* -details_marker := 'Result Details' -details := .* -``` diff --git a/ise/ise_logparser/pyproject.toml b/ise/ise_logparser/pyproject.toml deleted file mode 100644 index 3c2a0da..0000000 --- a/ise/ise_logparser/pyproject.toml +++ /dev/null @@ -1,33 +0,0 @@ -[project] -name = "ise-logparser" -version = "0.1.0" -description = "Add your description here" -authors = [ - { name = "Mira Kristipati", email = "akristip@cisco.com" } -] -dependencies = [ - "parsy>=2.1", - "icecream>=2.1.3", - "python-dotenv>=1.0.1", - "mypy>=1.11.1", - "setuptools>=72.1.0", - "colorama>=0.4.6", - "types-colorama>=0.4.15.20240311", - "flameprof>=0.4", -] -readme = "README.md" -requires-python = ">= 3.8" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.rye] -managed = true -dev-dependencies = [] - -[tool.hatch.metadata] -allow-direct-references = true - -[tool.hatch.build.targets.wheel] -packages = ["src/ise_logparser"] diff --git a/ise/ise_logparser/requirements-dev.lock b/ise/ise_logparser/requirements-dev.lock deleted file mode 100644 index c703ee8..0000000 --- a/ise/ise_logparser/requirements-dev.lock +++ /dev/null @@ -1,43 +0,0 @@ -# generated by rye -# use `rye lock` or `rye sync` to update this lockfile -# -# last locked with the following flags: -# pre: false -# features: [] -# all-features: false -# with-sources: false -# generate-hashes: false -# universal: false - --e file:. -asttokens==2.4.1 - # via icecream -colorama==0.4.6 - # via icecream - # via ise-logparser -executing==2.0.1 - # via icecream -flameprof==0.4 - # via ise-logparser -icecream==2.1.3 - # via ise-logparser -mypy==1.11.1 - # via ise-logparser -mypy-extensions==1.0.0 - # via mypy -parsy==2.1 - # via ise-logparser -pygments==2.18.0 - # via icecream -python-dotenv==1.0.1 - # via ise-logparser -setuptools==72.1.0 - # via ise-logparser -six==1.16.0 - # via asttokens -tomli==2.0.1 - # via mypy -types-colorama==0.4.15.20240311 - # via ise-logparser -typing-extensions==4.12.2 - # via mypy diff --git a/ise/ise_logparser/requirements.lock b/ise/ise_logparser/requirements.lock deleted file mode 100644 index c703ee8..0000000 --- a/ise/ise_logparser/requirements.lock +++ /dev/null @@ -1,43 +0,0 @@ -# generated by rye -# use `rye lock` or `rye sync` to update this lockfile -# -# last locked with the following flags: -# pre: false -# features: [] -# all-features: false -# with-sources: false -# generate-hashes: false -# universal: false - --e file:. -asttokens==2.4.1 - # via icecream -colorama==0.4.6 - # via icecream - # via ise-logparser -executing==2.0.1 - # via icecream -flameprof==0.4 - # via ise-logparser -icecream==2.1.3 - # via ise-logparser -mypy==1.11.1 - # via ise-logparser -mypy-extensions==1.0.0 - # via mypy -parsy==2.1 - # via ise-logparser -pygments==2.18.0 - # via icecream -python-dotenv==1.0.1 - # via ise-logparser -setuptools==72.1.0 - # via ise-logparser -six==1.16.0 - # via asttokens -tomli==2.0.1 - # via mypy -types-colorama==0.4.15.20240311 - # via ise-logparser -typing-extensions==4.12.2 - # via mypy diff --git a/ise/ise_logparser/src/main.py b/ise/ise_logparser/src/main.py deleted file mode 100755 index 819b4a2..0000000 --- a/ise/ise_logparser/src/main.py +++ /dev/null @@ -1,323 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import annotations -import cProfile -import argparse -import logging -import os -import profile -import re -from pathlib import Path -from typing import cast -import time -from icecream import ic -import pstats - -import parsy as ps -from colorama import Back, Fore, Style -from parsy import Parser, generate, peek, regex, seq, string -from functools import reduce - -ic.configureOutput(includeContext=True) - -LEVEL_UNKNOWN = 255 -NEWLINE = string("\n") -SPACE = string(" ") - - -class Config(dict[str, str]): - class LevelAction(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None) -> None: - _ = (parser, option_string) - values = cast(str, values) - setattr(namespace, self.dest, get_debug_level_const(values.upper())[0]) - - def __init__(self) -> None: - self.dict = {} - if os.path.exists(".env"): - from dotenv import dotenv_values - - self.dict = { - k: v for k, v in dotenv_values(".env").items() if v is not None - } - parser = argparse.ArgumentParser() - if not ("LOGFILE" in self.dict or "LOGFILE" in os.environ): - parser.add_argument( - "LOGFILE", - type=Path, - ) - parser.add_argument("-q", "--query", dest="QUERY") - parser.add_argument( - "-l", - "--level", - dest="LOGLEVEL", - type=str, - choices=["debug", "info", "warn", "err", "crit", "unk"], - default=logging.INFO, - action=self.LevelAction, - ) - - self.dict.update(parser.parse_args().__dict__) - - def __getitem__(self, key: str, /) -> str: - try: - return self.dict[key] - except KeyError: - return os.environ[key] - - def __setitem__(self, _key: str, _value: str, /) -> None: - msg = "Config is read-only" - raise NotImplementedError(msg) - - def __delitem__(self, _: str, /) -> None: - msg = "Config is read-only" - raise NotImplementedError(msg) - - def __iter__(self): - return iter(self.dict) - - def __len__(self) -> int: - return len(self.dict) - - def __repr__(self) -> str: - return self.dict.__repr__() - - -""" -Formatting functions -""" - - -def colorize_status(status: str) -> str: - if "PASS" in status: - return Fore.GREEN + status + Style.RESET_ALL - elif "FAIL" in status: - return Fore.RED + status + Style.RESET_ALL - elif "ERROR" in status: - return Fore.BLACK + Back.RED + status + Style.RESET_ALL - return status - - -def get_debug_level_const(level: str) -> tuple[int, str]: - if "DEBUG" in level: - return (logging.DEBUG, level) - elif "INFO" in level: - return (logging.INFO, level) - elif "WARN" in level: - return (logging.WARNING, level) - elif "ERR" in level: - return (logging.ERROR, level) - elif "CRIT" in level: - return (logging.CRITICAL, level) - else: - return (LEVEL_UNKNOWN, level) - - -def colorize_by_level(level: str, text: str) -> str: - if "DEBUG" in level: - return Style.DIM + text + Style.RESET_ALL - elif "INFO" in level: - return Style.BRIGHT + text + Style.RESET_ALL - elif "WARN" in level: - return Fore.YELLOW + text + Style.RESET_ALL - elif "ERR" in level: - return Fore.RED + text + Style.RESET_ALL - elif "CRIT" in level: - return Style.BRIGHT + Back.RED + Fore.BLACK + text + Style.RESET_ALL - else: - return Fore.BLUE + text + Style.RESET_ALL - # return level - - -""" -Output functions -""" - - -class TestPrinterBuilder: - loglevel: int = logging.NOTSET - query: str | re.Pattern[str] | None = None - - def __call__( - self, ts: str, level: tuple[int, str], src: str, msg: str - ) -> str | None: - level_name = level[1] - if (level[0] >= self.loglevel) or ( - self.query is not None and re.search(self.query, msg) - ): - res = f"{ts}\t{Fore.BLACK + Back.WHITE + level[1] + Style.RESET_ALL}\t{colorize_by_level(level_name,f'{src}: {msg}')}" - - print(res) - return res - return "" - - def with_loglevel(self, loglevel: int) -> TestPrinterBuilder: - self.loglevel = loglevel - return self - - def with_query(self, query: str | re.Pattern) -> TestPrinterBuilder: - self.query = query - return self - - -""" -Parser defs -""" - - -def block_parser(text: str) -> Parser: - return regex(rf"^.*\n^.*{text}.*$\n.*", re.MULTILINE) - - -timestamp: Parser = regex( - r"^\d{4}-\d{2}-\d{2}.\d{2}:\d{2}:\d{2}(\+\d{2}:\d{2})?(,\d{3})?", re.MULTILINE -).skip(string(":").optional()) - -debug_level: Parser = regex(r"[A-Za-z0-9_%-]+").skip(string(":").optional()) - - -start_block = block_parser("EASYPY JOB START") -end_block = block_parser("EASYPY JOB END") -report_block = block_parser("Easypy Report") -summary_block = block_parser("Task Result Summary") -details_block = block_parser("Task Result Details") - - -message = ps.any_char.until(ps.alt(ps.peek(timestamp), ps.eof)).concat() - - -@generate -def test_output_line(): - ts = yield timestamp.skip(SPACE) - level = yield debug_level.skip(SPACE) - src = yield ( - string("[").then(regex(r"[A-Za-z_0-9]+")).skip(string("] ")).optional() - ) - msg = yield message.map(lambda x: x.rstrip()) - - print_test_line(ts, get_debug_level_const(level), src, msg) - return ps.success("") - - -@generate -def test_details(): - indent = yield ( - NEWLINE.optional() - .skip(string("|").optional()) - .skip(SPACE.at_least(1)) - .then(ps.seq(ps.char_from("|`"), string("--").skip(ps.whitespace)).concat()) - ) - test_name = yield ps.any_char.until(ps.whitespace).skip(ps.whitespace).concat() - test_results = yield ps.letter.many().skip(NEWLINE).concat() - print(f" {' ' * (len(indent)//2)} {colorize_status(test_results)}\t{test_name}") - return {"test_results": test_results, "test_name": test_name} - - -@generate -def subtask_details(): - subtask_name = ( - yield seq(ps.alt(string("|--"), string("`--")), ps.whitespace) - .then(ps.any_char.until(ps.whitespace)) - .skip(ps.whitespace) - .concat() - ) - - subtask_result = yield ps.letter.many().skip(NEWLINE).concat() - print(f"  {colorize_status(subtask_result)}\t{subtask_name}") - tests = yield test_details.many() - return { - "subtask_result": subtask_result, - "subtask_name": subtask_name, - "tests": tests, - } - - -@generate -def task_details(): - task_number = ( - yield ps.any_char.until(string(":")) - .skip(string(":")) - .skip(ps.whitespace) - .concat() - ) - - task_name = yield ps.any_char.until(ps.whitespace).concat().skip(ps.whitespace) - print(f"{task_number}\t {Style.BRIGHT + task_name + Style.RESET_ALL}") - - subtasks = yield subtask_details.many() - return {"task_number": task_number, "task_name": task_name, "subtasks": subtasks} - - -@generate -# NOTE: Uncomment the print statements if you actually care what's in these sections -def sections(): - header = yield seq( - ps.any_char.until(peek(timestamp)), # TODO: output this - test_output_line.until(start_block).skip(start_block).skip(NEWLINE), - ).combine(list.__add__).concat() - - ic(elapsed()) - test_output = yield test_output_line.until(end_block).skip(end_block).skip(NEWLINE) - ic(elapsed()) - # exit(1) - post_test = yield ps.any_char.until(report_block).skip(report_block).concat() - ic(elapsed()) - # print(post_test) - report = yield ps.any_char.until(summary_block).skip(summary_block).concat() - ic(elapsed()) - # print(report) - summary = yield ps.any_char.until(details_block).skip(details_block).concat() - ic(elapsed()) - # print(summary) - details = yield task_details.many() - ic(elapsed()) - etc = yield ps.any_char.until(ps.eof).concat() - ic(elapsed()) - return { - "header": header, - "test_output": test_output, - "post_test": post_test, - "report": report, - "summary": summary, - "details": details, - "etc": etc, - } - - -def elapsed(): - global current - global prev - current = time.time() - elapsed = current - prev - prev = current - return elapsed - - -# TODO: make this work with streams -def main(): - global current - global prev - current = time.time() - prev = time.time() - config = Config() - with Path(config["LOGFILE"]).open() as f: - log = f.read() - global print_test_line - print_test_line = TestPrinterBuilder() - if loglevel := config["LOGLEVEL"]: - print_test_line = print_test_line.with_loglevel(cast(int, loglevel)) - if query := config.get("QUERY"): - print_test_line = print_test_line.with_query(query) - - sections.parse(log) - - -if __name__ == "__main__": - # import io - # pr = cProfile.Profile() - # pr.enable() - main() - # pr.disable() - # s = io.StringIO() - # ps = pstats.Stats(pr) - # ps.dump_stats("test.stats") - # print(s.getvalue()) diff --git a/ise/ise_logparser/src/main.rs b/ise/ise_logparser/src/main.rs deleted file mode 100644 index fcbc07e..0000000 --- a/ise/ise_logparser/src/main.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::{cell::OnceCell, sync::OnceLock}; - -use lazy_static::lazy_static; -use nom::{ - bytes::complete::take_while1, character::complete::anychar, error::ErrorKind, multi::many_till, - IResult, -}; -use nom_regex::str::re_match; -use regex::Regex; - -struct Sections { - header: String, -} - -static TIMESTAMP_REGEX: OnceLock = OnceLock::new(); -static START_BLOCK_REGEX: OnceLock = OnceLock::new(); -static END_BLOCK_REGEX: OnceLock = OnceLock::new(); -fn timestamp<'a>(input: &'a str) -> IResult<&'a str, &'a str> { - re_match::>(TIMESTAMP_REGEX.get().unwrap().clone())(input) -} - -fn debug_level(input: &str) -> IResult<&str, &str> { - take_while1(|c: char| c.is_alphabetic() || ['_', '-', '%'].contains(&c))(input) -} - -fn start_block(input: &str) -> IResult<&str, &str> { - re_match::>(START_BLOCK_REGEX.get().unwrap().clone())(input) -} - -fn end_block(input: &str) -> IResult<&str, &str> { - re_match::>(END_BLOCK_REGEX.get().unwrap().clone())(input) -} - - -fn test_output_line(input: &str) -> IResult<&str, &str> { - let (input, timestamp) = timestamp(input)?; - let (input, _) = nom::character::complete::char(' ')(input)?; - let (input, level) = debug_level(input)?; - let (input, _) = nom::character::complete::char(' ')(input)?; - let (input, _) = nom::character::complete::line_ending(input)?; - let (input, msg) = message(input)?; - IResult::Ok((input, "")) -} - -fn header(input: &str) -> IResult<&str, String> { - // any_char.until(timestamp).concat() - let (_, (b, rest)) = many_till(anychar, timestamp)(input)?; - let joined = b.iter().collect::(); - // test_output_line.until(start_block) - let (_, (c, rest)) = many_till(test_output_line, start_block)(rest)?; - print!("{}", rest); - IResult::Ok((input, joined)) -} -fn sections(log: &str) -> IResult<&str, Sections> { - let (_log, _header) = header(log)?; - todo!() -} - -fn main() { - TIMESTAMP_REGEX - .set(Regex::new(r"^\d{4}-\d{2}-\d{2}.\d{2}:\d{2}:\d{2}(\+\d{2}:\d{2})?(,\d{3})?").unwrap()) - .unwrap(); - - START_BLOCK_REGEX - .set(Regex::new(r"^.*\n^.*EASYPY JOB START.*$\n.*").unwrap()) - .unwrap(); - let file = include_str!("../consoleText"); - header(file); -} diff --git a/ise/reset-ise-passwd/.gitignore b/ise/reset-ise-passwd/.gitignore deleted file mode 100644 index 9773ff1..0000000 --- a/ise/reset-ise-passwd/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.venv -.ruff_cache diff --git a/ise/reset-ise-passwd/default.nix b/ise/reset-ise-passwd/default.nix deleted file mode 100644 index 8d3bc2f..0000000 --- a/ise/reset-ise-passwd/default.nix +++ /dev/null @@ -1,13 +0,0 @@ -{ pkgs ? import { } }: - -pkgs.mkShell { - packages = [ - (pkgs.python3.withPackages (python-pkgs: [ - python-pkgs.pexpect - python-pkgs.icecream - python-pkgs.mypy - # python-pkgs.ruff - ])) - pkgs.openssh - ]; -} diff --git a/ise/reset-ise-passwd/main.py b/ise/reset-ise-passwd/main.py deleted file mode 100755 index cc20b67..0000000 --- a/ise/reset-ise-passwd/main.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python3 -import argparse -import logging -import re -import sys -from logging import getLogger -from typing import List - -import pexpect - - -def login(username: str, password: str) -> pexpect.spawn: - child = pexpect.spawn( - f"ssh -i /dev/null {username}@{addr}", - encoding="utf-8", - logfile=sys.stdout, - ) - child.expect("password:") - child.sendline(password) - return child - - -def change_password(child: pexpect.spawn, old_password: str, new_password: str) -> None: - child.expect("password:") - child.sendline(old_password) - child.expect("[Nn]ew password:") - child.sendline(new_password) - child.expect("[Nn]ew password:") - child.sendline(new_password) - child.expect_list([re.compile("success"), re.compile(f"{username}#")]) - logger.info("Changing password to %s", new_password) - - -def set_new_password_and_verify( - child: pexpect.spawn, - password: str, - new_password: str, -) -> pexpect.spawn: - change_password(child, password, new_password) - - child = login(username, new_password) - child.expect(f"{username}#") - return child - - -if __name__ == "__main__": - logger = getLogger(__name__) - logger.level = logging.DEBUG - - parser = argparse.ArgumentParser() - parser.add_argument("addr", help="IP address of the device") - parser.add_argument("username", help="Username of the device", default="admin") - parser.add_argument("password", help="Password of the device") - args = parser.parse_args() - username = args.username - password = args.password - addr = args.addr - try: - passwords: List[str] = [password] + [ - "".join([f"{i}{j}" for i in password]) for j in range(4) - ] - - child = login(username, password) - new_password = passwords.pop() - child = set_new_password_and_verify(child, password, new_password) - - while len(passwords): - password = new_password - child.sendline("password") - new_password = passwords.pop() - child = set_new_password_and_verify(child, password, new_password) - - except Exception: - logger.exception("man idek anymore, file a bug") diff --git a/user.nix b/user.nix new file mode 100644 index 0000000..c609152 --- /dev/null +++ b/user.nix @@ -0,0 +1,44 @@ +# User config definitions +{ config, pkgs, lib, ... }: +{ + + options = { + calliope = { + hostname = lib.mkOption { + type = string; + default = "calliope"; + + }; + ipv4Address = lib.mkOption { + type = string; + }; + # TODO: + password = lib.mkOption {}; + cec = lib.mkOption { + type = string; + username = lib.mkOption { + type = string; + # TODO: make this default to CEC + }; + defaultShell = mkPackageOption pkgs "shell" { + default = [ "bash" ]; + }; + }; + # TODO: + authorizedKeys = lib.mkOption {}; + + # TODO: + sshIdentities = lib.mkOption {}; + } + config = { + networking.hostName = options.calliope.hostname; + # TODO: set the ipv4 address, and figure out how to set this without knowing interface name + # TODO: set default gateway + # TODO: use CEC to set up git identity + # TODO: set default shell + # TODO: set authorized_keys + # TODO: set SSH Private keys + + }; +} +