Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: authorized Katsu endpoints + slightly auth-aware Beacon #258

Merged
merged 30 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
99ef045
chore: rm proxy-controlled CORS from Katsu
davidlougheed Aug 12, 2024
17cdebc
set katsu to pr-529
davidlougheed Aug 12, 2024
ee0a83d
configure Katsu for CORS + authz
davidlougheed Aug 12, 2024
062bcb5
set public to pr-173
davidlougheed Aug 14, 2024
2e2e868
Merge branch 'releases/v17' into feat/v17/katsu-auth-v2
davidlougheed Aug 14, 2024
0a45ee5
chore(deps): update requirements
davidlougheed Aug 15, 2024
3f2f667
refact(bentoctl): factor out common client/secret creation code
davidlougheed Aug 15, 2024
1f9e2ae
set gateway to edge
davidlougheed Aug 19, 2024
8eed564
set public to pr-175
davidlougheed Aug 26, 2024
daf694d
Merge branch 'releases/v17' into feat/v17/katsu-auth-v2
davidlougheed Aug 29, 2024
5e9c86f
Merge remote-tracking branch 'origin/releases/v17' into feat/v17/kats…
davidlougheed Aug 30, 2024
64d7773
docs: link to v17 migration guide from README
davidlougheed Sep 9, 2024
eb20934
set Katsu to edge
davidlougheed Sep 9, 2024
0dc03d0
rm now-unused env var from public
davidlougheed Sep 9, 2024
90719de
docs: WIP migration guide content for v17
davidlougheed Sep 9, 2024
28ed301
docs: add public data access configuration step for v17 migration
davidlougheed Sep 9, 2024
65c9c1a
docs: instructions for public data access setup in installation guide
davidlougheed Sep 9, 2024
249012d
set authz to edge
davidlougheed Sep 9, 2024
50fec77
set public to edge
davidlougheed Sep 10, 2024
2c634bf
work on configuring beacon OIDC for data access
davidlougheed Sep 12, 2024
5971afd
fix missing BENTO_MONITORING_ENABLED from default_config + reorder
davidlougheed Sep 12, 2024
269d1b6
configure external URLs for Beacon Katsu/Gohan connection
davidlougheed Sep 12, 2024
9d01c05
docs: v17 migration and install guides for agg/Beacon, Grafana
davidlougheed Sep 12, 2024
64588d6
fix env vars passing to beacon
davidlougheed Sep 12, 2024
c552d3e
whitespace
davidlougheed Sep 12, 2024
0b957e2
set beacon to edge
davidlougheed Sep 16, 2024
cfdb800
Merge remote-tracking branch 'origin/releases/v17' into feat/v17/kats…
davidlougheed Sep 16, 2024
9b964d0
docs: fix issues with issuer template values
davidlougheed Sep 16, 2024
3a1f559
docs: reminder to put client secret(s) in local.env
davidlougheed Sep 16, 2024
b2bb0b4
docs: note granular discovery + fix typo
davidlougheed Sep 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ that make up the Bento platform.

### Migration documents

* [v16 to v17](./docs/migrating_to_17.md)
* [v15.2 to v16](./docs/migrating_to_16.md)
* [v15.1 to v15.2](./docs/migrating_to_15_2.md)
* [v15 to v15.1](./docs/migrating_to_15_1.md)
Expand Down
48 changes: 40 additions & 8 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,10 @@ specified in the step above.
./bentoctl.bash init-auth
```

**If using an external identity provider**, only start the cluster's gateway
after setting `CLIENT_SECRET` in your local environment file:
After running `init-auth`, be sure to put all client secrets into your `local.env` file!

**If using an external identity provider**, only start the cluster's gateway after setting various `*_CLIENT_SECRET`
variables in your local environment file:

```bash
./bentoctl.bash run gateway
Expand All @@ -297,7 +299,7 @@ utilize new variables generated during the OIDC configuration.

## 6. Configure permissions

### a. Create superuser permissions in the new Bento authorization service
### a. Create superuser permissions in the Bento authorization service

First, run the authorization service and then open a shell into the container:

