Stack
Client
The ecoPortal client is structured as a Single Page Application (SPA) built in AngularJS and hosts ReactJS application within it, only accessible through the AngularJS client. All requests made after the initial request are performed with JSON. We currently use the following client-side libraries, however this is subject to change as appropriate:
AngularJS:
serviceworker-companion
jquery
jquery-ui
jquery.autoellipsis-1.0.10.min
jquery.placeholder.min
jquery.ui.touch-punch
jquery.visible.min
modernizr.cssscrollbar
mobile-detect
fastclick
vissense
underscore
magnific-popup
includes
angular
angular-route
angular-cookies
angular-recursion
angular-rails-templates
angular_simple_format
angular-filter
textAngular-sanitize
ng-infinite-scroll
angular-sortable-view
ngTranscludeMod
devise
angular-animate
angular-aria
angular-material
md-date-time
summernote-lite
summernote-video-attributes
wookmark
FileSaver
ng-tags-input
tinycolor-min
md-color-picker
ace
theme-textmate
mode-clojure
ui-ace
ext-searchbox
ng-file-upload
papaparse.min
highcharts
dirPagination
humanize
angular-humanize
d3.v3.min
handsontable.full
ngHandsontable
ng-csv
moment-timezone
ng-storage
angular-ui-tree
flatpickr
angular-actioncable
angular-websocket
ReactJS:
@apollo/client
@date-io/moment
@emotion/babel-preset-css-prop
@emotion/core
@emotion/react
@emotion/styled
@faker-js/faker
@geoffcox/react-splitter
@mui/icons-material
@mui/material
@mui/system
@mui/x-date-pickers
@react-pdf/renderer
@reduxjs/toolkit
@testing-library/jest-dom
@testing-library/react
@testing-library/user-event
@tippyjs/react
axios
classnames
color
delay
file-saver
filesize
formik
graphql
gsap
indefinite
json2mq
lodash
mime-types
moment
moment-timezone
next
pluralize
qrcode
query-string
ramda
react
react-copy-to-clipboard
react-dom
react-draggable
react-helmet
react-highlight-words
react-icons
react-intersection-observer
react-modal
react-notifications-component
react-quill
react-redux
react-transition-group
redux-observable
sass
tippy.js
typescript
web-vitals
yup
Server
Our server side application is written using Ruby on Rails. We use puma as the application server and shoryuken to manage background jobs. We currently use the following server-side libraries, however this is subject to change as appropriate:
rails
sassc-rails
compass-rails
jquery-rails
asset_sync
coffee-rails
fog-aws
fog-google
non-stupid-digest-assets
uglifier
sprockets
sprockets-rails
devise
devise_invitable
omniauth
omniauth-saml
omniauth-multisaml
angular_rails_csrf
omniauth-multisaml
tilt
haml
paperclip
posix-spawn
private_address_check
unf
mongoid-elasticsearch
typhoeus
faraday_middleware
faraday_middleware-aws-signers-v4
chronic
sidekiq
shoryuken
sidekiq-failures
clockwork
useragent
rest-client
hekenga
airbrake
safety_mailer
puma
puma_worker_killer
aws-sdk
roadie
roadie-rails
scout_apm
memoist
oj
http
parallel
rubyzip
mongoid
mongoid-paperclip
authority
ruby-saml
concurrent-ruby
hiredis
redis
redis-actionpack
rails_12factor
dalli
memstat
angular-rails-templates
rack-pratchett
oauth2
mini_racer
keepass-password-generator
rack-attack
kramdown
bundler-audit
nokogiri
serviceworker-rails
Services
Overview
ecoPortal uses a 12factor 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, with the load balancer shifting client connections from the old containers to the new. 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 Google Cloud Storage on each deployment in a write-only fashion.
An isolated VPC contains the Load Balancer (LB) and ECS hosts. Security groups further isolate the load balancer and the hosts. The LB allows TCP connections on ports 80 & 443 only. The ECS hosts allow connections only from the LB (all ports) and SSH access (port 22) for maintenance. SSH access is via public/private key only with additional MFA. 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)
ECS
Replicates and runs copies of ecoPortal’s web hosts and background workers
Pulls images from ECR
Access is either:
Security group based (Load Balancer)
Public/private key based (SSH)
Container hosts run Trend Micro DSaaS
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 1 month
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)
Elasticsearch
Search engine, contains an intermediate form of most content
Sensitive data
Access is IAM based (User) via SigV4
An additional IP is whitelisted - the CTO’s static IP address for debug and maintenance purposes
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
Primary database - all data
Sensitive data
Access is password based over SSL
Redis
Metadata around jobs currently running and queued items for notifications
No sensitive data - ID lists only
Access is password based
Scout
Application pushes transaction traces, 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, however emails are not logged (only the metadata such as subject line, recipient, delivery status)
Access is password based over SSL