Merge pull request #56 from KasperskyLab/main

Update dev branch
This commit is contained in:
Félix Aimé 2021-02-26 12:13:27 +01:00 committed by GitHub
commit 92b89b78cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 411 additions and 127 deletions

View File

@ -40,15 +40,6 @@ Once installed, you can connect yourself to the TinyCheck backend by browsing th
The backend allows you to edit the configuration of TinyCheck, add extended IOCs and whitelisted elements in order to prevent false positives. Several IOCs are already provided such as few suricata rules, FreeDNS, Name servers, CIDRs known to host malicious servers and so on.
### Questions & Answers
**Your project seem very cool, does it send data to Kaspersky or any telemetry server?**<br /><br />
No, at all. You can look to the sources, the only data sent by TinyCheck is an HTTP GET request to a website that you can specify in the config, as well as the watchers URLs. Kaspersky don't - and will not - receive any telemetry from your TinyCheck device.<br /><br />
**Can you list some hardware which can be used with this project (touch screen, wifi dongle etc.)?**<br /><br />
Unfortunately, we prefer to not promote any hardware/constructor/website on this page. Do not hesitate to contact us if you want specific references. <br /><br />
**I'm not very confortable with the concept of "watchers" as the IOCs downloaded are public. Do you plan to develop a server to centralize AMBER/RED IOCs?**<br /><br />
Yes, if the demand is felt by NGOs (contact us!). Is it possible to develop this kind of thing, allowing you to centralize your IOCs and managing your fleet of TinyCheck instances on a server that you host. The server can also embed better detection rules thanks to the telemetry that it will receive from devices.<br />
### Special thanks
**Guys who provided some IOCs**

View File

@ -1806,6 +1806,16 @@
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
"dev": true
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"cacache": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz",
@ -1832,6 +1842,34 @@
"unique-filename": "^1.1.1"
}
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"find-cache-dir": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
@ -1853,6 +1891,25 @@
"path-exists": "^4.0.0"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@ -1917,6 +1974,16 @@
"minipass": "^3.1.1"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"terser-webpack-plugin": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz",
@ -1933,6 +2000,18 @@
"terser": "^4.6.12",
"webpack-sources": "^1.4.3"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.1.2",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz",
"integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
}
}
}
},
@ -11307,87 +11386,6 @@
}
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.1.2",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.1.2.tgz",
"integrity": "sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-router": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.3.tgz",

View File

@ -55,11 +55,19 @@
this.set_lang();
})
.catch(error => { console.log(error) });
},
get_version: function() {
axios.get('/api/update/get-version', { timeout: 60000 })
.then(response => {
if(response.data.status) window.current_version = response.data.current_version
})
.catch(error => { console.log(error) });
}
},
created: function() {
window.config = {}
this.get_config();
this.get_version();
}
}
</script>

View File