Expand All @@ -317,24 +319,54 @@ which in Keycloak should be a UUID.

### b. Create grants for the Workflow Execution Service (WES) OAuth2 client

Run the following commands to set up authorization for the WES client. Don't forget to replace `ISSUER_HERE` by the
issuer URL!
Run the following commands to set up authorization for the WES client.
**Don't forget to replace `<ISSUER_HERE>` with the issuer URL!**

```bash
# This grant is a temporary hack to get permissions working for v12/v13. In the future, it should be removed.
bento_authz create grant \
'{"iss": "ISSUER_HERE", "client": "wes"}' \
'{"iss": "<ISSUER_HERE>", "client": "wes"}' \
'{"everything": true}' \
'view:private_portal'

# This grant gives permission to access and ingest data into all projects and the reference genome service
bento_authz create grant \
'{"iss": "ISSUER_HERE", "client": "wes"}' \
'{"iss": "<ISSUER_HERE>", "client": "wes"}' \
'{"everything": true}' \
'query:data' 'ingest:data' 'ingest:reference_material' 'delete:reference_material'
```

### c. *Optional step:* Assign portal access to all users in the instance realm
### c. Create a grant for the aggregation and Beacon services

Run the following commands to set up authorization for the aggregation/Beacon client.
**Don't forget to replace `<ISSUER_HERE>` with the issuer URL!**

```bash
# In the future, view:private_portal will need to be removed from this grant.
bento_authz create grant \
'{"iss": "<ISSUER_HERE>", "client": "aggregation"}' \
'{"everything": true}' \
'query:data' 'view:private_portal'
```


### d. Configure public data access for all users, including anonymous visitors (if desired):

To configure public data access, run the following command in the authorization service container. Note that with the
`full` value, **THIS GIVES FULL DATA ACCESS TO EVERYONE WHO VISITS YOUR INSTANCE!**

```bash
# Configure public data access
# ----------------------------
# The level below ("counts") preserves previous functionality. Other possible options are:
# - none - will do nothing.
# - bool - for censored true/false discovery, but in effect right now forbids access.
# - counts - for censored count discovery.
# - full - allows full data access (record-level, including sensitive data such as IDs), uncensored counts, etc.
bento_authz public-data-access counts
```

### e. Assign portal access to all users in the instance realm

We added a special permission, `view:private_portal`, to Bento v12/v13 in order to carry forward the current
'legacy' authorization behaviour for one more major version. This permission currently behaves as a super-permission,
Expand Down
89 changes: 87 additions & 2 deletions docs/migrating_to_17.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,91 @@
# Migrating to Bento v17

Key points:
* Bento now has observability tools to help monitor the services (Grafana)
<!-- TODO: add migration guide for Grafana, with examples of user role attribution -->

* Bento now has observability tools to help monitor the services (Grafana). Some setup is required for this feature to
work.
* Katsu discovery endpoints now have an authorization layer.
* Data that used to be completely public by default (i.e.,
censored counts) now requires a permission (`query:project_level_counts` and/or `query:dataset_level_counts`), and
thus a grant in the authorization service.
* Beacon now requires a client ID/secret and an authorization service grant to access uncensored data.
* Katsu discovery is now more granular, and can be configured to the project or dataset level, in addition to the
instance level. See the [Public data discovery configuration](./public_discovery.md) document for more information.
* ...


## 1. Stop Bento

```bash
./bentoctl.bash stop
```


## 2. Update images

```bash
./bentoctl.bash pull
```


## 3. Set up credentials for aggregation/Beacon and, optionally, set up Grafana

If you wish to enable Grafana, you first must enable the monitoring feature in your `local.env` file:

```bash
BENTO_MONITORING_ENABLED='true'
```

To create the client secrets for aggregation/Beacon and Grafana (if the latter is enabled), run the following commands:

```bash
./bentoctl.bash start auth
./bentoctl.bash init-auth
```

**Reminder:** Make sure to put the client secret(s) generated by `init-auth` into your `local.env` file!

