예제 #1
0
        public async Task <JObject> GetReadableAccessorAsync(OutputObjectAccessorRequest accessorRequest)
        {
            var urlRequest = CreateUrlRequest(accessorRequest);
            var url        = await urlProvider.GetReadableUrlAsync(urlRequest);

            if (!string.IsNullOrEmpty(accessorRequest.SignatureRsaKeyXml))
            {
                url.Signature = await urlSigner.GenerateSignatureAsync(accessorRequest.SignatureRsaKeyXml, url);
            }

            return(JObject.FromObject(url));
        }
        public Task <string> GenerateSignatureAsync(string rsaKeyXml, HttpExecutionRequest toSign)
        {
            if (string.IsNullOrEmpty(rsaKeyXml))
            {
                throw new ArgumentNullException(nameof(rsaKeyXml));
            }

            if (toSign == null)
            {
                throw new ArgumentNullException(nameof(toSign));
            }

            // Convert the execution request to a canonical string.
            // TODO: Document this string format so that target extensions can verify execution request signatures.

            var toSignAsString =
                $"{toSign.ExecutionId}|" +
                $"{toSign.ExecutionProfileName}|" +
                $"{toSign.ExtensionId}|" +
                $"{toSign.ExtensionVersionId}|" +
                $"{toSign.StatusUpdateKey}|" +
                $"{toSign.GetExecutionStatusUrl}|" +
                $"{toSign.UpdateExecutionStatusUrl}";

            // Use the generic string signer to sign the canonical execution request string.

            return(stringSigner.GenerateSignatureAsync(rsaKeyXml, toSignAsString));
        }
예제 #3
0
        public Task <string> GenerateSignatureAsync(string rsaKeyXml, ObjectUrl toSign)
        {
            if (string.IsNullOrEmpty(rsaKeyXml))
            {
                throw new ArgumentNullException(nameof(rsaKeyXml));
            }

            if (toSign == null)
            {
                throw new ArgumentNullException(nameof(toSign));
            }

            return(stringSigner.GenerateSignatureAsync(rsaKeyXml, toSign.Url));
        }
예제 #4
0
        private async Task <DirectExecutionRequestApiModel> CreateDirectExecutionRequestAsync(IExecutionRequestContext erContext)
        {
            // Convert the API request context to a core execution request...

            var execRequest = ToExecutionRequestAsync(erContext);

            // Then, convert the core execution request into a direct execution token...

            var directExecRequest = new DirectExecutionRequestApiModel
            {
                ExecutionId           = execRequest.ExecutionId,
                ExecutionModelName    = execRequest.ExecutionModelName,
                ExecutionProfileName  = execRequest.ExecutionProfileName,
                ExecutionSettings     = execRequest.ExtensionSettings,
                ExtensionId           = execRequest.ExtensionId,
                ExtensionVersionId    = execRequest.ExtensionVersionId,
                GetExecutionStatusUrl = execRequest.GetExecutionStatusUrl,
                ObjectProviderName    = execRequest.ObjectProviderName,
                ExecutorProperties    = execRequest.ExecutorProperties,
                Services = await execServiceProvider.GetServiceConfigurationAsync(execRequest)
            };

            // Based on the selected execution profile, set the expiration date/time (how long the client can use the extension directly for)
            // and digitally sign the execution request using the hub's private key. In this model, we assume that the target execution has the hub's
            // public key and can us it to verify the authenticity of the token and all the information contained therein.
            // For more information, see /doc/architecture/direct-execution.md.

            directExecRequest.ExpirationDateTimeUtc = DateTime.UtcNow.Add(erContext.ExecutionProfile.DirectExecutionTokenDuration.Value);
            directExecRequest.Signature             = await directExecRequestSigner.GenerateSignatureAsync(execRequest.SignatureRsaKeyXml, directExecRequest);

            // Update the execution to indicate that a direct access token is being provided...

            erContext.Execution.ExecutionTimeoutDateTimeUtc = directExecRequest.ExpirationDateTimeUtc;
            erContext.Execution.Status = ExecutionStatus.DirectExecutionTokenProvided;
            erContext.Execution.LastUpdatedDateTimeUtc = DateTime.UtcNow;

            // Persist the execution and return the direct execution token...

            await UpdateExecutionAsync(erContext.Execution);

            return(directExecRequest);
        }
