vantage6 5.0.0a35__py3-none-any.whl → 5.0.0a37__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of vantage6 might be problematic. Click here for more details.

Files changed (84) hide show
  1. vantage6/cli/algorithm/generate_algorithm_json.py +9 -10
  2. vantage6/cli/algorithm/update.py +1 -1
  3. vantage6/cli/algostore/attach.py +1 -0
  4. vantage6/cli/algostore/files.py +3 -2
  5. vantage6/cli/algostore/list.py +0 -3
  6. vantage6/cli/algostore/new.py +3 -2
  7. vantage6/cli/algostore/start.py +14 -3
  8. vantage6/cli/algostore/stop.py +3 -0
  9. vantage6/cli/auth/attach.py +60 -0
  10. vantage6/cli/auth/files.py +16 -0
  11. vantage6/cli/auth/list.py +13 -0
  12. vantage6/cli/auth/new.py +81 -0
  13. vantage6/cli/auth/remove.py +31 -0
  14. vantage6/cli/auth/start.py +94 -0
  15. vantage6/cli/auth/stop.py +67 -0
  16. vantage6/cli/cli.py +56 -5
  17. vantage6/cli/common/decorator.py +24 -5
  18. vantage6/cli/common/new.py +27 -7
  19. vantage6/cli/common/start.py +49 -41
  20. vantage6/cli/common/stop.py +23 -5
  21. vantage6/cli/common/utils.py +25 -0
  22. vantage6/cli/config.py +10 -2
  23. vantage6/cli/{configuration_wizard.py → configuration_create.py} +28 -15
  24. vantage6/cli/configuration_manager.py +97 -17
  25. vantage6/cli/context/__init__.py +10 -5
  26. vantage6/cli/context/algorithm_store.py +11 -5
  27. vantage6/cli/context/auth.py +125 -0
  28. vantage6/cli/context/base_server.py +0 -4
  29. vantage6/cli/context/node.py +25 -8
  30. vantage6/cli/context/server.py +18 -6
  31. vantage6/cli/dev/clean.py +28 -0
  32. vantage6/cli/dev/common.py +34 -0
  33. vantage6/cli/dev/rebuild.py +39 -0
  34. vantage6/cli/dev/start.py +36 -0
  35. vantage6/cli/dev/stop.py +23 -0
  36. vantage6/cli/globals.py +5 -1
  37. vantage6/cli/node/common/__init__.py +26 -10
  38. vantage6/cli/node/list.py +5 -4
  39. vantage6/cli/node/new.py +13 -6
  40. vantage6/cli/node/set_api_key.py +1 -1
  41. vantage6/cli/node/start.py +19 -4
  42. vantage6/cli/node/stop.py +153 -7
  43. vantage6/cli/node/task_cleanup/__init__.py +153 -0
  44. vantage6/cli/node/version.py +5 -4
  45. vantage6/cli/prometheus/monitoring_manager.py +5 -3
  46. vantage6/cli/sandbox/config/base.py +101 -0
  47. vantage6/cli/sandbox/config/core.py +300 -0
  48. vantage6/cli/sandbox/config/node.py +314 -0
  49. vantage6/cli/sandbox/data/olympic_athletes_2016.csv +2425 -0
  50. vantage6/cli/sandbox/new.py +207 -0
  51. vantage6/cli/sandbox/populate/__init__.py +173 -0
  52. vantage6/cli/sandbox/populate/helpers/connect_store.py +203 -0
  53. vantage6/cli/sandbox/populate/helpers/delete_fixtures.py +67 -0
  54. vantage6/cli/sandbox/populate/helpers/load_fixtures.py +476 -0
  55. vantage6/cli/sandbox/populate/helpers/utils.py +35 -0
  56. vantage6/cli/sandbox/remove.py +173 -0
  57. vantage6/cli/sandbox/start.py +341 -0
  58. vantage6/cli/sandbox/stop.py +106 -0
  59. vantage6/cli/server/attach.py +1 -0
  60. vantage6/cli/server/common/__init__.py +6 -33
  61. vantage6/cli/server/import_.py +137 -119
  62. vantage6/cli/server/new.py +22 -7
  63. vantage6/cli/server/start.py +10 -1
  64. vantage6/cli/server/stop.py +2 -0
  65. vantage6/cli/template/auth_config.j2 +253 -0
  66. vantage6/cli/template/node_config.j2 +8 -8
  67. vantage6/cli/template/node_config_nonk8s.j2 +33 -0
  68. vantage6/cli/template/server_config.j2 +10 -7
  69. vantage6/cli/test/common/diagnostic_runner.py +5 -3
  70. vantage6/cli/use/namespace.py +2 -1
  71. vantage6/cli/utils.py +33 -1
  72. {vantage6-5.0.0a35.dist-info → vantage6-5.0.0a37.dist-info}/METADATA +4 -4
  73. vantage6-5.0.0a37.dist-info/RECORD +97 -0
  74. vantage6/cli/dev/create.py +0 -693
  75. vantage6/cli/dev/remove.py +0 -112
  76. vantage6/cli/rabbitmq/__init__.py +0 -0
  77. vantage6/cli/rabbitmq/definitions.py +0 -26
  78. vantage6/cli/rabbitmq/queue_manager.py +0 -218
  79. vantage6/cli/rabbitmq/rabbitmq.config +0 -8
  80. vantage6/cli/server/shell.py +0 -54
  81. vantage6-5.0.0a35.dist-info/RECORD +0 -75
  82. /vantage6/cli/{dev → sandbox}/data/km_dataset.csv +0 -0
  83. {vantage6-5.0.0a35.dist-info → vantage6-5.0.0a37.dist-info}/WHEEL +0 -0
  84. {vantage6-5.0.0a35.dist-info → vantage6-5.0.0a37.dist-info}/entry_points.txt +0 -0
