Beispiel #1
0
        public IActionResult GetDscAction(GetDscActionRequest input)
        {
            if (_logger.IsEnabled(LogLevel.Trace))
            {
                _logger.LogTrace($"{nameof(GetDscAction)}:  {GetDscActionRequest.VERB}");
            }

            if (ModelState.IsValid)
            {
                _logger.LogDebug($"AgentId=[{input.AgentId}]");

                var actionInfo = _dscHandler.GetDscAction(input.AgentId.Value, input.Body);
                if (actionInfo == null)
                {
                    return(NotFound());
                }

                var response = new GetDscActionResponse
                {
                    Body = new GetDscActionResponseBody
                    {
                        NodeStatus = actionInfo.NodeStatus,
                        Details    = actionInfo.ConfigurationStatuses?.ToArray(),
                    }
                };

                return(this.Model(response));
            }

            return(base.BadRequest(ModelState));
        }
Beispiel #2
0
        public async Task <IEnumerable <ActionDetailsItem> > GetDscAction(IEnumerable <ClientStatusItem> clientStatus = null)
        {
            if (LOG.IsEnabled(LogLevel.Trace))
            {
                LOG.LogTrace(nameof(GetDscAction));
            }

            AssertInit();

            var serverConfig = Configuration.ConfigurationRepositoryServer;

            AssertServerConfig(serverConfig);

            if (clientStatus == null)
            {
                if (Configuration.ConfigurationNames != null)
                {
                    clientStatus = Configuration.ConfigurationNames.Select(x =>
                    {
                        return(new ClientStatusItem
                        {
                            ConfigurationName = x,
                            ChecksumAlgorithm = "SHA-256", // TODO: figure out this
                            Checksum = string.Empty,
                        });
                    });
                }
                else
                {
                    clientStatus = new[]
                    {
                        new ClientStatusItem
                        {
                            ConfigurationName = string.Empty,
                            ChecksumAlgorithm = "SHA-256", // TODO: figure out this
                            Checksum          = string.Empty,
                        }
                    };
                }
            }

            var dscRequ = new GetDscActionRequest
            {
                AgentId           = Configuration.AgentId,
                ContentTypeHeader = DscContentTypes.JSON,
                Body = new GetDscActionRequestBody
                {
                    ClientStatus = clientStatus?.ToArray()
                }
            };

            var dscResp = new GetDscActionResponse();

            using (var disposable = await SendDscAsync(serverConfig, GetDscActionRequest.VERB,
                                                       GetDscActionRequest.ROUTE, dscRequ, dscResp))
            {
                LOG.LogDebug("*********************************************************");
                LOG.LogDebug("DSC Action:  " + JsonConvert.SerializeObject(dscResp.Body,
                                                                           _jsonSerSettings));

                if (dscResp?.Body?.Details?.Length == 0)
                {
                    return(new[]
                    {
                        new ActionDetailsItem
                        {
                            ConfigurationName = string.Empty,
                            Status = (dscResp?.Body?.NodeStatus).GetValueOrDefault(),
                        }
                    });
                }

                return(dscResp.Body.Details);
            }
        }