@ -683,6 +683,18 @@ ul {
opacity: 0.1;
}
.update-icon {
background-image: url("data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9JzMwMHB4JyB3aWR0aD0nMzAwcHgnICBmaWxsPSIjZmY4YjAwIiB4bWxuczp4PSJodHRwOi8vbnMuYWRvYmUuY29tL0V4dGVuc2liaWxpdHkvMS4wLyIgeG1sbnM6aT0iaHR0cDovL25zLmFkb2JlLmNvbS9BZG9iZUlsbHVzdHJhdG9yLzEwLjAvIiB4bWxuczpncmFwaD0iaHR0cDovL25zLmFkb2JlLmNvbS9HcmFwaHMvMS4wLyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMCAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHJlcXVpcmVkRXh0ZW5zaW9ucz0iaHR0cDovL25zLmFkb2JlLmNvbS9BZG9iZUlsbHVzdHJhdG9yLzEwLjAvIiB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIj48L2ZvcmVpZ25PYmplY3Q+PGcgaTpleHRyYW5lb3VzPSJzZWxmIj48Zz48cGF0aCBkPSJNNTI3My4xLDI0MDAuMXYtMmMwLTIuOC01LTQtOS43LTRzLTkuNywxLjMtOS43LDR2MmMwLDEuOCwwLjcsMy42LDIsNC45bDUsNC45YzAuMywwLjMsMC40LDAuNiwwLjQsMXY2LjQgICAgIGMwLDAuNCwwLjIsMC43LDAuNiwwLjhsMi45LDAuOWMwLjUsMC4xLDEtMC4yLDEtMC44di03LjJjMC0wLjQsMC4yLTAuNywwLjQtMWw1LjEtNUM1MjcyLjQsMjQwMy43LDUyNzMuMSwyNDAxLjksNTI3My4xLDI0MDAuMXogICAgICBNNTI2My40LDI0MDBjLTQuOCwwLTcuNC0xLjMtNy41LTEuOHYwYzAuMS0wLjUsMi43LTEuOCw3LjUtMS44YzQuOCwwLDcuMywxLjMsNy41LDEuOEM1MjcwLjcsMjM5OC43LDUyNjguMiwyNDAwLDUyNjMuNCwyNDAweiI+PC9wYXRoPjxwYXRoIGQ9Ik01MjY4LjQsMjQxMC4zYy0wLjYsMC0xLDAuNC0xLDFjMCwwLjYsMC40LDEsMSwxaDQuM2MwLjYsMCwxLTAuNCwxLTFjMC0wLjYtMC40LTEtMS0xSDUyNjguNHoiPjwvcGF0aD48cGF0aCBkPSJNNTI3Mi43LDI0MTMuN2gtNC4zYy0wLjYsMC0xLDAuNC0xLDFjMCwwLjYsMC40LDEsMSwxaDQuM2MwLjYsMCwxLTAuNCwxLTFDNTI3My43LDI0MTQuMSw1MjczLjMsMjQxMy43LDUyNzIuNywyNDEzLjd6Ij48L3BhdGg+PHBhdGggZD0iTTUyNzIuNywyNDE3aC00LjNjLTAuNiwwLTEsMC40LTEsMWMwLDAuNiwwLjQsMSwxLDFoNC4zYzAuNiwwLDEtMC40LDEtMUM1MjczLjcsMjQxNy41LDUyNzMuMywyNDE3LDUyNzIuNywyNDE3eiI+PC9wYXRoPjwvZz48cGF0aCBkPSJNNTAsMi41QzIzLjgsMi41LDIuNSwyMy44LDIuNSw1MGMwLDI2LjIsMjEuMyw0Ny41LDQ3LjUsNDcuNVM5Ny41LDc2LjIsOTcuNSw1MEM5Ny41LDIzLjgsNzYuMiwyLjUsNTAsMi41eiBNNDQuNywyNi4zICAgIGMwLTIuOSwyLjQtNS4zLDUuMy01LjNjMi45LDAsNS4zLDIuNCw1LjMsNS4zdjI2LjVjMCwyLjktMi40LDUuMy01LjMsNS4zYy0yLjksMC01LjMtMi40LTUuMy01LjNWMjYuM3ogTTUwLDc4LjcgICAgYy0zLjgsMC02LjktMy4xLTYuOS02LjlzMy4xLTYuOSw2LjktNi45czYuOSwzLjEsNi45LDYuOVM1My44LDc4LjcsNTAsNzguN3oiPjwvcGF0aD48L2c+PC9zd2l0Y2g+PC9zdmc+");
width: 30px;
height: 30px;
display: block;
margin-right: 10px;
margin-top: 10px;
background-size: cover;
opacity: 0.2;
}
.off-icon:hover {
opacity: 0.3;
cursor:pointer;
@ -691,4 +703,21 @@ ul {
.quit-icon:hover {
opacity: 0.3;
cursor:pointer;
}
.update-icon:hover {
opacity: 0.4;
cursor:pointer;
}
sup {
top: -2em;
font-size: 12px;
left: -0.2em;
color: #CCC;
font-family: 'Lobster';
}
.color-green {
color:#35c435;
}

View File

@ -1,19 +1,22 @@
<template>
<div class="controls">
<i class="off-icon" v-on:click="action('shutdown')" v-if="off_available && off_display"></i>
<i class="quit-icon" v-on:click="action('quit')" v-if="quit_available && quit_display"></i>
<div class="controls" v-if="display">
<i class="off-icon" v-on:click="action('shutdown')" v-if="off_available"></i>
<i class="quit-icon" v-on:click="action('quit')" v-if="quit_available"></i>
<i class="update-icon" v-if="update_available&&update_possible" @click="$router.push({ name: 'update' })"></i>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'Controls',
data: function (){
return {
off_available : false,
off_display : false,
display: true,
update_available: false,
update_possible: false,
quit_available: false,
quit_display : false
off_available: false
}
},
methods: {
@ -25,6 +28,26 @@ export default {
})
.catch(error => { console.log(error) });
},
check_update: function() {
axios.get('/api/update/check', { timeout: 60000 })
.then(response => {
if(response.data.status) {
if(response.data.message == "A new version is available"){
// Allow to show the warning chip.
this.update_available = true
this.update_possible = true
// Pass the versions as "global vars" through window variable.
window.current_version = response.data.current_version
window.next_version = response.data.next_version
}
} else {
this.update_possible = false
}
})
.catch(error => { console.log(error) });
},
load_config: function() {
axios.get(`/api/misc/config`, { timeout: 60000 })
.then(response => {
@ -36,17 +59,16 @@ export default {
},
watch: {
$route (){
if ( ["capture", "report"].includes(this.$router.currentRoute.name) || screen.height != window.innerHeight ){
this.off_display = false;
this.quit_display = false;
if ( ["capture", "report", "update", "loader"].includes(this.$router.currentRoute.name)){
this.display = false;
} else {
this.off_display = (this.off_available)? true : false;
this.quit_display = (this.quit_available)? true : false;
this.display = true;
}
}
},
created: function() {
this.load_config()
},
this.load_config();
this.check_update();
}
}
</script>

View File

@ -78,5 +78,12 @@
"tap_msg": "Podeu tocar la tecla USB per iniciar una nova captura.",
"capture_download": "La descàrrega de la captura començarà ...",
"start_capture_btn": "Inicia una altra captura"
},
"update": {
"tinycheck_needs": "TinyCheck ha d´actualitzar-se a la propera versió",
"please_click": "Feu click al botó de sota per actualitzar",
"the_process": "El procés pot trigar uns minuts, si us plau esperi ...",
"update_finished": "Actualització finalitzada, actualitzant la interfície...",
"update_it": "Actualitzar ara"
}
}

View File

@ -78,5 +78,12 @@
"tap_msg": "You can tap the USB key to start a new capture.",
"capture_download": "The capture download is going to start...",
"start_capture_btn": "Start another capture"
},
"update": {
"tinycheck_needs": "TinyCheck needs to be updated to the next version",
"please_click": "Please click on the button below to update it.",
"the_process": "The process can take few minutes, please wait...",
"update_finished": "Update finished, let's refresh the interface...",
"update_it": "Update it now"
}
}

