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 0000000000000000000000000000000000000000..5d6ee68100daaf3d608ebe18e65f298115afb19b --- /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 8ab17fc5fef09f454808f9e96683f31b57f86d6b..29ffa5d03c47312aa447b816bcbdde084ebb157b 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 ca0896dd910f8880911b07235cf8c233aa35a227..2ef297006030ed071fcdbaf15cc4533d70f81607 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 a13adc46f82ac4a757fd8507786f7a0b086724c5..00d561d12a6b9d1a5779350c8f3fce61c051c851 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 c2bf49b5e147b9e98f2e04c0b2a6f4e544a76c49..0000000000000000000000000000000000000000 --- 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 a373418b59f058f6c9305c78645e7f3ad7582549..c1ba20bc5e0c19fa3c9f8510667a537b342c9a6b 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 5ccde29ab642d686003111a553973ef7201d9b1a..c74f08cdc8c21f6957fe874fa2c57ffced7bbf1e 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)