Skip to content

Deny unauthenticated keyserver writes by default#42

Closed
YoungJinJung wants to merge 2 commits into
mainfrom
issue-30-keyserver-auth-defaults
Closed

Deny unauthenticated keyserver writes by default#42
YoungJinJung wants to merge 2 commits into
mainfrom
issue-30-keyserver-auth-defaults

Conversation

@YoungJinJung

@YoungJinJung YoungJinJung commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Deny unauthenticated keyserver writes by default when no admin token is configured.
  • Keep per-user publish tokens working for matching peer IDs.
  • Make delete operations admin-only.
  • Add a guarded local-development override for unauthenticated PUT requests.
  • Add regression tests for default deny behavior, admin delete, per-user publish, and unsafe override validation.

Closes #30.

Validation

  • PYTHONPATH=. python3 -m unittest discover keyserver/tests
  • env -u GOROOT -u GOPATH /opt/homebrew/bin/go test ./...

Add the local keyserver service, CLI publish/login/fetch commands, compose smoke wiring, and tests as a reviewable baseline for the security hardening work stacked above it.

Constraint: Security fixes for issues #30-#34 target files that are not yet present on main.
Rejected: Fold all security fixes into one PR | would make review and issue closure harder.
Confidence: medium
Scope-risk: broad
Directive: Review this foundation before merging stacked hardening PRs into main.
Tested: PYTHONPATH=. python3 -m unittest discover keyserver/tests; env -u GOROOT -u GOPATH /opt/homebrew/bin/go test ./...
Not-tested: Docker compose smoke test was not run locally.
Keyserver writes now require an admin token or per-user publish token by default, and delete is admin-only. A local-development unauthenticated publish override remains available but is blocked on non-loopback binds unless explicitly marked unsafe.

Constraint: Preserve the SSO-issued per-user publish-token workflow while closing the no-token default.
Rejected: Remove unauthenticated local publish override entirely | local isolated demos may still need it, but it must be explicit and guarded.
Confidence: high
Scope-risk: moderate
Directive: Treat the keyserver as public-facing; do not reintroduce implicit unauthenticated writes.
Tested: PYTHONPATH=. python3 -m unittest discover keyserver/tests; env -u GOROOT -u GOPATH /opt/homebrew/bin/go test ./...
Related: #30

@amazon-q-developer amazon-q-developer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR implements secure-by-default authentication for the keyserver by denying unauthenticated writes when no admin token is configured. The implementation includes proper validation to prevent unsafe configurations and comprehensive test coverage.

Critical Issues Found:

  • Multiple test methods use patch.dict(os.environ, env, clear=True) which clears ALL environment variables and could cause test failures or unpredictable behavior. This needs to be fixed before merge.

Security Improvements:

  • Default deny behavior prevents unauthorized writes
  • Loopback validation ensures unsafe configurations can't be used in production
  • Admin-only delete operations enforce proper access control

You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

Comment on lines +155 to +156
with patch.dict(os.environ, env, clear=True):
status, body = self.request("PUT", "/v1/peers/alice", valid_profile())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Logic Error: Using clear=True in patch.dict removes all environment variables, which could cause self.request() to fail if the HTTP connection or server depends on any environment variables. Test execution may crash or behave unpredictably.

Suggested change
with patch.dict(os.environ, env, clear=True):
status, body = self.request("PUT", "/v1/peers/alice", valid_profile())
env = {"ENDE_KEYSERVER_ALLOW_UNAUTHENTICATED_WRITES": "1"}
with patch.dict(os.environ, env):
status, body = self.request("PUT", "/v1/peers/alice", valid_profile())

Comment on lines +164 to +166
with patch.dict(os.environ, env, clear=True):
with self.assertRaisesRegex(ValueError, "loopback bind"):
keyserver_server.validate_write_auth_config("0.0.0.0", "")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Logic Error: Using clear=True clears all environment variables, which could cause test failures or unpredictable behavior if the system depends on environment variables like PATH, HOME, or locale settings during HTTP operations.

Suggested change
with patch.dict(os.environ, env, clear=True):
with self.assertRaisesRegex(ValueError, "loopback bind"):
keyserver_server.validate_write_auth_config("0.0.0.0", "")
env = {"ENDE_KEYSERVER_ALLOW_UNAUTHENTICATED_WRITES": "1"}
with patch.dict(os.environ, env):
with self.assertRaisesRegex(ValueError, "loopback bind"):
keyserver_server.validate_write_auth_config("0.0.0.0", "")

Comment on lines +170 to +171
with patch.dict(os.environ, env, clear=True):
keyserver_server.validate_write_auth_config("127.0.0.1", "")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Logic Error: Using clear=True removes all environment variables, which could cause failures if system operations depend on variables like PATH or locale settings.

Suggested change
with patch.dict(os.environ, env, clear=True):
keyserver_server.validate_write_auth_config("127.0.0.1", "")
env = {"ENDE_KEYSERVER_ALLOW_UNAUTHENTICATED_WRITES": "1"}
with patch.dict(os.environ, env):
keyserver_server.validate_write_auth_config("127.0.0.1", "")

@YoungJinJung YoungJinJung changed the base branch from keyserver-foundation to main June 16, 2026 06:19
@YoungJinJung

Copy link
Copy Markdown
Contributor Author

Closing because this was opened against the wrong repository. The security triage is being redone against companyjupiter/quarkify.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Require authentication for keyserver writes by default

1 participant