Merge branch 'main' into viewer-redux-integration

This commit is contained in:
AlexandruPopovici
2022-08-16 17:37:47 +03:00
47 changed files with 3095 additions and 414 deletions
+16 -4
View File
@@ -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
View File
@@ -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
-21
View File
@@ -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
View File
@@ -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
+1 -6
View File
@@ -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
View File
@@ -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",
+1 -1
View File
@@ -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
@@ -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))
-208
View File
@@ -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 })
]
}
+306
View File
@@ -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 })
]
@@ -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 }
@@ -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 }
+3 -12
View File
@@ -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 {
+73
View File
@@ -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"
}
}
+2
View File
@@ -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
+695 -34
View File
@@ -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
+71
View File
@@ -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