Aggregation/Beacon data access authorization will not work until an authorization service grant is configured;
davidlougheed marked this conversation as resolved.
Show resolved Hide resolved
see step 4 below.


## 4. Set up aggregation/Beacon permissions and public data access grants

Now that Beacon uses a client ID/secret to get authorized, uncensored data access for discovery, a grant must be
configured to give the aggregation/Beacon client data access.

Another change to permissions: starting from Bento v17, anonymous visitors do not have access to see censored counts
data by default, even if a discovery configuration has been set up. For anonymous visitors to access data, a level
(`bool`, `counts`, `full`) must be chosen and passed to the `bento_authz` CLI command below.

```bash
./bentoctl.bash shell authz

# Configure aggregation/Beacon permissions
# ----------------------------------------
# This assumes the aggregation/Beacon client ID is "aggregation".
# <ISSUER_HERE> MUST be replaced with your actual issuer value.
# - The query:data permission gives access to Katsu endpoints which are properly authz-enabled.
# - The view:private_portal permission gives access to Katsu and Gohan endpoints where the proxy still manages access.
# This permission will be removed in an uncoming version.
bento_authz create grant \
'{"iss": "<ISSUER_HERE>", "client": "aggregation"}' \
'{"everything": true}' \
'query:data' 'view:private_portal'

# Configure public data access
# ----------------------------
# The level below ("counts") preserves previous functionality. Other possible options are:
# - none - will do nothing.
# - bool - for censored true/false discovery, but in effect right now forbids access.
# - counts - for censored count discovery.
# - full - allows full data access (record-level, including sensitive data such as IDs), uncensored counts, etc.
bento_authz public-data-access counts
```


## 5. Start Bento

```bash
./bentoctl.bash start
```
25 changes: 18 additions & 7 deletions etc/bento.env
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ BENTOV2_GATEWAY_INTERNAL_CERTS_DIR=/usr/local/openresty/nginx/certs

# Gateway
BENTOV2_GATEWAY_IMAGE=ghcr.io/bento-platform/bento_gateway
BENTOV2_GATEWAY_VERSION=0.12.0
BENTOV2_GATEWAY_VERSION=edge
BENTOV2_GATEWAY_VERSION_DEV=${BENTOV2_GATEWAY_VERSION}-dev
BENTOV2_GATEWAY_CONTAINER_NAME=${BENTOV2_PREFIX}-gateway

Expand Down Expand Up @@ -77,7 +77,7 @@ BENTO_AUTH_DB_NETWORK="${BENTOV2_PREFIX}-auth-db-net"

# - Authz service
BENTO_AUTHZ_IMAGE=ghcr.io/bento-platform/bento_authorization_service
BENTO_AUTHZ_VERSION=0.9.2
BENTO_AUTHZ_VERSION=edge
BENTO_AUTHZ_VERSION_DEV=${BENTO_AUTHZ_VERSION}-dev
BENTO_AUTHZ_CONTAINER_NAME=${BENTOV2_PREFIX}-authz
BENTO_AUTHZ_NETWORK=${BENTOV2_PREFIX}-authz-net
Expand Down Expand Up @@ -133,6 +133,8 @@ BENTOV2_SERVICE_REGISTRY_EXTERNAL_PORT=5010
BENTOV2_SERVICE_REGISTRY_MEM_LIM=1G
BENTOV2_SERVICE_REGISTRY_CPUS=1

BENTO_SERVICE_REGISTRY_URL=${BENTOV2_PUBLIC_URL}/api/service-registry

# Notification
BENTOV2_NOTIFICATION_IMAGE=ghcr.io/bento-platform/bento_notification_service
BENTOV2_NOTIFICATION_VERSION=3.1.4
Expand Down Expand Up @@ -249,6 +251,10 @@ BENTOV2_DRS_DEBUGGER_EXTERNAL_PORT=5682
BENTOV2_DRS_MEM_LIM=2G
BENTOV2_DRS_CPUS=2

# Canonical/world-resolvable URL for DRS
# TODO: services should use the service registry instead
BENTO_DRS_URL=${BENTOV2_PUBLIC_URL}/api/drs