@@ -1,26 +1,19 @@
1
- import os
2
- from threading import Thread
3
-
4
1
  import click
5
- import docker
6
- from sqlalchemy.engine.url import make_url
2
+ import requests
3
+ import yaml
7
4
 
8
- from vantage6.common import info, warning
9
- from vantage6.common.docker.addons import check_docker_running, pull_image
5
+ from vantage6.common import error, info
10
6
  from vantage6.common.globals import (
11
- APPNAME,
12
- DEFAULT_DOCKER_REGISTRY,
13
- DEFAULT_SERVER_IMAGE,
14
7
  InstanceType,
15
8
  )
16
9
 
10
+ from vantage6.client import UserClient
11
+
12
+ from vantage6.cli import __version__
17
13
  from vantage6.cli.common.decorator import click_insert_context
18
- from vantage6.cli.common.utils import print_log_worker
19
14
  from vantage6.cli.context.server import ServerContext
20
- from vantage6.cli.utils import check_config_name_allowed
21
15
 
22
16
 
23
- # TODO this method has a lot of duplicated code from `start`
24
17
  @click.command()
25
18
  @click.argument("file", type=click.Path(exists=True))
26
19
  @click.option(
@@ -29,121 +22,146 @@ from vantage6.cli.utils import check_config_name_allowed
29
22
  default=False,
30
23
  help="Drop all existing data before importing",
31
24
  )
32
- @click.option("-i", "--image", default=None, help="Node Docker image to use")
33
- @click.option(
34
- "--mount-src",
35
- default="",
36
- help="Override vantage6 source code in container with the source code in this path",
37
- )
38
- @click.option(
39
- "--keep/--auto-remove",
40
- default=False,
41
- help="Keep image after finishing. Useful for debugging",
42
- )
43
- @click.option("--wait", default=False, help="Wait for the import to finish")
44
25
  @click_insert_context(type_=InstanceType.SERVER)
45
- def cli_server_import(
46
- ctx: ServerContext,
47
- file: str,
48
- drop_all: bool,
49
- image: str | None,
50
- mount_src: str,
51
- keep: bool,
52
- wait: bool,
53
- ) -> None:
26
+ def cli_server_import(ctx: ServerContext, file: str, drop_all: bool) -> None:
54
27
  """
55
- Import vantage6 resources into a server instance.
28
+ Import vantage6 resources into a server instance from a yaml FILE.
56
29
 
57
- This allows you to create organizations, collaborations, users, tasks, etc
58
- from a yaml file.
30
+ This allows you to create organizations, collaborations, users, tasks, etc. from a
31
+ yaml FILE. This method expects the server configuration file to be located on the
32
+ same machine as this method is invoked from.
59
33
 
60
- The FILE_ argument should be a path to a yaml file containing the vantage6
61
- formatted data to import.
34
+ This import assigns the root role to all users, which contains all permissions. So
35
+ use this with caution.
36
+
37
+ The FILE argument should be a path to a yaml file containing the vantage6 formatted
38
+ data to import.
62
39
  """
