Skip to content

Commit

Permalink
Merge pull request #2065 from openkfw/api-env-validation-fix-of-fixes
Browse files Browse the repository at this point in the history
api: allow undefined for some env vars
  • Loading branch information
MartinJurcoGlina authored Oct 29, 2024
2 parents 69a4896 + 8407b09 commit 0b94d0c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 32 deletions.
73 changes: 45 additions & 28 deletions api/src/envVarsSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import { randomString } from "./service/hash";

export const envVarsSchema = Joi.object({
LOG_LEVEL: Joi.string()
.allow("trace", "debug", "info", "warn", "error", "fatal", "", null)
.empty(["", null])
.default("info")
.allow("trace", "debug", "info", "warn", "error", "fatal")
.note("Defines the log output."),
ORGANIZATION: Joi.string()
.allow("")
.empty(["", null])
.min(1)
.max(100)
.required()
.default("MyOrga")
.note(
"In the blockchain network, each node is represented by its organization name. This environment variable sets this organization name. It is used to create the organization stream on the blockchain and is also displayed in the frontend's top right corner.",
),
Expand All @@ -28,7 +31,8 @@ export const envVarsSchema = Joi.object({
),
ROOT_SECRET: Joi.string()
.min(8)
.required()
.allow("")
.empty(["", null])
.default(randomString(32))
.note(
"The root secret is the password for the root user. If you start with an empty blockchain, the root user is needed to add other users, approve new nodes,.. If you don't set a value via the environment variable, the API generates one randomly and prints it to the console <br/>**Caution:** If you want to run TruBudget in production, make sure to set a secure root secret.",
Expand All @@ -51,13 +55,16 @@ export const envVarsSchema = Joi.object({
),
MULTICHAIN_RPC_USER: Joi.string()
.allow("")
.empty("")
.empty(["", null])
.default("multichainrpc")
.note("The user used to connect to the multichain daemon."),
MULTICHAIN_RPC_PASSWORD: Joi.string()
.allow("")
.empty(["", null])
.default("s750SiJnj50yIrmwxPnEdSzpfGlTAHzhaUwgqKeb0G1j")
.min(32)
.note(
"Password used by the API to connect to the blockchain. The password is set by the origin node upon start. Every beta node needs to use the same RPC password in order to be able to connect to the blockchain. <br/>**Hint:** Although the MULTICHAIN_RPC_PASSWORD is not required it is highly recommended to set an own secure one.",
"Password used by the API to connect to the blockchain. The password is set by the origin node upon start. Every beta node needs to use the same RPC password in order to be able to connect to the blockchain. <br/>**Hint:** Although the MULTICHAIN_RPC_PASSWORD is not required it is highly recommended to set an own secure one, at least 32 characters long.",
),
BLOCKCHAIN_PORT: Joi.number()
.default(8085)
Expand All @@ -83,16 +90,19 @@ export const envVarsSchema = Joi.object({
.default("HS256")
.note("Algorithm used for signing and verifying JWTs."),
JWT_SECRET: Joi.string()
.min(10)
.allow("")
.empty(["", null])
.default(randomString(10))
.when("JWT_ALGORITHM", {
is: "RS256",
then: Joi.string().base64().required(),
then: Joi.string().min(10).base64().required(),
})
.note(
"A string that is used to sign JWT which are created by the authenticate endpoint of the api. If JWT_ALGORITHM is set to `RS256`, this is required and holds BASE64 encoded PEM encoded private key for RSA.",
),
JWT_PUBLIC_KEY: Joi.string()
.allow("")
.empty(["", null])
.default("")
.when("JWT_ALGORITHM", {
is: "RS256",
Expand All @@ -102,48 +112,53 @@ export const envVarsSchema = Joi.object({
"If JWT_ALGORITHM is set to `RS256`, this is required and holds BASE64 encoded PEM encoded public key for RSA.",
),
DOCUMENT_FEATURE_ENABLED: Joi.boolean()
.empty("")
.empty(["", null])
.default(false)
.note(
"If true, all uploaded documents are stored using trubudget's storage-service. If false, the document feature of TruBudget is disabled, and trying to upload a document will result in an error.",
),
DOCUMENT_EXTERNAL_LINKS_ENABLED: Joi.boolean()
.default(false)
.empty("")
.empty(["", null])
.note(
'If true, it is possible to use external documents links also without TruBudget\'s storage-service. If false, the external documents links feature of TruBudget is still possible to use in case DOCUMENT_FEATURE_ENABLED equals "true".',
),
STORAGE_SERVICE_HOST: Joi.string().default("localhost").note("IP of connected storage service"),
STORAGE_SERVICE_PORT: Joi.number()
.allow("")
.empty("")
.empty(["", null])
.default(8090)
.note("Port of connected storage service"),
STORAGE_SERVICE_PROTOCOL: Joi.string()
.default("http")
.allow("http", "https")
.note("Protocol of connected storage service."),
STORAGE_SERVICE_EXTERNAL_URL: Joi.string()
.allow("")
.empty(null)
.default("")
.when("DOCUMENT_FEATURE_ENABLED", {
is: true,
then: Joi.required(),
})
.note("IP and port of own connected storage service accessible externally"),
EMAIL_HOST: Joi.string().default("localhost"),
EMAIL_PORT: Joi.number().default(8089),
EMAIL_HOST: Joi.string().allow("").empty(["", null]).default("localhost"),
EMAIL_PORT: Joi.number().allow("").empty(["", null]).default(8089),
EMAIL_PROTOCOL: Joi.string()
.default("http")
.allow("http", "https")
.note("Protocol of connected storage service."),
ACCESS_CONTROL_ALLOW_ORIGIN: Joi.string()
.allow("")
.empty(["", null])
.default("*")
.note(
"Since the service uses CORS, the domain by which it can be called needs to be set. Setting this value to `*` means that it can be called from any domain. Read more about this topic [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).",
),
NODE_ENV: Joi.string()
.default("production")
.allow("production", "development", "testing")
.allow("production", "development", "testing", "", null)
.empty(["", null])
.note(
"If set to `development` api will allow any string as password. If set to `production` passwords must satisfy safePasswordSchema, see lib/joiValidation-.ts & -.spec.ts files",
),
Expand All @@ -154,42 +169,44 @@ export const envVarsSchema = Joi.object({
),
SIGNING_METHOD: Joi.string()
.default("node")
.allow("node", "user")
.allow("node", "user", "", null)
.empty(["", null])
.note(
"Possible signing methods are: `node` and `user`. Transactions on the chain will be signed using either the address of the node or the address of the specific user publishing that transaction.",
),
RATE_LIMIT: Joi.number()
.allow("")
.empty("")
.allow("", null)
.empty(["", null])
.optional()
.note(
"If set, API will limit the number of requests from any individual IP address to the set number per minute. Can be set to any `number`, but shouldn't be set too low.",
),
AUTHPROXY_ENABLED: Joi.boolean()
.default(false)
.empty("")
.empty(["", null])
.note("Enables logging in using the authorization token from authentication proxy"),
AUTHPROXY_JWS_SIGNATURE: Joi.string()
.allow("")
.empty("")
.empty(["", null])
.when("AUTHPROXY_ENABLED", {
is: true,
then: Joi.required(),
})
.note("secret/public key/certificate for verifying auth proxy token signature"),
DB_TYPE: Joi.string().default("pg"),
SQL_DEBUG: Joi.boolean().default(false).empty(""),
SQL_DEBUG: Joi.boolean().empty(["", null]).default(false),
API_DB_USER: Joi.string()
.empty(["", null])
.default("postgres")
.allow("")
.empty("")
.when("REFRESH_TOKEN_STORAGE", {
is: "db",
then: Joi.required(),
})
.note("Database user for database connection, e.g. postgres"),
API_DB_PASSWORD: Joi.string()
.allow("")
.empty("")
.empty(["", null])
.when("REFRESH_TOKEN_STORAGE", {
is: "db",
then: Joi.required(),
Expand All @@ -202,27 +219,26 @@ export const envVarsSchema = Joi.object({
then: Joi.required(),
})
.allow("")
.empty("")
.empty(["", null])
.default("localhost")
.note("Database host"),
API_DB_NAME: Joi.string()
.allow("")
.empty("")
.empty(["", null])
.when("REFRESH_TOKEN_STORAGE", {
is: "db",
then: Joi.required(),
})
.default("trubudget_email_service")
.empty("")
.example("trubudget-db")
.note("Name of the used database"),
API_DB_PORT: Joi.number()
.when("REFRESH_TOKEN_STORAGE", {
is: "db",
then: Joi.required(),
})
.empty(["", null])
.allow("")
.empty("")
.default(5432)
.note("Database port, e.g. 5432"),
API_DB_SSL: Joi.boolean()
Expand All @@ -231,18 +247,19 @@ export const envVarsSchema = Joi.object({
then: Joi.required(),
})
.allow("")
.empty("")
.empty(["", null])
.default(false)
.empty("")
.note('Database SSL connection. Allowed values: "true" or "false".'),
API_DB_SCHEMA: Joi.string()
.when("REFRESH_TOKEN_STORAGE", {
is: "db",
then: Joi.required(),
})
.empty(["", null])
.default("public")
.note('Database schema, e.g. "public".'),
API_REFRESH_TOKENS_TABLE: Joi.string()
.empty(["", null])
.default("refresh_token")
.when("REFRESH_TOKEN_STORAGE", {
is: "db",
Expand All @@ -257,7 +274,7 @@ export const envVarsSchema = Joi.object({
SNAPSHOT_EVENT_INTERVAL: Joi.number().default(3),
SILENCE_LOGGING_ON_FREQUENT_ROUTES: Joi.boolean()
.default(false)
.empty("")
.empty(["", null])
.note(
'Set to "true" if you want to hide route logging on frequent and technical endpoints like `/readiness`, `/version`, etc.',
),
Expand Down
22 changes: 18 additions & 4 deletions blockchain/src/envVarsSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ const Joi = require("joi");
const envVarsSchema = Joi.object({
PORT: Joi.number().port().default(8085).note("This is the port where the multichain can be downloaded (backup)"),
ORGANIZATION: Joi.string()
.allow("")
.empty(["", null])
.default("MyOrga")
.note(
"In the blockchain network, each node is represented by its organization name. This environment variable sets this organization name. It is used to create the organization stream on the blockchain.",
),
MULTICHAIN_RPC_PORT: Joi.number()
.port()
.allow("")
.empty(["", null])
.default(8000)
.required()
.note(
"The port used to expose the multichain daemon of your Trubudget blockchain installation(bc). The port used to connect to the multichain daemon(api). This will be used internally for the communication between the API and the multichain daemon.",
),
Expand All @@ -20,10 +23,12 @@ const envVarsSchema = Joi.object({
.default("multichainrpc")
.note("The user used to connect to the multichain daemon."),
MULTICHAIN_RPC_PASSWORD: Joi.string()
.allow("")
.empty(["", null])
.default("s750SiJnj50yIrmwxPnEdSzpfGlTAHzhaUwgqKeb0G1j")
.min(32)
.required()
.note(
"Password used by the API to connect to the blockchain. The password is set by the origin node upon start. Every beta node needs to use the same RPC password in order to be able to connect to the blockchain. <br/>**Hint:** Although the MULTICHAIN_RPC_PASSWORD is not required it is highly recommended to set an own secure one.",
"Password used by the API to connect to the blockchain. The password is set by the origin node upon start. Every beta node needs to use the same RPC password in order to be able to connect to the blockchain. <br/>**Hint:** Although the MULTICHAIN_RPC_PASSWORD is not required it is highly recommended to set an own secure one, at least 32 characters long.",
),
RPC_ALLOW_IP: Joi.string()
.default("0.0.0.0/0")
Expand Down Expand Up @@ -54,7 +59,8 @@ const envVarsSchema = Joi.object({
),
LOG_LEVEL: Joi.string()
.default("info")
.allow("fatal", "error", "warn", "info", "debug", "trace")
.allow("fatal", "error", "warn", "info", "debug", "trace", "")
.empty(["", null])
.note("Defines the log output."),
P2P_HOST: Joi.string().note(
"The IP address of the blockchain node you want to connect to. When given, the node joins the existing network rather than creating its own chain.",
Expand All @@ -79,13 +85,17 @@ const envVarsSchema = Joi.object({
"The path to the multichain folder where the blockchain data is persisted. For installations via `docker compose`, this refers to the path within the docker container of the blockchain. For bare metal installations, this refers to the path on the machine the blockchain is running on.",
),
EMAIL_HOST: Joi.string()
.allow("")
.empty(["", null])
.when("EMAIL_SERVICE_ENABLED", {
is: true,
then: Joi.required(),
otherwise: Joi.optional(),
})
.note("The IP address from the email-notification service."),
EMAIL_PORT: Joi.number()
.allow("")
.empty(["", null])
.when("EMAIL_SERVICE_ENABLED", {
is: true,
then: Joi.required(),
Expand All @@ -110,6 +120,8 @@ const envVarsSchema = Joi.object({
"This number configure in which interval the notifications in the NOTIFICATION_PATH should be checked and send.",
),
JWT_SECRET: Joi.string()
.allow("")
.empty(["", null])
.when("EMAIL_SERVICE_ENABLED", {
is: true,
then: Joi.required(),
Expand All @@ -129,6 +141,8 @@ const envVarsSchema = Joi.object({
"If set to true the multichain-feed go script in src/multichain-feed/multichain-feed is passed to the multichain daemon and executed in a separate process. ",
),
NODE_ENV: Joi.string()
.allow("")
.empty(["", null])
.default("production")
.note(
"Environment: Default development when running development-script. Production when running production-script",
Expand Down

0 comments on commit 0b94d0c

Please sign in to comment.