add warning for users who need to enter a password to sudo

This commit is contained in:
az 2021-08-16 17:43:43 +02:00
parent 616230860d
commit 545be02d47
5 changed files with 81 additions and 10 deletions

View file

@ -7,7 +7,7 @@ interface DockerImage {
} }
/** /**
* Provides a docker image based on ubuntu additionally with a non-root default user and sudo isntalled * Provides a docker image based on ubuntu additionally with a non-root default user and sudo installed
*/ */
class UbuntuPlusUser(private val userName: String = "testuser") : DockerImage { class UbuntuPlusUser(private val userName: String = "testuser") : DockerImage {

View file

@ -10,24 +10,34 @@ import org.domaindrivenarchitecture.provs.core.processors.Processor
const val SHELL = "/bin/bash" const val SHELL = "/bin/bash"
class UbuntuProv internal constructor(processor : Processor = LocalProcessor(), name: String? = null, progressType: ProgressType) class UbuntuProv internal constructor(
: Prov(processor, name, progressType) { processor: Processor = LocalProcessor(),
name: String? = null,
progressType: ProgressType
) : Prov(processor, name, progressType) {
override fun cmd(cmd: String, dir: String?, sudo: Boolean) : ProvResult = def { init {
val user = cmdNoLog("whoami").out?.trim()
if (!cmdNoLog("timeout 1 sudo id").success) {
println("!!!!!!!!!! WARNING !!!!!!!!!!\nUser $user cannot sudo without entering a password, i.e. most functions may fail!\nPlease ensure $user can sudo without password.")
}
}
override fun cmd(cmd: String, dir: String?, sudo: Boolean): ProvResult = def {
xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo))
} }
override fun cmdNoLog(cmd: String, dir: String?, sudo: Boolean) : ProvResult { override fun cmdNoLog(cmd: String, dir: String?, sudo: Boolean): ProvResult {
return xecNoLog(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) return xecNoLog(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo))
} }
override fun cmdNoEval(cmd: String, dir: String?, sudo: Boolean) : ProvResult { override fun cmdNoEval(cmd: String, dir: String?, sudo: Boolean): ProvResult {
return xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo)) return xec(SHELL, "-c", commandWithDirAndSudo(cmd, dir, sudo))
} }
} }
private fun commandWithDirAndSudo(cmd: String, dir: String?, sudo: Boolean): String { private fun commandWithDirAndSudo(cmd: String, dir: String?, sudo: Boolean): String {
val cmdWithDir= if (dir == null) cmd else "cd $dir && $cmd" val cmdWithDir = if (dir == null) cmd else "cd $dir && $cmd"
return if (sudo) cmdWithDir.sudoize() else cmdWithDir return if (sudo) cmdWithDir.sudoize() else cmdWithDir
} }

View file

@ -46,7 +46,7 @@ fun Prov.provisionWorkplace(
userPassword?.also { makeUserSudoerWithNoSudoPasswordRequired(it) } userPassword?.also { makeUserSudoerWithNoSudoPasswordRequired(it) }
if (!currentUserCanSudo()) { if (!currentUserCanSudo()) {
throw Exception("Current user ${whoami()} cannot execute sudo without a password, but he must be able to in order to provisionWorkplace") throw Exception("Current user ${whoami()} cannot execute sudo without entering a password! This is necessary to execute provisionWorkplace")
} }
aptInstall("ssh gnupg curl git") aptInstall("ssh gnupg curl git")

View file

@ -67,7 +67,6 @@ fun Prov.configureUser(config: UserConfig) = requireAll {
@Suppress("unused") @Suppress("unused")
// todo create test
fun Prov.deleteUser(userName: String, deleteHomeDir: Boolean = false): ProvResult = requireAll { fun Prov.deleteUser(userName: String, deleteHomeDir: Boolean = false): ProvResult = requireAll {
val flagToDeleteHomeDir = if (deleteHomeDir) " -r " else "" val flagToDeleteHomeDir = if (deleteHomeDir) " -r " else ""
if (userExists(userName)) { if (userExists(userName)) {
@ -130,7 +129,7 @@ fun Prov.userIsInGroupSudo(userName: String): Boolean {
*/ */
@Suppress("unused") @Suppress("unused")
fun Prov.currentUserCanSudo(): Boolean { fun Prov.currentUserCanSudo(): Boolean {
return cmd("timeout 1 sudo id").success return chk("timeout 1 sudo id")
} }

View file

@ -1,8 +1,18 @@
package org.domaindrivenarchitecture.provs.core.platformTest package org.domaindrivenarchitecture.provs.core.platformTest
import org.domaindrivenarchitecture.provs.core.ProgressType
import org.domaindrivenarchitecture.provs.core.Prov import org.domaindrivenarchitecture.provs.core.Prov
import org.domaindrivenarchitecture.provs.core.docker.dockerImageExists
import org.domaindrivenarchitecture.provs.core.docker.dockerProvideImage
import org.domaindrivenarchitecture.provs.core.docker.dockerimages.DockerImage
import org.domaindrivenarchitecture.provs.core.processors.ContainerStartMode
import org.domaindrivenarchitecture.provs.core.processors.ContainerUbuntuHostProcessor
import org.domaindrivenarchitecture.provs.test.defaultTestContainerName
import org.domaindrivenarchitecture.provs.test.tags.NonCi import org.domaindrivenarchitecture.provs.test.tags.NonCi
import org.domaindrivenarchitecture.provs.test.testDockerWithSudo
import org.domaindrivenarchitecture.provs.test.testLocal import org.domaindrivenarchitecture.provs.test.testLocal
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.EnabledOnOs
import org.junit.jupiter.api.condition.OS import org.junit.jupiter.api.condition.OS
@ -95,5 +105,57 @@ internal class UbuntuProvTests {
assert(res3.out?.trim() == "echoed") assert(res3.out?.trim() == "echoed")
} }
@Test
@EnabledOnOs(OS.LINUX)
fun test_user_cannot_sudo_without_password() {
// given
val image = UbuntuUserNeedsPasswordForSudo()
val prov = testLocal()
if (!prov.dockerImageExists(image.imageName(), true)) {
prov.dockerProvideImage(image, sudo = true)
}
val a = Prov.newInstance(
ContainerUbuntuHostProcessor(
"provs_test_without_password_for_sudo",
startMode = ContainerStartMode.CREATE_NEW_KILL_EXISTING,
sudo = testDockerWithSudo,
dockerImage = image.imageName()
),
progressType = ProgressType.NONE
)
// when
val result = a.cmd("sudo echo bla")
// then
assertFalse(result.success)
assertEquals("sudo: no tty present and no askpass program specified\n", result.err)
}
} }
/**
* Provides a docker image based on ubuntu additionally with a non-root default user and sudo installed but user needs password to sudo
*/
class UbuntuUserNeedsPasswordForSudo(private val userName: String = "testuser") : DockerImage {
override fun imageName(): String {
return "ubuntu_user_needs_password_for_sudo"
}
override fun imageText(): String {
return """
FROM ubuntu:18.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get -y install sudo
RUN useradd -m $userName && echo "$userName:$userName" | chpasswd && adduser $userName sudo
USER $userName
CMD /bin/bash
WORKDIR /home/$userName
"""
}
}