using System.Reflection;
using System.Security.Cryptography;
using System.Text;
namespace MoShiro.Backend.Api;
///
/// 一行安装脚本:packaging/install/ 下的 install.sh 和 install.ps1 作为嵌入资源打进 Backend,原样返回,不替换任何值。
/// 静态,所以它的 SHA-256 在一个版本内固定:CI 构建时算出来写进签名的发布清单,面板给的命令先核对哈希再执行(docs/security/access.md 第 10 节)。
/// 角色、面板地址、代码都走命令里的环境变量。
///
public static class InstallScripts
{
public const string Sh = "install.sh";
public const string Ps1 = "install.ps1";
/// CI 的发布公钥(packaging/update/release-key.pub.pem):脚本里内置的就是这一把,测试核对两边一致。
public static string ReleaseKey() => Read("release-key.pub.pem").Trim();
public static string Script(string resource) => Read(resource);
/// compose 文件的资源名(agent.yaml、probe.yaml、backend.yaml 对应的);不是这三个就是 null。
public static string? ComposeResource(string file) => file is "agent.yaml" or "probe.yaml" or "backend.yaml" ? "compose-" + file : null;
/// 某个角色(agent、probe)的 compose 文件的 SHA-256;其他角色返回空。
public static string ComposeSha256(string? role) => role is "agent" or "probe" ? Sha256("compose-" + role + ".yaml") : string.Empty;
/// Quadlet 单元的资源名(agent.container、probe.container);不是这两个就是 null。
public static string? QuadletResource(string file) => file is "agent.container" or "probe.container" ? "quadlet-" + file : null;
/// 某个角色(agent、probe)的 Quadlet 单元的 SHA-256;其他角色返回空。
public static string QuadletSha256(string? role) => role is "agent" or "probe" ? Sha256("quadlet-" + role + ".container") : string.Empty;
/// 脚本内容的 SHA-256(小写十六进制,按 UTF-8 字节)。
public static string Sha256(string resource) => Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(Read(resource))));
private static string Read(string resource)
{
using Stream stream = typeof(InstallScripts).Assembly.GetManifestResourceStream(resource)
?? throw new InvalidOperationException($"the embedded resource {resource} is missing");
using var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
}