コード例 #1
0
    def test_admin_keyword_for_tickets(self):

        N_TICKETS = 3

        # Create some tickets as alice.

        with self.login(self.alice) as alice:
            alice_home_path = self.irods_homedir(alice, path_only=True)
            ticket_strings = [
                Ticket(alice).issue('read', alice_home_path).string
                for _ in range(N_TICKETS)
            ]

        # As rodsadmin, use the ADMIN_KW flag to delete alice's tickets.

        with helpers.make_session() as ses:
            alices_tickets = [
                t[TicketQuery.Ticket.string]
                for t in ses.query(TicketQuery.Ticket).filter(
                    TicketQuery.Owner.name == 'alice')
            ]
            self.assertEqual(len(alices_tickets), N_TICKETS)
            for s in alices_tickets:
                Ticket(ses, s).delete(**{kw.ADMIN_KW: ''})
            alices_tickets = [
                t[TicketQuery.Ticket.string]
                for t in ses.query(TicketQuery.Ticket).filter(
                    TicketQuery.Owner.name == 'alice')
            ]
            self.assertEqual(len(alices_tickets), 0)
コード例 #2
0
def create_session(ticket: str = None):
    # if we have a ticket, create an anonymous session and apply it to it
    if ticket is not None and ticket != '':
        session = iRODSSession(host='data.cyverse.org',
                               port=1247,
                               user='******',
                               password='',
                               zone='iplant')
        Ticket(session, ticket).supply()
        return session

    # otherwise check for an iRODS environment file (if we don't have one, abort)
    try:
        env_file = os.environ.get('IRODS_ENVIRONMENT_FILE')
    except KeyError:
        default_env_file = '~/.irods/irods_environment.json'
        if isfile(default_env_file): env_file = expanduser(default_env_file)
        else:
            raise ValueError(
                f"No iRODS authentication method provided (need ticket or environment file)"
            )

    ssl_context = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH,
                                             cafile=None,
                                             capath=None,
                                             cadata=None)
    ssl_settings = {'ssl_context': ssl_context}
    return iRODSSession(irods_env_file=env_file, **ssl_settings)
コード例 #3
0
def test_file_exists(remote_base_path):
    with TemporaryDirectory() as testdir:
        file1_name = 'f1.txt'
        file2_name = 'f2.txt'
        file1_path = join(testdir, file1_name)
        remote_path = join(remote_base_path, str(uuid.uuid4()))

        try:
            # prep collection
            create_collection(remote_path, token)

            # create files
            with open(file1_path, "w") as file1:
                file1.write('Hello, 1!')

            # upload files
            upload_file(file1_path, remote_path, token)

            # create iRODS session
            session = iRODSSession(host='data.cyverse.org',
                                   port=1247,
                                   user='******',
                                   password='',
                                   zone='iplant')
            ticket = TerrainTicket.get([join(remote_path, file1_name)], uses=2)
            Ticket(session, ticket).supply()

            # test remote files exist
            assert irods_store.file_exists(join(remote_path, file1_name),
                                           session)
            assert not irods_store.file_exists(join(remote_path, file2_name),
                                               session)
        finally:
            delete_collection(remote_path, token)
コード例 #4
0
 def _ticket_write_helper(self, obj_type):
     with iRODSSession(**self.rodsuser_params) as user_sess:
         Ticket(user_sess, self.tickets[obj_type]['write']).supply()
         data = user_sess.data_objects.get(self.data_path)
         with data.open('w') as obj:
             obj.write(self.MODIFIED_DATA)
         self.assertEqual(data.open('r').read(), self.MODIFIED_DATA)
