Пример #1
0
def ssl_storages_from_arguments(connection, args):
    """Helper function to build list of storages from cli arguments"""

    identities = []

    for storage in args.storage:
        if storage in (CLIENT_ANONYMOUS, CLIENT_STANDART):
            identities.append(IDENTITY_MAPPING[storage])
        else:
            raise SAPCliError(f'Unknown storage: {storage}')

    for identity in args.identity:
        try:
            identities.append(Identity(*identity.split('/')))
        except (ValueError, TypeError):
            # pylint: disable=raise-missing-from
            raise SAPCliError(f'Invalid identity format: {identity}')

    ssl_storages = []
    for identity in identities:
        ssl_storage = SSLCertStorage(connection, identity.pse_context,
                                     identity.pse_applic)
        ssl_storages.append(ssl_storage)

    return ssl_storages
Пример #2
0
    def lock(self):
        """Locks the object"""

        if self._lock is not None:
            raise SAPCliError(f'Object {self.uri}: already locked')

        resp = self._connection.execute(
            'POST',
            self.uri,
            params=lock_params(LOCK_ACCESS_MODE_MODIFY),
            headers={
                'X-sap-adt-sessiontype':
                'stateful',
                'Accept':
                ', '.join([
                    'application/vnd.sap.as+xml;charset=UTF-8;dataname=com.sap.adt.lock.result;q=0.8',
                    'application/vnd.sap.as+xml;charset=UTF-8;dataname=com.sap.adt.lock.result2;q=0.9'
                ])
            })

        if 'dataname=com.sap.adt.lock.Result' not in resp.headers[
                'Content-Type']:
            raise SAPCliError(
                f'Object {self.uri}: lock response does not have lock result\n'
                + resp.text)

        mod_log().debug(resp.text)

        # TODO: check encoding
        self._lock = re.match('.*<LOCK_HANDLE>(.*)</LOCK_HANDLE>.*',
                              resp.text)[1]
        mod_log().debug('LockHandle=%s', self._lock)
Пример #3
0
def mimetype_to_version(mime):
    """Converts Object MIME type to a version string"""

    if not mime.startswith('application/vnd.sap.'):
        return None

    smcln = mime.rfind(';')
    if smcln != -1:
        ver = mime[smcln + 1:]
        if ver.startswith('version='):
            return ver.split('=')[1]

    plus = mime.rfind('+')
    if plus == -1:
        raise SAPCliError('not a version + xml mime: ' + mime)

    dot = mime.rfind('.', 0, plus)
    if dot == -1:
        raise SAPCliError('not a version + xml mime: ' + mime)

    ver = mime[dot + 2:plus]
    if ver.isdigit():
        return ver

    return '0'
Пример #4
0
def run(connection, args):
    """Prints it out based on command line configuration.

       Exceptions:
         - SAPCliError:
           - when the given type does not belong to the type white list
    """

    types = {'program': sap.adt.Program, 'class': sap.adt.Class, 'package': sap.adt.Package}
    try:
        typ = types[args.type]
    except KeyError:
        raise SAPCliError(f'Unknown type: {args.type}')

    aunit = sap.adt.AUnit(connection)
    obj = typ(connection, args.name)
    response = aunit.execute(obj)
    run_results = sap.adt.aunit.parse_run_results(response.text)

    if args.output == 'human':
        return print_results_to_stream(run_results, sys.stdout)

    if args.output == 'raw':
        return print_raw(response.text, run_results)

    if args.output == 'junit4':
        return print_junit4(run_results, args, sys.stdout)

    raise SAPCliError(f'Unsupported output type: {args.output}')
