Skip to content

Commit

Permalink
Merge pull request #596 from danielballan/add-api-key-option
Browse files Browse the repository at this point in the history
Add `--api-key` CLI option
  • Loading branch information
padraic-shafer authored Nov 16, 2023
2 parents ebfa643 + fbf8292 commit 5df70f8
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 5 deletions.
9 changes: 7 additions & 2 deletions docs/source/explanations/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,13 @@ client, a cookie will be set in your client and you won’t need to use the toke
again. It is valid indefinitely.

For horizontally-scaled deployments where you need multiple instances of the
server to share the same secret, you can set it via an environment variable like
so.
server to share the same secret, you can set it with a CLI option

```
tiled serve ... --api-key=YOUR_SECRET
```

or via an environment variable

```
TILED_SINGLE_USER_API_KEY=YOUR_SECRET tiled serve ...
Expand Down
58 changes: 55 additions & 3 deletions tiled/commandline/_serve.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ def serve_directory(
"this option selected."
),
),
api_key: str = typer.Option(
None,
"--api-key",
help=(
"Set the single-user API key. "
"By default, a random key is generated at startup and printed."
),
),
keep_ext: bool = typer.Option(
False,
"--keep-ext",
Expand Down Expand Up @@ -182,7 +190,10 @@ def serve_directory(
register_logger.setLevel("INFO")
web_app = build_app(
catalog_adapter,
{"allow_anonymous_access": public},
{
"allow_anonymous_access": public,
"single_user_api_key": api_key,
},
server_settings,
)
if watch:
Expand Down Expand Up @@ -270,6 +281,14 @@ def serve_catalog(
"this option selected."
),
),
api_key: str = typer.Option(
None,
"--api-key",
help=(
"Set the single-user API key. "
"By default, a random key is generated at startup and printed."
),
),
host: str = typer.Option(
"127.0.0.1",
help=(
Expand Down Expand Up @@ -388,7 +407,13 @@ def serve_catalog(
init_if_not_exists=init,
)
web_app = build_app(
tree, {"allow_anonymous_access": public}, server_settings, scalable=scalable
tree,
{
"allow_anonymous_access": public,
"single_user_api_key": api_key,
},
server_settings,
scalable=scalable,
)
print_admin_api_key_if_generated(web_app, host=host, port=port)

Expand All @@ -414,6 +439,14 @@ def serve_pyobject(
"option selected."
),
),
api_key: str = typer.Option(
None,
"--api-key",
help=(
"Set the single-user API key. "
"By default, a random key is generated at startup and printed."
),
),
host: str = typer.Option(
"127.0.0.1",
help=(
Expand Down Expand Up @@ -453,7 +486,13 @@ def serve_pyobject(
"available_bytes"
] = object_cache_available_bytes
web_app = build_app(
tree, {"allow_anonymous_access": public}, server_settings, scalable=scalable
tree,
{
"allow_anonymous_access": public,
"single_user_api_key": api_key,
},
server_settings,
scalable=scalable,
)
print_admin_api_key_if_generated(web_app, host=host, port=port)

Expand Down Expand Up @@ -507,6 +546,14 @@ def serve_config(
"option selected."
),
),
api_key: str = typer.Option(
None,
"--api-key",
help=(
"Set the single-user API key. "
"By default, a random key is generated at startup and printed."
),
),
host: str = typer.Option(
None,
help=(
Expand Down Expand Up @@ -543,6 +590,11 @@ def serve_config(
if "authentication" not in parsed_config:
parsed_config["authentication"] = {}
parsed_config["authentication"]["allow_anonymous_access"] = True
# Let --api-key flag override config.
if api_key:
if "authentication" not in parsed_config:
parsed_config["authentication"] = {}
parsed_config["authentication"]["single_user_api_key"] = api_key

# Delay this import so that we can fail faster if config-parsing fails above.

Expand Down
2 changes: 2 additions & 0 deletions tiled/server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,8 @@ def override_get_settings():
]:
if authentication.get(item) is not None:
setattr(settings, item, authentication[item])
if authentication.get("single_user_api_key") is not None:
settings.single_user_api_key_generated = False
for item in [
"allow_origins",
"response_bytesize_limit",
Expand Down

0 comments on commit 5df70f8

Please sign in to comment.