diff --git a/Lib/Neon.Kube.Setup/KubeSetup.Operations.cs b/Lib/Neon.Kube.Setup/KubeSetup.Operations.cs index fd497d584..e62714f78 100644 --- a/Lib/Neon.Kube.Setup/KubeSetup.Operations.cs +++ b/Lib/Neon.Kube.Setup/KubeSetup.Operations.cs @@ -5008,7 +5008,7 @@ await controlNode.InvokeIdempotentAsync("setup/harbor-login", await Task.CompletedTask; #if TODO - var user = await KubeHelper.GetClusterLdapUserAsync(k8s, "root"); + var user = await KubeHelper.GetClusterLdapUserAsync(k8s, KubeConst.SysAdminUser); var password = user.Password; var command = $"echo '{password}' | podman login registry.neon.local --username {user.Name} --password-stdin"; @@ -5034,7 +5034,7 @@ await controlNode.InvokeIdempotentAsync("setup/harbor-login", await controlNode.InvokeIdempotentAsync("setup/harbor-login-workstation", async () => { - var user = await KubeHelper.GetClusterLdapUserAsync(k8s, "root"); + var user = await KubeHelper.GetClusterLdapUserAsync(k8s, KubeConst.SysAdminUser); var password = user.Password; if (!string.IsNullOrEmpty(NeonHelper.DockerCli)) @@ -5046,8 +5046,7 @@ await controlNode.InvokeIdempotentAsync("setup/harbor-login-workstation", { "login", $"{ClusterHost.HarborRegistry}.{cluster.SetupState.ClusterDomain}", - "--username", - "root", + "--username", KubeConst.SysAdminUser, "--password-stdin" }, input: new StringReader(cluster.SetupState.SsoPassword)); @@ -5898,7 +5897,7 @@ public static async Task InstallGlauthAsync(ISetupController controller, NodeSsh values.Add("config.backend.database.user", KubeConst.NeonSystemDbServiceUser); values.Add("config.backend.database.password", dbPassword); - values.Add("users.root.password", cluster.SetupState.SsoPassword); + values.Add("users.sysadmin.password", cluster.SetupState.SsoPassword); values.Add("users.serviceuser.password", NeonHelper.GetCryptoRandomPassword(cluster.SetupState.ClusterDefinition.Security.PasswordLength)); if (serviceAdvice.PodMemoryRequest.HasValue && serviceAdvice.PodMemoryLimit.HasValue) diff --git a/Lib/Neon.Kube.Setup/KubeSetup.PrepareCluster.cs b/Lib/Neon.Kube.Setup/KubeSetup.PrepareCluster.cs index bda22eb43..eb119ed75 100644 --- a/Lib/Neon.Kube.Setup/KubeSetup.PrepareCluster.cs +++ b/Lib/Neon.Kube.Setup/KubeSetup.PrepareCluster.cs @@ -298,7 +298,7 @@ public static async Task CreateClusterPrepareControllerAsync( // // WARNING: This should never be used for production clusters! - setupState.SshPassword = KubeConst.SysAdminPassword; + setupState.SshPassword = KubeConst.SysAdminInsecurePassword; } else { @@ -326,9 +326,9 @@ public static async Task CreateClusterPrepareControllerAsync( if (desktopReadyToGo || options.Insecure) { - // We're going to configure a fixed password for NEONDESKTOP clusters. + // We're going to configure a fixed password for NEONDESKTOP and insecure clusters. - setupState.SshPassword = KubeConst.SysAdminPassword; + setupState.SshPassword = KubeConst.SysAdminInsecurePassword; } else { @@ -371,7 +371,7 @@ public static async Task CreateClusterPrepareControllerAsync( controller.SetGlobalStepStatus("generate: SSO password"); setupState.SsoUsername = KubeConst.SysAdminUser; - setupState.SsoPassword = clusterDefinition.RootPassword ?? NeonHelper.GetCryptoRandomPassword(clusterDefinition.Security.PasswordLength); + setupState.SsoPassword = clusterDefinition.SsoPassword ?? NeonHelper.GetCryptoRandomPassword(clusterDefinition.Security.PasswordLength); setupState.Save(); }); diff --git a/Lib/Neon.Kube.Setup/KubeSetup.cs b/Lib/Neon.Kube.Setup/KubeSetup.cs index c23ccb98d..b8563f655 100644 --- a/Lib/Neon.Kube.Setup/KubeSetup.cs +++ b/Lib/Neon.Kube.Setup/KubeSetup.cs @@ -194,7 +194,9 @@ public static ClusterDefinition GetDesktopClusterDefinition(HostingEnvironment h clusterDefinition.Hosting.Hypervisor.VCpus = 3; } - clusterDefinition.RootPassword = KubeConst.RootDesktopPassword; + // Use the insecure password for NeonDESKTOP clusters. + + clusterDefinition.SsoPassword = KubeConst.SysAdminInsecurePassword; return clusterDefinition; } diff --git a/Lib/Neon.Kube.Setup/Resources/Helm/glauth/templates/users.yaml b/Lib/Neon.Kube.Setup/Resources/Helm/glauth/templates/users.yaml index 8fb43b40f..64d919256 100644 --- a/Lib/Neon.Kube.Setup/Resources/Helm/glauth/templates/users.yaml +++ b/Lib/Neon.Kube.Setup/Resources/Helm/glauth/templates/users.yaml @@ -79,13 +79,13 @@ stringData: # This user record shows all of the possible fields available [[users]] - name = "root" - givenname="root" + name = "sysadmin" + givenname="sysadmin" sn="" mail = "sysadmin@{{ $clusterDomain }}" uidnumber = 5001 primarygroup = 5501 - passsha256 = "{{ .Values.users.root.password | sha256sum }}" # {{ .Values.users.root.password }} + passsha256 = "{{ .Values.users.sysadmin.password | sha256sum }}" # {{ .Values.users.sysadmin.password }} [[users]] name = "serviceuser" givenname="serviceuser" diff --git a/Lib/Neon.Kube.Setup/Resources/Helm/glauth/values.yaml b/Lib/Neon.Kube.Setup/Resources/Helm/glauth/values.yaml index 3b69a15b3..d85945622 100644 --- a/Lib/Neon.Kube.Setup/Resources/Helm/glauth/values.yaml +++ b/Lib/Neon.Kube.Setup/Resources/Helm/glauth/values.yaml @@ -109,8 +109,6 @@ config: enabled: false users: - root: - password: "" sysadmin: password: "" user: diff --git a/Lib/Neon.Kube/ClusterDef/ClusterDefinition.cs b/Lib/Neon.Kube/ClusterDef/ClusterDefinition.cs index 82b3f868a..b6ac2713f 100644 --- a/Lib/Neon.Kube/ClusterDef/ClusterDefinition.cs +++ b/Lib/Neon.Kube/ClusterDef/ClusterDefinition.cs @@ -617,14 +617,21 @@ internal bool IsSpecialNeonCluster public Dictionary NodeDefinitions { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); /// + /// /// Optionally specifies the cluster root single sign-on (SSO) password. A random password /// with of will be created by default when no /// password is specified here. + /// + /// + /// The NeonDESKTOP SSO cluster's SSO password is always set to + /// to make the cluster easier to use. This isn't a big security risk, because the desktop cluster is + /// not accessable from the LAN. + /// > /// - [JsonProperty(PropertyName = "RootPassword", Required = Required.Default)] - [YamlMember(Alias = "rootPassword", ApplyNamingConventions = false)] + [JsonProperty(PropertyName = "SsoPassword", Required = Required.Default)] + [YamlMember(Alias = "ssoPassword", ApplyNamingConventions = false)] [DefaultValue(null)] - public string RootPassword { get; set; } = null; + public string SsoPassword { get; set; } = null; /// /// Clones the current cluster definition and then removes any hosting related diff --git a/Lib/Neon.Kube/Kube/KubeHelper.cs b/Lib/Neon.Kube/Kube/KubeHelper.cs index a2ffae73e..3fb3d5a68 100644 --- a/Lib/Neon.Kube/Kube/KubeHelper.cs +++ b/Lib/Neon.Kube/Kube/KubeHelper.cs @@ -1957,9 +1957,9 @@ private static string GetSshKeyGenPath() /// Creates a SSH key for a NEONKUBE cluster. /// /// The cluster name. - /// Optionally specifies the user name (defaults to root). + /// Specifies the user name. /// A holding the public and private parts of the key. - public static KubeSshKey GenerateSshKey(string clusterName, string userName = "root") + public static KubeSshKey GenerateSshKey(string clusterName, string userName) { Covenant.Requires(!string.IsNullOrEmpty(clusterName), nameof(clusterName)); Covenant.Requires(!string.IsNullOrEmpty(userName), nameof(userName)); diff --git a/Lib/Neon.Kube/KubeConst.cs b/Lib/Neon.Kube/KubeConst.cs index 860ea0994..b376ad85b 100644 --- a/Lib/Neon.Kube/KubeConst.cs +++ b/Lib/Neon.Kube/KubeConst.cs @@ -49,94 +49,87 @@ public static class KubeConst public static readonly TimeSpan MaxJitter = TimeSpan.FromMilliseconds(250); /// - /// The maximum number of cluster control-plane nodes. + /// Specifies the maximum number of cluster control-plane nodes. /// public const int MaxControlPlaneNodes = 5; /// - /// The minimum number of vCPUs required by control-plane nodes. + /// Specifies the minimum number of vCPUs required by control-plane nodes. /// public const int MinControlNodeVCpus = 2; /// - /// The minimum number of vCPUs required by worker nodes. + /// Specifies the minimum number of vCPUs required by worker nodes. /// public const int MinWorkerNodeVCpus = 4; /// - /// The minimum RAM (MiB) required for control-plane nodes. + /// Specifies the minimum RAM (MiB) required for control-plane nodes. /// public const int MinControlPlaneNodeRamMiB = 8192; /// - /// The minimum RAM (MiB) required for worker nodes. + /// Specifies the minimum RAM (MiB) required for worker nodes. /// public const int MinWorkerNodeRamMiB = 8192; /// - /// The minimum required network interface cards for control-plane nodes. + /// Specifies the minimum required network interface cards for control-plane nodes. /// public const int MinControlPlaneNodeNics = 1; /// - /// The minimum required network interface cards for worker nodes. + /// Specifies the minimum required network interface cards for worker nodes. /// public const int MinWorkerNodeNics = 1; /// - /// - /// The fixed SSO password for desktop clusters. - /// - /// - /// This isn't really a security risk because the desktop cluster cannot be - /// reached from outside the computer because the cluster IP address is not - /// routable. - /// - /// - public const string RootDesktopPassword = "root"; - - /// - /// The NEONKUBE domain used to host NEONKUBE cluster DNS records. + /// Specifies the NEONKUBE domain used to host NEONKUBE cluster DNS records. /// public const string NeonClusterDomain = "neoncluster.io"; /// - /// The fixed ID for all desktop clusters. + /// Specifies the fixed ID for all desktop clusters. /// public const string DesktopClusterId = $"desktop"; /// - /// The fixed domain for all desktop clusters. + /// Specifies the fixed domain for all desktop clusters. /// public const string DesktopClusterDomain = $"{DesktopClusterId}.{NeonClusterDomain}"; /// - /// The default host machine sysadmin username. + /// Specifies the default host machine sysadmin username. /// public const string SysAdminUser = "sysadmin"; /// - /// The default host machine sysadmin user ID. + /// Specifies the default host machine sysadmin user ID. /// public const int SysAdminUID = 1000; /// - /// The default host machine sysadmin group. + /// Specifies the default host machine sysadmin group. /// public const string SysAdminGroup = "sysadmin"; /// - /// The default host machine sysadmin group ID. + /// Specifies the default host machine sysadmin group ID. /// public const int SysAdminGID = 1000; /// - /// The default sysadmin account password baked into NEONKUBE + /// Specifies the default sysadmin account password baked into NEONKUBE /// base images. This will generally be changed to a secure password /// during cluster provisioning. /// public const string SysAdminPassword = "sysadmin0000"; + /// + /// Specifies the SSH and SSO passwords to be used for NeonDESKTOP and insecure clusters. + /// + public const string SysAdminInsecurePassword = "sysadmin"; + /// /// $/etc/hosts section name used by NEONKUBE applications for persisting /// DNS host entries via . @@ -145,14 +138,14 @@ public static class KubeConst /// /// - /// The default name for the local + /// Specifies the default name for the local /// /// public const string LocalStorageClassName = "local-storage"; /// /// - /// The default path for the + /// Specifies the default path for the /// /// /// This is temporary, once Kubernetes supports dynamic provisioning of local storage volumes, we'll use @@ -178,7 +171,7 @@ public static class KubeConst public const string ImagePrebuiltDesktopPath = "/etc/neonkube/prebuilt-desktop"; /// - /// The number of IP addresses reserved by cloud deployments at the beginning of the + /// Specifies the number of IP addresses reserved by cloud deployments at the beginning of the /// node subnet by the cloud provider and also for future NEONKUBE features. /// This typically includes the cloud default gateway and DNS forwarding IPs as well /// as potential future NEONKUBE features such as an integrated VPN and perhaps @@ -187,7 +180,7 @@ public static class KubeConst public const int CloudSubnetStartReservedIPs = 10; /// - /// The number of IP addresses reserved by cloud deployments at the end of the node + /// Specifies the number of IP addresses reserved by cloud deployments at the end of the node /// subnet by the cloud provider. This typically includes the network UDP broadcast /// address. /// @@ -204,19 +197,19 @@ public static class KubeConst public const string DefaultServiceSubnet = "10.253.0.0/16"; /// - /// The container image tag used to reference cluster container images tagged + /// Specifies the container image tag used to reference cluster container images tagged /// our prefix and the cluster version number. /// public const string NeonKubeImageTag = "neonkube-" + KubeVersions.NeonKube; /// - /// The size of the OS disk used for base images. + /// Specifies the size of the OS disk used for base images. /// public const int BaseDiskSizeGiB = 10; /// /// - /// The minimum supported cluster node disk size in GiB. + /// Specifies the minimum supported cluster node disk size in GiB. /// /// /// This size should match the size of the virtual disks created the base @@ -226,7 +219,7 @@ public static class KubeConst public const int MinNodeDiskSizeGiB = 48; /// - /// The maximum support cluster node disk size in GiB. + /// Specifies the maximum support cluster node disk size in GiB. /// public const int MaxNodeDiskSizeGiB = 16 * 1024; @@ -253,7 +246,7 @@ public static class KubeConst public const string LocalClusterRegistryHostName = $"registry.{ClusterNodeDomain}"; /// - /// The local cluster registry project. + /// Specifies the local cluster registry project. /// public const string LocalClusterRegistryProject = "neonkube"; @@ -266,7 +259,7 @@ public static class KubeConst /// User name used to log CRI-O on the cluster nodes into the local /// Harbor registry via podman. /// - public const string HarborCrioUser = "root"; // $todo(jefflill): change this to "neon-harbor-crio" (https://github.com/nforgeio/neonKUBE/issues/1404) + public const string HarborCrioUser = "sysadmin"; // $todo(jefflill): change this to "neon-harbor-crio" (https://github.com/nforgeio/neonKUBE/issues/1404) /// /// Returns the Harbor Project name. @@ -391,14 +384,14 @@ public static class KubeConst public const string ClusterImagesLastChecked = "cluster-images-last-checked"; /// - /// The name used by the hosting manager + /// Specifies the name used by the hosting manager /// for creating the internal virtual switch where the NEONDESKTOP cluster /// as well as user-defined internal clusters will be attached. /// public const string HyperVInternalSwitchName = "neon-internal"; /// - /// The NEONDESKTOP cluster name. + /// Specifies the NEONDESKTOP cluster name. /// public const string NeonDesktopClusterName = "neon-desktop"; @@ -418,7 +411,7 @@ public static class KubeConst public const string ClusterLogName = "cluster.log"; /// - /// The maximum size in bytes of a node image part published as a GitHub release. + /// Specifies the maximum size in bytes of a node image part published as a GitHub release. /// public const long NodeImagePartSize = (long)(100 * ByteUnits.MebiBytes); @@ -428,17 +421,17 @@ public static class KubeConst public const string NeonKubeResourceGroup = "neonkube.io"; /// - /// The minimum amount of OS disk on a cluster node after accounting for Minio volumes. + /// Specifies the minimum amount of OS disk on a cluster node after accounting for Minio volumes. /// public const string MinimumOsDiskAfterMinio = "40 GiB"; /// - /// The CIR-O socket. + /// Specifies the CIR-O socket path. /// public const string CrioSocketPath = "/var/run/crio/crio.sock"; /// - /// The maximum label length allowed. + /// Specifies the maximum label length allowed. /// public const byte MaxLabelLength = 63;