public async Task GetAsync_WithValidArguments_ReturnsValidCredentials()
        {
            var expectation = new TestExpectation(
                operationClaims: new[] { OperationClaim.Authentication },
                connectionOptions: ConnectionOptions.CreateDefault(),
                pluginVersion: ProtocolConstants.CurrentVersion,
                uri: _uri,
                authenticationUsername: _username,
                authenticationPassword: _password,
                success: true);

            using (var test = new PluginManagerMock(
                       pluginFilePath: "a",
                       pluginFileState: PluginFileState.Valid,
                       expectations: expectation))
            {
                var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy <PluginFileState>(() => PluginFileState.Valid)));
                var provider        = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance);

                IWebProxy proxy              = null;
                var       credType           = CredentialRequestType.Unauthorized;
                var       message            = "nothing";
                var       isRetry            = false;
                var       isInteractive      = false;
                var       token              = CancellationToken.None;
                var       credentialResponse = await provider.GetAsync(_uri, proxy, credType, message, isRetry, isInteractive, token);

                Assert.True(credentialResponse.Status == CredentialStatus.Success);
                Assert.NotNull(credentialResponse.Credentials);
                Assert.Equal(_username, credentialResponse.Credentials.GetCredential(_uri, authType: null).UserName);
                Assert.Equal(_password, credentialResponse.Credentials.GetCredential(_uri, authType: null).Password);
            }
        }
Exemplo n.º 2
0
        public async Task TryGetSourceAgnosticPluginAsync_WhenSuccessfullyCreated_OperationClaimsAreCached()
        {
            var operationClaims = new[] { OperationClaim.Authentication };

            using (var test = new PluginManagerTest(PluginFilePath, PluginFileState.Valid, operationClaims))
            {
                Assert.False(File.Exists(test.PluginCacheEntry.CacheFileName));

                var discoveryResult = new PluginDiscoveryResult(
                    new PluginFile(
                        PluginFilePath,
                        new Lazy <PluginFileState>(() => PluginFileState.Valid)));

                Tuple <bool, PluginCreationResult> result = await test.PluginManager.TryGetSourceAgnosticPluginAsync(
                    discoveryResult,
                    OperationClaim.Authentication,
                    CancellationToken.None);

                bool wasSomethingCreated            = result.Item1;
                PluginCreationResult creationResult = result.Item2;

                Assert.True(wasSomethingCreated);
                Assert.NotNull(creationResult);

                Assert.True(File.Exists(test.PluginCacheEntry.CacheFileName));

                Assert.Null(creationResult.Message);
                Assert.Null(creationResult.Exception);
                Assert.Same(test.Plugin, creationResult.Plugin);
                Assert.NotNull(creationResult.PluginMulticlientUtilities);
                Assert.Equal(operationClaims, creationResult.Claims);
            }
        }
        public async Task GetAsync_WhenPluginManagerReturnsException_ExceptionIsPropagated()
        {
            var expectedMessage      = "a";
            var expectedException    = CreateExceptionWithCallstack("b");
            var pluginCreationResult = new PluginCreationResult(expectedMessage, expectedException);
            var result        = new Tuple <bool, PluginCreationResult>(true, pluginCreationResult);
            var pluginManager = new Mock <IPluginManager>(MockBehavior.Strict);

            pluginManager.Setup(x => x.TryGetSourceAgnosticPluginAsync(
                                    It.IsNotNull <PluginDiscoveryResult>(),
                                    It.Is <OperationClaim>(claim => claim == OperationClaim.Authentication),
                                    It.IsAny <CancellationToken>()))
            .ReturnsAsync(result);

            var pluginDiscoveryResult = new PluginDiscoveryResult(new PluginFile("c", new Lazy <PluginFileState>(() => PluginFileState.Valid)));
            var logger = new Mock <ILogger>(MockBehavior.Strict);

            logger.Setup(x => x.LogError(It.Is <string>(data => data == expectedMessage)));
            logger.Setup(x => x.LogDebug(It.Is <string>(data => data == expectedException.ToString())));

            var provider = new SecurePluginCredentialProvider(pluginManager.Object, pluginDiscoveryResult, canShowDialog: false, logger: logger.Object);

            var exception = await Assert.ThrowsAsync <PluginException>(
                () => provider.GetAsync(_uri, proxy: null, type: CredentialRequestType.Forbidden, message: null, isRetry: false, nonInteractive: true, cancellationToken: CancellationToken.None));

            Assert.Same(expectedException, exception.InnerException);

            pluginManager.Verify();
            logger.Verify();
        }
 /// <summary>
 /// Create a credential provider based on provided plugin
 /// </summary>
 /// <param name="pluginManager"></param>
 /// <param name="pluginDiscoveryResult"></param>
 /// <param name="logger"></param>
 /// <exception cref="ArgumentNullException">if <paramref name="pluginDiscoveryResult"/> is null</exception>
 /// <exception cref="ArgumentNullException">if <paramref name="logger"/> is null</exception>
 /// <exception cref="ArgumentNullException">if <paramref name="pluginManager"/> is null</exception>
 /// <exception cref="ArgumentException">if plugin file is not valid</exception>
 public SecurePluginCredentialProvider(IPluginManager pluginManager, PluginDiscoveryResult pluginDiscoveryResult, ILogger logger)
 {
     _pluginManager    = pluginManager ?? throw new ArgumentNullException(nameof(pluginManager));
     _discoveredPlugin = pluginDiscoveryResult ?? throw new ArgumentNullException(nameof(pluginDiscoveryResult));
     _logger           = logger ?? throw new ArgumentNullException(nameof(logger));
     Id = $"{nameof(SecurePluginCredentialProvider)}_{pluginDiscoveryResult.PluginFile.Path}";
 }
