Skip to content

Commit 5a71939

Browse files
committed
refactor password source, allow for "pass" to be used, update tests to use password-source: pass
1 parent 09f8029 commit 5a71939

File tree

17 files changed

+322
-30
lines changed

17 files changed

+322
-30
lines changed

.travis.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
sudo: true
22
before_install:
3-
- sudo apt-get update && sudo apt-get install -y libgnome-keyring-dev
3+
- sudo apt-get update && sudo apt-get install -y pass gnupg
44

55
language: go
66

@@ -14,8 +14,4 @@ script:
1414
- make vet
1515
- make lint
1616
- make
17-
- JIRACLOUD=1 ./t/100basic.t -w -a 2>&1
18-
19-
cache:
20-
directories:
21-
- t/.maven-cache
17+
- export GNUPGHOME=$(pwd)/t/.gnupg && export PASSWORD_STORE_DIR=$(pwd)/t/.password-store && export JIRACLOUD=1 && ./t/100basic.t -w -a 2>&1

cli.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"time"
2020

2121
"github.com/kballard/go-shellquote"
22-
"github.com/tmc/keyring"
2322
"gopkg.in/coryb/yaml.v2"
2423
"gopkg.in/op/go-logging.v1"
2524
)
@@ -215,11 +214,11 @@ func (c *Cli) makeRequest(req *http.Request) (resp *http.Response, err error) {
215214
req.Header.Set("Accept", "application/json")
216215
req.Header.Set("Content-Type", "application/json")
217216

218-
if val, ok := c.opts["password-keyring"].(bool); ok && val && !strings.HasSuffix(req.URL.Path, "/rest/auth/1/session") {
217+
if source, ok := c.opts["password-source"]; ok && !strings.HasSuffix(req.URL.Path, "/rest/auth/1/session") {
219218
user, _ := c.opts["user"].(string)
220-
password, _ := keyring.Get("go-jira", user)
219+
password := c.GetPass(user)
221220
if password == "" {
222-
log.Warning("No password for user %s in keyring, please run the 'login' command first", user)
221+
log.Warning("No password for user %s in %s, please run the 'login' command first", user, source)
223222
} else {
224223
req.SetBasicAuth(user, password)
225224
}

commands.go

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import (
1010
"os"
1111
"strings"
1212

13-
"github.com/howeyc/gopass"
14-
"github.com/tmc/keyring"
1513
"gopkg.in/Netflix-Skunkworks/go-jira.v0/data"
1614
// "github.com/kr/pretty"
1715
)
@@ -23,13 +21,7 @@ func (c *Cli) CmdLogin() error {
2321
req, _ := http.NewRequest("GET", uri, nil)
2422
user, _ := c.opts["user"].(string)
2523

26-
fmt.Printf("Jira Password [%s]: ", user)
27-
pw, err := gopass.GetPasswdMasked()
28-
if err != nil {
29-
return err
30-
}
31-
passwd := string(pw)
32-
24+
passwd := c.GetPass(user)
3325
req.SetBasicAuth(user, passwd)
3426

3527
resp, err := c.makeRequest(req)
@@ -55,13 +47,8 @@ func (c *Cli) CmdLogin() error {
5547
log.Warning("Authentication Failed: %s", reason)
5648
continue
5749
}
58-
if val, ok := c.opts["password-keyring"].(bool); ok && val {
59-
// save password in keychain so that it can be used for subsequent http requests
60-
err := keyring.Set("go-jira", user, passwd)
61-
if err != nil {
62-
log.Errorf("Failed to set password in keyring: %s", err)
63-
return err
64-
}
50+
if _, ok := c.opts["password-source"]; ok {
51+
return c.SetPass(user, passwd)
6552
}
6653
break
6754
} else {

password.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package jira
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"os/exec"
7+
"strings"
8+
9+
"github.com/howeyc/gopass"
10+
"github.com/tmc/keyring"
11+
)
12+
13+
func (c *Cli) GetPass(user string) string {
14+
passwd := ""
15+
if source, ok := c.opts["password-source"].(string); ok {
16+
if source == "keyring" {
17+
passwd, _ = keyring.Get("go-jira", user)
18+
} else if source == "pass" {
19+
if bin, err := exec.LookPath("pass"); err == nil {
20+
buf := bytes.NewBufferString("")
21+
cmd := exec.Command(bin, fmt.Sprintf("GoJira/%s", user))
22+
cmd.Stdout = buf
23+
cmd.Stderr = buf
24+
if err := cmd.Run(); err == nil {
25+
passwd = strings.TrimSpace(buf.String())
26+
}
27+
}
28+
} else {
29+
log.Warningf("Unknown password-source: %s", source)
30+
}
31+
}
32+
33+
if passwd != "" {
34+
return passwd
35+
}
36+
fmt.Printf("Jira Password [%s]: ", user)
37+
pw, err := gopass.GetPasswdMasked()
38+
if err != nil {
39+
return ""
40+
}
41+
passwd = string(pw)
42+
return passwd
43+
}
44+
45+
func (c *Cli) SetPass(user, passwd string) error {
46+
if source, ok := c.opts["password-source"].(string); ok {
47+
if source == "keyring" {
48+
// save password in keychain so that it can be used for subsequent http requests
49+
err := keyring.Set("go-jira", user, passwd)
50+
if err != nil {
51+
log.Errorf("Failed to set password in keyring: %s", err)
52+
return err
53+
}
54+
} else if source == "pass" {
55+
if bin, err := exec.LookPath("pass"); err == nil {
56+
in := bytes.NewBufferString(fmt.Sprintf("%s\n%s\n", passwd, passwd))
57+
out := bytes.NewBufferString("")
58+
cmd := exec.Command(bin, "insert", fmt.Sprintf("GoJira/%s", user))
59+
cmd.Stdin = in
60+
cmd.Stdout = out
61+
cmd.Stderr = out
62+
if err := cmd.Run(); err != nil {
63+
return fmt.Errorf("Failed to insert password: %s", out.String())
64+
}
65+
}
66+
} else {
67+
return fmt.Errorf("Unknown password-source: %s", source)
68+
}
69+
}
70+
return nil
71+
}

t/.gnupg/gpg.conf

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
# Options for GnuPG
2+
# Copyright 1998, 1999, 2000, 2001, 2002, 2003,
3+
# 2010 Free Software Foundation, Inc.
4+
#
5+
# This file is free software; as a special exception the author gives
6+
# unlimited permission to copy and/or distribute it, with or without
7+
# modifications, as long as this notice is preserved.
8+
#
9+
# This file is distributed in the hope that it will be useful, but
10+
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
11+
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
#
13+
# Unless you specify which option file to use (with the command line
14+
# option "--options filename"), GnuPG uses the file ~/.gnupg/gpg.conf
15+
# by default.
16+
#
17+
# An options file can contain any long options which are available in
18+
# GnuPG. If the first non white space character of a line is a '#',
19+
# this line is ignored. Empty lines are also ignored.
20+
#
21+
# See the man page for a list of options.
22+
23+
# Uncomment the following option to get rid of the copyright notice
24+
25+
#no-greeting
26+
27+
# If you have more than 1 secret key in your keyring, you may want to
28+
# uncomment the following option and set your preferred keyid.
29+
30+
#default-key 621CC013
31+
32+
# If you do not pass a recipient to gpg, it will ask for one. Using
33+
# this option you can encrypt to a default key. Key validation will
34+
# not be done in this case. The second form uses the default key as
35+
# default recipient.
36+
37+
#default-recipient some-user-id
38+
#default-recipient-self
39+
40+
# Use --encrypt-to to add the specified key as a recipient to all
41+
# messages. This is useful, for example, when sending mail through a
42+
# mail client that does not automatically encrypt mail to your key.
43+
# In the example, this option allows you to read your local copy of
44+
# encrypted mail that you've sent to others.
45+
46+
#encrypt-to some-key-id
47+
48+
# By default GnuPG creates version 4 signatures for data files as
49+
# specified by OpenPGP. Some earlier (PGP 6, PGP 7) versions of PGP
50+
# require the older version 3 signatures. Setting this option forces
51+
# GnuPG to create version 3 signatures.
52+
53+
#force-v3-sigs
54+
55+
# Because some mailers change lines starting with "From " to ">From "
56+
# it is good to handle such lines in a special way when creating
57+
# cleartext signatures; all other PGP versions do it this way too.
58+
59+
#no-escape-from-lines
60+
61+
# If you do not use the Latin-1 (ISO-8859-1) charset, you should tell
62+
# GnuPG which is the native character set. Please check the man page
63+
# for supported character sets. This character set is only used for
64+
# metadata and not for the actual message which does not undergo any
65+
# translation. Note that future version of GnuPG will change to UTF-8
66+
# as default character set. In most cases this option is not required
67+
# as GnuPG is able to figure out the correct charset at runtime.
68+
69+
#charset utf-8
70+
71+
# Group names may be defined like this:
72+
# group mynames = paige 0x12345678 joe patti
73+
#
74+
# Any time "mynames" is a recipient (-r or --recipient), it will be
75+
# expanded to the names "paige", "joe", and "patti", and the key ID
76+
# "0x12345678". Note there is only one level of expansion - you
77+
# cannot make an group that points to another group. Note also that
78+
# if there are spaces in the recipient name, this will appear as two
79+
# recipients. In these cases it is better to use the key ID.
80+
81+
#group mynames = paige 0x12345678 joe patti
82+
83+
# Lock the file only once for the lifetime of a process. If you do
84+
# not define this, the lock will be obtained and released every time
85+
# it is needed, which is usually preferable.
86+
87+
#lock-once
88+
89+
# GnuPG can send and receive keys to and from a keyserver. These
90+
# servers can be HKP, email, or LDAP (if GnuPG is built with LDAP
91+
# support).
92+
#
93+
# Example HKP keyserver:
94+
# hkp://keys.gnupg.net
95+
# hkp://subkeys.pgp.net
96+
#
97+
# Example email keyserver:
98+
99+
#
100+
# Example LDAP keyservers:
101+
# ldap://keyserver.pgp.com
102+
#
103+
# Regular URL syntax applies, and you can set an alternate port
104+
# through the usual method:
105+
# hkp://keyserver.example.net:22742
106+
#
107+
# Most users just set the name and type of their preferred keyserver.
108+
# Note that most servers (with the notable exception of
109+
# ldap://keyserver.pgp.com) synchronize changes with each other. Note
110+
# also that a single server name may actually point to multiple
111+
# servers via DNS round-robin. hkp://keys.gnupg.net is an example of
112+
# such a "server", which spreads the load over a number of physical
113+
# servers. To see the IP address of the server actually used, you may use
114+
# the "--keyserver-options debug".
115+
116+
keyserver hkp://keys.gnupg.net
117+
#keyserver mailto:[email protected]
118+
#keyserver ldap://keyserver.pgp.com
119+
120+
# Common options for keyserver functions:
121+
#
122+
# include-disabled : when searching, include keys marked as "disabled"
123+
# on the keyserver (not all keyservers support this).
124+
#
125+
# no-include-revoked : when searching, do not include keys marked as
126+
# "revoked" on the keyserver.
127+
#
128+
# verbose : show more information as the keys are fetched.
129+
# Can be used more than once to increase the amount
130+
# of information shown.
131+
#
132+
# use-temp-files : use temporary files instead of a pipe to talk to the
133+
# keyserver. Some platforms (Win32 for one) always
134+
# have this on.
135+
#
136+
# keep-temp-files : do not delete temporary files after using them
137+
# (really only useful for debugging)
138+
#
139+
# http-proxy="proxy" : set the proxy to use for HTTP and HKP keyservers.
140+
# This overrides the "http_proxy" environment variable,
141+
# if any.
142+
#
143+
# auto-key-retrieve : automatically fetch keys as needed from the keyserver
144+
# when verifying signatures or when importing keys that
145+
# have been revoked by a revocation key that is not
146+
# present on the keyring.
147+
#
148+
# no-include-attributes : do not include attribute IDs (aka "photo IDs")
149+
# when sending keys to the keyserver.
150+
151+
#keyserver-options auto-key-retrieve
152+
153+
# Display photo user IDs in key listings
154+
155+
# list-options show-photos
156+
157+
# Display photo user IDs when a signature from a key with a photo is
158+
# verified
159+
160+
# verify-options show-photos
161+
162+
# Use this program to display photo user IDs
163+
#
164+
# %i is expanded to a temporary file that contains the photo.
165+
# %I is the same as %i, but the file isn't deleted afterwards by GnuPG.
166+
# %k is expanded to the key ID of the key.
167+
# %K is expanded to the long OpenPGP key ID of the key.
168+
# %t is expanded to the extension of the image (e.g. "jpg").
169+
# %T is expanded to the MIME type of the image (e.g. "image/jpeg").
170+
# %f is expanded to the fingerprint of the key.
171+
# %% is %, of course.
172+
#
173+
# If %i or %I are not present, then the photo is supplied to the
174+
# viewer on standard input. If your platform supports it, standard
175+
# input is the best way to do this as it avoids the time and effort in
176+
# generating and then cleaning up a secure temp file.
177+
#
178+
# If no photo-viewer is provided, GnuPG will look for xloadimage, eog,
179+
# or display (ImageMagick). On Mac OS X and Windows, the default is
180+
# to use your regular JPEG image viewer.
181+
#
182+
# Some other viewers:
183+
# photo-viewer "qiv %i"
184+
# photo-viewer "ee %i"
185+
#
186+
# This one saves a copy of the photo ID in your home directory:
187+
# photo-viewer "cat > ~/photoid-for-key-%k.%t"
188+
#
189+
# Use your MIME handler to view photos:
190+
# photo-viewer "metamail -q -d -b -c %T -s 'KeyID 0x%k' -f GnuPG"
191+
192+
# Passphrase agent
193+
#
194+
# We support the old experimental passphrase agent protocol as well as
195+
# the new Assuan based one (currently available in the "newpg" package
196+
# at ftp.gnupg.org/gcrypt/alpha/aegypten/). To make use of the agent,
197+
# you have to run an agent as daemon and use the option
198+
#
199+
# use-agent
200+
#
201+
# which tries to use the agent but will fallback to the regular mode
202+
# if there is a problem connecting to the agent. The normal way to
203+
# locate the agent is by looking at the environment variable
204+
# GPG_AGENT_INFO which should have been set during gpg-agent startup.
205+
# In certain situations the use of this variable is not possible, thus
206+
# the option
207+
#
208+
# --gpg-agent-info=<path>:<pid>:1
209+
#
210+
# may be used to override it.
211+
212+
# Automatic key location
213+
#
214+
# GnuPG can automatically locate and retrieve keys as needed using the
215+
# auto-key-locate option. This happens when encrypting to an email
216+
# address (in the "[email protected]" form), and there are no
217+
# [email protected] keys on the local keyring. This option takes the
218+
# following arguments, in the order they are to be tried:
219+
#
220+
# cert = locate a key using DNS CERT, as specified in RFC-4398.
221+
# GnuPG can handle both the PGP (key) and IPGP (URL + fingerprint)
222+
# CERT methods.
223+
#
224+
# pka = locate a key using DNS PKA.
225+
#
226+
# ldap = locate a key using the PGP Universal method of checking
227+
# "ldap://keys.(thedomain)". For example, encrypting to
228+
# [email protected] will check ldap://keys.example.com.
229+
#
230+
# keyserver = locate a key using whatever keyserver is defined using
231+
# the keyserver option.
232+
#
233+
# You may also list arbitrary keyservers here by URL.
234+
#
235+
# Try CERT, then PKA, then LDAP, then hkp://subkeys.net:
236+
#auto-key-locate cert pka ldap hkp://subkeys.pgp.net

t/.gnupg/pubring.gpg

1.16 KB
Binary file not shown.

t/.gnupg/random_seed

600 Bytes
Binary file not shown.

t/.gnupg/secring.gpg

2.43 KB
Binary file not shown.

t/.gnupg/trustdb.gpg

1.25 KB
Binary file not shown.

t/.jira.d/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/bin/sh
2+
echo password-source: pass
23
if [ -z "$JIRACLOUD" ]; then
34
echo endpoint: http://localhost:8080
45
echo user: gojira
5-
echo password-keyring: true
66
else
77
echo endpoint: https://go-jira.atlassian.net
88
echo user: [email protected]

0 commit comments

Comments
 (0)