# Katsu-DB
BENTOV2_KATSU_DB_IMAGE=postgres
BENTOV2_KATSU_DB_VERSION=13
Expand All @@ -269,7 +275,7 @@ BENTOV2_KATSU_DB_CPUS=4

# Katsu
BENTOV2_KATSU_IMAGE=ghcr.io/bento-platform/katsu
BENTOV2_KATSU_VERSION=8.0.1
BENTOV2_KATSU_VERSION=edge
BENTOV2_KATSU_VERSION_DEV=${BENTOV2_KATSU_VERSION}-dev
BENTOV2_KATSU_CONTAINER_NAME=${BENTOV2_PREFIX}-katsu
BENTO_KATSU_NETWORK=${BENTOV2_PREFIX}-katsu-net
Expand All @@ -290,6 +296,10 @@ BENTOV2_KATSU_CPUS=4
# urls in templates.
CHORD_METADATA_SUB_PATH=/api/metadata

# Canonical/world-resolvable URL for Katsu
# TODO: services should use the service registry instead
BENTO_KATSU_URL=${BENTOV2_PORTAL_PUBLIC_URL}${CHORD_METADATA_SUB_PATH}

# Redis
BENTOV2_REDIS_BASE_IMAGE=redis
BENTOV2_REDIS_BASE_IMAGE_VERSION=7.0.15-alpine
Expand Down Expand Up @@ -336,6 +346,10 @@ BENTOV2_GOHAN_API_AUTHZ_ENABLED=false
#BENTOV2_GOHAN_API_AUTHZ_AGREED_DISABLED_RISK=false
BENTOV2_GOHAN_API_AUTHZ_REQHEADS=X-CUSTOM-1,X-CUSTOM-2

# Canonical/world-resolvable URL for Gohan
# - TODO: services should use the service registry instead
BENTO_GOHAN_URL=${BENTOV2_PORTAL_PUBLIC_URL}/api/gohan

# -- Elasticsearch
BENTOV2_GOHAN_ES_USERNAME=elastic
# BENTOV2_GOHAN_ES_PASSWORD comes from default_config
Expand Down Expand Up @@ -382,7 +396,6 @@ BENTO_PUBLIC_EXTERNAL_PORT=8090
BENTO_PUBLIC_DEBUG=false
BENTO_PUBLIC_SERVICE_ID=${BENTOV2_PREFIX}-public
BENTO_PUBLIC_CLIENT_NAME=BentoPublicDev
BENTO_PUBLIC_KATSU_URL=http://${BENTOV2_KATSU_CONTAINER_NAME}:${BENTOV2_KATSU_INTERNAL_PORT}
BENTO_PUBLIC_WES_URL=http://${BENTOV2_WES_CONTAINER_NAME}:${BENTOV2_WES_INTERNAL_PORT}
BENTO_PUBLIC_GOHAN_URL=http://${BENTOV2_GOHAN_API_CONTAINER_NAME}:${BENTOV2_GOHAN_API_INTERNAL_PORT}
BENTO_PUBLIC_PORTAL_URL=${BENTOV2_PORTAL_PUBLIC_URL}
Expand All @@ -392,7 +405,7 @@ BENTO_PUBLIC_PORTAL_URL=${BENTOV2_PORTAL_PUBLIC_URL}
BENTO_BEACON_CONTAINER_NAME=${BENTOV2_PREFIX}-beacon
BENTO_BEACON_NETWORK=${BENTOV2_PREFIX}-beacon-net
BENTO_BEACON_IMAGE=ghcr.io/bento-platform/bento_beacon
BENTO_BEACON_VERSION=0.15.2
BENTO_BEACON_VERSION=edge
BENTO_BEACON_VERSION_DEV=${BENTO_BEACON_VERSION}-dev
BENTO_BEACON_INTERNAL_PORT=${BENTO_STD_SERVICE_INTERNAL_PORT}
BENTO_BEACON_EXTERNAL_PORT=5000
Expand All @@ -402,10 +415,8 @@ BENTO_BEACON_MEM_LIM=2G
BENTO_BEACON_CPUS=2
BENTO_BEACON_CONFIG_DIR=${PWD}/lib/beacon/config

