Mercurial > hg > orthanc-authorization
changeset 243:3a6194f51293 inbox tip
new ExtraPermissions config + improved anonymous profiles
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Thu, 12 Jun 2025 16:12:29 +0200 (4 days ago) |
parents | 1877694ab4f7 |
children | |
files | NEWS Plugin/BaseAuthorizationService.h Plugin/IAuthorizationService.h Plugin/Plugin.cpp |
diffstat | 4 files changed, 82 insertions(+), 74 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Wed Jun 11 10:55:44 2025 +0200 +++ b/NEWS Thu Jun 12 16:12:29 2025 +0200 @@ -1,3 +1,18 @@ +Pending changes in the mainline +=============================== + +=> Minimum Orthanc version: 1.11.3 <= +=> Recommended SDK version: 1.12.4 <= +=> Minimum SDK version: 1.11.3 <= + +* New configuration "ExtraPermissions" to ADD new permissions to + the default "Permissions" entries. +* Improved handling of "Anonymous" user profiles (when no auth-tokens + are provided): The plugin will now request the auth-service to + get an anonymous user profile even if there are no auth-tokens in the + HTTP request. + + 2025-06-11 - v 0.9.3 ====================
--- a/Plugin/BaseAuthorizationService.h Wed Jun 11 10:55:44 2025 +0200 +++ b/Plugin/BaseAuthorizationService.h Thu Jun 12 16:12:29 2025 +0200 @@ -102,25 +102,5 @@ return false; } - virtual bool HasAnonymousUserPermission(unsigned int& validity /* out */, - const std::set<std::string>& anyOfPermissions) ORTHANC_OVERRIDE - { - if (anyOfPermissions.size() == 0) - { - return true; - } - - UserProfile anonymousUserProfile; - anonymousUserProfile.tokenType = TokenType_None; - - for (std::set<std::string>::const_iterator it = anyOfPermissions.begin(); it != anyOfPermissions.end(); ++it) - { - if (HasUserPermissionInternal(validity, *it, anonymousUserProfile)) - { - return true; - } - } - return false; - } }; }
--- a/Plugin/IAuthorizationService.h Wed Jun 11 10:55:44 2025 +0200 +++ b/Plugin/IAuthorizationService.h Thu Jun 12 16:12:29 2025 +0200 @@ -96,9 +96,6 @@ const std::set<std::string>& anyOfPermissions, const UserProfile& profile) = 0; - virtual bool HasAnonymousUserPermission(unsigned int& validity /* out */, - const std::set<std::string>& anyOfPermissions) = 0; - virtual bool CreateToken(CreatedToken& response, const std::string& tokenType, const std::string& id,
--- a/Plugin/Plugin.cpp Wed Jun 11 10:55:44 2025 +0200 +++ b/Plugin/Plugin.cpp Thu Jun 12 16:12:29 2025 +0200 @@ -273,6 +273,47 @@ return false; } +static bool TestRequiredPermissions(bool& hasUserRequiredPermissions, + const std::set<std::string>& requiredPermissions, + const OrthancPlugins::IAuthorizationService::UserProfile& profile, + const std::string& msg, + const char* uri, + OrthancPluginHttpMethod method, + const OrthancPlugins::AssociativeArray& getArguments + ) +{ + unsigned int validity; // ignored + if (authorizationService_->HasUserPermission(validity, requiredPermissions, profile)) + { + LOG(INFO) << msg << " -> granted"; + hasUserRequiredPermissions = true; + + // check labels permissions + std::string msg2 = std::string("Testing whether user has the authorized_labels to access '") + uri + "'"; + + bool hasAuthorizedLabelsForResource = false; + if (CheckAuthorizedLabelsForResource(hasAuthorizedLabelsForResource, uri, method, getArguments, profile)) + { + if (hasAuthorizedLabelsForResource) + { + LOG(INFO) << msg2 << " -> granted"; + } + else + { + LOG(INFO) << msg2 << " -> not granted"; + return false; // the labels for this resource prevents access -> stop checking now ! + } + } + } + else + { + LOG(INFO) << msg << " -> not granted"; + hasUserRequiredPermissions = false; + } + + return true; +} + static int32_t FilterHttpRequests(OrthancPluginHttpMethod method, const char *uri, const char *ip, @@ -323,22 +364,19 @@ { if (authTokens.empty()) { - std::string msg = std::string("Testing whether anonymous user has any of the required permissions '") + JoinStrings(requiredPermissions) + "'"; - + std::string msg = std::string("Testing whether anonymous user has any of the required permissions '") + JoinStrings(requiredPermissions) + "' required to match '" + matchedPattern + "'"; + + OrthancPlugins::IAuthorizationService::UserProfile anonymousProfile; + unsigned int validityNotUsed; + authorizationService_->GetUserProfile(validityNotUsed, anonymousProfile, OrthancPlugins::Token(OrthancPlugins::TokenType_None, ""), ""); + LOG(INFO) << msg; - - unsigned int validity; // ignored - if (authorizationService_->HasAnonymousUserPermission(validity, requiredPermissions)) + if (!TestRequiredPermissions(hasUserRequiredPermissions, requiredPermissions, anonymousProfile, msg, uri, method, getArguments)) { - LOG(INFO) << msg << " -> granted"; - hasUserRequiredPermissions = true; + return 0; // the labels for this resource prevents access -> stop checking now ! } - else - { - LOG(INFO) << msg << " -> not granted"; - hasUserRequiredPermissions = false; - // continue in order to check if there is a resource token that could grant access to the resource - } + + // continue in order to check if there is a resource token that could grant access to the resource } else { @@ -346,39 +384,16 @@ { std::string msg = std::string("Testing whether user has the required permissions '") + JoinStrings(requiredPermissions) + "' based on the HTTP header '" + authTokens[i].GetToken().GetKey() + "' required to match '" + matchedPattern + "'"; - // LOG(INFO) << msg; + LOG(INFO) << msg; OrthancPlugins::IAuthorizationService::UserProfile profile; unsigned int validityNotUsed; authorizationService_->GetUserProfile(validityNotUsed, profile, authTokens[i].GetToken(), authTokens[i].GetValue()); - unsigned int validity; // ignored - if (authorizationService_->HasUserPermission(validity, requiredPermissions, profile)) + if (!TestRequiredPermissions(hasUserRequiredPermissions, requiredPermissions, profile, msg, uri, method, getArguments)) { - LOG(INFO) << msg << " -> granted"; - hasUserRequiredPermissions = true; - - // check labels permissions - msg = std::string("Testing whether user has the authorized_labels to access '") + uri + "' based on the HTTP header '" + authTokens[i].GetToken().GetKey() + "'"; + return 0; // the labels for this resource prevents access -> stop checking now ! + } - bool hasAuthorizedLabelsForResource = false; - if (CheckAuthorizedLabelsForResource(hasAuthorizedLabelsForResource, uri, method, getArguments, profile)) - { - if (hasAuthorizedLabelsForResource) - { - LOG(INFO) << msg << " -> granted"; - } - else - { - LOG(INFO) << msg << " -> not granted"; - return 0; // the labels for this resource prevents access -> stop checking now ! - } - } - } - else - { - LOG(INFO) << msg << " -> not granted"; - hasUserRequiredPermissions = false; - } } } } @@ -546,30 +561,25 @@ OrthancPlugins::IAuthorizationService::UserProfile tryProfile; std::string value; - - bool hasValue = false; switch (token->GetType()) { case OrthancPlugins::TokenType_HttpHeader: - hasValue = headers.GetValue(value, token->GetKey()); + headers.GetValue(value, token->GetKey()); break; case OrthancPlugins::TokenType_GetArgument: - hasValue = getArguments.GetValue(value, token->GetKey()); + getArguments.GetValue(value, token->GetKey()); break; default: throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } - if (hasValue) + unsigned int validity; // not used + if (authorizationService_->GetUserProfile(validity, tryProfile, *token, value)) { - unsigned int validity; // not used - if (authorizationService_->GetUserProfile(validity, tryProfile, *token, value)) - { - profile = tryProfile; - return true; - } + profile = tryProfile; + return true; } } @@ -1496,6 +1506,12 @@ (new OrthancPlugins::PermissionParser(dicomWebRoot, oe2Root)); permissionParser_->Add(pluginConfiguration.GetJson()[PERMISSIONS], authorizationParser_.get()); + + static const char* const EXTRA_PERMISSIONS = "ExtraPermissions"; + if (pluginConfiguration.GetJson().isMember(EXTRA_PERMISSIONS)) + { + permissionParser_->Add(pluginConfiguration.GetJson()[EXTRA_PERMISSIONS], authorizationParser_.get()); + } } else {