Пример #5
0
def putcertificate(connection, args):
    """Uploads X.509 Base64 certificates into SAP to enable SSL peer verification
       of remote servers

        Exceptions:
            - SAPCliError:
                - when the given storage does not belong to the storage white list
                - when identity argument has invalid format
    """

    identities = []

    for storage in args.storage:
        if storage in (CLIENT_ANONYMOUS, CLIENT_STANDART):
            identities.append(IDENTITY_MAPPING[storage])
        else:
            raise SAPCliError(f'Unknown storage: {storage}')

    for identity in args.identity:
        try:
            identities.append(Identity(*identity.split('/')))
        except (ValueError, TypeError):
            # pylint: disable=raise-missing-from
            raise SAPCliError('Invalid identity format')

    ssl_storages = []
    for identity in identities:
        ssl_storage = SSLCertStorage(connection, identity.pse_context, identity.pse_applic)

        if not ssl_storage.exists():
            ssl_storage.create(
                alg=args.algorithm,
                keylen=args.key_length,
                dn=args.dn
            )

        logging.debug('SSL Storage is OK: %s', ssl_storage)
        ssl_storages.append(ssl_storage)

    for file_path in args.paths:
        logging.info('Processing the file: %s', file_path)
        with open(file_path, 'rb') as cert_file:
            cert_contents = cert_file.read()
            for ssl_storage in ssl_storages:
                logging.info('Adding the file: %s to %s', file_path, ssl_storage)
                logging.info(ssl_storage.put_certificate(cert_contents))

    logging.info('Notifying ICM ... ')
    notify_icm_changed_pse(connection)

    for updated_storage in ssl_storages:
        logging.info('Certificates of %s:', str(updated_storage))

        for cert in iter_storage_certificates(updated_storage):
            logging.info('* %s', cert['EV_SUBJECT'])
Пример #6
0
def run(connection, args):
    """Prints it out based on command line configuration.

       Exceptions:
         - SAPCliError:
           - when the given type does not belong to the type white list
    """

    types = {
        'program': sap.adt.Program,
        'class': sap.adt.Class,
        'package': sap.adt.Package,
        'transport': TransportObjectSelector
    }

    try:
        typ = types[args.type]
    except KeyError:
        raise SAPCliError(f'Unknown type: {args.type}')

    obj = typ(connection, args.name)
    sets = sap.adt.objects.ADTObjectSets()

    if args.type == 'transport':
        testable = obj.get_testable_objects(args.as4user)

        if not testable:
            sap.cli.core.printerr('No testable objects found')
            return 1

        for tr_obj in testable:
            sets.include_object(tr_obj)
    else:
        sets.include_object(obj)

    aunit = sap.adt.AUnit(connection)
    response = aunit.execute(sets)
    run_results = sap.adt.aunit.parse_run_results(response.text)

    if args.output == 'human':
        return print_results_to_stream(run_results, sys.stdout)

    if args.output == 'raw':
        return print_raw(response.text, run_results)

    if args.output == 'junit4':
        return print_junit4(run_results, args, sys.stdout)

    if args.output == 'sonar':
        return print_sonar(run_results, args, sys.stdout)

    raise SAPCliError(f'Unsupported output type: {args.output}')
Пример #7
0
def print_acoverage_output(args, acoverage_response, root_node,
                           statement_responses):
    """Prints ACoverage output in selected format and console"""

    if args.coverage_output not in ('raw', 'human', 'jacoco'):
        raise SAPCliError(f'Unsupported output type: {args.coverage_output}')

    coverage_file = None
    if args.coverage_filepath:
        # pylint: disable=consider-using-with
        coverage_file = open(args.coverage_filepath, 'w+', encoding='utf8')
        console = sap.cli.core.PrintConsole(out_file=coverage_file,
                                            err_file=coverage_file)
    else:
        console = sap.cli.core.get_console()

    if args.coverage_output == 'raw':
        print_acoverage_raw(acoverage_response.text, console)
    elif args.coverage_output == 'human':
        print_acoverage_human(root_node, console)
    elif args.coverage_output == 'jacoco':
        print_acoverage_jacoco(root_node, statement_responses, args, console)

    if coverage_file is not None:
        coverage_file.close()
Пример #8
0
def iso_code_to_sap_code(iso_code: str) -> str:
    """Coverts ISO codes to one letter SAP language codes"""

    try:
        return next((entry[1] for entry in CODE_LIST if entry[0] == iso_code))
    except StopIteration:
        raise SAPCliError(f'Not found ISO Code: {iso_code}')
