===========
HTTPS Proxy
===========

.. contents::

Introduction
============

In addition to securing your SSH accesses, by splitting the authentication part (ingress connection)
and the authorization part (egress connection), The Bastion can do a similar job for HTTPS connections.

Note that there is an overhead (depending on your hardware setup) of several hundreds of milliseconds
for each query-response trip, due to the fact that multiple processes are spawned for each query,
to ensure proper security containment to the calling account's system user.
It's probably a bad idea to use on a multi-million queries/day workload,
or if each added millisecond to the query-response trip impacts the QoS of your service.

The primary use is for network devices, that happen to have more and more HTTPS APIs in addition
to the usual ``conf terminal`` available through SSH. As the same commands are usually available from
HTTPS and SSH on these devices, it would be too bad to secure the access to SSH through the bastion,
but leave direct access to their HTTPS API!

Query workflow
==============

The workflow is similar to the one used by SSH, e.g. two distinct connections (ingress and egress),
with the egress connection using credentials stored on the bastion:

- A client makes an HTTP request to the proxy, with the following information embedded in:

  - The type of request (GET or POST)
  - The complete URI, including the host of the remote HTTPS server it would like to send the request to
  - Potential body data for POST requests
  - Credentials to authenticate to the proxy on the ingress connection, namely the
    bastion account name and its proxy password (set by ``selfGenerateProxyPassword``)
  - User name to use to authenticate on the remote HTTPS server (for the egress connection)

- The bastion checks the provided credentials to authenticate the request against a known account (authentication part)
- The bastion verifies whether the just-authenticated account has access rights to connect to the remote server
  as the specified remote user (authorization part)
- The bastion uses the (group or personal) credentials stored on the bastion,
  to passthrough the HTTP request to the remote server, as the specified remote user
- The bastion forwards the response to the client

Setting up the HTTPS Proxy
==========================

You should enable the HTTPS Proxy daemon, and configure it.
Please check the :doc:`/administration/configuration/osh-http-proxy_conf` for more information.

Running a query through the proxy
=================================

First try
---------

Once the proxy is running, we can try to query it:

.. code-block:: none
   :emphasize-lines: 1

   curl https://bastion1.example.org:8443/
   No authentication provided, and authentication is mandatory

Of course, the proxy only accepts to work when one is properly authenticated to it.
To do this, one should have an account on the bastion, and use the :doc:`/plugins/open/selfGenerateProxyPassword`
command so that a new ingress password is set for their account. They'll then be able to authenticate to the proxy
using the HTTP basic-auth method, and try to send a request to a remote server.
To keep a high compatibility with HTTP clients and libraries that can be used on the ingress side,
all the additional data required by the bastion to properly authenticate, authorize and passthrough the request
is encoded in the *user* part of the widely supported HTTP Authorize header (basic-auth).
The *password* part corresponds to the password we've generated just above.

The format of the *user* part is as follows:

.. code-block:: none

   BASTION_ACCOUNT@REMOTE_USER@REMOTE_HOST%REMOTE_PORT

The **%REMOTE_PORT** part is optional, and defaults to **443** if omitted.
For example, to send a **GET /info** request to the remote network device named **router12.example.org** on
the default port **443**, using the remote account **monitoring**, through the **bastion1.example.org** bastion,
having the HTTPS Proxy listening on its port **8443** and a bastion account **robot-mon**, one can use **curl**:

.. code-block:: none
   :emphasize-lines: 1

   curl -u robot-mon@monitoring@router12.example.org https://bastion1.example.org:8443/info
   Enter host password for user 'robot-mon@monitoring@router12.example.org':
   This account doesn't have access to this user@host tuple (Access denied for robot-mon to monitoring@router12.example.org:443)

A password will be prompted: the password generated by ``selfGenerateProxyPassword`` should be entered.
Remember: this is to authenticate yourself to the bastion (ingress connection), then the bastion will authenticate
itself to the remote machine (egress connection), using credentials stored on the bastion,
that your account must have access to.

In the above case, we entered the password correctly, but our account doesn't have access to
the requested host `monitoring@router12.example.org`. This is what we need to do now.

Access declaration
------------------

The access check is the same than the one done for SSH accesses, which means that oneself
can have access to a remote host either through a :ref:`personal access <accessManagementPersonalAccesses>` or
a :ref:`group access <accessManagementGroupAccesses>`.

