Mercurial > hg > orthanc-authorization
changeset 195:2f1e872e8eaa
merge
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Fri, 14 Jun 2024 16:31:58 +0200 |
parents | 85859ec3aa7e (current diff) 7bec4de04c91 (diff) |
children | 55760c465c3a |
files | Plugin/AuthorizationWebService.h Plugin/CachedAuthorizationService.h Plugin/PermissionParser.cpp Plugin/PermissionParser.h Plugin/Plugin.cpp |
diffstat | 10 files changed, 105 insertions(+), 70 deletions(-) [+] |
line wrap: on
line diff
--- a/Plugin/AuthorizationParserBase.h Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/AuthorizationParserBase.h Fri Jun 14 16:31:58 2024 +0200 @@ -72,7 +72,7 @@ public: virtual void AddDicomStudy(AccessedResources& target, - const std::string& studyDicomUid); + const std::string& studyDicomUid) ORTHANC_OVERRIDE; explicit AuthorizationParserBase(ICacheFactory& factory);
--- a/Plugin/AuthorizationWebService.h Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/AuthorizationWebService.h Fri Jun 14 16:31:58 2024 +0200 @@ -72,17 +72,17 @@ void SetIdentifier(const std::string& webServiceIdentifier); - virtual bool HasUserProfile() const + virtual bool HasUserProfile() const ORTHANC_OVERRIDE { return !userProfileUrl_.empty(); } - virtual bool HasCreateToken() const + virtual bool HasCreateToken() const ORTHANC_OVERRIDE { return !tokenCreationBaseUrl_.empty(); } - virtual bool HasTokenValidation() const + virtual bool HasTokenValidation() const ORTHANC_OVERRIDE { return !tokenValidationUrl_.empty(); } @@ -101,7 +101,7 @@ virtual bool DecodeToken(DecodedToken& response, const std::string& tokenKey, - const std::string& tokenValue); + const std::string& tokenValue) ORTHANC_OVERRIDE; virtual bool GetSettingsRoles(Json::Value& roles); virtual bool UpdateSettingsRoles(Json::Value& response,
--- a/Plugin/BaseAuthorizationService.h Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/BaseAuthorizationService.h Fri Jun 14 16:31:58 2024 +0200 @@ -22,6 +22,8 @@ #include "IAuthorizationService.h" +#include <Compatibility.h> + namespace OrthancPlugins { @@ -55,14 +57,14 @@ OrthancPluginHttpMethod method, const AccessedResource& access, const Token& token, - const std::string& tokenValue) + const std::string& tokenValue) ORTHANC_OVERRIDE { return IsGrantedInternal(validity, method, access, &token, tokenValue); } virtual bool IsGrantedToAnonymousUser(unsigned int& validity, OrthancPluginHttpMethod method, - const AccessedResource& access) + const AccessedResource& access) ORTHANC_OVERRIDE { return IsGrantedInternal(validity, method, access, NULL, ""); } @@ -70,20 +72,20 @@ virtual bool GetUserProfile(unsigned int& validity, UserProfile& profile /* out */, const Token& token, - const std::string& tokenValue) + const std::string& tokenValue) ORTHANC_OVERRIDE { return GetUserProfileInternal(validity, profile, &token, tokenValue); } virtual bool GetAnonymousUserProfile(unsigned int& validity /* out */, - UserProfile& profile /* out */) + UserProfile& profile /* out */) ORTHANC_OVERRIDE { return GetUserProfileInternal(validity, profile, NULL, ""); } virtual bool HasUserPermission(unsigned int& validity /* out */, const std::set<std::string>& anyOfPermissions, - const UserProfile& profile) + const UserProfile& profile) ORTHANC_OVERRIDE { if (anyOfPermissions.size() == 0) { @@ -101,7 +103,7 @@ } virtual bool HasAnonymousUserPermission(unsigned int& validity /* out */, - const std::set<std::string>& anyOfPermissions) + const std::set<std::string>& anyOfPermissions) ORTHANC_OVERRIDE { if (anyOfPermissions.size() == 0) {
--- a/Plugin/CachedAuthorizationService.h Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/CachedAuthorizationService.h Fri Jun 14 16:31:58 2024 +0200 @@ -67,17 +67,17 @@ CachedAuthorizationService(BaseAuthorizationService* decorated /* takes ownership */, ICacheFactory& factory); - virtual bool HasUserProfile() const + virtual bool HasUserProfile() const ORTHANC_OVERRIDE { return decorated_->HasUserProfile(); } - virtual bool HasCreateToken() const + virtual bool HasCreateToken() const ORTHANC_OVERRIDE { return decorated_->HasCreateToken(); } - virtual bool HasTokenValidation() const + virtual bool HasTokenValidation() const ORTHANC_OVERRIDE { return decorated_->HasTokenValidation(); } @@ -87,7 +87,7 @@ const std::string& id, const std::vector<IAuthorizationService::OrthancResource>& resources, const std::string& expirationDateString, - const uint64_t& validityDuration) + const uint64_t& validityDuration) ORTHANC_OVERRIDE { return decorated_->CreateToken(response, tokenType, @@ -99,7 +99,7 @@ virtual bool DecodeToken(DecodedToken& response, const std::string& tokenKey, - const std::string& tokenValue) + const std::string& tokenValue) ORTHANC_OVERRIDE { return decorated_->DecodeToken(response, tokenKey,
--- a/Plugin/DefaultAuthorizationParser.h Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/DefaultAuthorizationParser.h Fri Jun 14 16:31:58 2024 +0200 @@ -52,10 +52,10 @@ virtual bool Parse(AccessedResources& target, const std::string& uri, - const std::map<std::string, std::string>& getArguments); + const std::map<std::string, std::string>& getArguments) ORTHANC_OVERRIDE; - virtual bool IsListOfResources(const std::string& uri) const; + virtual bool IsListOfResources(const std::string& uri) const ORTHANC_OVERRIDE; - virtual void GetSingleResourcePatterns(std::vector<boost::regex>& patterns) const; + virtual void GetSingleResourcePatterns(std::vector<boost::regex>& patterns) const ORTHANC_OVERRIDE; }; }
--- a/Plugin/PermissionParser.cpp Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/PermissionParser.cpp Fri Jun 14 16:31:58 2024 +0200 @@ -26,9 +26,11 @@ namespace OrthancPlugins { - PermissionPattern::PermissionPattern(const OrthancPluginHttpMethod& method, const std::string& patternRegex, const std::string& permissions) : - method(method), - pattern(patternRegex) + PermissionPattern::PermissionPattern(const OrthancPluginHttpMethod& method, + const std::string& patternRegex, + const std::string& permissions) : + method_(method), + pattern_(patternRegex) { if (!permissions.empty()) { @@ -37,7 +39,7 @@ for (size_t i = 0; i < permissionsVector.size(); ++i) { - this->permissions.insert(permissionsVector[i]); + permissions_.insert(permissionsVector[i]); } } } @@ -72,6 +74,16 @@ { } + PermissionParser::~PermissionParser() + { + for (std::list<PermissionPattern*>::iterator it = permissionsPattern_.begin(); + it != permissionsPattern_.begin(); ++it) + { + assert(*it != NULL); + delete *it; + } + } + void PermissionParser::Add(const Json::Value& configuration, const IAuthorizationParser* authorizationParser) { if (configuration.type() != Json::arrayValue) @@ -150,7 +162,7 @@ LOG(WARNING) << "Authorization plugin: adding a new permission pattern: " << lowerCaseMethod << " " << regex << " - " << permission; - permissionsPattern_.push_back(PermissionPattern(parsedMethod, regex, permission)); + permissionsPattern_.push_back(new PermissionPattern(parsedMethod, regex, permission)); { // extract individual permissions std::set<std::string> permissions; @@ -177,16 +189,16 @@ boost::mutex::scoped_lock lock(mutex_); - for (std::list<PermissionPattern>::const_iterator it = permissionsPattern_.begin(); - it != permissionsPattern_.end(); ++it) + for (std::list<PermissionPattern*>::const_iterator it = permissionsPattern_.begin(); + it != permissionsPattern_.end(); ++it) { - if (method == it->method) + if (method == (*it)->GetMethod()) { boost::smatch what; - if (boost::regex_match(uri, what, it->pattern)) + if (boost::regex_match(uri, what, (*it)->GetPattern())) { - matchedPattern = it->pattern.expression(); - permissions = it->permissions; + matchedPattern = (*it)->GetPattern().expression(); + permissions = (*it)->GetPermissions(); return true; } }
--- a/Plugin/PermissionParser.h Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/PermissionParser.h Fri Jun 14 16:31:58 2024 +0200 @@ -27,20 +27,39 @@ namespace OrthancPlugins { - struct PermissionPattern + class PermissionPattern : public boost::noncopyable { - OrthancPluginHttpMethod method; - boost::regex pattern; - std::set<std::string> permissions; + private: + OrthancPluginHttpMethod method_; + boost::regex pattern_; + std::set<std::string> permissions_; + + public: + PermissionPattern(const OrthancPluginHttpMethod& method, + const std::string& patternRegex, + const std::string& permissions); - PermissionPattern(const OrthancPluginHttpMethod& method, const std::string& patternRegex, const std::string& permissions); + OrthancPluginHttpMethod GetMethod() const + { + return method_; + } + + const boost::regex& GetPattern() const + { + return pattern_; + } + + const std::set<std::string>& GetPermissions() const + { + return permissions_; + } }; - class PermissionParser + class PermissionParser : public boost::noncopyable { private: mutable boost::mutex mutex_; - std::list<PermissionPattern> permissionsPattern_; + std::list<PermissionPattern*> permissionsPattern_; std::set<std::string> permissionsList_; std::string dicomWebRoot_; std::string oe2Root_; @@ -49,6 +68,8 @@ PermissionParser(const std::string& dicomWebRoot, const std::string& oe2Root); + ~PermissionParser(); + void Add(const std::string& method, const std::string& patternRegex, const std::string& permission);
--- a/Plugin/Plugin.cpp Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/Plugin.cpp Fri Jun 14 16:31:58 2024 +0200 @@ -229,8 +229,6 @@ OrthancPluginHttpMethod method, const OrthancPlugins::AccessedResource& access) { - unsigned int validity; // ignored - // Ignored the access levels that are unchecked // (cf. "UncheckedLevels" option) if (uncheckedLevels_.find(access.GetLevel()) == uncheckedLevels_.end()) @@ -242,6 +240,7 @@ if (authTokens.empty()) { + unsigned int validity; // ignored granted = authorizationService_->IsGrantedToAnonymousUser(validity, method, access); } else @@ -249,6 +248,7 @@ // Loop over all the authorization tokens in the request until finding one that is granted for (size_t i = 0; i < authTokens.size(); ++i) { + unsigned int validity; // ignored if (authorizationService_->IsGranted(validity, method, access, authTokens[i].GetToken(), authTokens[i].GetValue())) { granted = true; @@ -284,8 +284,6 @@ { try { - unsigned int validity; // ignored - // Allow GET accesses to unchecked resources/folders (usually static resources) //////////////////////////////////////////////////////////////// @@ -314,7 +312,6 @@ // Based on the tokens, check if the user has access based on its permissions and the mapping between urls and permissions //////////////////////////////////////////////////////////////// bool hasUserRequiredPermissions = false; - bool hasAuthorizedLabelsForResource = false; if (permissionParser_.get() != NULL && authorizationService_.get() != NULL) @@ -328,6 +325,8 @@ std::string msg = std::string("Testing whether anonymous user has any of the required permissions '") + JoinStrings(requiredPermissions) + "'"; LOG(INFO) << msg; + + unsigned int validity; // ignored if (authorizationService_->HasAnonymousUserPermission(validity, requiredPermissions)) { LOG(INFO) << msg << " -> granted"; @@ -351,13 +350,16 @@ unsigned int validityNotUsed; authorizationService_->GetUserProfile(validityNotUsed, profile, authTokens[i].GetToken(), authTokens[i].GetValue()); + unsigned int validity; // ignored if (authorizationService_->HasUserPermission(validity, requiredPermissions, profile)) { LOG(INFO) << msg << " -> granted"; hasUserRequiredPermissions = true; // check labels permissions - std::string msg = std::string("Testing whether user has the authorized_labels to access '") + uri + "' based on the HTTP header '" + authTokens[i].GetToken().GetKey() + "'"; + msg = std::string("Testing whether user has the authorized_labels to access '") + uri + "' based on the HTTP header '" + authTokens[i].GetToken().GetKey() + "'"; + + bool hasAuthorizedLabelsForResource = false; if (CheckAuthorizedLabelsForResource(hasAuthorizedLabelsForResource, uri, getArguments, profile)) { if (hasAuthorizedLabelsForResource) @@ -795,7 +797,7 @@ } else { - throw e; + throw; } } @@ -860,7 +862,7 @@ } else { - throw e; + throw; } } } @@ -989,11 +991,6 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "A JSON payload was expected"); } - Json::Value authPayload; - - authPayload["token-key"] = body["TokenKey"].asString(); - authPayload["token-value"] = body["TokenValue"].asString(); - OrthancPlugins::IAuthorizationService::DecodedToken decodedToken; if (authorizationService_->DecodeToken(decodedToken, body["TokenKey"].asString(), @@ -1176,7 +1173,7 @@ try { - static const char* PLUGIN_SECTION = "Authorization"; + static const char* const PLUGIN_SECTION = "Authorization"; OrthancPlugins::OrthancConfiguration orthancFullConfiguration; @@ -1259,13 +1256,8 @@ std::string urlSettingsRole; std::string urlRoot; - static const char* WEB_SERVICE_ROOT = "WebServiceRootUrl"; - static const char* WEB_SERVICE_TOKEN_DECODER = "WebServiceTokenDecoderUrl"; - static const char* WEB_SERVICE_TOKEN_VALIDATION = "WebServiceTokenValidationUrl"; - static const char* WEB_SERVICE_TOKEN_CREATION_BASE = "WebServiceTokenCreationBaseUrl"; - static const char* WEB_SERVICE_USER_PROFILE = "WebServiceUserProfileUrl"; - static const char* WEB_SERVICE_SETTINGS_ROLES = "WebServiceSettingsRolesUrl"; - static const char* WEB_SERVICE_TOKEN_VALIDATION_LEGACY = "WebService"; + static const char* const WEB_SERVICE_ROOT = "WebServiceRootUrl"; + if (pluginConfiguration.LookupStringValue(urlRoot, WEB_SERVICE_ROOT)) { urlTokenDecoder = Orthanc::Toolbox::JoinUri(urlRoot, "/tokens/decode"); @@ -1276,6 +1268,13 @@ } else { + static const char* const WEB_SERVICE_TOKEN_DECODER = "WebServiceTokenDecoderUrl"; + static const char* const WEB_SERVICE_TOKEN_VALIDATION = "WebServiceTokenValidationUrl"; + static const char* const WEB_SERVICE_TOKEN_CREATION_BASE = "WebServiceTokenCreationBaseUrl"; + static const char* const WEB_SERVICE_USER_PROFILE = "WebServiceUserProfileUrl"; + static const char* const WEB_SERVICE_SETTINGS_ROLES = "WebServiceSettingsRolesUrl"; + static const char* const WEB_SERVICE_TOKEN_VALIDATION_LEGACY = "WebService"; + pluginConfiguration.LookupStringValue(urlTokenValidation, WEB_SERVICE_TOKEN_VALIDATION); pluginConfiguration.LookupStringValue(urlTokenDecoder, WEB_SERVICE_TOKEN_DECODER); if (urlTokenValidation.empty()) @@ -1306,7 +1305,7 @@ LOG(WARNING) << "Authorization plugin: url defined for User Profile: " << urlUserProfile << ", user tokens validation is enabled"; userTokensEnabled_ = true; - static const char* PERMISSIONS = "Permissions"; + static const char* const PERMISSIONS = "Permissions"; if (!pluginConfiguration.GetJson().isMember(PERMISSIONS)) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, "Authorization plugin: Missing required \"" + std::string(PERMISSIONS) +
--- a/Plugin/Token.cpp Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/Token.cpp Fri Jun 14 16:31:58 2024 +0200 @@ -37,4 +37,15 @@ { } + bool Token::operator< (const Token &right) const + { + if (type_ != right.type_) + { + return type_ < right.type_; + } + else + { + return key_ < right.key_ ; + } + } }
--- a/Plugin/Token.h Fri Jun 14 16:26:53 2024 +0200 +++ b/Plugin/Token.h Fri Jun 14 16:31:58 2024 +0200 @@ -47,16 +47,6 @@ } // required to use this class in std::set - bool operator< (const Token &right) const - { - if (type_ != right.type_) - { - return type_ < right.type_; - } - else - { - return key_ < right.key_ ; - } - } + bool operator< (const Token &right) const; }; }