-
Notifications
You must be signed in to change notification settings - Fork 14
enh: add exapps info endpoint for HaRP #505
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+1,569
−208
Merged
Changes from 51 commits
Commits
Show all changes
53 commits
Select commit
Hold shift + click to select a range
ebe4a00
enh: add exapps info endpoint for HaRP
kyteinsky 6604b9e
get metadata for only one ex-app
kyteinsky 4b38bc2
add bruteforce throttler
kyteinsky e409bdb
enh: add user info endpoint for HaRP
kyteinsky c3c2cd5
enh: add user info endpoint for HaRP
kyteinsky 0ae2f24
fixes
kyteinsky 8b8dc22
adjustments
kyteinsky 5884ab7
occ: make daemon commands harp combatible
kyteinsky f21b930
connect to internal dsp of harp if present
kyteinsky 15881ab
ex-app harp specific env set
kyteinsky 8618103
update exapp cache in harp
kyteinsky fdeae77
frp cert copy from harp to exapp
kyteinsky 28127f3
ui: add harp daemon config
kyteinsky 88d3567
move haproxy password out of foldable
kyteinsky 3ede37f
change harp deploy config structure
kyteinsky ebab47d
use harp shared key from daemon config
kyteinsky 9608349
wip: improvements to daemon registration modal
kyteinsky f3c1b5c
ui second draft
kyteinsky e9516ca
final fixes
kyteinsky db1c359
little ui changes
kyteinsky 4c5b308
connect to exapps through harp
kyteinsky dde05a0
compiled assets
kyteinsky 6ab9a36
psalm fixes
kyteinsky 4d55d0a
exapp always binds to localhost for harp
kyteinsky f6fcd8a
fix register daemon isHarp option
kyteinsky bb91d7d
remove https checkbox + change def shared key
kyteinsky 0f0fc11
update daemon reg command help
kyteinsky b6de419
chore(assets): Recompile assets
nextcloud-command bb25682
ci: harp deploy tests
kyteinsky ea8a83c
Merge branch 'main' into enh/harp/exapp-info-endpoint
kyteinsky 57d26dc
fix reuse
kyteinsky f406fe4
ci: fix harp deploy tests
kyteinsky 7bfd140
test
kyteinsky d7b9ede
REMOVE L8R: faster test iteration
kyteinsky 8020ecf
fast fix ci
kyteinsky 058dd67
debug ci
oleksandr-nc 9bca87c
fix: remove suffix /index.php from exapp url
kyteinsky 402dcd3
ci fix
kyteinsky 8d8db26
add resolver in nginx conf
kyteinsky fee9809
add other two tests
kyteinsky a937d91
Revert "REMOVE L8R: faster test iteration"
kyteinsky aa325fd
require harp tests
kyteinsky 53fcce3
allow manual-install to use harp
kyteinsky 02b4486
fix: early error in appinfo json parsing
kyteinsky 46371dc
use deploy config from exapp instead of daemon config
kyteinsky 2f6fc74
ci: manual harp deploy test
kyteinsky c2a6430
chore(assets): Recompile assets
nextcloud-command d8adb83
feat: default daemon setup checks
kyteinsky 39239d0
fix enable harp toggle
kyteinsky 9ef202f
edit deploy daemon and manual-install fixes
kyteinsky 4e64578
chore(assets): Recompile assets
nextcloud-command bfb3d3d
do not fetch exapp twice for apps metadata
kyteinsky 272c54b
Merge branch 'main' into enh/harp/exapp-info-endpoint
oleksandr-nc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| /** | ||
| * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors | ||
| * SPDX-License-Identifier: AGPL-3.0-or-later | ||
| */ | ||
|
|
||
| namespace OCA\AppAPI\Controller; | ||
|
|
||
| use OCA\AppAPI\AppInfo\Application; | ||
| use OCA\AppAPI\Service\DaemonConfigService; | ||
| use OCA\AppAPI\Service\ExAppService; | ||
| use OCA\AppAPI\Service\HarpService; | ||
| use OCP\AppFramework\Controller; | ||
| use OCP\AppFramework\Http; | ||
| use OCP\AppFramework\Http\Attribute\NoCSRFRequired; | ||
| use OCP\AppFramework\Http\Attribute\PublicPage; | ||
| use OCP\AppFramework\Http\DataResponse; | ||
| use OCP\IAppConfig; | ||
| use OCP\IGroupManager; | ||
| use OCP\IRequest; | ||
| use OCP\IUserManager; | ||
| use OCP\Security\Bruteforce\IThrottler; | ||
| use OCP\Security\ICrypto; | ||
| use Psr\Log\LoggerInterface; | ||
|
|
||
| class HarpController extends Controller { | ||
| protected $request; | ||
|
|
||
| public function __construct( | ||
| IRequest $request, | ||
| private readonly IAppConfig $appConfig, | ||
| private readonly ExAppService $exAppService, | ||
| private readonly LoggerInterface $logger, | ||
| private readonly IThrottler $throttler, | ||
| private readonly IUserManager $userManager, | ||
| private readonly IGroupManager $groupManager, | ||
| private readonly DaemonConfigService $daemonConfigService, | ||
| private readonly ICrypto $crypto, | ||
| private readonly ?string $userId, | ||
| ) { | ||
| parent::__construct(Application::APP_ID, $request); | ||
|
|
||
| $this->request = $request; | ||
| } | ||
|
|
||
| private function validateHarpSharedKey(string $appId): bool { | ||
oleksandr-nc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| $exApp = $this->exAppService->getExApp($appId); | ||
| if ($exApp === null) { | ||
| $this->logger->error('ExApp not found', ['appId' => $appId]); | ||
| // Protection for guessing installed ExApps list | ||
| $this->throttler->registerAttempt(Application::APP_ID, $this->request->getRemoteAddress(), [ | ||
| 'appid' => $appId, | ||
| ]); | ||
| return false; | ||
| } | ||
|
|
||
| try { | ||
| if (!isset($exApp->getDeployConfig()['haproxy_password'])) { | ||
| $this->logger->error('Harp shared key is not set. Invalid daemon config.'); | ||
| return false; | ||
| } | ||
| $harpKey = $this->crypto->decrypt($exApp->getDeployConfig()['haproxy_password']); | ||
| } catch (\Exception $e) { | ||
| $this->logger->error('Failed to decrypt harp shared key. Invalid daemon config.', ['exception' => $e]); | ||
| return false; | ||
| } | ||
|
|
||
| $headerHarpKey = $this->request->getHeader('HARP-SHARED-KEY'); | ||
| if ($headerHarpKey === '' || $headerHarpKey !== $harpKey) { | ||
| $this->logger->error('Harp shared key is not valid'); | ||
| $this->throttler->registerAttempt(Application::APP_ID, $this->request->getRemoteAddress(), [ | ||
| 'appid' => $appId, | ||
| ]); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| #[PublicPage] | ||
| #[NoCSRFRequired] | ||
| public function getExAppMetadata(string $appId): DataResponse { | ||
| if (!$this->validateHarpSharedKey($appId)) { | ||
| return new DataResponse(['message' => 'Harp shared key is not valid'], Http::STATUS_UNAUTHORIZED); | ||
kyteinsky marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| $exApp = $this->exAppService->getExApp($appId); | ||
| if ($exApp === null) { | ||
| $this->logger->error(sprintf('ExApp with appId %s not found.', $appId)); | ||
| // Protection for guessing installed ExApps list | ||
| $this->throttler->registerAttempt(Application::APP_ID, $this->request->getRemoteAddress(), [ | ||
| 'appid' => $appId, | ||
| ]); | ||
| return new DataResponse(['message' => 'ExApp not found'], Http::STATUS_NOT_FOUND); | ||
| } | ||
|
|
||
| return new DataResponse(HarpService::getHarpExApp($exApp)); | ||
| } | ||
|
|
||
| protected function isUserEnabled(string $userId): bool { | ||
| $user = $this->userManager->get($userId); | ||
| if ($user === null) { | ||
| $this->logger->debug('User not found', ['userId' => $userId]); | ||
| return false; | ||
| } | ||
|
|
||
| if (!$user->isEnabled()) { | ||
| $this->logger->debug('User is not enabled', ['userId' => $userId]); | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * access_level: | ||
| * 0: PUBLIC | ||
| * 1: USER | ||
| * 2: ADMIN | ||
| * @return DataResponse array{ user_id: string, access_level: int } | ||
| */ | ||
| #[PublicPage] | ||
| #[NoCSRFRequired] | ||
| public function getUserInfo(string $appId): DataResponse { | ||
| if (!$this->validateHarpSharedKey($appId)) { | ||
| return new DataResponse(['message' => 'Invalid token'], Http::STATUS_UNAUTHORIZED); | ||
| } | ||
|
|
||
| if ($this->userId === null) { | ||
| $this->logger->debug('No user found in the harp request'); | ||
| return new DataResponse([ | ||
| 'user_id' => '', | ||
| 'access_level' => ExAppRouteAccessLevel::PUBLIC->value, | ||
| ]); | ||
| } | ||
|
|
||
| if (!$this->isUserEnabled($this->userId)) { | ||
| $this->logger->debug('User is not enabled in the harp request', ['userId' => $this->userId]); | ||
| return new DataResponse([ | ||
| 'user_id' => $this->userId, | ||
| 'access_level' => ExAppRouteAccessLevel::PUBLIC->value, | ||
| ]); | ||
| } | ||
|
|
||
| if ($this->groupManager->isAdmin($this->userId)) { | ||
| return new DataResponse([ | ||
| 'user_id' => $this->userId, | ||
| 'access_level' => ExAppRouteAccessLevel::ADMIN->value, | ||
| ]); | ||
| } | ||
|
|
||
| return new DataResponse([ | ||
| 'user_id' => $this->userId, | ||
| 'access_level' => ExAppRouteAccessLevel::USER->value, | ||
| ]); | ||
| } | ||
| } | ||
|
|
||
| enum ExAppRouteAccessLevel: int { | ||
| case PUBLIC = 0; | ||
| case USER = 1; | ||
| case ADMIN = 2; | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.