To get granted access to a remote device, through a personal access, either
the :doc:`/plugins/restricted/selfAddPersonalAccess` or the :doc:`/plugins/restricted/accountAddPersonalAccess` shall
be used (both are restricted commands) such as:

.. code-block:: none
   :emphasize-lines: 1

   bssh --osh accountAddPersonalAccess --host router12.example.org --port 443 --user monitoring --force

Note the use of ``--force`` to skip the SSH connection test, which is useless in our case.

To use a group access instead, one of the :ref:`aclkeepers <accessManagementGroupRoles>` of the group
should use :doc:`/plugins/group-aclkeeper/groupAddServer`, such as:

.. code-block:: none
   :emphasize-lines: 1

   bssh --osh groupAddServer --group netdevices --host router12.example.org --port 443 --user monitoring --force


Egress password
---------------

For personal accesses
*********************

If access to a remote device is granted to you through a personal access (using either the ``selfAddPersonalAccess``
or ``accountAddPersonalAccess`` commands), you must first generate a new set of credentials that will be stored
on your bastion account, for egress connections. This is the equivalent of your personal egress keys for SSH,
but in that case it's a password that will be used to authenticate using basic-auth to the remote server.
You can generate this password using the ``selfGeneratePassword`` command:

.. code-block:: none
   :emphasize-lines: 1

   bssh --osh selfGeneratePassword --do-it
   *------------------------------------------------------------------------------*
   |THIS IS A PRIVATE COMPUTER SYSTEM, UNAUTHORIZED ACCESS IS STRICTLY PROHIBITED.|
   |ALL CONNECTIONS ARE LOGGED. IF YOU ARE NOT AUTHORIZED, DISCONNECT NOW.        |
   *------------------------------------------------------------------------------*
   ╭──bastion1.example.org───────────────────────────────the-bastion-3.03.99-rc1───
   │ ▶ generating a new egress password for your account
   ├───────────────────────────────────────────────────────────────────────────────
   │ Generated a new password of length 16 for your account, robot-mon, hashes follow:
   │ md5crypt: $1$G0fo$2DH2OJQJ9bMgo5fUUuPeK.
   │ sha256crypt: $5$2xd1aGuD$ze7px3olXdjWthSrdnzelm6avzT2kszx/voXms8/V00
   │ sha512crypt: $6$udw2UNLs$tQ1p7ZYraOT4Woh1ZCGJNf.UAIh09nXPBf4ejpRurOY/fJUs6Dgh1WdkpY4pdCvKMQrPeetB42bNTSzIwJyGi1
   │ This new password will now be used by default.
   ╰─────────────────────────────────────────────────────</selfGeneratePassword>───

As you can see, the password is stored on your bastion account, and is not printed: only its hashes are.
With this information, the corresponding remote account can be provisioned on the device (usually, a network device).
In our above example, an account named **monitoring** would have to be created on the remote device,
using one of these hashes. Prefer to use the most secure hashing algorithm supported by the remote device.

To get your password (hash) list, you can use ``selfListPasswords``:

.. code-block:: none
   :emphasize-lines: 1

   bssh --osh selfListPasswords
   *------------------------------------------------------------------------------*
   |THIS IS A PRIVATE COMPUTER SYSTEM, UNAUTHORIZED ACCESS IS STRICTLY PROHIBITED.|
   |ALL CONNECTIONS ARE LOGGED. IF YOU ARE NOT AUTHORIZED, DISCONNECT NOW.        |
   *------------------------------------------------------------------------------*
   ╭──bastion1.example.org───────────────────────────────the-bastion-3.03.99-rc1───
   │ ▶ list your egress passwords
   ├───────────────────────────────────────────────────────────────────────────────
   │ Current password created at Tue Jun 22 15:42:10 2021 by robot-mon
   │ ... md5crypt: $1$G0fo$2DH2OJQJ9bMgo5fUUuPeK.
   │ ... sha256crypt: $5$2xd1aGuD$ze7px3olXdjWthSrdnzelm6avzT2kszx/voXms8/V00
   │ ... sha512crypt: $6$udw2UNLs$tQ1p7ZYraOT4Woh1ZCGJNf.UAIh09nXPBf4ejpRurOY/fJUs6Dgh1WdkpY4pdCvKMQrPeetB42bNTSzIwJyGi1
   │ 
   │ Fallback password 1 created at Wed Jun  2 08:00:01 2021 by robot-mon
   │ ... md5crypt: $1$qF0M$2.rbRRGs66aPiEpc/SqGv/
   │ ... sha256crypt: $5$E9qkC7D6$SG8BB.nXvwU0dB0Bq9S/sF5pDidLwSIDKCv95qNWhX0
   │ ... sha512crypt: $6$druGNgSk$bzVHSvux/OOE2ZhDpabFekQU3GTsiKS7Yl/lLmb9gIAmjnFfR6gj7GzOniK2jdLtEcB/hQlhcx9TDgj5zHhVd.
   │ 
   ╰────────────────────────────────────────────────────────</selfListPasswords>───

