zanzibar 0.1.13 → 0.1.15
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.
- checksums.yaml +8 -8
- data/.gitignore +3 -0
- data/.rspec +1 -1
- data/.rubocop.yml +5 -0
- data/Gemfile +0 -13
- data/README.md +68 -6
- data/Rakefile +11 -11
- data/bin/zamioculcas +3 -1
- data/bin/zanzibar +2 -68
- data/lib/zanzibar/actions/base.rb +27 -0
- data/lib/zanzibar/actions/bundle.rb +119 -0
- data/lib/zanzibar/actions/get.rb +61 -0
- data/lib/zanzibar/actions/init.rb +40 -0
- data/lib/zanzibar/actions.rb +3 -0
- data/lib/zanzibar/cli.rb +126 -0
- data/lib/zanzibar/defaults.rb +14 -0
- data/lib/zanzibar/error.rb +6 -0
- data/lib/zanzibar/ui.rb +42 -0
- data/lib/zanzibar/version.rb +4 -3
- data/lib/zanzibar.rb +190 -190
- data/spec/files/.gitignore +1 -0
- data/spec/files/Zanzifile +11 -0
- data/spec/files/scrt.wsdl +629 -0
- data/spec/lib/zanzibar/actions/bundle_spec.rb +95 -0
- data/spec/lib/zanzibar/actions/get_spec.rb +64 -0
- data/spec/lib/zanzibar/actions/init_spec.rb +53 -0
- data/spec/lib/zanzibar/version_spec.rb +12 -0
- data/spec/{zanzibar_spec.rb → lib/zanzibar_spec.rb} +116 -123
- data/spec/spec_helper.rb +37 -0
- data/templates/Zanzifile.erb +11 -0
- data/zanzibar.gemspec +12 -4
- metadata +142 -19
- data/spec/spec/spec_helper.rb +0 -95
checksums.yaml
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
!binary "U0hBMQ==":
|
|
3
3
|
metadata.gz: !binary |-
|
|
4
|
-
|
|
4
|
+
ODVkZWYyOTM0OWZkZjkzNTBjNmNkOWJkNThiYzRkNTc1MGQ4YjJlZQ==
|
|
5
5
|
data.tar.gz: !binary |-
|
|
6
|
-
|
|
6
|
+
NWJlM2NhM2ZiMWMzMGVjZmQ4YWVkNGY5MjVhODVlMjY5MTVjZTRjNg==
|
|
7
7
|
SHA512:
|
|
8
8
|
metadata.gz: !binary |-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
ZjVmNDdiMmVhZTA0MDg5MTNhNWM0OWM2ZTQyMWViNmE5ZjJmNGFkMjIxOWVi
|
|
10
|
+
Y2FjYjlkYzcyMWUzOGJhMmExOGY3MTljMWZkOTI1ZGEzZWE0Yjc1ZDU5NDE0
|
|
11
|
+
NDg5YWFkNTllOWNlZDkwNmRlNGI3MTRkNjFhY2QwNWQ2YjMxMGI=
|
|
12
12
|
data.tar.gz: !binary |-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
YmMwZGYyZGZlODEzMjkyN2UxZTc2YzhiMjAzZGZjN2M2OGI2OGZmMWY0ZThl
|
|
14
|
+
MjdlZjQ4NDc3OWRkMGZkYTNkYjEwM2ZhYWE1ZDkxOTI0YjdkNGNlZGE5N2Zh
|
|
15
|
+
NDgxOGNkM2I4NTAwZDc0ZGViYWQ4NjZkZGI5MjM4NDMzMDM0ODc=
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
--color
|
|
2
|
-
--require
|
|
2
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
data/Gemfile
CHANGED
|
@@ -1,16 +1,3 @@
|
|
|
1
1
|
source 'https://rubygems.org'
|
|
2
2
|
|
|
3
|
-
gem 'savon'
|
|
4
|
-
|
|
5
|
-
group :test do
|
|
6
|
-
gem 'rake'
|
|
7
|
-
gem 'savon_spec'
|
|
8
|
-
gem 'rspec'
|
|
9
|
-
gem 'webmock'
|
|
10
|
-
gem 'codeclimate-test-reporter'
|
|
11
|
-
gem 'zanzibar', path: '.'
|
|
12
|
-
gem 'rubocop'
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# Specify your gem's dependencies in zanzibar.gemspec
|
|
16
3
|
gemspec
|
data/README.md
CHANGED
|
@@ -21,7 +21,11 @@ Or install it yourself as:
|
|
|
21
21
|
|
|
22
22
|
## Usage
|
|
23
23
|
|
|
24
|
-
In your ruby project, rakefile, etc., create a new Zanzibar object.
|
|
24
|
+
In your ruby project, rakefile, etc., create a new Zanzibar object.
|
|
25
|
+
|
|
26
|
+
The constructor takes a hash of optional parameters for the WSDL location, the domain of the Secret Server, a hash of global variables to pass to savon (necessary for windows environments with self-signed certs) and a password for the current user (intended to be passed in through some encryption method, unless you really want a plaintext password there).
|
|
27
|
+
|
|
28
|
+
All of these parameters are optional and the user will be prompted to enter them if they are missing.
|
|
25
29
|
|
|
26
30
|
```ruby
|
|
27
31
|
my_object = Zanzibar::Zanzibar.new(:domain => 'my.domain.net', :wsdl => 'my.scrt.srvr.com/webservices/sswebservice.asmx?wdsl', :pwd => get_encrypted_password_from_somewhere)
|
|
@@ -51,20 +55,78 @@ secrets.download_secret_file(:scrt_id => 2345, :path => 'secrets/', :type => "At
|
|
|
51
55
|
|
|
52
56
|
```
|
|
53
57
|
|
|
58
|
+
### Providing Credentials
|
|
59
|
+
|
|
60
|
+
Zanzibar has several ways of finding Secret Server credentials. It will use credentials
|
|
61
|
+
discovered in this order:
|
|
62
|
+
|
|
63
|
+
* Credentials passed to the initializer
|
|
64
|
+
* `Zanzibar::Zanzibar.new(:username=>'auser', :password=>'itsmyPassword')`
|
|
65
|
+
* Credentials discovered via the environment
|
|
66
|
+
* If `ZANZIBAR_USER` exists, it will use that.
|
|
67
|
+
* If not, it will try `USER`
|
|
68
|
+
* If `ZANZIBAR_PASSWORD` exists, it will use that.
|
|
69
|
+
* Credentials entered by the user
|
|
70
|
+
* Zanzibar will prompt the user to enter their password on STDIN
|
|
71
|
+
|
|
54
72
|
### Command Line
|
|
55
73
|
|
|
56
|
-
Zanzibar comes bundled with the `zanzibar` command-line utility that can be used
|
|
74
|
+
Zanzibar comes bundled with the `zanzibar` command-line utility that can be used
|
|
75
|
+
for fetching passwords and downloading keys from outside of Ruby scripts.
|
|
57
76
|
|
|
58
|
-
`zanzibar` supports most actions provided by Zanzibar itself. Because it operates
|
|
77
|
+
`zanzibar` supports most actions provided by Zanzibar itself. Because it operates
|
|
78
|
+
on the command-line, it can be used as part of a pipeline or within a bash script.
|
|
59
79
|
|
|
60
80
|
```bash
|
|
61
|
-
# if
|
|
81
|
+
# if ZANZIBAR_PASSWORD is not set, you will be prompted to enter your password.
|
|
62
82
|
# this will download the private key from secret 1984 to the current directory
|
|
63
|
-
|
|
83
|
+
$ ZANZIBAR_PASSWORD=`gpg -d secretpasswd.txt.gpg` zanzibar get 1984 -s server.example.com -d example.com -f "Private Key"
|
|
84
|
+
|
|
85
|
+
$ ssh user@someremote -i ./private_key
|
|
86
|
+
```
|
|
64
87
|
|
|
65
|
-
|
|
88
|
+
#### Zanzifiles
|
|
89
|
+
|
|
90
|
+
The `zanzibar` command can also perform [bundler](http://bundler.io)-like actions.
|
|
91
|
+
Running `zanzibar init` will generate a `Zanzifile` in the current directory.
|
|
92
|
+
Information about Secret Server and the necessary secret files to be downloaded
|
|
93
|
+
can be added here.
|
|
94
|
+
|
|
95
|
+
Then `zanzibar bundle` will try to download the secrets named in the file.
|
|
96
|
+
When it downloads a file, it gets added to `Zanzifile.resolved`. And next time
|
|
97
|
+
`zanzibar bundle` is run, if the file exists and the hash matches the one in the
|
|
98
|
+
`resolved` file, it will not attempt to re-download. `zanzibar update` will attempt
|
|
99
|
+
to re-download all secrets.
|
|
100
|
+
|
|
101
|
+
Note: `zanzibar get` can fetch passwords or files, but `zanzibar bundle` can
|
|
102
|
+
only operate on secret files.
|
|
103
|
+
|
|
104
|
+
Sample `Zanzifile`:
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
---
|
|
108
|
+
settings:
|
|
109
|
+
wsdl: my.scrt.srvr.com/webservices/sswebservice.asmx?wdsl
|
|
110
|
+
domain: my.domain.net
|
|
111
|
+
secret_dir: secrets/
|
|
112
|
+
ignore_ssl: true
|
|
113
|
+
secrets:
|
|
114
|
+
ssh_key:
|
|
115
|
+
id: 249
|
|
116
|
+
label: Private Key
|
|
117
|
+
encryption_key:
|
|
118
|
+
id: 483
|
|
119
|
+
label: Attachment
|
|
120
|
+
cert_pem:
|
|
121
|
+
id: 123
|
|
122
|
+
label: Certificate
|
|
123
|
+
cert_key:
|
|
124
|
+
id: 986
|
|
125
|
+
label: Misc Attachment
|
|
66
126
|
```
|
|
67
127
|
|
|
128
|
+
Run `zanzibar help` or `zanzibar help [command]` for more information.
|
|
129
|
+
|
|
68
130
|
## Contributing
|
|
69
131
|
|
|
70
132
|
1. Fork it ( https://github.com/Cimpress-MCP/zanzibar/fork )
|
data/Rakefile
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
require 'bundler/gem_tasks'
|
|
2
|
-
require 'bundler/setup' # load up our gem environment (incl. local zanzibar)
|
|
3
|
-
require 'rspec/core/rake_task'
|
|
4
|
-
require 'zanzibar/version'
|
|
5
|
-
require 'rubocop/rake_task'
|
|
6
|
-
|
|
7
|
-
task default: [:test]
|
|
8
|
-
|
|
9
|
-
RSpec::Core::RakeTask.new(:test)
|
|
10
|
-
|
|
11
|
-
RuboCop::RakeTask.new
|
|
1
|
+
require 'bundler/gem_tasks'
|
|
2
|
+
require 'bundler/setup' # load up our gem environment (incl. local zanzibar)
|
|
3
|
+
require 'rspec/core/rake_task'
|
|
4
|
+
require 'zanzibar/version'
|
|
5
|
+
require 'rubocop/rake_task'
|
|
6
|
+
|
|
7
|
+
task default: [:test]
|
|
8
|
+
|
|
9
|
+
RSpec::Core::RakeTask.new(:test)
|
|
10
|
+
|
|
11
|
+
RuboCop::RakeTask.new
|
data/bin/zamioculcas
CHANGED
data/bin/zanzibar
CHANGED
|
@@ -1,70 +1,4 @@
|
|
|
1
1
|
#! ruby
|
|
2
|
+
require 'zanzibar/cli'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
require 'optparse'
|
|
5
|
-
|
|
6
|
-
options = {
|
|
7
|
-
:domain => 'local'
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
OptionParser.new do |opts|
|
|
11
|
-
opts.banner = "Usage: zamioculcas -d domain [-w wsdl] [-k] [-p] [secret_id]"
|
|
12
|
-
|
|
13
|
-
opts.on("-d", "--domain DOMAIN", "Specify domain") do |v|
|
|
14
|
-
options[:domain] = v
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
opts.on("-w", "--wsdl WSDL", "Specify WSDL location") do |v|
|
|
18
|
-
options[:wsdl] = v
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
opts.on("-s", "--server SERVER", "Secret server hostname or IP") do |v|
|
|
22
|
-
options[:server] = v
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
opts.on("-k", "--no-check-certificate", "Don't run SSL certificate checks") do |v|
|
|
26
|
-
options[:globals] = {:ssl_verify_mode => :none}
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
opts.on("-p", "--password PASSWORD", "Specify password") do |v|
|
|
30
|
-
options[:pwd] = v
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
opts.on("-t", "--type TYPE", "Specify the type of secret") do |v|
|
|
34
|
-
options[:type] = v
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
opts.on("-u", "--user USER", "Specify the username") do |v|
|
|
38
|
-
options[:username] = v
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
end.parse!
|
|
42
|
-
|
|
43
|
-
raise OptionParser::MissingArgument if options[:server].nil?
|
|
44
|
-
options[:type] = "password" if options[:type].nil?
|
|
45
|
-
|
|
46
|
-
unless STDIN.tty? || options[:pwd]
|
|
47
|
-
options[:pwd] = $stdin.read.strip
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
secret_id = Integer(ARGV.pop)
|
|
51
|
-
if(!secret_id)
|
|
52
|
-
fail "no secret!"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
unless options[:wsdl] || options[:server].nil?
|
|
56
|
-
options[:wsdl] = "https://#{options[:server]}/webservices/sswebservice.asmx?wsdl"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
scrt = Zanzibar::Zanzibar.new(options)
|
|
60
|
-
|
|
61
|
-
case options[:type]
|
|
62
|
-
when "password"
|
|
63
|
-
$stdout.write "#{scrt.get_password(secret_id)}\n"
|
|
64
|
-
when "privatekey"
|
|
65
|
-
scrt.download_private_key(:scrt_id=>secret_id)
|
|
66
|
-
when "publickey"
|
|
67
|
-
scrt.download_public_key(:scrt_id=>secret_id)
|
|
68
|
-
else
|
|
69
|
-
$stderr.write "#{options[:type]} is not a known type."
|
|
70
|
-
end
|
|
4
|
+
Zanzibar::Cli.start(ARGV)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Zanzibar
|
|
2
|
+
module Actions
|
|
3
|
+
# Basic plumbing for all actions
|
|
4
|
+
class Base
|
|
5
|
+
attr_accessor :options
|
|
6
|
+
private :options=
|
|
7
|
+
|
|
8
|
+
attr_accessor :logger
|
|
9
|
+
private :logger=
|
|
10
|
+
|
|
11
|
+
def initialize(logger, options = {})
|
|
12
|
+
self.logger = logger
|
|
13
|
+
self.options = options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def debug(*args, &block)
|
|
19
|
+
logger.debug(*args, &block)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def source_root
|
|
23
|
+
@source_root ||= Pathname.new(File.expand_path('../../../../', __FILE__))
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
require 'zanzibar/actions/base'
|
|
2
|
+
require 'zanzibar/error'
|
|
3
|
+
require 'zanzibar'
|
|
4
|
+
|
|
5
|
+
module Zanzibar
|
|
6
|
+
module Actions
|
|
7
|
+
# Download or verify the secrets in a Zanzifile
|
|
8
|
+
class Bundle < Base
|
|
9
|
+
attr_accessor :settings
|
|
10
|
+
attr_accessor :remote_secrets
|
|
11
|
+
attr_accessor :local_secrets
|
|
12
|
+
attr_accessor :update
|
|
13
|
+
attr_accessor :zanzibar
|
|
14
|
+
|
|
15
|
+
def initialize(ui, options, args = {})
|
|
16
|
+
super(ui, options)
|
|
17
|
+
@update = args[:update]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def run
|
|
21
|
+
ensure_zanzifile
|
|
22
|
+
load_required_secrets
|
|
23
|
+
validate_environment
|
|
24
|
+
load_resolved_secrets if resolved_file?
|
|
25
|
+
validate_local_secrets unless @update
|
|
26
|
+
run!
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def run!
|
|
32
|
+
if need_secrets?
|
|
33
|
+
new_secrets = download_remote_secrets
|
|
34
|
+
update_resolved_file new_secrets
|
|
35
|
+
else
|
|
36
|
+
debug { 'No secrets to download...' }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def ensure_zanzifile
|
|
41
|
+
fail Error, NO_ZANZIFILE_ERROR unless File.exist? ZANZIFILE_NAME
|
|
42
|
+
debug { "#{ZANZIFILE_NAME} located..." }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def resolved_file?
|
|
46
|
+
File.exist? RESOLVED_NAME
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def load_required_secrets
|
|
50
|
+
zanzifile = YAML.load_file(ZANZIFILE_NAME)
|
|
51
|
+
@settings = zanzifile['settings'] || {}
|
|
52
|
+
@remote_secrets = zanzifile['secrets'] || {}
|
|
53
|
+
@local_secrets = {}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def validate_environment
|
|
57
|
+
return unless @settings.empty? || @remote_secrets.empty?
|
|
58
|
+
fail Error, INVALID_ZANZIFILE_ERROR
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def load_resolved_secrets
|
|
62
|
+
@local_secrets = YAML.load_file RESOLVED_NAME
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def need_secrets?
|
|
66
|
+
!@remote_secrets.empty?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def validate_local_secrets
|
|
70
|
+
@local_secrets.each do |key, secret|
|
|
71
|
+
if File.exist?(secret[:path]) && secret[:hash] == Digest::MD5.file(secret[:path]).hexdigest
|
|
72
|
+
debug { "#{key} found locally, skipping download..." }
|
|
73
|
+
@remote_secrets.delete key
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def download_remote_secrets
|
|
79
|
+
args = @settings['ignore_ssl'] ? { ssl_verify_mode: :none } : {}
|
|
80
|
+
|
|
81
|
+
downloaded_secrets = {}
|
|
82
|
+
remote_secrets.each do |key, secret|
|
|
83
|
+
downloaded_secrets[key] = download_one_secret(secret['id'],
|
|
84
|
+
secret['label'],
|
|
85
|
+
@settings['secret_dir'],
|
|
86
|
+
args)
|
|
87
|
+
|
|
88
|
+
debug { "Downloaded secret: #{key} to #{path}..." }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
downloaded_secrets
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def download_one_secret(scrt_id, label, path, args)
|
|
95
|
+
path = zanzibar(args).download_secret_file(scrt_id: scrt_id,
|
|
96
|
+
type: label,
|
|
97
|
+
path: path)
|
|
98
|
+
|
|
99
|
+
{ path: path, hash: Digest::MD5.file(path).hexdigest }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def update_resolved_file(new_secrets)
|
|
103
|
+
@local_secrets.merge! new_secrets
|
|
104
|
+
|
|
105
|
+
File.open(RESOLVED_NAME, 'w') do |out|
|
|
106
|
+
YAML.dump(@local_secrets, out)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
debug { 'Updated resolved file...' }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def zanzibar(args)
|
|
113
|
+
@zanzibar ||= ::Zanzibar::Zanzibar.new(wsdl: @settings['wsdl'],
|
|
114
|
+
domain: @settings['domain'],
|
|
115
|
+
globals: args)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require 'zanzibar/actions/base'
|
|
2
|
+
require 'zanzibar/error'
|
|
3
|
+
require 'zanzibar'
|
|
4
|
+
require 'zanzibar/defaults'
|
|
5
|
+
|
|
6
|
+
module Zanzibar
|
|
7
|
+
module Actions
|
|
8
|
+
# Fetch a single secret
|
|
9
|
+
class Get < Base
|
|
10
|
+
attr_accessor :zanibar_options
|
|
11
|
+
attr_accessor :scrt_id
|
|
12
|
+
|
|
13
|
+
def initialize(ui, options, scrt_id)
|
|
14
|
+
super(ui, options)
|
|
15
|
+
@scrt_id = scrt_id
|
|
16
|
+
@zanzibar_options = {}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def run
|
|
20
|
+
construct_options
|
|
21
|
+
ensure_options
|
|
22
|
+
|
|
23
|
+
fetch_secret(@scrt_id, options['filelabel'])
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def fetch_secret(scrt_id, label = nil)
|
|
27
|
+
scrt = ::Zanzibar::Zanzibar.new(@zanzibar_options)
|
|
28
|
+
|
|
29
|
+
puts @zanzibar_options
|
|
30
|
+
|
|
31
|
+
if label
|
|
32
|
+
scrt.download_secret_file(scrt_id: scrt_id,
|
|
33
|
+
type: label)
|
|
34
|
+
else
|
|
35
|
+
scrt.get_password(scrt_id)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def construct_options
|
|
40
|
+
@zanzibar_options[:wsdl] = construct_wsdl
|
|
41
|
+
@zanzibar_options[:globals] = { ssl_verify_mode: :none } if options['ignoressl']
|
|
42
|
+
@zanzibar_options[:domain] = options['domain']
|
|
43
|
+
@zanzibar_options[:username] = options['username'] unless options['username'].nil?
|
|
44
|
+
@zanzibar_options[:domain] = options['domain'] ? options['domain'] : 'local'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def construct_wsdl
|
|
48
|
+
if options['wsdl'].nil? && options['server']
|
|
49
|
+
DEFAULT_WSDL % options['server']
|
|
50
|
+
else
|
|
51
|
+
options['wsdl']
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def ensure_options
|
|
56
|
+
return if @zanzibar_options[:wsdl]
|
|
57
|
+
fail Error, NO_WSDL_ERROR
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'zanzibar/actions/base'
|
|
2
|
+
require 'zanzibar/error'
|
|
3
|
+
require 'ostruct'
|
|
4
|
+
require 'erb'
|
|
5
|
+
require 'zanzibar/defaults'
|
|
6
|
+
|
|
7
|
+
module Zanzibar
|
|
8
|
+
module Actions
|
|
9
|
+
# Create a new Zanzifile
|
|
10
|
+
class Init < Base
|
|
11
|
+
def run
|
|
12
|
+
check_for_zanzifile
|
|
13
|
+
write_template
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def check_for_zanzifile
|
|
19
|
+
return unless File.exist?(ZANZIFILE_NAME) && !options['force']
|
|
20
|
+
fail Error, ALREADY_EXISTS_ERROR
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def write_template
|
|
24
|
+
template = TemplateRenderer.new(options)
|
|
25
|
+
|
|
26
|
+
File.open(ZANZIFILE_NAME, 'w') do |f|
|
|
27
|
+
f.write template.render(File.read(source_root.join(TEMPLATE_NAME)))
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Allows us to easily feed our options hash
|
|
32
|
+
# to an ERB
|
|
33
|
+
class TemplateRenderer < OpenStruct
|
|
34
|
+
def render(template)
|
|
35
|
+
ERB.new(template).result(binding)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/zanzibar/cli.rb
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require 'thor'
|
|
2
|
+
require 'thor/actions'
|
|
3
|
+
require 'zanzibar/version'
|
|
4
|
+
require 'zanzibar/cli'
|
|
5
|
+
require 'zanzibar/ui'
|
|
6
|
+
require 'zanzibar/actions'
|
|
7
|
+
require 'zanzibar/error'
|
|
8
|
+
require 'zanzibar/defaults'
|
|
9
|
+
|
|
10
|
+
module Zanzibar
|
|
11
|
+
# The `zanzibar` binay/thor application main class
|
|
12
|
+
class Cli < Thor
|
|
13
|
+
include Thor::Actions
|
|
14
|
+
|
|
15
|
+
attr_accessor :ui
|
|
16
|
+
|
|
17
|
+
def initialize(*)
|
|
18
|
+
super
|
|
19
|
+
the_shell = (options['no-color'] ? Thor::Shell::Basic.new : shell)
|
|
20
|
+
@ui = Shell.new(the_shell)
|
|
21
|
+
@ui.be_quiet! if options['quiet']
|
|
22
|
+
@ui.debug! if options['verbose']
|
|
23
|
+
|
|
24
|
+
debug_header
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
desc 'version', 'Display your Zanzibar verion'
|
|
28
|
+
def version
|
|
29
|
+
say "#{APPLICATION_NAME} Version: #{VERSION}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
desc 'init', "Create an empty #{ZANZIFILE_NAME} in the current directory."
|
|
33
|
+
option 'verbose', type: :boolean, default: false, aliases: :v
|
|
34
|
+
option 'wsdl', type: :string, aliases: :w,
|
|
35
|
+
default: DEFAULT_WSDL % DEFAULT_SERVER,
|
|
36
|
+
desc: 'The URI of the WSDL file for your Secret Server instance'
|
|
37
|
+
option 'domain', type: :string, default: 'local', aliases: :d,
|
|
38
|
+
desc: 'The logon domain for your Secret Server account'
|
|
39
|
+
option 'force', type: :boolean, default: false, aliases: :f,
|
|
40
|
+
desc: 'Recreate the Zanzifile if one already exists.'
|
|
41
|
+
option 'secretdir', type: :string, default: 'secrets/', aliases: :s,
|
|
42
|
+
desc: 'The directory to which secrets should be downloaded.'
|
|
43
|
+
option 'ignoressl', type: :boolean, default: 'false', aliases: :k,
|
|
44
|
+
desc: 'Don\'t check the SSL certificate of Secret Server'
|
|
45
|
+
def init
|
|
46
|
+
run_action { init! }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
desc 'bundle', "Fetch secrets declared in your #{ZANZIFILE_NAME}"
|
|
50
|
+
option 'verbose', type: :boolean, default: false, aliases: :v
|
|
51
|
+
def bundle
|
|
52
|
+
run_action { bundle! }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
desc 'plunder', "Alias to `#{APPLICATION_NAME} bundle`", :hide => true
|
|
56
|
+
alias_method :plunder, :bundle
|
|
57
|
+
|
|
58
|
+
desc 'install', "Alias to `#{APPLICATION_NAME} bundle`"
|
|
59
|
+
alias_method :install, :bundle
|
|
60
|
+
|
|
61
|
+
desc 'update', "Redownload all secrets in your #{ZANZIFILE_NAME}"
|
|
62
|
+
option 'verbose', type: :boolean, default: false, aliases: :v
|
|
63
|
+
def update
|
|
64
|
+
run_action { update! }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
desc 'get SECRETID', 'Fetch a single SECRETID from Secret Server'
|
|
68
|
+
option 'domain', type: :string, aliases: :d,
|
|
69
|
+
desc: 'The logon domain to use when logging in.'
|
|
70
|
+
option 'server', type: :string, aliases: :s,
|
|
71
|
+
desc: 'The Secret Server hostname or IP'
|
|
72
|
+
option 'wsdl', type: :string, aliases: :w,
|
|
73
|
+
desc: 'Full path to the Secret Server WSDL'
|
|
74
|
+
option 'ignoressl', type: :boolean, aliases: :k,
|
|
75
|
+
desc: 'Don\'t verify Secret Server\'s SSL certificate'
|
|
76
|
+
option 'filelabel', type: :string, aliases: :f,
|
|
77
|
+
desc: 'Specify a file (by label) to download'
|
|
78
|
+
option 'username', type: :string, aliases: :u
|
|
79
|
+
option 'password', type: :string, aliases: :p
|
|
80
|
+
def get(scrt_id)
|
|
81
|
+
run_action { get! scrt_id }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def debug_header
|
|
87
|
+
@ui.debug { "Running #{APPLICATION_NAME} in debug mode..." }
|
|
88
|
+
@ui.debug { "Ruby Version: #{RUBY_VERSION}" }
|
|
89
|
+
@ui.debug { "Ruby Platform: #{RUBY_PLATFORM}" }
|
|
90
|
+
@ui.debug { "#{APPLICATION_NAME} Version: #{VERSION}" }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Run the specified action and rescue errors we
|
|
94
|
+
# explicitly send back to format them
|
|
95
|
+
def run_action(&_block)
|
|
96
|
+
yield
|
|
97
|
+
rescue ::Zanzibar::Error => e
|
|
98
|
+
@ui.error e
|
|
99
|
+
abort "Fatal error: #{e.message}"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def init!
|
|
103
|
+
say "Initializing a new #{ZANZIFILE_NAME} in the current directory..."
|
|
104
|
+
Actions::Init.new(@ui, options).run
|
|
105
|
+
say "Your #{ZANZIFILE_NAME} has been created!"
|
|
106
|
+
say 'You should check the settings and add your secrets.'
|
|
107
|
+
say 'Then run `zanzibar bundle` to fetch them.'
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def bundle!
|
|
111
|
+
say "Checking for secrets declared in your #{ZANZIFILE_NAME}..."
|
|
112
|
+
Actions::Bundle.new(@ui, options).run
|
|
113
|
+
say 'Finished downloading secrets!'
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def update!
|
|
117
|
+
say "Redownloading all secrets declared in your #{ZANZIFILE_NAME}..."
|
|
118
|
+
Actions::Bundle.new(@ui, options, update: true).run
|
|
119
|
+
say 'Finished downloading secrets!'
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def get!(scrt_id)
|
|
123
|
+
say Actions::Get.new(@ui, options, scrt_id).run
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Definitions for various strings used throughout the gem
|
|
2
|
+
module Zanzibar
|
|
3
|
+
APPLICATION_NAME = Pathname.new($PROGRAM_NAME).basename
|
|
4
|
+
ZANZIFILE_NAME = 'Zanzifile'
|
|
5
|
+
RESOLVED_NAME = 'Zanzifile.resolved'
|
|
6
|
+
TEMPLATE_NAME = 'templates/Zanzifile.erb'
|
|
7
|
+
DEFAULT_SERVER = 'secret.example.com'
|
|
8
|
+
DEFAULT_WSDL = 'https://%s/webservices/sswebservice.asmx?wsdl'
|
|
9
|
+
|
|
10
|
+
ALREADY_EXISTS_ERROR = "#{ZANZIFILE_NAME} already exists! Aborting..."
|
|
11
|
+
NO_WSDL_ERROR = 'Could not construct WSDL URL. Please provide either --server or --wsdl'
|
|
12
|
+
NO_ZANZIFILE_ERROR = "You don't have a #{ZANZIFILE_NAME}! Run `#{APPLICATION_NAME} init` first!"
|
|
13
|
+
INVALID_ZANZIFILE_ERROR = "Unable to load your #{ZANZIFILE_NAME}. Please ensure it is valid YAML."
|
|
14
|
+
end
|