Пример #9
0
def run(connection, args):
    """Prints it out based on command line configuration.

       Exceptions:
         - SAPCliError:
           - when the given type does not belong to the type white list
    """

    types = {'program': sap.adt.Program, 'class': sap.adt.Class, 'package': sap.adt.Package}
    try:
        typ = types[args.type]
    except KeyError:
        raise SAPCliError(f'Unknown type: {args.type}')

    objects = sap.adt.objects.ADTObjectSets()
    objects.include_object(typ(connection, args.name))

    if args.variant is None:
        settings = sap.adt.atc.fetch_customizing(connection)
        args.variant = settings.system_check_variant

    mod_log().info('Variant: %s', args.variant)

    checks = sap.adt.atc.ChecksRunner(connection, args.variant)
    results = checks.run_for(objects, max_verdicts=args.max_verdicts)

    return print_worklist_to_stream(results.worklist, sys.stdout, error_level=args.error_level)
Пример #10
0
    def get_testable_objects(self, user=None):
        """Returns the list of all objects which can potentially have Unit tests
           and are included in the give transport.
        """

        types = {
            'PROG': sap.adt.Program,
            'CLAS': sap.adt.Class,
            'FUGR': sap.adt.FunctionGroup
        }

        mod_log().info('Fetching the transport or task %s', self._number)
        workbench = sap.adt.cts.Workbench(self._connection)
        transport = workbench.fetch_transport_request(self._number, user=user)

        if transport is None:
            raise SAPCliError(f'The transport was not found: {self._number}')

        result = []
        for task in transport.tasks:
            for abap_object in task.objects:
                mod_log().debug('? %s %s', abap_object.type, abap_object.name)

                try:
                    # TODO: get rid of the need to create the instances!
                    result.append(types[abap_object.type](self._connection,
                                                          abap_object.name))
                    mod_log().info('+ %s %s', abap_object.type,
                                   abap_object.name)
                except KeyError:
                    pass

        return result
Пример #11
0
def release(connection, args):
    """Releases the CTS request of the passed type and number."""

    try:
        factory = {
            'transport': partial(WorkbenchTransport, None),
            'task': partial(WorkbenchTask, None, None)
        }[args.type]
    except KeyError as ex:
        raise SAPCliError(
            f'Internal error: unknown request type: {args.type}') from ex
    else:
        request = factory(connection, args.number)

        if args.recursive:
            sap.cli.core.printout(
                f'Fetching details of {args.number} because of recursive execution'
            )
            request.fetch()

        sap.cli.core.printout(f'Releasing {args.number}')
        report = request.release(recursive=args.recursive)
        sap.cli.core.printout(str(report))

    return 0
Пример #12
0
    def get_declaration(self, handler):
        """Returns the command declaration for the handler"""

        try:
            return self.declarations[handler.__name__]
        except KeyError as ex:
            raise SAPCliError(
                f'No such Command Declaration: {handler.__name__}') from ex
Пример #13
0
    def get_uri_for_type(self, mimetype):
        """Mimic ADTObjectType's implementation"""

        if mimetype != 'text/plain':
            raise SAPCliError(
                f'Class Source code can be only of "text/plain": {mimetype}')

        return self.source_uri
Пример #14
0
    def get_uri_for_type(self, mimetype):
        """Returns and an ADT URL fragment for the given MIME type.
        """

        try:
            return '/' + self._typeuris[mimetype]
        except KeyError:
            raise SAPCliError(
                'Object {type} does not support plain \'text\' format')
Пример #15
0
    def open_editor(self, instance, lock_handle, corrnr=None):
        """Returns a new instance of Editor for this object type
           and raises SAPCliError if the object type does not allow modifications.
        """

        if self._editor_factory is None:
            raise SAPCliError(
                f'Object {self._code}: modifications are not supported')

        return self._editor_factory(instance, lock_handle, corrnr=corrnr)
Пример #16
0
def sap_code_to_iso_code(sap_code: str) -> str:
    """Coverts one letter SAP language codes to ISO codes.

       Raises sap.errors.SAPCliError if the give sap_code is not identified.
    """

    try:
        return next((entry[0] for entry in CODE_LIST if entry[1] == sap_code))
    except StopIteration:
        raise SAPCliError(f'Not found SAP Language Code: {sap_code}')
Пример #17
0
def release(connection, args):
    """Releases the CTS request of the passed type and number."""

    try:
        factory = {'transport': partial(WorkbenchTransport, None),
                   'task': partial(WorkbenchTask, None, None)}[args.type]
    except KeyError:
        raise SAPCliError(f'Internal error: unknown request type: {args.type}')
    else:
        request = factory(connection, args.number)
        request.release()