コード例 #5
0
    def setUp(self):
        """Create objects for test"""
        self.sess = helpers.make_session()
        user = self.sess.users.get(self.sess.username)
        if user.type != 'rodsadmin':
            self.skipTest('''Test runnable only by rodsadmin.''')

        admin = self.sess
        delete_my_tickets(admin)

        # Create test collection

        self.coll_path = '/{}/home/{}/ticket_test_dir'.format(
            admin.zone, admin.username)
        self.coll = helpers.make_collection(admin, self.coll_path)

        # Create anonymous test user
        self.user = admin.users.create('anonymous', 'rodsuser')
        self.rodsuser_params = {
            'host': admin.host,
            'port': admin.port,
            'user': '******',
            'password': '',
            'zone': admin.zone
        }

        # make new data object in the test collection with some initialized content

        self.INITIALIZED_DATA = b'1' * 16
        self.data_path = '{self.coll_path}/ticketed_data'.format(**locals())
        helpers.make_object(admin,
                            self.data_path,
                            content=self.INITIALIZED_DATA)

        self.MODIFIED_DATA = b'2' * 16

        # make new tickets for the various combinations

        self.tickets = {'coll': {}, 'data': {}}
        for obj_type in ('coll', 'data'):
            for access in ('read', 'write'):
                ticket = Ticket(admin)
                self.tickets[obj_type][access] = ticket.string
                ticket.issue(access, getattr(self, obj_type + '_path'))
コード例 #6
0
ファイル: data.py プロジェクト: pythseq/scelvis
def create_irods_session(url):
    """Create an iRODS session."""
    if "ssl" in url.scheme:
        ssl_settings = {
            "ssl_context": ssl.create_default_context(
                purpose=ssl.Purpose.CLIENT_AUTH, cafile=None, capath=None, cadata=None
            )
        }
    else:
        ssl_settings = {}

    if "pam" in url.scheme:
        irods_authentication_scheme = "pam"
    else:
        irods_authentication_scheme = "native"

    logger.info("Creating iRODS session")
    session = iRODSSession(
        host=url.hostname,
        port=(url.port or 1247),
        user=url.username,
        password=url.password or "",
        zone=(url.path or "/").split("/")[1],
        irods_authentication_scheme=irods_authentication_scheme,
        irods_client_server_negotiation=settings.IRODS_CLIENT_SERVER_NEGOTIATION,
        irods_client_server_policy=settings.IRODS_CLIENT_SERVER_POLICY,
        irods_ssl_verify_server=settings.IRODS_SSL_VERIFY_SERVER,
        irods_encryption_algorithm=settings.IRODS_ENCRYPTION_ALGORITHM,
        irods_encryption_key_size=settings.IRODS_ENCRYPTION_KEY_SIZE,
        irods_encryption_num_hash_rounds=settings.IRODS_ENCRYPTION_NUM_HASH_ROUNDS,
        irods_encryption_salt_size=settings.IRODS_ENCRYPTION_SALT_SIZE,
        **ssl_settings
    )
    query = parse_qs(url.query)
    if "ticket" in query:
        logger.info("Setting ticket for session")
        ticket = Ticket(session, query["ticket"][0])
        ticket.supply()
    return session
コード例 #7
0
 def _ticket_read_helper(self, obj_type, download=False):
     with iRODSSession(**self.rodsuser_params) as user_sess:
         temp_file = []
         if download: temp_file += [tempfile.mktemp()]
         try:
             Ticket(user_sess, self.tickets[obj_type]['read']).supply()
             data = user_sess.data_objects.get(self.data_path, *temp_file)
             self.assertEqual(data.open('r').read(), self.INITIALIZED_DATA)
             if temp_file:
                 with open(temp_file[0], 'rb') as local_file:
                     self.assertEqual(local_file.read(),
                                      self.INITIALIZED_DATA)
         finally:
             if temp_file and os.path.exists(temp_file[0]):
                 os.unlink(temp_file[0])