BENTO_BEACON_GOHAN_BASE_URL=http://${BENTOV2_GOHAN_API_CONTAINER_NAME}:${BENTOV2_GOHAN_API_INTERNAL_PORT}
BENTO_BEACON_KATSU_TIMEOUT=60
BENTO_BEACON_GOHAN_TIMEOUT=60
BENTO_BEACON_OIDC_ISSUER=${BENTOV2_AUTH_PUBLIC_URL}/auth/realms/${BENTOV2_AUTH_REALM}

# cBioPortal

Expand Down
8 changes: 6 additions & 2 deletions etc/bento_deploy.env
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ BENTO_GATEWAY_USE_TLS='true'
BENTO_BEACON_ENABLED='false' # Set to true if using Beacon!
BENTO_BEACON_UI_ENABLED='false'
BENTO_CBIOPORTAL_ENABLED='false'
BENTO_MONITORING_ENABLED='false'
BENTO_GOHAN_ENABLED='true'
BENTO_MONITORING_ENABLED='false'

# - Switch to enable French translation in Bento Public
BENTO_PUBLIC_TRANSLATED='true'
Expand Down Expand Up @@ -51,13 +51,17 @@ BENTOV2_AUTH_TEST_PASSWORD=
BENTO_AUTH_DB_PASSWORD= # TODO: SET ME WHEN DEPLOYING!
BENTO_AUTHZ_DB_PASSWORD= # TODO: SET ME WHEN DEPLOYING!

# - Aggregation/Beacon client ID/secret; client within BENTOV2_AUTH_REALM
BENTO_AGGREGATION_CLIENT_ID=aggregation
BENTO_AGGREGATION_CLIENT_SECRET= # TODO: SET ME WHEN DEPLOYING!

# - WES Client ID/secret; client within BENTOV2_AUTH_REALM
BENTO_WES_CLIENT_ID=wes
BENTO_WES_CLIENT_SECRET= # TODO: SET ME WHEN DEPLOYING!

# - Grafana Client ID/secret; client within BENTOV2_AUTH_REALM
BENTO_GRAFANA_CLIENT_ID=grafana
BENTO_GRAFANA_CLIENT_SECRET=
BENTO_GRAFANA_CLIENT_SECRET= # TODO: SET ME WHEN DEPLOYING IF GRAFANA IS ENABLED!
# ---------------------------------------------------------------------

BENTO_WEB_CUSTOM_HEADER=
Expand Down
6 changes: 5 additions & 1 deletion etc/bento_dev.env
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ BENTO_GATEWAY_USE_TLS='true'
BENTO_BEACON_ENABLED='true'
BENTO_BEACON_UI_ENABLED='true'
BENTO_CBIOPORTAL_ENABLED='false'
BENTO_MONITORING_ENABLED='false'
BENTO_GOHAN_ENABLED='true'
BENTO_MONITORING_ENABLED='false'

# - Switch to enable French translation in Bento Public
BENTO_PUBLIC_TRANSLATED='true'
Expand Down Expand Up @@ -51,6 +51,10 @@ BENTOV2_AUTH_ADMIN_PASSWORD=
BENTOV2_AUTH_TEST_USER=
BENTOV2_AUTH_TEST_PASSWORD=

# - Aggregation/Beacon client ID/secret; client within BENTOV2_AUTH_REALM
BENTO_AGGREGATION_CLIENT_ID=aggregation
BENTO_AGGREGATION_CLIENT_SECRET=

# - WES Client ID/secret; client within BENTOV2_AUTH_REALM
BENTO_WES_CLIENT_ID=wes
BENTO_WES_CLIENT_SECRET=
Expand Down
4 changes: 4 additions & 0 deletions etc/default_config.env
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ BENTO_BEACON_ENABLED='true'
BENTO_BEACON_UI_ENABLED='true'
BENTO_CBIOPORTAL_ENABLED='false'
BENTO_GOHAN_ENABLED='true'
BENTO_MONITORING_ENABLED='false'

