Esempio n. 1
0
        protected async Task AuthorizeAsync(IGrainCallContext grainCallContext,
                                            string accessToken, OAuth2EndpointInfo oAuth2EndpointInfo)
        {
            if (string.IsNullOrEmpty(accessToken))
            {
                throw new ArgumentNullException($"{nameof(accessToken)}");
            }

            if (oAuth2EndpointInfo == null)
            {
                throw new ArgumentNullException($"{nameof(oAuth2EndpointInfo)}");
            }

            var accessTokenValidationResult = await _accessTokenValidator.Validate(accessToken, oAuth2EndpointInfo);

            if (accessTokenValidationResult.IsValid)
            {
                IEnumerable <IAuthorizeData> grainAuthorizeData = null;
                var grainMethodAuthorizeData = grainCallContext.InterfaceMethod.GetCustomAttributes <AuthorizeAttribute>();

                if (grainCallContext.InterfaceMethod.ReflectedType != null)
                {
                    grainAuthorizeData =
                        grainCallContext.InterfaceMethod.ReflectedType.GetCustomAttributes <AuthorizeAttribute>();
                }

                await _authorizeHandler.AuthorizeAsync(accessTokenValidationResult.Claims,
                                                       grainAuthorizeData, grainMethodAuthorizeData);
            }
            else
            {
                throw new OrleansClusterUnauthorizedAccessException("Invalid Access Token.",
                                                                    new InvalidAccessTokenException(accessTokenValidationResult.InvalidValidationMessage));
            }
        }
            public GrainTags(IGrainCallContext target)
            {
                if (target.Grain != null && target.Grain is ISystemTarget == false)
                {
                    if (target.Grain.GetPrimaryKeyString() != null)
                    {
                        GrainId = target.Grain.GetPrimaryKeyString();
                    }
                    else if (target.Grain.IsPrimaryKeyBasedOnLong())
                    {
                        GrainId = target.Grain.GetPrimaryKeyLong(out var keyExt).ToString();
                        GrainId = (string.IsNullOrEmpty(keyExt) ? "" : keyExt + "/") + GrainId;
                    }
                    else
                    {
                        GrainId = target.Grain.GetPrimaryKey(out var keyExt).ToString();
                        GrainId = (string.IsNullOrEmpty(keyExt) ? "" : keyExt + "/") + GrainId;
                    }

                    // ReSharper disable once SuspiciousTypeConversion.Global
                    if (target is Grain grainTarget)
                    {
                        SiloAddress = grainTarget.RuntimeIdentity;
                    }
                }

                TargetType   = target.Grain?.GetType().FullName ?? target.InterfaceMethod?.DeclaringType?.FullName;
                TargetMethod = target.InterfaceMethod?.Name;
            }
Esempio n. 3
0
        public async Task Invoke(IGrainCallContext ctx)
        {
            //
            // NOTE: this grain demonstrates incorrect usage of grain call interceptors and should not be used
            // as an example of proper usage. Specifically, storing the context for later execution is invalid.
            //

            this.context = ctx;
            if (string.Equals(ctx.Method.Name, nameof(CallWithBadInterceptors)) && (bool)ctx.Arguments[0])
            {
                await ctx.Invoke();
            }

            if (RequestContext.Get(Key) is string value)
            {
                RequestContext.Set(Key, value + '3');
            }
            await ctx.Invoke();

            if (string.Equals(ctx.Method?.Name, nameof(CallWithBadInterceptors)) && (bool)ctx.Arguments[1])
            {
                await ctx.Invoke();
            }

            this.context = null;
        }
Esempio n. 4
0
        public bool AuthenticationChallenge(IGrainCallContext grainCallContext)
        {
            var allowAnonymousAttribute =
                grainCallContext.InterfaceMethod.GetCustomAttribute <AllowAnonymousAttribute>();

            // No authorization required.
            if (allowAnonymousAttribute != null)
            {
                return(false);
            }

            IEnumerable <IAuthorizeData> grainAuthorizeData = null;
            var grainMethodAuthorizeData = grainCallContext.InterfaceMethod.GetCustomAttributes <AuthorizeAttribute>();

            if (grainCallContext.InterfaceMethod.ReflectedType != null)
            {
                grainAuthorizeData =
                    grainCallContext.InterfaceMethod.ReflectedType.GetCustomAttributes <AuthorizeAttribute>();
            }

            // No authorization required.
            // ReSharper disable once ConvertIfStatementToReturnStatement
            if (grainAuthorizeData != null && !grainAuthorizeData.Any() && !grainMethodAuthorizeData.Any())
            {
                return(false);
            }

            return(true);
        }
