- 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 shouldn't 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!
I've noticed that 1pass
, and more specifically Python's json
library, has trouble parsing older 1Password items that contain forward slashes (/
). I'm not 100% certain of why this is, but it happens. You'll see this manifest in the form of an error that looks like this:
1pass: Error: Extra data: line 1 column ...
If you see this error, open up the 1Password item you're trying to load and retype any forward slashes. Chances are, these are in the URL associated with the item. Just edit it, delete the slashes and put them in again. Save the item and you're back in business. Note that it may be possible to replicate this effect by simply editing and then saving the item, but I didn't try that.
Guess what! If you put your credentials in the global settings, they get loaded not just when they're needed by your build, but also when SBT bootstraps itself. This means that you will need to enter your master password when SBT launches (any SBT instance, not just those using your credentials), and then again when you need to publish something. Though, if you publish repeatedly, I believe the password should be cached (hence the security leak). The point being that the completely unnecessary prompting for your password during the bootstrap is really, really annoying and I'd like to bypass it if at all possible, but I don't know how yet.