summaryrefslogtreecommitdiff
path: root/lib/authorization.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/authorization.rb')
-rw-r--r--lib/authorization.rb401
1 files changed, 379 insertions, 22 deletions
diff --git a/lib/authorization.rb b/lib/authorization.rb
index 9a1760a..eab20df 100644
--- a/lib/authorization.rb
+++ b/lib/authorization.rb
@@ -1,24 +1,381 @@
-helpers do
+module OpenTox
+
+ #Module for Authorization and Authentication
+ #@example Authentication
+ # require "opentox-ruby-api-wrapper"
+ # OpenTox::Authorization::AA_SERVER = "https://opensso.in-silico.ch" #if not set in .opentox/conf/[environment].yaml
+ # token = OpenTox::Authorization.authenticate("benutzer", "passwort")
+ #@see http://www.opentox.org/dev/apis/api-1.2/AA OpenTox A&A API 1.2 specification
+
+ module Authorization
+
+ #Helper Class AA to create and send default policies out of xml templates
+ #@example Creating a default policy to a URI
+ # aa=OpenTox::Authorization::AA.new(tok)
+ # xml=aa.get_xml('http://uri....')
+ # OpenTox::Authorization.create_policy(xml,tok)
+
+ class AA
+ attr_accessor :user, :subjectid, :policy
+
+ #Generates AA object - requires subjectid
+ # @param [String] subjectid
+ def initialize(subjectid)
+ @user = Authorization.get_user(subjectid)
+ @subjectid = subjectid
+ @policy = Policies.new()
+ end
+
+ #Cleans AA Policies and loads default xml file into policy attribute
+ #set uri and user, returns Policyfile(XML) for open-sso
+ # @param [String] URI to create a policy for
+ def get_xml(uri)
+ @policy.drop_policies
+ @policy.load_default_policy(@user, uri)
+ return @policy.to_xml
+ end
+
+ #Loads and sends Policyfile(XML) to open-sso server
+ # @param [String] URI to create a policy for
+ def send(uri)
+ xml = get_xml(uri)
+ ret = false
+ ret = Authorization.create_policy(xml, @subjectid)
+ LOGGER.debug "Policy send with subjectid: #{@subjectid}"
+ LOGGER.warn "Not created Policy is: #{xml}" if !ret
+ ret
+ end
+
+ end
+
+ #Returns the open-sso server set in the config file .opentox/config/[environment].yaml
+ # @return [String, nil] the openSSO server URI or nil
+ def self.server
+ return AA_SERVER
+ end
+
+ #Authentication against OpenSSO. Returns token. Requires Username and Password.
+ # @param [String, String]Username,Password
+ # @return [String, nil] gives subjectid or nil
+ def self.authenticate(user, pw)
+ return nil if !AA_SERVER
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/auth/authenticate")
+ out = resource.post(:username=>user, :password => pw).sub("token.id=","").sub("\n","")
+ return out
+ rescue
+ return nil
+ end
+ end
+
+ #Logout on opensso. Make token invalid. Requires token
+ # @param [String]subjectid the subjectid
+ # @return [Boolean] true if logout is OK
+ def self.logout(subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/auth/logout")
+ resource.post(:subjectid => subjectid)
+ return true
+ rescue
+ return false
+ end
+ end
+
+ #Authorization against OpenSSO for a URI with request-method (action) [GET/POST/PUT/DELETE]
+ # @param [String,String,String]uri,action,subjectid
+ # @return [Boolean, nil] returns true, false or nil (if authorization-request fails).
+ def self.authorize(uri, action, subjectid)
+ return true if !AA_SERVER
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/auth/authorize")
+ return true if resource.post(:uri => uri, :action => action, :subjectid => subjectid) == "boolean=true\n"
+ rescue
+ return nil
+ end
+ end
+
+ #Checks if a token is a valid token
+ # @param [String]subjectid subjectid from openSSO session
+ # @return [Boolean] subjectid is valid or not.
+ def self.is_token_valid(subjectid)
+ return true if !AA_SERVER
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/auth/isTokenValid")
+ return true if resource.post(:tokenid => subjectid) == "boolean=true\n"
+ rescue
+ return false
+ end
+ end
- def protected!
- response['WWW-Authenticate'] = %(Basic realm="Opentox Webservice Authentication") and \
- throw(:halt, [401, "Not authorized\n"]) and \
- return unless authorized?
+ #Returns array with all policies of the token owner
+ # @param [String]subjectid requires subjectid
+ # @return [Array, nil] returns an Array of policy names or nil if request fails
+ def self.list_policies(subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
+ out = resource.get(:subjectid => subjectid)
+ return out.split("\n")
+ rescue RestClient::InternalServerError => e
+ raise e.response
+ rescue
+ return nil
+ end
+ end
+
+ #Returns a policy in xml-format
+ # @param [String, String]policy,subjectid
+ # @return [String] XML of the policy
+ def self.list_policy(policy, subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
+ return resource.get(:subjectid => subjectid,:id => policy)
+ rescue
+ return nil
+ end
+ end
+
+ # Lists policies alongside with affected uris
+ # @param [String] subjectid
+ # @return [Hash] keys: all policies of the subjectid owner, values: uris affected by those policies
+ def self.list_policy_uris( subjectid )
+ names = list_policies(subjectid)
+ policies = {}
+ names.each do |n|
+ p = OpenTox::Policies.new
+ p.load_xml( list_policy(n, subjectid) )
+ policies[n] = p.uris
+ end
+ policies
+ end
+
+ #Returns the owner (who created the first policy) of an URI
+ # @param [String, String]uri,subjectid
+ # return [String, nil]owner,nil returns owner of the URI
+ def self.get_uri_owner(uri, subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
+ return resource.get(:uri => uri, :subjectid => subjectid).sub("\n","")
+ rescue
+ return nil
+ end
+ end
+
+ #Checks if a policy exists to a URI. Requires URI and token.
+ # @param [String, String]uri,subjectid
+ # return [Boolean]
+ def self.uri_has_policy(uri, subjectid)
+ owner = get_uri_owner(uri, subjectid)
+ return true if owner and owner != "null"
+ false
+ end
+
+ #List all policynames for a URI. Requires URI and token.
+ # @param [String, String]uri,subjectid
+ # return [Array, nil] returns an Array of policy names or nil if request fails
+ def self.list_uri_policies(uri, subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
+ out = resource.get(:uri => uri, :polnames => true, :subjectid => subjectid)
+ policies = []; notfirstline = false
+ out.split("\n").each do |line|
+ policies << line if notfirstline
+ notfirstline = true
+ end
+ return policies
+ rescue
+ return nil
+ end
+ end
+
+ #Sends a policy in xml-format to opensso server. Requires policy-xml and token.
+ # @param [String, String]policyxml,subjectid
+ # return [Boolean] returns true if policy is created
+ def self.create_policy(policy, subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/Pol/opensso-pol")
+ LOGGER.debug "OpenTox::Authorization.create_policy policy: #{policy[168,43]} with token:" + subjectid.to_s + " length: " + subjectid.length.to_s
+ return true if resource.post(policy, :subjectid => subjectid, :content_type => "application/xml")
+ rescue
+ return false
+ end
+ end
+
+ #Deletes a policy
+ # @param [String, String]policyname,subjectid
+ # @return [Boolean,nil]
+ def self.delete_policy(policy, subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
+ LOGGER.debug "OpenTox::Authorization.delete_policy policy: #{policy} with token: #{subjectid}"
+ return true if resource.delete(:subjectid => subjectid, :id => policy)
+ rescue
+ return nil
+ end
+ end
+
+ #Returns array of all possible LDAP-Groups
+ # @param [String]subjectid
+ # @return [Array]
+ def self.list_groups(subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/opensso/identity/search")
+ grps = resource.post(:admin => subjectid, :attributes_names => "objecttype", :attributes_values_objecttype => "group")
+ grps.split("\n").collect{|x| x.sub("string=","")}
+ rescue
+ []
+ end
+ end
+
+ #Returns array of the LDAP-Groups of an user
+ # @param [String]subjectid
+ # @return [Array] gives array of LDAP groups of a user
+ def self.list_user_groups(user, subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/opensso/identity/read")
+ out = resource.post(:name => user, :admin => subjectid, :attributes_names => "group")
+ grps = []
+ out.split("\n").each do |line|
+ grps << line.sub("identitydetails.group=","") if line.include?("identitydetails.group=")
+ end
+ return grps
+ rescue
+ []
+ end
+ end
+
+ #Returns the owner (user id) of a token
+ # @param [String]subjectid
+ # @return [String]user
+ def self.get_user(subjectid)
+ begin
+ resource = RestClient::Resource.new("#{AA_SERVER}/opensso/identity/attributes")
+ out = resource.post(:subjectid => subjectid, :attributes_names => "uid")
+ user = ""; check = false
+ out.split("\n").each do |line|
+ if check
+ user = line.sub("userdetails.attribute.value=","") if line.include?("userdetails.attribute.value=")
+ check = false
+ end
+ check = true if line.include?("userdetails.attribute.name=uid")
+ end
+ return user
+ rescue
+ nil
+ end
+ end
+
+ #Send default policy with Authorization::AA class
+ # @param [String, String]URI,subjectid
+ def self.send_policy(uri, subjectid)
+ return true if !AA_SERVER
+ aa = Authorization::AA.new(subjectid)
+ ret = aa.send(uri)
+ LOGGER.debug "OpenTox::Authorization send policy for URI: #{uri} | subjectid: #{subjectid} - policy created: #{ret}"
+ ret
+ end
+
+ #Deletes all policies of an URI
+ # @param [String, String]URI,subjectid
+ # @return [Boolean]
+ def self.delete_policies_from_uri(uri, subjectid)
+ policies = list_uri_policies(uri, subjectid)
+ policies.each do |policy|
+ ret = delete_policy(policy, subjectid)
+ LOGGER.debug "OpenTox::Authorization delete policy: #{policy} - with result: #{ret}"
+ end
+ return true
+ end
+
+ # Checks (if subjectid is valid) if a policy exist and create default policy if not
+ # @param [String] uri
+ # @param [String] subjectid
+ # @return [Boolean] true if policy checked/created successfully (or no uri/subjectid given), false else
+ def self.check_policy(uri, subjectid)
+ return true unless uri and subjectid
+ token_valid = OpenTox::Authorization.is_token_valid(subjectid)
+ LOGGER.debug "OpenTox::Authorization.check_policy with uri: #{uri}, subjectid: #{subjectid} is valid: #{token_valid}"
+ # check if subjectid is valid
+ unless token_valid
+ # abort if invalid
+ LOGGER.error "OpenTox::Authorization.check_policy, subjectid NOT valid: #{subjectid}"
+ return false
+ end
+
+ if !uri_has_policy(uri, subjectid)
+ # if no policy exists, create a policy, return result of send policy
+ send_policy(uri, subjectid)
+ else
+ # if policy exists check for POST rights
+ if authorize(uri, "POST", subjectid)
+ true
+ else
+ LOGGER.error "OpenTox::Authorization.check_policy, already exists, but no POST-authorization with subjectid: #{subjectid}"
+ false
+ end
+ end
+ true
+ end
+
+ class << self
+ alias :token_valid? :is_token_valid
+ end
+
+ # Check Authorization for a resource (identified via URI) with method and subjectid.
+ # @param [String] uri
+ # @param [String] request_method, should be GET, POST, PUT, DELETE
+ # @param [String] subjectid
+ # @return [Boolean] true if access granted, else otherwise
+ def self.authorized?(uri, request_method, subjectid)
+ if CONFIG[:authorization][:free_request].include?(request_method)
+ #LOGGER.debug "authorized? >>true<< (request is free), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
+ true
+ elsif OpenTox::Authorization.free_uri?(uri, request_method)
+ #LOGGER.debug "authorized? >>true<< (uris is free_uri), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
+ true
+ elsif CONFIG[:authorization][:authenticate_request].include?(request_method)
+ ret = OpenTox::Authorization.is_token_valid(subjectid)
+ LOGGER.debug "authorized? >>#{ret}<< (token is in/valid), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
+ ret
+ elsif OpenTox::Authorization.authorize_exception?(uri, request_method)
+ ret = OpenTox::Authorization.is_token_valid(subjectid)
+ LOGGER.debug "authorized? >>#{ret}<< (uris is authorize exception, token is in/valid), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
+ ret
+ elsif CONFIG[:authorization][:authorize_request].include?(request_method)
+ ret = OpenTox::Authorization.authorize(uri, request_method, subjectid)
+ LOGGER.debug "authorized? >>#{ret}<< (uri (not) authorized), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
+ ret
+ else
+ LOGGER.error "invalid request/uri method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
+ false
+ end
+ end
+
+ private
+ def self.free_uri?(uri, request_method)
+ if CONFIG[:authorization][:free_uris]
+ CONFIG[:authorization][:free_uris].each do |request_methods,uris|
+ if request_methods and uris and request_methods.include?(request_method.to_sym)
+ uris.each do |u|
+ return true if u.match uri
+ end
+ end
+ end
+ end
+ return false
+ end
+
+ def self.authorize_exception?(uri, request_method)
+ if CONFIG[:authorization][:authorize_exceptions]
+ CONFIG[:authorization][:authorize_exceptions].each do |request_methods,uris|
+ if request_methods and uris and request_methods.include?(request_method.to_sym)
+ uris.each do |u|
+ return true if u.match uri
+ end
+ end
+ end
+ end
+ return false
+ end
+
end
-
- def authorized?
- @auth ||= Rack::Auth::Basic::Request.new(request.env)
- @auth.provided? && @auth.basic? && @auth.credentials && valid_user?
- end
-
- def valid_user?
- users = @@users[:users]
- return @auth.credentials == [@auth.username, users.fetch(@auth.username)] if users.has_key?(@auth.username)
- return false
- end
-
-end
-
-before do
- #protected! unless env['REQUEST_METHOD'] == "GET"
-end
+end \ No newline at end of file