private async Task <ContainerProperties> ReadCollectionAsync(
            string collectionLink,
            IDocumentClientRetryPolicy retryPolicyInstance,
            ITrace trace,
            IClientSideRequestStatistics clientSideRequestStatistics,
            CancellationToken cancellationToken)
        {
            using (ITrace childTrace = trace.StartChild("Read Collection", TraceComponent.Transport, TraceLevel.Info))
            {
                cancellationToken.ThrowIfCancellationRequested();

                RequestNameValueCollection headers = new RequestNameValueCollection();
                using (DocumentServiceRequest request = DocumentServiceRequest.Create(
                           OperationType.Read,
                           ResourceType.Collection,
                           collectionLink,
                           AuthorizationTokenType.PrimaryMasterKey,
                           headers))
                {
                    headers.XDate = Rfc1123DateTimeCache.UtcNow();

                    request.RequestContext.ClientRequestStatistics = clientSideRequestStatistics ?? new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace.Summary);
                    if (clientSideRequestStatistics == null)
                    {
                        childTrace.AddDatum(
                            "Client Side Request Stats",
                            request.RequestContext.ClientRequestStatistics);
                    }

                    string authorizationToken = await this.tokenProvider.GetUserAuthorizationTokenAsync(
                        request.ResourceAddress,
                        PathsHelper.GetResourcePath(request.ResourceType),
                        HttpConstants.HttpMethods.Get,
                        request.Headers,
                        AuthorizationTokenType.PrimaryMasterKey,
                        childTrace);

                    headers.Authorization = authorizationToken;

                    using (new ActivityScope(Guid.NewGuid()))
                    {
                        retryPolicyInstance?.OnBeforeSendRequest(request);

                        try
                        {
                            using (DocumentServiceResponse response =
                                       await this.storeModel.ProcessMessageAsync(request))
                            {
                                return(CosmosResource.FromStream <ContainerProperties>(response));
                            }
                        }
                        catch (DocumentClientException ex)
                        {
                            childTrace.AddDatum("Exception Message", ex.Message);
                            throw;
                        }
                    }
                }
            }
        }
Example #2
0
        private static void ValidateInputRequestTime(
            string dateToCompare,
            int masterTokenExpiryInSeconds,
            int allowedClockSkewInSeconds)
        {
            if (string.IsNullOrEmpty(dateToCompare))
            {
                throw new UnauthorizedException(RMResources.MissingDateForAuthorization);
            }

            if (!DateTime.TryParse(dateToCompare, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal | DateTimeStyles.AllowWhiteSpaces, out DateTime utcStartTime))
            {
                throw new UnauthorizedException(RMResources.InvalidDateHeader);
            }

            // Check if time range is beyond DateTime.MaxValue
            bool outOfRange = utcStartTime >= DateTime.MaxValue.AddSeconds(-masterTokenExpiryInSeconds);

            if (outOfRange)
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                                               RMResources.InvalidTokenTimeRange,
                                               utcStartTime.ToString("r", CultureInfo.InvariantCulture),
                                               DateTime.MaxValue.ToString("r", CultureInfo.InvariantCulture),
                                               Rfc1123DateTimeCache.UtcNow());

                DefaultTrace.TraceError(message);

                throw new ForbiddenException(message);
            }

            DateTime utcEndTime = utcStartTime + TimeSpan.FromSeconds(masterTokenExpiryInSeconds);

            AuthorizationHelper.CheckTimeRangeIsCurrent(allowedClockSkewInSeconds, utcStartTime, utcEndTime);
        }
