Skip to content

Commit 0d5d65a

Browse files
committed
Initial commit
- Initial open source release of eVaka
0 parents  commit 0d5d65a

File tree

1,710 files changed

+323026
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,710 files changed

+323026
-0
lines changed

.circleci/config.yml

+929
Large diffs are not rendered by default.

.gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto

.github/PULL_REQUEST_TEMPLATE.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#### Summary
2+
<!-- Describe the change, including rationale and design decisions (not just what but also why) -->
3+
4+
#### Dependencies
5+
<!-- Describe the dependencies the change has on other repositories, pull requests etc. -->
6+
7+
#### Testing instructions
8+
<!-- Describe how the change can be tested, e.g., steps and tools to use -->
9+
10+
#### Checklist for pull request creator
11+
<!-- Check that the necessary steps have been done before the PR is created -->
12+
13+
- [ ] The code is consistent with the existing code base
14+
- [ ] Tests have been written for the change (e2e, integration tests)
15+
- [ ] The change has been tested locally
16+
- [ ] The change conforms to the UX specifications
17+
- [ ] The code is self-documenting or has been documented sufficiently, e.g., in the README
18+
- [ ] The branch has been rebased against master before the PR was created
19+
20+
#### Checklist for pull request reviewer (copy to review text box)
21+
<!-- Check that the necessary steps have been done in the review. Copy the template beneath for the review. -->
22+
23+
```
24+
- [ ] All changes in all changed files have been reviewed
25+
- [ ] The code is consistent with the existing code base
26+
- [ ] Tests have been written for the change (e2e, integration tests)
27+
- [ ] The change has been tested locally
28+
- [ ] The change conforms to the UX specifications
29+
- [ ] The code is self-documenting or has been documented sufficiently, e.g., in the README
30+
- [ ] The PR branch has been rebased against master and force pushed if necessary before merging
31+
```

.github/dependabot.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Dependabot configuration: https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates#scheduleinterval
2+
3+
version: 2
4+
# NOTE: Gradle Kotlin support is still missing: https://github.com/dependabot/dependabot-core/issues/2238
5+
# NOTE: There's no "security updates only" for Docker: https://github.com/dependabot/dependabot-core/issues/1971
6+
# and there's no support for OS packages: https://github.com/dependabot/dependabot-core/issues/2129
7+
updates:
8+
- package-ecosystem: docker
9+
directory: "/evaka-base"
10+
schedule:
11+
interval: weekly
12+
- package-ecosystem: docker
13+
directory: "/proxy"
14+
schedule:
15+
interval: weekly

.gitignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# SPDX-FileCopyrightText: 2017-2020 City of Espoo
2+
#
3+
# SPDX-License-Identifier: LGPL-2.1-or-later
4+
5+
# OSX
6+
.DS_Store
7+
8+
# IDEs
9+
/.vscode/
10+
/.idea/

CONTRIBUTING.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!--
2+
SPDX-FileCopyrightText: 2017-2020 City of Espoo
3+
4+
SPDX-License-Identifier: LGPL-2.1-or-later
5+
-->
6+
7+
# Contribution guide
8+
9+
We appreciate your interest in contributing to this project.
10+
eVaka project is currently in a very active development phase. Due to this, the core development
11+
team may be unable to process or accept any contributions at this stage.
12+
13+
We will establish contribution guidelines regarding e.g. how to create pull requests, what code
14+
conventions to use etc. in the upcoming months. This file will be updated accordingly, once the
15+
team is capable of accepting contributions. Thank you.

LICENSE

+504
Large diffs are not rendered by default.

LICENSES/LGPL-2.1-or-later.txt

+468
Large diffs are not rendered by default.

