MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Management.Automation.Internal;6using System.Text;7 8namespace System.Management.Automation9{10 /// <summary>11 /// Monad Logging in general is a two layer architecture. At the upper layer are the12 /// Msh Log Engine and Logging Api. At the lower layer is the Provider Interface13 /// and Log Providers. This architecture is adopted to achieve independency between14 /// Monad logging and logging details of different logging technology.15 ///16 /// This file implements the lower layer of the Monad Logging architecture.17 /// Upper layer of Msh Log architecture is implemented in MshLog.cs file.18 ///19 /// This class defines the provider interface to be implemented by each providers.20 ///21 /// Provider Interface.22 ///23 /// Corresponding to 5 categories of logging api interface, provider interface provides24 /// functions for logging25 /// a. EngineHealthEvent26 /// b. EngineLifecycleEvent27 /// c. CommandLifecycleEvent28 /// d. ProviderLifecycleEvent29 /// e. SettingsEvent.30 /// </summary>31 internal abstract class LogProvider32 {33 /// <summary>34 /// Constructor.35 /// </summary>36 internal LogProvider()37 {38 }39 40 #region Provider api41 42 /// <summary>43 /// Provider interface function for logging health event.44 /// </summary>45 /// <param name="logContext"></param>46 /// <param name="eventId"></param>47 /// <param name="exception"></param>48 /// <param name="additionalInfo"></param>49 internal abstract void LogEngineHealthEvent(LogContext logContext, int eventId, Exception exception, Dictionary<string, string> additionalInfo);50 51 /// <summary>52 /// Provider interface function for logging engine lifecycle event.53 /// </summary>54 /// <param name="logContext"></param>55 /// <param name="newState"></param>56 /// <param name="previousState"></param>57 internal abstract void LogEngineLifecycleEvent(LogContext logContext, EngineState newState, EngineState previousState);58 59 /// <summary>60 /// Provider interface function for logging command health event.61 /// </summary>62 /// <param name="logContext"></param>63 /// <param name="exception"></param>64 internal abstract void LogCommandHealthEvent(LogContext logContext, Exception exception);65 66 /// <summary>67 /// Provider interface function for logging command lifecycle event.68 /// </summary>69 /// <param name="getLogContext"></param>70 /// <param name="newState"></param>71 internal abstract void LogCommandLifecycleEvent(Func<LogContext> getLogContext, CommandState newState);72 73 /// <summary>74 /// Provider interface function for logging pipeline execution detail.75 /// </summary>76 /// <param name="logContext"></param>77 /// <param name="pipelineExecutionDetail"></param>78 internal abstract void LogPipelineExecutionDetailEvent(LogContext logContext, List<string> pipelineExecutionDetail);79 80 /// <summary>81 /// Provider interface function for logging provider health event.82 /// </summary>83 /// <param name="logContext"></param>84 /// <param name="providerName"></param>85 /// <param name="exception"></param>86 internal abstract void LogProviderHealthEvent(LogContext logContext, string providerName, Exception exception);87 88 /// <summary>89 /// Provider interface function for logging provider lifecycle event.90 /// </summary>91 /// <param name="logContext"></param>92 /// <param name="providerName"></param>93 /// <param name="newState"></param>94 internal abstract void LogProviderLifecycleEvent(LogContext logContext, string providerName, ProviderState newState);95 96 /// <summary>97 /// Provider interface function for logging settings event.98 /// </summary>99 /// <param name="logContext"></param>100 /// <param name="variableName"></param>101 /// <param name="value"></param>102 /// <param name="previousValue"></param>103 internal abstract void LogSettingsEvent(LogContext logContext, string variableName, string value, string previousValue);104 105 /// <summary>106 /// Provider interface function for logging AmsiUtil State event.107 /// </summary>108 /// <param name="state">This the action performed in AmsiUtil class, like init, scan, etc.</param>109 /// <param name="context">The amsiContext handled - Session pair.</param>110 internal abstract void LogAmsiUtilStateEvent(string state, string context);111 112 /// <summary>113 /// Provider interface function for logging WDAC query event.114 /// </summary>115 /// <param name="queryName">Name of the WDAC query.</param>116 /// <param name="fileName">Name of script file for policy query. Can be null value.</param>117 /// <param name="querySuccess">Query call succeed code.</param>118 /// <param name="queryResult">Result code of WDAC query.</param>119 internal abstract void LogWDACQueryEvent(120 string queryName,121 string fileName,122 int querySuccess,123 int queryResult);124 125 /// <summary>126 /// Provider interface function for logging WDAC audit event.127 /// </summary>128 /// <param name="title">Title of WDAC audit event.</param>129 /// <param name="message">WDAC audit event message.</param>130 /// <param name="fqid">FullyQualifiedId of WDAC audit event.</param>131 internal abstract void LogWDACAuditEvent(132 string title,133 string message,134 string fqid);135 136 /// <summary>137 /// True if the log provider needs to use logging variables.138 /// </summary>139 /// <returns></returns>140 internal virtual bool UseLoggingVariables()141 {142 return true;143 }144 145 #endregion146 147 #region Shared utilities148 149 private static class Strings150 {151 // The strings are stored in a different class to defer loading the resources until as late152 // as possible, e.g. if logging is never on, these strings won't be loaded.153 internal static readonly string LogContextSeverity = EtwLoggingStrings.LogContextSeverity;154 internal static readonly string LogContextHostName = EtwLoggingStrings.LogContextHostName;155 internal static readonly string LogContextHostVersion = EtwLoggingStrings.LogContextHostVersion;156 internal static readonly string LogContextHostId = EtwLoggingStrings.LogContextHostId;157 internal static readonly string LogContextHostApplication = EtwLoggingStrings.LogContextHostApplication;158 internal static readonly string LogContextEngineVersion = EtwLoggingStrings.LogContextEngineVersion;159 internal static readonly string LogContextRunspaceId = EtwLoggingStrings.LogContextRunspaceId;160 internal static readonly string LogContextPipelineId = EtwLoggingStrings.LogContextPipelineId;161 internal static readonly string LogContextCommandName = EtwLoggingStrings.LogContextCommandName;162 internal static readonly string LogContextCommandType = EtwLoggingStrings.LogContextCommandType;163 internal static readonly string LogContextScriptName = EtwLoggingStrings.LogContextScriptName;164 internal static readonly string LogContextCommandPath = EtwLoggingStrings.LogContextCommandPath;165 internal static readonly string LogContextSequenceNumber = EtwLoggingStrings.LogContextSequenceNumber;166 internal static readonly string LogContextUser = EtwLoggingStrings.LogContextUser;167 internal static readonly string LogContextConnectedUser = EtwLoggingStrings.LogContextConnectedUser;168 internal static readonly string LogContextTime = EtwLoggingStrings.LogContextTime;169 internal static readonly string LogContextShellId = EtwLoggingStrings.LogContextShellId;170 }171 172 /// <summary>173 /// Gets PSLogUserData from execution context.174 /// </summary>175 /// <param name="context"></param>176 /// <returns></returns>177 protected static string GetPSLogUserData(ExecutionContext context)178 {179 if (context == null)180 {181 return string.Empty;182 }183 184 object logData = context.GetVariableValue(SpecialVariables.PSLogUserDataPath);185 186 if (logData == null)187 {188 return string.Empty;189 }190 191 return logData.ToString();192 }193 194 /// <summary>195 /// Appends exception information.196 /// </summary>197 /// <param name="sb">String builder.</param>198 /// <param name="except">Exception.</param>199 protected static void AppendException(StringBuilder sb, Exception except)200 {201 sb.AppendLine(StringUtil.Format(EtwLoggingStrings.ErrorRecordMessage, except.Message));202 203 if (except is IContainsErrorRecord ier)204 {205 ErrorRecord er = ier.ErrorRecord;206 207 if (er != null)208 {209 sb.AppendLine(StringUtil.Format(EtwLoggingStrings.ErrorRecordId, er.FullyQualifiedErrorId));210 211 ErrorDetails details = er.ErrorDetails;212 213 if (details != null)214 {215 sb.AppendLine(StringUtil.Format(EtwLoggingStrings.ErrorRecordRecommendedAction, details.RecommendedAction));216 }217 }218 }219 }220 221 /// <summary>222 /// Appends additional information.223 /// </summary>224 /// <param name="sb">String builder.</param>225 /// <param name="additionalInfo">Additional information.</param>226 protected static void AppendAdditionalInfo(StringBuilder sb, Dictionary<string, string> additionalInfo)227 {228 if (additionalInfo != null)229 {230 foreach (KeyValuePair<string, string> value in additionalInfo)231 {232 sb.AppendLine(StringUtil.Format("{0} = {1}", value.Key, value.Value));233 }234 }235 }236 237 /// <summary>238 /// Gets PSLevel from severity.239 /// </summary>240 /// <param name="severity">Error severity.</param>241 /// <returns>PS log level.</returns>242 protected static PSLevel GetPSLevelFromSeverity(string severity)243 {244 switch (severity)245 {246 case "Critical":247 case "Error":248 return PSLevel.Error;249 case "Warning":250 return PSLevel.Warning;251 default:252 return PSLevel.Informational;253 }254 }255 256 // Estimate an approximate size to use for the StringBuilder in LogContextToString257 // Estimated length of all Strings.* values258 // Rough estimate of values259 // max path for Command path260 private const int LogContextInitialSize = 30 * 16 + 13 * 20 + 255;261 262 /// <summary>263 /// Converts log context to string.264 /// </summary>265 /// <param name="context">Log context.</param>266 /// <returns>String representation.</returns>267 protected static string LogContextToString(LogContext context)268 {269 StringBuilder sb = new StringBuilder(LogContextInitialSize);270 271 sb.Append(Strings.LogContextSeverity);272 sb.AppendLine(context.Severity);273 sb.Append(Strings.LogContextHostName);274 sb.AppendLine(context.HostName);275 sb.Append(Strings.LogContextHostVersion);276 sb.AppendLine(context.HostVersion);277 sb.Append(Strings.LogContextHostId);278 sb.AppendLine(context.HostId);279 sb.Append(Strings.LogContextHostApplication);280 sb.AppendLine(context.HostApplication);281 sb.Append(Strings.LogContextEngineVersion);282 sb.AppendLine(context.EngineVersion);283 sb.Append(Strings.LogContextRunspaceId);284 sb.AppendLine(context.RunspaceId);285 sb.Append(Strings.LogContextPipelineId);286 sb.AppendLine(context.PipelineId);287 sb.Append(Strings.LogContextCommandName);288 sb.AppendLine(context.CommandName);289 sb.Append(Strings.LogContextCommandType);290 sb.AppendLine(context.CommandType);291 sb.Append(Strings.LogContextScriptName);292 sb.AppendLine(context.ScriptName);293 sb.Append(Strings.LogContextCommandPath);294 sb.AppendLine(context.CommandPath);295 sb.Append(Strings.LogContextSequenceNumber);296 sb.AppendLine(context.SequenceNumber);297 sb.Append(Strings.LogContextUser);298 sb.AppendLine(context.User);299 sb.Append(Strings.LogContextConnectedUser);300 sb.AppendLine(context.ConnectedUser);301 sb.Append(Strings.LogContextShellId);302 sb.AppendLine(context.ShellId);303 304 return sb.ToString();305 }306 307 #endregion308 }309 310 /// <summary>311 /// </summary>312 internal class DummyLogProvider : LogProvider313 {314 /// <summary>315 /// Constructor.316 /// </summary>317 internal DummyLogProvider()318 {319 }320 321 #region Provider api322 323 /// <summary>324 /// DummyLogProvider does nothing to Logging EngineHealthEvent.325 /// </summary>326 /// <param name="logContext"></param>327 /// <param name="eventId"></param>328 /// <param name="exception"></param>329 /// <param name="additionalInfo"></param>330 internal override void LogEngineHealthEvent(LogContext logContext, int eventId, Exception exception, Dictionary<string, string> additionalInfo)331 {332 }333 334 /// <summary>335 /// DummyLogProvider does nothing to Logging EngineLifecycleEvent.336 /// </summary>337 /// <param name="logContext"></param>338 /// <param name="newState"></param>339 /// <param name="previousState"></param>340 internal override void LogEngineLifecycleEvent(LogContext logContext, EngineState newState, EngineState previousState)341 {342 }343 344 /// <summary>345 /// Provider interface function for logging command health event.346 /// </summary>347 /// <param name="logContext"></param>348 /// <param name="exception"></param>349 internal override void LogCommandHealthEvent(LogContext logContext, Exception exception)350 {351 }352 353 /// <summary>354 /// DummyLogProvider does nothing to Logging CommandLifecycleEvent.355 /// </summary>356 /// <param name="getLogContext"></param>357 /// <param name="newState"></param>358 internal override void LogCommandLifecycleEvent(Func<LogContext> getLogContext, CommandState newState)359 {360 }361 362 /// <summary>363 /// DummyLogProvider does nothing to Logging PipelineExecutionDetailEvent.364 /// </summary>365 /// <param name="logContext"></param>366 /// <param name="pipelineExecutionDetail"></param>367 internal override void LogPipelineExecutionDetailEvent(LogContext logContext, List<string> pipelineExecutionDetail)368 {369 }370 371 /// <summary>372 /// Provider interface function for logging provider health event.373 /// </summary>374 /// <param name="logContext"></param>375 /// <param name="providerName"></param>376 /// <param name="exception"></param>377 internal override void LogProviderHealthEvent(LogContext logContext, string providerName, Exception exception)378 {379 }380 381 /// <summary>382 /// DummyLogProvider does nothing to Logging ProviderLifecycleEvent.383 /// </summary>384 /// <param name="logContext"></param>385 /// <param name="providerName"></param>386 /// <param name="newState"></param>387 internal override void LogProviderLifecycleEvent(LogContext logContext, string providerName, ProviderState newState)388 {389 }390 391 /// <summary>392 /// DummyLogProvider does nothing to Logging SettingsEvent.393 /// </summary>394 /// <param name="logContext"></param>395 /// <param name="variableName"></param>396 /// <param name="value"></param>397 /// <param name="previousValue"></param>398 internal override void LogSettingsEvent(LogContext logContext, string variableName, string value, string previousValue)399 {400 }401 402 /// <summary>403 /// Provider interface function for logging provider health event.404 /// </summary>405 /// <param name="state">This the action performed in AmsiUtil class, like init, scan, etc.</param>406 /// <param name="context">The amsiContext handled - Session pair.</param>407 internal override void LogAmsiUtilStateEvent(string state, string context)408 {409 }410 411 /// <summary>412 /// Provider interface function for logging WDAC query event.413 /// </summary>414 /// <param name="queryName">Name of the WDAC query.</param>415 /// <param name="fileName">Name of script file for policy query. Can be null value.</param>416 /// <param name="querySuccess">Query call succeed code.</param>417 /// <param name="queryResult">Result code of WDAC query.</param>418 internal override void LogWDACQueryEvent(419 string queryName,420 string fileName,421 int querySuccess,422 int queryResult)423 {424 }425 426 /// <summary>427 /// Provider interface function for logging WDAC audit event.428 /// </summary>429 /// <param name="title">Title of WDAC audit event.</param>430 /// <param name="message">WDAC audit event message.</param>431 /// <param name="fqid">FullyQualifiedId of WDAC audit event.</param>432 internal override void LogWDACAuditEvent(433 string title,434 string message,435 string fqid)436 {437 }438 439 #endregion440 }441}442 