cipherpipe 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4f0e32f480bf3dfd34b87dded6a5bf13ab9e37e8cffcecf597828cac5f3d756
4
- data.tar.gz: f68ddc736e43122d4790f29647b898629be30804fc035c6d1c241decc3a6effa
3
+ metadata.gz: 9fbd9abc8551bd0d9d03d7fd91e1d4eb1c57ca0bffd8d12c0d8a13412fc23e8e
4
+ data.tar.gz: cbfee38900e2ed2bd30328c1789532fa53f3aa6f27b8ea56c0296948e97a9439
5
5
  SHA512:
6
- metadata.gz: 71f09bf4723137bc0e205d993d67ab9a9cb97e54b8aac05ce9d904ecf4596dd34caa22fffbeffe8f528148d8d8f9057ff78fe6973fcf3be48cb68d13a2519c9f
7
- data.tar.gz: aa5fd99b6dfac62daac9a2a2bf622ec614fb047bd169684b01077380c21f281a3612e0cf28c1a9094e001ede149320e23af8e5a935ec7b8d01ae23b2ded5f074
6
+ metadata.gz: 3ae3d44347e9f054c72bc838e83ff29d50e848dc46f47ab4aa78dbf0c114749141184037488452b48c986e13cc48a82fb93df594dbeaa4836632df366644bc35
7
+ data.tar.gz: '0079cb88864cd97ffea062d65ffdbd96ce20d3a4ab3b7fc0c5c44be67bc135102926d6ac939ebf39f13129654729f893466363f8a1555430fff7afad35b82257'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cipherpipe (0.2.4)
4
+ cipherpipe (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -29,6 +29,7 @@ GEM
29
29
  rspec-support (~> 3.7.0)
30
30
  rspec-support (3.7.1)
31
31
  safe_yaml (1.0.4)
32
+ shell_mock (0.3.3)
32
33
  vault (0.11.0)
33
34
  aws-sigv4
34
35
  webmock (3.4.2)
@@ -44,6 +45,7 @@ DEPENDENCIES
44
45
  cipherpipe!
45
46
  rake (~> 12.0)
46
47
  rspec (~> 3.7)
48
+ shell_mock (~> 0.3.3)
47
49
  vault (~> 0.11)
48
50
  webmock (~> 3.4)
49
51
 
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Cipherpipe
2
2
 
3
- Cipherpipe transfers secrets from stores (such as Vault) onto your local machine, or into the `ENV` of a Ruby app. You can then make changes and upload these back into the store - all of which is done only when you have valid access.
3
+ Cipherpipe transfers secrets from stores (such as Vault and 1Password) onto your local machine, or into the `ENV` of a Ruby app. You can then make changes and upload these back into the store - all of which is done only when you have valid access.
4
4
 
5
5
  ## Why?
6
6
 
@@ -34,11 +34,13 @@ Cipherpipe::Commands::Load.call
34
34
 
35
35
  If you're using Vault's EC2 authentication and have specified an `ec2_role` value for the primary source (as noted in the configuration example below), then loading the secrets will automatically authenticate against Vault using the EC2 instance's PKCS7-signed identity.
36
36
 
37
+ If you're using 1Password, you'll want to have [their command-line tool](https://support.1password.com/command-line-getting-started/) installed (testing has been conducted with v0.4.1). Any time you use cipherpipe commands that interact with 1Password, you'll have to be authenticated first (`op signin team-subdomain.1password.com me@myemail.com A3-XXXXXX-XXXXXX-XXXXX-XXXXX-XXXXX-XXXXX`).
38
+
37
39
  ## Configuration
38
40
 
39
41
  Everything for Cipherpipe is managed in a YAML configuration file `.cipherpipe.yml` which you should place in the root of your project. You'll need to specify at least one source (and mark it as the primary). Having an output file/format is optional, but likely useful.
40
42
 
41
- When setting a Vault source, the destination is a key-value store (v2) and the `secret/` prefix is added automatically.
43
+ When setting a Vault source, the destination is a key-value store (v2) and the `secret/` prefix is added automatically. When setting up 1Password, the destination is the name of the document, and you'll want to specify a vault as well.
42
44
 
43
45
  Here's an example for a Rails application using `dotenv` (and `ENVIRONMENT` is automatically translated to the appropriate Rails environment, as based on the RAILS_ENV variable):
44
46
 
@@ -49,6 +51,9 @@ sources:
49
51
  - type: vault
50
52
  destination: apps/myapp/ENVIRONMENT
51
53
  primary: true
54
+ - type: 1password
55
+ destination: "Apps: myapp ENVIRONMENT"
56
+ vault: Developers
52
57
  ```
53
58
 
54
59
  If you're running this on EC2 servers that are set up to authenticate with Vault via a specific role, you can provide that with the `ec2_role` setting and it'll automatically be used:
@@ -85,6 +90,8 @@ sources:
85
90
  primary: true
86
91
  ```
87
92
 
93
+ Note that you must have one primary source - the primary source is where data is downloaded from. Other sources are only for uploading (i.e. as a backup).
94
+
88
95
  ## Usage
89
96
 
90
97
  Once you've got things configured, you can use the `cipherpipe` executable to download or upload configuration.
@@ -105,7 +112,9 @@ If you're using Vault's EC2 authentication and have specified an `ec2_role` valu
105
112
 
106
113
  ## Dependencies
107
114
 
108
- If you're using Vault (which is likely, given it's currently the only supported secret storage service), you'll need to make sure it's using the V2 kv secrets engine.
115
+ If you're using Vault, you'll need to make sure it's using the V2 kv secrets engine.
116
+
117
+ If you're using 1Password, you'll need [their command-line tool](https://support.1password.com/command-line-getting-started/) installed (v0.4.1 or newer is recommended).
109
118
 
110
119
  ## Contributing
111
120
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "cipherpipe"
3
- spec.version = "0.2.4"
3
+ spec.version = "0.3.0"
4
4
  spec.authors = ["Pat Allan"]
5
5
  spec.email = ["pat@freelancing-gods.com"]
6
6
 
@@ -15,8 +15,9 @@ Gem::Specification.new do |spec|
15
15
  spec.executables = spec.files.grep(%r{^exe/}) { |file| File.basename(file) }
16
16
  spec.require_paths = ["lib"]
17
17
 
18
- spec.add_development_dependency "bundler", "~> 1.16"
19
- spec.add_development_dependency "rake", "~> 12.0"
20
- spec.add_development_dependency "rspec", "~> 3.7"
21
- spec.add_development_dependency "webmock", "~> 3.4"
18
+ spec.add_development_dependency "bundler", "~> 1.16"
19
+ spec.add_development_dependency "rake", "~> 12.0"
20
+ spec.add_development_dependency "rspec", "~> 3.7"
21
+ spec.add_development_dependency "shell_mock", "~> 0.3.3"
22
+ spec.add_development_dependency "webmock", "~> 3.4"
22
23
  end
@@ -49,15 +49,11 @@ class Cipherpipe::Configuration
49
49
  end
50
50
 
51
51
  def parse_source(hash)
52
- role = hash["ec2_role"]
53
- role.gsub!("ENVIRONMENT", environment) unless role.nil?
52
+ hash.each do |key, value|
53
+ hash[key] = value.gsub("ENVIRONMENT", environment) if value.is_a?(String)
54
+ end
54
55
 
55
- Cipherpipe::ExternalSource.new(
56
- hash["type"],
57
- hash["destination"].gsub("ENVIRONMENT", environment),
58
- hash["primary"],
59
- role
60
- )
56
+ Cipherpipe::ExternalSource.new hash
61
57
  end
62
58
 
63
59
  def yaml
@@ -1,13 +1,14 @@
1
1
  class Cipherpipe::ExternalSource
2
2
  UnknownProviderError = Class.new Cipherpipe::Error
3
3
 
4
- attr_reader :type, :destination, :primary, :ec2_role
4
+ attr_reader :type, :destination, :primary, :ec2_role, :options
5
5
 
6
- def initialize(type, destination, primary = false, ec2_role = nil)
7
- @type = type
8
- @destination = destination
9
- @primary = primary
10
- @ec2_role = ec2_role
6
+ def initialize(options = {})
7
+ @type = options.delete "type"
8
+ @destination = options.delete "destination"
9
+ @primary = options.delete "primary"
10
+ @ec2_role = options.delete "ec2_role"
11
+ @options = options
11
12
  end
12
13
 
13
14
  def download
@@ -37,6 +38,9 @@ class Cipherpipe::ExternalSource
37
38
  when "vault"
38
39
  require_relative "vault"
39
40
  Cipherpipe::Vault
41
+ when "1password"
42
+ require_relative "one_password"
43
+ Cipherpipe::OnePassword
40
44
  else
41
45
  raise UnknownProviderError, "unknown provider #{type}"
42
46
  end
@@ -0,0 +1,17 @@
1
+ class Cipherpipe::OnePassword
2
+ def self.available?
3
+ !`which op`.empty?
4
+ end
5
+
6
+ def self.download(external_source)
7
+ require_relative "one_password/download"
8
+
9
+ Cipherpipe::OnePassword::Download.call external_source
10
+ end
11
+
12
+ def self.upload(external_source, settings)
13
+ require_relative "one_password/upload"
14
+
15
+ Cipherpipe::OnePassword::Upload.call external_source, settings
16
+ end
17
+ end
@@ -0,0 +1,38 @@
1
+ require "json"
2
+
3
+ class Cipherpipe::OnePassword::Download
4
+ UnknownDocument = Class.new Cipherpipe::Error
5
+
6
+ def self.call(external_source)
7
+ new(external_source).call
8
+ end
9
+
10
+ def initialize(external_source)
11
+ @external_source = external_source
12
+ end
13
+
14
+ def call
15
+ hash = documents.detect do |document|
16
+ document["overview"]["title"] == external_source.destination
17
+ end
18
+
19
+ if hash.nil?
20
+ raise UnknownDocument,
21
+ "Cannot find #{external_source.destination} in 1Password vault #{vault}"
22
+ end
23
+
24
+ JSON.load `op get document \"#{hash["uuid"]}\" --vault \"#{vault}\"`
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :external_source
30
+
31
+ def documents
32
+ JSON.load `op list documents --vault \"#{vault}\"`
33
+ end
34
+
35
+ def vault
36
+ external_source.options["vault"]
37
+ end
38
+ end
@@ -0,0 +1,39 @@
1
+ require "tmpdir"
2
+ require "json"
3
+
4
+ class Cipherpipe::OnePassword::Upload
5
+ def self.call(external_source, variables)
6
+ new(external_source, variables).call
7
+ end
8
+
9
+ def initialize(external_source, variables)
10
+ @external_source = external_source
11
+ @variables = variables
12
+ end
13
+
14
+ def call
15
+ documents.each do |document|
16
+ next unless document["overview"]["title"] == external_source.destination
17
+
18
+ `op delete item "#{document["uuid"]}" --vault="#{vault}"`
19
+ end
20
+
21
+ Dir.mktmpdir do |directory|
22
+ File.write "#{directory}/cipherpipe.json", JSON.dump(variables)
23
+
24
+ `op create document "#{directory}/cipherpipe.json" --title="#{external_source.destination}" --vault="#{vault}"`
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :external_source, :variables
31
+
32
+ def documents
33
+ JSON.load `op list documents --vault "#{vault}"`
34
+ end
35
+
36
+ def vault
37
+ external_source.options["vault"]
38
+ end
39
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cipherpipe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pat Allan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-12 00:00:00.000000000 Z
11
+ date: 2018-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: shell_mock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.3.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.3.3
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: webmock
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -99,6 +113,9 @@ files:
99
113
  - lib/cipherpipe/formatters/env.rb
100
114
  - lib/cipherpipe/formatters/hcl.rb
101
115
  - lib/cipherpipe/formatters/json.rb
116
+ - lib/cipherpipe/one_password.rb
117
+ - lib/cipherpipe/one_password/download.rb
118
+ - lib/cipherpipe/one_password/upload.rb
102
119
  - lib/cipherpipe/vault.rb
103
120
  - lib/cipherpipe/vault/api.rb
104
121
  - lib/cipherpipe/vault/download.rb