From 1285541d46b72ff73a65f29bfd52ca00aad4c2d4 Mon Sep 17 00:00:00 2001 From: Stefano Alberto Russo <stefano.russo@gmail.com> Date: Sun, 15 Oct 2023 17:18:57 +0200 Subject: [PATCH] Added the option for disabling HTTP basicauth embedding. Minor fixes and cleanup. --- ...tainer_disable_http_basicauth_embedding.py | 18 ++++++ .../webapp/code/rosetta/core_app/models.py | 1 + .../core_app/templates/add_software.html | 7 ++ .../templates/components/container.html | 16 ++++- .../components/container_family_mah.html | 64 ------------------- .../core_app/templates/task_connect.html | 15 +++-- .../webapp/code/rosetta/core_app/views.py | 20 ++++-- 7 files changed, 63 insertions(+), 78 deletions(-) create mode 100644 services/webapp/code/rosetta/core_app/migrations/0036_container_disable_http_basicauth_embedding.py delete mode 100644 services/webapp/code/rosetta/core_app/templates/components/container_family_mah.html diff --git a/services/webapp/code/rosetta/core_app/migrations/0036_container_disable_http_basicauth_embedding.py b/services/webapp/code/rosetta/core_app/migrations/0036_container_disable_http_basicauth_embedding.py new file mode 100644 index 0000000..5d6ee68 --- /dev/null +++ b/services/webapp/code/rosetta/core_app/migrations/0036_container_disable_http_basicauth_embedding.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.1 on 2023-10-15 15:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core_app', '0035_auto_20231007_1249'), + ] + + operations = [ + migrations.AddField( + model_name='container', + name='disable_http_basicauth_embedding', + field=models.BooleanField(default=False, verbose_name='Disable HTTP basicauth credentials embedding'), + ), + ] diff --git a/services/webapp/code/rosetta/core_app/models.py b/services/webapp/code/rosetta/core_app/models.py index 8ab17fc..29ffa5d 100644 --- a/services/webapp/code/rosetta/core_app/models.py +++ b/services/webapp/code/rosetta/core_app/models.py @@ -140,6 +140,7 @@ class Container(models.Model): supports_custom_interface_port = models.BooleanField('Supports custom interface port', default=False) # BASE_PORT supports_interface_auth = models.BooleanField('Supports interface auth', default=False) # AUTH_USER / AUTH_PASS interface_auth_user = models.CharField('Interface auth fixed user if any', max_length=36, blank=True, null=True) + disable_http_basicauth_embedding = models.BooleanField('Disable HTTP basicauth credentials embedding', default=False) # Env vars for some container control env_vars = JSONField('Container env vars', blank=True, null=True) diff --git a/services/webapp/code/rosetta/core_app/templates/add_software.html b/services/webapp/code/rosetta/core_app/templates/add_software.html index ca0896d..2ef2970 100644 --- a/services/webapp/code/rosetta/core_app/templates/add_software.html +++ b/services/webapp/code/rosetta/core_app/templates/add_software.html @@ -142,6 +142,13 @@ </td> </tr> + <tr> + <td colspan=2> + <b>Disable HTTP auth embedding</b> + <input type="checkbox" name="container_disable_http_basicauth_embedding" value="True" /> + </td> + </tr> + <tr> <td><b>Environment variables</b></td> <td> diff --git a/services/webapp/code/rosetta/core_app/templates/components/container.html b/services/webapp/code/rosetta/core_app/templates/components/container.html index a13adc4..00d561d 100644 --- a/services/webapp/code/rosetta/core_app/templates/components/container.html +++ b/services/webapp/code/rosetta/core_app/templates/components/container.html @@ -101,7 +101,19 @@ <input type="checkbox" name="supports_interface_auth" checked disabled/> {% else %} <input type="checkbox" name="supports_interface_auth" disabled/> - {% endif %} </td> + {% endif %} + </td> + </tr> + + <tr> + <td colspan=2> + <b>Disable HTTP auth embedding</b> + {% if container.disable_http_basicauth_embedding %} + <input type="checkbox" name="disable_http_basicauth_embedding" checked disabled/> + {% else %} + <input type="checkbox" name="disable_http_basicauth_embedding" disabled/> + {% endif %} + </td> </tr> {% if container.env_vars %} @@ -114,7 +126,7 @@ {% if container.user %} <tr> <td><b>Operations</b></td> - <td><a href="?action=delete&uuid={{ container.uuid }}">Delete</a></td> + <td><a href="?action=delete&container_uuid={{ container.uuid }}">Delete</a></td> </tr> {% endif %} </table> diff --git a/services/webapp/code/rosetta/core_app/templates/components/container_family_mah.html b/services/webapp/code/rosetta/core_app/templates/components/container_family_mah.html deleted file mode 100644 index c2bf49b..0000000 --- a/services/webapp/code/rosetta/core_app/templates/components/container_family_mah.html +++ /dev/null @@ -1,64 +0,0 @@ - - - <div style="width:300px; float:left; border: #e0e0e0 solid 1px; margin:10px; background:#f8f8f8; margin-bottom:15px"> - <form action="/aaa" method=GET> - - - <div style="padding:10px; margin-top:5px; text-align:center; border-bottom: {{container.color}} solid 10px; "> - <a href="/software/?container_family={{ family_id }}">{{ container_family.name }}</a> - </div> - - <div style="padding:10px; height: 125px; "> - <!-- <div style="position: relative; top: 50%; transform: translateY(-50%);"> --> - - {% if container_family.description %} - <div class="description-box" title="{{ container_family.description }}"> - {{ container_family.description }} - </div> - {% else %} - <br/> - {% endif %} - - <div class="image-version-box"> - <b>Image:</b> <code>{{ container_family.image }}</code><br/> - <div style="margin-top:2px"> - - <span style="vertical-align:top;"><b>Tag:</b> </span> - <select name="task_container_uuid_and_arch" style="font-size:0.8em"> - {% for arch,container_by_tags in container_family.container_by_tags_by_arch.items %} - <optgroup label={{ arch }}> - {% for tag,container in container_by_tags.items %} - <option value="{{ container.uuid }}-{{ arch }}">{{ tag }}</option> - {% endfor %} - </optgroup> - {% endfor %} - </select> - - </div> - </div> - <!-- </div> --> - </div> - - <div style="margin-bottom:8px; margin-top: 3px; text-align:center"> - {% if not disable_play_button %} - - - <button type="submit" onclick="myFunction()" class="btn-link btn btn-light" style="border: #c0c0c0 1px solid"> - <i class="fa fa-play" style="color:green"></i> - </button> - - {% endif %} - </form> - </div> - - - - </div> - - - - - - - - \ No newline at end of file diff --git a/services/webapp/code/rosetta/core_app/templates/task_connect.html b/services/webapp/code/rosetta/core_app/templates/task_connect.html index a373418..c1ba20b 100644 --- a/services/webapp/code/rosetta/core_app/templates/task_connect.html +++ b/services/webapp/code/rosetta/core_app/templates/task_connect.html @@ -38,6 +38,12 @@ {% if data.task.auth_token %} Password: <input type="text" size=37 class="form-control" placeholder="" value="{{data.task.auth_token}}" name='password' readonly> + {% if data.task.container.disable_http_basicauth_embedding %} + <p style="margin-left:10px; margin-top:30px; font-size:0.9em; color:#484848"> + <i class="fa fa-info-circle" style="color:#337ab7"></i> + This task will require to manually enter the above user and password token + </p> + {% endif %} {% else %} Password: <input type="password" class="form-control" placeholder="" value="placeholder" name='password' readonly> <p style="margin-left:10px; font-size:0.9em; color:#484848"> @@ -50,7 +56,7 @@ {% if data.task.auth_token %} Password: <input type="text" class="form-control" placeholder="" value="{{data.task.auth_token}}" name='password' readonly> - <p style="margin-left:10px; font-size:0.9em; color:#484848"> + <p style="margin-left:10px; margin-top:30px; font-size:0.9em; color:#484848"> <i class="fa fa-info-circle" style="color:#337ab7"></i> {% if not data.task.requires_proxy_auth and data.task.container.interface_auth_user %} This task will require to manually enter the above user and password token @@ -60,7 +66,7 @@ </p> {% else %} Password: <input type="password" class="form-control" placeholder="" value="placeholder" name='password' readonly> - <p style="margin-left:10px; font-size:0.9em; color:#484848"> + <p style="margin-left:10px; margin-top:30px; font-size:0.9em; color:#484848"> <i class="fa fa-info-circle" style="color:#337ab7"></i> {% if not data.task.requires_proxy_auth and data.task.container.interface_auth_user %} This task will require to manually enter the above user and the password set up when creating the task @@ -85,16 +91,15 @@ </p> {% endif %} {% endif%} - </p> </form> </div> <br /><br /> {% if data.task.interface_status == 'running' %} - {% if data.task.requires_proxy_auth %} + {% if data.task.requires_proxy_auth and not data.task.container.disable_http_basicauth_embedding %} <p style="margin-left:10px; font-size:0.9em; color:rgb(200,200,200); max-width:600px"> - <i class="fa fa-info-warning" style="color:#337ab7"></i> + <i class="fa fa-info-circle"></i> Some web browsers (i.e. Safari) might require to manually re-enter the above user credentials. You can copy-paste them, or switch to a web browser which supports embedding user credentials in the connection URL (as Chorme, Edge or Firefox). </p> diff --git a/services/webapp/code/rosetta/core_app/views.py b/services/webapp/code/rosetta/core_app/views.py index 5ccde29..c74f08c 100644 --- a/services/webapp/code/rosetta/core_app/views.py +++ b/services/webapp/code/rosetta/core_app/views.py @@ -975,10 +975,16 @@ def add_software(request): container_supports_interface_auth = request.POST.get('container_supports_interface_auth', None) if container_supports_interface_auth and container_supports_interface_auth == 'True': - container_supports_pass_auth = True + container_supports_interface_auth = True else: - container_supports_pass_auth = False - + container_supports_interface_auth = False + + container_disable_http_basicauth_embedding = request.POST.get('container_disable_http_basicauth_embedding', None) + if container_disable_http_basicauth_embedding and container_disable_http_basicauth_embedding == 'True': + container_disable_http_basicauth_embedding = True + else: + container_disable_http_basicauth_embedding = False + # Environment variables container_env_vars = request.POST.get('container_env_vars', None) if container_env_vars: @@ -1001,7 +1007,8 @@ def add_software(request): interface_protocol = container_interface_protocol, interface_transport = container_interface_transport, supports_custom_interface_port = container_supports_custom_interface_port, - supports_interface_auth = container_supports_pass_auth, + supports_interface_auth = container_supports_interface_auth, + disable_http_basicauth_embedding = container_disable_http_basicauth_embedding, env_vars = container_env_vars) elif new_container_from == 'repository': @@ -1170,8 +1177,7 @@ def task_connect(request): # task.interface_status = 'running' data ={} - data['task'] = task - + data['task'] = task return render(request, 'task_connect.html', {'data': data}) @@ -1198,7 +1204,7 @@ def direct_connection_handler(request, uuid): # Redirect to the task through the tunnel if task.requires_proxy: - if task.requires_proxy_auth and task.auth_token: + if task.requires_proxy_auth and task.auth_token and not task.container.disable_http_basicauth_embedding: user = request.user.email password = task.auth_token redirect_string = 'https://{}:{}@{}:{}'.format(user, password, rosetta_tasks_proxy_host, task.tcp_tunnel_port) -- GitLab