63
- # will print an error if not
64
- check_docker_running()
40
+ info("Validating server version: ")
41
+ info(f"{ctx.config['server']['baseUrl']}{ctx.config['server']['apiPath']}/version")
42
+ response = requests.get(
43
+ f"{ctx.config['server']['baseUrl']}{ctx.config['server']['apiPath']}/version"
44
+ )
45
+ if response.status_code != 200:
46
+ error("Unable to get server version")
47
+ return
48
+
49
+ body = response.json()
50
+ if "version" not in body:
51
+ error("Server gave a valid response but did not include the version")
52
+ return
53
+
54
+ # Compare it to this package version
55
+ server_version = body["version"]
56
+ if server_version != __version__:
57
+ error(
58
+ f"You are using CLI version {__version__} but the server is running "
59
+ f"version {server_version}. Please use the same version of the CLI and "
60
+ "server."
61
+ )
62
+ return
63
+
64
+ info("Loading and validating import file")
65
+ with open(file, "r") as f:
66
+ import_data = yaml.safe_load(f)
67
+ # TODO: validate import file
68
+
69
+ client = UserClient(
70
+ server_url=f"{ctx.config['server']['baseUrl']}{ctx.config['server']['apiPath']}",
71
+ auth_url=ctx.config["ui"]["keycloakPublicUrl"],
72
+ auth_realm=ctx.config["ui"]["keycloakRealm"],
73
+ auth_client=ctx.config["ui"]["keycloakClient"],
74
+ log_level="info",
75
+ )
76
+
77
+ info("Authenticate using admin credentials (opens browser for login)")
78
+ client.authenticate()
65
79
 
66
- info("Starting server...")
67
- info("Finding Docker daemon.")
68
- docker_client = docker.from_env()
80
+ # TODO: validate that the user has the correct permissions to import data
69
81
 
70
- # check if name is allowed for docker volume, else exit
71
- check_config_name_allowed(ctx.name)
82
+ if drop_all:
83
+ info("Dropping all existing data")
84
+ _drop_all(client)
72
85
 