Beispiel #3
0
        public async Task <IActionResult> GetDscAction(GetDscActionRequest input)
        {
            if (_logger.IsEnabled(LogLevel.Trace))
            {
                _logger.LogTrace($"{nameof(GetDscAction)}:  {GetDscActionRequest.VERB}");
            }

            if (!ModelState.IsValid)
            {
                return(base.BadRequest(ModelState));
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug($"AgentId=[{input.AgentId}]");
            }

            RegisterDscAgentRequestBody regInfo;

            var regS3Key = $"{_settings.S3KeyPrefixRegistrations}/{input.AgentId}.json";

            _logger.LogDebug($"registration S3 Key resolved as [{regS3Key}]");

            using (var getResp = await _s3.GetObjectAsync(_settings.S3Bucket, regS3Key))
            {
                if (getResp == null || getResp.ContentLength == 0 ||
                    getResp.HttpStatusCode != HttpStatusCode.OK)
                {
                    _logger.LogWarning($"failed to get existing registration:"
                                       + " contentLen=[{getResp?.ContentLength}]"
                                       + " httpStatus=[{getResp.HttpStatusCode}]");
                    throw new InvalidOperationException("unknown agent id");
                }

                using (var rs = getResp.ResponseStream)
                    using (var reader = new System.IO.StreamReader(rs))
                    {
                        regInfo = JsonConvert.DeserializeObject <RegisterDscAgentRequestBody>(
                            await reader.ReadToEndAsync());
                    }
            }

            var detail      = input.Body;
            var nodeStatus  = DscActionStatus.OK;
            var configCount = (int)regInfo.ConfigurationNames?.Count();

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug($"loaded registration info with config count[{configCount}]");
            }

            string configName;

            if (detail.ClientStatus.Length > 1)
            {
                // TODO:
                return(base.StatusCode((int)HttpStatusCode.NotImplemented,
                                       "multiple input client statuses not yet implemented"));
            }

            var clientStatus = detail.ClientStatus[0];

            if (string.IsNullOrEmpty(clientStatus.ConfigurationName))
            {
                if (regInfo.ConfigurationNames.Length == 0)
                {
                    _logger.LogWarning("no configuration specified in request and no configuration specified in registration");
                    configName = null;
                }
                else if (regInfo.ConfigurationNames.Length > 1)
                {
                    // TODO:
                    return(base.StatusCode((int)HttpStatusCode.NotImplemented,
                                           "multiple registered configurations not yet implemented"));
                }
                else
                {
                    configName = regInfo.ConfigurationNames[0];
                }
            }
            else
            {
                configName = clientStatus.ConfigurationName;
            }

            _logger.LogDebug($"configuration name resolved as [{configName}]");

            if (configName != null)
            {
                string checksum;
                var    cfgS3Key = $"{_settings.S3KeyPrefixConfigurations}/{configName}.mof";
                _logger.LogDebug($"configuration S3 Key resolved as [{cfgS3Key}]");

                // We can't simply try to get the S3 object that corresponds to the
                // config name being requested because if it doesn't exist, we see
                // Amazon.S3.AmazonS3Exception with an underlying message of Access Denied;
                // instead we try to list the object first, and if it's not there, we
                // can response to the node appropriately with our own error protocol
                var listResp = await _s3.ListObjectsV2Async(new ListObjectsV2Request
                {
                    BucketName = _settings.S3Bucket,
                    Prefix     = cfgS3Key,
                    MaxKeys    = 1,
                });

                var firstS3Obj = listResp.S3Objects?.FirstOrDefault();
                if (_logger.IsEnabled(LogLevel.Debug))
                {
                    _logger.LogDebug("Request to list S3 objects matching requested config found"
                                     + " [{s3KeyCount}] keys, first is [{s3Key}]", listResp.KeyCount,
                                     firstS3Obj?.Key);
                }

                if (listResp.KeyCount < 1 || firstS3Obj.Key != cfgS3Key)
                {
                    _logger.LogWarning($"failed to get configuration by object key [{cfgS3Key}]:");
                    return(NotFound());
                }

                using (var getResp = await _s3.GetObjectAsync(_settings.S3Bucket, cfgS3Key))
                {
                    if (getResp == null || getResp.ContentLength == 0 ||
                        getResp.HttpStatusCode != HttpStatusCode.OK)
                    {
                        _logger.LogWarning($"failed to get configuration by name [{cfgS3Key}]:"
                                           + " contentLen=[{getResp?.ContentLength}]"
                                           + " httpStatus=[{getResp.HttpStatusCode}]");
                        return(NotFound());
                    }

                    using (var rs = getResp.ResponseStream)
                    {
                        checksum = ComputeChecksum(rs);
                    }
                    _logger.LogDebug($"configuration checksum resolved as [{checksum}]");
                }

                if (string.IsNullOrEmpty(clientStatus.Checksum))
                {
                    // Doesn't matter what the real checksum is,
                    // node is asking for it, pby its first time
                    nodeStatus = DscActionStatus.GetConfiguration;
                    _logger.LogDebug("client status checksum is empty; forcing [{nodeStatus}] response");
                }
                else
                {
                    // Make sure we're speaking the same language
                    if (ChecksumAlgorithm != clientStatus.ChecksumAlgorithm)
                    {
                        _logger.LogWarning($"checksum algorithm mismatch [{clientStatus.ChecksumAlgorithm}]");
                        return(BadRequest("unsupported checksum algorithm"));
                    }

                    // We've resolved the config name
                    nodeStatus = checksum == clientStatus.Checksum
                            ? DscActionStatus.OK
                            : DscActionStatus.GetConfiguration;
                    _logger.LogDebug($"checksum comparison resolved as [{nodeStatus.ToString()}]");
                }
            }
            else
            {
                _logger.LogWarning("no configuration name could be resolved from client status or registration");
                nodeStatus = DscActionStatus.OK;
            }

            var response = new GetDscActionResponse
            {
                Body = new GetDscActionResponseBody
                {
                    NodeStatus = nodeStatus,
                    Details    = new [] { new ActionDetailsItem
                                          {
                                              ConfigurationName = configName,
                                              Status            = nodeStatus,
                                          } },
                }
            };

            return(this.Model(response));
        }