コード例 #8
0
def test_upload_directory(remote_base_path):
    with TemporaryDirectory() as testdir:
        file1_name = 'f1.txt'
        file2_name = 'f2.txt'
        file1_path = join(testdir, file1_name)
        file2_path = join(testdir, file2_name)
        coll_name = str(uuid.uuid4())
        remote_path = join(remote_base_path, coll_name)

        try:
            # prep collection
            create_collection(remote_path, token)

            # create files
            with open(file1_path, "w") as file1, open(file2_path,
                                                      "w") as file2:
                file1.write('Hello, 1!')
                file2.write('Hello, 2!')

            # create iRODS session and get ticket
            with iRODSSession(host='data.cyverse.org',
                              port=1247,
                              user='******',
                              password='',
                              zone='iplant') as session:
                ticket = TerrainTicket.get([
                    join(remote_path, file1_name),
                    join(remote_path, file2_name)
                ], 'write', False)
                Ticket(session, ticket).supply()

                # upload files
                irods_store.push_dir(testdir,
                                     remote_path,
                                     session=session,
                                     include_patterns=['.txt'])

                # check uploads
                coll = session.query(Collection).one()
                collection = iRODSCollection(session.collections, coll)
                file_names = [o.name for o in collection.data_objects]
                print(file_names)
                assert file1_name in file_names
                assert file2_name in file_names
        finally:
            delete_collection(remote_path, token)
コード例 #9
0
def test_download_directory(remote_base_path):
    with TemporaryDirectory() as testdir:
        file1_name = 'f1.txt'
        file2_name = 'f2.txt'
        file1_path = join(testdir, file1_name)
        file2_path = join(testdir, file2_name)
        remote_path = join(remote_base_path, str(uuid.uuid4()))

        try:
            # prep collection
            create_collection(remote_path, token)

            # create files
            with open(file1_path, "w") as file1, open(file2_path,
                                                      "w") as file2:
                file1.write('Hello, 1!')
                file2.write('Hello, 2!')

            # upload files
            upload_file(file1_path, remote_path, token)
            upload_file(file2_path, remote_path, token)

            # remove local files
            os.remove(file1_path)
            os.remove(file2_path)

            # create iRODS session and get ticket
            with iRODSSession(host='data.cyverse.org',
                              port=1247,
                              user='******',
                              password='',
                              zone='iplant') as session:
                ticket = TerrainTicket.get([remote_path], 'write', False)
                Ticket(session, ticket).supply()

                # download files
                irods_store.pull_dir(remote_path,
                                     testdir,
                                     session=session,
                                     patterns=['.txt'])

            # check downloads
            assert isfile(file1_path)
            assert isfile(file2_path)
        finally:
            delete_collection(remote_path, token)
コード例 #10
0
def test_directory_exists(remote_base_path):
    remote_path = join(remote_base_path, str(uuid.uuid4()))

    with TemporaryDirectory() as testdir:
        try:
            # prep collection
            create_collection(remote_path, token)

            # create iRODS session
            session = iRODSSession(host='data.cyverse.org',
                                   port=1247,
                                   user='******',
                                   password='',
                                   zone='iplant')
            ticket = TerrainTicket.get([remote_path])
            Ticket(session, ticket).supply()

            # test remote directories exist
            assert irods_store.dir_exists(remote_path, session)
            assert not irods_store.dir_exists(
                join(remote_base_path, "not_a_collection"), session)
        finally:
            delete_collection(remote_path, token)
コード例 #11
0
def test_download_file(remote_base_path):
    with TemporaryDirectory() as testdir:
        file_name = 'f1.txt'
        file_path = join(testdir, file_name)
        remote_path = join(remote_base_path, str(uuid.uuid4()))
        local_path = join(testdir, f"d{file_name}")

        try:
            # prep collection
            create_collection(remote_path, token)

            # create files
            with open(file_path, "w") as file:
                file.write('Hello, 1!')

            # upload files
            upload_file(file_path, remote_path, token)

            # create iRODS session and get ticket
            with iRODSSession(host='data.cyverse.org',
                              port=1247,
                              user='******',
                              password='',
                              zone='iplant') as session:
                ticket = TerrainTicket.get([remote_path], 'write', False)
                Ticket(session, ticket).supply()

                # download file
                irods_store.pull_file(join(remote_path, file_name),
                                      local_path,
                                      session=session)

            # check download
            assert isfile(local_path)
        finally:
            delete_collection(remote_path, token)