Exemplo n.º 5
0
        public async Task TryGetSourceAgnosticPluginAsync_WhenCacheFileIndicatesIndicatesNoSupportedOperationClaims_PluginIsNotCreated()
        {
            var operationClaims = Array.Empty <OperationClaim>();

            using (var test = new PluginManagerTest(PluginFilePath, PluginFileState.Valid, operationClaims))
            {
                test.PluginCacheEntry.OperationClaims = operationClaims;

                await test.PluginCacheEntry.UpdateCacheFileAsync();

                Assert.True(File.Exists(test.PluginCacheEntry.CacheFileName));

                var discoveryResult = new PluginDiscoveryResult(
                    new PluginFile(
                        PluginFilePath,
                        new Lazy <PluginFileState>(() => PluginFileState.Valid)));

                Tuple <bool, PluginCreationResult> result = await test.PluginManager.TryGetSourceAgnosticPluginAsync(
                    discoveryResult,
                    OperationClaim.Authentication,
                    CancellationToken.None);

                bool wasSomethingCreated            = result.Item1;
                PluginCreationResult creationResult = result.Item2;

                Assert.False(wasSomethingCreated);
                Assert.Null(creationResult);

                Assert.True(File.Exists(test.PluginCacheEntry.CacheFileName));
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates a plugin from the discovered plugin.
        /// We firstly check the cache for the operation claims for the given request key.
        /// If there is a valid cache entry, and it does contain the requested operation claim, then we start the plugin, and if need be update the cache value itself.
        /// If there is a valid cache entry, and it does NOT contain the requested operation claim, then we return a null.
        /// If there is no valid cache entry or an invalid one, we start the plugin as normally, return an active plugin even if the requested claim is not available, and write a cache entry.
        /// </summary>
        /// <param name="result">plugin discovery result</param>
        /// <param name="requestedOperationClaim">The requested operation claim</param>
        /// <param name="requestKey">plugin request key</param>
        /// <param name="packageSourceRepository">package source repository</param>
        /// <param name="serviceIndex">service index</param>
        /// <param name="cancellationToken">cancellation token</param>
        /// <returns>A plugin creation result, null if the requested plugin cannot handle the given operation claim</returns>
        private async Task <Tuple <bool, PluginCreationResult> > TryCreatePluginAsync(
            PluginDiscoveryResult result,
            OperationClaim requestedOperationClaim,
            PluginRequestKey requestKey,
            string packageSourceRepository,
            JObject serviceIndex,
            CancellationToken cancellationToken)
        {
            PluginCreationResult pluginCreationResult = null;
            var cacheEntry = new PluginCacheEntry(_pluginsCacheDirectory.Value, result.PluginFile.Path, requestKey.PackageSourceRepository);

            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       cacheEntry.CacheFileName,
                       action : async lockedToken =>
            {
                if (cacheEntry.OperationClaims == null || cacheEntry.OperationClaims.Contains(requestedOperationClaim))
                {
                    if (result.PluginFile.State.Value == PluginFileState.Valid)
                    {
                        var plugin = await _pluginFactory.GetOrCreateAsync(
                            result.PluginFile.Path,
                            PluginConstants.PluginArguments,
                            new RequestHandlers(),
                            _connectionOptions,
                            cancellationToken);

                        var utilities = await PerformOneTimePluginInitializationAsync(plugin, cancellationToken);

                        // We still make the GetOperationClaims call even if we have the operation claims cached. This is a way to self-update the cache.
                        var operationClaims = await _pluginOperationClaims.GetOrAdd(
                            requestKey,
                            key => new Lazy <Task <IReadOnlyList <OperationClaim> > >(() =>
                                                                                      GetPluginOperationClaimsAsync(
                                                                                          plugin,
                                                                                          packageSourceRepository,
                                                                                          serviceIndex,
                                                                                          cancellationToken))).Value;

                        if (!EqualityUtility.SequenceEqualWithNullCheck(operationClaims, cacheEntry.OperationClaims))
                        {
                            cacheEntry.OperationClaims = operationClaims;
                            await cacheEntry.UpdateCacheFileAsync();
                        }

                        pluginCreationResult = new PluginCreationResult(
                            plugin,
                            utilities.Value,
                            operationClaims);
                    }
                    else
                    {
                        pluginCreationResult = new PluginCreationResult(result.Message);
                    }
                }
                return new Tuple <bool, PluginCreationResult>(pluginCreationResult != null, pluginCreationResult);
            },
                       token : cancellationToken
                       ));
        }
