diff --git a/.circleci/config.yml b/.circleci/config.yml index 91d3e30..f21303b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,7 +47,7 @@ jobs: docker push "${DOCKER_REGISTRY}/${DOCKER_NAMESPACE}/${CIRCLE_PROJECT_REPONAME}:latest" name: "Build and Deploy Website Docker Image" working_directory: ~/repo - build_package: + build_internal_package: docker: - image: cdssnc/track-web-build:0.1.0 working_directory: /opt/apps/track-web @@ -58,12 +58,25 @@ jobs: - store_artifacts: path: /opt/apps/track-web/track-web.tar.gz destination: track-web.tar.gz - + build_external_package: + docker: + - image: cdssnc/track-web-build:0.1.0 + working_directory: /opt/apps/track-web-public + steps: + - checkout + - run: + command: sh deploy/build-env-public.sh + - store_artifacts: + path: /opt/apps/track-web-public/track-web-public.tar.gz + destination: track-web-public.tar.gz workflows: version: 2 tracker: jobs: - track_web - - build_package: + - build_internal_package: + requires: + - track_web + - build_external_package: requires: - track_web diff --git a/.github/main.workflow b/.github/main.workflow new file mode 100644 index 0000000..3d19908 --- /dev/null +++ b/.github/main.workflow @@ -0,0 +1,11 @@ +workflow "CI" { + on = "push" + resolves = [ + "Dockerfile lint" + ] +} + +action "Dockerfile lint" { + uses = "docker://cdssnc/docker-lint" + args = "--ignore DL3013" +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 7ae0629..7d3c4e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,19 @@ -MAINTAINER David Buckley +FROM python:3.5 as python-base LABEL Description="Track Web Security Compliance" Vendor="Canadian Digital Service" -FROM python:3.5 as python-base COPY requirements.txt /opt/track-web/requirements.txt COPY setup.py /opt/track-web/setup.py COPY track /opt/track-web/track COPY MANIFEST.in /opt/track-web/MANIFEST.in -# Build wheels to install into production image -# Force a build with --no-binary to get around the case where a wheel is available for python:3.5 but not python:3.5-alpine RUN pip install --upgrade pip && mkdir wheels && pip wheel --no-binary :all: -r /opt/track-web/requirements.txt -w wheels && pip wheel --no-deps /opt/track-web/ -w wheels - -FROM python:3.5-alpine -MAINTAINER David Buckley -LABEL Description="Track Digital Security Compliance" Vendor="Canadian Digital Service" - -COPY --from=python-base /wheels /wheels RUN pip install /wheels/* && rm -rf /wheels /root/.cache/pip && \ - addgroup -S track-web && adduser -S -G track-web track-web && \ + addgroup --system track-web && adduser --system --group track-web && \ mkdir -p /opt/track-web/.cache && \ chown -R track-web /opt/track-web + USER track-web:track-web EXPOSE 5000 -ENTRYPOINT ["gunicorn", "track.wsgi:app", "--bind=0.0.0.0:5000", "--worker-class=gthread", "--access-logfile=-", "--error-logfile=-", "--capture-output"] +ENTRYPOINT ["gunicorn", "track.wsgi:app", "--bind=0.0.0.0:5000", "--worker-class=sync", "--access-logfile=-", "--error-logfile=-", "--log-level=debug", "--workers=4"] diff --git a/Dockerfile.build b/Dockerfile.build deleted file mode 100644 index e018b8c..0000000 --- a/Dockerfile.build +++ /dev/null @@ -1,7 +0,0 @@ -FROM ubuntu:16.04 - -COPY deploy/provision.sh /opt/provision.sh -RUN sh /opt/provision.sh - -COPY deploy/build-env.sh /opt/build-env.sh -CMD ["sh", "/opt/build-env.sh", "/opt/apps/track-web"] diff --git a/deploy/build-env-public.sh b/deploy/build-env-public.sh new file mode 100644 index 0000000..deabfb1 --- /dev/null +++ b/deploy/build-env-public.sh @@ -0,0 +1,9 @@ +WORKDIR=${1:-"/opt/apps/track-web-public"} +mkdir -p $WORKDIR +cd $WORKDIR +python3 -m venv .venv +. .venv/bin/activate +pip install --upgrade pip +pip install -r requirements.txt +tar -czvf track-web-public.tar.gz .venv track +rm -rf .venv diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 37fe88e..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,8 +0,0 @@ -version: '3' -services: - build-env: - build: - context: . - dockerfile: Dockerfile.build - volumes: - - .:/opt/apps/track-web/ diff --git a/elenchos.json b/elenchos.json new file mode 100644 index 0000000..11657f1 --- /dev/null +++ b/elenchos.json @@ -0,0 +1,6 @@ +{ + "dockerfiles": { + "grc.io/cdssnc/track-web": "." + }, + "overlay": "manifests/overlays/elenchos" + } \ No newline at end of file diff --git a/manifests/overlays/elenchos/app-deployment.yaml b/manifests/overlays/elenchos/app-deployment.yaml new file mode 100644 index 0000000..2a19064 --- /dev/null +++ b/manifests/overlays/elenchos/app-deployment.yaml @@ -0,0 +1,28 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: track-web + name: track-web +spec: + selector: + matchLabels: + app: track-web + template: + metadata: + labels: + app: track-web + spec: + containers: + - image: gcr.io/cdssnc/track-web + imagePullPolicy: Always + name: track-web + env: + - name: TRACKER_MONGO_URI + value: mongodb://track-ro:0D^GEPgF52d&2S@ds113692.mlab.com:13692/trackweb + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + terminationGracePeriodSeconds: 30 +status: {} \ No newline at end of file diff --git a/manifests/overlays/elenchos/app-service.yaml b/manifests/overlays/elenchos/app-service.yaml new file mode 100644 index 0000000..06ad9d5 --- /dev/null +++ b/manifests/overlays/elenchos/app-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + name: track-web + name: track-web +spec: + type: NodePort + ports: + - port: 5000 + targetPort: 5000 + selector: + app: track-web + diff --git a/manifests/overlays/elenchos/kustomization.yaml b/manifests/overlays/elenchos/kustomization.yaml new file mode 100644 index 0000000..20d5731 --- /dev/null +++ b/manifests/overlays/elenchos/kustomization.yaml @@ -0,0 +1,10 @@ +resources: + - app-deployment.yaml + - app-service.yaml + - traefik-ingress-controller-cluster-role-binding.yaml + - traefik-ingress-controller-cluster-role.yaml + - traefik-ingress-controller-deployment.yaml + - traefik-ingress-controller-service-account.yaml + - traefik-ingress.yaml + - traefik-ingress-service.yaml + diff --git a/manifests/overlays/elenchos/traefik-ingress-controller-cluster-role-binding.yaml b/manifests/overlays/elenchos/traefik-ingress-controller-cluster-role-binding.yaml new file mode 100644 index 0000000..b1ca54f --- /dev/null +++ b/manifests/overlays/elenchos/traefik-ingress-controller-cluster-role-binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: traefik-ingress-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: traefik-ingress-controller +subjects: + - kind: ServiceAccount + name: traefik-ingress-controller + namespace: kube-system diff --git a/manifests/overlays/elenchos/traefik-ingress-controller-cluster-role.yaml b/manifests/overlays/elenchos/traefik-ingress-controller-cluster-role.yaml new file mode 100644 index 0000000..76ab251 --- /dev/null +++ b/manifests/overlays/elenchos/traefik-ingress-controller-cluster-role.yaml @@ -0,0 +1,24 @@ +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: traefik-ingress-controller + namespace: kube-system +rules: + - apiGroups: + - "" + resources: + - services + - endpoints + - secrets + verbs: + - get + - list + - watch + - apiGroups: + - extensions + resources: + - ingresses + verbs: + - get + - list + - watch diff --git a/manifests/overlays/elenchos/traefik-ingress-controller-deployment.yaml b/manifests/overlays/elenchos/traefik-ingress-controller-deployment.yaml new file mode 100644 index 0000000..bb596cf --- /dev/null +++ b/manifests/overlays/elenchos/traefik-ingress-controller-deployment.yaml @@ -0,0 +1,37 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + labels: + k8s-app: traefik-ingress-lb + name: traefik-ingress-controller + namespace: kube-system +spec: + template: + metadata: + labels: + k8s-app: traefik-ingress-lb + spec: + containers: + - args: + - --api + - --kubernetes + - --debug + - --defaultentrypoints=http + - --entrypoints=Name:http Address::80 + image: traefik:1.7 + name: traefik-ingress-lb + ports: + - containerPort: 80 + hostPort: 80 + name: http + - containerPort: 8080 + hostPort: 8080 + name: admin + securityContext: + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + serviceAccountName: traefik-ingress-controller + terminationGracePeriodSeconds: 60 diff --git a/manifests/overlays/elenchos/traefik-ingress-controller-service-account.yaml b/manifests/overlays/elenchos/traefik-ingress-controller-service-account.yaml new file mode 100644 index 0000000..3472662 --- /dev/null +++ b/manifests/overlays/elenchos/traefik-ingress-controller-service-account.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: traefik-ingress-controller + namespace: kube-system diff --git a/manifests/overlays/elenchos/traefik-ingress-service.yaml b/manifests/overlays/elenchos/traefik-ingress-service.yaml new file mode 100644 index 0000000..f689654 --- /dev/null +++ b/manifests/overlays/elenchos/traefik-ingress-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: traefik-ingress-service + namespace: kube-system +spec: + ports: + - name: http + port: 80 + protocol: TCP + selector: + k8s-app: traefik-ingress-lb + type: LoadBalancer \ No newline at end of file diff --git a/manifests/overlays/elenchos/traefik-ingress.yaml b/manifests/overlays/elenchos/traefik-ingress.yaml new file mode 100644 index 0000000..21bf986 --- /dev/null +++ b/manifests/overlays/elenchos/traefik-ingress.yaml @@ -0,0 +1,14 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: traefik + name: traefik-ingress +spec: + rules: + - http: + paths: + - path: / + backend: + serviceName: track-web + servicePort: 5000 diff --git a/requirements.txt b/requirements.txt index 1ae0ad5..c8edf97 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,11 +2,11 @@ flask==0.12.4 gunicorn==19.6.0 pyyaml==3.13 python-slugify==1.2.1 -Flask-PyMongo==0.5.1 +Flask-PyMongo==2.2.0 flask-compress==1.4.0 click==6.7 Babel==2.6.0 Flask-Caching==1.4.0 -pymongo==3.7.0 +pymongo==3.7.2 azure-keyvault==1.1.0 msrestazure==0.5.1 diff --git a/setup.py b/setup.py index 9f8ffb4..f71dcf5 100644 --- a/setup.py +++ b/setup.py @@ -22,8 +22,8 @@ 'gunicorn==19.6.0', 'pyyaml==3.13', 'python-slugify==1.2.1', - 'pymongo==3.7.0', - 'Flask-PyMongo==0.5.1', + 'pymongo==3.7.2', + 'Flask-PyMongo==2.2.0', 'flask-compress==1.4.0', 'click==6.7', 'Babel==2.6.0', diff --git a/track/config.py b/track/config.py index d9c3aa6..f99ddff 100644 --- a/track/config.py +++ b/track/config.py @@ -13,13 +13,15 @@ class Config: DEBUG = False TESTING = False - MONGO_URI = "mongodb://localhost:27017/track" + MONGO_URI = os.environ.get("TRACKER_MONGO_URI", "mongodb://localhost:27017/track") CACHE_TYPE = "null" @staticmethod def init_app(app): pass + + class ProductionConfig(Config): CACHE_TYPE = "filesystem" diff --git a/track/helpers.py b/track/helpers.py index cc11b89..e76daab 100644 --- a/track/helpers.py +++ b/track/helpers.py @@ -1,6 +1,7 @@ import pkg_resources import yaml import datetime +import os from track import models from track.data import FIELD_MAPPING from babel.dates import format_date @@ -56,3 +57,7 @@ def percent(num, denom): @app.template_filter("percent_not") def percent_not(num, denom): return (100 - round((num / denom) * 100)) + + @app.template_filter("fetch_env") + def fetch_env(value): + return os.getenv(value) diff --git a/track/static/css/main.css b/track/static/css/main.css index 6f9a310..5777d6f 100644 --- a/track/static/css/main.css +++ b/track/static/css/main.css @@ -46,6 +46,13 @@ th { .beta-badge { background-color: #22A7F0; } +li a.myskip { + color: #3D4852; } + +li a.myskip:focus { + color: white; + text-decoration: none; } + table caption { left: -10000px; height: 1px; diff --git a/track/static/css/main.css.map b/track/static/css/main.css.map index 4e662fe..e4bbdce 100644 --- a/track/static/css/main.css.map +++ b/track/static/css/main.css.map @@ -1,6 +1,6 @@ { "version": 3, -"mappings": "AACE,CAAE;ECQI,kBAAoB,EDPJ,UAAU;ECY1B,eAAiB,EDZD,UAAU;EC2B1B,UAAY,ED3BI,UAAU;;AEFlC,KAAM;EDSE,6BAAoB,EAAE,sBAAM;EAK5B,0BAAiB,EAAE,sBAAM;EAKzB,yBAAgB,EAAE,sBAAM;EAUxB,qBAAY,EAAE,sBAAM;EC3B1B,eAAe,EAAE,QAAQ;EACzB,MAAM,EAAE,QAAgB;EACxB,YAAY,EAAE,KAAK;EACnB,KAAK,EAAE,IAAI;;AAGb,EAAG;EACD,aAAa,EAAE,iBAAyC;EACxD,WAAW,EAAE,GAAG;EAChB,OAAO,EAAE,QAAgB;EACzB,UAAU,EAAE,IAAI;;AAGlB,EAAG;EACD,aAAa,ECaD,iBAA4B;EDZxC,OAAO,EAAE,QAAgB;;AAG3B;;EAEG;EACD,cAAc,EAAE,MAAM;;AEpBxB,WAAY;EACX,UAAU,EAAE,eAAe;EAC3B,YAAY,EAAE,kBAAkB;EAChC,gBAAgB,EAAE,kBAAkB;;AAGrC,MAAO;EACN,gBAAgB,EAAE,KAAU;EACzB,gBAAgB,EAAE,kBAAe;;AAGrC,cAAe;EACd,MAAM,EAAE,GAAG;;AAGZ,WAAY;EACX,QAAQ,EAAE,MAAM;;AAGjB,WAAY;EACX,gBAAgB,EAAE,OAAO;;ACpB1B,aAAc;EACZ,IAAI,EAAE,QAAQ;EACd,MAAM,EAAE,GAAG;EACX,QAAQ,EAAE,MAAM;EAChB,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,IAAI;EACT,KAAK,EAAE,GAAG;;AAGZ,WAAY;EACV,cAAc,EAAE,SAAS;EACzB,UAAU,EAAE,SAAS;EACrB,UAAU,EAAE,UAAU;;AAItB,gBAAM;EACJ,WAAW,EAAE,iBAAiB;EAC9B,cAAc,EAAE,iBAAiB;;AAIrC,QAAS;EACP,aAAa,EAAE,cAAc;EAAE,UAAU;EACzC,iBAAiB,EAAE,cAAc;EAAE,YAAY;EAC/C,SAAS,EAAE,cAAc;;AAG3B,mBAAoB;EAClB,OAAO,EAAE,WAAW;EAEpB,sCAAmB;IACjB,SAAS,EAAE,KAAK;IAChB,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,IAAI;IAElB,wCAAE;MACA,eAAe,EAAE,SAAS;MAC1B,MAAM,EAAE,OAAO;IAGjB,sGAAyB;MACvB,eAAe,EAAE,IAAI;MACrB,KAAK,EAAE,gBAAgB;IAGzB,6CAAO;MACL,MAAM,EAAE,IAAI;MACZ,OAAO,EAAE,YAAY;MACrB,KAAK,EAAE,KAAK;MACZ,KAAK,EAAE,IAAI;MACX,aAAa,EAAE,GAAG;MAClB,OAAO,EAAE,KAAK;MACd,MAAM,EAAE,KAAK;MACb,MAAM,EAAE,IAAI;MACZ,kBAAkB,EAAE,IAAI;MACxB,eAAe,EAAE,IAAI;MACrB,UAAU,EAAE,IAAI;MAChB,MAAM,EAAE,OAAO;MACf,UAAU,EAAE,8DAAqE;MACjF,yDAAc;QACZ,OAAO,EAAE,IAAI;EAKnB,mCAAgB;IACd,OAAO,EAAE,MAAM;IAGf,4CAAS;MACP,KAAK,ECpDM,OAAO;IDwDpB,4CAAS;MACP,KAAK,ECxDA,OAAO;ID4Dd,4CAAS;MACP,YAAY,EAAE,IAAI;MAClB,WAAW,EAAE,IAAI;IAInB,qCAAE;MACA,eAAe,EAAE,SAAS;MAC1B,KAAK,EAAE,kBAAkB;IAG3B,2CAAQ;MACN,KAAK,EAAE,gBAAgB;IAGzB,6CAAU;MACR,eAAe,EAAE,eAAe;MAChC,KAAK,EAAE,gBAAgB;IAGzB,8EAAO;MACL,aAAa,EAAE,yBAAyB;MACxC,OAAO,EAAE,cAAc;MACvB,WAAW,EAAE,MAAM;IAGrB,4CAAS;MACP,OAAO,EAAE,yBAAyB;IAGpC,gDAAa;MACX,WAAW,EAAE,eAAe;MAC5B,YAAY,EAAE,eAAe;MAC7B,gBAAgB,EAAE,OAAO;IAIzB,sSAAqF;MACnF,mBAAmB,EAAE,WAAW;IAIpC,6CAAY;MACV,MAAM,EAAE,IAAI;IAGd;2DACoB;MAClB,WAAW,EAAE,MAAM;IAInB,8EAAsB;MACpB,GAAG,EAAE,GAAG;MACR,gBAAgB,EAAE,OAAyB;IAE7C,8EAAsB;MACpB,GAAG,EAAE,GAAG;MACR,gBAAgB,EAAE,OAAyB;IAO3C,+DAAS;MACP,WAAW,EAAE,GAAG;IAGlB,4DAAM;MACJ,aAAa,EAAE,IAAI;MACnB,OAAO,EAAE,SAAS;IAEpB,qEAAe;MACb,SAAS,EAAE,GAAG;IASZ,mEAAG;MAAE,aAAa,EAAE,eAAe;IAErC,+DAAQ;MACN,gBAAgB,EAAE,OAAO;MACzB,MAAM,EAAE,OAAO;MACf,wEAAQ;QACN,gBAAgB,EAAE,OAAO;IAO3B,mFAAc;MAAC,eAAe,EAAE,SAAS;IAK3C,sEAAQ;MACN,YAAY,EAAE,IAAI;IAQxB,mDAAG;MACD,OAAO,EAAE,2BAA2B;MEnKxC,qCAAsB;QFkKpB,mDAAG;UAIC,YAAY,EAAE,eAAe;UAC7B,sEAAqB;YAAE,GAAG,EAAE,eAAe;MEvKjD,oCAAsB;QF0KhB,sEAAqB;UAAE,GAAG,EAAE,eAAe;IAM/C,8IAAyB;MACvB,gBAAgB,EAAE,OAAO;MACzB,aAAa,EAAE,IAAI;MAEnB,KAAK,EAAE,GAAG;MACV,QAAQ,EAAE,QAAQ;MAClB,IAAI,EAAE,IAAI;MAEV,gKAAS;QJ/MT,kBAAoB,EIgNE,UAAU;QJ3MhC,eAAiB,EI2MK,UAAU;QJ5LhC,UAAY,EI4LU,UAAU;QAC9B,gBAAgB,EAAE,OAAO;QACzB,iBAAiB,EAAE,QAAQ;QAC3B,eAAe,EAAE,SAAS;QAC1B,aAAa,EAAE,aAAa;QAC5B,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE,GAAG;QACV,kLAAW;UACT,aAAa,EAAE,IAAI;QAGnB,8KAAa;UAAE,gBAAgB,EAAE,WAAW;QAA5C,8KAAa;UAAE,gBAAgB,EAAE,WAAW;QAA5C,8KAAa;UAAE,gBAAgB,EAAE,WAAW;MAIhD,kJAAE;QACA,SAAS,EAAE,OAAO;QAClB,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,GAAG;QACR,IAAI,EAAE,KAAK;EAKnB,oCAAiB;IACf,WAAW,EAAE,cAAc;EAG3B,0DAAkB;IAChB,OAAO,EAAE,kBAAkB;IAC3B,SAAS,EAAE,OAAO;IAClB,MAAM,EAAE,eAAe;IACvB,kEAAU;MACR,UAAU,EAAE,kBAAkB;MAC9B,KAAK,EAAE,gBAAgB;MACvB,wEAAQ;QACN,KAAK,EAAE,gBAAgB;IAG3B,kIAAiB;MACf,UAAU,EAAE,kBAAkB;MAC9B,KAAK,EAAE,gBAAgB;IAGvB,oJAAiB;MACf,UAAU,EAAE,sBAAsB;;AGrQ5C,aAAa;EAEX,UAAU,EAAE,OAAO;EACnB,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,MAAM;EACf,0BAA0B,EAAE,KAAK;ECMjC,QAAQ,EDJU,KAAK;ECOrB,GAAG,EARC,CAAoB;EAYxB,KAAK,EAXC,IAAoB;EAe1B,MAAM,EAdC,CAAoB;EAkB3B,IAAI,EAjBC,CAAoB;ECHzB,MAAM,EAJG,IAAa;EAQtB,KAAK,EAXC,KAAO;ETOT,iBAAoB,EAAE,kBAAM;EAK5B,cAAiB,EAAE,kBAAM;EAKzB,aAAgB,EAAE,kBAAM;EAKxB,YAAe,EAAE,kBAAM;EAKvB,SAAY,EAAE,kBAAM;EApBpB,kBAAoB,EAAE,gBAAM;EAK5B,eAAiB,EAAE,gBAAM;EAezB,UAAY,EAAE,gBAAM;EOd1B,wBAAa;IPNP,iBAAoB,EAAE,aAAM;IAK5B,cAAiB,EAAE,aAAM;IAKzB,aAAgB,EAAE,aAAM;IAKxB,YAAe,EAAE,aAAM;IAKvB,SAAY,EAAE,aAAM", +"mappings": "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", "sources": ["../scss/lib/neat/grid/_grid.scss","../scss/lib/bourbon/addons/_prefixer.scss","../scss/base/_tables.scss","../scss/base/_variables.scss","../scss/base/_base.scss","../scss/includes/datatables.scss","../scss/main.scss","../scss/lib/neat/grid/_media.scss","../scss/includes/header.scss","../scss/lib/bourbon/addons/_position.scss","../scss/lib/bourbon/addons/_size.scss"], "names": [], "file": "main.css" diff --git a/track/static/js/dataTables.downloads.js b/track/static/js/dataTables.downloads.js index 4b8585e..ea1475b 100644 --- a/track/static/js/dataTables.downloads.js +++ b/track/static/js/dataTables.downloads.js @@ -36,9 +36,7 @@ $.fn.dataTable.Download = function ( inst ) { if (drawnOnce) return; var elem = "" + - "" + - text + - ""; + "" + text +""; container.html(elem); drawnOnce = true; diff --git a/track/static/js/https/domains.js b/track/static/js/https/domains.js index cafea27..dafa79e 100755 --- a/track/static/js/https/domains.js +++ b/track/static/js/https/domains.js @@ -287,16 +287,16 @@ $(function () { // determines whether remote fetching has to happen var fetch = !(loneDomain(row)); - return n(row.domain) + "
" + l("", "#", showHideText(true, row), "onclick=\"return false\" data-fetch=\"" + fetch + "\" data-domain=\"" + row.domain + "\"") + "
"; + return n(row.domain) + "
" + l("", "#", showHideText(true, row), "data-fetch=\"" + fetch + "\" data-domain=\"" + row.domain + "\"") + "
"; }; var showHideText = function(show, row) { if (loneDomain(row)) - return (show ? "" + text.show[language] : "" + text.hide[language]) + " " + text.details[language]; + return (show ? "" + text.show[language] : "" + text.hide[language]) + " " + text.details[language]; else if(row.totals.https.eligible == 1) - return (show ? "" + {en: "Show", fr: "Montrer le"}[language] : "" + {en: "Hide", fr: "Cacher le"}[language]) + " " + {en: "1", fr:""}[language] + text.subdomain[language]; + return (show ? "" + {en: "Show", fr: "Montrer le"}[language] : "" + {en: "Hide", fr: "Cacher le"}[language]) + " " + {en: "1", fr:""}[language] + text.subdomain[language]; else - return (show ? "" + text.show[language] : "" + text.hide[language]) + " " + row.totals.https.eligible + text.subdomains[language]; + return (show ? "" + text.show[language] : "" + text.hide[language]) + " " + row.totals.https.eligible + text.subdomains[language]; }; var initExpansions = function() { @@ -321,7 +321,7 @@ $(function () { if (fetch) { console.log(text.fetch[language] + base_domain + "..."); - link.addClass("loading").html("" + text.loading[language] + base_domain + " services..."); + link.addClass("loading").html("" + text.loading[language] + base_domain + " services..."); $.ajax({ url: "/data/hosts/" + base_domain + "/https.json", @@ -369,9 +369,7 @@ $(function () { }; var l = function(base_domain, href, text, extra) { - // if base domain is provided, CSV download, so track with gtag - if(base_domain != "") return "" + text + ""; - + return "" + text + ""; }; diff --git a/track/static/js/https/donuts.js b/track/static/js/https/donuts.js new file mode 100644 index 0000000..b189e31 --- /dev/null +++ b/track/static/js/https/donuts.js @@ -0,0 +1,75 @@ +function generate_chart() { + var chart = d3.select('.compliant'); + var width = chart.attr("data-width"); + if (width == null) + width = calculate_width(); + width = parseInt(width); + var height = width * 1.2; + var radius = Math.min(width, height) / 2; + var color = d3.scale.ordinal() + .range(["#0071e1", "#888888"]); + var arc = d3.svg.arc() + .outerRadius(radius) + .innerRadius(radius - 40); + var pie = d3.layout.pie() + .value(function (d) { + return d.value; + }) + .sort(null); + chart = chart + .append('svg') + .attr("width", width) + .attr("height", height) + .append("g") + .attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")"); + d3.json("/data/reports/https.json", function (error, data) { + // calculate % client-side + var compliant = Math.round((data.enforces / data.eligible) * 100); + // just abort and leave it blank if something's wrong + // (instead of showing "NaN%" visually) + if (isNaN(compliant)) + return; + var pie_data = [ + {status: 'active', value: compliant}, + {status: 'inactive', value: (100-compliant)}, + ] + var g = chart.selectAll(".arc") + .data(pie(pie_data)) + .enter().append("g") + .attr("class", "arc"); + g.append("path") + .style("fill", function(d) { + return color(d.data.status); + }) + .transition().delay(function(d, i) { + return i *400; + }).duration(400) + .attrTween('d', function(d) { + var i = d3.interpolate(d.startAngle+ 0.1, d.endAngle); + return function(t) { + d.endAngle = i(t); + return arc(d); + } + }); + g.append("text") + .attr("text-anchor", "middle") + .attr("class", "text-5xl font-bold") + .attr("dy", "0.4em") + .attr("fill", "black") + .text(function(d){ + return "" + pie_data[0].value + "%"; + }); + }); +}; + +function calculate_width() { + var window_width = $(window).width(); + + if(window_width < 769) + return 250; + else + return 287; +} + +generate_chart(); + diff --git a/track/static/js/https/organizations.js b/track/static/js/https/organizations.js index 2b2ba63..5290df3 100644 --- a/track/static/js/https/organizations.js +++ b/track/static/js/https/organizations.js @@ -86,8 +86,8 @@ $(document).ready(function () { var link = function(link_text) { return "" + - "" + + "" + link_text + ""; } diff --git a/track/static/js/tables.js b/track/static/js/tables.js index 325d9f7..1d69b55 100644 --- a/track/static/js/tables.js +++ b/track/static/js/tables.js @@ -8,6 +8,9 @@ var Tables = { // add common options to all renderTables requests if (!options.responsive) options.responsive = true; + + // Older browsers need this to load in an acceptable time frame. We may want to make it conditional in the future + if (!options.deferRender) options.deferRender = true; var customInit = function() {}; // noop if (options.initComplete) customInit = options.initComplete; @@ -175,5 +178,6 @@ $(function() { $('#DataTables_Table_0_filter label').attr('class', 'w-full md:w-2/3'); $('#datatables-search').attr('class', 'border border-solid border-https-dark-gray bg-https-light-gray focus:border-https-blue block md:inline-block h-8 md:ml-6 mb-4 md:mb-8 w-full md:w-3/5 lg:w-3/4'); $('.dataTables_csv').attr('class', 'text-lg md:ml-4 mt-4 md:mt-6'); + }); }); diff --git a/track/static/scss/base/_base.scss b/track/static/scss/base/_base.scss index 3f7124f..84607c0 100644 --- a/track/static/scss/base/_base.scss +++ b/track/static/scss/base/_base.scss @@ -24,3 +24,11 @@ background-color: #22A7F0; } +li a.myskip { + color:$dark-gray; +} +li a.myskip:focus { + color:white; + text-decoration:none; +} + diff --git a/track/templates/en/domains.html b/track/templates/en/domains.html index 4b3af77..7e2af80 100644 --- a/track/templates/en/domains.html +++ b/track/templates/en/domains.html @@ -9,7 +9,7 @@ {% include 'includes/en/modal.html' %} -
+
diff --git a/track/templates/en/guidance.html b/track/templates/en/guidance.html index 4c45ac6..55fb8d0 100644 --- a/track/templates/en/guidance.html +++ b/track/templates/en/guidance.html @@ -6,9 +6,9 @@ {% block description %}Read guidance.{% endblock description %} {% block content %} -
+
-

Read guidance

+

Read guidance

Help us make government websites more secure. Please complete the following steps to become compliant with the Government of Canada's web security standards. If you have any questions about this process, please contact us.


@@ -18,7 +18,7 @@

Read guidance

@@ -34,8 +34,15 @@

Read guidance

-
  • Provide an up-to-date list of all domain and sub-domains of the publicly-accessible websites and web services to the following website: Submit your institution's domains.
  • -
  • Perform an assessment of the domains and sub-domains to determine the status of the configuration. Tools available to support this activity includes GC HTTPS Dashboard, SSL Labs, Hardenize, etc.
  • +
  • Provide an up-to-date list of all domain and sub-domains of the publicly-accessible websites and web services to TBS Cybersecurity. +
      +
    • Update and send the filtered "compliance.csv" file available from the HTTPS Dashboard for mass update; or
    • +
    • use the following website for domain additions: Submit your institution's domains
    • + +
    + +
  • +
  • Perform an assessment of the domains and sub-domains to determine the status of the configuration. Tools available to support this activity includes GC HTTPS Dashboard, SSL Labs, Hardenize, SSLShopper, etc.
  • Develop a prioritized implementation schedule for each of the affected websites and web services, following the recommended prioritization approach in the ITPIN: @@ -43,11 +50,11 @@

    Read guidance

  • 6.2.1 Newly developed websites and web services must adhere to this ITPIN upon launch.
  • 6.2.2 Websites and web services that involve an exchange of personal information or other sensitive information must receive priority following a risk-based approach, and migrate as soon as possible.
  • -
  • 6.2.3 All remaining websites and web services must be accessible through a secure connection, as outlined in Section 6.1, by September 30, 2019.
  • +
  • 6.2.3 All remaining websites and web services must be accessible through a secure connection, as outlined in Section 6.1, by December 31, 2019.
  • -
  • Engage the departmental IT group for implementation as appropriate. +
  • Engage departmental IT planning groups for implementation as appropriate.
    • Where necessary adjust IT Plans and budget estimates for the FY where work is expected.
    • @@ -56,7 +63,7 @@

      Read guidance

      -
    • Based on the assessment, and using the guidance available on GCpedia, the following activities may be required: +
    • Based on the assessment, and using the guidance available on GCcollab, the following activities may be required:
      • Obtain certificates from a GC-approved certificate source as outlined in the Recommendations for TLS Server Certificates for GC Public Facing Web Services
      • @@ -65,7 +72,8 @@

        Read guidance

        -
      • Perform another assessment of the applicable domains and sub-domains to confirm that the configuration has been updated and that HTTPS is enforced in accordance with the ITPIN. +
      • Perform another assessment of the applicable domains and sub-domains to confirm that the configuration has been updated and that HTTPS is enforced in accordance with the ITPIN. Results will + appear in the HTTPS Dashboard within 24 hours.
      • diff --git a/track/templates/en/help.html b/track/templates/en/help.html index ce3ad42..3d3afc5 100644 --- a/track/templates/en/help.html +++ b/track/templates/en/help.html @@ -6,7 +6,7 @@ {% block description %}For interpretation of any aspect of Implementing HTTPS for Secure Web Connections: Information Technology Policy Implementation Notice (ITPIN), contact Treasury Board of Canada Secretariat through Public Enquiries.{% endblock description %} {% block content %} -
        +

        Get help

        General public

        diff --git a/track/templates/en/index.html b/track/templates/en/index.html index a3c6ca7..d6b00f1 100644 --- a/track/templates/en/index.html +++ b/track/templates/en/index.html @@ -8,34 +8,35 @@ {% block content %} -
        - -
        -
        -

        Track web security compliance

        -

        Making government websites more secure

        -

        Canadians rely on the Government of Canada to provide secure digital services. A new - policy notice guides government websites to adopt good web security practices. Track how government sites are - becoming more secure.

        - - +
        -{% include 'includes/donut.html' %} + + + -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/track/templates/en/layout-en.html b/track/templates/en/layout-en.html index 77fb29b..355c203 100644 --- a/track/templates/en/layout-en.html +++ b/track/templates/en/layout-en.html @@ -4,7 +4,7 @@ {% block title %}{% endblock title %} - + {% include 'includes/head.html' %} @@ -12,7 +12,13 @@ - +{% set GTM_key = "GOOGLE_TAG_MANAGER" | fetch_env() %} +{% if GTM_key %} + + + +{% endif %}