# - Switch to enable French translation in Bento Public
BENTO_PUBLIC_TRANSLATED='true'
Expand Down Expand Up @@ -78,6 +79,9 @@ BENTOV2_AUTH_TEST_PASSWORD=
# - Auth (Keycloak) DB credentials
BENTO_AUTH_DB_PASSWORD=
BENTO_AUTHZ_DB_PASSWORD=
# - Aggregation/Beacon client ID/secret; secret to be filled by local.env - client within BENTOV2_AUTH_REALM
BENTO_AGGREGATION_CLIENT_ID=aggregation
BENTO_AGGREGATION_CLIENT_SECRET=
# - cBioPortal Client ID/secret; secret to be filled by local.env - client within BENTOV2_AUTH_REALM
BENTO_CBIOPORTAL_CLIENT_ID=cbioportal
BENTO_CBIOPORTAL_CLIENT_SECRET=
Expand Down
4 changes: 2 additions & 2 deletions lib/aggregation/docker-compose.aggregation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ services:
- BENTO_DEBUG=False
- USE_GOHAN=true
- CORS_ORIGINS=${BENTO_CORS_ORIGINS}
- KATSU_URL=${BENTOV2_PORTAL_PUBLIC_URL}/api/metadata/
- SERVICE_REGISTRY_URL=${BENTOV2_PUBLIC_URL}/api/service-registry/
- KATSU_URL=${BENTO_KATSU_URL}/
- SERVICE_REGISTRY_URL=${BENTO_SERVICE_REGISTRY_URL}/
- BENTO_AUTHZ_SERVICE_URL
networks:
- aggregation-net
Expand Down
12 changes: 7 additions & 5 deletions lib/beacon/docker-compose.beacon.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,28 @@ services:
container_name: ${BENTO_BEACON_CONTAINER_NAME}
environment:
- BENTO_UID
- GOHAN_BASE_URL=${BENTO_BEACON_GOHAN_BASE_URL}
- GOHAN_BASE_URL=${BENTO_GOHAN_URL}
- KATSU_TIMEOUT=${BENTO_BEACON_KATSU_TIMEOUT}
- KATSU_BASE_URL=http://${BENTOV2_KATSU_CONTAINER_NAME}:${BENTOV2_KATSU_INTERNAL_PORT}
- KATSU_BASE_URL=${BENTO_KATSU_URL}
- GOHAN_TIMEOUT=${BENTO_BEACON_GOHAN_TIMEOUT}
- BENTO_BEACON_INTERNAL_PORT
- INTERNAL_PORT=${BENTO_BEACON_INTERNAL_PORT}
- BENTO_BEACON_EXTERNAL_PORT
- BENTO_BEACON_DEBUGGER_INTERNAL_PORT
- BENTO_BEACON_DEBUGGER_EXTERNAL_PORT
- CONFIG_ABSOLUTE_PATH=/config/
- OIDC_ISSUER=${BENTO_BEACON_OIDC_ISSUER}
- CLIENT_ID=${BENTOV2_AUTH_CLIENT_ID}
- BEACON_BASE_URL=${BENTOV2_PUBLIC_URL}/api/beacon
- BENTO_BEACON_VERSION=${BENTO_BEACON_VERSION}
- BENTO_PUBLIC_CLIENT_NAME
- BENTOV2_DOMAIN
- BENTOV2_PUBLIC_URL
- BENTO_BEACON_UI_ENABLED
- DRS_URL=${BENTO_DRS_URL}
# Authorization
- BENTO_AUTHZ_SERVICE_URL
- DRS_URL=${BENTOV2_PUBLIC_URL}/api/drs
- BENTO_OPENID_CONFIG_URL
- BEACON_CLIENT_ID=${BENTO_AGGREGATION_CLIENT_ID}
- BEACON_CLIENT_SECRET=${BENTO_AGGREGATION_CLIENT_SECRET}
volumes:
- ${BENTO_BEACON_CONFIG_DIR}:/config:ro
networks:
Expand Down
Loading
Loading