Пример #18
0
    def add_command(self, handler, name=None):
        """Adds a new command"""

        fname = handler.__name__

        if fname in self.declarations:
            raise SAPCliError(f'Handler already registered: {fname}')

        cmd = CommandDeclaration(handler, name if name is not None else fname)
        self.declarations[fname] = cmd

        return cmd
Пример #19
0
    def unlock(self):
        """Locks the object"""

        if self._lock is None:
            raise SAPCliError(f'Object {self.uri}: not locked')

        self._connection.execute('POST',
                                 self.uri,
                                 params=unlock_params(self._lock),
                                 headers={
                                     'X-sap-adt-sessiontype': 'stateful',
                                 })

        self._lock = None
Пример #20
0
def find_mime_version(connection, objtype):
    """Returns the supported/required MIME version of the given objtype by
       the given connection.
    """

    mimes = connection.get_collection_types(objtype.basepath, objtype.mimetype)

    seri_mime = next((mime for mime in mimes if mime in objtype.all_mimetypes),
                     None)
    if seri_mime is None:
        raise SAPCliError('Not supported mimes: {} not in {}'.format(
            ';'.join(mimes), ';'.join(objtype.all_mimetypes)))

    version = mimetype_to_version(seri_mime)
    return (seri_mime, version)
Пример #21
0
    def serialize(self):
        """Creates a text representation"""

        mimes = self._connection.get_collection_types(self.objtype.basepath,
                                                      self.objtype.mimetype)

        seri_mime = next(
            (mime for mime in mimes if mime in self.objtype.all_mimetypes),
            None)
        if seri_mime is None:
            raise SAPCliError('Not supported mimes: {} not in {}'.format(
                ';'.join(mimes), ';'.join(self.objtype.all_mimetypes)))

        version = mimetype_to_version(seri_mime)
        marshal = sap.adt.marshalling.Marshal(object_schema_version=version)
        return (marshal.serialize(self), seri_mime)
Пример #22
0
def print_acoverage_output(args, acoverage_response, root_node, statement_responses):
    """Prints ACoverage output in selected format and stream"""

    if args.coverage_output not in ('raw', 'human', 'jacoco'):
        raise SAPCliError(f'Unsupported output type: {args.coverage_output}')

    stream = open(args.coverage_filepath, 'w+') if args.coverage_filepath else sys.stdout

    if args.coverage_output == 'raw':
        print_acoverage_raw(acoverage_response.text, stream)
    elif args.coverage_output == 'human':
        print_acoverage_human(root_node, stream)
    elif args.coverage_output == 'jacoco':
        print_acoverage_jacoco(root_node, statement_responses, args, stream)

    if args.coverage_filepath:
        stream.close()
Пример #23
0
    def activate(self):
        """Activate the object"""

        # pylint: disable=no-member
        request = f'''<?xml version="1.0" encoding="UTF-8"?>
<adtcore:objectReferences xmlns:adtcore="http://www.sap.com/adt/core">
<adtcore:objectReference adtcore:uri="/{self.connection.uri}/{self.uri}" adtcore:name="{self.name.upper()}"/>
</adtcore:objectReferences>'''

        resp = self._connection.execute('POST',
                                        'activation',
                                        params=activation_params(),
                                        headers={
                                            'Accept': 'application/xml',
                                            'Content-Type': 'application/xml'
                                        },
                                        body=request)

        if resp.text:
            raise SAPCliError(
                f'Could not activate the object {self.name}: {resp.text}')
Пример #24
0
def listcertificates(connection, args):
    """Lists X.509 Base64 certificates currently installed in SAP system

        Exceptions:
            - SAPCliError:
                - when the given storage does not belong to the storage white list
                - when identity argument has invalid format
    """

    ssl_storages = ssl_storages_from_arguments(connection, args)

    for ssl_storage in ssl_storages:

        if not ssl_storage.exists():
            raise SAPCliError(
                f'Storage for identity {ssl_storage.identity} does not exist')

        for cert in ssl_storage.get_certificates():

            cert = ssl_storage.parse_certificate(cert)
            printout('*', cert['EV_SUBJECT'])