View File

@ -78,5 +78,12 @@
"tap_msg": "Puede tocar la llave USB para iniciar una nueva captura",
"capture_download": "La descarga de la captura va a comenzar ...",
"start_capture_btn": "Iniciar otra captura"
},
"update": {
"tinycheck_needs": "TinyCheck debe actualizarse a la próxima versión",
"please_click": "Haga click en el botón de abajo para actualizar",
"the_process": "El proceso puede tardar unos minutos, por favor espere ...",
"update_finished": "Actualización finalizada, actualizando la interfaz...",
"update_it": "Actualizar ahora"
}
}

View File

@ -78,5 +78,12 @@
"tap_msg": "Vous pouvez appuyer sur l'animation pour lancer une nouvelle capture.",
"capture_download": "Le téléchargement de la capture va se lancer...",
"start_capture_btn": "Lancer une nouvelle capture"
},
"update": {
"tinycheck_needs": "Une nouvelle mise à jour de TinyCheck est disponible",
"please_click": "Cliquez sur le bouton ci-dessous pour le mettre à jour",
"the_process": "La mise à jour peut prendre plusieurs minutes, merci d'attendre...",
"update_finished": "Mise à jour terminée, vous allez être redirigé...",
"update_it": "Mettre TinyCheck à jour"
}
}