Exemplo n.º 7
0
        public void Constructor_InitializesProperties()
        {
            var pluginFile = new PluginFile(filePath: "a", state: new Lazy <PluginFileState>(() => PluginFileState.InvalidEmbeddedSignature));

            var result = new PluginDiscoveryResult(pluginFile);

            Assert.Same(pluginFile, result.PluginFile);
        }
Exemplo n.º 8
0
 /// <summary>
 /// Creates a plugin from the given pluginDiscoveryResult.
 /// This plugin's operations will be source agnostic ones
 /// </summary>
 /// <param name="pluginDiscoveryResult"></param>
 /// <param name="cancellationToken"></param>
 /// <returns>A PluginCreationResult</returns>
 public Task <PluginCreationResult> CreateSourceAgnosticPluginAsync(PluginDiscoveryResult pluginDiscoveryResult, CancellationToken cancellationToken)
 {
     if (pluginDiscoveryResult == null)
     {
         throw new ArgumentNullException(nameof(pluginDiscoveryResult));
     }
     return(CreatePluginAsync(pluginDiscoveryResult, new PluginRequestKey(pluginDiscoveryResult.PluginFile.Path, "Source-Agnostic"), null, null, cancellationToken));
 }
        public void Constructor_InitializesProperties()
        {
            var pluginFile = new PluginFile(filePath: "a", state: PluginFileState.InvalidEmbeddedSignature);

            var result = new PluginDiscoveryResult(pluginFile, message: "b");

            Assert.Same(pluginFile, result.PluginFile);
            Assert.Equal("b", result.Message);
        }
