29 Commits

Author SHA1 Message Date
Norm MacLennan
20c5d0e34d bump version 2015-11-20 08:55:43 -05:00
Norm MacLennan
b7558d64f5 Merge pull request #17 from ballou88/fix-for-broken-prompt-for-password
Fix for prompt_for_password
2015-11-20 08:54:56 -05:00
Mike Ballou
293abdacde this is a fix for commit 813b171d26 which
broke the prompt_for_password method and resulted a nil password.
2015-11-19 10:55:42 -08:00
Jason Davis-Cooke
804d044632 Merge pull request #16 from Cimpress-MCP/print-feedback
Print response to indicate when cli is no longer interactive
2015-10-12 08:48:30 -04:00
Theodore X. Pak
813b171d26 Print response to indicate when cli is no longer interactive 2015-10-07 16:04:56 -04:00
Norm MacLennan
7a0ce1c04d Build and test on more rubies
Build and test on 1.9.x, 2.0.x, 2.1.x, 2.2.x. I'd be comfortable-ish dropping 1.9.x and 2.0.x, but it's low effort/high value to just keep them there.

Also, build on containers for speed.
2015-09-18 12:42:39 -04:00
Norm MacLennan
49ea9ab9fa version bump 2015-07-28 10:22:00 -04:00
Norm MacLennan
60e0d52ab4 Merge pull request #12 from thedillonb/patch-1
Update get.rb to remove 'puts'
2015-07-28 10:21:34 -04:00
Dillon Buchanan
e3ec56210b Update get.rb to remove 'puts'
Remove the 'puts' dump of the options as it makes piping the output more difficult. Maybe better to add a verbosity flag and debug prints?
2015-07-28 08:55:54 -04:00
Jason Davis-Cooke
315d3d6499 don't write gitignore if one exists already 2015-06-29 08:50:13 -04:00
Calvin Leung Huang
0763265be1 Update README.md 2015-06-05 11:19:08 -04:00
Jason Davis-Cooke
8126deded5 Version bump 2015-06-05 10:00:37 -04:00
Jason Davis-Cooke
60545c5b7b Merge pull request #10 from Cimpress-MCP/feature/prefix_dir
Feature/prefix dir
2015-06-05 09:59:28 -04:00
Calvin Leung Huang
8b06192aa1 Update test 2015-06-04 14:55:00 -04:00
Calvin Leung Huang
244b9178b8 Add optional prefix option 2015-06-04 13:05:22 -04:00
Jason Davis-Cooke
4951f13e4f version bump 2015-06-03 16:42:16 -04:00
Ryan Breen
3e2c07defc Merge pull request #8 from Cimpress-MCP/addgitignore
Add a gitignore to secrets_dir
2015-06-03 16:33:29 -04:00
Jason Davis-Cooke
73b939808e Update bundle.rb
we need to puts so we get the requisite newlines
2015-06-03 16:27:03 -04:00
Jason Davis-Cooke
867e14214c Update bundle.rb
*, not .
2015-06-03 16:26:19 -04:00
Jason Davis-Cooke
ff99246b46 Update bundle.rb
Don't gitignore the gitignore
2015-06-03 16:24:40 -04:00
Jason Davis-Cooke
e6ec5e6dbd Add a gitignore to secrets_dir 2015-06-03 16:16:56 -04:00
Norm MacLennan
85b8c66d3d readme - wdsl->wsdl 2015-05-19 21:53:45 -04:00
Jason Davis-Cooke
e0e5bfd276 Merge pull request #6 from Cimpress-MCP/savepasswords
Savepasswords
2015-02-26 19:00:35 +00:00
Jason Davis-Cooke
3969d508f8 version bump 2015-02-26 13:46:32 -05:00
Jason Davis-Cooke
2ee47c2210 Save username and password to a Normariffic yaml file 2015-02-26 11:53:48 -05:00
Jason Davis-Cooke
8778c7b27d remove base64 encoding 2015-02-26 09:35:09 -05:00
Jason Davis-Cooke
431c86bb0e remove incorrect code documentation 2015-02-26 08:57:47 -05:00
Jason Davis-Cooke
179fa24ab9 Save zanzifile passwords to disk 2015-02-26 08:56:43 -05:00
Jason Davis-Cooke
ed496bd416 Save zanzifile passwords to file 2015-02-25 14:28:43 -05:00
10 changed files with 96 additions and 19 deletions

View File

@@ -1,7 +1,10 @@
sudo: false
language: ruby language: ruby
rvm: rvm:
- 1.9.3 - 1.9.3
- 2.0.0 - 2.0.0
- 2.1.7
- 2.2.3
addons: addons:
code_climate: code_climate:
repo_token: repo_token:

