- Install
swig-python
- Use
pip
to install1pass
- Install
py-levenshtein
to avoid annoying warnings - Locate the nearest
1pass
script (note: it may be behind you) - Test
1pass
on a random password
Create ~/.sbt/0.13/plugins/OnePassword.scala
and enter the following contents:
import sbt._
import java.io.ByteArrayInputStream
import java.nio.charset.StandardCharsets
object OnePassword {
// alright, let's be real here: this is a security leak. sbt-pgp has the same flaw
private[this] lazy val password =
SimpleReader.readLine("1Password Master Password: ", Some('*')) getOrElse error("Must provide a password")
def apply(zone: String, host: String, user: String, entry: String): Credentials = {
val onePass = Process("/opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin/1pass" :: "--no-prompt" :: entry :: Nil)
val is = new ByteArrayInputStream(password.getBytes(StandardCharsets.UTF_8))
val lines = (onePass #< is).lines
Credentials(
zone,
host,
user,
lines.last) // throw an exception if it doesn't work
}
}
Pay no mind to the dangerous security leak... If it makes you feel better, sbt-pgp
leaks credentials in exactly the same way! Of course, your PGP key password isn't quite as sensitive as your 1Password master password, so maybe you should feel better after all.
To configure a set of credentials with a password stored in 1Password, follow this pattern (here is my Sonatype credential entry):
credentials +=
OnePassword(
"Sonatype Nexus Repository Manager",
"oss.sonatype.org",
"djspiewak",
"Sonatype")
The "Sonatype"
final parameter refers to the name of the 1Password entry which contains my Sonatype password. At present, I do not have a way to derive the username from 1Password, though in theory this is possible.
At present, you are prompted for your master password on startup and on the first time you publish
. Ideally, it would only be at the latter time, but I honestly don't know how to do that with SBT plugins. Help appreciated!