boxen 0.8.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/boxen.gemspec +1 -1
- data/lib/boxen/config.rb +9 -22
- data/lib/boxen/keychain.rb +64 -0
- data/script/Boxen +0 -0
- data/script/build-keychain-helper +6 -0
- data/src/keychain-helper.c +67 -0
- data/test/boxen_keychain_test.rb +28 -0
- metadata +9 -3
data/.gitignore
CHANGED
data/boxen.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
4
|
gem.name = "boxen"
|
5
|
-
gem.version = "0.
|
5
|
+
gem.version = "1.0.0"
|
6
6
|
gem.authors = ["John Barnette", "Will Farrington"]
|
7
7
|
gem.email = ["jbarnette@github.com", "wfarr@github.com"]
|
8
8
|
gem.description = "Manage Mac development boxes with love (and Puppet)."
|
data/lib/boxen/config.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
require "boxen/keychain"
|
2
|
+
require "boxen/project"
|
1
3
|
require "fileutils"
|
2
4
|
require "json"
|
3
5
|
require "octokit"
|
4
|
-
require "
|
6
|
+
require "shellwords"
|
5
7
|
|
6
8
|
module Boxen
|
7
9
|
|
@@ -9,13 +11,6 @@ module Boxen
|
|
9
11
|
# args, environment variables, config files, or the keychain.
|
10
12
|
|
11
13
|
class Config
|
12
|
-
|
13
|
-
# The service name to use when loading/saving config in the Keychain.
|
14
|
-
|
15
|
-
KEYCHAIN_SERVICE = "Boxen"
|
16
|
-
|
17
|
-
# Load config. Yields config if `block` is given.
|
18
|
-
|
19
14
|
def self.load(&block)
|
20
15
|
new do |config|
|
21
16
|
file = "#{config.homedir}/config/boxen/defaults.json"
|
@@ -30,13 +25,9 @@ module Boxen
|
|
30
25
|
end
|
31
26
|
end
|
32
27
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
password = `#{cmd}`.strip
|
37
|
-
password = nil unless $?.success?
|
38
|
-
|
39
|
-
config.password = password
|
28
|
+
keychain = Boxen::Keychain.new config.user
|
29
|
+
config.password = keychain.password
|
30
|
+
config.token = keychain.token
|
40
31
|
|
41
32
|
yield config if block_given?
|
42
33
|
end
|
@@ -56,7 +47,6 @@ module Boxen
|
|
56
47
|
:repodir => config.repodir,
|
57
48
|
:reponame => config.reponame,
|
58
49
|
:srcdir => config.srcdir,
|
59
|
-
:token => config.token,
|
60
50
|
:user => config.user
|
61
51
|
}
|
62
52
|
|
@@ -67,12 +57,9 @@ module Boxen
|
|
67
57
|
f.write JSON.generate Hash[attrs.reject { |k, v| v.nil? }]
|
68
58
|
end
|
69
59
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
unless system *cmd
|
74
|
-
raise Boxen::Error, "Can't save config in the Keychain."
|
75
|
-
end
|
60
|
+
keychain = Boxen::Keychain.new config.user
|
61
|
+
keychain.password = config.password
|
62
|
+
keychain.token = config.token
|
76
63
|
|
77
64
|
config
|
78
65
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "shellwords"
|
2
|
+
|
3
|
+
module Boxen
|
4
|
+
class Keychain
|
5
|
+
|
6
|
+
# The keychain proxy we use to provide isolation and a friendly
|
7
|
+
# message in security prompts.
|
8
|
+
|
9
|
+
HELPER = File.expand_path "../../../script/Boxen", __FILE__
|
10
|
+
|
11
|
+
# The service name to use when loading/saving passwords.
|
12
|
+
|
13
|
+
PASSWORD_SERVICE = "GitHub Password"
|
14
|
+
|
15
|
+
# The service name to use when loading/saving API keys.
|
16
|
+
|
17
|
+
TOKEN_SERVICE = "GitHub API Token"
|
18
|
+
|
19
|
+
def initialize(login)
|
20
|
+
@login = login
|
21
|
+
end
|
22
|
+
|
23
|
+
def password
|
24
|
+
get PASSWORD_SERVICE
|
25
|
+
end
|
26
|
+
|
27
|
+
def password=(password)
|
28
|
+
set PASSWORD_SERVICE, password
|
29
|
+
end
|
30
|
+
|
31
|
+
def token
|
32
|
+
get TOKEN_SERVICE
|
33
|
+
end
|
34
|
+
|
35
|
+
def token=(token)
|
36
|
+
set TOKEN_SERVICE, token
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
attr_reader :login
|
42
|
+
|
43
|
+
def get(service)
|
44
|
+
cmd = shellescape(HELPER, service, login)
|
45
|
+
|
46
|
+
result = `#{cmd}`.strip
|
47
|
+
$?.success? ? result : nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def set(service, password)
|
51
|
+
cmd = shellescape(HELPER, service, login, password)
|
52
|
+
|
53
|
+
unless system *cmd
|
54
|
+
raise Boxen::Error, "Can't save #{service} in the keychain."
|
55
|
+
end
|
56
|
+
|
57
|
+
password
|
58
|
+
end
|
59
|
+
|
60
|
+
def shellescape(*args)
|
61
|
+
args.map { |s| Shellwords.shellescape s }.join " "
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/script/Boxen
ADDED
Binary file
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <Security/Security.h>
|
4
|
+
|
5
|
+
int key_exists_p(
|
6
|
+
const char *service,
|
7
|
+
const char *login,
|
8
|
+
SecKeychainItemRef *item
|
9
|
+
) {
|
10
|
+
void *buf;
|
11
|
+
UInt32 len;
|
12
|
+
|
13
|
+
OSStatus ret = SecKeychainFindGenericPassword(
|
14
|
+
NULL, strlen(service), service, strlen(login), login, &len, &buf, item
|
15
|
+
);
|
16
|
+
|
17
|
+
if (ret == 0) {
|
18
|
+
return 0;
|
19
|
+
} else {
|
20
|
+
fprintf(stderr, "Boxen Keychain Helper: Encountered error code: %d\n", ret);
|
21
|
+
return ret;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
int main(int argc, char **argv) {
|
26
|
+
if ((argc < 3) || (argc > 4)) {
|
27
|
+
printf("Usage: %s <service> <account> [<password>]\n", argv[0]);
|
28
|
+
return 1;
|
29
|
+
}
|
30
|
+
|
31
|
+
const char *service = argv[1];
|
32
|
+
const char *login = argv[2];
|
33
|
+
const char *password = argc == 4 ? argv[3] : NULL;
|
34
|
+
|
35
|
+
void *buf;
|
36
|
+
UInt32 len;
|
37
|
+
SecKeychainItemRef item;
|
38
|
+
|
39
|
+
if (password != NULL) {
|
40
|
+
if (key_exists_p(service, login, &item) == 0) {
|
41
|
+
SecKeychainItemDelete(item);
|
42
|
+
}
|
43
|
+
|
44
|
+
OSStatus create_key = SecKeychainAddGenericPassword(
|
45
|
+
NULL, strlen(service), service, strlen(login), login, strlen(password),
|
46
|
+
password, &item
|
47
|
+
);
|
48
|
+
|
49
|
+
if (create_key != 0) {
|
50
|
+
fprintf(stderr, "Boxen Keychain Helper: Encountered error code: %d\n", create_key);
|
51
|
+
return 1;
|
52
|
+
}
|
53
|
+
|
54
|
+
} else {
|
55
|
+
OSStatus find_key = SecKeychainFindGenericPassword(
|
56
|
+
NULL, strlen(service), service, strlen(login), login, &len, &buf, &item);
|
57
|
+
|
58
|
+
if (find_key != 0) {
|
59
|
+
fprintf(stderr, "Boxen Keychain Helper: Encountered error code: %d\n", find_key);
|
60
|
+
return 1;
|
61
|
+
}
|
62
|
+
|
63
|
+
fwrite(buf, 1, len, stdout);
|
64
|
+
}
|
65
|
+
|
66
|
+
return 0;
|
67
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "boxen/test"
|
2
|
+
require "boxen/keychain"
|
3
|
+
|
4
|
+
class BoxenKeychainTest < Boxen::Test
|
5
|
+
def setup
|
6
|
+
@keychain = Boxen::Keychain.new('test')
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_get_password
|
10
|
+
@keychain.expects(:get).with('GitHub Password').returns('foobar')
|
11
|
+
assert_equal 'foobar', @keychain.password
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_set_password
|
15
|
+
@keychain.expects(:set).with('GitHub Password', 'foobar').returns('foobar')
|
16
|
+
assert_equal 'foobar', @keychain.password=('foobar')
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_get_token
|
20
|
+
@keychain.expects(:get).with('GitHub API Token').returns('foobar')
|
21
|
+
assert_equal 'foobar', @keychain.token
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_set_token
|
25
|
+
@keychain.expects(:set).with('GitHub API Token', 'foobar').returns('foobar')
|
26
|
+
assert_equal 'foobar', @keychain.token=('foobar')
|
27
|
+
end
|
28
|
+
end
|
metadata
CHANGED
@@ -3,10 +3,10 @@ name: boxen
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
-
- 0
|
7
|
-
- 8
|
8
6
|
- 1
|
9
|
-
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- John Barnette
|
@@ -170,6 +170,7 @@ files:
|
|
170
170
|
- lib/boxen/hook.rb
|
171
171
|
- lib/boxen/hook/github_issue.rb
|
172
172
|
- lib/boxen/hook/web.rb
|
173
|
+
- lib/boxen/keychain.rb
|
173
174
|
- lib/boxen/postflight.rb
|
174
175
|
- lib/boxen/postflight/active.rb
|
175
176
|
- lib/boxen/postflight/env.rb
|
@@ -189,9 +190,12 @@ files:
|
|
189
190
|
- lib/boxen/util.rb
|
190
191
|
- lib/facter/boxen.rb
|
191
192
|
- lib/system_timer.rb
|
193
|
+
- script/Boxen
|
192
194
|
- script/bootstrap
|
195
|
+
- script/build-keychain-helper
|
193
196
|
- script/release
|
194
197
|
- script/tests
|
198
|
+
- src/keychain-helper.c
|
195
199
|
- test/boxen/test.rb
|
196
200
|
- test/boxen_check_test.rb
|
197
201
|
- test/boxen_checkout_test.rb
|
@@ -201,6 +205,7 @@ files:
|
|
201
205
|
- test/boxen_flags_test.rb
|
202
206
|
- test/boxen_hook_github_issue_test.rb
|
203
207
|
- test/boxen_hook_web_test.rb
|
208
|
+
- test/boxen_keychain_test.rb
|
204
209
|
- test/boxen_postflight_active_test.rb
|
205
210
|
- test/boxen_postflight_env_test.rb
|
206
211
|
- test/boxen_preflight_etc_my_cnf_test.rb
|
@@ -254,6 +259,7 @@ test_files:
|
|
254
259
|
- test/boxen_flags_test.rb
|
255
260
|
- test/boxen_hook_github_issue_test.rb
|
256
261
|
- test/boxen_hook_web_test.rb
|
262
|
+
- test/boxen_keychain_test.rb
|
257
263
|
- test/boxen_postflight_active_test.rb
|
258
264
|
- test/boxen_postflight_env_test.rb
|
259
265
|
- test/boxen_preflight_etc_my_cnf_test.rb
|