View File

@@ -98,6 +98,8 @@ When it downloads a file, it gets added to `Zanzifile.resolved`. And next time
`resolved` file, it will not attempt to re-download. `zanzibar update` will attempt `resolved` file, it will not attempt to re-download. `zanzibar update` will attempt
to re-download all secrets. to re-download all secrets.
Subdirectories under the root directory `secret_dir` can be created for individual keys by specifying a `prefix` path for that secret. Secrets will default to be downloaded to the root `secret_dir` directory otherwise.
Note: `zanzibar get` can fetch passwords or files, but `zanzibar bundle` can Note: `zanzibar get` can fetch passwords or files, but `zanzibar bundle` can
only operate on secret files. only operate on secret files.
@@ -106,7 +108,7 @@ Sample `Zanzifile`:
```yaml ```yaml
--- ---
settings: settings:
wsdl: my.scrt.srvr.com/webservices/sswebservice.asmx?wdsl wsdl: my.scrt.srvr.com/webservices/sswebservice.asmx?wsdl
domain: my.domain.net domain: my.domain.net
secret_dir: secrets/ secret_dir: secrets/
ignore_ssl: true ignore_ssl: true
@@ -114,6 +116,7 @@ secrets:
ssh_key: ssh_key:
id: 249 id: 249
label: Private Key label: Private Key
prefix: ssh/
encryption_key: encryption_key:
id: 483 id: 483
label: Attachment label: Attachment

View File

@@ -2,6 +2,7 @@ require 'zanzibar/version'
require 'savon' require 'savon'
require 'io/console' require 'io/console'
require 'fileutils' require 'fileutils'
require 'yaml'
module Zanzibar module Zanzibar
## ##
@@ -65,7 +66,9 @@ module Zanzibar
def prompt_for_password def prompt_for_password
puts "Please enter password for #{@@username}:" puts "Please enter password for #{@@username}:"
STDIN.noecho(&:gets).chomp STDIN.noecho(&:gets).chomp.tap do
puts "Using password to login..."
end
end end
## Gets the wsdl document location if none is provided in the constructor ## Gets the wsdl document location if none is provided in the constructor
@@ -123,12 +126,29 @@ module Zanzibar
raise "There was an error getting the password for secret #{scrt_id}: #{err}" raise "There was an error getting the password for secret #{scrt_id}: #{err}"
end end
## Get the password, save it to a file, and return the path to the file.
def get_username_and_password_and_save(scrt_id, path, name)
secret_items = get_secret(scrt_id)[:secret][:items][:secret_item]
password = get_secret_item_by_field_name(secret_items, 'Password')[:value]
username = get_secret_item_by_field_name(secret_items, 'Username')[:value]
save_username_and_password_to_file(password, username, path, name)
return File.join(path, name)
end
def write_secret_to_file(path, secret_response) def write_secret_to_file(path, secret_response)
File.open(File.join(path, secret_response[:file_name]), 'wb') do |file| File.open(File.join(path, secret_response[:file_name]), 'wb') do |file|
file.puts Base64.decode64(secret_response[:file_attachment]) file.puts Base64.decode64(secret_response[:file_attachment])
end end
end end
## Write the password to a file. Intended for use with a Zanzifile
def save_username_and_password_to_file(password, username, path, name)
user_pass = {'username' => username.to_s, 'password' => password.to_s}.to_yaml
File.open(File.join(path, name), 'wb') do |file|
file.print user_pass
end
end
def get_secret_item_by_field_name(secret_items, field_name) def get_secret_item_by_field_name(secret_items, field_name)
secret_items.each do |item| secret_items.each do |item|
return item if item[:field_name] == field_name return item if item[:field_name] == field_name

View File

