Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

appUser and appGroup now correctly own the installation directory #143

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ trait GenericPackageSettings
* `../man/...1` files are automatically compressed into .gz files.
*
*/
def mapGenericMappingsToLinux(mappings: Seq[(File, String)], user: String)(rename: String => String): Seq[LinuxPackageMapping] = {
def mapGenericMappingsToLinux(mappings: Seq[(File, String)], user: String, group: String)(rename: String => String): Seq[LinuxPackageMapping] = {
val (directories, nondirectories) = mappings.partition(_._1.isDirectory)
val (binaries, nonbinaries) = nondirectories.partition(_._1.canExecute)
val (manPages, nonManPages) = nonbinaries partition {
Expand All @@ -53,31 +53,31 @@ trait GenericPackageSettings
}

Seq(
packageMappingWithRename((binaries ++ directories):_*) withUser user withGroup user withPerms "0755",
packageMappingWithRename(compressedManPages:_*).gzipped withUser user withGroup user withPerms "0644",
packageMappingWithRename(configFiles:_*) withConfig() withUser user withGroup user withPerms "0644",
packageMappingWithRename(remaining:_*) withUser user withGroup user withPerms "0644"
packageMappingWithRename((binaries ++ directories):_*) withUser user withGroup group withPerms "0755",
packageMappingWithRename(compressedManPages:_*).gzipped withUser user withGroup group withPerms "0644",
packageMappingWithRename(configFiles:_*) withConfig() withUser user withGroup group withPerms "0644",
packageMappingWithRename(remaining:_*) withUser user withGroup group withPerms "0644"
)
}

def mapGenericFilesToLinux: Seq[Setting[_]] = Seq(

// Default place to install code.
defaultLinuxInstallLocation := "/usr/share",
defaultLinuxLogsLocation := "/var/log",

// First we look at the src/linux files
linuxPackageMappings <++= (sourceDirectory in Linux, appUser in Linux) map { (dir, user) =>
mapGenericMappingsToLinux((dir.*** --- dir) x relativeTo(dir), user)(identity)
linuxPackageMappings <++= (sourceDirectory in Linux, appUser in Linux, appGroup in Linux) map { (dir, user, group) =>
mapGenericMappingsToLinux((dir.*** --- dir) x relativeTo(dir), user, group)(identity)
},
// Now we look at the src/universal files.
linuxPackageMappings <++= (normalizedName in Universal, mappings in Universal, defaultLinuxInstallLocation, appUser in Linux) map {
(pkg, mappings, installLocation, user) =>
linuxPackageMappings <++= (normalizedName in Universal, mappings in Universal, defaultLinuxInstallLocation, appUser in Linux, appGroup in Linux) map {
(pkg, mappings, installLocation, user, group) =>
// TODO - More windows filters...
def isWindowsFile(f: (File, String)): Boolean =
f._2 endsWith ".bat"

mapGenericMappingsToLinux(mappings filterNot isWindowsFile, user) { name =>
mapGenericMappingsToLinux(mappings filterNot isWindowsFile, user, group) { name =>
installLocation + "/" + pkg + "/" + name
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Keys._
import sbt._
import sbt.Project.Initialize
import sbt.Keys.{ mappings, target, name, mainClass, normalizedName, sourceDirectory }
import linux.LinuxPackageMapping
import com.typesafe.sbt.packager.linux.{LinuxFileMetaData, LinuxPackageMapping}
import SbtNativePackager._

/**
Expand Down Expand Up @@ -63,6 +63,13 @@ object JavaAppPackaging {
for {
s <- script.toSeq
} yield s -> ("bin/" + name + ".bat")
},
linuxPackageMappings in Debian <+= (normalizedName, defaultLinuxInstallLocation, target in Debian, appUser in Linux, appGroup in Linux) map {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only in Debian because RPM handles things differently, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think this should also be in the RPM side....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be on the RPM side and I started going down that route but ended up taking the simple option as this is really needed for my previous PR

(name, installLocation, target, user, group) =>
// create empty var/log directory
val d = target / installLocation
d.mkdirs()
LinuxPackageMapping(Seq(d -> (installLocation + "/" + name)), LinuxFileMetaData(user, group))
})

def makeRelativeClasspathNames(mappings: Seq[(File, String)]): Seq[String] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ object JavaServerAppPackaging {
map { (tmpDir, loader, replacements, template) =>
makeDebianMaintainerScript(JavaAppStartScript.startScript, Some(template))(tmpDir, loader, replacements)
},
linuxPackageMappings in Debian <++= (debianMakeStartScript, normalizedName, serverLoading in Debian, appUser in Linux)
map { (script, name, loader, owner) =>
linuxPackageMappings in Debian <++= (debianMakeStartScript, normalizedName, serverLoading in Debian, appUser in Linux, appGroup in Linux)
map { (script, name, loader, owner, ownerGroup) =>
val (path, permissions) = loader match {
case Upstart => ("/etc/init/" + name + ".conf", "0644")
case SystemV => ("/etc/init.d/" + name, "0755")
}
for {
s <- script.toSeq
} yield LinuxPackageMapping(Seq(s -> path), LinuxFileMetaData(owner, owner, permissions, "true"))
} yield LinuxPackageMapping(Seq(s -> path), LinuxFileMetaData(owner, ownerGroup, permissions, "true"))
},

// === etc config mapping ===
Expand All @@ -75,18 +75,18 @@ object JavaServerAppPackaging {
},
debianMakeEtcDefault <<= (normalizedName, target in Universal, linuxEtcDefaultTemplate in Debian, debianScriptReplacements)
map makeEtcDefaultScript,
linuxPackageMappings in Debian <++= (debianMakeEtcDefault, normalizedName, appUser in Linux) map { (conf, name, owner) =>
conf.map(c => LinuxPackageMapping(Seq(c -> ("/etc/default/" + name)), LinuxFileMetaData(owner, owner)).withConfig()).toSeq
linuxPackageMappings in Debian <++= (debianMakeEtcDefault, normalizedName, appUser in Linux, appGroup in Linux) map { (conf, name, owner, ownerGroup) =>
conf.map(c => LinuxPackageMapping(Seq(c -> ("/etc/default/" + name)), LinuxFileMetaData(owner, ownerGroup)).withConfig()).toSeq
},
// TODO should we specify daemonGroup in configs?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can removed then :)


// === logging directory mapping ===
linuxPackageMappings in Debian <+= (normalizedName, defaultLinuxLogsLocation, target in Debian, appUser in Linux) map {
(name, logsDir, target, user) =>
linuxPackageMappings in Debian <+= (normalizedName, defaultLinuxLogsLocation, target in Debian, appUser in Linux, appGroup in Linux) map {
(name, logsDir, target, user, group) =>
// create empty var/log directory
val d = target / logsDir
d.mkdirs()
LinuxPackageMapping(Seq(d -> (logsDir + "/" + name)), LinuxFileMetaData(user, user))
LinuxPackageMapping(Seq(d -> (logsDir + "/" + name)), LinuxFileMetaData(user, group))
},
linuxPackageSymlinks in Debian <+= (normalizedName, defaultLinuxInstallLocation) map {
(name, install) => LinuxSymlink(install + "/" + name + "/logs", "/var/log/" + name)
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/com/typesafe/sbt/packager/debian/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ object Keys extends DebianKeys {

// file ownership
def appUser = linux.Keys.appUser
def appGroup = linux.Keys.appGroup

//init script parameters
def daemonUser = linux.Keys.daemonUser
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/com/typesafe/sbt/packager/linux/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ trait Keys {
val packageDescription = SettingKey[String]("package-description", "The description of the package. Used when searching.")
val maintainer = SettingKey[String]("maintainer", "The name/email address of a maintainer for the native package.")
val appUser = SettingKey[String]("app-user", "The owner of the files in the package")
val appGroup = SettingKey[String]("app-group", "The group owner of the files in the package")
val daemonUser = SettingKey[String]("daemon-user", "User to start application daemon")
val serverLoading = SettingKey[ServerLoader]("server-loader", "Loading system to be used for application start script")
val linuxPackageMappings = TaskKey[Seq[LinuxPackageMapping]]("linux-package-mappings", "File to install location mappings including owner and privileges.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ trait LinuxPlugin extends Plugin {
},
packageSummary in Linux <<= packageSummary,
packageDescription in Linux <<= packageDescription,
appUser := Users.Root)
appUser := Users.Root, appGroup <<= appUser in Linux)

/** DSL for packaging files into .deb */
def packageMapping(files: (File, String)*) = LinuxPackageMapping(files)
Expand Down
12 changes: 7 additions & 5 deletions src/sbt-test/debian/daemon-user-deb/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ serverLoading in Debian := ServerLoader.Upstart

appUser in Linux := "daemonUser"

appGroup in Linux := "daemonGroup"

mainClass in Compile := Some("empty")

name := "debian-test"
Expand All @@ -24,12 +26,12 @@ TaskKey[Unit]("check-control-files") <<= (target, streams) map { (target, out) =
val debian = target / "debian-test-0.1.0" / "DEBIAN"
val postinst = IO.read(debian / "postinst")
val postrm = IO.read(debian / "postrm")
assert(postinst contains "addgroup --system daemonUser", "postinst misses addgroup for daemonUser: " + postinst)
assert(postinst contains "useradd --system --no-create-home --gid daemonUser --shell /bin/false daemonUser", "postinst misses useradd for daemonUser: " + postinst)
assert(postinst contains "chown daemonUser:daemonUser /var/log/debian-test", "postinst misses chown daemonUser /var/log/debian-test: " + postinst)
assert(postinst contains "chown daemonUser:daemonUser /usr/share/debian-test/bin/debian-test", "postinst misses chown daemonUser /usr/share/debian-test/bin/debian-test: " + postinst)
assert(postinst contains "addgroup --system daemonGroup", "postinst misses addgroup for daemonGroup: " + postinst)
assert(postinst contains "useradd --system --no-create-home --gid daemonGroup --shell /bin/false daemonUser", "postinst misses useradd for daemonUser: " + postinst)
assert(postinst contains "chown daemonUser:daemonGroup /var/log/debian-test", "postinst misses chown daemonUser /var/log/debian-test: " + postinst)
assert(postinst contains "chown daemonUser:daemonGroup /usr/share/debian-test/bin/debian-test", "postinst misses chown daemonUser /usr/share/debian-test/bin/debian-test: " + postinst)
assert(postrm contains "deluser --quiet --system daemonUser > /dev/null || true", "postrm misses purging daemonUser user: " + postrm)
assert(postrm contains "delgroup --quiet --system daemonUser > /dev/null || true", "postrm misses purging daemonUser group: " + postrm)
assert(postrm contains "delgroup --quiet --system daemonGroup > /dev/null || true", "postrm misses purging daemonGroup group: " + postrm)
out.log.success("Successfully tested upstart control files")
()
}
Expand Down