.. _science-gateway:
Science Gateway
===============
The Science Gateway website consists of two core components, the frontend UI and the
backend API. The backend interacts with external services (amongst other things),
and provides endpoints in the form of a REST API. The frontend interacts with the
backend endpoints via the REST API, and provides a web-based Graphical User Interface
to the end-user.
The Science Gateway website can be deployed on a local machine for development or in a
production environment.
Deployment prerequisites
------------------------
.. _iam-science-gateway:
IAM Configuration
^^^^^^^^^^^^^^^^^
For this service, the scopes required are:
- ```openid```
- ```profile```
For the *Grant types*:
- Ensure `authorization_code` and `refresh_token` grants are checked.
Follow the next instructions to create and manage the :doc:`/services/dependent/iam-client/iam-client`, including these scopes and grant types.
One saved, get the ``Client ID`` and ``Client Secret``, to include them into your configuration file for `.env` or `docker-compose.yml`.
Docker
^^^^^^
The frontend and backend components of the Science Gateway are containerised using
docker. At the time of writing, there is one container for the frontend and two for the
backend (one for the core API and another for the Gateway database). The backend
containers are grouped as a service to conveniently specify shared resources.
To install docker refer to the
`official documentation `_.
Follow the instructions that applies to the OS on your local machine.
.. note::
This guide will make use of Docker CLI commands. Feel free to use the desktop
UI application if it is more convenient however, instructions are not provided for
that method in this guide.
Cloning the source repositories
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Repositories containing the Science Gateway source code are hosted on Gitlab.
Clone the backend repository:
.. code-block:: shell
$ git clone https://gitlab.com/ska-telescope/src/src-api/ska-src-api-gateway
Clone the frontend repository:
.. code-block:: shell
$ git clone https://gitlab.com/ska-telescope/src/src-ui/ska-src-ui-gateway
.. _science-gateway-local-docker:
Deploying the gateway on a local machine for development
--------------------------------------------------------
The Science Gateway can be deployed on a local machine. This provides a quick and
flexible way to make changes (e.g. to code, UI elements) and test the results. This is
especially useful for SRCNet developers working on the Science Gateway.
Both the frontend and backend can be deployed on a local machine, and both are required
for the Science Gateway to work as designed.
Prerequisites
^^^^^^^^^^^^^
.. _science-gateway-iam-account:
SKA IAM Account
"""""""""""""""
A SKA IAM user account with the necessary permissions for each service used by the
backend API is required. The frontend obtains a code following a succesful IAM login.
The frontend uses the code to obtain and exchange access tokens via the backend API.
The tokens are used to access services external to the Science Gateway via the backend
API.
Register for an IAM account on this website:
https://ska-iam.stfc.ac.uk/login
The IAM account should belong to the following permissions groups to use all of the
Science Gateway features:
- services/gateway-backend-api
- services/site-capabilities-api
- services/data-management-api
Deploying the backend API locally
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ensure that port ``8080`` is not in use on your local machine. This port is used to host
the backend API.
In your terminal, navigate to the directory of the backend repository.
.. code-block:: shell
$ cd ./path/to/ska-src-api-gateway
Edit the ``docker-compose.yml`` contents to look as follows for local deployments:
.. code-block:: yaml
version: "3.5"
services:
db:
container_name: gateway-backend-db
image: mysql:8.0
cap_add:
- SYS_NICE
restart: always
environment:
- MYSQL_DATABASE=gatewaysettings
- MYSQL_ROOT_PASSWORD=V1Lv5FxUde
ports:
- '3306:3306'
volumes:
- db:/var/lib/mysql
- ./db/init/init.sql:/docker-entrypoint-initdb.d/init.sql
core:
container_name: gateway-backend-core
image: gateway-backend-core:latest
build:
context: .
dockerfile: Dockerfile
depends_on:
- db
environment:
DISABLE_AUTHENTICATION: "no"
API_ROOT_PATH:
API_SCHEME: http
IAM_CLIENT_CONF_URL: https://ska-iam.stfc.ac.uk/.well-known/openid-configuration
API_IAM_CLIENT_ID: some-uuid
API_IAM_CLIENT_SECRET:
API_IAM_CLIENT_SCOPES: openid profile
API_IAM_CLIENT_AUDIENCE: gateway-backend-api
PERMISSIONS_API_URL: https://permissions.srcdev.skao.int/api/v1
PERMISSIONS_SERVICE_NAME: gateway-backend-api
PERMISSIONS_SERVICE_VERSION: 1
DB_HOST: db
DB_PORT: 3306
DB_USER: root
DB_PASSWORD: V1Lv5FxUde
DB_NAME: gatewaysettings
ports:
- 8080:8080
volumes:
db:
driver: local
Add values for the environment variables ``API_IAM_CLIENT_ID`` and
``API_IAM_CLIENT_SECRET`` to the ``docker-compose.yml`` file based on the IAM client
:ref:`created earlier `.
Set the value of the environment variable ``RUN_MODE`` in ``docker-compose.yml`` to
``DEV``.
Create a file called ``docker-compose.local.yml`` with the following contents:
.. code-block:: yaml
version: "3.5"
services:
core:
extends:
file: docker-compose.yml
service: core
environment:
DISABLE_AUTHENTICATION: "no"
volumes:
- $../:/opt/ska-src-api-gateway
Deploy the docker service:
.. code-block:: shell
$ docker-compose up -d
Access the database container and create the required tables:
.. code-block:: shell
$ docker exec -ti gateway-backend-db /bin/bash
$ mysql -u root -p # will prompt for a password, use V1Lv5FxUde
$ mysql> USE gatewaysettings
$ mysql> CREATE TABLE Users ( ID int NOT NULL AUTO_INCREMENT, IAM_ID varchar(255), PRIMARY KEY (ID) );
$ mysql> CREATE TABLE Preferences ( ID int NOT NULL AUTO_INCREMENT, UserID int, DarkMode tinyint, Language varchar(10), PRIMARY KEY (ID) );
$ mysql> CREATE TABLE Services ( ID int NOT NULL AUTO_INCREMENT, Service_ID varchar(255), PRIMARY KEY (ID) );
$ mysql> CREATE TABLE ServiceTokens ( ID int NOT NULL AUTO_INCREMENT, UserID int, ServiceID int, Username varchar(255), Token varchar(255), PRIMARY KEY (ID) );
$ mysql> CREATE TABLE DataManagementJobs ( ID int NOT NULL AUTO_INCREMENT, UserID int, JobID varchar(32), ToStorageAreaUUID varchar(255), Status varchar(255), PRIMARY KEY (ID) );
Check that the tables were created:
.. code-block:: shell
$ mysql> SHOW TABLES;
Type ``exit`` and enter twice to leave MySQL and the container.
Testing the local backend deployment
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Check that the service containers are running in docker:
.. code-block:: shell
$ docker container ls
You should see output similar to the following:
.. code-block:: shell
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc0189ee3037 mysql:8.0 "docker-entrypoint.s…" 8 days ago Up 2 days 0.0.0.0:3306->3306/tcp, 33060/tcp gateway-backend-db
b54d97c4723b gateway-backend-core:latest "/bin/bash etc/docke…" 8 days ago Up 9 seconds 0.0.0.0:8080->8080/tcp gateway-backend-core
- Test the backend API by using its ``ping`` endpoint by navigating to
http://localhost:8080/v1/ping in your web browser. Your browser should display output
similar to the following:
.. code-block:: json
{"status":"UP","version":"0.1.1"}
- Test the backend API by navigating to http://localhost:8080/v1/www/docs/oper in your
browser to view the swagger frontend.
Deploying the frontend web UI locally
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ensure that port ``3000`` is not in use on your local machine. It is used to host the
frontend website.
In your terminal, navigate to the directory of the backend repository:
.. code-block:: shell
$ cd ./path/to/ska-src-ui-gateway
Edit the Dockerfile so that its contents looks as follows:
.. code-block:: docker
FROM node:lts
RUN mkdir -p /app
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["npm", "run", "start"]
This ensures that the frontend react app will run in `development` mode, which means
it will access the backend API via ``http://localhost:8080``.
Build the frontend docker image:
.. code-block:: shell
$ docker build . --tag 'ska-src-ui-gateway'
Create a container using the image and run it in the background:
.. code-block:: shell
$ docker run --name 'gateway-ui' -p 3000:3000 -ti -d ska-src-ui-gateway
Testing the local frontend deployment
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Navigate to http://localhost:3000/ in your web browser. Login using your SKA IAM Account
:ref:`created earlier `.
.. _science-gateway-prod-docker:
Deploying the gateway in a production environment
-------------------------------------------------
The current deployment of the gateway (both frontend and backend) is spread over two
nodes. The deployment of new versions is handled through CI/CD. Here, we will describe
the relevant aspects of the setup of the nodes.
Deployment systems
^^^^^^^^^^^^^^^^^^
Both systems (to which we will respectively refer as ``test`` and ``production``
systems) run on the STFC cloud. The ``production`` system (for which the CI/CD system
is used to push the ``main`` branch of the corresponding repositories) is called
``srcnet-esap``, and is accessible through the URL https://gateway.srcdev.skao.int.
The test deployment, to which any branch can be deployed manually, runs on the
``srcnet-esap-test`` node, accessible through https://gateway.srcdev-test.skao.int.
The configuration of the proxies that forward the traffic from the URL to the node is
such that any traffic coming in on port ``443`` on the externally-facing URL is sent to
port ``80`` on the host.
Prerequisites
^^^^^^^^^^^^^
Traefik
"""""""
To route traffic within the host, we use `Traefik `_. We detail the
installation here.
To access the node, an account on the STFC system is required. Access via ssh is granted
through the ``bastion`` host. We will assume you have been granted access, know how
to access the system, and are logged in to a terminal on the host with root privileges.
For deployments, we use a user called ``gitlab_deploy``. So to manage the Traefik setup,
change to that user, and go to the directory holding the docker-compose file with the
configuration:
.. code-block:: shell
$ sudo su gitlab_deploy
$ cd ~/deploy-traefik
In this directory, you will find several artifacts. The first one being a docker-compose
file (a nice feature of Traefik is that it can run inside a docker container, while
proxying other docker containers. You will see in the docker-compose file that this is
achieved by linking in the docker socket in the docker container). The
``docker-compose.yml`` file looks like:
.. code-block:: yaml
services:
traefik:
image: traefik:2.10 # or any later version
ports:
- "80:80" # http
- "8081:8081" # Traefik Dashboard
- "3001:3001" # compute API
volumes:
- $PWD/traefik/local.yml:/etc/traefik/traefik.yml
- /var/run/docker.sock:/var/run/docker.sock # see Security considerations below
networks:
- esap_network
restart: always
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=PathPrefix(`/dashboard`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.entryPoints=dashboard"
The ``ports`` section tells us that Traefik will proxy traffic coming in through port 80
(for both the gateway frontend and backend). Port ``8081`` exposes the Traefik dashboard,
which is a nice debugging tool. However, the dashboard is only accessible from
within the internal network of the node (so some proxying is needed to look at it). The
last port exposed is ``3001`` which is used for the compute API demonstrator (which for
practical reasons also runs in a container on this host, but is mapped to a different
URL than the gateway).
Apart from the aforementioned Docker socket object, the Traefik configuration file is
linked as a volume (**NB** In principle the configuration could also have been fully
done using docker labels rather than a yml file, keeping everything in one place, this
is really a matter of taste of the deployer). We will come back to the ``.yml`` file
later.
The container is coupled to a network, currently called `esap_network` for historical
reasons. At the bottom you see that the network is of type `external`,
meaning that it has to be manually created and is not managed by docker-compose:
.. code-block:: shell
$ docker network create esap_network
The ``labels`` block define some of the configuration. In this configuration, Traefik
is enable, and the dashboard (which connects to an entrypoint called ``dashboard``).
Finally, the Traefik ``.yml`` configuration looks like this:
.. code-block:: yaml
entryPoints:
web:
address: :80
dashboard:
address: :8081
compute-api:
address: :3001
log:
level: DEBUG
providers:
docker:
exposedByDefault: false # explicitly make container available using labels
network: esap_network # should match the (external) network created earlier
api:
dashboard: true
The first block defines ``entrypoints`` which essentially are the ports to which the
Traefik application is listening (unsurprisingly those are the same as the ports opened
in the docker-compose file). Each docker container connecting to Traefik will need to
configure the entrypoint it will use so that Traefik knows from what incoming port on
the host to forward the requests. The log level is set to debug. There is only one
``provider`` (source of applications): the docker provider. The first
``exposedByDefault`` setting makes it required for any container to explicitly announce
it wants to be routed by Traefik through labels. The ``network`` setting tells Traefik
what the internal Docker network is that needs to be connected (unsurprisingly this
matches the name of the network in the docker-compose file). The final setting tells
Traefik to run the API so that it can be connected to.
Deploying the backend API
^^^^^^^^^^^^^^^^^^^^^^^^^
In your terminal, navigate to the directory of the backend repository.
.. code-block:: shell
$ cd ./path/to/ska-src-api-gateway
Add values for the environment variables ``API_IAM_CLIENT_ID`` and
``API_IAM_CLIENT_SECRET`` to the ``docker-compose.yml`` file based on the IAM client
:ref:`created earlier `.
Check that the value of the environment variable ``RUN_MODE`` in ``docker-compose.yml``
is set to ``PROD``.
Deploy the docker service:
.. code-block:: shell
$ docker-compose up -d
Access the database container and create the required tables:
.. code-block:: shell
$ docker exec -ti gateway-backend-db /bin/bash
$ mysql -u root -p # will prompt for a password, use V1Lv5FxUde
$ mysql> USE gatewaysettings
$ mysql> CREATE TABLE Users ( ID int NOT NULL AUTO_INCREMENT, IAM_ID varchar(255), PRIMARY KEY (ID) );
$ mysql> CREATE TABLE Preferences ( ID int NOT NULL AUTO_INCREMENT, UserID int, DarkMode tinyint, Language varchar(10), PRIMARY KEY (ID) );
$ mysql> CREATE TABLE Services ( ID int NOT NULL AUTO_INCREMENT, Service_ID varchar(255), PRIMARY KEY (ID) );
$ mysql> CREATE TABLE ServiceTokens ( ID int NOT NULL AUTO_INCREMENT, UserID int, ServiceID int, Username varchar(255), Token varchar(255), PRIMARY KEY (ID) );
$ mysql> CREATE TABLE DataManagementJobs ( ID int NOT NULL AUTO_INCREMENT, UserID int, JobID varchar(32), ToStorageAreaUUID varchar(255), Status varchar(255), PRIMARY KEY (ID) );
Check that the tables were created:
.. code-block:: shell
$ mysql> SHOW TABLES;
Type ``exit`` twice to leave MySQL and the container.
Deploying the frontend web UI
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In your terminal, navigate to the directory of the backend repository:
.. code-block:: shell
$ cd ./path/to/ska-src-ui-gateway
Build the frontend docker image:
.. code-block:: shell
$ docker build . --tag 'ska-src-ui-gateway'
Create a ``docker-compose.yml`` file with the following contents:
.. code-block:: yaml
services:
esap_api:
container_name: tangerinenet
image: ska-src-ui-gateway
expose:
- "3000"
networks:
- esap_network
restart: always
labels:
# Enables traefik to connect to the API
- "traefik.enable=true"
- "traefik.http.routers.tangerinenet.entryPoints=web"
- "traefik.http.routers.tangerinenet.rule=PathPrefix(`/`)"
- "traefik.http.routers.tangerinenet.service=tangerinenet"
- "traefik.http.services.tangerinenet.loadbalancer.server.port=3000"
networks:
esap_network:
external: true
Deploy the docker service:
.. code-block:: shell
$ docker-compose up -d