diff --git a/deploy/kubernetes/console/README.md b/deploy/kubernetes/console/README.md index e2ed7fe44e..79d13c8726 100644 --- a/deploy/kubernetes/console/README.md +++ b/deploy/kubernetes/console/README.md @@ -124,6 +124,10 @@ The following table lists the configurable parameters of the Stratos Helm chart |console.nodeSelector|Node selectors to use for the console Pod|| |mariadb.nodeSelector|Node selectors to use for the database Pod|| |configInit.nodeSelector|Node selectors to use for the configuration Pod|| +|console.pspEnabled|Enable Pod Security Policies. Set this to true if you cluster is configured with PSPs enabled|false| +|console.pspName|Name of an existing Pod Security Policy to use instead of the one created by the chart when PSPs are enabled|| +|console.pspAnnotations|Annotations to be added to all pod security policy resources|| +|console.pspExtraLabels|Additional labels to be added to all pod security policy resources|| ## Accessing the Console diff --git a/deploy/kubernetes/console/templates/analyzers.yaml b/deploy/kubernetes/console/templates/analyzers.yaml index 963f0dbc42..2f722d4083 100644 --- a/deploy/kubernetes/console/templates/analyzers.yaml +++ b/deploy/kubernetes/console/templates/analyzers.yaml @@ -63,6 +63,9 @@ spec: imagePullSecrets: - name: {{.Values.dockerRegistrySecret}} {{- end }} + {{- if and (eq (printf "%s" .Values.kube.auth) "rbac") (.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1") }} + serviceAccountName: "stratos" + {{- end }} {{- if not .Values.console.reportsVolumeDisabled }} volumes: - name: data diff --git a/deploy/kubernetes/console/templates/config-init.yaml b/deploy/kubernetes/console/templates/config-init.yaml index 6ed17f1e88..3a0f788d7d 100644 --- a/deploy/kubernetes/console/templates/config-init.yaml +++ b/deploy/kubernetes/console/templates/config-init.yaml @@ -26,6 +26,16 @@ metadata: app.kubernetes.io/version: "{{ .Chart.AppVersion }}" helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" rules: +{{- if .Values.console.pspEnabled }} +- apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ default (printf "%s-psp" .Release.Name) .Values.console.pspName }} +{{- end }} - apiGroups: - "" resources: diff --git a/deploy/kubernetes/console/templates/database.yaml b/deploy/kubernetes/console/templates/database.yaml index 5f64b162a7..c62f5466e1 100644 --- a/deploy/kubernetes/console/templates/database.yaml +++ b/deploy/kubernetes/console/templates/database.yaml @@ -1,5 +1,63 @@ {{- if not .Values.mariadb.external }} --- +# Service account "stratos-db" for the database, if needed +{{- if and (eq (printf "%s" .Values.kube.auth) "rbac") (.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1") (.Values.console.pspEnabled) }} +apiVersion: "v1" +kind: "ServiceAccount" +metadata: + name: "stratos-db" + labels: + app.kubernetes.io/component: "stratos-db" + app.kubernetes.io/instance: "{{ .Release.Name }}" + app.kubernetes.io/name: "stratos" + app.kubernetes.io/version: "{{ .Chart.AppVersion }}" + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" +{{- end }} +--- +# Role "stratos-db-role" only used by account "[- stratos-db]" +{{- if and (eq (printf "%s" .Values.kube.auth) "rbac") (.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1") (.Values.console.pspEnabled) }} +apiVersion: "rbac.authorization.k8s.io/v1" +kind: "Role" +metadata: + name: "stratos-db-role" + labels: + app.kubernetes.io/component: "stratos-db-role" + app.kubernetes.io/instance: "{{ .Release.Name }}" + app.kubernetes.io/name: "stratos" + app.kubernetes.io/version: "{{ .Chart.AppVersion }}" + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" +rules: +- apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ default (printf "%s-psp" .Release.Name) .Values.console.pspName }} +{{- end }} +--- +# Role binding for service account "stratos-db" and role "stratos-db-role" +{{- if and (eq (printf "%s" .Values.kube.auth) "rbac") (.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1") (.Values.console.pspEnabled) }} +apiVersion: "rbac.authorization.k8s.io/v1" +kind: "RoleBinding" +metadata: + name: "stratos-db-role-binding" + labels: + app.kubernetes.io/component: "stratos-db-role-binding" + app.kubernetes.io/instance: "{{ .Release.Name }}" + app.kubernetes.io/name: "stratos" + app.kubernetes.io/version: "{{ .Chart.AppVersion }}" + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" +subjects: +- kind: "ServiceAccount" + name: "stratos-db" +roleRef: + apiGroup: "rbac.authorization.k8s.io" + kind: "Role" + name: "stratos-db-role" +{{- end }} +--- {{- if semverCompare ">=1.16" (printf "%s.%s" .Capabilities.KubeVersion.Major (trimSuffix "+" .Capabilities.KubeVersion.Minor) )}} apiVersion: apps/v1 {{- else }} @@ -107,6 +165,9 @@ spec: imagePullSecrets: - name: {{.Values.dockerRegistrySecret}} {{- end }} + {{- if and (eq (printf "%s" .Values.kube.auth) "rbac") (.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1") (.Values.console.pspEnabled) }} + serviceAccountName: "stratos-db" + {{- end }} volumes: - name: data {{- if .Values.mariadb.persistence.enabled }} diff --git a/deploy/kubernetes/console/templates/psp.yaml b/deploy/kubernetes/console/templates/psp.yaml new file mode 100644 index 0000000000..2910521ba0 --- /dev/null +++ b/deploy/kubernetes/console/templates/psp.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.console.pspEnabled (not .Values.console.pspName) }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ .Release.Name }}-psp +{{- if .Values.console.pspAnnotations }} + annotations: +{{ toYaml .Values.console.pspAnnotations | indent 4 }} +{{- end }} + labels: + app.kubernetes.io/name: "stratos" + app.kubernetes.io/instance: "{{ .Release.Name }}" + app.kubernetes.io/version: "{{ .Chart.AppVersion }}" + app.kubernetes.io/component: "console-psp" + helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" +{{- if .Values.console.pspExtraLabels }} +{{ toYaml .Values.console.pspExtraLabels | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: + - '*' + volumes: + - 'configMap' + - 'downwardAPI' + - 'emptyDir' + - 'persistentVolumeClaim' + - 'secret' + - 'projected' + hostNetwork: false + hostPID: false + hostIPC: false + runAsUser: + rule: 'RunAsAny' + runAsGroup: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' + readOnlyRootFilesystem: false +{{- end }} \ No newline at end of file diff --git a/deploy/kubernetes/console/templates/service-account.yaml b/deploy/kubernetes/console/templates/service-account.yaml index d8ef0e07d7..bdf6565de2 100644 --- a/deploy/kubernetes/console/templates/service-account.yaml +++ b/deploy/kubernetes/console/templates/service-account.yaml @@ -25,6 +25,16 @@ metadata: app.kubernetes.io/version: "{{ .Chart.AppVersion }}" helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" rules: +{{- if .Values.console.pspEnabled }} +- apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ default (printf "%s-psp" .Release.Name) .Values.console.pspName }} +{{- end }} - apiGroups: - "" resources: diff --git a/deploy/kubernetes/console/values.yaml b/deploy/kubernetes/console/values.yaml index 3a9f647bff..5c7b537ede 100644 --- a/deploy/kubernetes/console/values.yaml +++ b/deploy/kubernetes/console/values.yaml @@ -110,6 +110,18 @@ console: # Extra labels to apply to Pods podExtraLabels: {} + # Whether PodSecurityPolicy is enabled + pspEnabled: false + + # Optional name of a PodSecurityPolicy to use - if not specified, a default will be created + pspName: + + # Custom annotations to apply to Pod Security Policies + pspAnnotations: {} + + # Extra labels to apply to Pod Security Policies + pspExtraLabels: {} + # Node Selector for console Pod nodeSelector: {} diff --git a/electron/README.md b/electron/README.md index 276bf542f9..260f1ef74b 100644 --- a/electron/README.md +++ b/electron/README.md @@ -1,27 +1,71 @@ # Stratos Desktop -From the top-level Stratos folder: +Stratos Desktop packages Stratos into a Desktop application using the Electron framework. -- Install dependencies with `npm install` -- Change to the `electron folder` with `cd electron` -- Install dependencies for the electron UI with `npm install` -- Run the Electron app with `./run.sh all` +## Quick Start -> Note this builds both the frontend and backend and run the app +From the top-level folder, run: -- To build only the front end before running, use `./run.sh fe` -- To build only the back end before running, use `./run.sh be` -- To run without building either the the back end or front end, use `./run.sh` +``` +cd electron +./package.sh +``` +This will: -You can also run the UI with `ng serve` from the top-level folder and then start electron with: +- Install the npm dependencies for Stratos and the Electron App if needed +- Build the Stratos frontend and backend if needed +- Package the Stratos frontend and backend together with the Electron app + +On a fresh checkout, this will take some time to run - at the end you'll see some log messages indicating where the packaged outputs have been written. + +For Mac OS, you'll get `.app` and `.dmg` files created. The `.app` file can be opened from a terminal with the `open` command. + +> Note, the Stratos back-end is written in go and currently we only build for the current architecture that you are running on - it should be possible with some extra scripts to build +the desktop application for Mac, Windows and Linux in one-go. + +For more information on other scripts you can run for different build/dev scenarios, so below. + +## Overview + +This section provides a short overview on what goes on when Stratos runs as a desktop application. + +Stratos consists of a go backend and an Angular front-end. The Angular frontend is compiled into a set of static files. The go back-end serves up the static files in addition to providing the backend API for Stratos. The frontend resources reside in the `dist` folder. + +For the desktop build, we build the Stratos backend including an extra plugin `desktop` (in `src/jetstream/plugins/desktop`). This adds support for endpoints from local configuration. The frontend is also build including the additional `desktop-extensions` extension (in `src/frontend/packages/desltop-extensions`). This extension also includes a slightly modified theme and some small UI tweaks for the desktop use-case. + +The Electron wrapper is in the `electron` folder - the main file being the `index.js` file. Some of the things this does: + +- Finds a free port and runs the go backend, listening on that port +- Creates a window and loads the UI from the backend +- Sets up file watchers on the local config files that are read for local endpoint information and sends a notification to the Stratos app when these are changed, so that it can update the endpoints + +## Scripts + +From the `electron` folder: + + +To run the Desktop application: + +- `./run.sh all` - This will build both the backend and frontend and then run the app +- `./run.sh fe` - This will build frontend and then run the app +- `./run.sh be` - This will build the backend and then run the app + +> Note: You can also use `all` and `fe` and `be` with the `build.sh` script - when run without any arg, the build script will only build the frontend and backend if they have not previously been built + + +## Frontend Development + +You can run the frontend in development mode, from the top-level folder with `ng serve` just as you would normally. + +You can then run the desktop application using: `./run.sh dev` -to load the UI from `https://127.0.0.1:4200` +This will start the backend and launch the Electron application - but it will load the UI from `https://127.0.0.1:4200` rather than from the built version that the backend serves. -# Packaging +This allows you to make changes to the frontend code and have the application refresh within the webview, just as it would for regular development. -Packaging as a DMG file for Mac: +## Packaging -`./package.sh all` \ No newline at end of file +Electron Forge is used for packaging. \ No newline at end of file diff --git a/electron/build.sh b/electron/build.sh index c27e9b007c..83ead891f9 100755 --- a/electron/build.sh +++ b/electron/build.sh @@ -1,5 +1,12 @@ #!/usr/bin/env bash +# Colours +CYAN="\033[96m" +YELLOW="\033[93m" +RED="\033[91m" +RESET="\033[0m" +BOLD="\033[1m" + # Script folder DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" STRATOS="`cd "${DIR}/..";pwd`" @@ -27,7 +34,7 @@ fi pushd ${DIR} > /dev/null # Checks for fresh run on checkout if [ ! -d "./node_modules" ]; then - echo "Installing node modules ..." + echo -e "${CYAN}${BOLD}Installing node modules for Electron${RESET}" npm install fi popd > /dev/null @@ -37,18 +44,18 @@ pushd ${STRATOS} > /dev/null cat ./package.json | jq -r .version > ${DIR}/version if [ ! -d "./node_modules" ]; then - echo "Installing node modules in top-level folder ..." + echo -e "${CYAN}${BOLD}Installing node modules for front-end ...${RESET}" npm install fi if [ "$1" != "be" ] && [ ! -d "./dist" ]; then BUILD_FRONTEND=true - echo "Frontend has not been built - will build" + echo -e "${CYAN}${BOLD}Frontend has not been built - will build${RESET}" fi if [ ! -f "./src/jetstream/jetstream" ]; then BUILD_BACKEND=true - echo "Backend has not been built - will build" + echo -e "${CYAN}${BOLD}Backend has not been built - will build${RESET}" fi if [ "$BUILD_FRONTEND" == "true" ]; then diff --git a/electron/package-lock.json b/electron/package-lock.json index 3172b2375e..0473c37d54 100644 --- a/electron/package-lock.json +++ b/electron/package-lock.json @@ -1,6 +1,6 @@ { "name": "Stratos", - "version": "4.0.0", + "version": "4.4.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1479,9 +1479,9 @@ } }, "electron": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/electron/-/electron-11.0.3.tgz", - "integrity": "sha512-nNfbLi7Q1xfJXOEO2adck5TS6asY4Jxc332E4Te8XfQ9hcaC3GiCdeEqk9FndNCwxhJA5Lr9jfSGRTwWebFa/w==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-11.1.0.tgz", + "integrity": "sha512-RFAhR/852VMaRd9NSe7jprwSoG9dLc6u1GwnqRWg+/3cy/8Zrwt1Betw1lXiZH7hGuB9K2cqju83Xv5Pq5ZSGA==", "dev": true, "requires": { "@electron/get": "^1.0.1", @@ -1490,9 +1490,9 @@ }, "dependencies": { "@types/node": { - "version": "12.19.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.8.tgz", - "integrity": "sha512-D4k2kNi0URNBxIRCb1khTnkWNHv8KSL1owPmS/K5e5t8B2GzMReY7AsJIY1BnP5KdlgC4rj9jk2IkDMasIE7xg==", + "version": "12.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.15.tgz", + "integrity": "sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==", "dev": true }, "extract-zip": { diff --git a/electron/package.json b/electron/package.json index 55bc0bf085..06c46adacb 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,7 +1,9 @@ { "name": "Stratos", - "version": "4.0.0", + "version": "4.4.1", "main": "index.js", + "description": "Stratos Electron", + "license" : "Apache-2.0", "scripts": { "ng": "ng", "start": "electron-forge start", @@ -31,7 +33,7 @@ "@electron-forge/maker-squirrel": "^6.0.0-beta.52", "@electron-forge/maker-zip": "^6.0.0-beta.52", "@electron-forge/publisher-github": "^6.0.0-beta.52", - "electron": "^11.0.3" + "electron": "^11.1.0" }, "config": { "forge": { @@ -48,9 +50,7 @@ }, { "name": "@electron-forge/maker-zip", - "platforms": [ - "darwin" - ] + "platforms": [] }, { "name": "@electron-forge/maker-deb", @@ -68,7 +68,7 @@ } } ], - "publishers": [ + "_publishers": [ { "name": "@electron-forge/publisher-github", "config": { diff --git a/electron/package.sh b/electron/package.sh index 54daf1d880..fd0298b2b2 100755 --- a/electron/package.sh +++ b/electron/package.sh @@ -1,5 +1,19 @@ #!/usr/bin/env bash +# Colours +CYAN="\033[96m" +YELLOW="\033[93m" +RED="\033[91m" +RESET="\033[0m" +BOLD="\033[1m" +NORMAL="\033[21m" + +echo -e "${CYAN}${BOLD}=========================\nPackaging Stratos Desktop\n=========================\n${RESET}" + +echo -e "${YELLOW}Note: This will only package for your current architecture and OS${RESET}" + +OS="$(uname -s)" + # Script folder DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" STRATOS="`cd "${DIR}/..";pwd`" @@ -8,11 +22,27 @@ source "${DIR}/build.sh" pushd ${DIR} > /dev/null rm -rf dist/*es5* +VERSION=$(cat ./package.json | jq -r .version) popd > /dev/null -npm run package +#npm run package +npm run epublish # Mac - move the app to the Applications folder if [ "$1" == "-i" ]; then mv ./out/Stratos-darwin-x64/Stratos.app /Applications +fi + +if [ "${OS}" == "Darwin" ]; then + DMG="Stratos-${VERSION}.dmg" + if [ -d "${DIR}/out/Stratos-darwin-x64" ]; then + echo -e "${YELLOW}${BOLD}Mac App${NORMAL} is in ${BOLD}${DIR}/out/Stratos-darwin-x64/Stratos.app${RESET}" + echo -e "${CYAN}You can run the app with:" + echo -e "${YELLOW}open ${DIR}/out/Stratos-darwin-x64/Stratos.app${RESET}" + echo "" + fi + + if [ -f "${DIR}/out/make/${DMG}" ]; then + echo -e "${YELLOW}${BOLD}Mac DMG${NORMAL} is in: ${BOLD}${DIR}/out/make/${DMG}${RESET}" + fi fi \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1578216fce..68189fc08a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10578,9 +10578,9 @@ "dev": true }, "immer": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/immer/-/immer-6.0.9.tgz", - "integrity": "sha512-SyCYnAuiRf67Lvk0VkwFvwtDoEiCMjeamnHvRfnVDyc7re1/rQrNxuL+jJ7lA3WvdC4uznrvbmm+clJ9+XXatg==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", + "integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==" }, "import-cwd": { "version": "2.1.0", diff --git a/package.json b/package.json index ee4f176af5..9c46afd22f 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "@types/moment-timezone": "^0.5.13", "angular2-virtual-scroll": "^0.4.16", "core-js": "^3.6.5", - "immer": "^6.0.3", + "immer": "^8.0.1", "intersect": "^1.0.1", "lodash-es": "^4.17.14", "mappy-breakpoints": "^0.2.3", diff --git a/website/internal-versions.json b/website/internal-versions.json index 386ffae736..3c374eb08d 100644 --- a/website/internal-versions.json +++ b/website/internal-versions.json @@ -1,4 +1,5 @@ [ + "4.4.0:4.4.0:true", "4.3.0:4.3.0:true", "4.2.1:f912fb9ac3:false", "4.2.0:f912fb9ac3:true",