From 112e14f81735b0e295f94d285ed60d28eac1205a Mon Sep 17 00:00:00 2001 From: PatrickRL <121479313+PatrickRL@users.noreply.github.com> Date: Thu, 16 May 2024 10:54:28 +0200 Subject: [PATCH] FIX: 2FA Setup (#1875) * Update AuthenticationService.js changed authenticationMethods order * UPDATE: change the 2 fa modals input type * fix: auth settings changed authentication methods setting * FIX: 2FA core fixes * ADD: experimental text to 2fa --------- Co-authored-by: mabasian <54101509+mabasian@users.noreply.github.com> Co-authored-by: daverolo <107847185+daverolo@users.noreply.github.com> Co-authored-by: Max Behzadi <69126271+MaxTheGeeek@users.noreply.github.com> --- controls/roles/2fa-enable/.travis.yml | 29 ++ controls/roles/2fa-enable/.yamllint | 33 ++ controls/roles/2fa-enable/tasks/main.yaml | 58 +++ controls/roles/2fa-enable/tests/test.yml | 5 + controls/roles/2fa-remove/.travis.yml | 29 ++ controls/roles/2fa-remove/.yamllint | 33 ++ controls/roles/2fa-remove/tasks/main.yaml | 37 ++ controls/roles/2fa-remove/tests/test.yml | 5 + controls/roles/2fa-setup/.travis.yml | 29 ++ controls/roles/2fa-setup/.yamllint | 33 ++ controls/roles/2fa-setup/tasks/main.yaml | 40 ++ controls/roles/2fa-setup/tests/test.yml | 5 + launcher/public/output.css | 419 ++++-------------- launcher/src/backend/AuthenticationService.js | 59 +-- .../components/modals/ReconnectModal.vue | 2 +- .../components/modals/TwofactorModal.vue | 2 +- .../two-factor-auth/TwoFactorAuth.vue | 14 +- launcher/src/components/base/BaseLayout.vue | 10 +- 18 files changed, 456 insertions(+), 386 deletions(-) create mode 100644 controls/roles/2fa-enable/.travis.yml create mode 100644 controls/roles/2fa-enable/.yamllint create mode 100644 controls/roles/2fa-enable/tasks/main.yaml create mode 100644 controls/roles/2fa-enable/tests/test.yml create mode 100644 controls/roles/2fa-remove/.travis.yml create mode 100644 controls/roles/2fa-remove/.yamllint create mode 100644 controls/roles/2fa-remove/tasks/main.yaml create mode 100644 controls/roles/2fa-remove/tests/test.yml create mode 100644 controls/roles/2fa-setup/.travis.yml create mode 100644 controls/roles/2fa-setup/.yamllint create mode 100644 controls/roles/2fa-setup/tasks/main.yaml create mode 100644 controls/roles/2fa-setup/tests/test.yml diff --git a/controls/roles/2fa-enable/.travis.yml b/controls/roles/2fa-enable/.travis.yml new file mode 100644 index 000000000..49e7e1c5b --- /dev/null +++ b/controls/roles/2fa-enable/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ diff --git a/controls/roles/2fa-enable/.yamllint b/controls/roles/2fa-enable/.yamllint new file mode 100644 index 000000000..882767605 --- /dev/null +++ b/controls/roles/2fa-enable/.yamllint @@ -0,0 +1,33 @@ +--- +# Based on ansible-lint config +extends: default + +rules: + braces: + max-spaces-inside: 1 + level: error + brackets: + max-spaces-inside: 1 + level: error + colons: + max-spaces-after: -1 + level: error + commas: + max-spaces-after: -1 + level: error + comments: disable + comments-indentation: disable + document-start: disable + empty-lines: + max: 3 + level: error + hyphens: + level: error + indentation: disable + key-duplicates: enable + line-length: disable + new-line-at-end-of-file: disable + new-lines: + type: unix + trailing-spaces: disable + truthy: disable diff --git a/controls/roles/2fa-enable/tasks/main.yaml b/controls/roles/2fa-enable/tasks/main.yaml new file mode 100644 index 000000000..93bbf44a3 --- /dev/null +++ b/controls/roles/2fa-enable/tasks/main.yaml @@ -0,0 +1,58 @@ +--- +# Backup and configure SSH for 2FA +- name: Check if /etc/ssh/sshd_config.stereum.bak exists + stat: + path: /etc/ssh/sshd_config.stereum.bak + register: sshd_config_backup + +- name: Check if /etc/pam.d/sshd.stereum.bak exists + stat: + path: /etc/pam.d/sshd.stereum.bak + register: pam_sshd_backup + +- name: Backup sshd_config if not already backed up + copy: + src: /etc/ssh/sshd_config + dest: /etc/ssh/sshd_config.stereum.bak + remote_src: yes + when: not sshd_config_backup.stat.exists + +- name: Backup pam-sshd if not already backed up + copy: + src: /etc/pam.d/sshd + dest: /etc/pam.d/sshd.stereum.bak + remote_src: yes + when: not pam_sshd_backup.stat.exists + +- name: Comment out KbdInteractiveAuthentication in sshd_config + lineinfile: + path: /etc/ssh/sshd_config + regexp: "^KbdInteractiveAuthentication.*$" + line: '# \0' + state: present + +- name: Add 2FA setup to sshd_config + blockinfile: + path: /etc/ssh/sshd_config + marker: "# {mark} 2FA-Setup" + block: | + KbdInteractiveAuthentication yes + AuthenticationMethods publickey,keyboard-interactive password,keyboard-interactive + +- name: Comment out @include common-auth in pam-sshd + lineinfile: + path: /etc/pam.d/sshd + regexp: "^@include common-auth$" + line: "# @include common-auth" + state: present + +- name: Add Google Authenticator configuration to pam-sshd + lineinfile: + path: /etc/pam.d/sshd + line: "auth required pam_google_authenticator.so grace_period=43200" + insertafter: EOF + +- name: Restart SSH service + systemd: + name: sshd + state: restarted diff --git a/controls/roles/2fa-enable/tests/test.yml b/controls/roles/2fa-enable/tests/test.yml new file mode 100644 index 000000000..4f2212498 --- /dev/null +++ b/controls/roles/2fa-enable/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - 2fa-enable diff --git a/controls/roles/2fa-remove/.travis.yml b/controls/roles/2fa-remove/.travis.yml new file mode 100644 index 000000000..49e7e1c5b --- /dev/null +++ b/controls/roles/2fa-remove/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ diff --git a/controls/roles/2fa-remove/.yamllint b/controls/roles/2fa-remove/.yamllint new file mode 100644 index 000000000..882767605 --- /dev/null +++ b/controls/roles/2fa-remove/.yamllint @@ -0,0 +1,33 @@ +--- +# Based on ansible-lint config +extends: default + +rules: + braces: + max-spaces-inside: 1 + level: error + brackets: + max-spaces-inside: 1 + level: error + colons: + max-spaces-after: -1 + level: error + commas: + max-spaces-after: -1 + level: error + comments: disable + comments-indentation: disable + document-start: disable + empty-lines: + max: 3 + level: error + hyphens: + level: error + indentation: disable + key-duplicates: enable + line-length: disable + new-line-at-end-of-file: disable + new-lines: + type: unix + trailing-spaces: disable + truthy: disable diff --git a/controls/roles/2fa-remove/tasks/main.yaml b/controls/roles/2fa-remove/tasks/main.yaml new file mode 100644 index 000000000..0cc7b0847 --- /dev/null +++ b/controls/roles/2fa-remove/tasks/main.yaml @@ -0,0 +1,37 @@ +--- +# Restore SSH and PAM configurations and clean up Google Authenticator +- name: Restore sshd_config from backup + copy: + src: /etc/ssh/sshd_config.stereum.bak + dest: /etc/ssh/sshd_config + remote_src: yes + +- name: Restore pam-sshd from backup + copy: + src: /etc/pam.d/sshd.stereum.bak + dest: /etc/pam.d/sshd + remote_src: yes + +- name: Remove Google Authenticator configuration file from {{ myuser }} + file: + path: "/home/{{ myuser }}/.google_authenticator" + state: absent + ignore_errors: yes + +- name: Remove Google Authenticator configuration file from root + file: + path: "/{{ myuser }}/.google_authenticator" + state: absent + when: myuser == "root" + ignore_errors: yes + +- name: Remove google-authenticator-libpam directory + file: + path: /root/google-authenticator-libpam + state: absent + ignore_errors: yes + +- name: Restart SSH service + systemd: + name: sshd + state: restarted diff --git a/controls/roles/2fa-remove/tests/test.yml b/controls/roles/2fa-remove/tests/test.yml new file mode 100644 index 000000000..8f537dfde --- /dev/null +++ b/controls/roles/2fa-remove/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - 2fa-remove diff --git a/controls/roles/2fa-setup/.travis.yml b/controls/roles/2fa-setup/.travis.yml new file mode 100644 index 000000000..49e7e1c5b --- /dev/null +++ b/controls/roles/2fa-setup/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ diff --git a/controls/roles/2fa-setup/.yamllint b/controls/roles/2fa-setup/.yamllint new file mode 100644 index 000000000..882767605 --- /dev/null +++ b/controls/roles/2fa-setup/.yamllint @@ -0,0 +1,33 @@ +--- +# Based on ansible-lint config +extends: default + +rules: + braces: + max-spaces-inside: 1 + level: error + brackets: + max-spaces-inside: 1 + level: error + colons: + max-spaces-after: -1 + level: error + commas: + max-spaces-after: -1 + level: error + comments: disable + comments-indentation: disable + document-start: disable + empty-lines: + max: 3 + level: error + hyphens: + level: error + indentation: disable + key-duplicates: enable + line-length: disable + new-line-at-end-of-file: disable + new-lines: + type: unix + trailing-spaces: disable + truthy: disable diff --git a/controls/roles/2fa-setup/tasks/main.yaml b/controls/roles/2fa-setup/tasks/main.yaml new file mode 100644 index 000000000..98222589b --- /dev/null +++ b/controls/roles/2fa-setup/tasks/main.yaml @@ -0,0 +1,40 @@ +--- +# Install Google Authenticator PAM module +- name: Update apt package index + apt: + update_cache: yes + +- name: Install required packages + apt: + name: + - libqrencode-dev + - libtool + - libpam-dev + - autoconf + - make + state: present + +- name: Clone google-authenticator-libpam repository + git: + repo: https://github.com/google/google-authenticator-libpam.git + dest: /root/google-authenticator-libpam + update: no + +- name: Run bootstrap.sh + command: ./bootstrap.sh + args: + chdir: /root/google-authenticator-libpam + +- name: Run configure with libdir + command: ./configure --libdir=/lib/x86_64-linux-gnu + args: + chdir: /root/google-authenticator-libpam + +- name: Compile the google-authenticator-libpam + make: + chdir: /root/google-authenticator-libpam + +- name: Install the google-authenticator-libpam + make: + target: install + chdir: /root/google-authenticator-libpam diff --git a/controls/roles/2fa-setup/tests/test.yml b/controls/roles/2fa-setup/tests/test.yml new file mode 100644 index 000000000..7639e6a24 --- /dev/null +++ b/controls/roles/2fa-setup/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - 2fa-setup diff --git a/launcher/public/output.css b/launcher/public/output.css index 548471cd2..5211774d5 100755 --- a/launcher/public/output.css +++ b/launcher/public/output.css @@ -791,6 +791,10 @@ video { right: -1.25rem; } +.-top-1{ + top: -0.25rem; +} + .-top-11{ top: -2.75rem; } @@ -935,14 +939,18 @@ video { right: 1.25rem; } -.right-8{ - right: 2rem; +.right-7{ + right: 1.75rem; } .right-\[10\.5rem\]{ right: 10.5rem; } +.right-\[1px\]{ + right: 1px; +} + .right-\[5px\]{ right: 5px; } @@ -983,10 +991,6 @@ video { top: 2rem; } -.top-9{ - top: 2.25rem; -} - .top-\[-18px\]{ top: -18px; } @@ -995,26 +999,6 @@ video { top: 7rem; } -.-top-1{ - top: -0.25rem; -} - -.right-7{ - right: 1.75rem; -} - -.right-\[\]{ - right: ; -} - -.right-\[2px\]{ - right: 2px; -} - -.right-\[1px\]{ - right: 1px; -} - .z-0{ z-index: 0; } @@ -1287,14 +1271,14 @@ video { grid-row: span 6 / span 6; } -.row-span-full{ - grid-row: 1 / -1; -} - .row-span-8{ grid-row: span 8 / span 8; } +.row-span-full{ + grid-row: 1 / -1; +} + .row-start-1{ grid-row-start: 1; } @@ -1311,8 +1295,8 @@ video { grid-row-start: 12; } -.row-start-14{ - grid-row-start: 14; +.row-start-13{ + grid-row-start: 13; } .row-start-2{ @@ -1347,10 +1331,6 @@ video { grid-row-start: 9; } -.row-start-13{ - grid-row-start: 13; -} - .row-end-10{ grid-row-end: 10; } @@ -1367,10 +1347,6 @@ video { grid-row-end: 13; } -.row-end-14{ - grid-row-end: 14; -} - .row-end-2{ grid-row-end: 2; } @@ -1399,10 +1375,6 @@ video { grid-row-end: 8; } -.row-end-9{ - grid-row-end: 9; -} - .float-right{ float: right; } @@ -1455,10 +1427,6 @@ video { margin-bottom: 0.5rem; } -.mb-3{ - margin-bottom: 0.75rem; -} - .mb-\[1px\]{ margin-bottom: 1px; } @@ -1527,10 +1495,6 @@ video { margin-top: 2.5rem; } -.mt-12{ - margin-top: 3rem; -} - .mt-2{ margin-top: 0.5rem; } @@ -1608,6 +1572,10 @@ video { display: none; } +.h-1\/2{ + height: 50%; +} + .h-1\/3{ height: 33.333333%; } @@ -1668,6 +1636,10 @@ video { height: 1.25rem; } +.h-5\/6{ + height: 83.333333%; +} + .h-6{ height: 1.5rem; } @@ -1696,10 +1668,6 @@ video { height: 110px; } -.h-\[120px\]{ - height: 120px; -} - .h-\[150px\]{ height: 150px; } @@ -1740,10 +1708,6 @@ video { height: 25px; } -.h-\[27px\]{ - height: 27px; -} - .h-\[280px\]{ height: 280px; } @@ -1812,6 +1776,10 @@ video { height: 90px; } +.h-\[95\%\]{ + height: 95%; +} + .h-fit{ height: -webkit-fit-content; height: -moz-fit-content; @@ -1826,18 +1794,6 @@ video { height: 100vh; } -.h-1\/2{ - height: 50%; -} - -.h-5\/6{ - height: 83.333333%; -} - -.h-\[95\%\]{ - height: 95%; -} - .max-h-10{ max-height: 2.5rem; } @@ -1970,10 +1926,6 @@ video { max-height: 503px; } -.max-h-\[60px\]{ - max-height: 60px; -} - .max-h-\[78px\]{ max-height: 78px; } @@ -1986,10 +1938,6 @@ video { min-height: 2.75rem; } -.min-h-20{ - min-height: 5rem; -} - .min-h-7{ min-height: 1.75rem; } @@ -2122,18 +2070,6 @@ video { width: 66.666667%; } -.w-40{ - width: 10rem; -} - -.w-44{ - width: 11rem; -} - -.w-48{ - width: 12rem; -} - .w-5{ width: 1.25rem; } @@ -2190,10 +2126,6 @@ video { width: 120px; } -.w-\[130px\]{ - width: 130px; -} - .w-\[150px\]{ width: 150px; } @@ -2238,10 +2170,6 @@ video { width: 25px; } -.w-\[27px\]{ - width: 27px; -} - .w-\[30\%\]{ width: 30%; } @@ -2254,6 +2182,10 @@ video { width: 390px; } +.w-\[40\%\]{ + width: 40%; +} + .w-\[400px\]{ width: 400px; } @@ -2312,10 +2244,6 @@ video { width: 100vw; } -.w-\[40\%\]{ - width: 40%; -} - .min-w-\[100px\]{ min-width: 100px; } @@ -2332,10 +2260,6 @@ video { min-width: 50px; } -.max-w-10{ - max-width: 2.5rem; -} - .max-w-\[180px\]{ max-width: 180px; } @@ -2387,36 +2311,18 @@ video { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.-translate-y-1\/2{ - --tw-translate-y: -50%; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - .translate-x-8{ --tw-translate-x: 2rem; -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.translate-y-0{ - --tw-translate-y: 0px; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - .-rotate-90{ --tw-rotate: -90deg; -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.rotate-0{ - --tw-rotate: 0deg; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - .rotate-180{ --tw-rotate: 180deg; -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -2464,18 +2370,6 @@ video { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.scale-y-0{ - --tw-scale-y: 0; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - -.scale-y-100{ - --tw-scale-y: 1; - -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); -} - .transform{ -webkit-transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -2580,10 +2474,6 @@ video { grid-auto-flow: row; } -.auto-rows-fr{ - grid-auto-rows: minmax(0, 1fr); -} - .auto-rows-max{ grid-auto-rows: -webkit-max-content; grid-auto-rows: max-content; @@ -2657,6 +2547,10 @@ video { grid-template-rows: repeat(12 , minmax(0,1fr)); } +.grid-rows-14{ + grid-template-rows: repeat(14 , minmax(0,1fr)); +} + .grid-rows-15{ grid-template-rows: repeat(15 , minmax(0,1fr)); } @@ -2689,10 +2583,6 @@ video { grid-template-rows: repeat(8 , minmax(0,1fr)); } -.grid-rows-14{ - grid-template-rows: repeat(14 , minmax(0,1fr)); -} - .flex-col{ -webkit-box-orient: vertical; -webkit-box-direction: normal; @@ -2771,6 +2661,10 @@ video { gap: 0.5rem; } +.gap-3{ + gap: 0.75rem; +} + .gap-4{ gap: 1rem; } @@ -2779,10 +2673,6 @@ video { gap: 1.25rem; } -.gap-3{ - gap: 0.75rem; -} - .gap-x-1{ -webkit-column-gap: 0.25rem; -moz-column-gap: 0.25rem; @@ -3006,6 +2896,10 @@ video { border-radius: 0.25rem; } +.rounded-2xl{ + border-radius: 1rem; +} + .rounded-3xl{ border-radius: 1.5rem; } @@ -3014,18 +2908,10 @@ video { border-radius: 35px; } -.rounded-\[4px\]{ - border-radius: 4px; -} - .rounded-\[55px\]{ border-radius: 55px; } -.rounded-\[5px\]{ - border-radius: 5px; -} - .rounded-\[75px\]{ border-radius: 75px; } @@ -3050,10 +2936,6 @@ video { border-radius: 0.75rem; } -.rounded-2xl{ - border-radius: 1rem; -} - .rounded-b-lg{ border-bottom-right-radius: 0.5rem; border-bottom-left-radius: 0.5rem; @@ -3074,6 +2956,11 @@ video { border-bottom-left-radius: 0.375rem; } +.rounded-l-none{ + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; +} + .rounded-l-xl{ border-top-left-radius: 0.75rem; border-bottom-left-radius: 0.75rem; @@ -3089,11 +2976,6 @@ video { border-bottom-right-radius: 0.375rem; } -.rounded-t-\[0\.28rem\]{ - border-top-left-radius: 0.28rem; - border-top-right-radius: 0.28rem; -} - .rounded-t-\[5px\]{ border-top-left-radius: 5px; border-top-right-radius: 5px; @@ -3109,11 +2991,6 @@ video { border-top-right-radius: 0.375rem; } -.rounded-l-none{ - border-top-left-radius: 0px; - border-bottom-left-radius: 0px; -} - .rounded-bl-\[37px\]{ border-bottom-left-radius: 37px; } @@ -3298,11 +3175,6 @@ video { border-color: rgb(55 65 81 / var(--tw-border-opacity)); } -.border-gray-800{ - --tw-border-opacity: 1; - border-color: rgb(31 41 55 / var(--tw-border-opacity)); -} - .border-gray-950{ --tw-border-opacity: 1; border-color: rgb(3 7 18 / var(--tw-border-opacity)); @@ -3430,16 +3302,6 @@ video { border-top-color: rgb(255 255 255 / var(--tw-border-opacity)); } -.border-r-blue-500{ - --tw-border-opacity: 1; - border-right-color: rgb(59 130 246 / var(--tw-border-opacity)); -} - -.border-t-blue-500{ - --tw-border-opacity: 1; - border-top-color: rgb(59 130 246 / var(--tw-border-opacity)); -} - .bg-\[\#0F1217\]{ --tw-bg-opacity: 1; background-color: rgb(15 18 23 / var(--tw-bg-opacity)); @@ -3530,6 +3392,11 @@ video { background-color: rgb(25 28 33 / var(--tw-bg-opacity)); } +.bg-\[\#1BA5F8\]{ + --tw-bg-opacity: 1; + background-color: rgb(27 165 248 / var(--tw-bg-opacity)); +} + .bg-\[\#1E2429\]{ --tw-bg-opacity: 1; background-color: rgb(30 36 41 / var(--tw-bg-opacity)); @@ -3585,11 +3452,6 @@ video { background-color: rgb(29 31 32 / var(--tw-bg-opacity)); } -.bg-\[\#1d1f21\]{ - --tw-bg-opacity: 1; - background-color: rgb(29 31 33 / var(--tw-bg-opacity)); -} - .bg-\[\#1f2123\]{ --tw-bg-opacity: 1; background-color: rgb(31 33 35 / var(--tw-bg-opacity)); @@ -3635,16 +3497,6 @@ video { background-color: rgb(34 65 65 / var(--tw-bg-opacity)); } -.bg-\[\#232428\]{ - --tw-bg-opacity: 1; - background-color: rgb(35 36 40 / var(--tw-bg-opacity)); -} - -.bg-\[\#232528\]{ - --tw-bg-opacity: 1; - background-color: rgb(35 37 40 / var(--tw-bg-opacity)); -} - .bg-\[\#23272c\]{ --tw-bg-opacity: 1; background-color: rgb(35 39 44 / var(--tw-bg-opacity)); @@ -3685,11 +3537,6 @@ video { background-color: rgb(40 42 44 / var(--tw-bg-opacity)); } -.bg-\[\#292e32\]{ - --tw-bg-opacity: 1; - background-color: rgb(41 46 50 / var(--tw-bg-opacity)); -} - .bg-\[\#2a2e30\]{ --tw-bg-opacity: 1; background-color: rgb(42 46 48 / var(--tw-bg-opacity)); @@ -3740,11 +3587,6 @@ video { background-color: rgb(50 54 58 / var(--tw-bg-opacity)); } -.bg-\[\#333539\]{ - --tw-bg-opacity: 1; - background-color: rgb(51 53 57 / var(--tw-bg-opacity)); -} - .bg-\[\#33393E\]{ --tw-bg-opacity: 1; background-color: rgb(51 57 62 / var(--tw-bg-opacity)); @@ -3775,11 +3617,21 @@ video { background-color: rgb(52 52 52 / var(--tw-bg-opacity)); } +.bg-\[\#38504e\]{ + --tw-bg-opacity: 1; + background-color: rgb(56 80 78 / var(--tw-bg-opacity)); +} + .bg-\[\#387272\]{ --tw-bg-opacity: 1; background-color: rgb(56 114 114 / var(--tw-bg-opacity)); } +.bg-\[\#393939\]{ + --tw-bg-opacity: 1; + background-color: rgb(57 57 57 / var(--tw-bg-opacity)); +} + .bg-\[\#3d4244\]{ --tw-bg-opacity: 1; background-color: rgb(61 66 68 / var(--tw-bg-opacity)); @@ -3810,11 +3662,6 @@ video { background-color: rgb(77 117 117 / var(--tw-bg-opacity)); } -.bg-\[\#503C3C\]{ - --tw-bg-opacity: 1; - background-color: rgb(80 60 60 / var(--tw-bg-opacity)); -} - .bg-\[\#505f6d\]{ --tw-bg-opacity: 1; background-color: rgb(80 95 109 / var(--tw-bg-opacity)); @@ -3835,14 +3682,9 @@ video { background-color: rgb(96 152 121 / var(--tw-bg-opacity)); } -.bg-\[\#D1BB9E\]{ - --tw-bg-opacity: 1; - background-color: rgb(209 187 158 / var(--tw-bg-opacity)); -} - -.bg-\[\#F7C566\]{ +.bg-\[\#A0A0A0\]{ --tw-bg-opacity: 1; - background-color: rgb(247 197 102 / var(--tw-bg-opacity)); + background-color: rgb(160 160 160 / var(--tw-bg-opacity)); } .bg-\[\#a7aeb5\]{ @@ -3870,11 +3712,6 @@ video { background-color: rgb(234 236 238 / var(--tw-bg-opacity)); } -.bg-\[\#fb923c\]{ - --tw-bg-opacity: 1; - background-color: rgb(251 146 60 / var(--tw-bg-opacity)); -} - .bg-amber-400{ --tw-bg-opacity: 1; background-color: rgb(251 191 36 / var(--tw-bg-opacity)); @@ -3900,26 +3737,11 @@ video { background-color: rgb(59 130 246 / var(--tw-bg-opacity)); } -.bg-blue-900{ - --tw-bg-opacity: 1; - background-color: rgb(30 58 138 / var(--tw-bg-opacity)); -} - -.bg-cyan-200{ - --tw-bg-opacity: 1; - background-color: rgb(165 243 252 / var(--tw-bg-opacity)); -} - .bg-cyan-300{ --tw-bg-opacity: 1; background-color: rgb(103 232 249 / var(--tw-bg-opacity)); } -.bg-cyan-500{ - --tw-bg-opacity: 1; - background-color: rgb(6 182 212 / var(--tw-bg-opacity)); -} - .bg-gray-100{ --tw-bg-opacity: 1; background-color: rgb(243 244 246 / var(--tw-bg-opacity)); @@ -3990,11 +3812,6 @@ video { background-color: rgb(22 101 52 / var(--tw-bg-opacity)); } -.bg-lime-900{ - --tw-bg-opacity: 1; - background-color: rgb(54 83 20 / var(--tw-bg-opacity)); -} - .bg-orange-500{ --tw-bg-opacity: 1; background-color: rgb(249 115 22 / var(--tw-bg-opacity)); @@ -4005,11 +3822,6 @@ video { background-color: rgb(254 226 226 / var(--tw-bg-opacity)); } -.bg-red-300{ - --tw-bg-opacity: 1; - background-color: rgb(252 165 165 / var(--tw-bg-opacity)); -} - .bg-red-500{ --tw-bg-opacity: 1; background-color: rgb(239 68 68 / var(--tw-bg-opacity)); @@ -4064,46 +3876,11 @@ video { background-color: transparent; } -.bg-violet-500{ - --tw-bg-opacity: 1; - background-color: rgb(139 92 246 / var(--tw-bg-opacity)); -} - -.bg-violet-900{ - --tw-bg-opacity: 1; - background-color: rgb(76 29 149 / var(--tw-bg-opacity)); -} - .bg-white{ --tw-bg-opacity: 1; background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-zinc-700{ - --tw-bg-opacity: 1; - background-color: rgb(63 63 70 / var(--tw-bg-opacity)); -} - -.bg-\[\#38504e\]{ - --tw-bg-opacity: 1; - background-color: rgb(56 80 78 / var(--tw-bg-opacity)); -} - -.bg-\[\#1BA5F8\]{ - --tw-bg-opacity: 1; - background-color: rgb(27 165 248 / var(--tw-bg-opacity)); -} - -.bg-\[\#393939\]{ - --tw-bg-opacity: 1; - background-color: rgb(57 57 57 / var(--tw-bg-opacity)); -} - -.bg-\[\#A0A0A0\]{ - --tw-bg-opacity: 1; - background-color: rgb(160 160 160 / var(--tw-bg-opacity)); -} - .bg-opacity-80{ --tw-bg-opacity: 0.8; } @@ -4338,6 +4115,10 @@ video { padding-top: 0.25rem; } +.pt-2{ + padding-top: 0.5rem; +} + .pt-20{ padding-top: 5rem; } @@ -4354,10 +4135,6 @@ video { padding-top: 2rem; } -.pt-2{ - padding-top: 0.5rem; -} - .text-left{ text-align: left; } @@ -4466,14 +4243,6 @@ video { line-height: 1rem; } -.font-\[400\]{ - font-weight: 400; -} - -.font-\[500\]{ - font-weight: 500; -} - .font-bold{ font-weight: 700; } @@ -4498,6 +4267,10 @@ video { text-transform: capitalize; } +.leading-5{ + line-height: 1.25rem; +} + .leading-6{ line-height: 1.5rem; } @@ -4510,10 +4283,6 @@ video { line-height: 1.25; } -.leading-5{ - line-height: 1.25rem; -} - .tracking-wide{ letter-spacing: 0.025em; } @@ -4547,6 +4316,11 @@ video { color: rgb(230 228 228 / var(--tw-text-opacity)); } +.text-\[greenyellow\]{ + --tw-text-opacity: 1; + color: rgb(173 255 47 / var(--tw-text-opacity)); +} + .text-amber-200{ --tw-text-opacity: 1; color: rgb(253 230 138 / var(--tw-text-opacity)); @@ -4717,11 +4491,6 @@ video { color: rgb(234 179 8 / var(--tw-text-opacity)); } -.text-\[greenyellow\]{ - --tw-text-opacity: 1; - color: rgb(173 255 47 / var(--tw-text-opacity)); -} - .placeholder-gray-400\/70::-webkit-input-placeholder{ color: rgb(156 163 175 / 0.7); } @@ -4812,10 +4581,6 @@ video { opacity: 0.4; } -.opacity-45{ - opacity: 0.45; -} - .opacity-50{ opacity: 0.5; } @@ -5490,11 +5255,6 @@ html body { border-color: rgb(209 213 219 / var(--tw-border-opacity)); } -.hover\:border-gray-500:hover{ - --tw-border-opacity: 1; - border-color: rgb(107 114 128 / var(--tw-border-opacity)); -} - .hover\:border-gray-600:hover{ --tw-border-opacity: 1; border-color: rgb(75 85 99 / var(--tw-border-opacity)); @@ -5620,11 +5380,6 @@ html body { background-color: rgb(219 234 254 / var(--tw-bg-opacity)); } -.hover\:bg-blue-300:hover{ - --tw-bg-opacity: 1; - background-color: rgb(147 197 253 / var(--tw-bg-opacity)); -} - .hover\:bg-blue-400:hover{ --tw-bg-opacity: 1; background-color: rgb(96 165 250 / var(--tw-bg-opacity)); @@ -5980,22 +5735,6 @@ html body { } } -@media (forced-colors: active){ - .forced-colors\:block{ - display: block; - } - - .forced-colors\:hidden{ - display: none; - } - - .forced-colors\:appearance-auto{ - -webkit-appearance: auto; - -moz-appearance: auto; - appearance: auto; - } -} - .\[\&\:checked_\+_span_svg\[data-checked-icon\]\]\:block:checked + span svg[data-checked-icon]{ display: block; } diff --git a/launcher/src/backend/AuthenticationService.js b/launcher/src/backend/AuthenticationService.js index 5ec3f9a92..aecb45aa9 100644 --- a/launcher/src/backend/AuthenticationService.js +++ b/launcher/src/backend/AuthenticationService.js @@ -15,21 +15,12 @@ export class AuthenticationService { let sendKey = false; let validCode = false; - await this.nodeConnection.sshService.exec("apt update"); - await this.nodeConnection.sshService.exec("apt install libqrencode-dev -y"); - await this.nodeConnection.sshService.exec("apt install libtool -y"); - await this.nodeConnection.sshService.exec("apt install libpam-dev -y"); - await this.nodeConnection.sshService.exec("apt install autoconf -y"); - await this.nodeConnection.sshService.exec("apt install make -y"); - await this.nodeConnection.sshService.exec( - "cd /root && git clone https://github.com/google/google-authenticator-libpam.git" - ); - await this.nodeConnection.sshService.exec("cd /root/google-authenticator-libpam && ./bootstrap.sh"); - await this.nodeConnection.sshService.exec( - "cd /root/google-authenticator-libpam && ./configure --libdir=/lib/x86_64-linux-gnu" - ); - await this.nodeConnection.sshService.exec("cd /root/google-authenticator-libpam && make && make install"); + // Setup Google Authenticator PAM module + await this.nodeConnection.runPlaybook("2FA Setup", { + stereum_role: "2fa-setup", + }); + // Start 2FA user setup with google-authenticator const conn = this.nodeConnection.sshService.getConnectionFromPool(); conn.shell((err, stream) => { if (err) throw err; @@ -142,39 +133,27 @@ export class AuthenticationService { } else { this.authStream.write("n\n"); } - - await this.nodeConnection.sshService.exec( - `sed -i 's/^KbdInteractiveAuthentication[ ]no$/KbdInteractiveAuthentication yes/g' /etc/ssh/sshd_config` - ); - await this.nodeConnection.sshService.exec( - `echo "AuthenticationMethods publickey,password publickey,keyboard-interactive" >> /etc/ssh/sshd_config` - ); - await this.nodeConnection.sshService.exec( - `echo 'auth required pam_google_authenticator.so grace_period=43200' >> /etc/pam.d/sshd` - ); - await this.nodeConnection.sshService.exec(`sed -i '/^@include common-auth$/s/^/#/' /etc/pam.d/sshd`); - await this.nodeConnection.sshService.exec("systemctl restart sshd.service"); + // Enable 2FA configs and restart SSH server + await this.nodeConnection.runPlaybook("Enable 2FA", { + stereum_role: "2fa-enable", + }); this.authStream.end(); } async removeAuthenticator() { - await this.nodeConnection.sshService.exec( - `sed -i '/AuthenticationMethods publickey,password publickey,keyboard-interactive/d' /etc/ssh/sshd_config` - ); - await this.nodeConnection.sshService.exec( - `sed -i '/auth required pam_google_authenticator.so grace_period=86400/d' /etc/pam.d/sshd` - ); - await this.nodeConnection.sshService.exec("rm ~/.google_authenticator", true, false); - await this.nodeConnection.sshService.exec("cd /root && rm -rf google-authenticator-libpam"); - await this.nodeConnection.sshService.exec("apt remove libtool -y"); - await this.nodeConnection.sshService.exec("apt remove libpam-dev -y"); - await this.nodeConnection.sshService.exec("apt remove autoconf -y"); - await this.nodeConnection.sshService.exec("apt remove make -y"); - await this.nodeConnection.sshService.exec("systemctl restart sshd.service"); + let resultuser = await this.nodeConnection.sshService.exec(`whoami`, false); + if (resultuser.rc == 0) { + let user = resultuser.stdout.trim(); + let result = await this.nodeConnection.runPlaybook("Remove 2FA", { + stereum_role: "2fa-remove", + myuser: user, + }); + console.log(result); + } } async checkForAuthenticator() { - let result = await this.nodeConnection.sshService.exec(`test -a ~/.google_authenticator`, true, false); + let result = await this.nodeConnection.sshService.exec(`test -a ~/.google_authenticator`, false); if (result.rc == 0) { return true; } else { diff --git a/launcher/src/components/UI/base-header/components/modals/ReconnectModal.vue b/launcher/src/components/UI/base-header/components/modals/ReconnectModal.vue index f757226a9..d69b77624 100644 --- a/launcher/src/components/UI/base-header/components/modals/ReconnectModal.vue +++ b/launcher/src/components/UI/base-header/components/modals/ReconnectModal.vue @@ -1,5 +1,5 @@ diff --git a/launcher/src/components/UI/server-management/components/two-factor-auth/TwoFactorAuth.vue b/launcher/src/components/UI/server-management/components/two-factor-auth/TwoFactorAuth.vue index 01009a56f..1d3a319d8 100644 --- a/launcher/src/components/UI/server-management/components/two-factor-auth/TwoFactorAuth.vue +++ b/launcher/src/components/UI/server-management/components/two-factor-auth/TwoFactorAuth.vue @@ -5,10 +5,22 @@ {{ titleManager }} +
+

EXPERIMENTAL!

+ Before using note: + - Use at your own risk + - Have an SSH session + - Have a backup + - Have a snapshot of your VM +
+ { serverStore.connectingAnimActive = false; headerStore.refresh = false; serverStore.isTerminalStopped = true; - await ControlService.stopShell(); - await ControlService.logout(); + try { + await ControlService.stopShell(); + await ControlService.logout(); + } catch (e) {} router.push("/login").then(() => { location.reload(); }); @@ -152,7 +154,9 @@ const loggingOut = async () => { const reconnect = async () => { headerStore.reconnecting = true; - await ControlService.reconnect(); + try { + await ControlService.reconnect(); + } catch (e) {} headerStore.reconnecting = false; headerStore.refresh = true; };