def invoke(self, service_id, operation_id, input_value, ctx): """ Invoke an API request :type service_id: :class:`str` :param service_id: Service identifier :type operation_id: :class:`str` :param operation_id: Operation identifier :type input_value: :class:`vmware.vapi.data.value.StructValue` :param input_value: Method input parameters :type ctx: :class:`vmware.vapi.core.ExecutionContext` :param ctx: Execution context for this method :rtype: :class:`vmware.vapi.core.MethodResult` :return: Result of the method invocation """ sec_ctx = ctx.security_context app_ctx = ctx.application_context authn_result = None request_scheme = sec_ctx.get(SCHEME_ID) if (self._authn_handlers and request_scheme and request_scheme != NO_AUTH): for handler in self._authn_handlers: # Call authenticate method and get the UserIdentity try: authn_result = handler.authenticate(sec_ctx) except Exception as e: logger.exception( 'Error in invoking authentication handler %s - %s', handler, e) error_value = make_error_value_from_msg_id( self._internal_server_error_def, 'vapi.security.authentication.exception', str(e)) return MethodResult(error=error_value) # authn result false means authentication failed if authn_result is False: error_value = make_error_value_from_msg_id( self._unauthenticated_error_def, 'vapi.security.authentication.invalid') return MethodResult(error=error_value) if authn_result is not None: # Matching authN handler found break if authn_result: # Add the authN identity to the security context to pass on to next # provider sec_ctx[AUTHN_IDENTITY] = authn_result ctx = ExecutionContext(app_ctx, sec_ctx) else: # No AuthN handler found pass an empty security context ctx = ExecutionContext(app_ctx, SecurityContext()) return ApiProviderFilter.invoke(self, service_id, operation_id, input_value, ctx)
def invoke(self, service_id, operation_id, input_value, ctx): logger.debug( 'Operation started: Service: %s, Operation: %s, Ctx: %s, Input: %s', service_id, operation_id, ctx, input_value) try: method_result = self._invoke_int(service_id, operation_id, input_value, ctx) if method_result.success(): method_result = augment_method_result_with_errors( service_id, operation_id, method_result, self._error_values_to_augment) except Exception as e: logger.exception("Error in invoking %s in %s - %s", service_id, operation_id, e) error_value = make_error_value_from_msg_id( self._internal_server_error_def, 'vapi.method.invoke.exception', str(e)) method_result = MethodResult(error=error_value) logger.debug( 'Operation finished: Service: %s, Operation %s, Ctx: %s, ' 'Output: %s', service_id, operation_id, ctx, method_result) return method_result
def invoke(self, service_id, operation_id, input_value, ctx): """ Invoke an API request :type service_id: :class:`str` :param service_id: Service identifier :type operation_id: :class:`str` :param operation_id: Operation identifier :type input_value: :class:`vmware.vapi.data.value.StructValue` :param input_value: Method input parameters :type ctx: :class:`vmware.vapi.core.ExecutionContext` :param ctx: Execution context for this method :rtype: :class:`vmware.vapi.core.MethodResult` :return: Result of the method invocation """ try: veto_error = self.execute( 'veto', service_id, operation_id, ctx, input_value) if veto_error is not None: return MethodResult(error=veto_error) else: self.execute('pre', service_id, operation_id, ctx, input_value) method_result = ApiProviderFilter.invoke( self, service_id, operation_id, input_value, ctx) self.execute('post', service_id, operation_id, ctx, input_value) return method_result except Exception as e: logger.exception('service: %s, operation: %s, input_value: %s', service_id, operation_id, input_value) error_value = make_error_value_from_msg_id( self._internal_server_error_def, 'vapi.method.invoke.exception', str(e)) method_result = MethodResult(error=error_value) return method_result
def _invoke_int(self, service_id, operation_id, input_value, ctx): # pylint: disable=R0911 """ Internal implementation of InvokeMethod :type service_id: :class:`str` :param service_id: Service identifier :type operation_id: :class:`str` :param operation_id: Operation identifier :type ctx: :class:`vmware.vapi.core.ExecutionContext` :param ctx: Execution context for this method :type input_value: :class:`vmware.vapi.data.value.StructValue` :param input_value: Method input parameters :rtype: :class:`vmware.vapi.core.MethodResult` :return: Result of the method invocation """ # Step 0: Verify input types if (input_value and not (input_value.type == Type.STRUCTURE)): logger.error("Invalid inputs") error_value = make_error_value_from_msg_id( self._invalid_argument_def, 'vapi.method.input.invalid') return MethodResult(error=error_value) iface_id = InterfaceIdentifier(service_id) method_id = MethodIdentifier(iface_id, operation_id) # Step 1: Get method definition iface = self._service_map.get(service_id) if not iface: logger.error('Could not find service: %s', service_id) error_value = make_error_value_from_msg_id( self._operation_not_found_def, 'vapi.method.input.invalid.interface', service_id) return MethodResult(error=error_value) method_def = iface.get_method_definition(method_id) if not method_def: logger.error("Could not find method %s", method_id.get_name()) error_value = make_error_value_from_msg_id( self._operation_not_found_def, 'vapi.method.input.invalid.method', method_id.get_name()) return MethodResult(error=error_value) input_def = method_def.get_input_definition() if not isinstance(input_def, StructDefinition): error_value = make_error_value_from_msg_id( self._internal_server_error_def, 'vapi.method.input.invalid.definition') return MethodResult(error=error_value) output_def = method_def.get_output_definition() if not isinstance(output_def, DataDefinition): error_value = make_error_value_from_msg_id( self._internal_server_error_def, 'vapi.method.output.invalid.definition') return MethodResult(error=error_value) # Step 2: Validate input with input def input_def.complete_value(input_value) messages = input_def.validate(input_value) if messages: logger.error("Input validation failed for method %s", method_id.get_name()) error_value = make_error_value_from_msgs( self._invalid_argument_def, *messages) return MethodResult(error=error_value) # Step 3: Execute method method_result = iface.invoke(ctx, method_id, input_value) # Step 4: Validate output with output def or error against errors set if method_result.success(): messages = output_def.validate(method_result.output) if messages: logger.error("Output validation failed for method %s", method_id.get_name()) error_value = make_error_value_from_msgs( self._internal_server_error_def, *messages) return MethodResult(error=error_value) else: error_value = method_result.error messages = self._validate_error(error_value, method_def) if messages: new_error_value = make_error_value_from_error_value_and_msgs( self._internal_server_error_def, error_value, *messages) return MethodResult(error=new_error_value) return method_result
def invoke(self, service_id, operation_id, input_value, ctx): """ Invoke an API request :type service_id: :class:`str` :param service_id: Service identifier :type operation_id: :class:`str` :param operation_id: Operation identifier :type input_value: :class:`vmware.vapi.data.value.StructValue` :param input_value: Method input parameters :type ctx: :class:`vmware.vapi.core.ExecutionContext` :param ctx: Execution context for this method :rtype: :class:`vmware.vapi.core.MethodResult` :return: Result of the method invocation """ sec_ctx = ctx.security_context authn_result = sec_ctx.get(AUTHN_IDENTITY) try: allowed_authn_schemes = self._allowed_schemes( service_id, operation_id) except Exception: error_value = make_error_value_from_msg_id( self._internal_server_error_def, 'vapi.security.authentication.metadata.invalid', operation_id, service_id) return MethodResult(error=error_value) if allowed_authn_schemes is None or NO_AUTH in allowed_authn_schemes: is_no_auth_allowed = True else: is_no_auth_allowed = False # No valid AuthN info received from AuthN filter for an # operation which requires authentication if (authn_result is None and not is_no_auth_allowed): error_value = make_error_value_from_msg_id( self._unauthorized_error_def, 'vapi.security.authorization.invalid') return MethodResult(error=error_value) if is_no_auth_allowed: return ApiProviderFilter.invoke(self, service_id, operation_id, input_value, ctx) else: result = None for handler in self._authz_handlers: # Call authorize method and validate authZ info try: result = handler.authorize(service_id, operation_id, sec_ctx) except Exception as e: logger.exception( 'Error in invoking authorization handler %s - %s', handler, e) error_value = make_error_value_from_msg_id( self._internal_server_error_def, 'vapi.security.authorization.exception', str(e)) return MethodResult(error=error_value) if result: return ApiProviderFilter.invoke(self, service_id, operation_id, input_value, ctx) error_value = make_error_value_from_msg_id( self._unauthorized_error_def, 'vapi.security.authorization.invalid') return MethodResult(error=error_value)