Return-Path: X-Original-To: apmail-airavata-dev-archive@www.apache.org Delivered-To: apmail-airavata-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 77DBB11D96 for ; Wed, 30 Jul 2014 15:57:14 +0000 (UTC) Received: (qmail 17557 invoked by uid 500); 30 Jul 2014 15:57:14 -0000 Delivered-To: apmail-airavata-dev-archive@airavata.apache.org Received: (qmail 17529 invoked by uid 500); 30 Jul 2014 15:57:14 -0000 Mailing-List: contact dev-help@airavata.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@airavata.apache.org Delivered-To: mailing list dev@airavata.apache.org Received: (qmail 17518 invoked by uid 99); 30 Jul 2014 15:57:13 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Jul 2014 15:57:13 +0000 X-ASF-Spam-Status: No, hits=-2.3 required=5.0 tests=RCVD_IN_DNSWL_MED,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: local policy) Received: from [129.79.1.194] (HELO hartman.uits.indiana.edu) (129.79.1.194) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 30 Jul 2014 15:57:09 +0000 X-IronPort-AV: E=Sophos;i="5.01,765,1400040000"; d="out'?scan'208";a="160435105" Received: from mssg-relay.indiana.edu ([129.79.1.73]) by irpt-internal-relay.indiana.edu with ESMTP; 30 Jul 2014 11:56:48 -0400 Received: from hartman.uits.indiana.edu (hartman.uits.indiana.edu [129.79.1.194]) by mssg-relay.indiana.edu (8.14.7/8.14.4/IU Messaging Team) with ESMTP id s6UFumfr002933 for ; Wed, 30 Jul 2014 11:56:48 -0400 X-IronPort-AV: E=Sophos;i="5.01,765,1400040000"; d="out'?scan'208";a="160166243" Received: from burns.uits.indiana.edu (HELO mail-relay.iu.edu) ([129.79.1.202]) by irpt-internal-relay.indiana.edu with ESMTP; 30 Jul 2014 11:56:47 -0400 Received: from 149-160-240-223.dhcp-bl.indiana.edu (149-160-240-223.dhcp-bl.indiana.edu [149.160.240.223]) (authenticated bits=0) by mail-relay.iu.edu (8.14.7/8.14.4/IU Messaging Team) with ESMTP id s6UFulBi024305 for ; Wed, 30 Jul 2014 11:56:47 -0400 Message-ID: <53D915C0.8020506@iu.edu> Date: Wed, 30 Jul 2014 11:56:48 -0400 From: Marlon Pierce User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:24.0) Gecko/20100101 Thunderbird/24.6.0 MIME-Version: 1.0 To: dev@airavata.apache.org Subject: Re: Notion of user roles in the PHP Reference Gateway References: <83A6DF07-2C0D-4970-95B0-C264555BF531@apache.org> <53B1BEE0.3020008@iu.edu> <53BADFFA.8060605@iu.edu> <53BAE512.5010405@iu.edu> <53BC0357.9090803@iu.edu> <53BE6D81.2050703@iu.edu> <53D65231.3030101@iu.edu> In-Reply-To: Content-Type: multipart/mixed; boundary="------------000305020305080300030101" X-Virus-Checked: Checked by ClamAV on apache.org This is a multi-part message in MIME format. --------------000305020305080300030101 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hi Supun-- I got things working, more or less. I had to "localize" the startup scripts to get the API server to start; see my comments in github. The PHP command line tools work fine, but I was not able to run the unit tests (see attachment). The core work looks good but you have several rough edges still. I may have deeper comments about the core later. Marlon On 7/28/14, 9:48 AM, Supun Nakandala wrote: > Hi Marlon, > > Please see the inline comments > > > On Mon, Jul 28, 2014 at 7:07 PM, Marlon Pierce wrote: > >> Hi Supun-- >> >> Nice progress and writeup. I'll test out with the php client samples. Some >> small comments below. >> >> * Does the "authenticateGateway()" method authenticate a user to a >> particular gateway, or do I misunderstand? >> > authenticateGateway method is called for authenticating the gateway. Not > for authenticating a particular user. For authenticating a user > authenticateUser > method has to be used. > > >> * You should add a "disableUser()" method. Hopefully this is easily >> implemented in the IS. A disabled user may be able to authenticate but not >> be able to do anything (no permissions), or he/she may simply be denied >> authentication. But all the user's profile information and roles are >> retained in case the account is re-enabled. >> > I did some research into this previously. But apparently there is no > explicit way of disabling a user. What they have suggested is to specify a > new role for disabled users and assign it. I'll see more into this. [ > http://stackoverflow.com/questions/15420138/wso2-identity-server-deactivating-user-account > ] > >> * Are you assigning permissions directly to the user object or indirectly >> through roles. That is, the role has the permission and the user is >> assigned to the role. The API implies it is assigned to the user directly >> but it seems like a better design to assign these to the roles directly. >> > The permissions are added to roles. This has to be configured from the wso2 > IS side. Not from the User API. From the user api gateways can assign roles > to users and remove them via the methods addUserToRole and > removeUserFromRole. > >> >> Marlon >> >> >> >> >> On 7/25/14, 1:35 PM, Supun Nakandala wrote: >> >>> Hi All, >>> >>> During the past few weeks I have done several changes to the airavata user >>> api. The new thrift interface descriptors can be found at >>> https://github.com/scnakandala/airavata-userapi/ >>> tree/master/userapi/thrift-interface-descriptors >>> >>> Most of the new changes are related to permissions and role. >>> >>> - Earlier it was possible to create roles and delete them from the >>> user >>> >>> api side. But now I have removed that. Now roles can be created and >>> deleted >>> only from the WSO2 IS management console. >>> - I have added addUserToRole , >>> >>> removeUserFromRole , getUserListOfRole >> get >>> the user list of particular role>, getRoleListOfUser >> list for a user. user can have more than one role>, getAllRoleNames >>> >> admin, and Internal/*> >>> - As per the gateway specific roles I have created the roles from the >>> >>> WSO2 IS side specified by Suresh previously in this thread. >>> - In terms of permission validation I have added getUserPermissions >>> and >>> checkPermission methods. >>> - getUserPermissions returns an object ( >>> >>> https://github.com/scnakandala/airavata-userapi/ >>> blob/master/userapi/thrift-interface-descriptors/userAPIModels.thrift#L50 >>> ) >>> which contains two maps of permissions sets one for airavata api and >>> other >>> for app catalog. The key value in these maps is the name of the api >>> method >>> and the value will be true if the user has permission else false. In >>> addition to these to maps it also has a string signature. I have >>> added this >>> signature so that this object can be verified by the server or any >>> intended >>> party. This addresses the issue of avoiding too many calls to server >>> as >>> Marlon mentioned previously in this thread. Currently this signature >>> is >>> prepared by concatenating the serialized strings of the two maps and >>> the >>> time stamp which is then encrypted using AES. >>> - checkPermission method can verify whether a user has a particular >>> >>> permission. eg >>> getUserPermission('scnakandala','airavata-api/create_project',$token) >>> - Also now the authenticateUser method returns the same output as in >>> >>> getUserPermissions if the authentication is successful. >>> >>> I also looked into the concerns related to token generation. >>> >>> Although wso2 IS provides OAuth based authentication/authorization there >>> is >>> a problem of using it in the user api. User api is operated by calling the >>> admin services of the wso2 IS under the cover. These services are soap >>> endpoints and cannot be accessed via oauth authorization. There are SCIM >>> REST services which can be accessed via oauth authorization but those >>> services are not sufficient for the user api functions. >>> >>> Currently I have used http basic authentication. This means for every soap >>> call from user api to wso2 IS I send admin username and the password of >>> the >>> tenant in use. Since we are sending the username IS knows on which tenant >>> we are dealing with. This creates two possibilities for the communication >>> between gateway and the user api >>> >>> 1. gateway send tenant admin username and password with every request >>> to >>> the user api >>> 2. user api stores tenant admin's username and password upon >>> successful >>> >>> gateway authentication and issue a temporary token to identify the >>> gateway. >>> This requires to maintain tokens, username, password information at >>> the >>> user api. >>> >>> In the current implementation I have followed the second approach with a >>> slight change. Rather than storing the credential information I have embed >>> the credential information and time stamp in the token. This token is then >>> encrypted using AES. So when a gateway calls a method with the token user >>> api can decrypt the token and retrieve the gateway admin credentials. This >>> was done for easy implementation. But if sending username, password >>> information has security implications we can implement a token store in >>> the >>> user api side to store the gateway admin's credential information. >>> >>> I renamed the previous adminLogin method to authenticateGateway to better >>> suit its purpose. Upon successful authentication it returns a >>> AuthenticationResponse ( >>> https://github.com/scnakandala/airavata-userapi/ >>> blob/master/userapi/thrift-interface-descriptors/userAPIModels.thrift#L45 >>> ) >>> which contains the token and the time to expire. >>> >>> At the gateway side the gateway has to call this method at an interval >>> which corresponds to the expiration time of the token. For the PHP >>> Reference Gateway I have added this feature where it stores the token >>> information in a xml file. ( >>> https://github.com/SciGaP/PHP-Reference-Gateway/blob/master/ >>> userapi_tokens.xml). >>> Though for every user api call the token has to be read from this file it >>> will not be an issue as this file will get buffed in the memory most of >>> the >>> time. >>> >>> >>> I have incorporated these changes to the PHP Reference Gateway and also >>> updated the php client sample which can be found at >>> https://github.com/scnakandala/airavata-userapi/tree/master/clients/php- >>> client/client-samples >>> >>> Thank you >>> Supun >>> >>> >>> On Thu, Jul 10, 2014 at 4:10 PM, Marlon Pierce wrote: >>> >>> Thanks, Supun. Some comments and questions below: >>>> * When and how often does the adminLogin method get invoked? >>>> >>>> * The string that adminLogin returns is the encrypted token you describe >>>> below? >>>> >>>> * I don't like the idea of sending around tokens with embedded passwords, >>>> even if encrypted. Why do you require this? I think you need to rethink >>>> this part and look more closely at other multi-party Web security >>>> protocols >>>> (OAuth, OpenID,...). >>>> >>>> * How are you encrypting? Amila pointed out earlier that public key >>>> encryption is slow and usually shared secret keys are used after some >>>> handshake. >>>> >>>> * Also you need to take into account that these calls to the IS are >>>> frequent operations in your design. They can't add a lot of overhead to >>>> the >>>> process (too much network communication, too much time >>>> encrypting/decrypting, server gets overloaded processing requests, etc). >>>> >>>> * You need to think about scaling. Servers are not up all the time, can't >>>> handle infinite requests in zero time, and don't have infinitely fast and >>>> wide network connections. If we have lots of over the wire communications >>>> to the IS for every single Airavata API requests, this won't scale. >>>> >>>> * For permission checking, I think your second approach is better. There >>>> is no need for Airavata to do the checking itself. It should just ask the >>>> IS if OK and bet a yes/no answer. You could also expose "getRoles" and >>>> "getPermissions" as optional methods. >>>> >>>> Marlon >>>> >>>> >>>> >>>> On 7/9/14, 7:58 AM, Supun Nakandala wrote: >>>> >>>> Hi Marlon, >>>>> Please see the inline comments. >>>>> >>>>> >>>>> On Tue, Jul 8, 2014 at 8:12 PM, Marlon Pierce wrote: >>>>> >>>>> Thanks, Supun. Could you say more about the UserAPI at the top? >>>>> >>>>>> Please also say more about the implementation. For example, how do you >>>>>> check permissions for the "gateway user" role and the "gateway admin" >>>>>> role? >>>>>> Also, how can Airavata determine which gateway the user is associated >>>>>> with? >>>>>> >>>>>> The flow goes like this. >>>>>> >>>>>> 1. First the tenant admin should provide his username >>>>> (username@domain >>>>> , >>>>> >>>>> eg admin@phprg.scigap.org) and password to the user api and get >>>>> authenticated. This operation corresponds to ( >>>>> https://github.com/scnakandala/airavata-userapi/ >>>>> blob/master/userapi/thrift-interface-descriptors/userAPI.thrift#L65) >>>>> method in thrift interface descriptor. If the login is successful >>>>> user api >>>>> creates an encrypted token which contains the username of the admin >>>>> (with >>>>> the domain) , password and the time stamp. For all other api >>>>> methods >>>>> the >>>>> gateway should send this token. The valid time duration of this >>>>> token >>>>> is >>>>> configurable. >>>>> 2. When checking for permissions I am going to use an API method as >>>>> *bool >>>>> isUserAuthorized(username, permissionString, token) . *As this >>>>> request >>>>> >>>>> contains the token we can decrypt it find the gateway admin's >>>>> username, >>>>> domain, and password and use these credentials to the communication >>>>> between >>>>> wso2 IS and user api. *From the domain we can distinguish which >>>>> gateway >>>>> the user is associated with*. >>>>> >>>>> >>>>> For checking the permissions of the gateway user and gateway admin user >>>>> (or >>>>> any other roles) there are two approaches. >>>>> >>>>> - given a username and the permission string first fetch the roles >>>>> of >>>>> >>>>> that user and then retrieve the permissions of those roles to check >>>>> the >>>>> permissions. >>>>> - given a username and the permission string use the wso2 IS >>>>> directly >>>>> to >>>>> >>>>> check the permissions. >>>>> >>>>> I personally prefer the second approach. In this approach we can define >>>>> permission strings and assign these permissions to different roles. [If >>>>> you >>>>> can login to the wso2 IS phprg tenant you can see the permissions that I >>>>> have defined and the roles that I have created.] If we want to check >>>>> permission for a user from the user API side we need not to bother about >>>>> the roles of that particular user. We can simply send the username and >>>>> permission string to the wso2 IS which will check whether this user has >>>>> at >>>>> least one role which contains the given permission. >>>>> >>>>> Later, it may be nice if there was some way to avoid the call from >>>>> Airavata >>>>> >>>>> to the UserAPI (step 3). For example (just brainstorming), when the >>>>>> user >>>>>> logs, the UserAPI returns a session object that has all the user's >>>>>> roles >>>>>> and permissions. This object includes signing information from the IS >>>>>> that >>>>>> Airavata can verify directly. This would remove the call (step 3) and >>>>>> so >>>>>> may increase reliability. Performance may or may not increase, >>>>>> depending >>>>>> on >>>>>> how long it takes to verify the signature. >>>>>> >>>>>> I understand the requirement. I'll see to this also >>>>> Marlon >>>>> >>>>>> On 7/8/14, 1:00 AM, Supun Nakandala wrote: >>>>>> >>>>>> Hi Marlon, >>>>>> >>>>>>> Below is the schematic diagram of the proposed solution architecture. >>>>>>> >>>>>>> ​Supun. >>>>>>> >>>>>>> >>>>>>> On Tue, Jul 8, 2014 at 12:24 AM, Supun Nakandala < >>>>>>> supun.nakandala@gmail.com> >>>>>>> wrote: >>>>>>> >>>>>>> My plan is to use tokens when calling the API methods. These tokens >>>>>>> will >>>>>>> >>>>>>> be granted by the user store at the time of user authentication. This >>>>>>>> tokens will be encrypted tokens which will contain the information >>>>>>>> about >>>>>>>> the gateway which can be used to verify the identity of the gateway. >>>>>>>> When authorization happens the user store has to call the correct >>>>>>>> WSO2 >>>>>>>> IS >>>>>>>> tenant. It can use the information inside the token to do so. >>>>>>>> >>>>>>>> I will give a schematic diagram of the proposed solution ASAP. >>>>>>>> >>>>>>>> >>>>>>>> On Mon, Jul 7, 2014 at 11:51 PM, Marlon Pierce >>>>>>>> wrote: >>>>>>>> >>>>>>>> That's great. Can you say more about your plans? Two concerns: >>>>>>>> >>>>>>>> * The new application catalog functions fit within the "gateway >>>>>>>>> admin" >>>>>>>>> role that Suresh listed previously. >>>>>>>>> >>>>>>>>> * The API also does not distinguish which gateway may be calling the >>>>>>>>> server. This is the multi-tenanted scenario--that is, multiple >>>>>>>>> gateways >>>>>>>>> call the same Airavata server. >>>>>>>>> >>>>>>>>> So I strongly advise making a sample plan based on simple scenarios >>>>>>>>> and >>>>>>>>> share this on the dev list as soon as possible so that we make sure >>>>>>>>> you >>>>>>>>> are >>>>>>>>> on the right path. >>>>>>>>> >>>>>>>>> Marlon >>>>>>>>> >>>>>>>>> >>>>>>>>> On 7/7/14, 2:10 PM, Supun Nakandala wrote: >>>>>>>>> >>>>>>>>> I do agree with Amila. XACML can be used to implement very fine >>>>>>>>> grained >>>>>>>>> >>>>>>>>> authorization. But that level is not required in the Airavata >>>>>>>>>> context. >>>>>>>>>> >>>>>>>>>> From WSO2 IS 5.0 on wards we can register applications with IS >>>>>>>>>> and >>>>>>>>>> define >>>>>>>>>> various permissions and grant these permissions to users. This is >>>>>>>>>> exactly >>>>>>>>>> inline with what Amila suggested previously. I am planning to use >>>>>>>>>> this >>>>>>>>>> feature to implement authorization of the Airavata API. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Mon, Jul 7, 2014 at 11:29 PM, Marlon Pierce >>>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>> Hi Supun, what do you think of Amila's suggestion below? >>>>>>>>>> >>>>>>>>>> Marlon >>>>>>>>>> >>>>>>>>>>> On 7/1/14, 10:35 AM, Amila Jayasekara wrote: >>>>>>>>>>> >>>>>>>>>>> On Mon, Jun 30, 2014 at 3:47 PM, Marlon Pierce < >>>>>>>>>>> marpierc@iu.edu> >>>>>>>>>>> >>>>>>>>>>> wrote: >>>>>>>>>>> >>>>>>>>>>>> A little question, maybe premature: how are these roles >>>>>>>>>>>> going >>>>>>>>>>>> to >>>>>>>>>>>> be >>>>>>>>>>>> >>>>>>>>>>>> communicated over the Thrift-based API? >>>>>>>>>>>> >>>>>>>>>>>> This is what I have in mind; >>>>>>>>>>>>> Each API function has a permission string (E.g :- for >>>>>>>>>>>>> >>>>>>>>>>>> executeExperiment() >>>>>>>>>>>> permission string is "/apache/airavata/execute"). These >>>>>>>>>>>> permission >>>>>>>>>>>> strings >>>>>>>>>>>> are defined in IS. Also IS is connected to user store (LDAP or >>>>>>>>>>>> Database) >>>>>>>>>>>> in >>>>>>>>>>>> read/write mode. But Airavata should be connected to user store >>>>>>>>>>>> in >>>>>>>>>>>> "read >>>>>>>>>>>> only" mode. >>>>>>>>>>>> >>>>>>>>>>>> There are 2 steps to consider. >>>>>>>>>>>> >>>>>>>>>>>> Step 1 : Granting permission - For this we expect an >>>>>>>>>>>> administrator >>>>>>>>>>>> (maybe >>>>>>>>>>>> tenant admin) to follow below steps; >>>>>>>>>>>> 1. Login to IS as administrator >>>>>>>>>>>> 2. Select/Create role >>>>>>>>>>>> 3. Assign appropriate permissions to role >>>>>>>>>>>> 4. Add needed users to role >>>>>>>>>>>> >>>>>>>>>>>> Step 2 : Authorising user at Airavata >>>>>>>>>>>> 1. Before invoking API function we authenticate user. From this >>>>>>>>>>>> we >>>>>>>>>>>> get >>>>>>>>>>>> user >>>>>>>>>>>> name >>>>>>>>>>>> 2. Then we need to check whether user is authorized to execute >>>>>>>>>>>> function. >>>>>>>>>>>> 3. For this we need to get the permission (permission string) >>>>>>>>>>>> associated >>>>>>>>>>>> with currently executing function. (We need to figure out where >>>>>>>>>>>> these >>>>>>>>>>>> permission to function mapping should be stored) >>>>>>>>>>>> 4. Now invoke "IS user API" to check whether user has permissions >>>>>>>>>>>> (isUserAuthorise(permission, username) kind of function in "IS >>>>>>>>>>>> API") >>>>>>>>>>>> 5. "IS API" will take care of finding appropriate roles and >>>>>>>>>>>> permissions >>>>>>>>>>>> and >>>>>>>>>>>> will finally return whether user is authorized or not for given >>>>>>>>>>>> permission >>>>>>>>>>>> string >>>>>>>>>>>> 6. Based on the return value you continue operation or throw an >>>>>>>>>>>> error. >>>>>>>>>>>> >>>>>>>>>>>> So if I go to your original question (i.e. how roles are >>>>>>>>>>>> communicated >>>>>>>>>>>> over >>>>>>>>>>>> thrift ?); the answer is we do not communicate role to Airavata. >>>>>>>>>>>> We >>>>>>>>>>>> only >>>>>>>>>>>> send user name/password (or some other authentication data) to >>>>>>>>>>>> Airavata. >>>>>>>>>>>> But Airavata needs to communicate with underlying user store in >>>>>>>>>>>> read >>>>>>>>>>>> only >>>>>>>>>>>> mode. For this we can use IS user store API. From the user name >>>>>>>>>>>> the >>>>>>>>>>>> "User >>>>>>>>>>>> store API" will figure out roles and also associated permissions. >>>>>>>>>>>> >>>>>>>>>>>> All above are based on my knowledge I had 2 years ago about IS. >>>>>>>>>>>> Things >>>>>>>>>>>> might have changed. So Supun, please check how to achieve above >>>>>>>>>>>> functionality with current IS. >>>>>>>>>>>> >>>>>>>>>>>> Thank you >>>>>>>>>>>> Regards >>>>>>>>>>>> -Thejaka Amila >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> Marlon >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On 6/30/14, 3:43 PM, Supun Nakandala wrote: >>>>>>>>>>>>> Hi Suresh, >>>>>>>>>>>>> >>>>>>>>>>>>> On Mon, Jun 30, 2014 at 5:57 PM, Suresh Marru < >>>>>>>>>>>>> smarru@apache.org> >>>>>>>>>>>>> >>>>>>>>>>>>> wrote: >>>>>>>>>>>>>> Hi Supun, >>>>>>>>>>>>>> >>>>>>>>>>>>>> Amila is right on. To your question on what roles PHP >>>>>>>>>>>>>> Gateway >>>>>>>>>>>>>> will >>>>>>>>>>>>>> >>>>>>>>>>>>>> need, >>>>>>>>>>>>>> >>>>>>>>>>>>>>> I >>>>>>>>>>>>>>> will make a first order approximation and suggest the >>>>>>>>>>>>>>> following: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Casual Users - When users stumble upon a gateway, provide >>>>>>>>>>>>>>> basic >>>>>>>>>>>>>>> tutorials. >>>>>>>>>>>>>>> For example, we used to allow casual users execute educational >>>>>>>>>>>>>>> experiments >>>>>>>>>>>>>>> - http://www.atmos.millersville.edu/~lead/modules.htm >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I think in Casual Users the requirement is to have >>>>>>>>>>>>>>> experiment >>>>>>>>>>>>>>> level >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> access >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> control and not API level access controlling. So I think in >>>>>>>>>>>>>> addition >>>>>>>>>>>>>> to >>>>>>>>>>>>>> considering the API level functions as resources (as Amila >>>>>>>>>>>>>> suggested) we >>>>>>>>>>>>>> may have to define several other resources which does not have >>>>>>>>>>>>>> a >>>>>>>>>>>>>> direct >>>>>>>>>>>>>> mapping to API level functions but will require in order to >>>>>>>>>>>>>> handle >>>>>>>>>>>>>> this >>>>>>>>>>>>>> type of scenarios. >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> Gateway Users - These users are vetted by the >>>>>>>>>>>>>> administrators >>>>>>>>>>>>>> and >>>>>>>>>>>>>> pretty >>>>>>>>>>>>>> >>>>>>>>>>>>>> much have permission to execute all applications and >>>>>>>>>>>>>> charge to >>>>>>>>>>>>>> >>>>>>>>>>>>>> allocations. >>>>>>>>>>>>>> >>>>>>>>>>>>>>> Application Providers - This role will allow to register new >>>>>>>>>>>>>>> applications >>>>>>>>>>>>>>> and workflows (as opposed to only using them by gateway >>>>>>>>>>>>>>> users). >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Gateway Administrators - essentially tenant admins. Manage >>>>>>>>>>>>>>> community >>>>>>>>>>>>>>> account credentials, add remove user roles and other admin >>>>>>>>>>>>>>> functions. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Gateway Operators - Typically this is done by gateway >>>>>>>>>>>>>>> administrators >>>>>>>>>>>>>>> themselves, but better to have a separate role. These role >>>>>>>>>>>>>>> will >>>>>>>>>>>>>>> be >>>>>>>>>>>>>>> used >>>>>>>>>>>>>>> for >>>>>>>>>>>>>>> notifying when user experiments go wrong due to infrastructure >>>>>>>>>>>>>>> reasons. >>>>>>>>>>>>>>> Enable/Disable compute resources, applications. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> A users may be in one or more roles. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Suresh >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On Jun 30, 2014, at 3:53 AM, Amila Jayasekara < >>>>>>>>>>>>>>> thejaka.amila@gmail.com >>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Hi Supun, >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I would expect following; (others please correct me if I >>>>>>>>>>>>>>> am >>>>>>>>>>>>>>> wrong) >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> We need to control access to API functions through roles. >>>>>>>>>>>>>>> Also >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> IS >>>>>>>>>>>>>>>> has >>>>>>>>>>>>>>>> a >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> notion of permissions and resources. So the resources >>>>>>>>>>>>>>>> are >>>>>>>>>>>>>>>> mapped >>>>>>>>>>>>>>>> to >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> functions defined in thrift API. So a permission would >>>>>>>>>>>>>>>> look >>>>>>>>>>>>>>>> like >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> follows >>>>>>>>>>>>>>> (hypothetically); >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> permission = ("execute", /scigap/thrift/ >>>>>>>>>>>>>>> executeExperiment); >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> We should be able to attach such permissions to roles. So >>>>>>>>>>>>>>> when >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> user >>>>>>>>>>>>>>>> invokes an API function we need to do following; >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 1. find user's role >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> 2. examine role's permissions >>>>>>>>>>>>>>> 3. check whether any role has permission relevant to invoking >>>>>>>>>>>>>>>> function >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> AFAIK IS provided a way to define permissions and attach them >>>>>>>>>>>>>>>> to >>>>>>>>>>>>>>>> roles. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> You may need to check how those can be used through APIs >>>>>>>>>>>>>>>> and >>>>>>>>>>>>>>>> how >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> achieve >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> above described functionality. >>>>>>>>>>>>>>> Thanks >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Regards >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> -Thejaka Amila >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> On Sun, Jun 29, 2014 at 2:19 PM, Supun Nakandala < >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> supun.nakandala@gmail.com> wrote: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Hi all, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I am in the process of incorporating the notion of roles >>>>>>>>>>>>>>> to >>>>>>>>>>>>>>> the >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> PHP >>>>>>>>>>>>>>>> Reference Gateway using the proxy user api that I am >>>>>>>>>>>>>>>> developing. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> WSO2 IS >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> enables the tenant admin (gateway admin) to create roles and >>>>>>>>>>>>>>> assign >>>>>>>>>>>>>>> users >>>>>>>>>>>>>>> to roles (many to many mapping). From the gateway side we can >>>>>>>>>>>>>>> consume >>>>>>>>>>>>>>> these >>>>>>>>>>>>>>> services and implement role based user functionality. The >>>>>>>>>>>>>>> roles >>>>>>>>>>>>>>> defined >>>>>>>>>>>>>>> will only be visible to that particular gateway(tenant). >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I would like to know what type of role based >>>>>>>>>>>>>>> functionality >>>>>>>>>>>>>>> is >>>>>>>>>>>>>>> required >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> in the context of the PHP Reference Gateway. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thank you. >>>>>>>>>>>>>>>> Supun >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> Thank you >>>>>>>> Supun Nakandala >>>>>>>> Dept. Computer Science and Engineering >>>>>>>> University of Moratuwa >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> > --------------000305020305080300030101 Content-Type: text/plain; charset=UTF-8; x-mac-type="0"; x-mac-creator="0"; name="maven.out" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="maven.out" W0lORk9dIFNjYW5uaW5nIGZvciBwcm9qZWN0cy4uLgpbSU5GT10gICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgCltJTkZPXSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KW0lORk9dIEJ1aWxkaW5nIEFpcmF2YXRh IFVzZXIgQVBJIDAuMS1TTkFQU0hPVApbSU5GT10gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCltJTkZP XSAKW0lORk9dIC0tLSBtYXZlbi1jbGVhbi1wbHVnaW46Mi40LjE6Y2xlYW4gKGRlZmF1bHQt Y2xlYW4pIEAgdXNlcmFwaSAtLS0KW0lORk9dIERlbGV0aW5nIC9Vc2Vycy9tcGllcmNlL2Fp cmF2YXRhLXVzZXJhcGkvdXNlcmFwaS90YXJnZXQKW0lORk9dIApbSU5GT10gLS0tIG1hdmVu LXJlc291cmNlcy1wbHVnaW46Mi40LjM6cmVzb3VyY2VzIChkZWZhdWx0LXJlc291cmNlcykg QCB1c2VyYXBpIC0tLQpbV0FSTklOR10gVXNpbmcgcGxhdGZvcm0gZW5jb2RpbmcgKFVURi04 IGFjdHVhbGx5KSB0byBjb3B5IGZpbHRlcmVkIHJlc291cmNlcywgaS5lLiBidWlsZCBpcyBw bGF0Zm9ybSBkZXBlbmRlbnQhCltJTkZPXSBDb3B5aW5nIDYgcmVzb3VyY2VzCltJTkZPXSAK W0lORk9dIC0tLSBtYXZlbi1jb21waWxlci1wbHVnaW46Mi4zLjI6Y29tcGlsZSAoZGVmYXVs dC1jb21waWxlKSBAIHVzZXJhcGkgLS0tCltJTkZPXSBDb21waWxpbmcgMjQgc291cmNlIGZp bGVzIHRvIC9Vc2Vycy9tcGllcmNlL2FpcmF2YXRhLXVzZXJhcGkvdXNlcmFwaS90YXJnZXQv Y2xhc3NlcwpbSU5GT10gCltJTkZPXSAtLS0gbWF2ZW4tcmVzb3VyY2VzLXBsdWdpbjoyLjQu Mzp0ZXN0UmVzb3VyY2VzIChkZWZhdWx0LXRlc3RSZXNvdXJjZXMpIEAgdXNlcmFwaSAtLS0K W1dBUk5JTkddIFVzaW5nIHBsYXRmb3JtIGVuY29kaW5nIChVVEYtOCBhY3R1YWxseSkgdG8g Y29weSBmaWx0ZXJlZCByZXNvdXJjZXMsIGkuZS4gYnVpbGQgaXMgcGxhdGZvcm0gZGVwZW5k ZW50IQpbSU5GT10gc2tpcCBub24gZXhpc3RpbmcgcmVzb3VyY2VEaXJlY3RvcnkgL1VzZXJz L21waWVyY2UvYWlyYXZhdGEtdXNlcmFwaS91c2VyYXBpL3NyYy90ZXN0L3Jlc291cmNlcwpb SU5GT10gCltJTkZPXSAtLS0gbWF2ZW4tY29tcGlsZXItcGx1Z2luOjIuMy4yOnRlc3RDb21w aWxlIChkZWZhdWx0LXRlc3RDb21waWxlKSBAIHVzZXJhcGkgLS0tCltJTkZPXSBDb21waWxp bmcgMSBzb3VyY2UgZmlsZSB0byAvVXNlcnMvbXBpZXJjZS9haXJhdmF0YS11c2VyYXBpL3Vz ZXJhcGkvdGFyZ2V0L3Rlc3QtY2xhc3NlcwpbSU5GT10gCltJTkZPXSAtLS0gbWF2ZW4tc3Vy ZWZpcmUtcGx1Z2luOjIuNy4yOnRlc3QgKGRlZmF1bHQtdGVzdCkgQCB1c2VyYXBpIC0tLQpb SU5GT10gU3VyZWZpcmUgcmVwb3J0IGRpcmVjdG9yeTogL1VzZXJzL21waWVyY2UvYWlyYXZh dGEtdXNlcmFwaS91c2VyYXBpL3RhcmdldC9zdXJlZmlyZS1yZXBvcnRzCgotLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiBUIEUgUyBU IFMKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLQpSdW5uaW5nIG9yZy5hcGFjaGUuYWlyYXZhdGEudXNlcmFwaS5zZXJ2ZXIuaGFuZGxl ci5Vc2VyQVBJU2VydmVySGFuZGxlclRlc3QKbG9nNGo6V0FSTiBObyBhcHBlbmRlcnMgY291 bGQgYmUgZm91bmQgZm9yIGxvZ2dlciAob3JnLmFwYWNoZS5heGlzMi5kZXNjcmlwdGlvbi5B eGlzT3BlcmF0aW9uKS4KbG9nNGo6V0FSTiBQbGVhc2UgaW5pdGlhbGl6ZSB0aGUgbG9nNGog c3lzdGVtIHByb3Blcmx5Lgpsb2c0ajpXQVJOIFNlZSBodHRwOi8vbG9nZ2luZy5hcGFjaGUu b3JnL2xvZzRqLzEuMi9mYXEuaHRtbCNub2NvbmZpZyBmb3IgbW9yZSBpbmZvLgpBdXRob3Jp emF0aW9uRXhjZXB0aW9uKG1lc3NhZ2U6bnVsbCkKCWF0IG9yZy5hcGFjaGUuYWlyYXZhdGEu dXNlcmFwaS5zZXJ2ZXIudXRpbHMuVG9rZW5FbmNyeXB0aW9uVXRpbC5kZWNyeXB0KFRva2Vu RW5jcnlwdGlvblV0aWwuamF2YTo4MCkKCWF0IG9yZy5hcGFjaGUuYWlyYXZhdGEudXNlcmFw aS5zZXJ2ZXIuY2xpZW50cy5CYXNlU2VydmljZUNsaWVudC5hdXRoZW50aWNhdGVTdHViRnJv bVRva2VuKEJhc2VTZXJ2aWNlQ2xpZW50LmphdmE6NTApCglhdCBvcmcuYXBhY2hlLmFpcmF2 YXRhLnVzZXJhcGkuc2VydmVyLmNsaWVudHMuVXNlclN0b3JlTWFuYWdlclNlcnZpY2VDbGll bnQuYXV0aGVudGljYXRlVXNlcihVc2VyU3RvcmVNYW5hZ2VyU2VydmljZUNsaWVudC5qYXZh OjI4MCkKCWF0IG9yZy5hcGFjaGUuYWlyYXZhdGEudXNlcmFwaS5zZXJ2ZXIuaGFuZGxlci5V c2VyQVBJU2VydmVySGFuZGxlci5hdXRoZW50aWNhdGVVc2VyKFVzZXJBUElTZXJ2ZXJIYW5k bGVyLmphdmE6MTcxKQoJYXQgb3JnLmFwYWNoZS5haXJhdmF0YS51c2VyYXBpLnNlcnZlci5o YW5kbGVyLlVzZXJBUElTZXJ2ZXJIYW5kbGVyVGVzdC50ZXN0QXV0aGVudGljYXRlVXNlcihV c2VyQVBJU2VydmVySGFuZGxlclRlc3QuamF2YToxMzgpCglhdCBzdW4ucmVmbGVjdC5OYXRp dmVNZXRob2RBY2Nlc3NvckltcGwuaW52b2tlMChOYXRpdmUgTWV0aG9kKQoJYXQgc3VuLnJl ZmxlY3QuTmF0aXZlTWV0aG9kQWNjZXNzb3JJbXBsLmludm9rZShOYXRpdmVNZXRob2RBY2Nl c3NvckltcGwuamF2YTo2MikKCWF0IHN1bi5yZWZsZWN0LkRlbGVnYXRpbmdNZXRob2RBY2Nl c3NvckltcGwuaW52b2tlKERlbGVnYXRpbmdNZXRob2RBY2Nlc3NvckltcGwuamF2YTo0MykK CWF0IGphdmEubGFuZy5yZWZsZWN0Lk1ldGhvZC5pbnZva2UoTWV0aG9kLmphdmE6NDgzKQoJ YXQganVuaXQuZnJhbWV3b3JrLlRlc3RDYXNlLnJ1blRlc3QoVGVzdENhc2UuamF2YToxNTQp CglhdCBqdW5pdC5mcmFtZXdvcmsuVGVzdENhc2UucnVuQmFyZShUZXN0Q2FzZS5qYXZhOjEy NykKCWF0IGp1bml0LmZyYW1ld29yay5UZXN0UmVzdWx0JDEucHJvdGVjdChUZXN0UmVzdWx0 LmphdmE6MTA2KQoJYXQganVuaXQuZnJhbWV3b3JrLlRlc3RSZXN1bHQucnVuUHJvdGVjdGVk KFRlc3RSZXN1bHQuamF2YToxMjQpCglhdCBqdW5pdC5mcmFtZXdvcmsuVGVzdFJlc3VsdC5y dW4oVGVzdFJlc3VsdC5qYXZhOjEwOSkKCWF0IGp1bml0LmZyYW1ld29yay5UZXN0Q2FzZS5y dW4oVGVzdENhc2UuamF2YToxMTgpCglhdCBqdW5pdC5mcmFtZXdvcmsuVGVzdFN1aXRlLnJ1 blRlc3QoVGVzdFN1aXRlLmphdmE6MjA4KQoJYXQganVuaXQuZnJhbWV3b3JrLlRlc3RTdWl0 ZS5ydW4oVGVzdFN1aXRlLmphdmE6MjAzKQoJYXQgc3VuLnJlZmxlY3QuTmF0aXZlTWV0aG9k QWNjZXNzb3JJbXBsLmludm9rZTAoTmF0aXZlIE1ldGhvZCkKCWF0IHN1bi5yZWZsZWN0Lk5h dGl2ZU1ldGhvZEFjY2Vzc29ySW1wbC5pbnZva2UoTmF0aXZlTWV0aG9kQWNjZXNzb3JJbXBs LmphdmE6NjIpCglhdCBzdW4ucmVmbGVjdC5EZWxlZ2F0aW5nTWV0aG9kQWNjZXNzb3JJbXBs Lmludm9rZShEZWxlZ2F0aW5nTWV0aG9kQWNjZXNzb3JJbXBsLmphdmE6NDMpCglhdCBqYXZh LmxhbmcucmVmbGVjdC5NZXRob2QuaW52b2tlKE1ldGhvZC5qYXZhOjQ4MykKCWF0IG9yZy5h cGFjaGUubWF2ZW4uc3VyZWZpcmUuanVuaXQuSlVuaXRUZXN0U2V0LmV4ZWN1dGUoSlVuaXRU ZXN0U2V0LmphdmE6OTgpCglhdCBvcmcuYXBhY2hlLm1hdmVuLnN1cmVmaXJlLmp1bml0LkpV bml0M1Byb3ZpZGVyLmV4ZWN1dGVUZXN0U2V0KEpVbml0M1Byb3ZpZGVyLmphdmE6MTA3KQoJ YXQgb3JnLmFwYWNoZS5tYXZlbi5zdXJlZmlyZS5qdW5pdC5KVW5pdDNQcm92aWRlci5pbnZv a2UoSlVuaXQzUHJvdmlkZXIuamF2YTo4NCkKCWF0IHN1bi5yZWZsZWN0Lk5hdGl2ZU1ldGhv ZEFjY2Vzc29ySW1wbC5pbnZva2UwKE5hdGl2ZSBNZXRob2QpCglhdCBzdW4ucmVmbGVjdC5O YXRpdmVNZXRob2RBY2Nlc3NvckltcGwuaW52b2tlKE5hdGl2ZU1ldGhvZEFjY2Vzc29ySW1w bC5qYXZhOjYyKQoJYXQgc3VuLnJlZmxlY3QuRGVsZWdhdGluZ01ldGhvZEFjY2Vzc29ySW1w bC5pbnZva2UoRGVsZWdhdGluZ01ldGhvZEFjY2Vzc29ySW1wbC5qYXZhOjQzKQoJYXQgamF2 YS5sYW5nLnJlZmxlY3QuTWV0aG9kLmludm9rZShNZXRob2QuamF2YTo0ODMpCglhdCBvcmcu YXBhY2hlLm1hdmVuLnN1cmVmaXJlLmJvb3Rlci5Qcm92aWRlckZhY3RvcnkkQ2xhc3NMb2Fk ZXJQcm94eS5pbnZva2UoUHJvdmlkZXJGYWN0b3J5LmphdmE6MTAzKQoJYXQgY29tLnN1bi5w cm94eS4kUHJveHkwLmludm9rZShVbmtub3duIFNvdXJjZSkKCWF0IG9yZy5hcGFjaGUubWF2 ZW4uc3VyZWZpcmUuYm9vdGVyLlN1cmVmaXJlU3RhcnRlci5pbnZva2VQcm92aWRlcihTdXJl ZmlyZVN0YXJ0ZXIuamF2YToxNTApCglhdCBvcmcuYXBhY2hlLm1hdmVuLnN1cmVmaXJlLmJv b3Rlci5TdXJlZmlyZVN0YXJ0ZXIucnVuU3VpdGVzSW5Qcm9jZXNzKFN1cmVmaXJlU3RhcnRl ci5qYXZhOjkxKQoJYXQgb3JnLmFwYWNoZS5tYXZlbi5zdXJlZmlyZS5ib290ZXIuRm9ya2Vk Qm9vdGVyLm1haW4oRm9ya2VkQm9vdGVyLmphdmE6NjkpClRlc3RzIHJ1bjogMTIsIEZhaWx1 cmVzOiAzLCBFcnJvcnM6IDcsIFNraXBwZWQ6IDAsIFRpbWUgZWxhcHNlZDogMi45NDcgc2Vj IDw8PCBGQUlMVVJFIQoKUmVzdWx0cyA6CgpGYWlsZWQgdGVzdHM6IAogIHRlc3RVcGRhdGVV c2VyUHJvZmlsZShvcmcuYXBhY2hlLmFpcmF2YXRhLnVzZXJhcGkuc2VydmVyLmhhbmRsZXIu VXNlckFQSVNlcnZlckhhbmRsZXJUZXN0KQogIHRlc3RSZW1vdmVVc2VyKG9yZy5hcGFjaGUu YWlyYXZhdGEudXNlcmFwaS5zZXJ2ZXIuaGFuZGxlci5Vc2VyQVBJU2VydmVySGFuZGxlclRl c3QpCiAgdGVzdFVwZGF0ZVVzZXJQYXNzd29yZChvcmcuYXBhY2hlLmFpcmF2YXRhLnVzZXJh cGkuc2VydmVyLmhhbmRsZXIuVXNlckFQSVNlcnZlckhhbmRsZXJUZXN0KQoKVGVzdHMgaW4g ZXJyb3I6IAogIHRlc3RDaGVja1VzZXJuYW1lRXhpc3RzKG9yZy5hcGFjaGUuYWlyYXZhdGEu dXNlcmFwaS5zZXJ2ZXIuaGFuZGxlci5Vc2VyQVBJU2VydmVySGFuZGxlclRlc3QpCiAgdGVz dENyZWF0ZU5ld1VzZXIob3JnLmFwYWNoZS5haXJhdmF0YS51c2VyYXBpLnNlcnZlci5oYW5k bGVyLlVzZXJBUElTZXJ2ZXJIYW5kbGVyVGVzdCkKICB0ZXN0R2V0VXNlclByb2ZpbGUob3Jn LmFwYWNoZS5haXJhdmF0YS51c2VyYXBpLnNlcnZlci5oYW5kbGVyLlVzZXJBUElTZXJ2ZXJI YW5kbGVyVGVzdCkKICB0ZXN0QXV0aGVudGljYXRlVXNlcihvcmcuYXBhY2hlLmFpcmF2YXRh LnVzZXJhcGkuc2VydmVyLmhhbmRsZXIuVXNlckFQSVNlcnZlckhhbmRsZXJUZXN0KQogIHRl c3RHZXRSb2xlTmFtZXMob3JnLmFwYWNoZS5haXJhdmF0YS51c2VyYXBpLnNlcnZlci5oYW5k bGVyLlVzZXJBUElTZXJ2ZXJIYW5kbGVyVGVzdCkKICB0ZXN0Q2hlY2tQZXJtaXNzaW9uU3Ry aW5nKG9yZy5hcGFjaGUuYWlyYXZhdGEudXNlcmFwaS5zZXJ2ZXIuaGFuZGxlci5Vc2VyQVBJ U2VydmVySGFuZGxlclRlc3QpCiAgdGVzdEdldFVzZXJQZXJtaXNzaW9ucyhvcmcuYXBhY2hl LmFpcmF2YXRhLnVzZXJhcGkuc2VydmVyLmhhbmRsZXIuVXNlckFQSVNlcnZlckhhbmRsZXJU ZXN0KQoKVGVzdHMgcnVuOiAxMiwgRmFpbHVyZXM6IDMsIEVycm9yczogNywgU2tpcHBlZDog MAoKW0lORk9dIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpbSU5GT10gQlVJTEQgRkFJTFVSRQpbSU5G T10gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tCltJTkZPXSBUb3RhbCB0aW1lOiAxMy4zNzlzCltJTkZP XSBGaW5pc2hlZCBhdDogV2VkIEp1bCAzMCAxMTo1NDo1MyBFRFQgMjAxNApbSU5GT10gRmlu YWwgTWVtb3J5OiAzNU0vMTk0TQpbSU5GT10gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCltFUlJPUl0g RmFpbGVkIHRvIGV4ZWN1dGUgZ29hbCBvcmcuYXBhY2hlLm1hdmVuLnBsdWdpbnM6bWF2ZW4t c3VyZWZpcmUtcGx1Z2luOjIuNy4yOnRlc3QgKGRlZmF1bHQtdGVzdCkgb24gcHJvamVjdCB1 c2VyYXBpOiBUaGVyZSBhcmUgdGVzdCBmYWlsdXJlcy4KW0VSUk9SXSAKW0VSUk9SXSBQbGVh c2UgcmVmZXIgdG8gL1VzZXJzL21waWVyY2UvYWlyYXZhdGEtdXNlcmFwaS91c2VyYXBpL3Rh cmdldC9zdXJlZmlyZS1yZXBvcnRzIGZvciB0aGUgaW5kaXZpZHVhbCB0ZXN0IHJlc3VsdHMu CltFUlJPUl0gLT4gW0hlbHAgMV0KW0VSUk9SXSAKW0VSUk9SXSBUbyBzZWUgdGhlIGZ1bGwg c3RhY2sgdHJhY2Ugb2YgdGhlIGVycm9ycywgcmUtcnVuIE1hdmVuIHdpdGggdGhlIC1lIHN3 aXRjaC4KW0VSUk9SXSBSZS1ydW4gTWF2ZW4gdXNpbmcgdGhlIC1YIHN3aXRjaCB0byBlbmFi bGUgZnVsbCBkZWJ1ZyBsb2dnaW5nLgpbRVJST1JdIApbRVJST1JdIEZvciBtb3JlIGluZm9y bWF0aW9uIGFib3V0IHRoZSBlcnJvcnMgYW5kIHBvc3NpYmxlIHNvbHV0aW9ucywgcGxlYXNl IHJlYWQgdGhlIGZvbGxvd2luZyBhcnRpY2xlczoKW0VSUk9SXSBbSGVscCAxXSBodHRwOi8v Y3dpa2kuYXBhY2hlLm9yZy9jb25mbHVlbmNlL2Rpc3BsYXkvTUFWRU4vTW9qb0ZhaWx1cmVF eGNlcHRpb24K --------------000305020305080300030101--