Title: AccountDaoImpl.findUserAccountByApiKey() generates random UUID instead of reading from database · Issue #12612 · apache/cloudstack · GitHub
Open Graph Title: AccountDaoImpl.findUserAccountByApiKey() generates random UUID instead of reading from database · Issue #12612 · apache/cloudstack
X Title: AccountDaoImpl.findUserAccountByApiKey() generates random UUID instead of reading from database · Issue #12612 · apache/cloudstack
Description: problem API key authentication returns random user UUID on every request. AccountDaoImpl.findUserAccountByApiKey() constructs a UserVO object using new UserVO(rs.getLong(1)), which generates a random UUID on every call instead of reading...
Open Graph Description: problem API key authentication returns random user UUID on every request. AccountDaoImpl.findUserAccountByApiKey() constructs a UserVO object using new UserVO(rs.getLong(1)), which generates a rand...
X Description: problem API key authentication returns random user UUID on every request. AccountDaoImpl.findUserAccountByApiKey() constructs a UserVO object using new UserVO(rs.getLong(1)), which generates a rand...
Opengraph URL: https://github.com/apache/cloudstack/issues/12612
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"AccountDaoImpl.findUserAccountByApiKey() generates random UUID instead of reading from database","articleBody":"### problem\nAPI key authentication returns random user UUID on every request.\n\nAccountDaoImpl.findUserAccountByApiKey() constructs a UserVO object using new UserVO(rs.getLong(1)), which generates a random UUID on every call instead of reading the user's actual UUID from the database. This causes misleading error messages where the user UUID changes on every request, making debugging and log correlation impossible.\n\nThe bug is visible when an API permission check fails (e.g., UnavailableCommandException), but the random UUID is also propagated to CallContext for all API-key-authenticated requests, potentially affecting audit trails and logging even for successful calls.\n\n### versions\n\nmain branch (also likely affects 4.19, 4.20 — the code has been this way for a long time)\nAPI, ACL (Dynamic Role-Based Access Checker)\n\n### The steps to reproduce the bug\n\nCreate a non-admin user with API keys\nEnsure the user's role does NOT have permission for a specific API (e.g., listGpuDevices)\nCall the API repeatedly using API key + signature authentication:\n\ncurl \"http://\u003cmgmt-server\u003e:8080/client/api?command=listGpuDevices\u0026apikey=\u003cKEY\u003e\u0026signature=\u003cSIG\u003e\"\ncurl \"http://\u003cmgmt-server\u003e:8080/client/api?command=listGpuDevices\u0026apikey=\u003cKEY\u003e\u0026signature=\u003cSIG\u003e\"\ncurl \"http://\u003cmgmt-server\u003e:8080/client/api?command=listGpuDevices\u0026apikey=\u003cKEY\u003e\u0026signature=\u003cSIG\u003e\"\nObserve the UUID in the error message changes with every request\nEXPECTED RESULTS\n\nThe user UUID in the error message should be the same on every request, matching the \nuser's actual UUID stored in the database:\n\n\"The API [listGpuDevices] does not exist or is not available for the account for user id [\u003cconsistent-uuid\u003e].\"\nACTUAL RESULTS\n\nEach request returns a different randomly generated UUID:\n\nRequest 1: \"The API [listGpuDevices] does not exist or is not available for the account for user id [976292f1-84d7-471d-8fa2-a77b6a4cc466].\"\nRequest 2: \"The API [listGpuDevices] does not exist or is not available for the account for user id [a3b1c2d4-5678-9012-abcd-ef3456789012].\"\nRequest 3: \"The API [listGpuDevices] does not exist or is not available for the account for user id [f1e2d3c4-b5a6-7890-1234-567890abcdef].\"\n\n### What to do about it?\n\nAccountDaoImpl.findUserAccountByApiKey() at engine/schema/src/main/java/com/cloud/user/dao/AccountDaoImpl.java:147 uses a raw SQL query and manually constructs a UserVO:\n\n\nUser u = new UserVO(rs.getLong(1)); // Constructor generates UUID.randomUUID()\nu.setUsername(rs.getString(2));\nu.setAccountId(rs.getLong(3));\nu.setSecretKey(DBEncryptionUtil.decrypt(rs.getString(4)));\nu.setState(State.getValueOf(rs.getString(5)));\nThe UserVO(long id) constructor at engine/schema/src/main/java/com/cloud/user/UserVO.java:125-128:\n\n\npublic UserVO(long id) {\n this.id = id;\n this.uuid = UUID.randomUUID().toString(); // Random UUID generated here!\n}\nThe SQL query (FIND_USER_ACCOUNT_BY_API_KEY) does not select the uuid column, and the code never calls u.setUuid() with the database value.\n\nFix: Add u.uuid to the SQL SELECT and call u.setUuid() when constructing the UserVO, or use the standard DAO findBy pattern instead of raw SQL.","author":{"url":"https://github.com/rybakovanton-metta","@type":"Person","name":"rybakovanton-metta"},"datePublished":"2026-02-09T12:00:47.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/12612/cloudstack/issues/12612"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:2396584a-3218-539d-9a90-8b582697f5bb |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 84F0:23D8A:F98CD:17156F:6A4DFBFB |
| html-safe-nonce | a5ea64a23d57c0e40ec56c91526e12947eba4bc5c9b1e5302552f713ea9da73c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4NEYwOjIzRDhBOkY5OENEOjE3MTU2Rjo2QTRERkJGQiIsInZpc2l0b3JfaWQiOiI3MTk0OTcxNDM5ODY2MTgyNjUxIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | b18221452cb9fb9becbfbaed844ae8dce9aa5937e20c040261d8fe94d4d977dd |
| hovercard-subject-tag | issue:3916030991 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/apache/cloudstack/12612/issue_layout |
| twitter:image | https://opengraph.githubassets.com/3c212978999349635967376d0537d2954e571c4861361ca42fc53629d4e8ca85/apache/cloudstack/issues/12612 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/3c212978999349635967376d0537d2954e571c4861361ca42fc53629d4e8ca85/apache/cloudstack/issues/12612 |
| og:image:alt | problem API key authentication returns random user UUID on every request. AccountDaoImpl.findUserAccountByApiKey() constructs a UserVO object using new UserVO(rs.getLong(1)), which generates a rand... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | rybakovanton-metta |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5818716c93c6a2925b815402541a32814e43a7b1261c322b0c2df75224289566 |
| turbo-cache-control | no-preview |
| go-import | github.com/apache/cloudstack git https://github.com/apache/cloudstack.git |
| octolytics-dimension-user_id | 47359 |
| octolytics-dimension-user_login | apache |
| octolytics-dimension-repository_id | 9759448 |
| octolytics-dimension-repository_nwo | apache/cloudstack |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 9759448 |
| octolytics-dimension-repository_network_root_nwo | apache/cloudstack |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 4314b1df11fa8a565684f3a72dc971e3785da365 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width