예제 #5
0
        public Task <string> GenerateSignatureAsync(string rsaKeyXml, DirectExecutionRequestApiModel toSign)
        {
            if (string.IsNullOrEmpty(rsaKeyXml))
            {
                throw new ArgumentNullException(nameof(rsaKeyXml));
            }

            if (toSign == null)
            {
                throw new ArgumentNullException(nameof(toSign));
            }

            var apiModelString =
                $"{toSign.ExecutionId}|" +
                $"{toSign.ExtensionId}|" +
                $"{toSign.ExtensionVersionId}|" +
                $"{toSign.ExecutionModelName}|" +
                $"{toSign.ExecutionProfileName}|" +
                $"{toSign.ObjectProviderName}|" +
                $"{toSign.GetExecutionStatusUrl}|" +
                $"{toSign.ExpirationDateTimeUtc.ToString("s")}";

            return(stringSigner.GenerateSignatureAsync(rsaKeyXml, apiModelString));
        }
예제 #6
0
        public async Task <Core.Models.ExecutionContext> ExecuteAsync(ExecutionRequest execRequest, CancellationToken cancelToken)
        {
            if (execRequest == null)
            {
                throw new ArgumentNullException(nameof(execRequest));
            }

            logger.LogInformation($"Processing execution request [{execRequest.ExecutionId}]...");

            // Give all the applicable extension services a chance to do any synchronous pre-work ahead of the actual execution...
            // For more information on extension services, see /doc/architecture/extension-services.md.

            await(execRequest.ValidateOnly ?
                  this.execServiceProvider.OnValidatingAsync(execRequest) :
                  this.execServiceProvider.OnExecutingAsync(execRequest));

            // UTC now + the execution timeout on the execution request if it was provided.
            // If no execution timeout was defined, default to an hour [defaultTimeoutPeriod].

            execRequest.CalculateExecutionTimeoutDateTimeUtc(defaultTimeoutPeriod);

            logger.LogDebug($"Execution [{execRequest.ExecutionId}] timeout set to [{execRequest.ExecutionTimeoutDateTimeUtc}] UTC.");

            // We're about to execution the extension. Create an execution context to capture the results...

            var execContext = execRequest.ToExecutionContext();

            try
            {
                // Deserialize the execution model-specific settings, provided in the [execRequest.extensionSettings] JSON object property,
                // to get the execution and/or validation URLs that we need to handle the request.

                var httpSettings = GetHttpExtensionSettings(execRequest);

                // Create the execution request that we'll POST to the extension...

                var httpExecRequest = await ToHttpExecutionRequestAsync(execRequest);

                logger.LogDebug($"Execution [{execRequest.ExecutionId}] URL is [{httpSettings.ExecutionUrl}].");

                logger.LogDebug(string.IsNullOrEmpty(httpSettings.ValidationUrl) ?
                                $"Execution [{execRequest.ExecutionId}] validation URL is [{httpSettings.ValidationUrl}]." :
                                $"Execution [{execRequest.ExecutionId}] validation URL not provided.");

                // If there was a valid RSA public/private key pair provided along with the request,
                // sign the request before we send it along to the extension...

                if (!string.IsNullOrEmpty(execRequest.SignatureRsaKeyXml))
                {
                    logger.LogDebug($"Signing execution request [{execRequest.ExecutionId}]...");

                    httpExecRequest.Signature = await httpExecRequestSigner.GenerateSignatureAsync(execRequest.SignatureRsaKeyXml, httpExecRequest);
                }

                if (execRequest.ValidateOnly)
                {
                    // If it's a validation only request, make sure that the extension actually supports validation.
                    // Under normal circumstances, this should have been caught way further upstream at the execution API.

                    if (execRequest.IsValidationSupported == false)
                    {
                        throw new NotSupportedException($"Extension [{execRequest.ExtensionId}:{execRequest.ExtensionVersionId}] " +
                                                        "does not support validation.");
                    }

                    // Validate the request...

                    execContext = await ValidateAsync(execContext, httpExecRequest, httpSettings);
                }
                else
                {
                    // Execute the request...

                    execContext = await ExecuteAsync(execContext, httpExecRequest, httpSettings);
                }
            }
            catch (Exception ex)
            {
                logger.LogError($"An error occurred while processing execution request [{execRequest.ExecutionId}]: [{ex.Message}].");

                execContext.UpdateStatus(ExecutionStatus.Failed);
            }
            finally
            {
                // Give all the applicable extension services a chance to do any synchronous post-work after the execution
                // regardless of whether or not it succeeded. For more information on extension services, see /doc/architecture/extension-services.md.

                await(execRequest.ValidateOnly ?
                      this.execServiceProvider.OnValidatedAsync(execContext) :
                      this.execServiceProvider.OnExecutedAsync(execContext));

                logger.LogInformation($"Execution request [{execRequest.ExecutionId}] processing complete.");
            }

            return(execContext);
        }