View File

@ -17,6 +17,12 @@ const routes = [
component: () => import('../views/home.vue'),
props: true
},
{
path: '/update',
name: 'update',
component: () => import('../views/update.vue'),
props: true
},
{
path: '/wifi-select',
name: 'wifi-select',

View File

@ -25,8 +25,7 @@ export default {
question: true,
running: false,
check_alerts: false,
long_waiting: false,
translation: {}
long_waiting: false
}
},
props: {

View File

@ -29,8 +29,7 @@ export default {
loading: false,
stats_interval: false,
chrono_interval: false,
sparklines: false,
translation: {}
sparklines: false
}
},
props: {

View File

@ -55,8 +55,7 @@ export default {
interval: false,
error: false,
reboot_option: window.config.reboot_option,
attempts: 3,
translation: {}
attempts: 3
}
},
methods: {

View File

@ -1,6 +1,6 @@
<template>
<div class="center">
<h3 class="lobster">{{ $t("home.welcome_msg") }}</h3>
<h3 class="lobster">{{ $t("home.welcome_msg") }}<sup>{{current_version}}</sup></h3>
<p>{{ $t("home.help_msg") }}</p>
<button class="btn btn-primary" v-on:click="next()">{{ $t("home.start_btn") }}</button>
</div>
@ -14,7 +14,7 @@ export default {
props: { saved_ssid: String, list_ssids: Array, internet: Boolean },
data() {
return {
translation: {},
current_version:""
}
},
methods: {
@ -31,6 +31,10 @@ export default {
internet: internet } });
}
}
},
created: function() {
if ('current_version' in window)
this.current_version = window.current_version
}
}
</script>

View File

