Stack
Client
The ecoPortal client is structured as a Single Page Application (SPA) built in AngularJS and hosts ReactJS applications within it, only accessible through the AngularJS client. All requests made after the initial request are performed with JSON.
Server
Our server-side application is written using Ruby on Rails. We use Puma as the application server and Shoryuken to manage background jobs.
Overview
ecoPortal uses a 12-factor design where all application components are independently stateless. This allows the web and worker container hosts to easily scale up/down or be killed as required with no adverse effects. It also allows zero-downtime deployments to be performed by gradually replacing old containers with new ones, with the load balancer shifting client connections from the old containers to the new ones. Application images are versioned and stored within AWS Elastic Container Repository (ECR).
The application is containerised and will run on a dynamic port, “pushing” itself into the load balancer’s target group. This allows any given virtual host to run multiple web containers if needed. Health checks are automatic and containers which go bad will be replaced once detected. Application assets (CSS & Javascript) are fingerprinted and stored using S3/Cloudfront on each deployment in a write-only fashion.
An isolated VPC contains the Load Balancer (LB) and Fargate hosts. Security groups further isolate the load balancer and the hosts. The LB allows TCP connections on ports 80 & 443 only. Access from the application to other services is managed through a mixture of IAM rules and password authentication. Required secrets (passwords etc) are stored encrypted in AWS parameter store with an IAM container role providing temporary access to the secrets on container boot.
Service details
ECR
Application code (sensitive)
Images are compiled from git and then uploaded and tagged
100 versions are kept
Push/pull access is IAM-based (User)
Deployment access is IAM-based (Role)
Fargate
Replicates and runs copies of ecoPortal’s web hosts and background workers
Pulls images from ECR
SQS
Queuing system for background jobs
Push/pull access is IAM-based (User)
No sensitive data
Expires as used
Cloudwatch
Output logging for application
Write access is IAM-based (Role)
Read access is separate IAM (Group)
No sensitive data, just metadata
Expires after 12 months
Parameter Store
Manages the application credentials (sensitive data)
Credentials are encrypted & isolated between environments with namespaces
Developer access is IAM (Group)
Application read access is IAM (Role)
OpenSearch
Search-engine contains an intermediate form of most content
Sensitive data
Access is IAM-based (User) via SigV4
S3
Stores file uploads
Encrypted at rest, sensitive data
Access is IAM-based (User)
Client uploads are managed via pre-signed requests into isolated per-user prefixes that are then reprocessed by the server and moved into an appropriate non-user modifiable location
Client uploads are automatically scanned for malware and viruses with up-to-date ClamAV through AWS Lambda. Infected files are tagged and cannot be downloaded.
Client downloads are managed via a redirect which verifies permissions and then generates an expiring signed download link
Some resources (user avatars) are less sensitive and are secured simply by being in an unguessable prefix to reduce unnecessary overheads
MongoDB Atlas
Primary database - all data
Sensitive data
ElasticCache
Metadata around jobs currently running and queued items for notifications
No sensitive data - ID lists only
Access is password-based
ElasticAPM
Application pushes transaction traces, and performance data so that we can ensure that ecoPortal is performing correctly
No sensitive data - code locations + internal IDs only
Sendgrid
Sends emails from the system
Sensitive data can be transmitted depending on notification setup on the organisation