コード例 #12
0
    def test_object_read_and_write_tickets(self):
        if self.alice is None or self.bob is None:
            self.skipTest(
                "A rodsuser (alice and/or bob) could not be created.")
        t = None
        data_objs = []
        tmpfiles = []
        try:
            # Create ticket for read access to alice's home collection.
            alice = self.login(self.alice)
            home = self.irods_homedir(alice)

            # Create 'R' and 'W' in alice's home collection.
            data_objs = [
                helpers.make_object(alice,
                                    home.path + "/" + name,
                                    content='abcxyz') for name in ('R', 'W')
            ]
            tickets = {
                'R': Ticket(alice).issue('read', home.path + "/R").string,
                'W': Ticket(alice).issue('write', home.path + "/W").string
            }
            # Test only write ticket allows upload.
            with self.login(self.bob) as bob:
                rw_names = {}
                for name in ('R', 'W'):
                    Ticket(bob, tickets[name]).supply()
                    with tempfile.NamedTemporaryFile(delete=False) as tmpf:
                        tmpfiles += [tmpf]
                        rw_names[name] = tmpf.name
                        tmpf.write(b'hello')
                    if name == 'W':
                        bob.data_objects.put(tmpf.name, home.path + "/" + name)
                    else:
                        try:
                            bob.data_objects.put(tmpf.name,
                                                 home.path + "/" + name)
                        except ex.CAT_NO_ACCESS_PERMISSION:
                            pass
                        else:
                            raise AssertionError(
                                "A read ticket allowed a data object write operation to happen without error."
                            )

            # Test upload was successful, by getting and confirming contents.

            with self.login(
                    self.bob
            ) as bob:  # This check must be in a new session or we get CollectionDoesNotExist. - Possibly a new issue [ ]
                for name in ('R', 'W'):
                    Ticket(bob, tickets[name]).supply()
                    bob.data_objects.get(home.path + "/" + name,
                                         rw_names[name],
                                         **{kw.FORCE_FLAG_KW: ''})
                    with open(rw_names[name], 'r') as tmpread:
                        self.assertEqual(tmpread.read(),
                                         'abcxyz' if name == 'R' else 'hello')
        finally:
            if t: t.delete()
            for d in data_objs:
                d.unlink(force=True)
            for file_ in tmpfiles:
                os.unlink(file_.name)
            alice.cleanup()
コード例 #13
0
def delete_my_tickets(session):
    my_userid = session.users.get(session.username).id
    my_tickets = session.query(
        TicketQuery.Ticket).filter(TicketQuery.Ticket.user_id == my_userid)
    for res in my_tickets:
        Ticket(session, result=res).delete()
コード例 #14
0
    def test_coll_read_ticket_between_rodsusers(self):
        t = None
        data_objs = []
        tmpfiles = []
        try:
            # Create ticket for read access to alice's home collection.
            alice = self.login(self.alice)
            tc = Ticket(alice)
            home = self.irods_homedir(alice)
            tc.issue('read', home.path)

            # Create 'x' and 'y' in alice's home collection
            data_objs = [
                helpers.make_object(alice,
                                    home.path + "/" + name,
                                    content='abcxyz') for name in ('x', 'y')
            ]

            with self.login(self.bob) as bob:
                ts = Ticket(bob, tc.string)
                ts.supply()
                # Check collection access ticket allows bob to list both subobjects
                self.assertEqual(len(self.list_objects(bob)), 2)
                # and that we can get (and read) them properly.
                for name in ('x', 'y'):
                    with tempfile.NamedTemporaryFile(delete=False) as tmpf:
                        tmpfiles += [tmpf]
                    bob.data_objects.get(home.path + "/" + name, tmpf.name,
                                         **{kw.FORCE_FLAG_KW: ''})
                    with open(tmpf.name, 'r') as tmpread:
                        self.assertEqual(tmpread.read(), 'abcxyz')

            td = Ticket(alice)
            td.issue('read', home.path + "/x")

            with self.login(self.bob) as bob:
                ts = Ticket(bob, td.string)
                ts.supply()

                # Check data access ticket allows bob to list only one data object
                self.assertEqual(len(self.list_objects(bob)), 1)

                # ... and fetch that object (verifying content)
                with tempfile.NamedTemporaryFile(delete=False) as tmpf:
                    tmpfiles += [tmpf]
                bob.data_objects.get(home.path + "/x", tmpf.name,
                                     **{kw.FORCE_FLAG_KW: ''})
                with open(tmpf.name, 'r') as tmpread:
                    self.assertEqual(tmpread.read(), 'abcxyz')

                # ... but not fetch the other data object owned by alice.
                with self.assertRaises(ex.DataObjectDoesNotExist):
                    bob.data_objects.get(home.path + "/y")
        finally:
            if t: t.delete()
            for d in data_objs:
                d.unlink(force=True)
            for file_ in tmpfiles:
                os.unlink(file_.name)
            alice.cleanup()