Exemplo n.º 10
0
        public async Task PluginManager_CreatePlugin_PrefersFrameworkSpecificEnvironmentVariable(string pluginPath)
        {
            var operationClaims = new[] { OperationClaim.Authentication };
            var mockReader      = new Mock <IEnvironmentVariableReader>(MockBehavior.Strict);

            mockReader.Setup(x => x.GetEnvironmentVariable(
                                 It.Is <string>(value => value == EnvironmentVariableConstants.PluginPaths)))
            .Returns("badPluginPath");
#if IS_DESKTOP
            mockReader.Setup(x => x.GetEnvironmentVariable(
                                 It.Is <string>(value => value == EnvironmentVariableConstants.DesktopPluginPaths)))
            .Returns(pluginPath);
#else
            mockReader.Setup(x => x.GetEnvironmentVariable(
                                 It.Is <string>(value => value == EnvironmentVariableConstants.CorePluginPaths)))
            .Returns(pluginPath);
#endif
            mockReader.Setup(x => x.GetEnvironmentVariable(
                                 It.Is <string>(value => value == EnvironmentVariableConstants.RequestTimeout)))
            .Returns("RequestTimeout");
            mockReader.Setup(x => x.GetEnvironmentVariable(
                                 It.Is <string>(value => value == EnvironmentVariableConstants.IdleTimeout)))
            .Returns("IdleTimeout");
            mockReader.Setup(x => x.GetEnvironmentVariable(
                                 It.Is <string>(value => value == EnvironmentVariableConstants.HandshakeTimeout)))
            .Returns("HandshakeTimeout");

            using (var test = new PluginManagerTest(pluginPath, PluginFileState.Valid, operationClaims, mockReader))
            {
                var discoveryResult = new PluginDiscoveryResult(
                    new PluginFile(
                        PluginFilePath,
                        new Lazy <PluginFileState>(() => PluginFileState.Valid)));

                Tuple <bool, PluginCreationResult> result = await test.PluginManager.TryGetSourceAgnosticPluginAsync(
                    discoveryResult,
                    OperationClaim.Authentication,
                    CancellationToken.None);

                bool wasSomethingCreated            = result.Item1;
                PluginCreationResult creationResult = result.Item2;

                Assert.True(wasSomethingCreated);
                Assert.NotNull(creationResult);

                Assert.Null(creationResult.Message);
                Assert.Null(creationResult.Exception);
                Assert.Same(test.Plugin, creationResult.Plugin);
                Assert.NotNull(creationResult.PluginMulticlientUtilities);
                Assert.Equal(operationClaims, creationResult.Claims);
            }
        }
Exemplo n.º 11
0
 /// <summary>
 /// Create a credential provider based on provided plugin
 /// </summary>
 /// <param name="pluginManager"></param>
 /// <param name="pluginDiscoveryResult"></param>
 /// <param name="logger"></param>
 /// <exception cref="ArgumentNullException">if <paramref name="pluginDiscoveryResult"/> is null</exception>
 /// <exception cref="ArgumentNullException">if <paramref name="logger"/> is null</exception>
 /// <exception cref="ArgumentNullException">if <paramref name="pluginManager"/> is null</exception>
 /// <exception cref="ArgumentException">if plugin file is not valid</exception>
 public SecurePluginCredentialProvider(IPluginManager pluginManager, PluginDiscoveryResult pluginDiscoveryResult, ILogger logger)
 {
     if (pluginDiscoveryResult == null)
     {
         throw new ArgumentNullException(nameof(pluginDiscoveryResult));
     }
     if (pluginDiscoveryResult.PluginFile.State != PluginFileState.Valid)
     {
         throw new ArgumentException(string.Format(Resources.SecureCredentialProvider_InvalidPluginFile, pluginDiscoveryResult.PluginFile.State, pluginDiscoveryResult.Message), nameof(pluginDiscoveryResult));
     }
     _pluginManager    = pluginManager ?? throw new ArgumentNullException(nameof(pluginManager));
     _discoveredPlugin = pluginDiscoveryResult;
     _logger           = logger ?? throw new ArgumentNullException(nameof(logger));
     Id = $"{nameof(SecurePluginCredentialProvider)}_{pluginDiscoveryResult.PluginFile.Path}";
 }
Exemplo n.º 12
0
        public async Task TryGetSourceAgnosticPluginAsync_WhenExceptionIsThrownDuringPluginCreation_PropagatesException()
        {
            const string pluginFilePath = "a";
            const string message        = "b";

            var reader        = Mock.Of <IEnvironmentVariableReader>();
            var pluginFactory = new Mock <IPluginFactory>(MockBehavior.Strict);
            var exception     = new Exception(message);

            pluginFactory.Setup(x => x.GetOrCreateAsync(
                                    It.Is <string>(filePath => string.Equals(filePath, pluginFilePath, StringComparison.Ordinal)),
                                    It.Is <IEnumerable <string> >(arguments => arguments != null && arguments.Any()),
                                    It.IsNotNull <IRequestHandlers>(),
                                    It.IsNotNull <ConnectionOptions>(),
                                    It.IsAny <CancellationToken>()))
            .ThrowsAsync(exception);
            pluginFactory.Setup(x => x.Dispose());

            using (var directory = TestDirectory.Create())
                using (var pluginManager = new PluginManager(
                           reader,
                           new Lazy <IPluginDiscoverer>(() => Mock.Of <IPluginDiscoverer>()),
                           (TimeSpan idleTimeout) => pluginFactory.Object,
                           new Lazy <string>(() => directory.Path)))
                {
                    var discoveryResult = new PluginDiscoveryResult(
                        new PluginFile(
                            pluginFilePath,
                            new Lazy <PluginFileState>(() => PluginFileState.Valid)));

                    Tuple <bool, PluginCreationResult> result = await pluginManager.TryGetSourceAgnosticPluginAsync(
                        discoveryResult,
                        OperationClaim.Authentication,
                        CancellationToken.None);

                    bool wasSomethingCreated            = result.Item1;
                    PluginCreationResult creationResult = result.Item2;

                    Assert.True(wasSomethingCreated);
                    Assert.NotNull(creationResult);

                    Assert.Equal($"Problem starting the plugin '{pluginFilePath}'. {message}", creationResult.Message);
                    Assert.Same(exception, creationResult.Exception);
                }

            pluginFactory.Verify();
        }
