cipherpipe 0.2.4 → 0.3.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.
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