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

Use normalizedName as the default appUser for Linux Packages #144

Merged
merged 1 commit into from
Feb 1, 2014
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
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ For debian packaging there are a few things generated for you
* A template folder `/var/log/<app-name>`
* A symlink `/installdir/<app-name>/logs` to `/var/log/<app-name` (Installdir is by default `/usr/share`)
* Default `serverLoading` is `Upstart` (you can choose SystemV with `com.typesafe.sbt.packager.archetypes.ServerLoader.SystemV` )
* Default `daemonUser` is _root_
* If you choose different permissions than the default ones for your packages, _add-user_ and _remove-user_ statements will be added to
the `postrm` and `postinst` control files
* Default `appUser` is the normalized name of the package
* Default `daemonUser` is `appUser`
* _add-user_ and _remove-user_ statements will be added to
the `postrm` and `postinst` control files for `appUser`

### By-hand packaging ###

Expand Down
29 changes: 25 additions & 4 deletions src/main/scala/com/typesafe/sbt/packager/debian/DebianPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ package debian

import Keys._
import sbt._
import sbt.Keys.{ mappings, target, name, mainClass, normalizedName }
import sbt.Keys.{ target, name, normalizedName, TaskStreams }
import linux.LinuxPackageMapping
import linux.LinuxSymlink
import linux.LinuxFileMetaData
import com.typesafe.sbt.packager.Hashing
import com.typesafe.sbt.packager.linux.LinuxSymlink
import com.typesafe.sbt.packager.archetypes.TemplateWriter

trait DebianPlugin extends Plugin with linux.LinuxPlugin {
val Debian = config("debian") extend Linux
val UserNamePattern = "^[a-z][-a-z0-9_]*$".r

import com.typesafe.sbt.packager.universal.Archives
import DebianPlugin.Names
Expand Down Expand Up @@ -57,6 +57,15 @@ trait DebianPlugin extends Plugin with linux.LinuxPlugin {
}


private[this] def createFileIfRequired(script: File, perms: LinuxFileMetaData): File = {
if (!script.exists()) {
script.createNewFile()
chmod(script, perms.permissions)
}
script
}


private[this] def scriptMapping(scriptName: String)(script: Option[File], controlDir: File): Seq[(File, String)] = {
(script, controlDir) match {
// check if user defined script exists
Expand All @@ -67,6 +76,15 @@ trait DebianPlugin extends Plugin with linux.LinuxPlugin {
}
}

private[this] def validateUserGroupNames(user: String, streams: TaskStreams) {
if ((UserNamePattern findFirstIn user).isEmpty) {
streams.log.warn("The user or group '" + user + "' may contain invalid characters for Debian based distributions")
}
if (user.length > 32) {
streams.log.warn("The length of '" + user + "' must be not be greater than 32 characters for Debian based distributions.")
}
}


def debianSettings: Seq[Setting[_]] = Seq(
debianPriority := "optional",
Expand Down Expand Up @@ -172,8 +190,8 @@ trait DebianPlugin extends Plugin with linux.LinuxPlugin {
} groupBy (_._1) foreach {
case ((user, group), pathList) =>
streams.log info ("Altering postrm/postinst files to add user " + user + " and group " + group)
val postinst = t / Names.Debian / Names.Postinst
val postrm = t / Names.Debian / Names.Postrm
val postinst = createFileIfRequired(t / Names.Debian / Names.Postinst, LinuxFileMetaData())
val postrm = createFileIfRequired(t / Names.Debian / Names.Postrm, LinuxFileMetaData())

val replacements = Seq("group" -> group, "user" -> user)

Expand All @@ -185,6 +203,9 @@ trait DebianPlugin extends Plugin with linux.LinuxPlugin {
prependAndFixPerms(postinst, chownAdd, LinuxFileMetaData())
}

validateUserGroupNames(user, streams)
validateUserGroupNames(group, streams)

val userGroupAdd = Seq(
TemplateWriter.generateScript(DebianPlugin.postinstGroupaddTemplateSource, replacements),
TemplateWriter.generateScript(DebianPlugin.postinstUseraddTemplateSource, replacements)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package linux

import Keys._
import sbt._
import sbt.Keys.{ normalizedName }
import com.typesafe.sbt.packager.linux.LinuxPlugin.Users

/**
Expand All @@ -27,7 +28,7 @@ trait LinuxPlugin extends Plugin {
},
packageSummary in Linux <<= packageSummary,
packageDescription in Linux <<= packageDescription,
appUser := Users.Root, appGroup <<= appUser in Linux)
appUser <<= normalizedName, appGroup <<= appUser in Linux)

/** DSL for packaging files into .deb */
def packageMapping(files: (File, String)*) = LinuxPackageMapping(files)
Expand Down
7 changes: 5 additions & 2 deletions src/sphinx/archetypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,18 @@ For Debian servers, you can select to either use SystemV or Upstart for your ser

serverLoading in Debian := ServerLoader.SystemV

By default, the native packager will install and run services using the ``root`` user and group. This is not a good default for services, which should not be exposed to root access. You can change the installation and usage user via the ``daemonUser`` key:
By default, the native packager will install and run services using a user and group based on your package name. You can change the installation and usage user via the ``appUser`` and ``appGroup`` key:

.. code-block:: scala

daemonUser in Debian := "my_app_user"
appUser in Linux := "my_app_user"

appGroup in Linux := "my_app_group"

The archetype will automatically append/prepend the creation/deletion of the user
to your packaging for Debian. *Note:* All specified users are **deleted** on an ``apt-get purge <dpkg>``.

*Note:* It is not a good idea to use **root** as the ``appUser`` for services as it represents a security risk.



Expand Down
20 changes: 11 additions & 9 deletions src/sphinx/debian.rst
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ can add ``preinst`` , ``postinst`` , ``prerm`` and/or ``postrm`` scripts. Just p

If you use the ``packageArchetype.java_server`` there are predefined ``postinst`` and
``preinst`` files, which start/stop the application on install/remove calls. Existing
maintainer scripts will be extended not overidden.
maintainer scripts will be extended not overridden.

Your control scripts are in a different castle.. directory? No problem.

Expand All @@ -149,12 +149,14 @@ The default configuration looks like this (that means you don't have to add anyt
import com.typesafe.sbt.packager.archetypes.ServerLoader.{Upstart, SystemV}

serverLoading := Upstart

daemonUser := "root"

Change these values as you need. When you change the ``daemonUser`` make sure
you alter the ``packageMappings`` correctly. All users you define in the
``packageMappings`` will be generated within in the ``postinst`` script and
removed with ``apt-get purge`` through the ``postrm`` script.

For more informations look at the :ref:`Archetypes` page.
The default configuration will create a default system user and group for ownerships of the
installed files. This user will also be used to execute the daemon service so it does
not run as the **root** user.

This default can be overridden using the ``appUser`` and ``appGroup`` keys, change
these values as you need. The user or group you define in the appropriate keys will be
created within in the ``postinst`` script and removed with ``apt-get purge`` through the
``postrm`` script.

For more information look at the :ref:`Archetypes` page.