README.md

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!--
2+
SPDX-FileCopyrightText: 2017-2020 City of Espoo
3+
4+
SPDX-License-Identifier: LGPL-2.1-or-later
5+
-->
6+
7+
# eVaka – ERP for early childhood education
8+
9+
This is eVaka – an ERP system developed for early childhood education in
10+
Finland. It is a web application developed using modern technologies and
11+
designed to be deployed in cloud environment.
12+
13+
**Caution:** eVaka is currently under very active development. At this
14+
point, it is not yet adviced to start developing or running your custom
15+
solution based on this project. Most likely, the project will evolve
16+
considerably before reaching more stable phase. Please refer to
17+
project's roadmap for further information regarding development plans.
18+
However, feel free to explore the project and try running it locally.
19+
20+
## How to get started
21+
22+
For development purposes, the application can be run locally on your
23+
development machine. See further instructions in the
24+
[README](compose/README.md) file of the `compose/` directory.
25+
26+
The applications consists of several sub-projects:
27+
28+
- [`apigw`](apigw/) – API gateway, responsible for handling authentication and routing requests to backend services
29+
- [`frontend`](frontend/) – User interfaces for the citizens and
30+
employees
31+
- [`service`](service/) – All the business logic, e.g. handling early
32+
childhood education application process and daily work in daycare
33+
- [`message-service`](message-service/) – Service for sending messages
34+
via [Suomi.fi Messages](https://www.suomi.fi/messages) service
35+
- [`compose`](compose/) – Tooling for running application in local
36+
development environment, using e.g. [Docker](https://www.docker.com)
37+
- [`proxy`](proxy/)[Nginx](https://www.nginx.com) image for proxying
38+
fronetend requests to services
39+
- [`service-lib`](service-lib/) – A common library shared with `service` and
40+
`message-service` projects
41+
42+
## Contributing
43+
44+
Please refer to [CONTRIBUTING.md](CONTRIBUTING.md) for further
45+
instructions regarding code contributions.
46+
47+
## Security issues
48+
49+
In case you notice any information security related issue in our
50+
services, or you have an idea how to improve information security,
51+
please contact us by email at [tietoturva@espoo.fi](tietoturva@espoo.fi)
52+
53+
## License
54+
55+
eVaka is published under **LGPL-2.1-or-later** license. Please refer to
56+
[LICENSE](LICENSE) for further details.
57+
58+
## Contact information

SECURITY.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!--
2+
SPDX-FileCopyrightText: 2017-2020 City of Espoo
3+
4+
SPDX-License-Identifier: LGPL-2.1-or-later
5+
-->
6+
7+
# Security Policy
8+
9+
## Reporting a Vulnerability
10+
11+
If you notice anything that may affect the information security of our services
12+
or you have ideas on how to improve information security, please contact
13+
**[tietoturva@espoo.fi](mailto:tietoturva@espoo.fi)**.

apigw/.dockerignore

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# SPDX-FileCopyrightText: 2017-2020 City of Espoo
2+
#
3+
# SPDX-License-Identifier: LGPL-2.1-or-later
4+
5+
*
6+
!dist
7+
!config/certificates
8+
!package.json
9+
!yarn.lock
10+
!entrypoint.sh

apigw/.gitignore

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# SPDX-FileCopyrightText: 2017-2020 City of Espoo
2+
#
3+
# SPDX-License-Identifier: LGPL-2.1-or-later
4+
5+
node_modules/
6+
.cache/
7+
.idea/
8+
dist/
9+
*~
10+
*.bak
11+
*.log
12+
*.swp
13+
*.tmp
14+
*.iml
15+
.npmrc
16+
build/
17+
test-reports/
18+
.vscode

apigw/Dockerfile

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# SPDX-FileCopyrightText: 2017-2020 City of Espoo
2+
#
3+
# SPDX-License-Identifier: LGPL-2.1-or-later
4+
5+
FROM evaka-base:latest
6+
7+
ARG DEBIAN_FRONTEND=noninteractive
8+
9+
USER root
10+
RUN set -euxo pipefail \
11+
&& apt-get update && apt-get -y --no-install-recommends install \
12+
curl=7.68.* \
13+
gnupg2=2.2.* \
14+
&& curl -sL https://deb.nodesource.com/setup_12.x | bash - \
15+
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
16+
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
17+
&& apt-get update && apt-get -y --no-install-recommends install \
18+
nodejs \
19+
yarn=1.22.* \
20+
&& rm -rf /var/lib/apt/lists/*
21+
22+
USER evaka
23+
WORKDIR /home/evaka
24+
25+
ENV NODE_ENV production
26+
COPY --chown=evaka:evaka . .
27+
RUN yarn install --production --frozen-lockfile && \
28+
yarn cache clean
29+
30+
# Add build and commit environment variables and labels
31+
# for tracing the image to the commit and build from which the image has been built.
32+
ARG build=none
33+
ARG commit=none
34+
ENV APP_BUILD "$build"
35+
ENV APP_COMMIT "$commit"
36+
LABEL fi.espoo.build="$build" \
37+
fi.espoo.commit="$commit"
38+
39+
ENTRYPOINT ["./entrypoint.sh"]
40+
CMD ["node", "dist/index.js"]

apigw/README.md

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<!--
2+
SPDX-FileCopyrightText: 2017-2020 City of Espoo
3+
4+
SPDX-License-Identifier: LGPL-2.1-or-later
5+
-->
6+
7+
# evaka-api-gateways
8+
9+
Gateway between eVaka frontends and backend services
10+
11+
* enduser gateway
12+
* internal gateway
13+
14+
## Requirements
15+
16+
* Node version 10.16
17+
* Yarn version 1.16
18+
19+
The service requires redis running on port 6379. Easiest way is to run it with [compose](../compose/README.md) command
20+
21+
```bash
22+
docker-compose up -d redis
23+
```
24+
25+
## Development
26+
27+
Install dependencies
28+
29+
```bash
30+
yarn
31+
```
32+
33+
Start development server with hot reloading. Requires running backend services.
34+
35+
```bash
36+
yarn dev
37+
```
38+
39+
Run tests
40+
41+
```bash
42+
yarn test
43+
```
44+
45+
Lint with auto-fix
46+
47+
```bash
48+
yarn lint
49+
yarn lint-fix
50+
```
51+
52+
## Generated JWTs for local testing
53+
54+
If you need a JWT to test a service API locally, you can generate tokens for each gateway with:
55+
56+
```bash
57+
NODE_ENV=local npx ts-node generate-jwts.ts
58+
```
59+
60+
The JWTs by default includes all user roles, but you can edit the `generate-jwts.ts` to remove some of them, if you need to test that only certain roles are authorized to access an endpoint.
61+
62+
## Run with Docker
63+
64+
To run with Docker Compose, check the instructions in [compose README](../compose/README.md).
65+
You can build a local image by running
66+
67+
```bash
68+
./build-docker.sh
69+
```
70+
71+
## Keys
72+
73+
Each gateway needs a set of keys to communicate with evaka services. New keys can be generated as follows:
74+
75+
```bash
76+
openssl genpkey -out jwk_private_key.pem -algorithm RSA -pkeyopt rsa_keygen_bits:4096
77+
openssl rsa -in jwk_private_key.pem -pubout > jwk_public_key.pem
78+
```
79+
80+
The public key can be converted to jwk-format with
81+
82+
```bash
83+
npx pem-jwk jwk_public_key.pem > public.jwk
84+
```
85+
86+
You then need to add `"kid": <service name>` pair to the `public.jwk` contents, eg.
87+
88+
```json
89+
{
90+
"kid": "evaka-internal-gw",
91+
"kty": "RSA",
92+
"n": ...,
93+
"e": "AQAB"
94+
}
95+
```
96+
97+
The pem files must be put into a **private** S3 buckets accessible to the services, into gateway-specific directories
98+
like: `s3://my-deployment-bucket-<env>/<gateway>/`. The contents of `public.jwk` must be copied into each related
99+
service's `keys` list in `jwks.json`, which should be similarly found in `s3://my-deployment-bucket-<env>/<service>/`.
100+
101+
You can put the generated files to `dev` environment's bucket with e.g.:
102+
103+
```bash
104+
# For Voltti environments, you can find the bucket ID from Terraform output
105+
export DEPLOYMENT_BUCKET=<REPLACE ME>
106+
echo aws s3 cp jwks.json "s3://${DEPLOYMENT_BUCKET}/evaka-srv/jwks.json"
107+
for VER in public private; do
108+
echo aws s3 cp "jwk_${VER}_key.pem" "s3://${DEPLOYMENT_BUCKET}/internal-gw/jwk_${VER}_key.pem"
109+
done
110+
```
111+
112+
Same goes for `test`, `staging` and `prod` but *be sure to use different keys* in all environments.
113+
114+
## Authentication and session
115+
116+
Session data is store in ElastiCache for Redis. Session includes the logged in user details required by passport
117+
and SAML to log out the user with Single Sign Out. The session also stores the user UUID. Downstream calls are
118+
authenticated with JWK-signed JWT:s that contain the user ID. To add an authentication header to a downstream call
119+
use the `createAuthHeaders(user)` function from `shared/auth/index.ts`. The user parameter is the user object
120+
from a logged in session (available at `req.user`).
121+
122+
## Security
123+
124+
### Headers
125+
126+
The project uses Helmet to set sane default headers and remove unsafe headers set by Express. Many of these headers
127+
are already set at the proxy, but helmet was chosen to be kept with a default setting to incorporate possible additions
128+
that don't get updated to the proxy.
129+
130+
### XSRF Protection
131+
132+
After login an `XSRF-TOKEN` cookie is set with a random token value. The csurf middleware check all incoming traffic
133+
with HTTP POST methods for headers containing the token. Axios HTTP client automatically recognizes this cookie and
134+
send a `X-XSRF-TOKEN` header with the cookie value.
135+
136+
Since the domain of the service is shared among multiple services all with different sessions and XSRF cookies. Some
137+
requests might fail when browsing multiple application simultaneously.
138+
139+
### Session handling
140+
141+
The session identifier of the login cookie is rolled after login to mitigate session fixation attacks.
142+
143+
The session cookie is set without the secure flag, since the connection to the proxy is not secured and Express refuses
144+
to set the cookie. The cookie flag is ultimately set at the proxy.

apigw/build-docker.sh

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/env bash
2+
3+
# SPDX-FileCopyrightText: 2017-2020 City of Espoo
4+
#
5+
# SPDX-License-Identifier: LGPL-2.1-or-later
6+
7+
set -euo pipefail
8+
9+
DOCKER_IMAGE=${DOCKER_IMAGE:-evaka/api-gateway}
10+
DOCKER_TAG=${DOCKER_TAG:-local}
11+
GIT_SHA=$(git rev-parse HEAD)
12+
13+
yarn build
14+
15+
docker build --build-arg commit="${GIT_SHA}" --build-arg build=local -t "${DOCKER_IMAGE}" .
16+
docker tag "${DOCKER_IMAGE}" "${DOCKER_IMAGE}:${DOCKER_TAG}"
17+
docker tag "${DOCKER_IMAGE}:${DOCKER_TAG}" "${DOCKER_IMAGE}:${GIT_SHA}"

0 commit comments

Comments
 (0)