@@ -20,6 +20,7 @@ module Zanzibar
def run def run
ensure_zanzifile ensure_zanzifile
load_required_secrets load_required_secrets
ensure_secrets_path
validate_environment validate_environment
load_resolved_secrets if resolved_file? load_resolved_secrets if resolved_file?
validate_local_secrets unless @update validate_local_secrets unless @update
@@ -42,6 +43,19 @@ module Zanzibar
debug { "#{ZANZIFILE_NAME} located..." } debug { "#{ZANZIFILE_NAME} located..." }
end end
def ensure_secrets_path
## Make sure the directory exists and that a .gitignore is there to ignore it
if @settings['secret_dir']
FileUtils.mkdir_p(@settings['secret_dir'])
if !File.exist? "#{@settings['secret_dir']}/.gitignore"
File.open("#{@settings['secret_dir']}/.gitignore", 'w') do |file|
file.puts '*'
file.puts '!.gitignore'
end
end
end
end
def resolved_file? def resolved_file?
File.exist? RESOLVED_NAME File.exist? RESOLVED_NAME
end end
@@ -80,24 +94,30 @@ module Zanzibar
downloaded_secrets = {} downloaded_secrets = {}
remote_secrets.each do |key, secret| remote_secrets.each do |key, secret|
full_path = secret.has_key?('prefix') ? File.join(@settings['secret_dir'], secret['prefix']) : @settings['secret_dir']
downloaded_secrets[key] = download_one_secret(secret['id'], downloaded_secrets[key] = download_one_secret(secret['id'],
secret['label'], secret['label'],
@settings['secret_dir'], full_path,
args) args,
secret['name'] || "#{secret['id']}_password")
debug { "Downloaded secret: #{key} to #{path}..." } debug { "Downloaded secret: #{key} to #{@settings['secret_dir']}..." }
end end
downloaded_secrets downloaded_secrets
end end
def download_one_secret(scrt_id, label, path, args) def download_one_secret(scrt_id, label, path, args, name = nil)
if label == 'Password'
path = zanzibar(args).get_username_and_password_and_save(scrt_id, path, name)
{ path: path, hash: Digest::MD5.file(path).hexdigest }
else
path = zanzibar(args).download_secret_file(scrt_id: scrt_id, path = zanzibar(args).download_secret_file(scrt_id: scrt_id,
type: label, type: label,
path: path) path: path)
{ path: path, hash: Digest::MD5.file(path).hexdigest } { path: path, hash: Digest::MD5.file(path).hexdigest }
end end
end
def update_resolved_file(new_secrets) def update_resolved_file(new_secrets)
@local_secrets.merge! new_secrets @local_secrets.merge! new_secrets

View File

@@ -26,8 +26,6 @@ module Zanzibar
def fetch_secret(scrt_id, label = nil) def fetch_secret(scrt_id, label = nil)
scrt = ::Zanzibar::Zanzibar.new(@zanzibar_options) scrt = ::Zanzibar::Zanzibar.new(@zanzibar_options)
puts @zanzibar_options
if label if label
scrt.download_secret_file(scrt_id: scrt_id, scrt.download_secret_file(scrt_id: scrt_id,
type: label) type: label)

View File

@@ -53,6 +53,7 @@ module Zanzibar
end end
desc 'plunder', "Alias to `#{APPLICATION_NAME} bundle`", :hide => true desc 'plunder', "Alias to `#{APPLICATION_NAME} bundle`", :hide => true
option 'verbose', type: :boolean, default: false, aliases: :v
alias_method :plunder, :bundle alias_method :plunder, :bundle
desc 'install', "Alias to `#{APPLICATION_NAME} bundle`" desc 'install', "Alias to `#{APPLICATION_NAME} bundle`"

View File

@@ -1,4 +1,4 @@
# The version of the gem # The version of the gem
module Zanzibar module Zanzibar
VERSION = '0.1.16' VERSION = '0.1.23'
end end

View File

@@ -4,8 +4,11 @@ settings:
domain: zanzitest.net domain: zanzitest.net
secret_dir: secrets/ secret_dir: secrets/
ignore_ssl: true ignore_ssl: true
secrets:
secrets: secrets:
ssh_key: ssh_key:
id: 2345 id: 2345
label: Private Key label: Private Key
prefix_ssh_key:
id: 2345
label: Private Key
prefix: ssh/

View File