Exemplo n.º 13
0
        public void TryCreate_SetsProxyCredentials()
        {
            var uri           = new Uri("https://api.nuget.org/v3/index.json");
            var authUsername  = "******";
            var authPassword  = "******";
            var proxyUsername = "******";
            var proxyPassword = "******";

            var expectation = new TestExpectation(
                serviceIndexJson: null,
                sourceUri: null,
                operationClaims: new[] { OperationClaim.Authentication },
                connectionOptions: ConnectionOptions.CreateDefault(),
                pluginVersion: ProtocolConstants.CurrentVersion,
                uri: uri,
                authenticationUsername: authUsername,
                authenticationPassword: authPassword,
                success: true,
                proxyUsername: proxyUsername,
                proxyPassword: proxyPassword
                );

            using (var test = new PluginManagerMock(
                       pluginFilePath: "a",
                       pluginFileState: PluginFileState.Valid,
                       expectations: expectation))
            {
                var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy <PluginFileState>(() => PluginFileState.Valid)));
                var provider        = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, NullLogger.Instance);
                var proxy           = new System.Net.WebProxy()
                {
                    Credentials = new NetworkCredential(proxyUsername, proxyPassword)
                };
                var credType           = CredentialRequestType.Unauthorized;
                var message            = "nothing";
                var isRetry            = false;
                var isInteractive      = false;
                var token              = CancellationToken.None;
                var credentialResponse = provider.GetAsync(uri, proxy, credType, message, isRetry, isInteractive, token).Result;

                Assert.True(credentialResponse.Status == CredentialStatus.Success);
                Assert.NotNull(credentialResponse.Credentials);
                Assert.Equal(authUsername, credentialResponse.Credentials.GetCredential(uri, null).UserName);
                Assert.Equal(authPassword, credentialResponse.Credentials.GetCredential(uri, null).Password);
            }
        }
        public void TryCreate_DoesNotCreateNonCredentialsPluginTwice()
        {
            var uri          = new Uri("https://api.nuget.org/v3/index.json");
            var authUsername = "******";
            var authPassword = "******";

            var expectation = new TestExpectation(
                serviceIndexJson: null,
                sourceUri: null,
                operationClaims: new[] { OperationClaim.DownloadPackage },
                connectionOptions: ConnectionOptions.CreateDefault(),
                pluginVersion: ProtocolConstants.CurrentVersion,
                uri: uri,
                authenticationUsername: authUsername,
                authenticationPassword: authPassword,
                success: false
                );

            using (var test = new PluginManagerMock(
                       pluginFilePath: "a",
                       pluginFileState: PluginFileState.Valid,
                       expectations: expectation))
            {
                var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", PluginFileState.Valid));
                var provider        = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, NullLogger.Instance);

                System.Net.IWebProxy proxy = null;
                var credType           = CredentialRequestType.Unauthorized;
                var message            = "nothing";
                var isRetry            = false;
                var isInteractive      = false;
                var token              = CancellationToken.None;
                var credentialResponse = provider.GetAsync(uri, proxy, credType, message, isRetry, isInteractive, token).Result;

                Assert.True(credentialResponse.Status == CredentialStatus.ProviderNotApplicable);
                Assert.Null(credentialResponse.Credentials);

                var credentialResponse2 = provider.GetAsync(uri, proxy, credType, message, isRetry, isInteractive, token).Result;
                Assert.True(credentialResponse2.Status == CredentialStatus.ProviderNotApplicable);
                Assert.Null(credentialResponse2.Credentials);
            }
        }
