diff --git a/api/src/api/views/MediaViews.py b/api/src/api/views/MediaViews.py index 9c5291435f4782277a8ec3219f8e4d1189dbe991..697ae6c3d9913c0a328bbcbce5fb97c63c57429e 100644 --- a/api/src/api/views/MediaViews.py +++ b/api/src/api/views/MediaViews.py @@ -1,4 +1,5 @@ import json +import os import re import time import traceback @@ -67,11 +68,16 @@ def api_v3_admin_media_insert(payload): traceback.format_exc(), ) url = urlparse(data["url"]) - if url.scheme != "https" or not re.compile( - r"^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|" - r"([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|" - r"([a-zA-Z0-9][-_.a-zA-Z0-9]{0,61}[a-zA-Z0-9]))\." - r"([a-zA-Z]{2,13}|[a-zA-Z0-9-]{2,30}.[a-zA-Z]{2,3})$" + allow_unsecured_connections = ( + os.environ.get("ENGINE_ALLOW_UNSECURED_CONNECTIONS", "") == "true" + ) + connection_conditions = ( + ["http", "https"] if allow_unsecured_connections else ["https"] + ) + + if url.scheme not in connection_conditions or not re.compile( + r"^(([a-zA-Z0-9-]{1,63})|(([a-zA-Z0-9][-_.a-zA-Z0-9]{0,61}[a-zA-Z0-9])?\." + r"[a-zA-Z]{2,13}|[a-zA-Z0-9-]{2,30}\.[a-zA-Z]{2,3}))(:[0-9]{1,5})?$" ).match(url.netloc): raise Error( "bad_request", diff --git a/docker-compose-parts/api.yml b/docker-compose-parts/api.yml index 054bff11dd53eca0b675f36e2b189f50bfb66247..81be36c2792249d7c624f4ffeeafa2451109a143 100644 --- a/docker-compose-parts/api.yml +++ b/docker-compose-parts/api.yml @@ -67,4 +67,5 @@ services: AUTHENTICATION_AUTHENTICATION_GOOGLE_ENABLED: BASTION_ENABLED: BASTION_SSH_PORT: - OPERATIONS_API_ENABLED: \ No newline at end of file + OPERATIONS_API_ENABLED: + ENGINE_ALLOW_UNSECURED_CONNECTIONS: diff --git a/docker-compose-parts/engine.yml b/docker-compose-parts/engine.yml index c947a0858ce160e8530be1d25b759c891df5e085..ffb6f209ef1706cb03b8e9bb2981b0e39297652a 100644 --- a/docker-compose-parts/engine.yml +++ b/docker-compose-parts/engine.yml @@ -27,6 +27,7 @@ services: API_ISARDVDI_SECRET: DOMAIN: ENGINE_DISK_BALANCER: + ENGINE_ALLOW_UNSECURED_CONNECTIONS: ENGINE_HYPER_BALANCER: GPU_FAKE: LOG_LEVEL: diff --git a/docker-compose-parts/static.devel.yml b/docker-compose-parts/static.devel.yml index 329ceae1564a6b2dbeccadfc76cff496204d538d..63ac780330fb66f3238e91ba00fa19dd012e5784 100644 --- a/docker-compose-parts/static.devel.yml +++ b/docker-compose-parts/static.devel.yml @@ -35,6 +35,7 @@ services: working_dir: /usr/local/src/isard-old-frontend/ environment: CYPRESS_CACHE_FOLDER: /usr/local/src/isard-old-frontend/node_modules/.cache/cypress + VUE_APP_ENGINE_ALLOW_UNSECURED_CONNECTIONS: ${ENGINE_ALLOW_UNSECURED_CONNECTIONS-false} command: sh -c "yarn install && yarn serve" volumes: - ${BUILD_ROOT_PATH}/old-frontend/:/usr/local/src/isard-old-frontend/ diff --git a/docker-compose-parts/webapp.yml b/docker-compose-parts/webapp.yml index 508dea80ec1853ad806fd2d324cf33af30c63311..304ec646309cbea5097e460f2b18e71e478e134f 100644 --- a/docker-compose-parts/webapp.yml +++ b/docker-compose-parts/webapp.yml @@ -22,3 +22,4 @@ services: LOG_LEVEL: GRAFANA_WEBAPP_URL: OPERATIONS_API_ENABLED: + ENGINE_ALLOW_UNSECURED_CONNECTIONS: diff --git a/engine/engine/engine/services/threads/download_thread.py b/engine/engine/engine/services/threads/download_thread.py index 07dd970f4736d64398c474b44588feb259a25a2f..63fcea8f7b57ee5045b58f1b8089abdc0675587e 100644 --- a/engine/engine/engine/services/threads/download_thread.py +++ b/engine/engine/engine/services/threads/download_thread.py @@ -50,7 +50,9 @@ from engine.services.log import logs from isardvdi_common.default_storage_pool import DEFAULT_STORAGE_POOL_ID from rethinkdb import r -URL_DOWNLOAD_INSECURE_SSL = True +URL_DOWNLOAD_INSECURE_SSL = ( + os.environ.get("ENGINE_ALLOW_UNSECURED_CONNECTIONS", "") == "true" +) TIMEOUT_WAITING_HYPERVISOR_TO_DOWNLOAD = 10 FILETYPES_MEDIA_OK = ["application/x-iso9660-image"] diff --git a/isardvdi.cfg.example b/isardvdi.cfg.example index a3fab4c6932f0651a1cf7110f4089d91ac12313c..b8ea54d925690d86faaf344f2870c546477db7f6 100644 --- a/isardvdi.cfg.example +++ b/isardvdi.cfg.example @@ -398,6 +398,13 @@ HAPROXY_LOGGING=. ## ----- Disk operations balancer #ENGINE_DISK_BALANCER=less_cpu +# ------ ENGINE UPLOAD MEDIA --------------------------------------------------- +## Allow unsecured connections to upload media files +## Values: (first value is the default one) +## - false: only allow https connections +## - true: allow http connections (recommended only local/testing/dev) +#ENGINE_ALLOW_UNSECURED_CONNECTIONS=false + # ------ ENGINE TELEGRAM --------------------------------------------------- ## Will notify this bot/chat if system not fully operational #TELEGRAM_ENGINE_TOKEN= diff --git a/old-frontend/src/pages/MediaNew.vue b/old-frontend/src/pages/MediaNew.vue index b57de27080f61b92745ff3b824c108913e08c12f..5b0d5e88e16a73bc5c7dbdf85c75e889bd818c3a 100644 --- a/old-frontend/src/pages/MediaNew.vue +++ b/old-frontend/src/pages/MediaNew.vue @@ -162,7 +162,8 @@ import { required, minLength, maxLength, url } from '@vuelidate/validators' import { map } from 'lodash' import i18n from '@/i18n' const inputFormat = value => /^[-_àèìòùáéíóúñçÀÈÌÒÙÁÉÍÓÚÑÇ .a-zA-Z0-9]+$/.test(value) -const URLFormat = value => /^https:\/\/[a-zA-Z0-9.-_~:/?#[\]@!$&'()*+,;=%]+(?:\/[a-zA-Z0-9.-_~:/?#[\]@!$&'()*+,;=%]+)*(?:\/)?[^\s?#]+(?:\?.*)?$/.test(value) +const URLFormatSecured = value => /^https:\/\/[a-zA-Z0-9.-_~:/?#[\]@!$&'()*+,;=%]+(?:\/[a-zA-Z0-9.-_~:/?#[\]@!$&'()*+,;=%]+)*(?:\/)?[^\s?#]+(?:\?.*)?$/.test(value) +const URLFormatUnsecured = value => /^https?:\/\/[a-zA-Z0-9.-_~:/?#[\]@!$&'()*+,;=%]+(?:\/[a-zA-Z0-9.-_~:/?#[\]@!$&'()*+,;=%]+)*(?:\/)?[^\s?#]+(?:\?.*)?$/.test(value) export default { components: { @@ -187,6 +188,7 @@ export default { const selectedGroups = computed(() => $store.getters.getSelectedGroups) const usersChecked = computed(() => $store.getters.getUsersChecked) const selectedUsers = computed(() => $store.getters.getSelectedUsers) + const allowUnsecured = process.env.VUE_APP_ENGINE_ALLOW_UNSECURED_CONNECTIONS === 'true' const setMediaName = () => { if (name.value === '') { @@ -199,7 +201,7 @@ export default { mediaUrl: { required, url, - URLFormat + URLFormat: allowUnsecured ? URLFormatUnsecured : URLFormatSecured }, type: { required diff --git a/webapp/webapp/webapp/templates/admin/pages/media_modals.html b/webapp/webapp/webapp/templates/admin/pages/media_modals.html index 557d3c920a65394fc24019400fbfa7fbdfc29d56..d2bae817a87b9a84cf1e7bd1901d836b0d6aec1d 100644 --- a/webapp/webapp/webapp/templates/admin/pages/media_modals.html +++ b/webapp/webapp/webapp/templates/admin/pages/media_modals.html @@ -21,15 +21,28 @@
+ {% if allow_unsecured_connections %} + + {% else %} + {% endif %}
diff --git a/webapp/webapp/webapp/views/AdminViews.py b/webapp/webapp/webapp/views/AdminViews.py index 5eaaf9dc9d82bf0204874422f97580155eba6cbe..49569548ce170f854e1400dea1aa21ec886c4666 100644 --- a/webapp/webapp/webapp/views/AdminViews.py +++ b/webapp/webapp/webapp/views/AdminViews.py @@ -30,6 +30,9 @@ from ..auth.authentication import * from ..lib.log import * from .decorators import isAdmin, isAdminManager, maintenance +allow_unsecured_connections = ( + os.environ.get("ENGINE_ALLOW_UNSECURED_CONNECTIONS", "") == "true" +) monitor_host = os.getenv("GRAFANA_WEBAPP_URL") if not monitor_host: monitor_host = f'https://{os.getenv("DOMAIN", "localhost")}/monitor' @@ -296,6 +299,7 @@ def admin_media(): "admin/pages/media.html", nav="Media", title="Media", + allow_unsecured_connections=allow_unsecured_connections, )