mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-07-16 05:13:36 +00:00
feat(auth): opt-in OIDC DEK unlock for API-key requests (ALLOW_APIKEY_DATA_UNLOCK) (#1064)
* chore: fix release workflow to merge docs branch
* fix: svg donation generator push fail
* fix: svg donation generator push fail
* Update termix.rb
* fix: svg donation generator push fail
* chore: move donation badge to badges branch to avoid ruleset conflicts
* chore: remove unneeded token from donation badge workflow
* chore: debug donation badge commit step
* fix: escape < character in donation SVG
* fix: point donation badge to badges branch
* chore: remove unused donation badge svg from main
* Add Rack Genius logo to README
Added Rack Genius logo to the README.
* chore: improve donation goal svg generator to include stablecoins
* chore: donation goal generator syntax error
* chore: donation goal generator incorrect docs url usage
* chore: donation bar reporting wrong result
* feat: add Open File Manager to tab right-click menu (#1046)
* Revert "feat: add Open File Manager to tab right-click menu (#1046)" (#1050)
This reverts commit 0712fdd731.
* Remove donation badge from README
Removed donation badge from README.
* Delete .github/workflows/donation-goal.yml
* feat(auth): opt-in OIDC DEK unlock for API-key requests
API keys authenticate but cannot touch the encrypted credential/host store
('User data not unlocked') unless the user has a live interactive session,
making them unusable for headless automation. For OIDC users the DEK is
server-derivable (deriveOIDCSystemKey), so handleApiKeyAuth can unlock it
without a password.
Gated behind ALLOW_APIKEY_DATA_UNLOCK (default off) because enabling it widens
the blast radius of a leaked API key. OIDC-only; password users are untouched.
Refs #1063
---------
Co-authored-by: LukeGus <bugattiguy527@gmail.com>
Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
Co-authored-by: Sankeerth Nara <sankeerthnara@gmail.com>
Co-authored-by: ZacharyZcR <zacharyzcr1984@gmail.com>
This commit is contained in:
@@ -35,8 +35,6 @@
|
|||||||
|
|
||||||
Termix is free and open source. If you find it useful, consider [donating](https://donate.termix.site/) to help cover server costs and development time.
|
Termix is free and open source. If you find it useful, consider [donating](https://donate.termix.site/) to help cover server costs and development time.
|
||||||
|
|
||||||
<a href="https://donate.termix.site/"><img src="./repo-images/donation-goal.svg" alt="Monthly donation goal" /></a>
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<img src="./repo-images/Termix Header.png" alt="Termix Banner" width="900" />
|
<img src="./repo-images/Termix Header.png" alt="Termix Banner" width="900" />
|
||||||
@@ -392,6 +390,10 @@ See [Projects](https://github.com/orgs/Termix-SSH/projects/5) for all planned fe
|
|||||||
<a href="https://aws.amazon.com/">
|
<a href="https://aws.amazon.com/">
|
||||||
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
|
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/93/Amazon_Web_Services_Logo.svg/960px-Amazon_Web_Services_Logo.svg.png" height="40" alt="AWS" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<a href="https://rackgenius.com/">
|
||||||
|
<img src="https://rackgenius.com/rackgenius-logo.png" height="40" alt="AWS" />
|
||||||
|
</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -881,6 +881,41 @@ class AuthManager {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Auto-unlock the per-user Data Encryption Key for OIDC-backed users so
|
||||||
|
// API-key (headless / automation) requests can access encrypted
|
||||||
|
// credentials/hosts. Without this, every encrypted-table op throws
|
||||||
|
// "User data not unlocked" because the API-key path never established a
|
||||||
|
// DEK session. OIDC DEKs are wrapped with a server-derived system key
|
||||||
|
// (deriveOIDCSystemKey), so no user password is required. Password-based
|
||||||
|
// users are deliberately NOT unlocked here (their KEK is password-derived
|
||||||
|
// and cannot be reproduced server-side).
|
||||||
|
//
|
||||||
|
// Opt-in and OFF by default: enabling this widens the blast radius of a
|
||||||
|
// leaked API key (it can then read that user's stored SSH secrets in
|
||||||
|
// clear text), so operators must turn it on explicitly.
|
||||||
|
if (
|
||||||
|
process.env.ALLOW_APIKEY_DATA_UNLOCK === "true" &&
|
||||||
|
!this.userCrypto.isUserUnlocked(matchedKey.userId)
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const { users } = await import("../database/db/schema.js");
|
||||||
|
const oidcRows = await db
|
||||||
|
.select()
|
||||||
|
.from(users)
|
||||||
|
.where(eq(users.id, matchedKey.userId))
|
||||||
|
.limit(1);
|
||||||
|
if (oidcRows[0]?.isOidc) {
|
||||||
|
await this.authenticateOIDCUser(matchedKey.userId);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
databaseLogger.warn("API-key OIDC auto-unlock failed", {
|
||||||
|
operation: "api_key_oidc_unlock_failed",
|
||||||
|
userId: matchedKey.userId,
|
||||||
|
error: err instanceof Error ? err.message : "Unknown",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req.userId = matchedKey.userId;
|
req.userId = matchedKey.userId;
|
||||||
req.apiKeyId = matchedKey.id;
|
req.apiKeyId = matchedKey.id;
|
||||||
next();
|
next();
|
||||||
|
|||||||
Reference in New Issue
Block a user