Example #3
0
        public static void CheckTimeRangeIsCurrent(
            int allowedClockSkewInSeconds,
            DateTime startDateTime,
            DateTime expiryDateTime)
        {
            // Check if time ranges provided are beyond DateTime.MinValue or DateTime.MaxValue
            bool outOfRange = startDateTime <= DateTime.MinValue.AddSeconds(allowedClockSkewInSeconds) ||
                              expiryDateTime >= DateTime.MaxValue.AddSeconds(-allowedClockSkewInSeconds);

            // Adjust for a time lag between various instances upto 5 minutes i.e. allow [start-5, end+5]
            if (outOfRange ||
                startDateTime.AddSeconds(-allowedClockSkewInSeconds) > DateTime.UtcNow ||
                expiryDateTime.AddSeconds(allowedClockSkewInSeconds) < DateTime.UtcNow)
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                                               RMResources.InvalidTokenTimeRange,
                                               startDateTime.ToString("r", CultureInfo.InvariantCulture),
                                               expiryDateTime.ToString("r", CultureInfo.InvariantCulture),
                                               Rfc1123DateTimeCache.UtcNow());

                DefaultTrace.TraceError(message);

                throw new ForbiddenException(message);
            }
        }
        public override ValueTask <(string token, string payload)> GetUserAuthorizationAsync(
            string resourceAddress,
            string resourceType,
            string requestVerb,
            INameValueCollection headers,
            AuthorizationTokenType tokenType)
        {
            // this is masterkey authZ
            headers[HttpConstants.HttpHeaders.XDate] = Rfc1123DateTimeCache.UtcNow();

            string authorizationToken = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                requestVerb,
                resourceAddress,
                resourceType,
                headers,
                this.authKeyHashFunction,
                out AuthorizationHelper.ArrayOwner arrayOwner);

            using (arrayOwner)
            {
                string payload = null;
                if (arrayOwner.Buffer.Count > 0)
                {
                    payload = Encoding.UTF8.GetString(arrayOwner.Buffer.Array, arrayOwner.Buffer.Offset, (int)arrayOwner.Buffer.Count);
                }

                return(new ValueTask <(string token, string payload)>((authorizationToken, payload)));
            }
        }
        private async Task <DocumentServiceResponse> GetMasterAddressesViaGatewayAsync(
            DocumentServiceRequest request,
            ResourceType resourceType,
            string resourceAddress,
            string entryUrl,
            bool forceRefresh,
            bool useMasterCollectionResolver)
        {
            INameValueCollection addressQuery = new RequestNameValueCollection
            {
                { HttpConstants.QueryStrings.Url, HttpUtility.UrlEncode(entryUrl) }
            };

            INameValueCollection headers = new RequestNameValueCollection();

            if (forceRefresh)
            {
                headers.Set(HttpConstants.HttpHeaders.ForceRefresh, bool.TrueString);
            }

            if (useMasterCollectionResolver)
            {
                headers.Set(HttpConstants.HttpHeaders.UseMasterCollectionResolver, bool.TrueString);
            }

            if (request.ForceCollectionRoutingMapRefresh)
            {
                headers.Set(HttpConstants.HttpHeaders.ForceCollectionRoutingMapRefresh, bool.TrueString);
            }

            addressQuery.Add(HttpConstants.QueryStrings.Filter, this.protocolFilter);

            string resourceTypeToSign = PathsHelper.GetResourcePath(resourceType);

            headers.Set(HttpConstants.HttpHeaders.XDate, Rfc1123DateTimeCache.UtcNow());
            using (ITrace trace = Trace.GetRootTrace(nameof(GetMasterAddressesViaGatewayAsync), TraceComponent.Authorization, TraceLevel.Info))
            {
                string token = await this.tokenProvider.GetUserAuthorizationTokenAsync(
                    resourceAddress,
                    resourceTypeToSign,
                    HttpConstants.HttpMethods.Get,
                    headers,
                    AuthorizationTokenType.PrimaryMasterKey,
                    trace);

                headers.Set(HttpConstants.HttpHeaders.Authorization, token);

                Uri targetEndpoint = UrlUtility.SetQuery(this.addressEndpoint, UrlUtility.CreateQuery(addressQuery));

                string identifier = GatewayAddressCache.LogAddressResolutionStart(request, targetEndpoint);
                using (HttpResponseMessage httpResponseMessage = await this.httpClient.GetAsync(
                           uri: targetEndpoint,
                           additionalHeaders: headers,
                           resourceType: resourceType,
                           timeoutPolicy: HttpTimeoutPolicyControlPlaneRetriableHotPath.Instance,
                           clientSideRequestStatistics: request.RequestContext?.ClientRequestStatistics,
                           cancellationToken: default))
        public MasterKeyAuthorizationBenchmark()
        {
            this.authKeyHashFunction = new StringHMACSHA256Hash(MockDocumentClient.GenerateRandomKey());
            Headers headers = new Headers();

            headers[HttpConstants.HttpHeaders.XDate] = Rfc1123DateTimeCache.UtcNow();

            this.testHeaders = headers.CosmosMessageHeaders.INameValueCollection;
        }
Example #7
0
        public async Task AddSystemAuthorizationHeaderAsync(
            DocumentServiceRequest request,
            string federationId,
            string verb,
            string resourceId)
        {
            request.Headers[HttpConstants.HttpHeaders.XDate] = Rfc1123DateTimeCache.UtcNow();

            request.Headers[HttpConstants.HttpHeaders.Authorization] = (await this.GetUserAuthorizationAsync(
                                                                            resourceId ?? request.ResourceAddress,
                                                                            PathsHelper.GetResourcePath(request.ResourceType),
                                                                            verb,
                                                                            request.Headers,
                                                                            request.RequestAuthorizationTokenType)).token;
        }
        public override ValueTask AddAuthorizationHeaderAsync(
            INameValueCollection headersCollection,
            Uri requestAddress,
            string verb,
            AuthorizationTokenType tokenType)
        {
            string dateTime = Rfc1123DateTimeCache.UtcNow();

            headersCollection[HttpConstants.HttpHeaders.XDate] = dateTime;

            string token = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                verb,
                requestAddress,
                headersCollection,
                this.authKeyHashFunction);

            headersCollection.Add(HttpConstants.HttpHeaders.Authorization, token);
            return(default);
Example #9
0
        public void TestGenerateAuthorizationTokenWithHashCoreDoesNotEncodeUrl()
        {
            Mock <INameValueCollection> mockHeaders = new Mock <INameValueCollection>();

            mockHeaders.SetupGet(h => h["x-ms-date"]).Returns(Rfc1123DateTimeCache.UtcNow());
            Mock <IComputeHash> hashHelperMock = new Mock <IComputeHash>();

            hashHelperMock.Setup(
                ch => ch.ComputeHash(It.IsAny <ArraySegment <byte> >()))
            .Returns(new byte[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 });

            string token = AuthorizationHelper.GenerateAuthorizationTokenWithHashCore(
                verb: "testVerb",
                resourceId: "dbs/V4lVAA==/colls/V4lVAMl0wuQ=/",
                resourceType: "colls",
                headers: mockHeaders.Object,
                stringHMACSHA256Helper: hashHelperMock.Object,
                out _);

            // Encoding.UTF8 string representation of the key byte array. (if it were URL encoded, it would end with "3d%3d" instead of "==").
            Assert.AreEqual("AgQGCAoMDhASFA==", token);
        }
        ValueTask <string> ICosmosAuthorizationTokenProvider.GetUserAuthorizationTokenAsync(
            string resourceAddress,
            string resourceType,
            string requestVerb,
            INameValueCollection headers,
            AuthorizationTokenType tokenType,
            ITrace trace) // unused, use token based upon what is passed in constructor
        {
            // this is masterkey authZ
            headers[HttpConstants.HttpHeaders.XDate] = Rfc1123DateTimeCache.UtcNow();

            string authorization = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                verb: requestVerb,
                resourceId: resourceAddress,
                resourceType: resourceType,
                headers: headers,
                stringHMACSHA256Helper: this.authKeyHashFunction,
                payload: out AuthorizationHelper.ArrayOwner payload);

            using (payload)
            {
                return(new ValueTask <string>(authorization));
            }
        }
        public override ValueTask <string> GetUserAuthorizationTokenAsync(
            string resourceAddress,
            string resourceType,
            string requestVerb,
            INameValueCollection headers,
            AuthorizationTokenType tokenType,
            ITrace trace)
        {
            // this is masterkey authZ
            headers[HttpConstants.HttpHeaders.XDate] = Rfc1123DateTimeCache.UtcNow();

            string authorizationToken = AuthorizationHelper.GenerateKeyAuthorizationSignature(
                requestVerb,
                resourceAddress,
                resourceType,
                headers,
                this.authKeyHashFunction,
                out AuthorizationHelper.ArrayOwner arrayOwner);

            using (arrayOwner)
            {
                return(new ValueTask <string>(authorizationToken));
            }
        }
 public void Rfc1123DateTimeCacheUtcNow()
 {
     _ = Rfc1123DateTimeCache.UtcNow();
 }
Example #13
0
        public static int SerializeMessagePayload(
            Span <byte> stream,
            string verb,
            string resourceId,
            string resourceType,
            INameValueCollection headers,
            bool bUseUtcNowForMissingXDate = false)
        {
            string xDate = AuthorizationHelper.GetHeaderValue(headers, HttpConstants.HttpHeaders.XDate);
            string date  = AuthorizationHelper.GetHeaderValue(headers, HttpConstants.HttpHeaders.HttpDate);

            // At-least one of date header should present
            // https://docs.microsoft.com/en-us/rest/api/documentdb/access-control-on-documentdb-resources
            if (string.IsNullOrEmpty(xDate) && string.IsNullOrWhiteSpace(date))
            {
                if (!bUseUtcNowForMissingXDate)
                {
                    throw new UnauthorizedException(RMResources.InvalidDateHeader);
                }

                headers[HttpConstants.HttpHeaders.XDate] = Rfc1123DateTimeCache.UtcNow();
                xDate = AuthorizationHelper.GetHeaderValue(headers, HttpConstants.HttpHeaders.XDate);
            }

            // for name based, it is case sensitive, we won't use the lower case
            if (!PathsHelper.IsNameBased(resourceId))
            {
                resourceId = resourceId.ToLowerInvariant();
            }

            int totalLength = 0;
            int length      = stream.Write(verb.ToLowerInvariant());

            totalLength += length;
            stream       = stream.Slice(length);
            length       = stream.Write("\n");
            totalLength += length;
            stream       = stream.Slice(length);
            length       = stream.Write(resourceType.ToLowerInvariant());
            totalLength += length;
            stream       = stream.Slice(length);
            length       = stream.Write("\n");
            totalLength += length;
            stream       = stream.Slice(length);
            length       = stream.Write(resourceId);
            totalLength += length;
            stream       = stream.Slice(length);
            length       = stream.Write("\n");
            totalLength += length;
            stream       = stream.Slice(length);
            length       = stream.Write(xDate.ToLowerInvariant());
            totalLength += length;
            stream       = stream.Slice(length);
            length       = stream.Write("\n");
            totalLength += length;
            stream       = stream.Slice(length);
            length       = stream.Write(xDate.Equals(string.Empty, StringComparison.OrdinalIgnoreCase) ? date.ToLowerInvariant() : string.Empty);
            totalLength += length;
            stream       = stream.Slice(length);
            length       = stream.Write("\n");
            totalLength += length;
            return(totalLength);
        }
 private static string GetUtcDateTime()
 {
     return(Rfc1123DateTimeCache.UtcNow());
 }