コード例 #15
0
 def ticket(self, path):
     ticket = Ticket(self.prc)
     # print("TEST", self.prc, path)
     ticket.issue('read', path)
     return ticket
コード例 #16
0
 def ticket_supply(self, code):
     # use ticket for access
     ticket = Ticket(self.prc, code)
     ticket.supply()
コード例 #17
0
    def test_ticket_expiry(self):
        with helpers.make_session() as ses:
            t1 = t2 = dobj = None
            try:
                gm_now = time.gmtime()
                gm_later = time.gmtime(calendar.timegm(gm_now) + 10)
                home = self.irods_homedir(ses)
                dobj = helpers.make_object(ses,
                                           home.path + '/dummy',
                                           content='abcxyz')

                later_ts = gmtime_to_timestamp(gm_later)
                later_epoch = calendar.timegm(gm_later)

                t1 = Ticket(ses)
                t2 = Ticket(ses)

                tickets = [
                    _.issue('read', dobj.path).string for _ in (
                        t1,
                        t2,
                    )
                ]
                t1.modify(
                    'expire', later_ts
                )  # - Specify expiry with the human readable timestamp.
                t2.modify('expire', later_epoch
                          )  # - Specify expiry formatted as epoch seconds.

                # Check normal access succeeds prior to expiration
                for ticket_string in tickets:
                    with self.login(self.alice) as alice:
                        Ticket(alice, ticket_string).supply()
                        alice.data_objects.get(dobj.path)

                # Check that both time formats have effected the same expiry time (The catalog returns epoch secs.)
                timestamps = []
                for ticket_string in tickets:
                    t = ses.query(TicketQuery.Ticket).filter(
                        TicketQuery.Ticket.string == ticket_string).one()
                    timestamps.append(t[TicketQuery.Ticket.expiry_ts])
                self.assertEqual(len(timestamps), 2)
                self.assertEqual(timestamps[0], timestamps[1])

                # Wait for tickets to expire.
                epoch = int(time.time())
                while epoch <= later_epoch:
                    time.sleep(later_epoch - epoch + 1)
                    epoch = int(time.time())

                Expected_Exception = ex.CAT_TICKET_EXPIRED if ses.server_version >= (4,2,9) \
                        else ex.SYS_FILE_DESC_OUT_OF_RANGE

                # Check tickets no longer allow access.
                for ticket_string in tickets:
                    with self.login(
                            self.alice) as alice, tempfile.NamedTemporaryFile(
                            ) as f:
                        Ticket(alice, ticket_string).supply()
                        with self.assertRaises(Expected_Exception):
                            alice.data_objects.get(dobj.path, f.name,
                                                   **{kw.FORCE_FLAG_KW: ''})

            finally:
                if t1: t1.delete()
                if t2: t2.delete()
                if dobj: dobj.unlink(force=True)