mirror of https://github.com/sbt/sbt.git
Merge pull request #3922 from swaldman/suppressServer
Implement a suppressServer setting for high-security builds
This commit is contained in:
commit
bd1532eb4b
|
|
@ -39,6 +39,12 @@ object BasicKeys {
|
||||||
"The wire protocol for the server command.",
|
"The wire protocol for the server command.",
|
||||||
10000)
|
10000)
|
||||||
|
|
||||||
|
val autoStartServer =
|
||||||
|
AttributeKey[Boolean](
|
||||||
|
"autoStartServer",
|
||||||
|
"If true, the sbt server will startup automatically during interactive sessions.",
|
||||||
|
10000)
|
||||||
|
|
||||||
// Unlike other BasicKeys, this is not used directly as a setting key,
|
// Unlike other BasicKeys, this is not used directly as a setting key,
|
||||||
// and severLog / logLevel is used instead.
|
// and severLog / logLevel is used instead.
|
||||||
private[sbt] val serverLogLevel =
|
private[sbt] val serverLogLevel =
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,7 @@ object Defaults extends BuildCommon {
|
||||||
.getOrElse(GCUtil.defaultForceGarbageCollection),
|
.getOrElse(GCUtil.defaultForceGarbageCollection),
|
||||||
minForcegcInterval :== GCUtil.defaultMinForcegcInterval,
|
minForcegcInterval :== GCUtil.defaultMinForcegcInterval,
|
||||||
interactionService :== CommandLineUIService,
|
interactionService :== CommandLineUIService,
|
||||||
|
autoStartServer := true,
|
||||||
serverHost := "127.0.0.1",
|
serverHost := "127.0.0.1",
|
||||||
serverPort := 5000 + (Hash
|
serverPort := 5000 + (Hash
|
||||||
.toHex(Hash(appConfiguration.value.baseDirectory.toString))
|
.toHex(Hash(appConfiguration.value.baseDirectory.toString))
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,7 @@ object Keys {
|
||||||
// Command keys
|
// Command keys
|
||||||
val historyPath = SettingKey(BasicKeys.historyPath)
|
val historyPath = SettingKey(BasicKeys.historyPath)
|
||||||
val shellPrompt = SettingKey(BasicKeys.shellPrompt)
|
val shellPrompt = SettingKey(BasicKeys.shellPrompt)
|
||||||
|
val autoStartServer = SettingKey(BasicKeys.autoStartServer)
|
||||||
val serverPort = SettingKey(BasicKeys.serverPort)
|
val serverPort = SettingKey(BasicKeys.serverPort)
|
||||||
val serverHost = SettingKey(BasicKeys.serverHost)
|
val serverHost = SettingKey(BasicKeys.serverHost)
|
||||||
val serverAuthentication = SettingKey(BasicKeys.serverAuthentication)
|
val serverAuthentication = SettingKey(BasicKeys.serverAuthentication)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import Keys.{
|
||||||
sessionSettings,
|
sessionSettings,
|
||||||
shellPrompt,
|
shellPrompt,
|
||||||
templateResolverInfos,
|
templateResolverInfos,
|
||||||
|
autoStartServer,
|
||||||
serverHost,
|
serverHost,
|
||||||
serverLog,
|
serverLog,
|
||||||
serverPort,
|
serverPort,
|
||||||
|
|
@ -462,6 +463,7 @@ object Project extends ProjectExtra {
|
||||||
val prompt = get(shellPrompt)
|
val prompt = get(shellPrompt)
|
||||||
val trs = (templateResolverInfos in Global get structure.data).toList.flatten
|
val trs = (templateResolverInfos in Global get structure.data).toList.flatten
|
||||||
val watched = get(watch)
|
val watched = get(watch)
|
||||||
|
val startSvr: Option[Boolean] = get(autoStartServer)
|
||||||
val host: Option[String] = get(serverHost)
|
val host: Option[String] = get(serverHost)
|
||||||
val port: Option[Int] = get(serverPort)
|
val port: Option[Int] = get(serverPort)
|
||||||
val authentication: Option[Set[ServerAuthentication]] = get(serverAuthentication)
|
val authentication: Option[Set[ServerAuthentication]] = get(serverAuthentication)
|
||||||
|
|
@ -474,6 +476,7 @@ object Project extends ProjectExtra {
|
||||||
s.attributes
|
s.attributes
|
||||||
.setCond(Watched.Configuration, watched)
|
.setCond(Watched.Configuration, watched)
|
||||||
.put(historyPath.key, history)
|
.put(historyPath.key, history)
|
||||||
|
.setCond(autoStartServer.key, startSvr)
|
||||||
.setCond(serverPort.key, port)
|
.setCond(serverPort.key, port)
|
||||||
.setCond(serverHost.key, host)
|
.setCond(serverHost.key, host)
|
||||||
.setCond(serverAuthentication.key, authentication)
|
.setCond(serverAuthentication.key, authentication)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import java.util.concurrent.atomic._
|
||||||
import scala.collection.mutable.ListBuffer
|
import scala.collection.mutable.ListBuffer
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
import BasicKeys.{
|
import BasicKeys.{
|
||||||
|
autoStartServer,
|
||||||
serverHost,
|
serverHost,
|
||||||
serverPort,
|
serverPort,
|
||||||
serverAuthentication,
|
serverAuthentication,
|
||||||
|
|
@ -43,7 +44,7 @@ import sbt.util.{ Level, Logger, LogExchange }
|
||||||
* this exchange, which could serve command request from either of the channel.
|
* this exchange, which could serve command request from either of the channel.
|
||||||
*/
|
*/
|
||||||
private[sbt] final class CommandExchange {
|
private[sbt] final class CommandExchange {
|
||||||
private val autoStartServer = sys.props.get("sbt.server.autostart") map {
|
private val autoStartServerSysProp = sys.props.get("sbt.server.autostart") map {
|
||||||
_.toLowerCase == "true"
|
_.toLowerCase == "true"
|
||||||
} getOrElse true
|
} getOrElse true
|
||||||
private val lock = new AnyRef {}
|
private val lock = new AnyRef {}
|
||||||
|
|
@ -87,7 +88,11 @@ private[sbt] final class CommandExchange {
|
||||||
consoleChannel = Some(x)
|
consoleChannel = Some(x)
|
||||||
subscribe(x)
|
subscribe(x)
|
||||||
}
|
}
|
||||||
if (autoStartServer) runServer(s)
|
val autoStartServerAttr = (s get autoStartServer) match {
|
||||||
|
case Some(bool) => bool
|
||||||
|
case None => true
|
||||||
|
}
|
||||||
|
if (autoStartServerSysProp && autoStartServerAttr) runServer(s)
|
||||||
else s
|
else s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
This pull request implements a Boolean setting called `autoStartServer`, whose default value is `true'.
|
||||||
|
|
||||||
|
If a build or plugin explicitly sets it to `false`, the sbt-1.x server will not start up
|
||||||
|
(exactly as if the system property `sbt.server.autostart` were set to `false`).
|
||||||
|
|
||||||
|
Users who set `autoStartServer` to `false` may manually execute `startServer` at the interactive prompt,
|
||||||
|
if they wish to use the server during a shell session.
|
||||||
|
|
||||||
|
### Motivation
|
||||||
|
|
||||||
|
Projects often encounter private information, such as deployment credentials, private keys, etc.
|
||||||
|
For such projects, it may be preferable to reduce the potential attack surface than to enjoy the
|
||||||
|
interoperability offered by sbt's server. Projects that wish to make this tradeoff can set `autoStartServer`
|
||||||
|
to `false` in their build. Security-sensitive plugins can disable `autoStartServer` as well, modifying the
|
||||||
|
default behavior in favor of security.
|
||||||
|
|
||||||
|
(My own motivation is that I am working on a [plugin for developing Ethereum applications](https://github.com/swaldman/sbt-ethereum)
|
||||||
|
with scala and sbt. It must work with extremely sensitive private keys.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
See also a [recent conversation on Stack Exchange](https://stackoverflow.com/questions/48591179/can-one-disable-the-sbt-1-x-server/48593906#48593906).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
##### History
|
||||||
|
|
||||||
|
2018-02-06 Modified from negative `suppressServer` to positive `autoStartServer` at the (sensible) request of @eed3si9n
|
||||||
|
|
||||||
Loading…
Reference in New Issue