Merge branch 'main' into viewer-redux-integration
This commit is contained in:
+16
-4
@@ -211,12 +211,23 @@ jobs:
|
||||
key: cache-pre-commit-<<parameters.cache_prefix>>-{{ checksum "<<parameters.config_file>>" }}
|
||||
paths:
|
||||
- ~/.cache/pre-commit
|
||||
- restore_cache:
|
||||
name: Restore Yarn Package Cache
|
||||
keys:
|
||||
- yarn-packages-{{ checksum "yarn.lock" }}
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: yarn
|
||||
|
||||
- save_cache:
|
||||
name: Save Yarn Package Cache
|
||||
key: yarn-packages-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- .yarn/cache
|
||||
- .yarn/unplugged
|
||||
- run:
|
||||
name: Run pre-commit
|
||||
command: pre-commit run --all-files --config <<parameters.config_file>>
|
||||
- run:
|
||||
name: Run deployment pre-commit
|
||||
command: pre-commit run --all-files --config <<parameters.deployment_config_file>>
|
||||
command: ./.husky/pre-commit
|
||||
- run:
|
||||
command: git --no-pager diff
|
||||
name: git diff
|
||||
@@ -248,6 +259,7 @@ jobs:
|
||||
S3_SECRET_KEY: 'minioadmin'
|
||||
S3_BUCKET: 'speckle-server'
|
||||
S3_CREATE_BUCKET: 'true'
|
||||
S3_REGION: '' # optional, defaults to 'us-east-1'
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
|
||||
@@ -34,7 +34,7 @@ Connects #123
|
||||
|
||||
-->
|
||||
|
||||
## To-do before merge
|
||||
## To-do before merge:
|
||||
|
||||
<!---
|
||||
|
||||
@@ -72,9 +72,9 @@ This checklist is mostly useful as a reminder of small things that can easily be
|
||||
|
||||
forgotten – it is meant as a helpful tool rather than hoops to jump through.
|
||||
|
||||
Put an `x` in all the items that apply, make notes next to any that haven't been
|
||||
Put an `x` between the square brackets, e.g. [x], for all the items that apply,
|
||||
|
||||
addressed, and remove any items that are not relevant to this PR.
|
||||
make notes next to any that haven't been addressed, and remove any items that are not relevant to this PR.
|
||||
|
||||
-->
|
||||
|
||||
@@ -84,3 +84,19 @@ addressed, and remove any items that are not relevant to this PR.
|
||||
- [ ] My code follows a similar style to existing code.
|
||||
- [ ] I have added appropriate tests.
|
||||
- [ ] I have updated or added relevant documentation.
|
||||
|
||||
## References
|
||||
|
||||
<!---
|
||||
|
||||
(Optional -- remove this section if not needed )
|
||||
|
||||
Include **important** links regarding the implementation of this PR.
|
||||
|
||||
This usually includes a RFC or an aggregation of issues and/or individual conversations
|
||||
|
||||
that helped put this solution together. This helps ensure we retain and share knowledge
|
||||
|
||||
regarding the implementation, and may help others understand motivation and design decisions etc..
|
||||
|
||||
-->
|
||||
+28
-12
@@ -1,16 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
[ -n "$CI" ] && exit 0
|
||||
#!/usr/bin/env sh
|
||||
# shellcheck disable=SC1091
|
||||
set -e
|
||||
|
||||
#shellcheck source=/dev/null
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
if [ -n "$CI" ]
|
||||
then
|
||||
echo "running eslint"
|
||||
yarn lint
|
||||
yarn prettier:check
|
||||
else
|
||||
# shellcheck disable=SC1090
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
yarn lint-staged
|
||||
fi
|
||||
|
||||
yarn lint-staged
|
||||
|
||||
if ! command -v pre-commit &> /dev/null; then exit 0; fi
|
||||
echo "🔍 Detected pre-commit on this system. Running pre-commit checks..."
|
||||
pre-commit run --all-files --config .pre-commit-config.yaml
|
||||
echo "🔍 looking for additional linter dependencies"
|
||||
|
||||
if ! command -v hadolint &> /dev/null || ! command -v helm &> /dev/null || ! command -v shellcheck &> /dev/null; then exit 0; fi
|
||||
echo "🔍 Detected additional dependencies (hadolint, helm, and shellcheck) on this system. Running additional pre-commit checks..."
|
||||
pre-commit run --all-files --config .pre-commit-config.deployment.yaml
|
||||
check_dependencies_available() {
|
||||
for i in "${@}"
|
||||
do
|
||||
if ! command -v "${i}"; then
|
||||
echo "No ${i} executable found skipping additional checks" >&2
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check_dependencies_available pre-commit hadolint helm shellcheck
|
||||
|
||||
echo "All systems functional, running additional pre-commit checks..."
|
||||
pre-commit run --all-files
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# pre-commit for deployment related resources
|
||||
# e.g. shell files, dockerfiles, helm chart etc..
|
||||
repos:
|
||||
- repo: https://github.com/hadolint/hadolint
|
||||
rev: 'v2.10.0'
|
||||
hooks:
|
||||
- id: hadolint
|
||||
|
||||
# Cannot use official repo as it relies on Docker, which cannot be supported by either pre-commit.ci or CircleCI
|
||||
- repo: https://github.com/Jarmos-san/shellcheck-precommit
|
||||
rev: 'v0.2.0'
|
||||
hooks:
|
||||
- id: shellcheck-system
|
||||
|
||||
- repo: https://github.com/gruntwork-io/pre-commit
|
||||
rev: 'v0.1.17'
|
||||
hooks:
|
||||
- id: helmlint
|
||||
|
||||
ci:
|
||||
autoupdate_schedule: quarterly
|
||||
+14
-23
@@ -1,29 +1,20 @@
|
||||
# default pre-commit file, checks node.js code and basic file formatting
|
||||
# pre-commit for deployment related resources
|
||||
# e.g. shell files, dockerfiles, helm chart etc..
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/mirrors-eslint
|
||||
rev: 'v8.19.0' # Use the sha / tag you want to point at
|
||||
- repo: https://github.com/hadolint/hadolint
|
||||
rev: 'v2.10.0'
|
||||
hooks:
|
||||
- id: eslint
|
||||
types: [file]
|
||||
files: \.[jt]s$|vue$ # *.js, *.ts and vue
|
||||
exclude: '(\/|^)((generated\/.*)|(\..*\.([jt]sx?|vue)))$'
|
||||
args:
|
||||
- '--max-warnings=0'
|
||||
additional_dependencies:
|
||||
- eslint@8.11.0
|
||||
- eslint-config-prettier@8.5.0
|
||||
- eslint-plugin-vue@8.5.0
|
||||
- '@babel/eslint-parser@7.18.2'
|
||||
- '@babel/preset-env@t 7.16.11'
|
||||
- '@typescript-eslint/eslint-plugin@5.21.0'
|
||||
- '@typescript-eslint/parser@5.21.0'
|
||||
- typescript@4.5.4
|
||||
- '@rushstack/eslint-patch@1.1.3'
|
||||
- '@vue/eslint-config-typescript@11.0.0'
|
||||
- id: hadolint
|
||||
# Cannot use official repo as it relies on Docker, which cannot be supported by either pre-commit.ci or CircleCI
|
||||
- repo: https://github.com/Jarmos-san/shellcheck-precommit
|
||||
rev: 'v0.2.0'
|
||||
hooks:
|
||||
- id: shellcheck-system
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: 'v2.7.1' # Use the sha / tag you want to point at
|
||||
- repo: https://github.com/gruntwork-io/pre-commit
|
||||
rev: 'v0.1.17'
|
||||
hooks:
|
||||
- id: prettier
|
||||
- id: helmlint
|
||||
|
||||
ci:
|
||||
autoupdate_schedule: quarterly
|
||||
|
||||
@@ -39,6 +39,7 @@ services:
|
||||
S3_SECRET_KEY: 'minioadmin'
|
||||
S3_BUCKET: 'speckle-server'
|
||||
S3_CREATE_BUCKET: 'true'
|
||||
S3_REGION: '' # optional, defaults to 'us-east-1'
|
||||
FILE_SIZE_LIMIT_MB: 100
|
||||
|
||||
preview-service:
|
||||
@@ -72,10 +73,4 @@ services:
|
||||
environment:
|
||||
DEBUG: 'fileimport-service:*'
|
||||
PG_CONNECTION_STRING: 'postgres://speckle:speckle@postgres/speckle'
|
||||
|
||||
S3_ENDPOINT: 'http://minio:9000'
|
||||
S3_ACCESS_KEY: 'minioadmin'
|
||||
S3_SECRET_KEY: 'minioadmin'
|
||||
S3_BUCKET: 'speckle-server'
|
||||
|
||||
SPECKLE_SERVER_URL: 'http://speckle-server:3000'
|
||||
|
||||
+1
-1
@@ -12,9 +12,9 @@
|
||||
"build": "yarn workspaces foreach -ptv run build",
|
||||
"build:public": "yarn workspaces foreach -ptv --no-private run build",
|
||||
"lint": "eslint . --ext .js,.ts,.vue --max-warnings=0",
|
||||
"helm:readme:generate": "./utils/helm/update-documentation.sh",
|
||||
"prettier:check": "prettier --check .",
|
||||
"prettier:fix": "prettier --write .",
|
||||
"pre-commit": "pre-commit run --all-files --config .pre-commit-config.yaml && pre-commit run --all-files --config .pre-commit-config.deployment.yaml",
|
||||
"circleci:check": "circleci config validate ./.circleci/config.yml",
|
||||
"dev:docker:up": "docker-compose -f ./docker-compose-deps.yml -f ./docker-compose-dev.yml up -d",
|
||||
"dev:docker:down": "docker-compose -f ./docker-compose-deps.yml -f ./docker-compose-dev.yml down",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"node": "^16.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "cross-env S3_BUCKET=speckle-server POSTGRES_URL=postgres://speckle:speckle@localhost/speckle NODE_ENV=development SPECKLE_SERVER_URL=http://localhost:3000 nodemon ./src/daemon.js",
|
||||
"dev": "cross-env POSTGRES_URL=postgres://speckle:speckle@localhost/speckle NODE_ENV=development SPECKLE_SERVER_URL=http://localhost:3000 nodemon ./src/daemon.js",
|
||||
"parse:ifc": "node ./ifc/import_file.js /tmp/file_to_import/file 33763848d6 2e4bfb467a main File upload: steelplates.ifc",
|
||||
"lint": "eslint . --ext .js,.ts"
|
||||
},
|
||||
|
||||
@@ -56,11 +56,19 @@ set_real_ip_from 2a06:98c0::/29;
|
||||
real_ip_header CF-Connecting-IP;
|
||||
#real_ip_header X-Forwarded-For;
|
||||
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
client_max_body_size 100m;
|
||||
|
||||
# move default write paths to a custom directory
|
||||
# kubernetes can mount this directory and prevent writes to the root directory
|
||||
# https://github.com/openresty/docker-openresty/issues/119
|
||||
client_body_temp_path /var/run/openresty/nginx-client-body;
|
||||
proxy_temp_path /var/run/openresty/nginx-proxy;
|
||||
fastcgi_temp_path /var/run/openresty/nginx-fastcgi;
|
||||
uwsgi_temp_path /var/run/openresty/nginx-uwsgi;
|
||||
scgi_temp_path /var/run/openresty/nginx-scgi;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index app.html;
|
||||
|
||||
@@ -27,7 +27,7 @@ const getS3Config = () => {
|
||||
forcePathStyle: true,
|
||||
// s3ForcePathStyle: true,
|
||||
// signatureVersion: 'v4',
|
||||
region: 'us-east-1'
|
||||
region: process.env.S3_REGION || 'us-east-1'
|
||||
}
|
||||
}
|
||||
return s3Config
|
||||
|
||||
+7
-10
@@ -1,11 +1,11 @@
|
||||
const _ = require('lodash')
|
||||
import _ from 'lodash'
|
||||
|
||||
/**
|
||||
* Speckle role constants
|
||||
* - Stream - user roles in the context of a specific stream
|
||||
* - Server - user roles in the context of the entire server
|
||||
*/
|
||||
const Roles = Object.freeze({
|
||||
export const Roles = Object.freeze(<const>{
|
||||
Stream: {
|
||||
Owner: 'stream:owner',
|
||||
Contributor: 'stream:contributor',
|
||||
@@ -18,11 +18,14 @@ const Roles = Object.freeze({
|
||||
}
|
||||
})
|
||||
|
||||
export type ServerRoles = typeof Roles['Server'][keyof typeof Roles['Server']]
|
||||
export type StreamRoles = typeof Roles['Stream'][keyof typeof Roles['Stream']]
|
||||
|
||||
/**
|
||||
* Speckle scope constants
|
||||
* - Scopes define what kind of access has a user approved for a specific access token
|
||||
*/
|
||||
const Scopes = Object.freeze({
|
||||
export const Scopes = Object.freeze(<const>{
|
||||
Streams: {
|
||||
Read: 'streams:read',
|
||||
Write: 'streams:write'
|
||||
@@ -51,10 +54,4 @@ const Scopes = Object.freeze({
|
||||
* All scopes
|
||||
* @type {string[]}
|
||||
*/
|
||||
const AllScopes = _.flatMap(Scopes, (v) => Object.values(v))
|
||||
|
||||
module.exports = {
|
||||
Roles,
|
||||
Scopes,
|
||||
AllScopes
|
||||
}
|
||||
export const AllScopes = _.flatMap(Scopes, (v) => Object.values(v))
|
||||
@@ -1,208 +0,0 @@
|
||||
const { Roles, Scopes } = require('@/modules/core/helpers/mainConstants')
|
||||
const { getStream } = require('@/modules/core/services/streams')
|
||||
const { getRoles } = require('@/modules/shared')
|
||||
const {
|
||||
ForbiddenError: SFE,
|
||||
UnauthorizedError: SUE,
|
||||
ContextError,
|
||||
BadRequestError
|
||||
} = require('@/modules/shared/errors')
|
||||
|
||||
const authFailed = (context, error = null, fatal = false) => ({
|
||||
context,
|
||||
authResult: { authorized: false, error, fatal }
|
||||
})
|
||||
const authSuccess = (context) => ({
|
||||
context,
|
||||
authResult: { authorized: true, error: null }
|
||||
})
|
||||
|
||||
const validateRole =
|
||||
({ requiredRole, rolesLookup, iddqd, roleGetter }) =>
|
||||
async ({ context, authResult }) => {
|
||||
const roles = await rolesLookup()
|
||||
// having the required role doesn't rescue from authResult failure
|
||||
if (authResult.error) return { context, authResult }
|
||||
|
||||
// role validation has nothing to do with auth...
|
||||
//this check doesn't belong here, move it out to the auth pipeline
|
||||
if (!context.auth)
|
||||
return authFailed(context, new SUE('Cannot validate role without auth'))
|
||||
|
||||
const role = roles.find((r) => r.name === requiredRole)
|
||||
const myRole = roles.find((r) => r.name === roleGetter(context))
|
||||
|
||||
if (!role) return authFailed(context, new SFE('Invalid role requirement specified'))
|
||||
if (!myRole) return authFailed(context, new SFE('Your role is not valid'))
|
||||
if (myRole.name === iddqd || myRole.weight >= role.weight)
|
||||
return authSuccess(context)
|
||||
|
||||
return authFailed(context, new SFE('You do not have the required role'))
|
||||
}
|
||||
|
||||
const validateServerRole = ({ requiredRole }) =>
|
||||
validateRole({
|
||||
requiredRole,
|
||||
rolesLookup: getRoles,
|
||||
iddqd: Roles.Server.Admin,
|
||||
roleGetter: (context) => context.role
|
||||
})
|
||||
|
||||
const validateStreamRole = ({ requiredRole }) =>
|
||||
validateRole({
|
||||
requiredRole,
|
||||
rolesLookup: getRoles,
|
||||
iddqd: Roles.Stream.Owner,
|
||||
roleGetter: (context) => context.stream?.role
|
||||
})
|
||||
|
||||
// this could be still useful, if the operation doesnt require a stream context
|
||||
// const authorizeResolver = refactor the implementation in ../index.js
|
||||
|
||||
const validateScope =
|
||||
({ requiredScope }) =>
|
||||
async ({ context, authResult }) => {
|
||||
// having the required role doesn't rescue from authResult failure
|
||||
if (authResult.error) return { context, authResult }
|
||||
if (!context.scopes)
|
||||
return authFailed(context, new SFE('You do not have the required privileges.'))
|
||||
if (
|
||||
context.scopes.indexOf(requiredScope) === -1 &&
|
||||
context.scopes.indexOf('*') === -1
|
||||
)
|
||||
return authFailed(context, new SFE('You do not have the required privileges.'))
|
||||
return authSuccess(context)
|
||||
}
|
||||
|
||||
// this doesn't do any checks on the scopes, its sole responsibility is to add the
|
||||
// stream object to the pipeline context
|
||||
const contextRequiresStream =
|
||||
(streamGetter) =>
|
||||
// stream getter is an async func over { streamId, userId } returning a stream object
|
||||
// IoC baby...
|
||||
async ({ context, authResult, params }) => {
|
||||
if (!params?.streamId)
|
||||
return authFailed(
|
||||
context,
|
||||
new ContextError("The context doesn't have a streamId")
|
||||
)
|
||||
// because we're assigning to the context, it would raise if it would be null
|
||||
// its probably?? safer than returning a new context
|
||||
if (!context)
|
||||
return authFailed(context, new ContextError('The context is not defined'))
|
||||
|
||||
// cause stream getter could throw, its not a safe function if we want to
|
||||
// keep the pipeline rolling
|
||||
try {
|
||||
const stream = await streamGetter({
|
||||
streamId: params.streamId,
|
||||
userId: context?.userId
|
||||
})
|
||||
if (!stream)
|
||||
return authFailed(
|
||||
context,
|
||||
new BadRequestError('Stream inputs are malformed'),
|
||||
true
|
||||
)
|
||||
context.stream = stream
|
||||
return { context, authResult }
|
||||
} catch (err) {
|
||||
// this prob needs some more detailing to not leak internal errors
|
||||
return authFailed(context, new ContextError(err.message))
|
||||
}
|
||||
}
|
||||
|
||||
const allowForRegisteredUsersOnPublicStreamsEvenWithoutRole = async ({
|
||||
context,
|
||||
authResult
|
||||
}) =>
|
||||
context.auth && context.stream?.isPublic
|
||||
? authSuccess(context)
|
||||
: { context, authResult }
|
||||
|
||||
const allowForAllRegisteredUsersOnPublicStreamsWithPublicComments = async ({
|
||||
context,
|
||||
authResult
|
||||
}) =>
|
||||
context.auth && context.stream?.isPublic && context.stream?.allowPublicComments
|
||||
? authSuccess(context)
|
||||
: { context, authResult }
|
||||
|
||||
const allowAnonymousUsersOnPublicStreams = async ({ context, authResult }) => {
|
||||
return context.stream?.isPublic ? authSuccess(context) : { context, authResult }
|
||||
}
|
||||
|
||||
const authPipelineCreator = (steps) => {
|
||||
const pipeline = async ({ context, params }) => {
|
||||
let authResult = { authorized: false, error: null }
|
||||
for (const step of steps) {
|
||||
;({ context, authResult } = await step({ context, authResult, params }))
|
||||
if (authResult.fatal) break
|
||||
}
|
||||
// validate auth result a bit...
|
||||
if (authResult.authorized && authResult.error) throw new Error('Auth failure')
|
||||
return { context, authResult }
|
||||
}
|
||||
return pipeline
|
||||
}
|
||||
|
||||
//we could even add an auth middleware creator
|
||||
// todo move this to a webserver related module, it has no place here
|
||||
const authMiddlewareCreator = (steps) => {
|
||||
const pipeline = authPipelineCreator(steps)
|
||||
|
||||
const middleware = async (req, res, next) => {
|
||||
const { authResult } = await pipeline({ context: req.context, params: req.params })
|
||||
if (!authResult.authorized) {
|
||||
let message = 'Unknown AuthZ error'
|
||||
let status = 500
|
||||
if (authResult.error) {
|
||||
message = authResult.error.message
|
||||
if (authResult.error instanceof SUE) status = 401
|
||||
if (authResult.error instanceof SFE) status = 403
|
||||
}
|
||||
|
||||
return res.status(status).json({ error: message })
|
||||
}
|
||||
next()
|
||||
}
|
||||
return middleware
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const exampleMiddleware = authMiddlewareCreator([
|
||||
// at some point add the context preparation here too
|
||||
validateServerRole({ requiredRole: Roles.Server.User }),
|
||||
validateScope({ requiredScope: Scopes.Streams.Write }),
|
||||
contextRequiresStream(getStream),
|
||||
validateStreamRole({ requiredRole: Roles.Stream.Reviewer }),
|
||||
allowForRegisteredUsersOnPublicStreamsEvenWithoutRole
|
||||
])
|
||||
|
||||
module.exports = {
|
||||
authPipelineCreator,
|
||||
authSuccess,
|
||||
authFailed,
|
||||
validateRole,
|
||||
validateScope,
|
||||
validateServerRole,
|
||||
validateStreamRole,
|
||||
contextRequiresStream,
|
||||
ContextError,
|
||||
authMiddlewareCreator,
|
||||
allowForRegisteredUsersOnPublicStreamsEvenWithoutRole,
|
||||
allowForAllRegisteredUsersOnPublicStreamsWithPublicComments,
|
||||
allowAnonymousUsersOnPublicStreams,
|
||||
streamWritePermissions: [
|
||||
validateServerRole({ requiredRole: Roles.Server.User }),
|
||||
validateScope({ requiredScope: Scopes.Streams.Write }),
|
||||
contextRequiresStream(getStream),
|
||||
validateStreamRole({ requiredRole: Roles.Stream.Contributor })
|
||||
],
|
||||
streamReadPermissions: [
|
||||
validateServerRole({ requiredRole: Roles.Server.User }),
|
||||
validateScope({ requiredScope: Scopes.Streams.Read }),
|
||||
contextRequiresStream(getStream),
|
||||
validateStreamRole({ requiredRole: Roles.Stream.Contributor })
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
import Express from 'express'
|
||||
import {
|
||||
Scopes,
|
||||
Roles,
|
||||
ServerRoles,
|
||||
StreamRoles
|
||||
} from '@/modules/core/helpers/mainConstants'
|
||||
import { getRoles } from '@/modules/shared'
|
||||
import { getStream } from '@/modules/core/services/streams'
|
||||
|
||||
import {
|
||||
BaseError,
|
||||
ForbiddenError,
|
||||
UnauthorizedError,
|
||||
ContextError,
|
||||
BadRequestError
|
||||
} from '@/modules/shared/errors'
|
||||
// import { getbAllRoles } from '../core/services/generic'
|
||||
|
||||
interface AuthResult {
|
||||
authorized: boolean
|
||||
}
|
||||
|
||||
interface AuthFailedResult extends AuthResult {
|
||||
authorized: false
|
||||
error: BaseError | null
|
||||
fatal?: boolean
|
||||
}
|
||||
|
||||
interface Stream {
|
||||
role?: StreamRoles
|
||||
isPublic: boolean
|
||||
allowPublicComments: boolean
|
||||
}
|
||||
|
||||
export interface AuthContext {
|
||||
auth: boolean
|
||||
userId?: string
|
||||
role?: ServerRoles
|
||||
token?: string
|
||||
scopes?: string[]
|
||||
stream?: Stream
|
||||
}
|
||||
|
||||
interface AuthParams {
|
||||
streamId?: string
|
||||
}
|
||||
|
||||
interface AuthData {
|
||||
context: AuthContext
|
||||
authResult: AuthResult
|
||||
params?: AuthParams
|
||||
}
|
||||
|
||||
interface AuthFailedData extends AuthData {
|
||||
authResult: AuthFailedResult
|
||||
}
|
||||
|
||||
export const authFailed = (
|
||||
context: AuthContext,
|
||||
error: BaseError | null,
|
||||
fatal = false
|
||||
): AuthFailedData => ({
|
||||
context,
|
||||
authResult: { authorized: false, error, fatal }
|
||||
})
|
||||
|
||||
export const authSuccess = (context: AuthContext): AuthData => ({
|
||||
context,
|
||||
authResult: { authorized: true }
|
||||
})
|
||||
|
||||
type AvailableRoles = ServerRoles | StreamRoles
|
||||
|
||||
interface RoleData<T extends AvailableRoles> {
|
||||
weight: number
|
||||
name: T
|
||||
}
|
||||
|
||||
type AuthPipelineFunction = ({
|
||||
context,
|
||||
authResult,
|
||||
params
|
||||
}: AuthData) => Promise<AuthData>
|
||||
|
||||
const authHasFailed = (authResult: AuthResult): authResult is AuthFailedResult =>
|
||||
'error' in authResult
|
||||
|
||||
interface RoleValidationInput<T extends AvailableRoles> {
|
||||
requiredRole: T
|
||||
rolesLookup: () => Promise<RoleData<T>[]>
|
||||
iddqd: T
|
||||
roleGetter: (context: AuthContext) => T | null
|
||||
}
|
||||
|
||||
// interface StreamRoleValidationInput {
|
||||
// requiredRole: StreamRoles
|
||||
// rolesLookup: () => Promise<StreamRoleData[]>
|
||||
// iddqd: StreamRoles
|
||||
// roleGetter: (AuthContext) => StreamRoles
|
||||
// }
|
||||
|
||||
export function validateRole<T extends AvailableRoles>({
|
||||
requiredRole,
|
||||
rolesLookup,
|
||||
iddqd,
|
||||
roleGetter
|
||||
}: RoleValidationInput<T>): AuthPipelineFunction {
|
||||
return async ({ context, authResult }): Promise<AuthData> => {
|
||||
const roles = await rolesLookup()
|
||||
//having the required role doesn't rescue from authResult failure
|
||||
if (authHasFailed(authResult)) return { context, authResult }
|
||||
|
||||
// role validation has nothing to do with auth...
|
||||
//this check doesn't belong here, move it out to the auth pipeline
|
||||
if (!context.auth)
|
||||
return authFailed(
|
||||
context,
|
||||
new UnauthorizedError('Cannot validate role without auth')
|
||||
)
|
||||
|
||||
const contextRole = roleGetter(context)
|
||||
if (!contextRole)
|
||||
return authFailed(
|
||||
context,
|
||||
new ForbiddenError('You do not have the required role')
|
||||
)
|
||||
|
||||
const role = roles.find((r) => r.name === requiredRole)
|
||||
const myRole = roles.find((r) => r.name === contextRole)
|
||||
|
||||
if (!role)
|
||||
return authFailed(
|
||||
context,
|
||||
new ForbiddenError('Invalid role requirement specified')
|
||||
)
|
||||
if (!myRole)
|
||||
return authFailed(context, new ForbiddenError('Your role is not valid'))
|
||||
if (myRole.name === iddqd || myRole.weight >= role.weight)
|
||||
return authSuccess(context)
|
||||
return authFailed(context, new ForbiddenError('You do not have the required role'))
|
||||
}
|
||||
}
|
||||
|
||||
export const validateServerRole = ({ requiredRole }: { requiredRole: ServerRoles }) =>
|
||||
validateRole({
|
||||
requiredRole,
|
||||
rolesLookup: getRoles,
|
||||
iddqd: Roles.Server.Admin,
|
||||
roleGetter: (context) => context.role || null
|
||||
})
|
||||
|
||||
export const validateStreamRole = ({ requiredRole }: { requiredRole: StreamRoles }) =>
|
||||
validateRole({
|
||||
requiredRole,
|
||||
rolesLookup: getRoles,
|
||||
iddqd: Roles.Stream.Owner,
|
||||
roleGetter: (context) => context?.stream?.role || null
|
||||
})
|
||||
|
||||
export const validateScope =
|
||||
({ requiredScope }: { requiredScope: string }): AuthPipelineFunction =>
|
||||
async ({ context, authResult }) => {
|
||||
// having the required role doesn't rescue from authResult failure
|
||||
if (authHasFailed(authResult)) return { context, authResult }
|
||||
if (!context.scopes)
|
||||
return authFailed(
|
||||
context,
|
||||
new ForbiddenError('You do not have the required privileges.')
|
||||
)
|
||||
if (
|
||||
context.scopes.indexOf(requiredScope) === -1 &&
|
||||
context.scopes.indexOf('*') === -1
|
||||
)
|
||||
return authFailed(
|
||||
context,
|
||||
new ForbiddenError('You do not have the required privileges.')
|
||||
)
|
||||
return authSuccess(context)
|
||||
}
|
||||
|
||||
type StreamGetter = (params: { streamId: string; userId?: string }) => Promise<Stream>
|
||||
|
||||
// this doesn't do any checks on the scopes, its sole responsibility is to add the
|
||||
// stream object to the pipeline context
|
||||
export const contextRequiresStream =
|
||||
(streamGetter: StreamGetter): AuthPipelineFunction =>
|
||||
// stream getter is an async func over { streamId, userId } returning a stream object
|
||||
// IoC baby...
|
||||
async ({ context, authResult, params }) => {
|
||||
if (!params?.streamId)
|
||||
return authFailed(
|
||||
context,
|
||||
new ContextError("The context doesn't have a streamId")
|
||||
)
|
||||
// because we're assigning to the context, it would raise if it would be null
|
||||
// its probably?? safer than returning a new context
|
||||
if (!context)
|
||||
return authFailed(context, new ContextError('The context is not defined'))
|
||||
|
||||
// cause stream getter could throw, its not a safe function if we want to
|
||||
// keep the pipeline rolling
|
||||
try {
|
||||
const stream = await streamGetter({
|
||||
streamId: params.streamId,
|
||||
userId: context?.userId
|
||||
})
|
||||
if (!stream)
|
||||
return authFailed(
|
||||
context,
|
||||
new BadRequestError('Stream inputs are malformed'),
|
||||
true
|
||||
)
|
||||
context.stream = stream
|
||||
return { context, authResult }
|
||||
} catch (err) {
|
||||
// this prob needs some more detailing to not leak internal errors
|
||||
const error = err as Error
|
||||
return authFailed(context, new ContextError(error.message))
|
||||
}
|
||||
}
|
||||
|
||||
export const allowForRegisteredUsersOnPublicStreamsEvenWithoutRole: AuthPipelineFunction =
|
||||
async ({ context, authResult }) =>
|
||||
context.auth && context.stream?.isPublic
|
||||
? authSuccess(context)
|
||||
: { context, authResult }
|
||||
|
||||
export const allowForAllRegisteredUsersOnPublicStreamsWithPublicComments: AuthPipelineFunction =
|
||||
async ({ context, authResult }) =>
|
||||
context.auth && context.stream?.isPublic && context.stream?.allowPublicComments
|
||||
? authSuccess(context)
|
||||
: { context, authResult }
|
||||
|
||||
export const allowAnonymousUsersOnPublicStreams: AuthPipelineFunction = async ({
|
||||
context,
|
||||
authResult
|
||||
}) => (context.stream?.isPublic ? authSuccess(context) : { context, authResult })
|
||||
|
||||
export const authPipelineCreator = (
|
||||
steps: AuthPipelineFunction[]
|
||||
): AuthPipelineFunction => {
|
||||
const pipeline: AuthPipelineFunction = async ({
|
||||
context,
|
||||
params,
|
||||
authResult = { authorized: false }
|
||||
}) => {
|
||||
for (const step of steps) {
|
||||
;({ context, authResult } = await step({ context, authResult, params }))
|
||||
if (authHasFailed(authResult) && authResult?.fatal) break
|
||||
}
|
||||
// validate auth result a bit...
|
||||
if (authResult.authorized && authHasFailed(authResult))
|
||||
throw new Error('Auth failure')
|
||||
return { context, authResult }
|
||||
}
|
||||
return pipeline
|
||||
}
|
||||
|
||||
interface RequestWithContext extends Express.Request {
|
||||
context: AuthContext
|
||||
}
|
||||
|
||||
//we could even add an auth middleware creator
|
||||
// todo move this to a webserver related module, it has no place here
|
||||
export const authMiddlewareCreator = (steps: AuthPipelineFunction[]) => {
|
||||
const pipeline = authPipelineCreator(steps)
|
||||
|
||||
const middleware = async (
|
||||
req: RequestWithContext,
|
||||
res: Express.Response,
|
||||
next: Express.NextFunction
|
||||
) => {
|
||||
const { authResult } = await pipeline({
|
||||
context: req.context as AuthContext,
|
||||
params: req.params as AuthParams,
|
||||
authResult: { authorized: false }
|
||||
})
|
||||
if (!authResult.authorized) {
|
||||
let message = 'Unknown AuthZ error'
|
||||
let status = 500
|
||||
if (authHasFailed(authResult)) {
|
||||
message = authResult.error?.message || message
|
||||
if (authResult.error instanceof UnauthorizedError) status = 401
|
||||
if (authResult.error instanceof ForbiddenError) status = 403
|
||||
}
|
||||
|
||||
return res.status(status).json({ error: message })
|
||||
}
|
||||
next()
|
||||
}
|
||||
return middleware
|
||||
}
|
||||
|
||||
export const streamWritePermissions = [
|
||||
validateServerRole({ requiredRole: Roles.Server.User }),
|
||||
validateScope({ requiredScope: Scopes.Streams.Write }),
|
||||
contextRequiresStream(getStream as StreamGetter),
|
||||
validateStreamRole({ requiredRole: Roles.Stream.Contributor })
|
||||
]
|
||||
export const streamReadPermissions = [
|
||||
validateServerRole({ requiredRole: Roles.Server.User }),
|
||||
validateScope({ requiredScope: Scopes.Streams.Read }),
|
||||
contextRequiresStream(getStream as StreamGetter),
|
||||
validateStreamRole({ requiredRole: Roles.Stream.Contributor })
|
||||
]
|
||||
+7
-10
@@ -1,4 +1,4 @@
|
||||
const VError = require('verror')
|
||||
import { VError, Options } from 'verror'
|
||||
|
||||
/**
|
||||
* Base application error (don't use directly, treat it as abstract). Built on top of `verror` so that you can
|
||||
@@ -6,7 +6,7 @@ const VError = require('verror')
|
||||
*
|
||||
* This allows for much nicer error handling & monitoring
|
||||
*/
|
||||
class BaseError extends VError {
|
||||
export class BaseError extends VError {
|
||||
/**
|
||||
* Error code (override in child class)
|
||||
*/
|
||||
@@ -17,11 +17,10 @@ class BaseError extends VError {
|
||||
*/
|
||||
static defaultMessage = 'Unexpected error occurred!'
|
||||
|
||||
/**
|
||||
* @param {string | null} message
|
||||
* @param {import('verror').Options | Error} options
|
||||
*/
|
||||
constructor(message, options) {
|
||||
constructor(
|
||||
message: string | null | undefined,
|
||||
options: Options | Error | undefined = undefined
|
||||
) {
|
||||
// Resolve options correctly
|
||||
if (options) {
|
||||
const cause = options instanceof Error ? options : options.cause
|
||||
@@ -53,8 +52,6 @@ class BaseError extends VError {
|
||||
* Get collected info of this object and previous errors
|
||||
*/
|
||||
info() {
|
||||
return BaseError.info(this)
|
||||
return BaseError.info(this as unknown as Error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { BaseError }
|
||||
+12
-21
@@ -1,6 +1,6 @@
|
||||
const { BaseError } = require('./base')
|
||||
import { BaseError } from '@/modules/shared/errors/base'
|
||||
|
||||
class ForbiddenError extends BaseError {
|
||||
export class ForbiddenError extends BaseError {
|
||||
static code = 'FORBIDDEN_ERROR'
|
||||
static defaultMessage = 'Access to the resource is forbidden'
|
||||
}
|
||||
@@ -9,7 +9,7 @@ class ForbiddenError extends BaseError {
|
||||
* Use this in logic branches that should never execute, and if they do - it means
|
||||
* there's most definitely a bug in the code
|
||||
*/
|
||||
class LogicError extends BaseError {
|
||||
export class LogicError extends BaseError {
|
||||
static code = 'LOGIC_ERROR'
|
||||
static defaultMessage = 'An unexpected issue occurred'
|
||||
}
|
||||
@@ -17,51 +17,42 @@ class LogicError extends BaseError {
|
||||
/**
|
||||
* Use this to throw when user tries to access data that he shouldn't have access to
|
||||
*/
|
||||
class UnauthorizedError extends BaseError {
|
||||
export class UnauthorizedError extends BaseError {
|
||||
static code = 'UNAUTHORIZED_ACCESS_ERROR'
|
||||
static defaultMessage = 'Attempted unauthorized access to data'
|
||||
}
|
||||
|
||||
class NotFoundError extends BaseError {
|
||||
export class NotFoundError extends BaseError {
|
||||
static code = 'NOT_FOUND_ERROR'
|
||||
static defaultMessage = "These aren't the droids you're looking for."
|
||||
}
|
||||
|
||||
class BadRequestError extends BaseError {
|
||||
export class BadRequestError extends BaseError {
|
||||
static code = 'BAD_REQUEST_ERROR'
|
||||
static defaultMessage = 'The request contains invalid data'
|
||||
}
|
||||
|
||||
class ResourceMismatch extends BaseError {
|
||||
export class ResourceMismatch extends BaseError {
|
||||
static code = 'BAD_REQUEST_ERROR'
|
||||
static defaultMessage = 'The target resources mismatch'
|
||||
}
|
||||
/**
|
||||
* Use this to validate args
|
||||
*/
|
||||
class InvalidArgumentError extends BaseError {
|
||||
export class InvalidArgumentError extends BaseError {
|
||||
static code = 'INVALID_ARGUMENT_ERROR'
|
||||
static defaultMessage = 'Invalid arguments received'
|
||||
}
|
||||
class RichTextParseError extends BaseError {
|
||||
|
||||
export class RichTextParseError extends BaseError {
|
||||
static code = 'RICH_TEXT_PARSE_ERROR'
|
||||
static defaultMessage =
|
||||
'An error occurred while trying to parse the rich text document'
|
||||
}
|
||||
|
||||
class ContextError extends BaseError {
|
||||
export class ContextError extends BaseError {
|
||||
static code = 'CONTEXT_ERROR'
|
||||
static defaultMessage = 'The context is missing from the request'
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
BadRequestError,
|
||||
ForbiddenError,
|
||||
UnauthorizedError,
|
||||
NotFoundError,
|
||||
ResourceMismatch,
|
||||
InvalidArgumentError,
|
||||
RichTextParseError,
|
||||
ContextError,
|
||||
LogicError
|
||||
}
|
||||
export { BaseError }
|
||||
@@ -19,21 +19,12 @@ const pubsub = new RedisPubSub({
|
||||
})
|
||||
|
||||
/**
|
||||
* @typedef {Object} AuthContextPart
|
||||
* @property {boolean} auth Whether or not user is logged in
|
||||
* @property {string | undefined} userId User ID, if user is logged in
|
||||
* @property {string | undefined} role User role, if logged in
|
||||
* @property {string | undefined} token User token, if logged in
|
||||
* @property {string[] | undefined} scopes Token scopes, if logged in
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {AuthContextPart & {loaders: import('@/modules/core/loaders').RequestDataLoaders}} GraphQLContext
|
||||
* @typedef {import('@/modules/shared/authz').AuthContext & {loaders: import('@/modules/core/loaders').RequestDataLoaders}} GraphQLContext
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add data loaders to auth ctx
|
||||
* @param {AuthContextPart} ctx
|
||||
* @param {import('@/modules/shared/authz').AuthContext} ctx
|
||||
* @returns {GraphQLContext}
|
||||
*/
|
||||
async function addLoadersToCtx(ctx) {
|
||||
@@ -56,7 +47,7 @@ async function buildContext({ req, connection }) {
|
||||
|
||||
/**
|
||||
* Not just Graphql server context helper: sets req.context to have an auth prop (true/false), userId and server role.
|
||||
* @returns {AuthContextPart}
|
||||
* @returns {import('@/modules/shared/authz').AuthContext}
|
||||
*/
|
||||
async function contextApiTokenHelper({ req, connection }) {
|
||||
let token = null
|
||||
|
||||
@@ -6,7 +6,6 @@ const {
|
||||
validateRole,
|
||||
validateScope,
|
||||
contextRequiresStream,
|
||||
ContextError,
|
||||
allowForAllRegisteredUsersOnPublicStreamsWithPublicComments,
|
||||
allowForRegisteredUsersOnPublicStreamsEvenWithoutRole
|
||||
} = require('@/modules/shared/authz')
|
||||
@@ -14,7 +13,8 @@ const {
|
||||
ForbiddenError: SFE,
|
||||
UnauthorizedError: SUE,
|
||||
BadRequestError,
|
||||
UnauthorizedError
|
||||
UnauthorizedError,
|
||||
ContextError
|
||||
} = require('@/modules/shared/errors')
|
||||
|
||||
describe('AuthZ @shared', () => {
|
||||
@@ -45,7 +45,11 @@ describe('AuthZ @shared', () => {
|
||||
})
|
||||
it('Pipeline throws Error if authorized but has error', async () => {
|
||||
const borkedStep = async () => ({
|
||||
authResult: { authorized: true, error: new UnauthorizedError('Weird stuff') }
|
||||
authResult: {
|
||||
authorized: true,
|
||||
error: new UnauthorizedError('Weird stuff'),
|
||||
fatal: false
|
||||
}
|
||||
})
|
||||
const pipeline = authPipelineCreator([borkedStep])
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
require('../bootstrap')
|
||||
const { getUserByEmail } = require('@/modules/core/services/users')
|
||||
const { createPersonalAccessToken } = require('@/modules/core/services/tokens')
|
||||
const { createStream } = require('@/modules/core/services/streams')
|
||||
|
||||
const { createManyObjects } = require('@/test/helpers')
|
||||
const { fetch } = require('undici')
|
||||
const { init } = require(`@/app`)
|
||||
const request = require('supertest')
|
||||
const { exit } = require('yargs')
|
||||
|
||||
const main = async () => {
|
||||
const testStream = {
|
||||
name: 'Test Stream 01',
|
||||
description: 'wonderful test stream'
|
||||
}
|
||||
|
||||
// const userA = {
|
||||
// name: 'd1',
|
||||
// email: 'd.1@speckle.systems',
|
||||
// password: 'wowwow8charsplease'
|
||||
// }
|
||||
// userA.id = await createUser(userA)
|
||||
|
||||
const userA = await getUserByEmail({
|
||||
email: 'd.1@speckle.systems'
|
||||
})
|
||||
userA.token = `Bearer ${await createPersonalAccessToken(
|
||||
userA.id,
|
||||
'test token user A',
|
||||
[
|
||||
'streams:read',
|
||||
'streams:write',
|
||||
'users:read',
|
||||
'users:email',
|
||||
'tokens:write',
|
||||
'tokens:read',
|
||||
'profile:read',
|
||||
'profile:email'
|
||||
]
|
||||
)}`
|
||||
|
||||
testStream.id = await createStream({ ...testStream, ownerId: userA.id })
|
||||
|
||||
const { app } = await init()
|
||||
|
||||
const numObjs = 5000
|
||||
const objBatch = createManyObjects(numObjs)
|
||||
|
||||
const uploadRes = await request(app)
|
||||
.post(`/objects/${testStream.id}`)
|
||||
.set('Authorization', userA.token)
|
||||
.set('Content-type', 'multipart/form-data')
|
||||
.attach('batch1', Buffer.from(JSON.stringify(objBatch), 'utf8'))
|
||||
|
||||
console.log(uploadRes.status)
|
||||
const objectIds = objBatch.map((obj) => obj.id)
|
||||
|
||||
const res = await fetch(`http://localhost:3000/api/getobjects/${testStream.id}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: userA.token,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain'
|
||||
},
|
||||
body: JSON.stringify({ objects: JSON.stringify(objectIds) })
|
||||
})
|
||||
const data = await res.body.getReader().read()
|
||||
console.log(data)
|
||||
exit(0)
|
||||
}
|
||||
|
||||
main().then(console.log('created')).catch(console.log('failed'))
|
||||
@@ -79,6 +79,7 @@ services:
|
||||
S3_SECRET_KEY: 'minioadmin'
|
||||
S3_BUCKET: 'speckle-server'
|
||||
S3_CREATE_BUCKET: 'true'
|
||||
S3_REGION: '' # optional, defaults to 'us-east-1'
|
||||
|
||||
FILE_SIZE_LIMIT_MB: 100
|
||||
|
||||
@@ -110,11 +111,5 @@ services:
|
||||
environment:
|
||||
DEBUG: 'fileimport-service:*'
|
||||
PG_CONNECTION_STRING: 'postgres://speckle:speckle@postgres/speckle'
|
||||
WAIT_HOSTS: 'postgres:5432, minio:9000'
|
||||
|
||||
S3_ENDPOINT: 'http://minio:9000'
|
||||
S3_ACCESS_KEY: 'minioadmin'
|
||||
S3_SECRET_KEY: 'minioadmin'
|
||||
S3_BUCKET: 'speckle-server'
|
||||
|
||||
WAIT_HOSTS: 'postgres:5432'
|
||||
SPECKLE_SERVER_URL: 'http://speckle-server:3000'
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"comments": {
|
||||
"format": "##"
|
||||
},
|
||||
"tags": {
|
||||
"param": "@param",
|
||||
"section": "@section",
|
||||
"descriptionStart": "@descriptionStart",
|
||||
"descriptionEnd": "@descriptionEnd",
|
||||
"skip": "@skip",
|
||||
"extra": "@extra"
|
||||
},
|
||||
"modifiers": {
|
||||
"array": "array",
|
||||
"object": "object",
|
||||
"string": "string",
|
||||
"nullable": "nullable"
|
||||
},
|
||||
"regexp": {
|
||||
"paramsSectionTitle": "Parameters"
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ build:
|
||||
cd ../.. && docker build -t speckle/speckle-webhook-service:local -f packages/webhook-service/Dockerfile .
|
||||
cd ../.. && docker build -t speckle/speckle-fileimport-service:local -f packages/fileimport-service/Dockerfile .
|
||||
cd ../.. && docker build -t speckle/speckle-monitor-deployment:local -f utils/monitor-deployment/Dockerfile .
|
||||
cd ../.. && docker build -t speckle/speckle-test-deployment:local -f utils/test-deployment/Dockerfile .
|
||||
|
||||
echo "Making locally built images available inside minikube cluster. This takes a bit to copy, unfortunately..."
|
||||
|
||||
@@ -16,6 +17,7 @@ build:
|
||||
minikube image load speckle/speckle-webhook-service:local
|
||||
minikube image load speckle/speckle-fileimport-service:local
|
||||
minikube image load speckle/speckle-monitor-deployment:local
|
||||
minikube image load speckle/speckle-test-deployment:local
|
||||
|
||||
|
||||
install:
|
||||
|
||||
@@ -93,3 +93,143 @@ Part-of label
|
||||
{{- define "speckle.labels.part-of" -}}
|
||||
app.kubernetes.io/part-of: {{ include "speckle.name" . }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Creates a network policy egress definition for connecting to Redis
|
||||
|
||||
Expects the global context "$" to be passed as the parameter
|
||||
*/}}
|
||||
{{- define "speckle.networkpolicy.egress.redis" -}}
|
||||
{{- $port := (default "6379" .Values.redis.networkPolicy.port ) -}}
|
||||
{{- if .Values.redis.networkPolicy.inCluster.enabled -}}
|
||||
{{ include "speckle.networkpolicy.egress.internal" (dict "podSelector" .Values.redis.networkPolicy.inCluster.podSelector "namespaceSelector" .Values.redis.networkPolicy.inCluster.namespaceSelector "port" $port) }}
|
||||
{{- else if .Values.redis.networkPolicy.externalToCluster.enabled -}}
|
||||
{{ include "speckle.networkpolicy.egress.external" (dict "ip" .Values.redis.networkPolicy.externalToCluster.ipv4 "port" $port) }}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Creates a network policy egress definition for connecting to Postgres
|
||||
*/}}
|
||||
{{- define "speckle.networkpolicy.egress.postgres" -}}
|
||||
{{- $port := (default "5432" .Values.db.networkPolicy.port ) -}}
|
||||
{{- if .Values.db.networkPolicy.inCluster.enabled -}}
|
||||
{{ include "speckle.networkpolicy.egress.internal" (dict "podSelector" .Values.db.networkPolicy.inCluster.podSelector "namespaceSelector" .Values.db.networkPolicy.inCluster.namespaceSelector "port" $port) }}
|
||||
{{- else if .Values.db.networkPolicy.externalToCluster.enabled -}}
|
||||
{{ include "speckle.networkpolicy.egress.external" (dict "ip" .Values.db.networkPolicy.externalToCluster.ipv4 "port" $port) }}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Creates a network policy egress definition for connecting to Postgres
|
||||
*/}}
|
||||
{{- define "speckle.networkpolicy.egress.blob_storage" -}}
|
||||
{{- $port := (default "443" .Values.s3.networkPolicy.port ) -}}
|
||||
{{- if .Values.s3.networkPolicy.inCluster.enabled -}}
|
||||
{{ include "speckle.networkpolicy.egress.internal" (dict "podSelector" .Values.s3.networkPolicy.inCluster.podSelector "namespaceSelector" .Values.s3.networkPolicy.inCluster.namespaceSelector "port" $port) }}
|
||||
{{- else if .Values.s3.networkPolicy.externalToCluster.enabled -}}
|
||||
{{- $host := (urlParse .Values.s3.endpoint).host -}}
|
||||
{{- if (contains ":" $host) -}}
|
||||
{{- $host = first (mustRegexSplit ":" $host) -}}
|
||||
{{- end -}}
|
||||
{{- $ip := "" -}}
|
||||
{{- if eq (include "speckle.isIPv4" $host) "true" -}}
|
||||
{{- $ip = $host -}}
|
||||
{{- end -}}
|
||||
{{ include "speckle.networkpolicy.egress.external" (dict "ip" $ip "port" $port) }}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Creates a network policy egress definition for connecting to an external url:port or ip:port
|
||||
|
||||
Usage:
|
||||
{{ include "speckle.networkpolicy.egress.external" (dict "ip" "" "port" "6379") }}
|
||||
|
||||
Params:
|
||||
- ip - String - Optional - If the IP is not known, then egress is allowed to 0.0.0.0/0.
|
||||
- port - String - Required
|
||||
|
||||
Limitations:
|
||||
- IP is limited to IPv4 due to Kubernetes use of IPv4 CIDR
|
||||
- Kubernetes network policies do not support FQDN, hence if IP is not known egress is allowed to 0.0.0.0/0
|
||||
|
||||
*/}}
|
||||
{{- define "speckle.networkpolicy.egress.external" -}}
|
||||
{{- if not .port -}}
|
||||
{{- printf "\nNETWORKPOLICY ERROR: The port was not provided \"%s\"\n" .port | fail -}}
|
||||
{{- end -}}
|
||||
- to:
|
||||
- ipBlock:
|
||||
{{- if .ip }}
|
||||
cidr: {{ printf "%s/32" .ip }}
|
||||
{{- else }}
|
||||
# Kubernetes network policy does not support fqdn, so we have to allow egress anywhere
|
||||
cidr: 0.0.0.0/0
|
||||
# except to kubernetes pods or services
|
||||
except:
|
||||
- 10.0.0.0/8
|
||||
{{- end }}
|
||||
ports:
|
||||
- port: {{ printf "%s" .port }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Creates a network policy egress definition for connecting to a pod within the cluster
|
||||
|
||||
Usage:
|
||||
{{ include "speckle.networkpolicy.egress.internal" (dict "podSelectorLabels" {matchLabels.name=redis} "namespaceSelector" {matchLabels.name=redis} "port" "6379") }}
|
||||
|
||||
Params:
|
||||
- podSelector - Object - Required
|
||||
- namespaceSelector - Object - Required
|
||||
- port - String - Required
|
||||
|
||||
*/}}
|
||||
{{- define "speckle.networkpolicy.egress.internal" -}}
|
||||
{{- if not .podSelector -}}
|
||||
{{- printf "\nNETWORKPOLICY ERROR: The pod selector was not provided\n" | fail -}}
|
||||
{{- end -}}
|
||||
{{- if not .namespaceSelector -}}
|
||||
{{- printf "\nNETWORKPOLICY ERROR: The namespace selector was not provided\n" | fail -}}
|
||||
{{- end -}}
|
||||
{{- if not .port -}}
|
||||
{{- printf "\nNETWORKPOLICY ERROR: The port was not provided \"%s\"\n" .port | fail -}}
|
||||
{{- end -}}
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
{{ .namespaceSelector | toYaml | indent 8 }}
|
||||
podSelector:
|
||||
{{ .podSelector | toYaml | indent 8 }}
|
||||
ports:
|
||||
- port: {{ printf "%s" .port }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Tries to determine if a given string is a valid IP address
|
||||
Usage:
|
||||
{{ include "speckle.isIPv4" "123.45.67.89" }}
|
||||
|
||||
Params:
|
||||
- ip - String - Required - The string which we will try to determine is a valid IP address
|
||||
*/}}
|
||||
{{- define "speckle.isIPv4" -}}
|
||||
{{- if regexMatch "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" . -}}
|
||||
{{- printf "true" -}}
|
||||
{{- else -}}
|
||||
{{- printf "false" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Renders a value that contains template.
|
||||
Usage:
|
||||
{{ include "speckle.renderTpl" ( dict "value" .Values.path.to.value "context" $) }}
|
||||
*/}}
|
||||
{{- define "speckle.renderTpl" -}}
|
||||
{{- if typeIs "string" .value }}
|
||||
{{- tpl .value .context }}
|
||||
{{- else }}
|
||||
{{- tpl (.value | toYaml) .context }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
@@ -44,8 +44,20 @@ spec:
|
||||
cpu: {{ .Values.fileimport_service.limits.cpu }}
|
||||
memory: {{ .Values.fileimport_service.limits.memory }}
|
||||
|
||||
{{- if .Values.db.useCertificate }}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
|
||||
volumeMounts:
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
{{- if .Values.db.useCertificate }}
|
||||
- name: postgres-certificate
|
||||
mountPath: /postgres-certificate
|
||||
{{- end }}
|
||||
@@ -53,7 +65,7 @@ spec:
|
||||
env:
|
||||
- name: SPECKLE_SERVER_URL
|
||||
value: "http://speckle-server:3000"
|
||||
|
||||
|
||||
- name: PG_CONNECTION_STRING
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
@@ -68,31 +80,42 @@ spec:
|
||||
value: "/postgres-certificate/ca-certificate.crt"
|
||||
{{- end }}
|
||||
|
||||
|
||||
- name: S3_ENDPOINT
|
||||
value: {{ .Values.s3.endpoint }}
|
||||
- name: S3_ACCESS_KEY
|
||||
value: {{ .Values.s3.access_key }}
|
||||
- name: S3_BUCKET
|
||||
value: {{ .Values.s3.bucket }}
|
||||
- name: S3_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ .Values.secretName }}
|
||||
key: s3_secret_key
|
||||
|
||||
- name: FILE_IMPORT_TIME_LIMIT_MIN
|
||||
value: {{ .Values.fileimport_service.time_limit_min | quote }}
|
||||
|
||||
priorityClassName: low-priority
|
||||
{{- if .Values.fileimport_service.affinity }}
|
||||
affinity: {{- include "speckle.renderTpl" (dict "value" .Values.fileimport_service.affinity "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.fileimport_service.nodeSelector }}
|
||||
nodeSelector: {{- include "speckle.renderTpl" (dict "value" .Values.fileimport_service.nodeSelector "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.fileimport_service.tolerations }}
|
||||
tolerations: {{- include "speckle.renderTpl" (dict "value" .Values.fileimport_service.tolerations "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.fileimport_service.topologySpreadConstraints }}
|
||||
topologySpreadConstraints: {{- include "speckle.renderTpl" (dict "value" .Values.fileimport_service.topologySpreadConstraints "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.db.useCertificate }}
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
fsGroup: 25000
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
runAsGroup: 30000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
priorityClassName: low-priority
|
||||
{{- if .Values.fileimport_service.serviceAccount.create }}
|
||||
serviceAccountName: {{ include "fileimport_service.name" $ }}
|
||||
{{- end }}
|
||||
# Should be > File import timeout to allow finishing up imports
|
||||
terminationGracePeriodSeconds: 610
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
{{- if .Values.db.useCertificate }}
|
||||
- name: postgres-certificate
|
||||
configMap:
|
||||
name: postgres-certificate
|
||||
{{- end }}
|
||||
|
||||
# Should be > File import timeout to allow finishing up imports
|
||||
terminationGracePeriodSeconds: 610
|
||||
{{- end }}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
{{- if .Values.fileimport_service.networkPolicy.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ include "fileimport_service.name" $ }}
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
{{ include "fileimport_service.labels" . | indent 4 }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
{{ include "fileimport_service.selectorLabels" . | indent 6 }}
|
||||
policyTypes:
|
||||
- Egress
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: {{ default .Values.namespace .Values.prometheusMonitoring.namespace }}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
prometheus: {{ default "kube-prometheus-stack" .Values.prometheusMonitoring.release }}-prometheus
|
||||
ports:
|
||||
- port: metrics
|
||||
egress:
|
||||
# allow access to DNS
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
# allow egress to speckle-server
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
{{ include "server.selectorLabels" $ | indent 16 }}
|
||||
ports:
|
||||
- port: 3000
|
||||
# postgres
|
||||
{{ include "speckle.networkpolicy.egress.postgres" $ | indent 4 }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.fileimport_service.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "fileimport_service.name" $ }}
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
labels:
|
||||
{{ include "fileimport_service.labels" $ | indent 4 }}
|
||||
annotations:
|
||||
"kubernetes.io/enforce-mountable-secrets": "true"
|
||||
automountServiceAccountToken: false
|
||||
secrets:
|
||||
- name: {{ .Values.secretName }}
|
||||
{{- end -}}
|
||||
@@ -46,9 +46,24 @@ spec:
|
||||
port: www
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
|
||||
|
||||
env:
|
||||
- name: FILE_SIZE_LIMIT_MB
|
||||
value: {{ .Values.file_size_limit_mb | quote }}
|
||||
|
||||
priorityClassName: high-priority
|
||||
{{- if .Values.frontend.affinity }}
|
||||
affinity: {{- include "speckle.renderTpl" (dict "value" .Values.frontend.affinity "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.frontend.nodeSelector }}
|
||||
nodeSelector: {{- include "speckle.renderTpl" (dict "value" .Values.frontend.nodeSelector "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.frontend.tolerations }}
|
||||
tolerations: {{- include "speckle.renderTpl" (dict "value" .Values.frontend.tolerations "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.frontend.topologySpreadConstraints }}
|
||||
topologySpreadConstraints: {{- include "speckle.renderTpl" (dict "value" .Values.frontend.topologySpreadConstraints "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.frontend.serviceAccount.create }}
|
||||
serviceAccountName: {{ include "frontend.name" $ }}
|
||||
{{- end }}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{{- if .Values.frontend.networkPolicy.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ include "frontend.name" $ }}
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
{{ include "frontend.labels" . | indent 4 }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
{{ include "frontend.selectorLabels" . | indent 6 }}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
# allow ingress from the loadbalancer
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: {{ .Values.ingress.namespace }}
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ .Values.ingress.controllerName }}
|
||||
ports:
|
||||
- port: www
|
||||
egress: [] # block all egress
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,13 @@
|
||||
{{- if .Values.frontend.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "frontend.name" $ }}
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
labels:
|
||||
{{ include "frontend.labels" $ | indent 4 }}
|
||||
annotations:
|
||||
"kubernetes.io/enforce-mountable-secrets": "true"
|
||||
automountServiceAccountToken: false
|
||||
secrets: [] # no access to any secret
|
||||
{{- end -}}
|
||||
@@ -34,6 +34,15 @@ spec:
|
||||
cpu: {{ .Values.monitoring.limits.cpu }}
|
||||
memory: {{ .Values.monitoring.limits.memory }}
|
||||
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
|
||||
{{- if .Values.db.useCertificate }}
|
||||
volumeMounts:
|
||||
@@ -54,6 +63,18 @@ spec:
|
||||
{{- end }}
|
||||
|
||||
priorityClassName: low-priority
|
||||
{{- if .Values.monitoring.serviceAccount.create }}
|
||||
serviceAccountName: {{ include "monitoring.name" $ }}
|
||||
{{- end }}
|
||||
terminationGracePeriodSeconds: 10
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
fsGroup: 25000
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
runAsGroup: 30000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
{{- if .Values.db.useCertificate }}
|
||||
volumes:
|
||||
@@ -62,4 +83,15 @@ spec:
|
||||
name: postgres-certificate
|
||||
{{- end }}
|
||||
|
||||
terminationGracePeriodSeconds: 10
|
||||
{{- if .Values.monitoring.affinity }}
|
||||
affinity: {{- include "speckle.renderTpl" (dict "value" .Values.monitoring.affinity "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.monitoring.nodeSelector }}
|
||||
nodeSelector: {{- include "speckle.renderTpl" (dict "value" .Values.monitoring.nodeSelector "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.monitoring.tolerations }}
|
||||
tolerations: {{- include "speckle.renderTpl" (dict "value" .Values.monitoring.tolerations "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.monitoring.topologySpreadConstraints }}
|
||||
topologySpreadConstraints: {{- include "speckle.renderTpl" (dict "value" .Values.monitoring.topologySpreadConstraints "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
{{- if .Values.monitoring.networkPolicy.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ include "monitoring.name" $ }}
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
{{ include "monitoring.labels" . | indent 4 }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
{{ include "monitoring.selectorLabels" . | indent 6 }}
|
||||
policyTypes:
|
||||
- Egress
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: {{ default .Values.namespace .Values.prometheusMonitoring.namespace }}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
prometheus: {{ default "kube-prometheus-stack" .Values.prometheusMonitoring.release }}-prometheus
|
||||
ports:
|
||||
- port: metrics
|
||||
egress:
|
||||
# allow access to DNS
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
# postgres
|
||||
{{ include "speckle.networkpolicy.egress.postgres" $ | indent 4 }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.monitoring.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "monitoring.name" $ }}
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
labels:
|
||||
{{ include "monitoring.labels" $ | indent 4 }}
|
||||
annotations:
|
||||
"kubernetes.io/enforce-mountable-secrets": "true"
|
||||
automountServiceAccountToken: false
|
||||
secrets:
|
||||
- name: {{ .Values.secretName }}
|
||||
{{- end -}}
|
||||
@@ -43,8 +43,20 @@ spec:
|
||||
cpu: {{ .Values.preview_service.limits.cpu }}
|
||||
memory: {{ .Values.preview_service.limits.memory }}
|
||||
|
||||
{{- if .Values.db.useCertificate }}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
|
||||
volumeMounts:
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
{{- if .Values.db.useCertificate }}
|
||||
- name: postgres-certificate
|
||||
mountPath: /postgres-certificate
|
||||
{{- end }}
|
||||
@@ -64,13 +76,39 @@ spec:
|
||||
value: "/postgres-certificate/ca-certificate.crt"
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.preview_service.affinity }}
|
||||
affinity: {{- include "speckle.renderTpl" (dict "value" .Values.preview_service.affinity "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.preview_service.nodeSelector }}
|
||||
nodeSelector: {{- include "speckle.renderTpl" (dict "value" .Values.preview_service.nodeSelector "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.preview_service.tolerations }}
|
||||
tolerations: {{- include "speckle.renderTpl" (dict "value" .Values.preview_service.tolerations "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.preview_service.topologySpreadConstraints }}
|
||||
topologySpreadConstraints: {{- include "speckle.renderTpl" (dict "value" .Values.preview_service.topologySpreadConstraints "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
priorityClassName: low-priority
|
||||
{{- if .Values.preview_service.serviceAccount.create }}
|
||||
serviceAccountName: {{ include "preview_service.name" $ }}
|
||||
{{- end }}
|
||||
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
fsGroup: 25000
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
runAsGroup: 30000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
# Should be > preview generation time ( 1 hour for good measure )
|
||||
terminationGracePeriodSeconds: 3600
|
||||
|
||||
{{- if .Values.db.useCertificate }}
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
{{- if .Values.db.useCertificate }}
|
||||
- name: postgres-certificate
|
||||
configMap:
|
||||
name: postgres-certificate
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
{{- if .Values.preview_service.networkPolicy.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ include "preview_service.name" $ }}
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
{{ include "preview_service.labels" . | indent 4 }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
{{ include "preview_service.selectorLabels" . | indent 6 }}
|
||||
policyTypes:
|
||||
- Egress
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: {{ default .Values.namespace .Values.prometheusMonitoring.namespace }}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
prometheus: {{ default "kube-prometheus-stack" .Values.prometheusMonitoring.release }}-prometheus
|
||||
ports:
|
||||
- port: metrics
|
||||
egress:
|
||||
# allow access to DNS
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
# postgres
|
||||
{{ include "speckle.networkpolicy.egress.postgres" $ | indent 4 }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.preview_service.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "preview_service.name" $ }}
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
labels:
|
||||
{{ include "preview_service.labels" $ | indent 4 }}
|
||||
annotations:
|
||||
"kubernetes.io/enforce-mountable-secrets": "true"
|
||||
automountServiceAccountToken: false
|
||||
secrets:
|
||||
- name: {{ .Values.secretName }}
|
||||
{{- end -}}
|
||||
@@ -34,10 +34,22 @@ spec:
|
||||
cpu: {{ .Values.server.limits.cpu }}
|
||||
memory: {{ .Values.server.limits.memory }}
|
||||
|
||||
{{- if .Values.db.useCertificate }}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
|
||||
volumeMounts:
|
||||
- name: postgres-certificate
|
||||
mountPath: /postgres-certificate
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
{{- if .Values.db.useCertificate }}
|
||||
- name: postgres-certificate
|
||||
mountPath: /postgres-certificate
|
||||
{{- end }}
|
||||
|
||||
# Allow for k8s to remove the pod from the service endpoints to stop receive traffic
|
||||
@@ -129,6 +141,8 @@ spec:
|
||||
key: s3_secret_key
|
||||
- name: S3_CREATE_BUCKET
|
||||
value: "{{ .Values.s3.create_bucket }}"
|
||||
- name: S3_REGION
|
||||
value: "{{ .Values.s3.region }}"
|
||||
|
||||
{{- end }}
|
||||
|
||||
@@ -241,10 +255,37 @@ spec:
|
||||
name: {{ .Values.secretName }}
|
||||
key: apollo_key
|
||||
{{- end }}
|
||||
{{- if .Values.server.affinity }}
|
||||
affinity: {{- include "speckle.renderTpl" (dict "value" .Values.server.affinity "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.server.nodeSelector }}
|
||||
nodeSelector: {{- include "speckle.renderTpl" (dict "value" .Values.server.nodeSelector "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.server.tolerations }}
|
||||
tolerations: {{- include "speckle.renderTpl" (dict "value" .Values.server.tolerations "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.server.topologySpreadConstraints }}
|
||||
topologySpreadConstraints: {{- include "speckle.renderTpl" (dict "value" .Values.server.topologySpreadConstraints "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
priorityClassName: high-priority
|
||||
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
fsGroup: 25000
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
runAsGroup: 30000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
{{- if .Values.server.serviceAccount.create }}
|
||||
serviceAccountName: {{ include "server.name" $ }}
|
||||
{{- end }}
|
||||
terminationGracePeriodSeconds: 310
|
||||
{{- if .Values.db.useCertificate }}
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
{{- if .Values.db.useCertificate }}
|
||||
- name: postgres-certificate
|
||||
configMap:
|
||||
name: postgres-certificate
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
{{- if .Values.server.networkPolicy.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ include "server.name" $ }}
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
{{ include "server.labels" . | indent 4 }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
{{ include "server.selectorLabels" . | indent 6 }}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
egress:
|
||||
# allow access to DNS
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
{{- if .Values.server.sentry_dns }}
|
||||
# sentry.io https://docs.sentry.io/product/security/ip-ranges/#event-ingestion
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 34.120.195.249/32
|
||||
ports:
|
||||
- port: 443
|
||||
{{- end }}
|
||||
# redis
|
||||
{{ include "speckle.networkpolicy.egress.redis" $ | indent 4 }}
|
||||
# postgres
|
||||
{{ include "speckle.networkpolicy.egress.postgres" $ | indent 4 }}
|
||||
# blob storage
|
||||
{{ include "speckle.networkpolicy.egress.blob_storage" $ | indent 4 }}
|
||||
ingress:
|
||||
# allow ingress from the loadbalancer
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: {{ .Values.ingress.namespace }}
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ .Values.ingress.controllerName }}
|
||||
ports:
|
||||
- port: http
|
||||
# allow ingress from servicemonitor/prometheus
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: {{ default .Values.namespace .Values.prometheusMonitoring.namespace }}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
prometheus: {{ default "kube-prometheus-stack" .Values.prometheusMonitoring.release }}-prometheus
|
||||
ports:
|
||||
- port: http
|
||||
# allow ingress from the fileimport service
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
{{ include "fileimport_service.selectorLabels" $ | indent 14}}
|
||||
ports:
|
||||
- port: http
|
||||
{{- if .Values.helm_test_enabled }}
|
||||
# allow ingress from the test
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
{{ include "test.selectorLabels" $ | indent 14}}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.server.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "server.name" $ }}
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
labels:
|
||||
{{ include "server.labels" $ | indent 4 }}
|
||||
annotations:
|
||||
"kubernetes.io/enforce-mountable-secrets": "true"
|
||||
automountServiceAccountToken: false
|
||||
secrets:
|
||||
- name: {{ .Values.secretName }}
|
||||
{{- end -}}
|
||||
@@ -1,19 +1,22 @@
|
||||
{{ if .Values.enable_prometheus_monitoring }}
|
||||
|
||||
{{- if .Values.enable_prometheus_monitoring }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: speckle-server
|
||||
namespace: {{ .Values.namespace }}
|
||||
namespace: {{ default .Values.namespace .Values.prometheusMonitoring.namespace }}
|
||||
labels:
|
||||
app: speckle-server
|
||||
release: kube-prometheus-stack
|
||||
release: {{ default "kube-prometheus-stack" .Values.prometheusMonitoring.release }}
|
||||
{{ include "speckle.labels" . | indent 4 }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
project: speckle-server
|
||||
{{- if and .Values.prometheusMonitoring.namespace (ne .Values.namespace .Values.prometheusMonitoring.namespace) }}
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Values.namespace }}
|
||||
{{- end }}
|
||||
endpoints:
|
||||
- port: web
|
||||
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -24,5 +24,26 @@ spec:
|
||||
limits:
|
||||
cpu: {{ .Values.test.limits.cpu }}
|
||||
memory: {{ .Values.test.limits.memory }}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
|
||||
restartPolicy: Never
|
||||
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
runAsGroup: 30000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
{{- if .Values.test.serviceAccount.create }}
|
||||
serviceAccountName: {{ include "test.name" $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
{{- if and .Values.helm_test_enabled .Values.test.networkPolicy.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ include "test.name" $ }}
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
{{ include "test.labels" $ | indent 4 }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
{{ include "test.selectorLabels" $ | indent 6 }}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
# all ingress is blocked
|
||||
ingress: []
|
||||
|
||||
egress:
|
||||
# allow egress to speckle-server
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
{{ include "server.selectorLabels" $ | indent 16 }}
|
||||
ports:
|
||||
- port: http
|
||||
# allow access to DNS
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,13 @@
|
||||
{{- if .Values.test.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "test.name" $ }}
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
labels:
|
||||
{{ include "test.labels" $ | indent 4 }}
|
||||
annotations:
|
||||
"kubernetes.io/enforce-mountable-secrets": "true"
|
||||
automountServiceAccountToken: false
|
||||
secrets: [] # does not have access to any secrets
|
||||
{{- end -}}
|
||||
@@ -43,8 +43,20 @@ spec:
|
||||
cpu: {{ .Values.webhook_service.limits.cpu }}
|
||||
memory: {{ .Values.webhook_service.limits.memory }}
|
||||
|
||||
{{- if .Values.db.useCertificate }}
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
|
||||
volumeMounts:
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
{{- if .Values.db.useCertificate }}
|
||||
- name: postgres-certificate
|
||||
mountPath: /postgres-certificate
|
||||
{{- end }}
|
||||
@@ -64,13 +76,40 @@ spec:
|
||||
value: "/postgres-certificate/ca-certificate.crt"
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.webhook_service.affinity }}
|
||||
affinity: {{- include "speckle.renderTpl" (dict "value" .Values.webhook_service.affinity "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.webhook_service.nodeSelector }}
|
||||
nodeSelector: {{- include "speckle.renderTpl" (dict "value" .Values.webhook_service.nodeSelector "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.webhook_service.tolerations }}
|
||||
tolerations: {{- include "speckle.renderTpl" (dict "value" .Values.webhook_service.tolerations "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.webhook_service.topologySpreadConstraints }}
|
||||
topologySpreadConstraints: {{- include "speckle.renderTpl" (dict "value" .Values.webhook_service.topologySpreadConstraints "context" $) | nindent 8 }}
|
||||
{{- end }}
|
||||
|
||||
priorityClassName: low-priority
|
||||
{{- if .Values.webhook_service.serviceAccount.create }}
|
||||
serviceAccountName: {{ include "webhook_service.name" $ }}
|
||||
{{- end }}
|
||||
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 20000
|
||||
fsGroup: 25000
|
||||
fsGroupChangePolicy: OnRootMismatch
|
||||
runAsGroup: 30000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
# Should be > webhook max call time ( ~= 10 seconds )
|
||||
terminationGracePeriodSeconds: 30
|
||||
|
||||
{{- if .Values.db.useCertificate }}
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
{{- if .Values.db.useCertificate }}
|
||||
- name: postgres-certificate
|
||||
configMap:
|
||||
name: postgres-certificate
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
{{- if .Values.webhook_service.networkPolicy.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: {{ include "webhook_service.name" $ }}
|
||||
namespace: {{ .Values.namespace }}
|
||||
labels:
|
||||
{{ include "webhook_service.labels" . | indent 4 }}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
{{ include "webhook_service.selectorLabels" . | indent 6 }}
|
||||
policyTypes:
|
||||
- Egress
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: {{ default .Values.namespace .Values.prometheusMonitoring.namespace }}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
prometheus: {{ default "kube-prometheus-stack" .Values.prometheusMonitoring.release }}-prometheus
|
||||
ports:
|
||||
- port: metrics
|
||||
egress:
|
||||
# webhook can call anything external, but is blocked from egress elsewhere within the cluster
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 0.0.0.0/0
|
||||
# postgres
|
||||
{{ include "speckle.networkpolicy.egress.postgres" $ | indent 4 }}
|
||||
# allow access to DNS
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- port: 53
|
||||
protocol: UDP
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.webhook_service.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "webhook_service.name" $ }}
|
||||
namespace: {{ .Values.namespace | quote }}
|
||||
labels:
|
||||
{{ include "webhook_service.labels" $ | indent 4 }}
|
||||
annotations:
|
||||
"kubernetes.io/enforce-mountable-secrets": "true"
|
||||
automountServiceAccountToken: false
|
||||
secrets:
|
||||
- name: {{ .Values.secretName }}
|
||||
{{- end -}}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,133 +1,794 @@
|
||||
## @section Namespace
|
||||
##
|
||||
|
||||
## @param namespace The name of the namespace in which Speckle will be deployed.
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
|
||||
##
|
||||
namespace: speckle-test
|
||||
|
||||
## @param create_namespace Enabling this will create a new namespace into which Speckle will be deployed
|
||||
## The name of the namespace to create should be provided in the `namespace` parameter.
|
||||
##
|
||||
create_namespace: false
|
||||
|
||||
## @section SSL
|
||||
##
|
||||
|
||||
## @param domain The DNS host name at which this Speckle deployment will be reachable
|
||||
##
|
||||
domain: localhost
|
||||
|
||||
## @param ssl_canonical_url HTTPS protocol will be the preferred protocol for serving this Speckle deployment
|
||||
##
|
||||
ssl_canonical_url: true
|
||||
|
||||
## @param cert_manager_issuer The name of the ClusterIssuer kubernetes resource that provides the SSL Certificate
|
||||
##
|
||||
cert_manager_issuer: letsencrypt-staging
|
||||
|
||||
## @section Ingress metadata for NetworkPolicy
|
||||
## @descriptionStart
|
||||
## This section is ignored unless networkPolicy is enabled for frontend or server.
|
||||
## The NetworkPolicy uses this value to enable connections from the ingress controller pod in this namespace to reach Speckle.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
## @descriptionEnd
|
||||
##
|
||||
ingress:
|
||||
## @param ingress.namespace The namespace in which the ingress controller is deployed.
|
||||
namespace: ingress-nginx
|
||||
## @param ingress.controllerName The name of the Kubernetes pod in which the ingress controller is deployed.
|
||||
controllerName: ingress-nginx
|
||||
|
||||
## @section Common parameters
|
||||
##
|
||||
## @param docker_image_tag Speckle is published as a Docker Image. The version of the image which will be deployed is specified by this tag.
|
||||
##
|
||||
docker_image_tag: v2.3.3
|
||||
|
||||
## @param imagePullPolicy Determines the conditions when the Docker Images for Speckle should be pulled from the Image registry.
|
||||
## ref: https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy
|
||||
##
|
||||
imagePullPolicy: IfNotPresent
|
||||
|
||||
## @param secretName This is the name of the Kubernetes Secret resource in which secrets for Speckle are stored.
|
||||
## Secrets within this Secret resource may include Postgres and Redis connectin strings, S3 secret values, email server passwords, etc..
|
||||
## The expected key within the Secret resource is indicated elsewhere in this values.yaml file.
|
||||
## This is expected to be an opaque Secret resource type.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
##
|
||||
secretName: server-vars
|
||||
|
||||
## @param file_size_limit_mb This maximum size of any single file (unit is Megabytes) that can be uploaded to Speckle
|
||||
##
|
||||
file_size_limit_mb: 100
|
||||
|
||||
## @section Monitoring
|
||||
## @descriptionStart
|
||||
## This enables metrics generated by Speckle to be ingested by Prometheus: https://prometheus.io/
|
||||
## Enabling this requires Prometheus to have been deployed prior, as this resource expects the Prometheus Customer Resource Definition
|
||||
## for the ServiceMonitor to already be existing within the cluster.
|
||||
## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/getting-started.md#related-resources
|
||||
## @descriptionEnd
|
||||
##
|
||||
|
||||
## @param enable_prometheus_monitoring If enabled, Speckle deploys a Prometheus ServiceMonitor resource
|
||||
##
|
||||
enable_prometheus_monitoring: false
|
||||
|
||||
prometheusMonitoring:
|
||||
## @param prometheusMonitoring.namespace If provided, deploys Speckle's Prometheus resources in the given namespace
|
||||
## Prometheus prior to v0.19.0, or any version when deployed with default parameters, expects ServiceMonitors to be deployed within the same namespace.
|
||||
## This parameter allows the Prometheus resources provided by Speckle to be deployed in another namespace.
|
||||
## This allows Prometheus (< v0.19.0 or any version with default configuration) to be deployed in a separate namespace from Speckle.
|
||||
## Note that Speckle expect the namespace to exist prior to deployment.
|
||||
## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/getting-started.md#related-resources
|
||||
##
|
||||
namespace: ''
|
||||
## @param prometheusMonitoring.release If provided, adds the value to a `release` label on all the Prometheus resources deployed by Speckle
|
||||
## Prometheus prior to v0.19.0, or any version when deployed with default parameters, expects ServiceMonitors to be selectable on the release label.
|
||||
## This parameter allows Prometheus to be deployed with a non-default release name.
|
||||
## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/getting-started.md#related-resources
|
||||
##
|
||||
release: ''
|
||||
|
||||
## @section Postgres Database
|
||||
## @descriptionStart
|
||||
## Defines parameters related to connections to the Postgres database.
|
||||
## A secret containing the connection string to the Postgres database must stored within the Kubernetes cluster as an opaque Kubernetes Secret.
|
||||
## The name of the secret must match the `secretName` parameter, and the key within this secret must be `postgres_url`.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
## @descriptionEnd
|
||||
##
|
||||
db:
|
||||
# postgres_url: secret -> postgres_url
|
||||
## @param db.useCertificate If enabled, the certificate defined in db.certificate is used to verify TLS connections to the Postgres database
|
||||
##
|
||||
useCertificate: false
|
||||
## @param db.maxConnectionsServer The number of connections to the Postgres database to provide in the connection pool
|
||||
##
|
||||
maxConnectionsServer: 4
|
||||
## @param db.certificate The x509 public certificate for SSL connections to the Postgres database
|
||||
## Use of this certificate requires db.useCertificate to be enabled and an appropriate value for db.PGSSLMODE provided.
|
||||
## The value must be formatted as a multi-line string. We recommend using the pipe-symbol and taking care to
|
||||
## indent all lines of the value correctly.
|
||||
## ref: https://helm.sh/docs/chart_template_guide/yaml_techniques/#strings-in-yaml
|
||||
##
|
||||
certificate: '' # Multi-line string with the contents of `ca-certificate.crt`
|
||||
## @param db.PGSSLMODE This defines the level of security used when connecting to the Postgres database
|
||||
## Postgres provides different froms of protection from different types of threat when communicating between the client (Speckle) and the Postgres database.
|
||||
## ref: https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-PROTECTION
|
||||
##
|
||||
PGSSLMODE: require
|
||||
## @extra db.networkPolicy If networkPolicy is enabled for any service, this provides the NetworkPolicy with the necessary details to allow egress connections to the Postgres database
|
||||
##
|
||||
networkPolicy:
|
||||
## @param db.networkPolicy.port the port on the server providing the Postgres database (default: "5432")
|
||||
##
|
||||
port: ''
|
||||
## @extra db.networkPolicy.externalToCluster Only required if the Postgres database is not hosted within the Kubernetes cluster in which Speckle will be deployed.
|
||||
##
|
||||
externalToCluster:
|
||||
## @param db.networkPolicy.externalToCluster.enabled If enabled, indicates that the Postgres database is hosted externally to the Kubernetes cluster
|
||||
## Only one of externalToCluster or inCluster should be enabled. If both are enabled then inCluster takes precedence and is the only one deployed
|
||||
##
|
||||
enabled: true
|
||||
## @param db.networkPolicy.externalToCluster.host The domain name at which the Postgres database is hosted.
|
||||
## This should match the value provided within the connection string.
|
||||
## Provide the IP address if available (use the `ipv4` parameter), as the IP address takes precedence.
|
||||
##
|
||||
host: ''
|
||||
## @param db.networkPolicy.externalToCluster.ipv4 The IP address at which the Postgres database is hosted
|
||||
## This should be an IP address not within the Kubernetes Cluster Pod or Service IP ranges.
|
||||
## If both host and ipv4 parameters are provided, ipv4 takes precedence and host is ignored.
|
||||
##
|
||||
ipv4: ''
|
||||
## @extra db.networkPolicy.inCluster Only required if the Postgres database is hosted within the Kubernetes cluster in which Speckle will be deployed.
|
||||
##
|
||||
inCluster:
|
||||
## @param db.networkPolicy.inCluster.enabled If enabled, indicates that the Postgres database is hosted withing the same Kubernetes cluster in which Speckle will be deployed
|
||||
## Only one of externalToCluster or inCluster should be enabled. If both are enabled then inCluster takes precedence and is the only set of egress network policy rules deployed.
|
||||
##
|
||||
enabled: false
|
||||
## @param db.networkPolicy.inCluster.podSelector The pod Selector yaml object used to uniquely select the Postgres database pods within the cluster and given namespace
|
||||
## This is a Kubernetes podSelector object
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
##
|
||||
podSelector: {}
|
||||
## @param db.networkPolicy.inCluster.namespaceSelector The namespace selector yaml object used to uniquely select the namespace in which the Postgres database pods are deployed
|
||||
## This is a Kubernetes namespaceSelector object
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
##
|
||||
namespaceSelector: {}
|
||||
|
||||
## @section S3 Compatible Storage
|
||||
## @descriptionStart
|
||||
## Defines parameters related to connecting to the S3 compatible storage.
|
||||
## A secret containing the secret key must stored within the Kubernetes cluster as an opaque Kubernetes Secret.
|
||||
## The name of the Kubernetes Secret resource must match the `secretName` parameter, and the key within this Kubernetes Secret must be `s3_secret_key`.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
## @descriptionEnd
|
||||
##
|
||||
s3:
|
||||
## @param s3.endpoint The URL at which the s3 compatible storage is hosted
|
||||
## The url should be prefixed by the protocol (e.g. `https://`)
|
||||
## The url may need to include the port if it is not the default (e.g. `443` for `https` protocol)
|
||||
##
|
||||
endpoint: ''
|
||||
## @param s3.bucket The s3 compatible bucket in which Speckle data will be stored
|
||||
## The access key should be granted write permissions to this bucket
|
||||
##
|
||||
bucket: ''
|
||||
## @param s3.access_key The key of the access key used to authenticate with the s3 compatible storage
|
||||
##
|
||||
access_key: ''
|
||||
## @param s3.create_bucket If enabled, will create a bucket with the given bucket name at this endpoint
|
||||
## If enabled, the access_key must be granted the appropriate bucket creation privileges
|
||||
##
|
||||
create_bucket: 'false'
|
||||
# secret_key: secret -> s3_secret_key
|
||||
## @param s3.region The region in which the bucket resides (or will be created in).
|
||||
## If not provided, defaults to `us-east-1`. For many providers of s3 compatible storage, such as minio, this value may be ignored.
|
||||
##
|
||||
region: ''
|
||||
## @extra s3.networkPolicy If networkPolicy is enabled for any service, this provides the NetworkPolicy with the necessary details to allow egress connections to the s3 compatible storage
|
||||
##
|
||||
networkPolicy:
|
||||
## @param s3.networkPolicy.port the port on the server providing the s3 compatible storage (default: "443")
|
||||
##
|
||||
port: ''
|
||||
## @extra s3.networkPolicy.externalToCluster Only required if the s3 compatible storage is not hosted within the Kubernetes cluster in which Speckle will be deployed.
|
||||
##
|
||||
externalToCluster:
|
||||
## @param s3.networkPolicy.externalToCluster.enabled If enabled, indicates that the s3 compatible storage is hosted externally to the Kubernetes cluster
|
||||
## Only one of externalToCluster or inCluster should be enabled. If both are enabled then inCluster takes precedence and is the only one deployed
|
||||
##
|
||||
enabled: true
|
||||
## @param s3.networkPolicy.externalToCluster.host The domain name at which the s3 compatible storage is hosted.
|
||||
## This should match the value provided within the connection string.
|
||||
## Provide the IP address if available (use the `ipv4` parameter), as the IP address takes precedence.
|
||||
##
|
||||
host: ''
|
||||
## @param s3.networkPolicy.externalToCluster.ipv4 The IP address at which the s3 compatible storage is hosted
|
||||
## This should be an IP address not within the Kubernetes Cluster Pod or Service IP ranges.
|
||||
## If both host and ipv4 parameters are provided, ipv4 takes precedence and host is ignored.
|
||||
##
|
||||
ipv4: ''
|
||||
## @extra s3.networkPolicy.inCluster Only required if the s3 compatible storage is hosted within the Kubernetes cluster in which Speckle will be deployed.
|
||||
##
|
||||
inCluster:
|
||||
## @param s3.networkPolicy.inCluster.enabled If enabled, indicates that the s3 compatible storage is hosted withing the same Kubernetes cluster in which Speckle will be deployed
|
||||
## Only one of externalToCluster or inCluster should be enabled. If both are enabled then inCluster takes precedence and is the only set of egress network policy rules deployed.
|
||||
##
|
||||
enabled: false
|
||||
## @param s3.networkPolicy.inCluster.podSelector The pod Selector yaml object used to uniquely select the s3 compatible storage pods within the cluster and given namespace
|
||||
## This is a Kubernetes podSelector object
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
##
|
||||
podSelector: {}
|
||||
## @param s3.networkPolicy.inCluster.namespaceSelector The namespace selector yaml object used to uniquely select the namespace in which the s3 compatible storage pods are deployed
|
||||
## This is a Kubernetes namespaceSelector object
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
##
|
||||
namespaceSelector: {}
|
||||
|
||||
#redis:
|
||||
# redis_url: secret -> redis_url
|
||||
## @section Redis Store
|
||||
## @descriptionStart
|
||||
## Defines parameters related to connecting to the Redis Store.
|
||||
## A secret containing the redis url (containing domain, username, and password) must stored within the Kubernetes cluster as an opaque Kubernetes Secret.
|
||||
## The name of the Kubernetes Secret resource must match the `secretName` parameter, and the key within this Kubernetes Secret resource must be `redis_url`.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
## @descriptionEnd
|
||||
##
|
||||
redis:
|
||||
## @extra redis.networkPolicy If networkPolicy is enabled for Speckle server, this provides the NetworkPolicy with the necessary details to allow egress connections to the Redis store
|
||||
##
|
||||
networkPolicy:
|
||||
## @param redis.networkPolicy.port the port on the server providing the Redis store (default: "6379")
|
||||
##
|
||||
port: ''
|
||||
## @extra redis.networkPolicy.externalToCluster Only required if the Redis store is not hosted within the Kubernetes cluster in which Speckle will be deployed.
|
||||
##
|
||||
externalToCluster:
|
||||
## @param redis.networkPolicy.externalToCluster.enabled If enabled, indicates that the Redis store is hosted externally to the Kubernetes cluster
|
||||
## Only one of externalToCluster or inCluster should be enabled. If both are enabled then inCluster takes precedence and is the only one deployed
|
||||
##
|
||||
enabled: true
|
||||
## @param redis.networkPolicy.externalToCluster.host The domain name at which the Redis store is hosted.
|
||||
## This should match the value provided within the connection string.
|
||||
## Provide the IP address if available (use the `ipv4` parameter), as the IP address takes precedence.
|
||||
##
|
||||
host: ''
|
||||
## @param redis.networkPolicy.externalToCluster.ipv4 The IP address at which the Redis store is hosted
|
||||
## This should be an IP address not within the Kubernetes Cluster Pod or Service IP ranges.
|
||||
## If both host and ipv4 parameters are provided, ipv4 takes precedence and host is ignored.
|
||||
##
|
||||
ipv4: ''
|
||||
## @extra redis.networkPolicy.inCluster is only required if the Redis store is hosted within the Kubernetes cluster in which Speckle will be deployed.
|
||||
##
|
||||
inCluster:
|
||||
## @param redis.networkPolicy.inCluster.enabled If enabled, indicates that the Redis store is hosted withing the same Kubernetes cluster in which Speckle will be deployed
|
||||
## Only one of externalToCluster or inCluster should be enabled. If both are enabled then inCluster takes precedence and is the only set of egress network policy rules deployed.
|
||||
##
|
||||
enabled: false
|
||||
## @param redis.networkPolicy.inCluster.podSelector The pod Selector yaml object used to uniquely select the Redis store pods within the cluster and given namespace
|
||||
## This is a Kubernetes podSelector object
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
##
|
||||
podSelector: {}
|
||||
## @param redis.networkPolicy.inCluster.namespaceSelector The namespace selector yaml object used to uniquely select the namespace in which the Redis store pods are deployed
|
||||
## This is a Kubernetes namespaceSelector object
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
##
|
||||
namespaceSelector: {}
|
||||
|
||||
## @section Server
|
||||
## @descriptionStart
|
||||
## Defines parameters related to the backend server component of Speckle.
|
||||
## A secret containing the an unique value (this can be generated randomly) must stored within the Kubernetes cluster as an opaque Kubernetes Secret.
|
||||
## The name of the Kubernetes Secret resource must match the `secretName` parameter, and the key within this Secret resource must be `session_secret`.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
## @descriptionEnd
|
||||
##
|
||||
server:
|
||||
## @param server.replicas The number of instances of the Server pod to be deployed within the cluster.
|
||||
##
|
||||
replicas: 1
|
||||
# session_secret: secret -> `session_secret`
|
||||
## @extra server.auth Speckle provides a number of different mechanisms for authenticating users. Each available option must be configured here.
|
||||
##
|
||||
auth:
|
||||
local:
|
||||
## @param server.auth.local.enabled If enabled, users can register and authenticate with an email address and password.
|
||||
## The login details are stored in the Postgres database connected to Speckle and are encrypted.
|
||||
##
|
||||
enabled: true
|
||||
google:
|
||||
## @param server.auth.google.enabled If enabled, users can authenticate via Google with their Google account credentials.
|
||||
## If enabling Google, the `server.auth.google.client_id` parameter is required.
|
||||
## A secret containing the client secret must stored within the Kubernetes cluster as an opaque Kubernetes Secret.
|
||||
## The name of the Kubernetes Secret resource must match the `secretName` parameter, and the key within this Kubernetes Secret must be `google_client_secret`.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
##
|
||||
enabled: false
|
||||
## @param server.auth.google.client_id This is the ID for Speckle that you have registered with Google.
|
||||
##
|
||||
client_id: ''
|
||||
# client_secret: secret -> `google_client_secret`
|
||||
github:
|
||||
## @param server.auth.github.enabled If enabled, users can authenticate via Github with their Github account credentials.
|
||||
## If enabling Github authentication, the `server.auth.github.client_id` parameter is required.
|
||||
## A secret containing the client secret must stored within the Kubernetes cluster as an opaque Kubernetes Secret.
|
||||
## The name of the Kubernetes Secret resource must match the `secretName` parameter, and the key within this Kubernetes Secret must be `github_client_secret`.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
##
|
||||
enabled: false
|
||||
## @param server.auth.github.client_id This is the ID for Speckle that you have registered with Github
|
||||
##
|
||||
client_id: ''
|
||||
# client_secret: secret -> `github_client_secret`
|
||||
azure_ad:
|
||||
## @param server.auth.azure_ad.enabled If enabled, users can authenticate via Azure Active Directory.
|
||||
## If enabling Azure Active Directory authentication, a secret containing the client secret must stored within the Kubernetes cluster as an opaque Kubernetes Secret.
|
||||
## The name of the Kubernetes Secret resource must match the `secretName` parameter, and the key within this Kubernetes Secret must be `azure_ad_client_secret`.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
##
|
||||
enabled: false
|
||||
## @param server.auth.azure_ad.org_name This is the Organisation Name that you have registered with Azure
|
||||
##
|
||||
org_name: ''
|
||||
## @param server.auth.azure_ad.identity_metadata This is the identity metadata for Speckle that you have registered with Azure
|
||||
##
|
||||
identity_metadata: ''
|
||||
## @param server.auth.azure_ad.issuer This is the issuer name for Speckle that you have registered with Azure
|
||||
##
|
||||
issuer: ''
|
||||
## @param server.auth.azure_ad.client_id This is the ID for Speckle that you have registered with Azure
|
||||
##
|
||||
client_id: ''
|
||||
# client_secret: secret -> `azure_ad_client_secret`
|
||||
## @extra server.email Speckle can communicate with users via email, providing account verification and notification.
|
||||
##
|
||||
email:
|
||||
## @param server.email.enabled If enabled, Speckle can send email to users - for example, email verification for account registration.
|
||||
## If enabling Email, a secret containing the password to the email server must stored within the Kubernetes cluster as an opaque Kubernetes Secret.
|
||||
## The name of the Kubernetes Secret resource must match the `secretName` parameter, and the key within this Kubernetes Secret must be `email_password`.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
##
|
||||
enabled: false
|
||||
## @param server.email.host The domain name or IP address of the server hosting the email service.
|
||||
##
|
||||
host: ''
|
||||
## @param server.email.port The port on the server for the email service.
|
||||
##
|
||||
port: ''
|
||||
## @param server.email.username The username with which Speckle will authenticate with the email service.
|
||||
## Note that the `email_password` is expected to be provided in the Kubernetes Secret with the name provided in the `secretName` parameter.
|
||||
##
|
||||
username: ''
|
||||
# password: secret -> `email_password`
|
||||
requests:
|
||||
## @param server.requests.cpu The CPU that should be available on a node when scheduling this pod.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 500m
|
||||
## @param server.requests.memory The Memory that should be available on a node when scheduling this pod.
|
||||
## Depending on the Kubernetes cluster's configuration, exceeding this value may result in pod eviction from a node.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 1Gi
|
||||
limits:
|
||||
## @param server.limits.cpu The maximum CPU that will be made available to the server Pod in a given period.
|
||||
## If this limit is exceeded, execution of the Pod will be paused until the next period.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 1000m
|
||||
## @param server.limits.memory The maximum Memory that will be made available to the server Pod.
|
||||
## If this limit is exceeded, processes within the pod that request additional memory may be stopped.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 3Gi
|
||||
serviceAccount:
|
||||
## @param server.serviceAccount.create If enabled, a Kubernetes Service Account will be created for this pod.
|
||||
## This provides additional security by limiting this pod's access to the Kubernetes API and to Secrets on the Kubernetes cluster.
|
||||
## If disabled, the default Service Account will be used which in most Kubernetes configurations will grant this pod
|
||||
## access to most secrets on the cluster and access to the Kubernetes API.
|
||||
##
|
||||
create: true
|
||||
|
||||
monitoring:
|
||||
apollo:
|
||||
## @param server.monitoring.apollo.enabled (Optional) If enabled, exports metrics from the GraphQL API to Apollo Graphql Studio.
|
||||
## If enabling Apollo, a secret containing the key to the Apollo Graphql Studio API must stored within the Kubernetes cluster as an opaque Kubernetes Secret.
|
||||
## The name of the Kubernetes Secret resource must match the `secretName` parameter, and the key within this Kubernetes Secret must be `apollo_key`.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/secret/#opaque-secrets
|
||||
##
|
||||
enabled: false
|
||||
## @param server.monitoring.apollo.graph_id The ID for Speckle that you registered in Apollo Graphql Studio.
|
||||
##
|
||||
graph_id: ''
|
||||
# key: secret -> `apollo_key`
|
||||
|
||||
# Sentry specific:
|
||||
## @param server.sentry_dns (Optional) The Data Source Name that was provided by Sentry.io
|
||||
## Sentry.io allows events within Speckle to be monitored
|
||||
##
|
||||
sentry_dns: ''
|
||||
## @param server.disable_tracking If set to true, will prevent tracking metrics from being collected
|
||||
## Setting this value to false requires `sentry_dns` to be set
|
||||
##
|
||||
disable_tracking: false
|
||||
## @param server.disable_tracing If set to true, will prevent tracing metrics from being collected
|
||||
## Setting this value to false requires `sentry_dns` to be set
|
||||
##
|
||||
disable_tracing: false
|
||||
networkPolicy:
|
||||
## @param server.networkPolicy.enabled If enabled, will provide additional security be limiting network traffic into and out of the pod to only the required endpoints and ports.
|
||||
## If enabled, the `ingress`, `postgres.networkPolicy`, `redis.networkPolicy`, and `s3.networkPolicy` parameters need be configured.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
##
|
||||
enabled: false
|
||||
## @param server.affinity Affinity for Speckle server pods scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
##
|
||||
affinity: {}
|
||||
## @param server.nodeSelector Node labels for Speckle server pods scheduling
|
||||
## ref: https://kubernetes.io/docs/user-guide/node-selection/
|
||||
##
|
||||
nodeSelector: {}
|
||||
## @param server.tolerations Tolerations for Speckle server pods scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
##
|
||||
tolerations: []
|
||||
## @param server.topologySpreadConstraints Spread Constraints for Speckle server pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
|
||||
##
|
||||
topologySpreadConstraints: []
|
||||
|
||||
## @section Frontend
|
||||
## @descriptionStart
|
||||
## Defines parameters related to the frontend server component of Speckle.
|
||||
## @descriptionEnd
|
||||
##
|
||||
frontend:
|
||||
## @param frontend.replicas The number of instances of the Frontend pod to be deployed within the cluster.
|
||||
##
|
||||
replicas: 1
|
||||
requests:
|
||||
## @param frontend.requests.cpu The CPU that should be available on a node when scheduling this pod.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 250m
|
||||
## @param frontend.requests.memory The Memory that should be available on a node when scheduling this pod.
|
||||
## Depending on the Kubernetes cluster's configuration, exceeding this value may result in pod eviction from a node.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 256Mi
|
||||
limits:
|
||||
## @param frontend.limits.cpu The maximum CPU that will be made available to the frontend Pod in a given period.
|
||||
## If this limit is exceeded, execution of the Pod will be paused until the next period.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 1000m
|
||||
## @param frontend.limits.memory The maximum Memory that will be made available to the frontend Pod.
|
||||
## If this limit is exceeded, processes within the pod that request additional memory may be stopped.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 512Mi
|
||||
networkPolicy:
|
||||
## @param frontend.networkPolicy.enabled If enabled, will provide additional security be limiting network traffic into and out of the pod to only the required endpoints and ports.
|
||||
## If enabled, the `ingress` parameters need be configured.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
##
|
||||
enabled: false
|
||||
## @param frontend.affinity Affinity for Speckle frontend pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
##
|
||||
affinity: {}
|
||||
## @param frontend.nodeSelector Node labels for Speckle frontend pods scheduling
|
||||
## ref: https://kubernetes.io/docs/user-guide/node-selection/
|
||||
##
|
||||
nodeSelector: {}
|
||||
## @param frontend.tolerations Tolerations for Speckle frontend pods scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
##
|
||||
tolerations: []
|
||||
## @param frontend.topologySpreadConstraints Spread Constraints for Speckle frontend pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
|
||||
##
|
||||
topologySpreadConstraints: []
|
||||
serviceAccount:
|
||||
## @param frontend.serviceAccount.create If enabled, a Kubernetes Service Account will be created for this pod.
|
||||
## This provides additional security by limiting this pod's access to the Kubernetes API and to Secrets on the Kubernetes cluster.
|
||||
## If disabled, the default Service Account will be used which in most Kubernetes configurations will grant this pod
|
||||
## access to most secrets on the cluster and access to the Kubernetes API.
|
||||
##
|
||||
create: true
|
||||
|
||||
## @section Preview Service
|
||||
## @descriptionStart
|
||||
## Defines parameters related to the Preview Service component of Speckle.
|
||||
## @descriptionEnd
|
||||
##
|
||||
preview_service:
|
||||
## @param preview_service.replicas The number of instances of the Preview Service pod to be deployed within the cluster.
|
||||
##
|
||||
replicas: 1
|
||||
requests:
|
||||
## @param preview_service.requests.cpu The CPU that should be available on a node when scheduling this pod.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 500m
|
||||
## @param preview_service.requests.memory The Memory that should be available on a node when scheduling this pod.
|
||||
## Depending on the Kubernetes cluster's configuration, exceeding this value may result in pod eviction from a node.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 2Gi
|
||||
limits:
|
||||
## @param preview_service.limits.cpu The maximum CPU that will be made available to the Preview Service Pod in a given period.
|
||||
## If this limit is exceeded, execution of the Pod will be paused until the next period.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 1000m
|
||||
## @param preview_service.limits.memory The maximum Memory that will be made available to the Preview Service Pod.
|
||||
## If this limit is exceeded, processes within the pod that request additional memory may be stopped.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 4Gi
|
||||
networkPolicy:
|
||||
## @param preview_service.networkPolicy.enabled If enabled, will provide additional security be limiting network traffic into and out of the pod to only the required endpoints and ports.
|
||||
## If enabled, the `db.networkPolicy` parameters need be configured.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
##
|
||||
enabled: false
|
||||
## @param preview_service.affinity Affinity for Speckle Preview Service pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
##
|
||||
affinity: {}
|
||||
## @param preview_service.nodeSelector Node labels for Speckle Preview Service pods scheduling
|
||||
## ref: https://kubernetes.io/docs/user-guide/node-selection/
|
||||
##
|
||||
nodeSelector: {}
|
||||
## @param preview_service.tolerations Tolerations for Speckle Preview Service pods scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
##
|
||||
tolerations: []
|
||||
## @param preview_service.topologySpreadConstraints Spread Constraints for Speckle Preview Service pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
|
||||
##
|
||||
topologySpreadConstraints: []
|
||||
serviceAccount:
|
||||
## @param preview_service.serviceAccount.create If enabled, a Kubernetes Service Account will be created for this pod.
|
||||
## This provides additional security by limiting this pod's access to the Kubernetes API and to Secrets on the Kubernetes cluster.
|
||||
## If disabled, the default Service Account will be used which in most Kubernetes configurations will grant this pod
|
||||
## access to most secrets on the cluster and access to the Kubernetes API.
|
||||
##
|
||||
create: true
|
||||
|
||||
## @section Webhook Service
|
||||
## @descriptionStart
|
||||
## Defines parameters related to the Webhook Service component of Speckle.
|
||||
## @descriptionEnd
|
||||
##
|
||||
webhook_service:
|
||||
## @param webhook_service.replicas The number of instances of the Webhook Service pod to be deployed within the cluster.
|
||||
##
|
||||
replicas: 1
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
|
||||
fileimport_service:
|
||||
replicas: 1
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
## @param webhook_service.requests.cpu The CPU that should be available on a node when scheduling this pod.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 500m
|
||||
## @param webhook_service.requests.memory The Memory that should be available on a node when scheduling this pod.
|
||||
## Depending on the Kubernetes cluster's configuration, exceeding this value may result in pod eviction from a node.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 2Gi
|
||||
limits:
|
||||
## @param webhook_service.limits.cpu The maximum CPU that will be made available to the Webhook Service Pod in a given period.
|
||||
## If this limit is exceeded, execution of the Pod will be paused until the next period.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 1000m
|
||||
## @param webhook_service.limits.memory The maximum Memory that will be made available to the Webhook Service Pod.
|
||||
## If this limit is exceeded, processes within the pod that request additional memory may be stopped.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 4Gi
|
||||
networkPolicy:
|
||||
## @param webhook_service.networkPolicy.enabled If enabled, will provide additional security be limiting network traffic into and out of the pod to only the required endpoints and ports.
|
||||
## If enabled, the `db.networkPolicy` parameters need be configured.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
##
|
||||
enabled: false
|
||||
## @param webhook_service.affinity Affinity for Speckle Webhook Service pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
##
|
||||
affinity: {}
|
||||
## @param webhook_service.nodeSelector Node labels for Speckle Webhook Service pods scheduling
|
||||
## ref: https://kubernetes.io/docs/user-guide/node-selection/
|
||||
##
|
||||
nodeSelector: {}
|
||||
## @param webhook_service.tolerations Tolerations for Speckle Webhook Service pods scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
##
|
||||
tolerations: []
|
||||
## @param webhook_service.topologySpreadConstraints Spread Constraints for Speckle Webhook Service pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
|
||||
##
|
||||
topologySpreadConstraints: []
|
||||
serviceAccount:
|
||||
## @param webhook_service.serviceAccount.create If enabled, a Kubernetes Service Account will be created for this pod.
|
||||
## This provides additional security by limiting this pod's access to the Kubernetes API and to Secrets on the Kubernetes cluster.
|
||||
## If disabled, the default Service Account will be used which in most Kubernetes configurations will grant this pod
|
||||
## access to most secrets on the cluster and access to the Kubernetes API.
|
||||
##
|
||||
create: true
|
||||
|
||||
## @section File Import Service
|
||||
## @descriptionStart
|
||||
## Defines parameters related to the File Import Service component of Speckle.
|
||||
## @descriptionEnd
|
||||
##
|
||||
fileimport_service:
|
||||
## @param fileimport_service.replicas The number of instances of the FileImport Service pod to be deployed within the cluster.
|
||||
##
|
||||
replicas: 1
|
||||
requests:
|
||||
## @param fileimport_service.requests.cpu The CPU that should be available on a node when scheduling this pod.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 100m
|
||||
## @param fileimport_service.requests.memory The Memory that should be available on a node when scheduling this pod.
|
||||
## Depending on the Kubernetes cluster's configuration, exceeding this value may result in pod eviction from a node.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 512Mi
|
||||
limits:
|
||||
## @param fileimport_service.limits.cpu The maximum CPU that will be made available to the FileImport Service Pod in a given period.
|
||||
## If this limit is exceeded, execution of the Pod will be paused until the next period.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 1000m
|
||||
## @param fileimport_service.limits.memory The maximum Memory that will be made available to the FileImport Service Pod.
|
||||
## If this limit is exceeded, processes within the pod that request additional memory may be stopped.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 2Gi
|
||||
networkPolicy:
|
||||
## @param fileimport_service.networkPolicy.enabled If enabled, will provide additional security be limiting network traffic into and out of the pod to only the required endpoints and ports.
|
||||
## If enabled, the `db.networkPolicy` parameters need be configured.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
##
|
||||
enabled: false
|
||||
## @param fileimport_service.affinity Affinity for Speckle FileImport Service pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
##
|
||||
affinity: {}
|
||||
## @param fileimport_service.nodeSelector Node labels for Speckle FileImport Service pods scheduling
|
||||
## ref: https://kubernetes.io/docs/user-guide/node-selection/
|
||||
##
|
||||
nodeSelector: {}
|
||||
## @param fileimport_service.tolerations Tolerations for Speckle FileImport Service pods scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
##
|
||||
tolerations: []
|
||||
## @param fileimport_service.topologySpreadConstraints Spread Constraints for Speckle FileImport Service pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
|
||||
##
|
||||
topologySpreadConstraints: []
|
||||
serviceAccount:
|
||||
## @param fileimport_service.serviceAccount.create If enabled, a Kubernetes Service Account will be created for this pod.
|
||||
## This provides additional security by limiting this pod's access to the Kubernetes API and to Secrets on the Kubernetes cluster.
|
||||
## If disabled, the default Service Account will be used which in most Kubernetes configurations will grant this pod
|
||||
## access to most secrets on the cluster and access to the Kubernetes API.
|
||||
##
|
||||
create: true
|
||||
## @param fileimport_service.time_limit_min The maximum time that a file can take to be processed by the FileImport Service.
|
||||
## Files which take longer than this value to process will be cancelled.
|
||||
## If you experience repeated issues with small files taking a long time, and increasing CPU and/or memory requests & limits does not help,
|
||||
## please reach out to Speckle at https://speckle.community/
|
||||
##
|
||||
time_limit_min: 10
|
||||
|
||||
## @section Monitoring
|
||||
## @descriptionStart
|
||||
## Provides Speckle with metrics related to the Postgres database.
|
||||
## @descriptionEnd
|
||||
##
|
||||
monitoring:
|
||||
## @param monitoring.replicas The number of instances of the Monitoring pod to be deployed within the cluster.
|
||||
##
|
||||
replicas: 1
|
||||
requests:
|
||||
## @param monitoring.requests.cpu The CPU that should be available on a node when scheduling this pod.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 100m
|
||||
## @param monitoring.requests.memory The Memory that should be available on a node when scheduling this pod.
|
||||
## Depending on the Kubernetes cluster's configuration, exceeding this value may result in pod eviction from a node.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 64Mi
|
||||
limits:
|
||||
## @param monitoring.limits.cpu The maximum CPU that will be made available to the Monitoring Pod in a given period.
|
||||
## If this limit is exceeded, execution of the Pod will be paused until the next period.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 200m
|
||||
## @param monitoring.limits.memory The maximum Memory that will be made available to the Monitoring Pod.
|
||||
## If this limit is exceeded, processes within the pod that request additional memory may be stopped.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 512Mi
|
||||
networkPolicy:
|
||||
## @param monitoring.networkPolicy.enabled If enabled, will provide additional security be limiting network traffic into and out of the pod to only the required endpoints and ports.
|
||||
## If enabled, the `db.networkPolicy` parameters need be configured.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
##
|
||||
enabled: false
|
||||
## @param monitoring.affinity Affinity for Speckle Monitoring pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
##
|
||||
affinity: {}
|
||||
## @param monitoring.nodeSelector Node labels for Speckle Monitoring pods scheduling
|
||||
## ref: https://kubernetes.io/docs/user-guide/node-selection/
|
||||
##
|
||||
nodeSelector: {}
|
||||
## @param monitoring.tolerations Tolerations for Speckle Monitoring pods scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
##
|
||||
tolerations: []
|
||||
## @param monitoring.topologySpreadConstraints Spread Constraints for Speckle Monitoring pod scheduling
|
||||
## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
|
||||
##
|
||||
topologySpreadConstraints: []
|
||||
serviceAccount:
|
||||
## @param monitoring.serviceAccount.create If enabled, a Kubernetes Service Account will be created for this pod.
|
||||
## This provides additional security by limiting this pod's access to the Kubernetes API and to Secrets on the Kubernetes cluster.
|
||||
## If disabled, the default Service Account will be used which in most Kubernetes configurations will grant this pod
|
||||
## access to most secrets on the cluster and access to the Kubernetes API.
|
||||
##
|
||||
create: true
|
||||
|
||||
## @section Testing
|
||||
## @descriptionStart
|
||||
## Defines parameters related to testing that the deployment of Speckle has been successful.
|
||||
## @descriptionEnd
|
||||
##
|
||||
|
||||
## @param helm_test_enabled If enabled, an additional pod is deployed which verifies some functionality of Speckle to determine if it is deployed correctly
|
||||
##
|
||||
helm_test_enabled: true
|
||||
|
||||
test:
|
||||
requests:
|
||||
## @param test.requests.cpu The CPU that should be available on a node when scheduling this pod.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 100m
|
||||
## @param test.requests.memory The Memory that should be available on a node when scheduling this pod.
|
||||
## Depending on the Kubernetes cluster's configuration, exceeding this value may result in pod eviction from a node.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 64Mi
|
||||
limits:
|
||||
## @param test.limits.cpu The maximum CPU that will be made available to the Test Pod in a given period.
|
||||
## If this limit is exceeded, execution of the Pod will be paused until the next period.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
cpu: 200m
|
||||
## @param test.limits.memory The maximum Memory that will be made available to the Test Pod.
|
||||
## If this limit is exceeded, processes within the pod that request additional memory may be stopped.
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
##
|
||||
memory: 512Mi
|
||||
|
||||
secretName: server-vars
|
||||
|
||||
enable_prometheus_monitoring: false
|
||||
cert_manager_issuer: letsencrypt-staging
|
||||
|
||||
helm_test_enabled: true
|
||||
|
||||
create_namespace: false
|
||||
file_size_limit_mb: 100
|
||||
imagePullPolicy: IfNotPresent
|
||||
networkPolicy:
|
||||
## @param test.networkPolicy.enabled If enabled, will provide additional security be limiting network traffic into and out of the pod to only the required endpoints and ports.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
##
|
||||
enabled: false
|
||||
serviceAccount:
|
||||
## @param test.serviceAccount.create If enabled, a Kubernetes Service Account will be created for this pod.
|
||||
## This provides additional security by limiting this pod's access to the Kubernetes API and to Secrets on the Kubernetes cluster.
|
||||
## If disabled, the default Service Account will be used which in most Kubernetes configurations will grant this pod
|
||||
## access to most secrets on the cluster and access to the Kubernetes API.
|
||||
##
|
||||
create: true
|
||||
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
if ! command -v node &> /dev/null
|
||||
then
|
||||
echo "🛑 node could not be found. Please install node (and ensure it is in your PATH) before trying again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v git &> /dev/null
|
||||
then
|
||||
echo "🛑 git could not be found. Please install git (and ensure it is in your PATH) before trying again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GIT_ROOT="$(git rev-parse --show-toplevel)"
|
||||
|
||||
README_GENERATOR_DIR="${GIT_ROOT}/../readme-generator-for-helm"
|
||||
HELM_DIR="${GIT_ROOT}/../speckle-helm"
|
||||
HELM_GIT_TARGET_BRANCH="gh-pages"
|
||||
HELM_GIT_PR_BRANCH="${HELM_GIT_TARGET_BRANCH}-$(openssl rand -hex 6)"
|
||||
|
||||
JSON_SCHEMA_PATH="${GIT_ROOT}/utils/helm/speckle-server/values.schema.json"
|
||||
|
||||
if [ ! -d "${README_GENERATOR_DIR}" ]; then
|
||||
echo "🔭 Could not find readme-generator-for-helm in a sibling directory to speckle-server"
|
||||
echo "👩👩👧👧 Proceeding with cloning readme-generator-for-helm to a sibling directory, readme-generator-for-helm"
|
||||
git clone git@github.com:bitnami-labs/readme-generator-for-helm.git "${README_GENERATOR_DIR}"
|
||||
fi
|
||||
|
||||
pushd "${README_GENERATOR_DIR}"
|
||||
echo "✨ Updating to the latest version of readme-generator-for-helm"
|
||||
git switch main
|
||||
git pull origin main
|
||||
popd
|
||||
|
||||
if [ ! -d "${HELM_DIR}" ]; then
|
||||
echo "🔭 Could not find Speckle Helm in a sibling directory (named speckle-helm) to speckle-server"
|
||||
echo "👩👩👧👧 Proceeding with cloning Speckle's helm repository to a sibling directory, speckle-helm"
|
||||
git clone git@github.com:specklesystems/helm.git "${HELM_DIR}"
|
||||
fi
|
||||
|
||||
pushd "${HELM_DIR}"
|
||||
echo "✨ Updating to the latest version of Speckle helm"
|
||||
git switch main
|
||||
git pull origin main
|
||||
echo "🍽 Preparing forked branch for updates"
|
||||
git switch "${HELM_GIT_TARGET_BRANCH}"
|
||||
git pull origin "${HELM_GIT_TARGET_BRANCH}"
|
||||
git switch -c "${HELM_GIT_PR_BRANCH}"
|
||||
popd
|
||||
|
||||
pushd "${GIT_ROOT}"
|
||||
echo "🏗 Generating the documentation"
|
||||
node "${README_GENERATOR_DIR}/bin/index.js" \
|
||||
--config "${GIT_ROOT}/utils/helm/.helm-readme-configuration.json" \
|
||||
--values "${GIT_ROOT}/utils/helm/speckle-server/values.yaml" \
|
||||
--readme "${HELM_DIR}/README.md" \
|
||||
--schema "${JSON_SCHEMA_PATH}"
|
||||
|
||||
echo "🐛 Workaround for bug in generator for schema.json: https://github.com/bitnami-labs/readme-generator-for-helm/issues/34"
|
||||
TMP_OUTPUT="$(mktemp -t speckle-server-json-schema)"
|
||||
jq --arg replacement 'object' '(.. | .items? | select(.type == "")).type |= $replacement' "${JSON_SCHEMA_PATH}" > "${TMP_OUTPUT}" && mv "${TMP_OUTPUT}" "${JSON_SCHEMA_PATH}"
|
||||
popd
|
||||
|
||||
pushd "${HELM_DIR}"
|
||||
echo "🌳 Preparing Pull Request for Helm README..."
|
||||
git add README.md
|
||||
git commit -m "Updating README with revised parameters from values.yaml"
|
||||
git push --set-upstream origin "${HELM_GIT_PR_BRANCH}"
|
||||
echo "🙏 Please create a Pull Request, ❗️selecting gh-pages as the target branch❗️: https://github.com/specklesystems/helm/pull/new/${HELM_GIT_PR_BRANCH}"
|
||||
popd
|
||||
Reference in New Issue
Block a user