73
- # pull latest Docker image
74
- if image is None:
75
- image = ctx.config.get(
76
- "image", f"{DEFAULT_DOCKER_REGISTRY}/{DEFAULT_SERVER_IMAGE}"
86
+ info("Collecting root role and rule")
87
+ root_role_id = client.role.list(name="Root", include_root=True)["data"][0]["id"]
88
+
89
+ info("Importing organizations")
90
+ organizations = []
91
+ for organization in import_data["organizations"]:
92
+ org = client.organization.create(
93
+ name=organization["name"],
94
+ address1=organization["address1"] or "",
95
+ address2=organization["address2"] or "",
96
+ zipcode=organization["zipcode"] or "",
97
+ country=organization["country"] or "",
98
+ domain=organization["domain"] or "",
77
99
  )
78
- info(f"Pulling latest server image '{image}'.")
79
- pull_image(docker_client, image)
80
-
81
- info("Creating mounts")
82
- mounts = [
83
- docker.types.Mount("/mnt/config.yaml", str(ctx.config_file), type="bind"),
84
- docker.types.Mount("/mnt/import.yaml", str(file), type="bind"),
85
- ]
86
-
87
- # FIXME: code duplication with cli_server_start()
88
- # try to mount database
89
- uri = ctx.config["uri"]
90
- url = make_url(uri)
91
- environment_vars = None
92
-
93
- if mount_src:
94
- mount_src = os.path.abspath(mount_src)
95
- mounts.append(docker.types.Mount("/vantage6", mount_src, type="bind"))
96
-
97
- # If host is None, we're dealing with a file-based DB, like SQLite
98
- if url.host is None:
99
- db_path = url.database
100
-
101
- if not os.path.isabs(db_path):
102
- # We're dealing with a relative path here -> make it absolute
103
- db_path = ctx.data_dir / url.database
104
-
105
- basename = os.path.basename(db_path)
106
- dirname = os.path.dirname(db_path)
107
- os.makedirs(dirname, exist_ok=True)
108
-
109
- # we're mounting the entire folder that contains the database
110
- mounts.append(docker.types.Mount("/mnt/database/", dirname, type="bind"))
111
-
112
- environment_vars = {
113
- # ServerGlobals.DB_URI_ENV_VAR.value: f"sqlite:////mnt/database/{basename}"
114
- }
115
-
116
- else:
117
- warning(
118
- f"Database could not be transferred, make sure {url.host} "
119
- "is reachable from the Docker container"
100
+ organizations.append(org)
101
+
102
+ info(f"Importing users for organization {org['name']}")
103
+ for user in organization.get("users", []):
104
+ client.user.create(
105
+ username=user["username"],
106
+ password=user["password"],
107
+ organization=org["id"],
108
+ roles=[root_role_id],
109
+ )
110
+
111
+ info("Importing collaborations")
112
+ all_nodes = []
113
+ for collaboration in import_data["collaborations"]:
114
+ # Collecting organization ids
115
+ organization_ids = []
116
+ for participant in collaboration["participants"]:
117
+ for org in organizations:
118
+ if org["name"] == participant["name"]:
119
+ organization_ids.append(org["id"])
120
+
121
+ col = client.collaboration.create(
122
+ name=collaboration["name"],
123
+ organizations=organization_ids,
124
+ encrypted=collaboration.get("encrypted", False),
120
125
  )
121
- info("Consider using the docker-compose method to start a server")
122
-
123
- drop_all_ = "--drop-all" if drop_all else ""
124
- cmd = f"vserver-local import -c /mnt/config.yaml {drop_all_} /mnt/import.yaml"
125
-
126
- info(cmd)
127
-
128
- info("Run Docker container")
129
- container = docker_client.containers.run(
130
- image,
131
- command=cmd,
132
- mounts=mounts,
133
- detach=True,
134
- labels={
135
- f"{APPNAME}-type": InstanceType.SERVER.value,
136
- "name": ctx.config_file_name,
137
- },
138
- environment=environment_vars,
139
- auto_remove=not keep,
140
- tty=True,
141
- )
142
- logs = container.logs(stream=True, stdout=True)
143
- Thread(target=print_log_worker, args=(logs,), daemon=False).start()
144
126
 
145
- info(f"Success! container id = {container.id}")
127
+ info("Registering nodes for collaboration")
128
+ for participant in collaboration["participants"]:
129
+ for org in organizations:
130
+ if org["name"] == participant["name"]:
131
+ node = client.node.create(
132
+ name=f"{collaboration['name']}-{org['name'].replace(' ', '-')}-node",
133
+ organization=org["id"],
134
+ collaboration=col["id"],
135
+ )
136
+ all_nodes.append(node)
146
137
 
147
- if wait:
148
- container.wait()
149
- info("Container finished!")
138
+ return all_nodes
139
+
140
+
141
+ def _drop_all(client: UserClient) -> None:
142
+ """
143
+ Drop all existing data from the server.
144
+ """
145
+ while nodes := client.node.list()["data"]:
146
+ for node in nodes:
147
+ info(f"Deleting node {node['name']}")
148
+ client.node.delete(node["id"])
149
+
150
+ while collaborations := client.collaboration.list(scope="global")["data"]:
151
+ for collaboration in collaborations:
152
+ info(f"Deleting collaboration {collaboration['name']}")
153
+ client.collaboration.delete(collaboration["id"], delete_dependents=True)
154
+
155
+ # TODO: For some reason, the `delete_dependents` parameter is not working for users,
156
+ # so we delete them here first.
157
+ while users := [u for u in client.user.list()["data"] if u["username"] != "admin"]:
158
+ for user in users:
159
+ info(f"Deleting user {user['username']}")
160
+ client.user.delete(user["id"])
161
+
162
+ while orgs := [
163
+ o for o in client.organization.list()["data"] if o["name"] != "root"
164
+ ]:
165
+ for org in orgs:
166
+ info(f"Deleting organization {org['name']}")
167
+ client.organization.delete(org["id"], delete_dependents=True)
@@ -9,7 +9,7 @@ from vantage6.common.globals import (
9
9
 
10
10
  from vantage6.cli.common.new import new
11
11
  from vantage6.cli.config import CliConfig
12
- from vantage6.cli.configuration_wizard import add_common_server_config
12
+ from vantage6.cli.configuration_create import add_common_server_config
13
13
  from vantage6.cli.globals import DEFAULT_SERVER_SYSTEM_FOLDERS
14
14
 
15
15
 
@@ -45,8 +45,20 @@ def cli_server_new(
45
45
  """
46
46
  Create a new server configuration.
47
47
  """
48
+ # info(
49
+ # "Vantage6 uses keycloak for authentication. Please configure a keycloak "
50
+ # "server here unless you have one running externally."
51
+ # )
52
+ # configure_keycloak = q.confirm(
53
+ # "Do you want to configure a keycloak server?",
54
+ # default=True,
55
+ # ).unsafe_ask()
56
+ # if configure_keycloak:
57
+ # print("awefawef")
58
+
48
59
  new(
49
- questionnaire_function=server_configuration_questionaire,
60
+ config_producing_func=server_configuration_questionaire,
61
+ config_producing_func_args=(name,),
50
62
  name=name,
51
63
  system_folders=system_folders,
52
64
  namespace=namespace,
@@ -69,10 +81,6 @@ def server_configuration_questionaire(instance_name: str) -> dict[str, Any]:
69
81
  dict[str, Any]
70
82
  dictionary with Helm values for the server configuration
71
83
  """
72
- # Get active kube namespace
73
- cli_config = CliConfig()
74
- kube_namespace = cli_config.get_last_namespace()
75
-
76
84
  # Initialize config with basic structure
77
85
  config = {"server": {}, "database": {}, "ui": {}, "rabbitmq": {}}
78
86
 
@@ -85,7 +93,8 @@ def server_configuration_questionaire(instance_name: str) -> dict[str, Any]:
85
93
  }
86
94
  config["server"]["dev"] = {
87
95
  "host_uri": "host.docker.internal",
88
- "store_in_local_cluster": True,
96
+ # TODO v5+ adapt to name space and service name etc, check from sandbox
97
+ "store_address": "http://vantage6-store-store.service.default.svc.cluster.local",
89
98
  }
90
99
 
91
100
  # TODO v5+ these should be removed, latest should usually be used so question is
@@ -102,7 +111,13 @@ def server_configuration_questionaire(instance_name: str) -> dict[str, Any]:
102
111
  default="harbor2.vantage6.ai/infrastructure/ui:latest",
103
112
  ).unsafe_ask()
104
113
 
114
+ # TODO v5+ we need to add a question to ask which algorithm stores are allowed, to
115
+ # set the CSP headers in the UI. This is not done now because it becomes easier when
116
+ # store and keycloak service can also be setup in the `v6 server new` command.
117
+
105
118
  # === Keycloak settings ===
119
+ cli_config = CliConfig()
120
+ kube_namespace = cli_config.get_last_namespace()
106
121
  keycloak_url = f"http://vantage6-auth-keycloak.{kube_namespace}.svc.cluster.local"
107
122
  config["server"]["keycloakUrl"] = keycloak_url
108
123
 
@@ -12,6 +12,7 @@ from vantage6.cli.common.start import (
12
12
  from vantage6.cli.common.utils import (
13
13
  attach_logs,
14
14
  create_directory_if_not_exists,
15
+ select_context_and_namespace,
15
16
  )
16
17
  from vantage6.cli.context.server import ServerContext
17
18
  from vantage6.cli.globals import ChartName
@@ -32,6 +33,7 @@ from vantage6.cli.globals import ChartName
32
33
  default=False,
33
34
  help="Print server logs to the console after start",
34
35
  )
36
+ @click.option("--local-chart-dir", default=None, help="Local chart directory to use")
35
37
  @click_insert_context(
36
38
  type_=InstanceType.SERVER, include_name=True, include_system_folders=True
37
39
  )
@@ -45,13 +47,18 @@ def cli_server_start(
45
47
  port: int,
46
48
  ui_port: int,
47
49
  attach: bool,
50
+ local_chart_dir: str | None,
48
51
  ) -> None:
49
52
  """
50
53
  Start the server.
51
54
  """
52
55
  info("Starting server...")
56
+ prestart_checks(ctx, InstanceType.SERVER, name, system_folders)
53
57
 
54
- prestart_checks(ctx, InstanceType.SERVER, name, system_folders, context, namespace)
58
+ context, namespace = select_context_and_namespace(
59
+ context=context,
60
+ namespace=namespace,
61
+ )
55
62
 
56
63
  create_directory_if_not_exists(ctx.log_dir)
57
64
 
@@ -61,11 +68,13 @@ def cli_server_start(
61
68
  values_file=ctx.config_file,
62
69
  context=context,
63
70
  namespace=namespace,
71
+ local_chart_dir=local_chart_dir,
64
72
  )
65
73
 
66
74
  # port forward for server
67
75
  info("Port forwarding for server")
68
76
  start_port_forward(
77
+ # TODO: make this dynamic
69
78
  service_name=f"{ctx.helm_release_name}-vantage6-server-service",
70
79
  service_port=ctx.config["server"].get("port", Ports.DEV_SERVER.value),
71
80
  port=port or ctx.config["server"].get("port", Ports.DEV_SERVER.value),
@@ -32,6 +32,7 @@ def cli_server_stop(
32
32
  namespace: str,
33
33
  system_folders: bool,
34
34
  all_servers: bool,
35
+ is_sandbox: bool = False,
35
36
  ):
36
37
  """
37
38
  Stop an running server.
@@ -45,6 +46,7 @@ def cli_server_stop(
45
46
  namespace=namespace,
46
47
  context=context,
47
48
  system_folders=system_folders,
49
+ is_sandbox=is_sandbox,
48
50
  )
49
51
 
50
52
 
@@ -0,0 +1,253 @@
1
+ # for more options on the deployment of this chart, see:
2
+ # https://artifacthub.io/packages/helm/bitnami/keycloak
3
+ keycloak:
4
+
5
+ # for development, use a local PostgreSQL instance.
6
+ {% if keycloak.production %}
7
+ postgresql:
8
+ enabled: false
9
+
10
+ # TODO v5+ set these variables from the CLI
11
+ externalDatabase:
12
+ host: "sql.example.vantage6.ai"
13
+ port: 5432
14
+ username: my-username
15
+ password: my-secret-password
16
+ database: my-keycloak-database
17
+ schema: public
18
+ existingSecretHostKey: my-secret-contains-the-host
19
+ existingSecretPortKey: my-secret-contains-the-port
20
+ existingSecretUsernameKey: my-secret-contains-the-username
21
+ existingSecretPasswordKey: my-secret-contains-the-password
22
+ existingSecretDatabaseKey: my-secret-contains-the-database
23
+
24
+ # TODO v5+ set secrets in CLI
25
+ auth:
26
+ # Set the username and password for the Keycloak admin. This user is created when
27
+ # the service is initialized.
28
+ adminUser: {{ keycloak.adminUser | default('admin') }}
29
+ existingSecret: secret-containing-admin-password
30
+ passwordSecretKey: key-to-admin-password-in-secret
31
+ # For a development environment, you can set the admin user and password directly.
32
+ # adminPassword: admin
33
+
34
+ # for production, TLS should be enabled for internal Keycloak communication
35
+ # TODO v5+ we should test if this works when we have CLI commands (#1923)
36
+ production: true
37
+ tls:
38
+ enabled: true
39
+ autoGenerated: true
40
+ {% else %}
41
+ postgresql:
42
+ enabled: true
43
+ auth:
44
+ postgresPassword: postgres
45
+ password: keycloak
46
+ database: keycloak
47
+
48
+ # for production, use an external PostgreSQL instance. This requires setting up config
49
+ # as follows. Be sure to set postgres.enabled to false just above here.
50
+ # externalDatabase:
51
+ # host: "sql.example.vantage6.ai"
52
+ # port: 5432
53
+ # username: my-username
54
+ # password: my-secret-password
55
+ # database: my-keycloak-database
56
+ # schema: public
57
+ # # or alternatively, use secrets for all of the above formatted as:
58
+ # existingSecretHostKey: my-secret-contains-the-host
59
+ # existingSecretPortKey: my-secret-contains-the-port
60
+ # existingSecretUsernameKey: my-secret-contains-the-username
61
+ # existingSecretPasswordKey: my-secret-contains-the-password
62
+ # existingSecretDatabaseKey: my-secret-contains-the-database
63
+
64
+ auth:
65
+ # for development environment, set a dummy password for the admin user.
66
+ adminUser: admin
67
+ adminPassword: admin
68
+ # for production, the password should be stored in a secret. Below you should then
69
+ # give the name of the secret and the key to where the password is within the
70
+ # secret.
71
+ # existingSecret: secret-containing-admin-password
72
+ # passwordSecretKey: key-to-admin-password-in-secret
73
+
74
+ # if you want to switch to production, you should set the following settings to true.
75
+ production: false
76
+ tls:
77
+ enabled: false
78
+ autoGenerated: false
79
+ {% endif %}
80
+
81
+ # ensure that the auth pod has enough resources to run. The default values are enough
82
+ # in most cases, but for a larger environment, you might need to increase the limits.
83
+ resources:
84
+ limits:
85
+ memory: 2Gi
86
+ cpu: 1000m
87
+ requests:
88
+ memory: 1Gi
89
+ cpu: 500m
90
+
91
+ # The following configuration is run via the CLI when the Keycloak service is
92
+ # initialized. It creates a number of users, roles and secrets that are required for
93
+ # vantage6 to work properly.
94
+ keycloakConfigCli:
95
+ enabled: true
96
+ configuration:
97
+ # Keycloak realm configuration. For all options, see
98
+ # https://www.keycloak.org/docs-api/latest/rest-api/index.html#RealmRepresentation
99
+ realm:
100
+ # Keycloak realm name
101
+ realm: {{ keycloak.realm | default('vantage6') }}
102
+ enabled: true
103
+
104
+ # access token lifespan in seconds
105
+ accessTokenLifespan: {{ keycloak.accessTokenLifespan | default(300) }}
106
+
107
+ # sso session idle timeout in seconds. This is the time before the refresh token
108
+ # expires. With default settings, this value controls the time before the
109
+ # refresh token expires. Note that if setting this to >3600, you also need to
110
+ # set ssoSessionMaxLifespan and/or clientSessionIdleTimeout and/or
111
+ # clientSessionMaxLifespan to higher values to effectively lengthen the session.
112
+ ssoSessionIdleTimeout: {{ keycloak.ssoSessionIdleTimeout | default(1800) }}
113
+
114
+ # password policy configuration. If you prefer not to have a password policy,
115
+ # you can set this to an empty string.
116
+ {% if keycloak.production %}
117
+ passwordPolicy: "length(8) and upperCase(1) and lowerCase(1) and digits(1) and specialChars(1)"
118
+ {% else %}
119
+ passwordPolicy: ""
120
+ {% endif %}
121
+
122
+ # do not allow users to edit their username - this would lead to problems with
123
+ # syncing the user between keycloak and vantage6 server/store. This setting
124
+ # should always be set to false.
125
+ editUsernameAllowed: false
126
+
127
+ {% if keycloak.production %}
128
+ # required actions for users. By setting defaultAction to true for configuring
129
+ # OTP, the user will be prompted to configure OTP (for two-factor
130
+ # authentication) on first login.
131
+ requiredActions:
132
+ - alias: CONFIGURE_TOTP
133
+ name: Configure OTP
134
+ providerId: CONFIGURE_TOTP
135
+ enabled: true
136
+ defaultAction: true
137
+ priority: 10
138
+ {% else %}
139
+ # If you want to require users to use two-factor authentication on first login,
140
+ # enable the settings below.
141
+ # requiredActions:
142
+ # - alias: CONFIGURE_TOTP
143
+ # name: Configure OTP
144
+ # providerId: CONFIGURE_TOTP
145
+ # enabled: true
146
+ # defaultAction: true
147
+ # priority: 10
148
+ {% endif %}
149
+
150
+ # users to be created in the realm. This initializes the realm with a default
151
+ # admin user. It also initializes the service account for the backend admin
152
+ # client to give it the necessary permissions to manage the realm.
153
+ # TODO v5+ configure secrets where necessary
154
+ users:
155
+ # create the vantage6 admin user. The name of this user should also be present
156
+ # in the vantage6 server and store configuration - it is the user that will be
157
+ # assigned admin permissions on initial startup.
158
+ - username: {{ keycloak.adminUser | default('admin') }}
159
+ enabled: true
160
+ {% if not keycloak.production %}
161
+ email: admin@vantage6.org
162
+ firstName: Admin
163
+ lastName: Admin
164
+ {% endif %}
165
+ credentials:
166
+ - type: password
167
+ {% if keycloak.production %}
168
+ value: {{ keycloak.adminPassword | default('Admin123!') }}
169
+ {% else %}
170
+ value: {{ keycloak.adminPassword | default('admin') }}
171
+ {% endif %}
172
+ requiredActions:
173
+ {% if keycloak.production %}
174
+ # this requires all users to update their password on first login and
175
+ # configure two-factor authentication
176
+ - CONFIGURE_TOTP
177
+ - UPDATE_PASSWORD
178
+ {% elif keycloak.no_password_update_required%}
179
+ # enable configure OTP only if you want to use two-factor authentication
180
+ # - CONFIGURE_TOTP
181
+ # enable password update if you want every user to have to change their
182
+ # password on first login
183
+ # - UPDATE_PASSWORD
184
+ {% else %}
185
+ # enable configure OTP only if you want to use two-factor authentication
186
+ # - CONFIGURE_TOTP
187
+ # this requires all users to update their password on first login
188
+ - UPDATE_PASSWORD
189
+ {% endif %}
190
+ # create a service account user for the backend admin client. The
191
+ # serviceAccountClientId should match the value set in the client section
192
+ # below. The vantage6 server and store will use this user to create new
193
+ # accounts for users and nodes in keycloak - that is why it gets assigned some
194
+ # realm-management permissions.
195
+ - username: service-account-backend-admin-client
196
+ enabled: true
197
+ serviceAccountClientId: backend-admin-client
198
+ clientRoles:
199
+ realm-management:
200
+ - view-users
201
+ - manage-users
202
+ - view-clients
203
+ - manage-clients
204
+ - create-client
205
+
206
+ # clients to be created in the realm. This initializes the realm with a default
207
+ # public client and a backend admin client. The public client is used by users
208
+ # to authenticate in the browser. Either the UI or the Python client will
209
+ # redirect to this client.
210
+ clients:
211
+ - clientId: public_client
212
+ publicClient: true
213
+ # redirect URIs are the URIs that keycloak is allowed to redirect to after
214
+ # authentication. This should be set to the UI URL, and to the Keyloak
215
+ # service on port 7681. The latter is needed for authentication from outside
216
+ # the browser - if e.g. the Python client authenticates, it will open a
217
+ # browser window to authenticate that redirects to the Keycloak service on
218
+ # port 7681.
219
+ {% if keycloak.redirectUris %}
220
+ redirectUris:
221
+ {% for uri in keycloak.redirectUris %}
222
+ - "{{ uri }}/*"
223
+ {% endfor %}
224
+ {% else %}
225
+ redirectUris:
226
+ # allow logging in via a local UI
227
+ - "http://localhost:7600/*"
228
+ # allow logging in via the Python client (which spins up a local server
229
+ # on port 7681)
230
+ - "http://localhost:7681/*"
231
+ {% endif %}
232
+ # By setting webOrigins to "+", we allow the same origins as redirectUris.
233
+ webOrigins:
234
+ - "+"
235
+ # The public client is only for users, not for nodes. Therefore, map a
236
+ # constant claim to indicate the that the client is a user.
237
+ protocolMappers:
238
+ - name: vantage6_client_type
239
+ protocol: openid-connect
240
+ protocolMapper: oidc-hardcoded-claim-mapper
241
+ consentRequired: false
242
+ config:
243
+ claim.name: vantage6_client_type
244
+ claim.value: user
245
+ access.token.claim: true
246
+ # create a client that will allow the backend to manage users and clients in
247
+ # keycloak.
248
+ - clientId: backend-admin-client
249
+ publicClient: false
250
+ # TODO v5+ configure secrets where necessary
251
+ secret: myadminclientsecret
252
+ serviceAccountsEnabled: true
253
+ standardFlowEnabled: false