Exemplo n.º 15
0
        private async Task <PluginCreationResult> CreatePluginAsync(PluginDiscoveryResult result, PluginRequestKey requestKey, string packageSourceRepository, JObject serviceIndex, CancellationToken cancellationToken)
        {
            PluginCreationResult pluginCreationResult = null;

            if (result.PluginFile.State == PluginFileState.Valid)
            {
                var plugin = await _pluginFactory.GetOrCreateAsync(
                    result.PluginFile.Path,
                    PluginConstants.PluginArguments,
                    new RequestHandlers(),
                    _connectionOptions,
                    cancellationToken);

                var utilities = await PerformOneTimePluginInitializationAsync(plugin, cancellationToken);

                plugin.Connection.ProtocolVersion.Equals(Plugins.ProtocolConstants.CurrentVersion);

                var lazyOperationClaims = _pluginOperationClaims.GetOrAdd(
                    requestKey,
                    key => new Lazy <Task <IReadOnlyList <OperationClaim> > >(() =>
                                                                              GetPluginOperationClaimsAsync(
                                                                                  plugin,
                                                                                  packageSourceRepository,
                                                                                  serviceIndex,
                                                                                  cancellationToken)));

                await lazyOperationClaims.Value;

                pluginCreationResult = new PluginCreationResult(
                    plugin,
                    utilities.Value,
                    lazyOperationClaims.Value.Result);
            }
            else
            {
                pluginCreationResult = new PluginCreationResult(result.Message);
            }

            return(pluginCreationResult);
        }
        public async Task GetAsync_WhenCalledMultipleTimes_DoesNotCreateMultipleInstancesOfANonCredentialsPlugin()
        {
            var expectation = new TestExpectation(
                operationClaims: new[] { OperationClaim.DownloadPackage },
                connectionOptions: ConnectionOptions.CreateDefault(),
                pluginVersion: ProtocolConstants.CurrentVersion,
                uri: _uri,
                authenticationUsername: _username,
                authenticationPassword: _password,
                success: false);

            using (var test = new PluginManagerMock(
                       pluginFilePath: "a",
                       pluginFileState: PluginFileState.Valid,
                       expectations: expectation))
            {
                var discoveryResult = new PluginDiscoveryResult(new PluginFile("a", new Lazy <PluginFileState>(() => PluginFileState.Valid)));
                var provider        = new SecurePluginCredentialProvider(test.PluginManager, discoveryResult, canShowDialog: true, logger: NullLogger.Instance);

                IWebProxy proxy              = null;
                var       credType           = CredentialRequestType.Unauthorized;
                var       message            = "nothing";
                var       isRetry            = false;
                var       isInteractive      = false;
                var       token              = CancellationToken.None;
                var       credentialResponse = await provider.GetAsync(_uri, proxy, credType, message, isRetry, isInteractive, token);

                Assert.True(credentialResponse.Status == CredentialStatus.ProviderNotApplicable);
                Assert.Null(credentialResponse.Credentials);

                var credentialResponse2 = await provider.GetAsync(_uri, proxy, credType, message, isRetry, isInteractive, token);

                Assert.True(credentialResponse2.Status == CredentialStatus.ProviderNotApplicable);
                Assert.Null(credentialResponse2.Credentials);
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Creates a plugin from the given pluginDiscoveryResult.
        /// This plugin's operations will be source agnostic ones (Authentication)
        /// </summary>
        /// <param name="pluginDiscoveryResult">plugin discovery result</param>
        /// <param name="requestedOperationClaim">The requested operation claim</param>
        /// <param name="cancellationToken">cancellation token</param>
        /// <returns>A plugin creation result, null if the requested plugin cannot handle the given operation claim</returns>
        public Task <Tuple <bool, PluginCreationResult> > TryGetSourceAgnosticPluginAsync(PluginDiscoveryResult pluginDiscoveryResult, OperationClaim requestedOperationClaim, CancellationToken cancellationToken)
        {
            if (pluginDiscoveryResult == null)
            {
                throw new ArgumentNullException(nameof(pluginDiscoveryResult));
            }

            return(TryCreatePluginAsync(
                       pluginDiscoveryResult,
                       requestedOperationClaim,
                       new PluginRequestKey(pluginDiscoveryResult.PluginFile.Path, "Source-Agnostic"),
                       packageSourceRepository: null,
                       serviceIndex: null,
                       cancellationToken: cancellationToken));
        }