Пример #25
0
def print_aunit_output(args, aunit_response, aunit_parsed_response):
    """Prints AUnit output in selected format and stream"""

    result = None

    run_results = aunit_parsed_response.run_results

    if args.output == 'human':
        result = print_aunit_human(run_results, sys.stdout)

    elif args.output == 'raw':
        result = print_aunit_raw(aunit_response.text, run_results, sys.stdout)

    elif args.output == 'junit4':
        result = print_aunit_junit4(run_results, args, sys.stdout)

    elif args.output == 'sonar':
        result = print_aunit_sonar(run_results, args, sys.stdout)
    else:
        raise SAPCliError(f'Unsupported output type: {args.output}')

    return result
Пример #26
0
def create(connection, args):
    """Create CTS request"""

    try:
        factory = {
            'transport': partial(WorkbenchTransport, None),
            'task': partial(WorkbenchTask, None, None)
        }[args.type]
    except KeyError as ex:
        raise SAPCliError(
            f'Internal error: unknown request type: {args.type}') from ex
    else:
        request = factory(connection,
                          None,
                          owner=connection.user,
                          description=args.description,
                          target=args.target)

        response = request.create()
        sap.cli.core.printout(response.number)

    return 0
Пример #27
0
    def _buid_group(self, group, catalogs):
        get_logger().info('Creating group: %s', group['title'])

        self._service.create_group({
            'id': group['id'],
            'title': group['title']
        })

        for tile in group['tiles']:
            get_logger().info('Adding tile: %s', tile['title'])

            try:
                catalog_tile = _get_catalog_tile(catalogs, tile['catalog_id'],
                                                 tile['catalog_tile_id'])
            except CatalogTileError as ex:
                raise SAPCliError(
                    f"Failed to add tile {tile['title']} to group {group['title']}"
                ) from ex

            self._service.add_tile_to_group(
                group_id=group['id'],
                catalog_id=tile['catalog_id'],
                tile_id=catalog_tile['instance_id'])
Пример #28
0
def activate(adt_object):
    """Activates the given object"""

    request = ADTObjectReferences()
    request.add_object(adt_object)

    resp = _send_activate(adt_object, request,
                          activation_params(pre_audit_requested=True))

    if 'application/vnd.sap.adt.inactivectsobjects.v1+xml' in resp.headers.get(
            'Content-Type', ''):
        ioc = Marshal.deserialize(resp.text, IOCList())
        get_logger().debug(ioc.entries)
        request = ADTObjectReferences([
            entry.object.reference for entry in ioc.entries
            if entry.object is not None and entry.object.deleted == 'false'
        ])
        resp = _send_activate(adt_object, request,
                              activation_params(pre_audit_requested=False))

    if resp.text:
        raise SAPCliError(
            f'Could not activate the object {adt_object.name}: {resp.text}')
Пример #29
0
    def find_service(self, service_name=None, service_version=None):
        """Returns a first service matching the given parameters.

           If any parameter is None, the parameter is not considered for
           comparison.
        """

        if service_name and service_version:
            return next((item for item in self.services
                         if item.definition.name == service_name
                         and item.version == service_version), None)

        if service_name is not None:
            return next((item for item in self.services
                         if item.definition.name == service_name), None)

        if service_version is not None:
            return next(
                (item
                 for item in self.services if item.version == service_version),
                None)

        raise SAPCliError(
            "You must specify either Service Name or Service Version or both")
Пример #30
0
def dumpcertificates(connection, args):
    """Dumps X.509 Base64 certificates currently installed in SAP system

        Exceptions:
            - SAPCliError:
                - when the given storage does not belong to the storage white list
                - when identity argument has invalid format
    """

    ssl_storages = ssl_storages_from_arguments(connection, args)

    for ssl_storage in ssl_storages:

        if not ssl_storage.exists():
            raise SAPCliError(
                f'Storage for identity {ssl_storage.identity} does not exist')

        for cert in ssl_storage.get_certificates():

            c_b64 = base64.b64encode(cert)

            printout('-----BEGIN CERTIFICATE-----')
            printout(c_b64.decode('ascii'))
            printout('-----END CERTIFICATE-----')