diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 939993500c43ffa137554a349f58c3949a651a4e..da2e652173e422ff11754b8b690387246c1335c9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,7 +9,7 @@ build: only: - master script: - - docker-compose build + - docker-compose --project-name portail-data-documentation build --no-cache deploy: stage: deploy diff --git a/Dockerfile b/Dockerfile index 5fe2165537f674bad4d43993b076336c60b9b1b2..cdf170a882244dc611b08d200122ca9ac90c40b1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ WORKDIR /app # add the current directory to the container as /app ADD . /docs # Perform build and cleanup artifacts -RUN pip install mkdocs && pip install mkdocs-material +RUN pip install mkdocs && pip install mkdocs-material && pip install plantuml-markdown # Set working directory WORKDIR /docs diff --git a/docs/architecture/services/authentication.md b/docs/architecture/services/authentication.md index 1c80f37db372d4f9c6763fddc176f61f393c0bfc..3dc331505c1586df2942981241657e6ec6459991 100644 --- a/docs/architecture/services/authentication.md +++ b/docs/architecture/services/authentication.md @@ -22,21 +22,21 @@ The entrypoint of the service is a REST API provided by a [NestJS](https://githu ## API documentation -NestJS provides a swagger module that can be easily integrated. Using specific annotations alongside your endpoints declaration, this module will automatically generates a swagger documentation, reachable at `/api-docs`. +NestJS provides a [swagger module](https://docs.nestjs.com/recipes/swagger) that can be easily integrated. Using specific annotations alongside your endpoints declaration, this module will automatically generates a swagger documentation, reachable at `/api-doc`. ## Service health -NestJS provides a [health module](https://github.com/nestjs/terminus) based on Terminus, that gives you the opportunity to declare predifined or custom health indicators. It exposes the health status of the service at `/health`. +NestJS provides a [health module](https://github.com/nestjs/terminus) based on Terminus, that gives you the opportunity to declare predefined or custom health indicators. It exposes the health status of the service at `/health`. This service will return a `200` http status code when all indicators are healthy. Otherwise it will return a `503` http status code. -For this service we declared two health indicators that: +For this service we declared two health indicators that verify that: * the Kong API gateway is up * the legacy authentication middleware is up ## Stats We are using a Node module called [swagger-stats](http://swaggerstats.io/). -It traces API calls, monitors API performance and usage statistics. It exposes the metrics in different formats, such as Prometheus format, so you may use Prometheus and Graphana for API monitoring and alterting. +It traces API calls, monitors API performance and usage statistics. It exposes the metrics in different formats, such as Prometheus format, so you may use Prometheus and Graphana for API monitoring and alerting. Those metrics are available at `/swagger-stats/metrics`. For more information about this module, visit the [official swagger-stat page](http://swaggerstats.io/docs.html). diff --git a/docs/architecture/services/legacy-auth-middleware.md b/docs/architecture/services/legacy-auth-middleware.md index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..734b582816036c2a4f1877ac2b8ec0ba95fd8d37 100644 --- a/docs/architecture/services/legacy-auth-middleware.md +++ b/docs/architecture/services/legacy-auth-middleware.md @@ -0,0 +1,42 @@ + +# Legacy Authentication middleware + +## What it does + + + +## How it works + + + +The entrypoint of the service is a REST API provided by a [NestJS](https://github.com/nestjs/nest) application. + +<!-- It depends on two other services: + +* The Legacy Authentication Middleware to verify the identity of the user and retrieve its profile (called through our api gateway: Kong) +* The Admin API of Kong to get the user specific secrets in order to sign the JSON Web Tokens --> + +## API documentation + +NestJS provides a [swagger module](https://docs.nestjs.com/recipes/swagger) that can be easily integrated. Using specific annotations alongside your endpoints declaration, this module will automatically generates a swagger documentation, reachable at `/api-doc`. + +## Service health + +NestJS provides a [health module](https://github.com/nestjs/terminus) based on Terminus, that gives you the opportunity to declare predefined or custom health indicators. It exposes the health status of the service at `/health`. +This service will return a `200` http status code when all indicators are healthy. Otherwise it will return a `503` http status code. + +<!-- For this service we declared two health indicators that verify that: +* the Kong API gateway is up +* the legacy authentication middleware is up --> + +## Stats + +We are using a Node module called [swagger-stats](http://swaggerstats.io/). +It traces API calls, monitors API performance and usage statistics. It exposes the metrics in different formats, such as Prometheus format, so you may use Prometheus and Graphana for API monitoring and alerting. +Those metrics are available at `/swagger-stats/metrics`. + +For more information about this module, visit the [official swagger-stat page](http://swaggerstats.io/docs.html). + +## Docker +It is possible to run this service using Docker containers, using the `docker-compose.yml` and `Dockerfile` files. +For more information, refer to the project [legacy-auth-middleware][add a link] \ No newline at end of file diff --git a/docs/architecture/services/mail.md b/docs/architecture/services/mail.md index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f74485404ba624e4e2ac4a76cc578759b0ac67e0 100644 --- a/docs/architecture/services/mail.md +++ b/docs/architecture/services/mail.md @@ -0,0 +1,36 @@ +# Mail service + +## What it does + +This service allow to deliver mails to any email address from the address specified in the configuration. It also provides two particular endpoints, one for the user to give a feedback and another one for general contact purpose. Those endpoints will both send an email to the admin address specified in the configuration. + +## How it works + + + +The entrypoint of the service is a REST API provided by a [NestJS](https://github.com/nestjs/nest) application. The service builds email bodies based on the information it receives and on the provided HTML templates. It then format a JSON with all the properties (to, from, body...) expected by an SMTP server to correctly send an email. + +However the service does not send this JSON directly to the distant SMTP server. Indeed as a connection failure might occure, we chose to persist this object in a RabbitMQ queue. Then a small worker written in Node.js will consume the messages from the queue and send it to the SMTP server if correctly formatted. The messages will be removed (acknoledged) from the queue only if the SMTP received the message. + +## API documentation + +NestJS provides a [swagger module](https://docs.nestjs.com/recipes/swagger) that can be easily integrated. Using specific annotations alongside your endpoints declaration, this module will automatically generates a swagger documentation, reachable at `/api-doc`. + +## Service health + +NestJS provides a [health module](https://github.com/nestjs/terminus) based on Terminus, that gives you the opportunity to declare predefined or custom health indicators. It exposes the health status of the service at `/health`. +This service will return a `200` http status code when all indicators are healthy. Otherwise it will return a `503` http status code. + +For this service we declared an health indicator that verify that the connection to the RabbitMQ is available. + +## Stats + +We are using a Node module called [swagger-stats](http://swaggerstats.io/). +It traces API calls, monitors API performance and usage statistics. It exposes the metrics in different formats, such as Prometheus format, so you may use Prometheus and Graphana for API monitoring and alerting. +Those metrics are available at `/swagger-stats/metrics`. + +For more information about this module, visit the [official swagger-stat page](http://swaggerstats.io/docs.html). + +## Docker +It is possible to run this service using Docker containers, using the `docker-compose.yml` and `Dockerfile` files. +For more information, refer to the project [service-email][add a link] \ No newline at end of file diff --git a/docs/architecture/services/media-library.md b/docs/architecture/services/media-library.md index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..152c31f10de45d9ec14ee29701f407fb16126627 100644 --- a/docs/architecture/services/media-library.md +++ b/docs/architecture/services/media-library.md @@ -0,0 +1,40 @@ +# Media library service + +## What it does + +This service allows you to upload a file on the [Minio](https://min.io/) instance (compatible with S3) of your choice. The file will be stored in the bucket defined in the configuration of the service. + +## How it works + + + +The entrypoint of the service is a REST API provided by a [NestJS](https://github.com/nestjs/nest) application. The service uses the [Javascript MinIO SDK](https://docs.min.io/docs/javascript-client-quickstart-guide.html) to interact with a running instance of Minio. + +Before uploading the file, it makes sure that the specified bucket is created. If this is not the case, it creates it with a `public read access`. + +The files are folded in sub-buckets as following `/<specified-bucket-name>/<year-YYYY>/<month-MM>/`. + +The uploaded file keep its original name but is prefixed by an md5 computed based on its content witch gives the following pattern for file names: `<md5>-<original-name>`. This means that if we upload twice the exact same file, with the same name there will be only one file stored in MinIO. + +## API documentation + +NestJS provides a [swagger module](https://docs.nestjs.com/recipes/swagger) that can be easily integrated. Using specific annotations alongside your endpoints declaration, this module will automatically generates a swagger documentation, reachable at `/api-doc`. + +## Service health + +NestJS provides a [health module](https://github.com/nestjs/terminus) based on Terminus, that gives you the opportunity to declare predefined or custom health indicators. It exposes the health status of the service at `/health`. +This service will return a `200` http status code when all indicators are healthy. Otherwise it will return a `503` http status code. + +For this service we implemented a custom health indicator that checks the connection to MinIO giving the total number of buckets when the connection is succesful. + +## Stats + +We are using a Node module called [swagger-stats](http://swaggerstats.io/). +It traces API calls, monitors API performance and usage statistics. It exposes the metrics in different formats, such as Prometheus format, so you may use Prometheus and Graphana for API monitoring and alerting. +Those metrics are available at `/swagger-stats/metrics`. + +For more information about this module, visit the [official swagger-stat page](http://swaggerstats.io/docs.html). + +## Docker +It is possible to run this service using Docker containers, using the `docker-compose.yml` and `Dockerfile` files. +For more information, refer to the project [service-media-library][add a link] \ No newline at end of file diff --git a/docs/architecture/services/organizations.md b/docs/architecture/services/organizations.md index f04d41c4e3057f307cd29b2e89d20c9de770656e..0637a0931ba5aeec7ff31ca162fa82c1bdfb6f5c 100644 --- a/docs/architecture/services/organizations.md +++ b/docs/architecture/services/organizations.md @@ -1,7 +1,5 @@ # Organizations service - - ## What it does This service provides a list of organizations with different information about it (such as description, logo..etc). In our application, one organization is usually a provider of data, used in the Portal Open Data. It can be a public actor or a private one. @@ -15,11 +13,11 @@ The entrypoint of the service is a REST API provided by a [NestJS](https://githu ## API documentation -NestJS provides a swagger module that can be easily integrated. Using specific annotations alongside your endpoints declaration, this module will automatically generates a swagger documentation, reachable at `/api-doc`. +NestJS provides a [swagger module](https://docs.nestjs.com/recipes/swagger) that can be easily integrated. Using specific annotations alongside your endpoints declaration, this module will automatically generates a swagger documentation, reachable at `/api-doc`. ## Service health -NestJS provides a [health module](https://github.com/nestjs/terminus) based on Terminus, that gives you the opportunity to declare predifined or custom health indicators. It exposes the health status of the service at `/health`. +NestJS provides a [health module](https://github.com/nestjs/terminus) based on Terminus, that gives you the opportunity to declare predefined or custom health indicators. It exposes the health status of the service at `/health`. This service will return a `200` http status code when all indicators are healthy. Otherwise it will return a `503` http status code. For this service we declared an health indicator that verifies that it can connect to the database. @@ -27,7 +25,7 @@ For this service we declared an health indicator that verifies that it can conne ## Stats We are using a Node module called [swagger-stats](http://swaggerstats.io/). -It traces API calls, monitors API performance and usage statistics. It exposes the metrics in different formats, such as Prometheus format, so you may use Prometheus and Graphana for API monitoring and alterting. +It traces API calls, monitors API performance and usage statistics. It exposes the metrics in different formats, such as Prometheus format, so you may use Prometheus and Graphana for API monitoring and alerting. Those metrics are available at `/swagger-stats/metrics`. For more information about this module, visit the [official swagger-stat page](http://swaggerstats.io/docs.html). diff --git a/docs/architecture/services/resources.md b/docs/architecture/services/resources.md index 836f9f450ad32c1ea8321fff260041b4728849cf..2b65ea858fe30c5c43a12eae2d1084e65611456d 100644 --- a/docs/architecture/services/resources.md +++ b/docs/architecture/services/resources.md @@ -17,11 +17,11 @@ The entrypoint of the service is a REST API provided by a [NestJS](https://githu ## API documentation -NestJS provides a swagger module that can be easily integrated. Using specific annotations alongside your endpoints declaration, this module will automatically generates a swagger documentation, reachable at `/api-doc`. +NestJS provides a [swagger module](https://docs.nestjs.com/recipes/swagger) that can be easily integrated. Using specific annotations alongside your endpoints declaration, this module will automatically generates a swagger documentation, reachable at `/api-doc`. ## Service health -NestJS provides a [health module](https://github.com/nestjs/terminus) based on Terminus, that gives you the opportunity to declare predifined or custom health indicators. It exposes the health status of the service at `/health`. +NestJS provides a [health module](https://github.com/nestjs/terminus) based on Terminus, that gives you the opportunity to declare predefined or custom health indicators. It exposes the health status of the service at `/health`. This service will return a `200` http status code when all indicators are healthy. Otherwise it will return a `503` http status code. For this service we declared an health indicator that verifies that it can connect to the database. @@ -29,7 +29,7 @@ For this service we declared an health indicator that verifies that it can conne ## Stats We are using a Node module called [swagger-stats](http://swaggerstats.io/). -It traces API calls, monitors API performance and usage statistics. It exposes the metrics in different formats, such as Prometheus format, so you may use Prometheus and Graphana for API monitoring and alterting. +It traces API calls, monitors API performance and usage statistics. It exposes the metrics in different formats, such as Prometheus format, so you may use Prometheus and Graphana for API monitoring and alerting. Those metrics are available at `/swagger-stats/metrics`. For more information about this module, visit the [official swagger-stat page](http://swaggerstats.io/docs.html). diff --git a/docs/assets/kong-acl-plugin.PNG b/docs/assets/kong-acl-plugin.PNG new file mode 100644 index 0000000000000000000000000000000000000000..0897366e0e31cbe4724700e799e3db2fea58590d Binary files /dev/null and b/docs/assets/kong-acl-plugin.PNG differ diff --git a/docs/assets/kong-consumer-api-key.PNG b/docs/assets/kong-consumer-api-key.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f5590f087d2303a2b1638ee1c688672b2fbda1ca Binary files /dev/null and b/docs/assets/kong-consumer-api-key.PNG differ diff --git a/docs/assets/kong-consumer-groups.PNG b/docs/assets/kong-consumer-groups.PNG new file mode 100644 index 0000000000000000000000000000000000000000..4aafafccc32a17d02dce8fba34f93d5294025593 Binary files /dev/null and b/docs/assets/kong-consumer-groups.PNG differ diff --git a/docs/assets/kong-consumer.PNG b/docs/assets/kong-consumer.PNG new file mode 100644 index 0000000000000000000000000000000000000000..62be82619a50854fbeb924cd6251d66aede5ed07 Binary files /dev/null and b/docs/assets/kong-consumer.PNG differ diff --git a/docs/assets/kong-key-auth-plugin.PNG b/docs/assets/kong-key-auth-plugin.PNG new file mode 100644 index 0000000000000000000000000000000000000000..c5514755596e03698fa490930c3ffb1c144303d2 Binary files /dev/null and b/docs/assets/kong-key-auth-plugin.PNG differ diff --git a/docs/assets/mail-service.png b/docs/assets/mail-service.png new file mode 100644 index 0000000000000000000000000000000000000000..8729bfa95ca0ba053de7fc93efe1c81dae7db2db Binary files /dev/null and b/docs/assets/mail-service.png differ diff --git a/docs/assets/media-library-service.png b/docs/assets/media-library-service.png new file mode 100644 index 0000000000000000000000000000000000000000..b13811342853ec729e33b309c3349d09b7f8fae9 Binary files /dev/null and b/docs/assets/media-library-service.png differ diff --git a/docs/miscellaneous/authentication&authorization.md b/docs/miscellaneous/authentication&authorization.md new file mode 100644 index 0000000000000000000000000000000000000000..fe50108f49646411e5f745e9372d4cec24b73ecf --- /dev/null +++ b/docs/miscellaneous/authentication&authorization.md @@ -0,0 +1,381 @@ +In the context of the "portail Data", we needed an authentication/authorization system in order to control and restrict the access of some ressources. + +There is an existing system that let a user authenticate and then access or not some restricted access dataset. However, it does not implement those security features in a modern and very secure way. For exemple, to get the resources accessible by a user we need to pass its username and password. Obviously we cannot just store and pass the user's unencrypted credentials everytime we need it. To address this problem, we developped a middleware that implements a more modern authentication system using features of our API gateway and the legacy service to generate JSON Web Token. + +In the following sections we will explain in more details what as been implemented. + +## Authentication + +There are two kind of entities that can be authenticated: user and services. + +### Authenticating a user + +Lets explain step by step what is going on from the user account creation to the when he/she lists its accessible resources. + +```plantuml +@startuml + +!define BLACK #333745 +!define RED #d5232a +!define GREEN #37A77C + +' Base Setting +skinparam BackgroundColor transparent + +skinparam Sequence { + ArrowThickness 1 + ArrowColor RED + LifeLineBorderColor GREEN + ParticipantBorderThickness 1 +} +skinparam Participant { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +skinparam note { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +participant "Front" as front +participant "Middleware Legacy Auth" as middle + + group Get Public Key + front -> middle : <b>GET</b> /publicKey + front <-- middle : { publicKey } + end + +@enduml +``` +Before anything, the front web application has to retrieve the public encryption key from the middleware. It will use it to encrypt the password entered by the user when creating its account but also when logging in. This key is part of a public/private key generated by the middleware when it starts up. + +```plantuml +@startuml + +!define BLACK #333745 +!define RED #d5232a +!define GREEN #37A77C + +' Base Setting +skinparam BackgroundColor transparent + +skinparam Sequence { + ArrowThickness 1 + ArrowColor RED + LifeLineBorderColor GREEN + ParticipantBorderThickness 1 +} +skinparam Participant { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +skinparam note { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +participant "Front" as front +participant "Middleware Legacy Auth" as middle +participant "Email Service" as email + +group User creation + front -> middle : <b>POST</b> /user + note over middle : Set token in redis with ttl 24h + middle -> email : email : <b>POST</b> /email/send (body contains account validation link) + middle <-- email : void + front <-- middle : void +end +@enduml +``` + +When a user has entered and submitted its information, the account is not directly created. We require the user to verify its email address. To do so the middleware stores temporarily the user information in redis store as a key/value pair. The key is a generated unique Uuid4 token. This key/value pair is valid for 24h. + +then, the middleware formats an email containing a link to a particular page of the front web application that includes the Uuid token. + +Finally it transfers the email to the email service that will handle the delivery job. + +```plantuml +@startuml + +!define BLACK #333745 +!define RED #d5232a +!define GREEN #37A77C + +' Base Setting +skinparam BackgroundColor transparent + +skinparam Sequence { + ArrowThickness 1 + ArrowColor RED + LifeLineBorderColor GREEN + ParticipantBorderThickness 1 +} +skinparam Participant { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +skinparam note { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +participant "Front" as front +participant "Middleware Legacy Auth" as middle +participant "Email Service" as email +participant "Legacy Auth (Neogeo)" as django + +group Validate User creation + front -> middle : <b>POST</b> /user/validateAccount + note over middle : Validate token existance in redis + middle -> django : <b>POST</b> /add_user/ + middle <-- django : Ok + note over middle : Remove token from redis + front <-- middle : void +end + +@enduml +``` + +When the user receives the "account validation" email, he/she is invited to click the link. This will open the web application that will get the Uuid4 token from the url and call a validate account endpoint of the middleware. + +If the token is still in Redis, then the middleware can process with the account creation calling the legacy Auth service. + +```plantuml +@startuml + +!define BLACK #333745 +!define RED #d5232a +!define GREEN #37A77C + +' Base Setting +skinparam BackgroundColor transparent + +skinparam Sequence { + ArrowThickness 1 + ArrowColor RED + LifeLineBorderColor GREEN + ParticipantBorderThickness 1 +} +skinparam Participant { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +skinparam note { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +participant "Front" as front +participant "Authentication Service" as auth +participant "Middleware Legacy Auth" as middle +participant "Legacy Auth (Neogeo)" as django +participant "Email Service" as email +participant "Kong" as kong + +group Login + front -> auth : <b>POST</b> /login/legacy + auth -> middle : <b>POST</b> /user/login + middle -> django : <b>POST</b> /get_user/ + middle <-- django : { userInfo } + middle --> auth : { userInfo with encrypted password as authzKey} + auth -> kong : <b>PUT</b> /consumers/:email + auth <-- kong : Ok + auth -> kong : <b>GET or POST</b> /consumers/:email/jwt (POST if no creadetials exist for this user) + auth <-- kong : { credentials } + front <-- auth : { token: jwt } +end + +@enduml +``` + +Once the account creation done, the user can log in with its credentials. The front sends the username and encrypted password to the authentication service. + +This authentication service will then start a process of couple steps: +* Verify the user identity transfering the credentials to the middleware which will unencrypt the password and call the legacy authentication service to get user info. If the credentials are correct the authentication service will receive the information of the user profil. +* Once the profile verified, the authentication service will create the user identity in our API Gateway (Kong) (if not already existing). This is referenced as a [consumer](https://docs.konghq.com/0.14.x/admin-api/#consumer-object) in the API Gateway documentation. +* Based on the created consumer and thanks to the [JWT plugin](https://docs.konghq.com/hub/kong-inc/jwt/) of Kong, the authentication service will get the JWT Credentials of the user. Those are per user credentials containing a public and private key. If the user does not have credentials yet the authentication service will generate them using the appropriate endpoint of the Kong JWT plugin. +* The service generates a unique random Uuid4 that we will call the xsrf token +* At this point, the authentication service get everything it needs to generate authentication pieces for the user. Using the credentials coming from Kong it will sign a JSON Web Token containing some of the User info (firstname, lastname, username, email) as well as the user encrypted password and the xsrf token. +* Finally the authentication service will return a response to front application with the xsrf token and the user info in the body. It will also set a cookie `access_token` containing the JWT for the domaine name hosting the application. + +```plantuml +@startuml + +!define BLACK #333745 +!define RED #d5232a +!define GREEN #37A77C + +' Base Setting +skinparam BackgroundColor transparent + +skinparam Sequence { + ArrowThickness 1 + ArrowColor RED + LifeLineBorderColor GREEN + ParticipantBorderThickness 1 +} +skinparam Participant { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +skinparam note { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +participant "Front" as front +participant "Authentication Service" as auth +participant "Middleware Legacy Auth" as middle +participant "Legacy Auth (Neogeo)" as django +participant "Email Service" as email +participant "Kong" as kong + +group Login + front -> auth : <b>POST</b> /login/legacy + auth -> middle : <b>POST</b> /user/login + middle -> django : <b>POST</b> /get_user/ + middle <-- django : { userInfo } + middle --> auth : { userInfo with encrypted password as authzKey} + auth -> kong : <b>PUT</b> /consumers/:email + auth <-- kong : Ok + auth -> kong : <b>GET or POST</b> /consumers/:email/jwt (POST if no creadetials exist for this user) + auth <-- kong : { credentials } + front <-- auth : { token: jwt } +end + +@enduml +``` + +At the end of this process, the front web application has the authentication pieces required to access restricted resources. Let's take the example of the user data accesses. + +```plantuml +@startuml + +!define BLACK #333745 +!define RED #d5232a +!define GREEN #37A77C + +' Base Setting +skinparam BackgroundColor transparent + +skinparam Sequence { + ArrowThickness 1 + ArrowColor RED + LifeLineBorderColor GREEN + ParticipantBorderThickness 1 +} +skinparam Participant { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +skinparam note { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +participant "Front" as front +participant "Kong" as kong +participant "Middleware Legacy Auth" as middle +participant "Legacy Auth (Neogeo)" as django + +group User Info + front -> middle : <b>GET</b> /user/resources + middle -> django : <b>POST</b> /get_user_service/ + middle <-- django : { userResources } + front <-- middle : { userResources } +end + +@enduml +``` + +When a user access the data accesses page, the web application makes a call to the middleware through the API gateway: Kong. The JWT plugin of Kong will verify that the request has a valid JWT (not expired, not modifed) in the dedicated cookie. If the failing case, Kong will return a `401` http error, otherwise it will proxify the request to the authentication service. + +Each endpoints that requires a user identity are protected by a "middleware". You can find the corresponding code in the `decode-jwt-payload.middleware.ts` file of our projects. The main role of this application middleware is to decode the JWT payload in order to get the user identity (username, encrypted password). + +However in order to get through the middleware and go on with the incoming request the following criteria must be met: +* the `x-anonymous-consumer` header value of the request must not be `true` (meaning that kong as identified an existing user) +* the request contains the two pieces of identity `JWT` and `xsrf-token` +* the xsrf-token present in the header is the same as the one present in the JWT payload +If one or more of those verifications fails the middleware will return a `401 Unauthenticated` error. + +If the get user resources request pass successfully those tests, the legacy middleware authentication will call the Legacy auth service and return the user resoures. + +### Authenticating a service + +In a micro-services architecture, it is very common that a particular service needs another one to accomplish a task. There could different way to implement this depending on the needs. In our most common cases the first service needs are direct response of the second service. Thus, we decided to use HTTP requests. Just as the web application calls a service through the api gateway, a service calls another one through the proxy of the API Gateway. + +Some HTTP endpoints might be secured and the service will need to authenticate it self to the other service. Obviously a service can't log in with its own credentials as a user would do. The authentication method for services is consequently a bit different and based on API Keys which is another authentication method supported by Kong. + +Each service that need to access protected endpoints will need to have its own key. You can use Kong admin API or [Konga](https://pantsel.github.io/konga/) that provides a GUI for the management of Kong in order to generate keys. In the following I will explain how to proceed using Konga interface. + +An API key is associated to a consumer, so the first step is to create a consumer that will represent the service. As a convention we decided to prefix the services related consumers by '__' which gives for example `__legacy-auth-middleware`. In the consumers section, we can create a new consumer and enter the username of our choice. + + + +Once the consumer is created, when clicking on its name, we can management its credentials, its groups and a couple more things. In the credentials section and under the API KEYS tab we can create new keys for this specific user. After clicking the create button, juste leave the key field empty if you want to let kong generate it for you. + + + +There we go, the service has its own API key! Now every time it needs to make a call to a restricted access endpoint, it will be able to pass along its identity using this key. Though, at this point kong does not know were to look for api keys. To remedy to that we need to configure a `key-auth` plugin. It can be specific to a service or a route but can also be global. + +Let's say we want a global plugin. In the plugin section, click the "add global plugins" button, and select `key-auth`. Then specify the name of the header where we will put the api key in key names. If you want this plugin blocking your request when you don't specify an api key you can add the id of your `ANONYMOUS` user. This means that when kong doesn't identify an existing user, it will transmit the request server with an `x-anonymous-consumer` header set to true. + + + +So now the service just need to pass a header `ApiKey:<the service api key>` when calling another service through kong to pass its identity. + +However specifying one by one which service is allowed to access a service endpoint is not very convenient, we were more interested in a group based approach. For example our authentication-middleware could belong to a `email-writter` group which would allow it to give send mail tasks to the email service. + +Thankfully kong consumers already support this functionnality. We will explain in the next section how we impleteded a group based authorization. + +## Authorization + +In the previous section we have seen how the identity of a user (or a service) is pass to a service through the API Gateway and how it can use it. Knowing the identity of the consumer was not sufficient in some cases. If I take the example of the organization service, we didn't really care about the specific identity of the user but we wanted to know whether the user was an admin or not: a group based authorization. + +First thing first let's see how to add a group to a consumer. Find the consumer in the list and click on it to see the details. Navigate to the group section. Click the add group button and enter the name of the group. The consumer now belongs to group. This works fboth for user related consumers or service related consumers. + + + +Then, we need to configure an Access Control List plugin in order for kong to pass the user groups to the upstream. The ACL plugin needs an authentication plugin (JWT plugin, key-auth plugin...) to have indentified an existing user to then get its groups. Go to the global plugin section, click the add plugin button and select `Acl` under security. We don't really want to whitelist or blacklist user here we just want to propagate the user's groups to the upstream server. As the plugin require one of the two fields to be filled, we basically just enter a fake user id under blacklist. + + + +At this point if a service receive an authenticated request it will find the user/service's groups in the following header: `x-consumer-groups`. + +Our services are developed using the frameword Nest.js. This framework comes with a concept call guards. A guard is basically a middleware that intercept the request and that will let it through only if it respect some conditions. In our case we need a group guard that would return a `403 Forbidden` error if the user does not belong to the required group. + +The corresponding code can be found in the `groups.guards.ts` file of the project that required this king of authorization (ex: email service). In order for this guard to be applied to our service, we declared it as a provider in the `app.module.ts` file as following. + +```ts +@Module({ + imports: [...], + controllers: [...], + providers: [ + { + provide: APP_GUARD, + useClass: GroupsGuard, + }, + ], +}) +export class AppModule { } +``` + +As we need this guard to work for any group it is used in combination with a custom decorator `@Groups` defined in the `groups.decorators.ts` file. Doing so, in the controller file, before the declaration of an endpoint we can specify `@Groups('emailWritter')` to restrict the access to users belonging to this group. Actually, 'emailWritter' is just the key that is used to get the real group name from the configuration of the service (please refer to the code). diff --git a/docs/miscellaneous/webapp-auth.md b/docs/miscellaneous/webapp-auth.md index b6175cb138fbb1020c874fd1f8a8ea4cc6f09e18..b78d4a3bb62dffbab26800ae40a6f9260910ca92 100644 --- a/docs/miscellaneous/webapp-auth.md +++ b/docs/miscellaneous/webapp-auth.md @@ -63,6 +63,42 @@ group Authentication with OIDC providers front <-- auth : [302] redirection to the appropriate url end end +``` + +```plantuml + +!define BLACK #333745 +!define RED #d5232a +!define GREEN #37A77C + +' Base Setting +skinparam BackgroundColor transparent + +skinparam Sequence { + ArrowThickness 1 + ArrowColor RED + LifeLineBorderColor GREEN + ParticipantBorderThickness 1 +} +skinparam Participant { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +skinparam note { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +participant "Front" as front +participant "Authentication Service" as auth +participant "Middleware Legacy Auth" as middle +participant "Legacy Auth (Neogeo)" as django +participant "Email Service" as email +participant "Kong" as kong +participant "OIDC Server" as oidc group Authentication with Django Server group Get Public Key @@ -163,7 +199,42 @@ group Authentication with Django Server front <-- middle : void end end +``` +```plantuml + +!define BLACK #333745 +!define RED #d5232a +!define GREEN #37A77C + +' Base Setting +skinparam BackgroundColor transparent + +skinparam Sequence { + ArrowThickness 1 + ArrowColor RED + LifeLineBorderColor GREEN + ParticipantBorderThickness 1 +} +skinparam Participant { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +skinparam note { + BackgroundColor #FFFFFF + BorderColor BLACK + FontColor BLACK +} + +participant "Front" as front +participant "Authentication Service" as auth +participant "Middleware Legacy Auth" as middle +participant "Legacy Auth (Neogeo)" as django +participant "Email Service" as email +participant "Kong" as kong +participant "OIDC Server" as oidc group Authorization with Django server group List User resources front -> middle : <b>POST</b> /user/resources diff --git a/material_theme_override/assets/images/favicon.ico b/material_theme_override/assets/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5619a8f1cf3db720725e00d80636e23de406e8de Binary files /dev/null and b/material_theme_override/assets/images/favicon.ico differ diff --git a/material_theme_override/assets/images/favicon.png b/material_theme_override/assets/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..2c1dfc65a0287f91abb83b5aa5d8c1924278ff5b Binary files /dev/null and b/material_theme_override/assets/images/favicon.png differ diff --git a/material_theme_override/assets/images/home_logo_data.svg b/material_theme_override/assets/images/home_logo_data.svg new file mode 100644 index 0000000000000000000000000000000000000000..6fbcc7636a1e1d2c4abbb93a640a0044548f2ed1 --- /dev/null +++ b/material_theme_override/assets/images/home_logo_data.svg @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="b64850fe-2e14-40d7-8c6c-d81e0fedf6b3" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 509 48.1" + style="enable-background:new 0 0 509 48.1;" xml:space="preserve"> +<style type="text/css"> + .Style_x0020_graphique_x0020_2{fill:#FFFFFF;} + .Style_x0020_graphique{fill:#E93232;} +</style> +<title>logo_data_alpha</title> +<path class="Style_x0020_graphique" d="M457.1,10h37.8c7.8,0,14.1,6.3,14.1,14.1c0,0,0,0,0,0l0,0c0,7.8-6.3,14.1-14.1,14.2h-37.8 + c-7.8-0.1-14.1-6.4-14.1-14.2l0,0C443,16.3,449.3,10,457.1,10L457.1,10z"/> +<path class="Style_x0020_graphique_x0020_2" d="M462,29.2h-1.9l-0.2-0.3l-0.7-2.1H455l-0.8,2.1l-0.2,0.3h-1.9l4-10.1h1.9L462,29.2z + M455.4,25.4h3.3l-1.3-3.4c0-0.2-0.1-0.3-0.1-0.5c-0.1-0.2-0.2-0.5-0.2-0.7c-0.1,0.2-0.2,0.5-0.2,0.7c-0.1,0.2-0.2,0.3-0.2,0.5 + L455.4,25.4z"/> +<path class="Style_x0020_graphique_x0020_2" d="M464.9,27.6h4.1v1.6h-5.9V19.1h1.8V27.6z"/> +<path class="Style_x0020_graphique_x0020_2" d="M472.3,25.6v3.6h-1.9V19.1h3.3c0.6,0,1.2,0,1.7,0.2l1.3,0.7c0.3,0.3,0.5,0.6,0.7,1 + c0.1,0.4,0.2,0.9,0.2,1.3c0,0.4-0.1,0.9-0.2,1.3c-0.1,0.4-0.4,0.8-0.8,1.1c-0.3,0.3-0.8,0.5-1.2,0.7c-0.5,0.2-1.1,0.2-1.7,0.2 + L472.3,25.6z M472.3,24.2h1.4l0.9-0.2l0.6-0.3l0.4-0.6c0.1-0.3,0.1-0.5,0.1-0.8c0-0.2,0-0.5-0.1-0.7c0-0.2-0.2-0.5-0.4-0.6 + c-0.1-0.2-0.4-0.3-0.6-0.4h-2.3V24.2z"/> +<path class="Style_x0020_graphique_x0020_2" d="M487.6,29.2h-1.9v-4.4H481v4.4h-1.9V19.1h1.9v4.3h4.7v-4.3h1.9V29.2z"/> +<path class="Style_x0020_graphique_x0020_2" d="M498.6,29.2h-1.9l-0.2-0.3l-0.7-2.1h-4.2l-0.8,2.1l-0.2,0.3h-1.9l4-10.1h1.9 + L498.6,29.2z M492,25.4h3.3L494,22c0-0.2-0.1-0.3-0.1-0.5c-0.1-0.2-0.2-0.5-0.2-0.7c-0.1,0.2-0.2,0.5-0.2,0.7 + c-0.1,0.2-0.2,0.3-0.2,0.5L492,25.4z"/> +<path class="Style_x0020_graphique" d="M24.5,36.5V0.1h-7.1v12c-1.1-0.4-2.6-0.8-4.5-0.8C5.8,11.3,1.3,16.6,1.3,25 + c0,8.5,5,13.5,13.1,13.5C18.7,38.5,22.4,37.5,24.5,36.5z M17.4,32.7c-0.7,0.2-1.6,0.4-3,0.4c-4,0-6-3.2-6-8.4c0-4.9,1.6-8.3,5.8-8.3 + c1.3,0,2.4,0.4,3.2,0.7V32.7z"/> +<path class="Style_x0020_graphique" d="M50.9,36.8V22.3c0-1.1,0-2.1-0.1-3.1c-0.6-5.4-4.1-8.1-10.3-8.1c-3.9,0-7.3,1-9.1,1.7 + l1.2,5.1c1.7-0.8,4.2-1.5,6.9-1.5c3.5,0,4.5,1.9,4.6,4.7c-0.6,0-1.7-0.1-2.6,0c-6.6,0.4-12,2.6-12,8.9c0,5.9,4.1,8.4,11,8.4 + C45,38.4,48.9,37.7,50.9,36.8z M44.2,33.1c-0.9,0.3-1.7,0.4-3.3,0.4c-2.8,0-4.6-1.1-4.6-3.7c0-3,2.3-3.9,5.1-4.2c1.1-0.1,2,0,2.8,0 + V33.1z"/> +<path class="Style_x0020_graphique" d="M72.8,37.2c-0.2-1.7-0.4-3.4-0.6-5.1c-1.2,0.6-2.5,0.8-3.8,0.7c-2.3-0.2-2.7-1.7-2.7-5.3 + V17.1h6.6v-5.4h-6.6V4.9h-7.1v6.9h-3.4v5.3h3.4c0,2.9,0,7.9,0.1,10.8c0.3,5.6,1.5,10.8,9.4,10.5C70.1,38.2,71.7,37.7,72.8,37.2z"/> +<path class="Style_x0020_graphique" d="M97.2,36.8V22.3c0-1.1,0-2.1-0.1-3.1c-0.6-5.4-4.1-8.1-10.3-8.1c-3.9,0-7.3,1-9.1,1.7 + l1.2,5.1c1.7-0.8,4.2-1.5,6.9-1.5c3.5,0,4.5,1.9,4.6,4.7c-0.6,0-1.7-0.1-2.6,0c-6.6,0.4-12,2.6-12,8.9c0,5.9,4.1,8.4,11,8.4 + C91.3,38.4,95.1,37.7,97.2,36.8z M90.4,33.1c-0.9,0.3-1.7,0.4-3.3,0.4c-2.8,0-4.6-1.1-4.6-3.7c0-3,2.3-3.9,5.1-4.2 + c1.1-0.1,2,0,2.8,0V33.1z"/> +<path class="Style_x0020_graphique" d="M110.5,34.2c0-2.5-1.9-4.3-4.3-4.3c-2.4,0-4.3,1.8-4.3,4.3c0,2.5,2,4.2,4.3,4.2 + C108.6,38.4,110.5,36.7,110.5,34.2z"/> +<path class="Style_x0020_graphique_x0020_2" d="M131.5,33.3c-1.1,0.8-3,1.5-5.1,1.5c-4.4,0-7.2-3.2-7.2-9.6c0-6.1,2.6-10.2,7.8-10.2 + c2.2,0,3.6,0.2,4.6,0.7V33.3z M135.3,37.5V13.6c-1.7-0.8-4.4-1.6-8.4-1.6c-7.6,0-11.9,5.5-11.9,13.2c0,8.2,4.5,12.5,10.7,12.5 + c2.8,0,4.8-0.9,5.8-1.4v1.6c0,2.4-0.7,4.1-2.2,5.2c-1.2,1.1-3,1.7-5.4,1.7c-2.4,0-4.9-0.7-6.3-1.4c-0.4,1.1-0.7,2.1-1,3.1 + c1.9,0.9,4.6,1.5,7.9,1.5C131.6,48,135.3,44.6,135.3,37.5z"/> +<path class="Style_x0020_graphique_x0020_2" d="M156.4,12.5c-1.2-0.2-2.8-0.3-4.3-0.3h-0.6c-3.4,0.1-5.8,0.9-7.5,1.7v24.3h3.9V16 + c0.6-0.3,1.9-0.8,3.7-0.8h0.7c1.2,0,2.2,0.1,3.2,0.4C155.9,14.6,156.1,13.5,156.4,12.5z"/> +<path class="Style_x0020_graphique_x0020_2" d="M175.1,35.1c-1.2,0.4-2.8,0.6-4.8,0.6c-3.8,0-6.1-1.4-6.1-5c0-4.1,3.1-5.3,6.9-5.8 + c0.6,0,1.2-0.1,1.7-0.1c0.9,0,1.7,0.1,2.4,0.1V35.1z M178.9,37.1V23.3c0-1,0-1.9,0-2.8c-0.1-5.6-3.5-8.4-9.1-8.4 + c-3.3,0-6,0.9-7.3,1.5l0.7,2.9c1.2-0.6,3.2-1.3,6.2-1.3c4.8,0,5.7,2.7,5.8,7.2c-0.7,0-1.8-0.1-2.9-0.1c-0.3,0-0.7,0-1,0 + c-6.2,0.5-10.9,2.9-10.9,8.6c0,5.2,3.6,7.8,9.6,7.8C173.7,38.6,177.1,37.9,178.9,37.1z"/> +<path class="Style_x0020_graphique_x0020_2" d="M205.7,38.1V23.6c0-5.4-0.6-11.6-9.6-11.6c-4.4,0-7.5,0.7-9.6,1.7v24.3h3.9V15.9 + c1-0.4,2.6-0.8,5.2-0.8c6,0,6.1,4.1,6.1,9.2v13.8H205.7z"/> +<path class="Style_x0020_graphique_x0020_2" d="M229.3,34.9c-0.9,0.4-2.3,0.7-4.6,0.7c-5.3,0-8-4-8-10.2c0-5.5,2-10.3,7.9-10.3 + c1.9,0,3.6,0.7,4.7,1.2V34.9z M233.2,37V0.6h-3.9v12.8c-1.2-0.5-3-1.2-5.2-1.2c-7,0-11.3,5.2-11.3,13.4c0,7.9,4.4,13.1,11.9,13.1 + C228.5,38.6,231.5,37.8,233.2,37z"/> +<path class="Style_x0020_graphique_x0020_2" d="M250.4,36.1c-3.4-1-4.2-1.5-4.2-9.3V0.6h-3.9V30c0,6.5,2.4,8.1,7.3,8.6L250.4,36.1z" + /> +<path class="Style_x0020_graphique_x0020_2" d="M273.5,12.5h-3.8c-1.7,6.5-3.2,12.1-5.2,18.1c-0.4,1.2-0.9,3.4-1.1,3.5 + c-0.3-0.7-0.7-2.1-1.2-3.6c-2.3-6.2-4.3-12.4-5.7-18.1h-4.2c2.5,8.7,5.8,17.5,9.3,25.6c-0.6,1.9-1.3,5-3.3,5c-0.9,0-1.7-0.5-2.9-1.2 + l-0.8,2.5c1,0.5,2.3,1.4,4.6,1.4c2.7,0,4-2.5,5.4-6.1C268,31.3,270.8,22.1,273.5,12.5z"/> +<path class="Style_x0020_graphique_x0020_2" d="M294.2,25.3c0,5.6-1.9,10.1-6.8,10.1c-4.9,0-6.9-4.6-6.9-10.1c0-5.5,2-10.3,6.9-10.3 + C292.2,15,294.2,19.8,294.2,25.3z M298.1,25.3c0-7.8-3.9-13.3-10.8-13.3c-6.9,0-10.8,5.5-10.8,13.3c0,7.8,3.9,13.3,10.8,13.3 + C294.2,38.6,298.1,33.1,298.1,25.3z"/> +<path class="Style_x0020_graphique_x0020_2" d="M325,38.1V23.6c0-5.4-0.6-11.6-9.6-11.6c-4.4,0-7.5,0.7-9.6,1.7v24.3h3.9V15.9 + c1-0.4,2.6-0.8,5.2-0.8c6,0,6.1,4.1,6.1,9.2v13.8H325z"/> +<path class="Style_x0020_graphique_x0020_2" d="M338.4,35.7c0-1.6-1.2-2.8-2.8-2.8c-1.6,0-2.8,1.2-2.8,2.8c0,1.6,1.2,2.8,2.8,2.8 + C337.2,38.5,338.4,37.3,338.4,35.7z"/> +<path class="Style_x0020_graphique_x0020_2" d="M360,37l-0.9-3c-1,0.6-2.6,1.3-4.8,1.3c-5.2,0-7.5-4.1-7.5-10.1 + c0-6.1,2.3-10.1,7.3-10.1c2.3,0,3.6,0.5,4.7,1.2c0.3-1,0.6-1.9,1-2.8c-1.2-0.7-3.3-1.5-6.2-1.5c-6.6,0-10.8,5.2-10.8,13.3 + c0,8.1,4.1,13.2,10.9,13.2C356.5,38.6,358.8,37.8,360,37z"/> +<path class="Style_x0020_graphique_x0020_2" d="M381.4,25.3c0,5.6-1.9,10.1-6.8,10.1c-4.9,0-6.9-4.6-6.9-10.1c0-5.5,2-10.3,6.9-10.3 + C379.5,15,381.4,19.8,381.4,25.3z M385.4,25.3c0-7.8-3.9-13.3-10.8-13.3c-6.9,0-10.8,5.5-10.8,13.3c0,7.8,3.9,13.3,10.8,13.3 + C381.5,38.6,385.4,33.1,385.4,25.3z"/> +<path class="Style_x0020_graphique_x0020_2" d="M426.6,38.1V23.6c0-5.2-0.3-11.6-8.8-11.6c-3.9,0-6.7,1.7-8.1,2.9 + c-1.5-1.8-3.8-2.9-7.3-2.9c-4.4,0-7.1,0.8-9.3,1.6v24.4h3.9V15.9c1-0.4,2.6-0.8,5-0.8c5.6,0,5.9,3.5,5.9,9.1v13.9h3.9V24.7 + c0-2.5-0.1-5.1-0.4-7.4c1.1-1.1,3.1-2.2,5.9-2.2c5.2,0,5.4,4,5.4,9.1v13.8H426.6z"/> +</svg> diff --git a/material_theme_override/partials/header.html b/material_theme_override/partials/header.html new file mode 100644 index 0000000000000000000000000000000000000000..0b2dff4ec7f98e3b1c8b2a72f4b7b7998d2755a7 --- /dev/null +++ b/material_theme_override/partials/header.html @@ -0,0 +1,35 @@ + {#- + This file was automatically generated - do not edit + -#} + <header class="md-header" data-md-component="header"> + <nav class="md-header-nav md-grid"> + <div class="md-flex"> + <div class="md-flex__cell md-flex__cell--shrink"> + <a href="https://data.alpha.grandlyon.com/en/accueil" title="{{ config.site_name }}" class="md-header-nav__button md-logo"> + + <img src="/assets/images/home_logo_data.svg" width="200" height="24"> </a> + </div> + <div class="md-flex__cell md-flex__cell--shrink"> + <label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label> + </div> + <div class="md-flex__cell md-flex__cell--stretch"> + <div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">{%- if config.site_name == page.title -%} {{ config.site_name }} {%- else -%} + <span class="md-header-nav__topic"> + {{- config.site_name -}} + </span> + <span class="md-header-nav__topic"> + {%- if page and page.meta and page.meta.title -%} {{- page.meta.title -}} {%- else -%} {{- page.title -}} {%- endif -%} + </span>{%- endif -%}</div></div> + <div class="md-flex__cell md-flex__cell--shrink">{%- if "search" in config["plugins"] -%} + <label class="md-icon md-icon--search md-header-nav__button" for="__search"> + + </label> {%- include "partials/search.html" -%} {%- endif -%} + </div> + {%- if config.repo_url -%}<div class="md-flex__cell md-flex__cell--shrink"> + <div class="md-header-nav__source">{%- include "partials/source.html" -%} + </div> + </div> + {%- endif -%} + </div> + </nav> + </header> \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 82a314b8daf0f585774975098a4ebd5038f73881..d3f79443217af215997ba8a3138d3f6a71e54296 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,10 +4,15 @@ site_author: MkDocs Team theme: name: 'material' + custom_dir: material_theme_override/ palette: primary: 'grey' accent: 'amber' +markdown_extensions: + - plantuml_markdown: + server: http://www.plantuml.com/plantuml + nav: - Home: index.md - Architecture Guide: @@ -17,13 +22,14 @@ nav: - CMS: architecture/cms.md - Monitoring: architecture/monitoring.md - Web-app: architecture/web-app.md - - Service: - - authentification: architecture/service/authentication.md - - organizations: architecture/service/organizations.md - - resources: architecture/service/resources.md + - Services: + - authentification: architecture/services/authentication.md + - organizations: architecture/services/organizations.md + - resources: architecture/services/resources.md - Elasticsearch: - - Indexer: architecture/service/elasticsearch/indexer.md + - Indexer: architecture/services/elasticsearch/indexer.md + - UML Diagrams: + - Webapp-auth: miscellaneous/webapp-auth.md - About: - Gitflow: miscellaneous/gitflow-ci-cd.md - VSCode: miscellaneous/vscode-settings.md - - Webapp: miscellaneous/webapp-auth.md