Esempio n. 5
0
        private Activity StartActivity(IGrainCallContext callContext, IDictionary <string, object> requestContext)
        {
            var activity = new Activity(DiagnosticsLoggingStrings.GrainRequestIn);

            if (requestContext.TryGetValue(DiagnosticsLoggingStrings.RequestIdHeaderName, out object requestId))
            {
                activity.SetParentId((string)requestId);

                // We expect baggage to be empty by default
                // Only very advanced users will be using it in near future, we encourage them to keep baggage small (few items)

                if (requestContext.TryGetValue(DiagnosticsLoggingStrings.CorrelationContextHeaderName, out object baggage))
                {
                    KeyValuePair <string, string>[] values = (KeyValuePair <string, string>[])baggage;

                    foreach (var item in values)
                    {
                        activity.AddBaggage(item.Key, item.Value);
                    }
                }
            }

            if (_listener.IsEnabled(DiagnosticsLoggingStrings.GrainRequestInStartName))
            {
                _listener.StartActivity(activity, new { RequestContext = requestContext, CallContext = callContext });
            }
            else
            {
                // always start activity
                activity.Start();
            }

            return(activity);
        }
Esempio n. 6
0
        public async Task Invoke(IGrainCallContext context)
        {
            if (context.Method.Name == nameof(GetInputAsString))
            {
                context.Result = $"Hah! You wanted {context.Arguments[0]}, but you got me!";
                return;
            }

            await context.Invoke();
        }
Esempio n. 7
0
            public Task Invoke(IGrainCallContext context)
            {
                if (string.Equals(context.Method.Name, nameof(IGrainCallFilterTestGrain.GetRequestContext)))
                {
                    if (RequestContext.Get(GrainCallFilterTestConstants.Key) is string value)
                    {
                        RequestContext.Set(GrainCallFilterTestConstants.Key, value + '2');
                    }
                }

                return(context.Invoke());
            }
Esempio n. 8
0
        public async Task Invoke(IGrainCallContext context)
        {
            var initialLastStreamValue = this.lastStreamValue;
            await context.Invoke();

            // If the last stream value changed after the invoke, then the stream must have produced a value, double
            // it for testing purposes.
            if (this.lastStreamValue != initialLastStreamValue)
            {
                this.lastStreamValue *= 2;
            }
        }
Esempio n. 9
0
 private void RecordUnhandledExceptionDiagnostics(IGrainCallContext context, long timestamp, Exception exception)
 {
     //isenabled check is done in parent
     _listener.Write(
         DiagnosticsLoggingStrings.DiagnosticsUnhandledExceptionName,
         new
     {
         RequestContext = RequestContext.Export(_serializationManager),
         CallContext    = context,
         Exception      = exception,
         Timestamp      = timestamp
     });
 }
Esempio n. 10
0
        async Task IGrainCallFilter.Invoke(IGrainCallContext context)
        {
            var methodInfo = context.Method;

            if (methodInfo.Name == nameof(One) && methodInfo.GetParameters().Length == 0)
            {
                // Short-circuit the request and return to the caller without actually invoking the grain method.
                context.Result = "intercepted one with no args";
                return;
            }

            if (methodInfo.Name == nameof(IncorrectResultType))
            {
                // This method has a string return type, but we are setting the result to a Guid.
                // This should result in an invalid cast exception.
                context.Result = Guid.NewGuid();
                return;
            }

            if (methodInfo.Name == nameof(FilterThrows))
            {
                throw new MyDomainSpecificException("Filter THROW!");
            }

            // Invoke the request.
            try
            {
                await context.Invoke();
            }
            catch (MyDomainSpecificException e)
            {
                context.Result = "EXCEPTION! " + e.Message;
                return;
            }

            // To prove that the MethodInfo is from the implementation and not the interface,
            // we check for this attribute which is only present on the implementation. This could be
            // done in a simpler fashion, but this demonstrates a potential usage scenario.
            var shouldMessWithResult = methodInfo.GetCustomAttribute <MessWithResultAttribute>();
            var resultString         = context.Result as string;

            if (shouldMessWithResult != null && resultString != null)
            {
                context.Result = string.Concat(resultString.Reverse());
            }
        }
