diff --git a/build/Dockerfile b/build/Dockerfile index b301591833e..c281147ddd5 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -69,6 +69,7 @@ EXPOSE 5000 ENV General__ValidInstancePaths__0 /tgs_instances ENV FileLogging__Directory /tgs_logs +ENV Internal__UsingDocker true WORKDIR /app diff --git a/src/Tgstation.Server.Host/Components/InstanceManager.cs b/src/Tgstation.Server.Host/Components/InstanceManager.cs index c86f5c8eded..5f6a101260c 100644 --- a/src/Tgstation.Server.Host/Components/InstanceManager.cs +++ b/src/Tgstation.Server.Host/Components/InstanceManager.cs @@ -130,6 +130,11 @@ sealed class InstanceManager : /// readonly SwarmConfiguration swarmConfiguration; + /// + /// The for the . + /// + readonly InternalConfiguration internalConfiguration; + /// /// The for . /// @@ -177,6 +182,7 @@ sealed class InstanceManager : /// The value of . /// The containing the value of . /// The containing the value of . + /// The containing the value of . /// The value of . public InstanceManager( IInstanceFactory instanceFactory, @@ -193,6 +199,7 @@ public InstanceManager( IPlatformIdentifier platformIdentifier, IOptions generalConfigurationOptions, IOptions swarmConfigurationOptions, + IOptions internalConfigurationOptions, ILogger logger) { this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory)); @@ -209,6 +216,7 @@ public InstanceManager( this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier)); generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions)); swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions)); + internalConfiguration = internalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(internalConfigurationOptions)); this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); originalConsoleTitle = console.Title; @@ -675,6 +683,11 @@ void CheckSystemCompatibility() { if (!systemIdentity.CanCreateSymlinks) throw new InvalidOperationException($"The user running {Constants.CanonicalPackageName} cannot create symlinks! Please try running as an administrative user!"); + + if (!platformIdentifier.IsWindows && systemIdentity.IsSuperUser && !internalConfiguration.UsingDocker) + { + logger.LogWarning("TGS is being run as the root account. This is not recommended."); + } } // This runs before the real socket is opened, ensures we don't perform reattaches unless we're fairly certain the bind won't fail diff --git a/src/Tgstation.Server.Host/Configuration/InternalConfiguration.cs b/src/Tgstation.Server.Host/Configuration/InternalConfiguration.cs index 58f2ad4720b..1d2723e26db 100644 --- a/src/Tgstation.Server.Host/Configuration/InternalConfiguration.cs +++ b/src/Tgstation.Server.Host/Configuration/InternalConfiguration.cs @@ -25,6 +25,11 @@ public sealed class InternalConfiguration /// public bool UsingSystemD { get; set; } + /// + /// If the server is running inside of a Docker container. + /// + public bool UsingDocker { get; set; } + /// /// The base path for the app settings configuration files. /// diff --git a/src/Tgstation.Server.Host/Security/ISystemIdentity.cs b/src/Tgstation.Server.Host/Security/ISystemIdentity.cs index bd63d784dea..f976066e50a 100644 --- a/src/Tgstation.Server.Host/Security/ISystemIdentity.cs +++ b/src/Tgstation.Server.Host/Security/ISystemIdentity.cs @@ -24,6 +24,12 @@ public interface ISystemIdentity : IDisposable /// bool CanCreateSymlinks { get; } + /// + /// Is this identity a SuperUser for the OS. + /// See Administrator on Windows or root on Linux. + /// + bool IsSuperUser { get; } + /// /// Clone the creating another copy that must have called on it. /// diff --git a/src/Tgstation.Server.Host/Security/PosixSystemIdentity.cs b/src/Tgstation.Server.Host/Security/PosixSystemIdentity.cs index 67f0e3ac838..ea8e23d3e84 100644 --- a/src/Tgstation.Server.Host/Security/PosixSystemIdentity.cs +++ b/src/Tgstation.Server.Host/Security/PosixSystemIdentity.cs @@ -2,6 +2,8 @@ using System.Threading; using System.Threading.Tasks; +using Mono.Unix.Native; + namespace Tgstation.Server.Host.Security { /// @@ -9,6 +11,9 @@ namespace Tgstation.Server.Host.Security /// sealed class PosixSystemIdentity : ISystemIdentity { + /// + public bool IsSuperUser => Syscall.getuid() == 0; + /// public string Uid => throw new NotImplementedException(); diff --git a/src/Tgstation.Server.Host/Security/WindowsSystemIdentity.cs b/src/Tgstation.Server.Host/Security/WindowsSystemIdentity.cs index 136c3c24e7e..609f33d2a28 100644 --- a/src/Tgstation.Server.Host/Security/WindowsSystemIdentity.cs +++ b/src/Tgstation.Server.Host/Security/WindowsSystemIdentity.cs @@ -22,7 +22,10 @@ sealed class WindowsSystemIdentity : ISystemIdentity public string Username => userPrincipal?.Name ?? identity!.Name; /// - public bool CanCreateSymlinks => canCreateSymlinks ?? throw new NotSupportedException(); + public bool CanCreateSymlinks => IsSuperUser; + + /// + public bool IsSuperUser => isAdmin ?? throw new NotSupportedException(); /// /// The for the . @@ -35,9 +38,9 @@ sealed class WindowsSystemIdentity : ISystemIdentity readonly UserPrincipal? userPrincipal; /// - /// Backing field for . + /// Backing field for . /// - readonly bool? canCreateSymlinks; + readonly bool? isAdmin; /// /// Initializes a new instance of the class. @@ -49,7 +52,7 @@ public WindowsSystemIdentity(WindowsIdentity identity) if (identity.IsAnonymous) throw new ArgumentException($"Cannot use anonymous {nameof(WindowsIdentity)} as a {nameof(WindowsSystemIdentity)}!", nameof(identity)); - canCreateSymlinks = new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator); + isAdmin = new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator); } ///