If the ``selfGeneratePassword`` command is used several times, the newly generated password will always override
the previous one. Still, all the previous passwords are kept (archived) for good measure, and can be restored
manually by a bastion admin. These passwords are named *Fallback passwords* in the output of ``selfListPasswords``.

For group accesses
******************

If the access to the remote device is given through a group, then the group's own credentials will be used.
To this effect, one of the group owners should use the :doc:`/plugins/group-owner/groupGeneratePassword` command:

.. code-block:: none
   :emphasize-lines: 1

   bssh --osh groupGeneratePassword --group netdevices --do-it
   ╭──bastion1.example.org───────────────────────────────the-bastion-3.03.99-rc1───
   │ ▶ generating a new egress password for the group
   ├───────────────────────────────────────────────────────────────────────────────
   │ Generated a new password of length 16 for group netdevices, hashes follow:
   │ md5crypt: $1$9sb2$X8/pPBSLfQ0ddBGR/bzsT1
   │ sha256crypt: $5$o6Jr8w0X$yQfLuX17tUwE1jfhhAX//vsn6KpXU5jUd7SCNbkYNH.
   │ sha512crypt: $6$gyxMyjao$YNhZJPXZa4r838XKg2tfvvoV/Dtm5HKsyKt18BnvFfT.y.hZuSXRX9GhM4mA0hUsO9f0UBisO/WiK3vF/9qsL1
   │ This new password will now be used by default.
   ╰────────────────────────────────────────────────────</groupGeneratePassword>───

As with the personal egress passwords, the password is stored on the bastion only, and is not printed:
only its hashes are. With this information, the corresponding remote account can be provisioned
on the device (usually, a network device).
In our above example, an account named **monitoring** would have to be created on the remote device,
using one of these hashes. Prefer to use the most secure hashing algorithm supported by the remote device.

To get the group's password (hash) list, one can use the :doc:`/plugins/open/groupListPasswords` command:

.. code-block:: none
   :emphasize-lines: 1

   bssh --osh groupListPasswords --group netdevices
   *------------------------------------------------------------------------------*
   |THIS IS A PRIVATE COMPUTER SYSTEM, UNAUTHORIZED ACCESS IS STRICTLY PROHIBITED.|
   |ALL CONNECTIONS ARE LOGGED. IF YOU ARE NOT AUTHORIZED, DISCONNECT NOW.        |
   *------------------------------------------------------------------------------*
   ╭──bastion1.example.org───────────────────────────────the-bastion-3.03.99-rc1───
   │ ▶ list the egress passwords of the group
   ├───────────────────────────────────────────────────────────────────────────────
   │ Current password created at Tue Jun 29 10:21:38 2021 by slesimpl
   │ ... md5crypt: $1$9sb2$X8/pPBSLfQ0ddBGR/bzsT1
   │ ... sha256crypt: $5$o6Jr8w0X$yQfLuX17tUwE1jfhhAX//vsn6KpXU5jUd7SCNbkYNH.
   │ ... sha512crypt: $6$gyxMyjao$YNhZJPXZa4r838XKg2tfvvoV/Dtm5HKsyKt18BnvFfT.y.hZuSXRX9GhM4mA0hUsO9f0UBisO/WiK3vF/9qsL1
   ╰───────────────────────────────────────────────────────</groupListPasswords>───

If the ``groupGeneratePassword`` command is used several times, the newly generated password will always
override the previous one. Still, all the previous passwords are kept (archived) for good measure,
and can be restored manually by a bastion admin.
These passwords are named *Fallback passwords* in the output of ``groupListPasswords``.