Esempio n. 11
0
        public static string Format(IGrainCallContext context)
        {
            if (context.InterfaceMethod == null)
            {
                return("Unknown");
            }

            if (string.Equals(context.InterfaceMethod.Name, nameof(IDomainObjectGrain.ExecuteAsync), StringComparison.CurrentCultureIgnoreCase) &&
                context.Arguments?.Length == 1 &&
                context.Arguments[0] != null)
            {
                var argumentFullName = context.Arguments[0].ToString();

                if (argumentFullName != null)
                {
                    var argumentParts = argumentFullName.Split('.');
                    var argumentName  = argumentParts[^ 1];
Esempio n. 12
0
        public async Task Invoke(IGrainCallContext ctx)
        {
            //
            // NOTE: this grain demonstrates incorrect usage of grain call interceptors and should not be used
            // as an example of proper usage. Specifically, storing the context for later execution is invalid.
            //

            this.context = ctx;
            var value = RequestContext.Get(Key) as string;

            if (value != null)
            {
                RequestContext.Set(Key, value + '4');
            }
            await ctx.Invoke();

            this.context = null;
        }
        private void PublishEvent(IGrainCallContext target, Exception ex)
        {
            var grainEvent = _eventPublisher.CreateEvent();

            if (target.Grain != null && target.Grain is ISystemTarget == false)
            {
                if (target.Grain?.GetPrimaryKeyString() != null)
                {
                    grainEvent.GrainKeyString = target.Grain.GetPrimaryKeyString();
                }
                else if (target.Grain.IsPrimaryKeyBasedOnLong())
                {
                    grainEvent.GrainKeyLong      = target.Grain.GetPrimaryKeyLong(out var keyExt);
                    grainEvent.GrainKeyExtention = keyExt;
                }
                else
                {
                    grainEvent.GrainKeyGuid      = target.Grain.GetPrimaryKey(out var keyExt);
                    grainEvent.GrainKeyExtention = keyExt;
                }

                if (target is Grain grainTarget)
                {
                    grainEvent.SiloAddress = grainTarget.RuntimeIdentity;
                }
            }


            grainEvent.SiloDeploymentId = _clusterIdentity.DeploymentId;
            grainEvent.TargetType       = target.Grain?.GetType().FullName ?? target.InterfaceMethod.DeclaringType?.FullName;
            grainEvent.TargetMethod     = target.InterfaceMethod.Name;
            grainEvent.Exception        = ex;
            grainEvent.ErrCode          = ex != null ? null : (int?)0;

            try
            {
                _eventPublisher.TryPublish(grainEvent);
            }
            catch (Exception)
            {
                EventsDiscarded.Increment();
            }
        }
Esempio n. 14
0
        public async Task Invoke(IGrainCallContext context)
        {
            var timerInfo    = context.Method.GetCustomAttribute <LogElapsedTimeAttribute>();
            var globalMillis = _runtimeConfiguration.LogGrainCallsExceedingMilliseconds;

            if (context.Grain is IGrain grain && (timerInfo != null || globalMillis > 0))
            {
                var sw        = Stopwatch.StartNew();
                var logMillis = timerInfo?.IfExceedsMilliseconds ?? globalMillis;

                try {
                    await context.Invoke();
                } finally {
                    sw.Stop();
                    if (sw.ElapsedMilliseconds > logMillis)
                    {
                        grain.Info($"GRAIN_ELAPSED_TIME {grain.GetType().Name}.{context.Method.Name}: {sw.Elapsed}", "", "", 0);
                    }
                }
            }
Esempio n. 15
0
        protected static async Task Process(IGrainCallContext context, Activity activity)
        {
            if (activity is not null)
            {
                // rpc attributes from https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/rpc.md
                activity.SetTag("rpc.service", context.InterfaceMethod?.DeclaringType?.FullName);
                activity.SetTag("rpc.method", context.InterfaceMethod?.Name);
                activity.SetTag("net.peer.name", context.Grain?.ToString());
                activity.SetTag("rpc.system", "orleans");
            }

            try
            {
                await context.Invoke();

                if (activity is not null && activity.IsAllDataRequested)
                {
                    activity.SetTag("status", "Ok");
                }
            }
            catch (Exception e)
            {
                if (activity is not null && activity.IsAllDataRequested)
                {
                    // exception attributes from https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/exceptions.md
                    activity.SetTag("exception.type", e.GetType().FullName);
                    activity.SetTag("exception.message", e.Message);
                    activity.SetTag("exception.stacktrace", e.StackTrace);
                    activity.SetTag("exception.escaped", true);
                    activity.SetTag("status", "Error");
                }
                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
Esempio n. 16
0
        public async Task Invoke(IGrainCallContext context)
        {
            Activity activity = null;

            // export requestcontext once
            IDictionary <string, object> requestContext = RequestContext.Export(_serializationManager);;

            if (requestContext != null && requestContext.ContainsKey(DiagnosticsLoggingStrings.RequestIdHeaderName))
            {
                // flow activity from request headers
                activity = StartActivity(context, requestContext);
            }

            try
            {
                await context.Invoke().ConfigureAwait(false);

                if (activity != null)
                {
                    // is set when diagnosticslistener is enabled
                    // requestcontext dictionary is also not null
                    StopActivity(context, activity, requestContext);
                }
            }
            catch (Exception ex)
            {
                //capture failed method...
                if (_listener.IsEnabled(DiagnosticsLoggingStrings.DiagnosticsUnhandledExceptionName))
                {
                    var timestamp = Stopwatch.GetTimestamp();
                    // Diagnostics is enabled for UnhandledException, but it may not be for BeginRequest
                    // so call GetTimestamp if currentTimestamp is zero (from above)
                    RecordUnhandledExceptionDiagnostics(context, timestamp, ex);
                }
                throw;
            }
        }
        protected async Task <IEnumerable <Claim> > AuthorizeAsync(IGrainCallContext grainCallContext)
        {
            var accessToken = RequestContext.Get(ConfigurationKeys.AccessTokenKey)?.ToString();

            if (string.IsNullOrWhiteSpace(accessToken))
            {
                throw new InvalidOperationException("AccessToken can not be null or empty.");
            }

            var accessTokenVerificationResult = await _accessTokenVerifier.Verify(accessToken);

            // ReSharper disable once InvertIf
            if (accessTokenVerificationResult.IsVerified)
            {
                IEnumerable <IAuthorizeData> grainAuthorizeData = null;
                var grainMethodAuthorizeData = grainCallContext.InterfaceMethod.GetCustomAttributes <AuthorizeAttribute>();

                if (grainCallContext.InterfaceMethod.ReflectedType != null)
                {
                    grainAuthorizeData =
                        grainCallContext.InterfaceMethod.ReflectedType.GetCustomAttributes <AuthorizeAttribute>();
                }

                var authorizationSucceeded = await _authorizeHandler.AuthorizeAsync(accessTokenVerificationResult.Claims,
                                                                                    grainAuthorizeData, grainMethodAuthorizeData);

                if (!authorizationSucceeded)
                {
                    throw new NotAuthorizedException("Access to the requested grain denied.");
                }

                return(accessTokenVerificationResult.Claims);
            }

            throw new NotAuthorizedException("Access token verification failed.",
                                             new InvalidAccessTokenException(accessTokenVerificationResult.InvalidValidationMessage));
        }
Esempio n. 18
0
        public async Task Invoke(IGrainCallContext context)
        {
            if (siloAddress == null)
            {
                var providerRuntime = services.GetRequiredService <IProviderRuntime>();

                siloAddress = providerRuntime.SiloIdentity.ToSiloAddress();
            }

            var stopwatch = Stopwatch.StartNew();

            var isException = false;

            try
            {
                await context.Invoke();
            }
            catch (Exception)
            {
                isException = true;
                throw;
            }
            finally
            {
                try
                {
                    stopwatch.Stop();

                    var elapsedMs  = (double)stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond;
                    var grainName  = context.Grain.GetType().FullName;
                    var methodName = formatMethodName(context);

                    var key = string.Format("{0}.{1}", grainName, methodName);

                    grainTrace.AddOrUpdate(key, _ =>
                                           new GrainTraceEntry
                    {
                        Count          = 1,
                        ExceptionCount = (isException ? 1 : 0),
                        SiloAddress    = siloAddress,
                        ElapsedTime    = elapsedMs,
                        Grain          = grainName,
                        Method         = methodName,
                        Period         = DateTime.UtcNow
                    },
                                           (_, last) =>
                    {
                        last.Count       += 1;
                        last.ElapsedTime += elapsedMs;

                        if (isException)
                        {
                            last.ExceptionCount += 1;
                        }

                        return(last);
                    });
                }
                catch (Exception ex)
                {
                    logger.LogError(100002, "error recording results for grain", ex);
                }
            }
        }
Esempio n. 19
0
 public Task Invoke(IGrainCallContext context) => this.interceptor.Invoke(context);
        private void RejectRequestIfLateOrOverloaded(IGrainCallContext grainCallContext)
        {
            var config = _loadSheddingConfig();
            var now    = DateTimeOffset.UtcNow;

            // Too much time passed since our direct caller made the request to us; something's causing a delay. Log or reject the request, if needed.
            if (config.DropOrleansRequestsBySpanTime != LoadShedding.Toggle.Disabled &&
                TracingContext.SpanStartTime != null &&
                TracingContext.SpanStartTime.Value + config.DropOrleansRequestsOlderThanSpanTimeBy < now)
            {
                if (config.DropOrleansRequestsBySpanTime == LoadShedding.Toggle.LogOnly)
                {
                    _log.Warn(_ => _("Accepted Orleans request despite that too much time passed since the client sent it to us.", unencryptedTags: new
                    {
                        clientSendTime    = TracingContext.SpanStartTime,
                        currentTime       = now,
                        maxDelayInSecs    = config.DropOrleansRequestsOlderThanSpanTimeBy.TotalSeconds,
                        actualDelayInSecs = (now - TracingContext.SpanStartTime.Value).TotalSeconds,
                    }));
                }
                else if (config.DropOrleansRequestsBySpanTime == LoadShedding.Toggle.Drop)
                {
                    //Add grain  id to tags
                    throw new EnvironmentException(
                              "Dropping Orleans request since too much time passed since the client sent it to us.",
                              unencrypted: new Tags
                    {
                        ["clientSendTime"]    = TracingContext.SpanStartTime.ToString(),
                        ["currentTime"]       = now.ToString(),
                        ["maxDelayInSecs"]    = config.DropOrleansRequestsOlderThanSpanTimeBy.TotalSeconds.ToString(),
                        ["actualDelayInSecs"] = (now - TracingContext.SpanStartTime.Value).TotalSeconds.ToString(),
                    });
                }
            }

            // Too much time passed since the API gateway initially sent this request till it reached us (potentially
            // passing through other micro-services along the way). Log or reject the request, if needed.
            if (config.DropRequestsByDeathTime != LoadShedding.Toggle.Disabled &&
                TracingContext.AbandonRequestBy != null &&
                now > TracingContext.AbandonRequestBy.Value - config.TimeToDropBeforeDeathTime)
            {
                if (config.DropRequestsByDeathTime == LoadShedding.Toggle.LogOnly)
                {
                    _log.Warn(_ => _("Accepted Orleans request despite exceeding the API gateway timeout.", unencryptedTags: new
                    {
                        requestDeathTime = TracingContext.AbandonRequestBy,
                        currentTime      = now,
                        overTimeInSecs   = (now - TracingContext.AbandonRequestBy.Value).TotalSeconds,
                    }));
                }
                else if (config.DropRequestsByDeathTime == LoadShedding.Toggle.Drop)
                {
                    //Add grain  id to tags
                    throw new EnvironmentException("Dropping Orleans request since the API gateway timeout passed.", unencrypted: new Tags
                    {
                        ["requestDeathTime"] = TracingContext.AbandonRequestBy.ToString(),
                        ["currentTime"]      = now.ToString(),
                        ["overTimeInSecs"]   = (now - TracingContext.AbandonRequestBy.Value).TotalSeconds.ToString(),
                    });
                }
            }
        }
Esempio n. 21
0
 private void StopActivity(IGrainCallContext callContext, Activity activity, IDictionary <string, object> requestContext)
 {
     _listener.StopActivity(activity, new { RequestContext = requestContext, CallContext = callContext });
 }