@ -99,8 +99,7 @@ export default {
name: 'report',
data() {
return {
results: true,
translation: {}
results: true
}
},
props: {

View File

@ -144,8 +144,7 @@ export default {
usb: false,
saved: false,
save_usb: false,
init: false,
translation: {}
init: false
}
},
props: {

View File

@ -20,7 +20,7 @@
},
methods: {
internet_check: function() {
axios.get('/api/network/status', { timeout: 10000 })
axios.get('/api/network/status', { timeout: 30000 })
.then(response => {
if (response.data.internet) this.internet = true
if (window.config.iface_out.charAt(0) == 'e') {
@ -32,7 +32,7 @@
.catch(err => (console.log(err)))
},
get_wifi_networks: function() {
axios.get('/api/network/wifi/list', { timeout: 10000 })
axios.get('/api/network/wifi/list', { timeout: 30000 })
.then(response => {
this.list_ssids = response.data.networks
this.goto_home();

View File

@ -0,0 +1,68 @@
<template>
<div class="center">
<p><strong>{{ $t("update.tinycheck_needs") }} ({{next_version}}).</strong><br />
<span v-if="!update_launched">{{ $t("update.please_click") }}</span>
<span v-if="update_launched&&!update_finished">{{ $t("update.the_process") }}</span>
<span v-if="update_launched&&update_finished" class="color-green"> {{ $t("update.update_finished") }}</span>
</p>
<button class="btn btn-primary" :class="[ update_launched ? 'loading' : '' ]" v-on:click="launch_update()" v-if="!update_finished">{{ $t("update.update_it") }}</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'update',
data() {
return {
translation: {},
update_launched: null,
check_interval: null,
next_version: null,
current_version: null,
update_finished: false
}
},
methods: {
check_version: function() {
axios.get('/api/update/get-version', { timeout: 60000 })
.then(response => {
if(response.data.status) {
if(response.data.current_version == window.next_version){
window.current_version = response.data.current_version
this.update_finished = true
clearInterval(this.check_interval);
setTimeout(function () { window.location.href = "/"; }, 10000)
}
}
})
.catch(error => { console.log(error) });
},
launch_update: function() {
axios.get(`/api/update/process`, { timeout: 60000 })
.then(response => {
if(response.data.status) {
if(response.data.message == "Update successfully launched"){
this.update_launched = true
this.check_interval = setInterval(function(){ this.check_version(); }.bind(this), 3000);
}
}
})
.catch(error => { console.log(error) });
}
},
created: function() {
if ('next_version' in window && 'current_version' in window){
if (window.current_version != window.next_version){
this.next_version = window.next_version
this.current_version = window.current_version
} else {
window.location.href = "/";
}
} else {
window.location.href = "/";
}
}
}
</script>

View File

@ -72,8 +72,7 @@ export default {
virtual_keyboard: window.config.virtual_keyboard,
have_internet: false,
enter_creds: false,
refreshing: false,
translation: {}
refreshing: false
}
},
props: {

File diff suppressed because one or more lines are too long

View File

@ -50,7 +50,8 @@ frontend:
sparklines: true
virtual_keyboard: true
user_lang: userlang
update: updateoption
# NETWORK -
# Some elements related to the network configuration, such as
# the interfaces (updated during the install), the list of SSIDs

View File

@ -97,6 +97,19 @@ set_kioskmode() {
fi
}
set_update() {
echo -n "[?] Do you want to be able to update TinyCheck from the frontend interface? [Yes/No] "
read answer
if [[ "$answer" =~ ^([yY][eE][sS]|[yY])$ ]]
then
sed -i "s/updateoption/true/g" /usr/share/tinycheck/config.yaml
echo -e "\e[92m [✔] You'll be able to update it from the frontend!\e[39m"
else
sed -i "s/updateoption/false/g" /usr/share/tinycheck/config.yaml
echo -e "\e[92m [✔] You'll need to pass by the console script to update TinyCheck.\e[39m"
fi
}
create_directory() {
# Create the TinyCheck directory and move the whole stuff there.
echo -e "[+] Creating TinyCheck folder under /usr/share/"
@ -104,6 +117,10 @@ create_directory() {
cp -Rf ./* /usr/share/tinycheck
}
get_version() {
git tag | tail -n 1 | xargs echo -n > /usr/share/tinycheck/VERSION
}
generate_certificate() {
# Generating SSL certificate for the backend.
echo -e "[+] Generating SSL certificate for the backend"
@ -444,9 +461,11 @@ else
check_operating_system
check_interfaces
create_directory
get_version
set_userlang
set_credentials
set_kioskmode
set_update
check_dependencies
configure_dnsmask
configure_dhcpcd

View File

@ -0,0 +1,25 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from flask import jsonify, Blueprint
from app.classes.update import Update
update_bp = Blueprint("update", __name__)
@update_bp.route("/check", methods=["GET"])
def check():
""" Check the presence of new version """
return jsonify(Update().check_version())
@update_bp.route("/get-version", methods=["GET"])
def get_version():
""" Check the current version """
return jsonify(Update().get_current_version())
@update_bp.route("/process", methods=["GET"])
def process():
""" Check the presence of new version """
return jsonify(Update().update_instance())

View File

@ -0,0 +1,82 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from app.utils import read_config
import subprocess as sp
import requests
import json
import os
import re
class Update(object):
def __init__(self):
self.project_url = "https://api.github.com/repos/KasperskyLab/TinyCheck/tags"
self.app_path = "/usr/share/tinycheck"
return None
def check_version(self):
"""
Check if a new version of TinyCheck is available
by quering the Github api and comparing the last
tag inside the VERSION file.
:return: dict containing the available versions.
"""
if read_config(("frontend", "update")):
try:
res = requests.get(self.project_url)
res = json.loads(res.content.decode("utf8"))
with open(os.path.join(self.app_path, "VERSION")) as f:
cv = f.read()
if cv != res[0]["name"]:
return {"status": True,
"message": "A new version is available",
"current_version": cv,
"next_version": res[0]["name"]}
else:
return {"status": True,
"message": "This is the latest version",
"current_version": cv}
except:
return {"status": False,
"message": "Something went wrong (no API access nor version file)"}
else:
return {"status": False,
"message": "You don't have rights to do this operation."}
def get_current_version(self):
"""
Get the current version of the TinyCheck instance
:return: dict containing the current version or error.
"""
if read_config(("frontend", "update")):
try:
with open(os.path.join(self.app_path, "VERSION")) as f:
return {"status": True,
"current_version": f.read()}
except:
return {"status": False,
"message": "Something went wrong - no version file ?"}
else:
return {"status": False,
"message": "You don't have rights to do this operation."}
def update_instance(self):
"""
Update the instance by executing the update script.
:return: dict containing the update status.
"""
if read_config(("frontend", "update")):
try:
os.chdir(self.app_path)
sp.Popen(["bash", os.path.join(self.app_path, "update.sh")])
return {"status": True,
"message": "Update successfully launched"}
except:
return {"status": False,
"message": "Issue during the update"}
else:
return {"status": False,
"message": "You don't have rights to do this operation."}

View File

@ -8,6 +8,7 @@ from app.blueprints.device import device_bp
from app.blueprints.analysis import analysis_bp
from app.blueprints.save import save_bp
from app.blueprints.misc import misc_bp
from app.blueprints.update import update_bp
from app.utils import read_config
app = Flask(__name__, template_folder="../../app/frontend/dist")
@ -42,6 +43,7 @@ app.register_blueprint(device_bp, url_prefix='/api/device')
app.register_blueprint(analysis_bp, url_prefix='/api/analysis')
app.register_blueprint(save_bp, url_prefix='/api/save')
app.register_blueprint(misc_bp, url_prefix='/api/misc')
app.register_blueprint(update_bp, url_prefix='/api/update')
if __name__ == '__main__':
if read_config(("frontend", "remote_access")):

View File

@ -40,12 +40,7 @@ elif [ $PWD = "/tmp/tinycheck" ]; then
cd /usr/share/tinycheck/app/frontend/ && npm install && npm run build
cd /usr/share/tinycheck/app/backend/ && npm install && npm run build
echo "[+] Restarting services"
service tinycheck-backend restart
service tinycheck-frontend restart
service tinycheck-watchers restart
# Updating configuration with new values.
echo "[+] Updating current configuration with new values."
if ! grep -q reboot_option /usr/share/tinycheck/config.yaml; then
sed -i 's/frontend:/frontend:\n reboot_option: true/g' /usr/share/tinycheck/config.yaml
fi
@ -66,9 +61,21 @@ elif [ $PWD = "/tmp/tinycheck" ]; then
sed -i 's/analysis:/analysis:\n active: true/g' /usr/share/tinycheck/config.yaml
fi
if ! grep -q update /usr/share/tinycheck/config.yaml; then
sed -i 's/frontend:/frontend:\n update: true/g' /usr/share/tinycheck/config.yaml
fi
if ! grep -q "CN=R3,O=Let's Encrypt,C=US" /usr/share/tinycheck/config.yaml; then
sed -i "s/free_issuers:/free_issuers:\n - CN=R3,O=Let's Encrypt,C=US/g" /usr/share/tinycheck/config.yaml
fi
echo "[+] Restarting services"
service tinycheck-backend restart
service tinycheck-frontend restart
service tinycheck-watchers restart
echo "[+] Updating the TinyCheck version"
cd /tmp/tinycheck && git tag | tail -n 1 | xargs echo -n > /usr/share/tinycheck/VERSION
echo "[+] TinyCheck updated!"
fi