refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)
Solution + 23 src projects + 26 test projects renamed; folders, csproj, namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated. ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated. SQL roles/logins, LDAP domains, CLI command name, and CLI config dir (~/.scadalink → ~/.scadabridge) also renamed. Build green; 5 Host.Tests fail awaiting SQL login rename in next commit. Pre-existing StaleTagMonitor timing flakes unchanged. Rename script committed at tools/rename-to-scadabridge.sh.
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.TemplateEngine.Validation;
|
||||
|
||||
/// <summary>
|
||||
/// Validates script code by attempting to compile it using Roslyn.
|
||||
/// In production, this would compile C# scripts against a stub ScriptApi assembly
|
||||
/// that provides the allowed API surface (attribute read/write, CallScript, CallShared, etc.)
|
||||
/// and enforces the forbidden API list (System.IO, Process, Threading, Reflection, raw network).
|
||||
///
|
||||
/// For now, this implementation performs basic syntax validation.
|
||||
///
|
||||
/// <para>
|
||||
/// <b>SECURITY LIMITATION (TemplateEngine-006):</b> the forbidden-API check below
|
||||
/// is an interim, <i>advisory</i> text scan — it is NOT an authoritative trust-model
|
||||
/// boundary. <see cref="CSharpDelimiterScanner.ContainsInCode"/> removes the
|
||||
/// false-positive half (forbidden text inside a string/comment is ignored), but a
|
||||
/// determined script can still bypass the literal patterns via namespace aliases,
|
||||
/// <c>using static</c>, or <c>global::</c>-qualified references. Authoritative
|
||||
/// enforcement requires Roslyn semantic symbol analysis of the referenced
|
||||
/// types/namespaces and is the responsibility of the real script compiler and the
|
||||
/// Site Runtime sandbox. Do not rely on this class as the sole trust-model gate.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public class ScriptCompiler
|
||||
{
|
||||
/// <summary>
|
||||
/// Forbidden namespace patterns — scripts (and trigger expressions, via
|
||||
/// <see cref="ValidationService"/>) must not use these. Trigger expressions run
|
||||
/// under the same trust model as scripts, so the list is shared from here rather
|
||||
/// than duplicated.
|
||||
///
|
||||
/// <para>
|
||||
/// Matched with <see cref="CSharpDelimiterScanner.ContainsInCode"/> against code
|
||||
/// regions only. This is advisory — see the class summary's SECURITY LIMITATION
|
||||
/// note; the substring patterns are bypassable and the authoritative check is
|
||||
/// deferred to Roslyn semantic analysis.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
internal static readonly string[] ForbiddenPatterns =
|
||||
[
|
||||
"System.IO.",
|
||||
"System.Diagnostics.Process",
|
||||
"System.Threading.",
|
||||
"System.Reflection.",
|
||||
"System.Net.Sockets.",
|
||||
"System.Net.Http.",
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to compile a script and returns success or a compilation error.
|
||||
/// </summary>
|
||||
/// <param name="code">The C# script code.</param>
|
||||
/// <param name="scriptName">The canonical name of the script (for error messages).</param>
|
||||
/// <returns>Success if the script compiles, or Failure with the error message.</returns>
|
||||
public Result<bool> TryCompile(string code, string scriptName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
return Result<bool>.Failure($"Script '{scriptName}' has empty code.");
|
||||
|
||||
// Check for forbidden APIs. Advisory only (see class summary): the scan is
|
||||
// code-region-aware so forbidden text inside a string/comment is ignored,
|
||||
// but it remains a substring match and is not an authoritative boundary.
|
||||
foreach (var pattern in ForbiddenPatterns)
|
||||
{
|
||||
if (CSharpDelimiterScanner.ContainsInCode(code, pattern))
|
||||
{
|
||||
return Result<bool>.Failure(
|
||||
$"Script '{scriptName}' uses forbidden API: '{pattern.TrimEnd('.')}'. " +
|
||||
"Scripts cannot use System.IO, Process, Threading, Reflection, or raw network APIs.");
|
||||
}
|
||||
}
|
||||
|
||||
// Basic structural validation: balanced braces/brackets/parens. The scan
|
||||
// is string- and comment-aware (see CSharpDelimiterScanner) so a delimiter
|
||||
// inside a regular/verbatim/interpolated/raw string, a char literal, or a
|
||||
// comment does not produce a false mismatch. This remains an interim check
|
||||
// until the Roslyn-based compiler is wired in.
|
||||
var mismatch = CSharpDelimiterScanner.Scan(code);
|
||||
return mismatch switch
|
||||
{
|
||||
CSharpDelimiterScanner.Mismatch.None =>
|
||||
Result<bool>.Success(true),
|
||||
CSharpDelimiterScanner.Mismatch.UnexpectedCloseBrace =>
|
||||
Result<bool>.Failure($"Script '{scriptName}' has mismatched braces (unexpected closing brace)."),
|
||||
CSharpDelimiterScanner.Mismatch.UnclosedBrace =>
|
||||
Result<bool>.Failure($"Script '{scriptName}' has mismatched braces (unclosed opening brace)."),
|
||||
CSharpDelimiterScanner.Mismatch.UnexpectedCloseBracket =>
|
||||
Result<bool>.Failure($"Script '{scriptName}' has mismatched brackets (unexpected closing bracket)."),
|
||||
CSharpDelimiterScanner.Mismatch.UnclosedBracket =>
|
||||
Result<bool>.Failure($"Script '{scriptName}' has mismatched brackets (unclosed opening bracket)."),
|
||||
CSharpDelimiterScanner.Mismatch.UnexpectedCloseParen =>
|
||||
Result<bool>.Failure($"Script '{scriptName}' has mismatched parentheses (unexpected closing parenthesis)."),
|
||||
CSharpDelimiterScanner.Mismatch.UnclosedParen =>
|
||||
Result<bool>.Failure($"Script '{scriptName}' has mismatched parentheses (unclosed opening parenthesis)."),
|
||||
CSharpDelimiterScanner.Mismatch.UnclosedBlockComment =>
|
||||
Result<bool>.Failure($"Script '{scriptName}' has an unclosed block comment."),
|
||||
CSharpDelimiterScanner.Mismatch.UnterminatedString =>
|
||||
Result<bool>.Failure($"Script '{scriptName}' has an unterminated string literal."),
|
||||
CSharpDelimiterScanner.Mismatch.UnterminatedChar =>
|
||||
Result<bool>.Failure($"Script '{scriptName}' has an unterminated character literal."),
|
||||
_ => Result<bool>.Success(true),
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user