@@ -24,9 +24,12 @@ describe Zanzibar::Cli do
FakeFS::FileSystem.clone files FakeFS::FileSystem.clone files
stub_request(:any, 'https://www.zanzitest.net/webservices/sswebservice.asmx') stub_request(:any, 'https://www.zanzitest.net/webservices/sswebservice.asmx')
.to_return(body: AUTH_XML, status: 200).then .to_return({body: AUTH_XML, status: 200}).then
.to_return(body: SECRET_WITH_KEY_XML, status: 200).then .to_return({body: SECRET_WITH_KEY_XML, status: 200}).then
.to_return(body: PRIVATE_KEY_XML, status: 200) .to_return({body: PRIVATE_KEY_XML, status: 200}).then
.to_return({body: AUTH_XML, status: 200}).then
.to_return({body: SECRET_WITH_KEY_XML, status: 200}).then
.to_return({body: PRIVATE_KEY_XML, status: 200})
Dir.chdir File.join(source_root, 'spec', 'files') Dir.chdir File.join(source_root, 'spec', 'files')
end end
@@ -50,6 +53,18 @@ describe Zanzibar::Cli do
expect(FakeFS::FileTest.file? File.join('secrets', 'zanzi_key')).to be(true) expect(FakeFS::FileTest.file? File.join('secrets', 'zanzi_key')).to be(true)
end end
it 'should download a file to a prefix' do
expect(FakeFS::FileTest.file? File.join('secrets/ssh', 'zanzi_key')).to be(false)
expect { subject.bundle }.to output(/Finished downloading secrets/).to_stdout
expect(FakeFS::FileTest.file? File.join('secrets/ssh', 'zanzi_key')).to be(true)
end
it 'should create a .gitignore' do
expect(FakeFS::FileTest.file? File.join('secrets', '.gitignore')).to be(false)
expect { subject.bundle }.to output(/Finished downloading secrets/).to_stdout
expect(FakeFS::FileTest.file? File.join('secrets', '.gitignore')).to be(true)
end
it 'should create a resolved file' do it 'should create a resolved file' do
expect(FakeFS::FileTest.file? Zanzibar::RESOLVED_NAME).to be(false) expect(FakeFS::FileTest.file? Zanzibar::RESOLVED_NAME).to be(false)
expect { subject.bundle }.to output(/Finished downloading secrets/).to_stdout expect { subject.bundle }.to output(/Finished downloading secrets/).to_stdout
@@ -58,7 +73,7 @@ describe Zanzibar::Cli do
it 'should not redownload files it already has' do it 'should not redownload files it already has' do
expect { subject.bundle }.to output(/Finished downloading secrets/).to_stdout expect { subject.bundle }.to output(/Finished downloading secrets/).to_stdout
expect(WebMock).to have_requested(:post, 'https://www.zanzitest.net/webservices/sswebservice.asmx').times(3) expect(WebMock).to have_requested(:post, 'https://www.zanzitest.net/webservices/sswebservice.asmx').times(6)
WebMock.reset! WebMock.reset!
@@ -68,16 +83,19 @@ describe Zanzibar::Cli do
it 'should redownload on update action' do it 'should redownload on update action' do
expect { subject.bundle }.to output(/Finished downloading secrets/).to_stdout expect { subject.bundle }.to output(/Finished downloading secrets/).to_stdout
expect(WebMock).to have_requested(:post, 'https://www.zanzitest.net/webservices/sswebservice.asmx').times(3) expect(WebMock).to have_requested(:post, 'https://www.zanzitest.net/webservices/sswebservice.asmx').times(6)
WebMock.reset! WebMock.reset!
stub_request(:any, 'https://www.zanzitest.net/webservices/sswebservice.asmx') stub_request(:any, 'https://www.zanzitest.net/webservices/sswebservice.asmx')
.to_return({body: AUTH_XML, status: 200}).then
.to_return({body: SECRET_WITH_KEY_XML, status: 200}).then
.to_return({body: PRIVATE_KEY_XML, status: 200}).then
.to_return(body: AUTH_XML, status: 200).then .to_return(body: AUTH_XML, status: 200).then
.to_return(body: SECRET_WITH_KEY_XML, status: 200).then .to_return(body: SECRET_WITH_KEY_XML, status: 200).then
.to_return(body: PRIVATE_KEY_XML, status: 200) .to_return(body: PRIVATE_KEY_XML, status: 200)
expect { subject.update }.to output(/Finished downloading secrets/).to_stdout expect { subject.update }.to output(/Finished downloading secrets/).to_stdout
expect(WebMock).to have_requested(:post, 'https://www.zanzitest.net/webservices/sswebservice.asmx').times(3) expect(WebMock).to have_requested(:post, 'https://www.zanzitest.net/webservices/sswebservice.asmx').times(6)
end end
it 'should reject a malformed Zanzifile' do it 'should reject a malformed Zanzifile' do

View File

@@ -104,6 +104,17 @@ describe 'Zanzibar Test' do
File.delete('attachment.txt') File.delete('attachment.txt')
end end
it 'should save credentials to a file' do
stub_request(:any, 'https://www.zanzitest.net/webservices/sswebservice.asmx')
.to_return(body: AUTH_XML, status: 200).then
.to_return(body: SECRET_XML, status: 200)
client.get_username_and_password_and_save(1234, '.', 'zanziTestCreds')
expect(File.exist? 'zanziTestCreds')
expect(File.read('zanziTestCreds')).to eq({'username' => 'ZanziUser', 'password' => 'zanziUserPassword'}.to_yaml)
File.delete('zanziTestCreds')
end
it 'should use environment variables for credentials' do it 'should use environment variables for credentials' do
ENV['ZANZIBAR_USER'] = 'environment_user' ENV['ZANZIBAR_USER'] = 'environment_user'
ENV['ZANZIBAR_PASSWORD'] = 'environment_password' ENV['ZANZIBAR_PASSWORD'] = 'environment_password'