constancy 0.1.5 → 0.2.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
- SHA1:
3
- metadata.gz: 7f2b5ae0525b88e9fc9b56f9d5bdcd4d84c143a3
4
- data.tar.gz: 6350e6dec7a606733ba292e002bc423dff8634af
2
+ SHA256:
3
+ metadata.gz: 65a3785bc8276043c12dd3a82fc0da2f23db508f8ccb9de6e074ef3fb34a0c01
4
+ data.tar.gz: 6f83ec7f19dfe57f28ae56b9179c3c34b9b5419c1bfc8c3f7f4338d08564675b
5
5
  SHA512:
6
- metadata.gz: 213832240c59baf7d8289a27cc5829d66c7cc6e61a072eaf9a25b20d54d6929f21c8b85a76ac6c0f76cd704dbe180d21a30e0d1adc58564f3d964d58f15e80b7
7
- data.tar.gz: c013397a8786af4f9f309a80217440b069c0459f7d71a8c072d1de34c366abbc2f2e4f2c69a31f960f560589e2c681bbe291e40310ff37cf2bba426913661093
6
+ metadata.gz: 6b4a9af5164674a87cc132d026fd7b7a1205f30ed94d255e37fa43d0ac46922235ab665836c7158f862441106947e3792bcd5d2338ca76f8ceb3cf4c22738c7b
7
+ data.tar.gz: 3b589b72c830dd07283e5fc5a19c5feb9f7404e4d3f949fa20915a44e9bf91a7fb03b9409e9d66805bb7343dbcdf9d33542bdb69373bc55020f5c82ee26900de
data/README.md CHANGED
@@ -112,6 +112,29 @@ required. An example `constancy.yml` is below including explanatory comments:
112
112
  # something other than the datacenter of the Consul agent.
113
113
  datacenter: dc1
114
114
 
115
+ # token_source - defaults to 'none'
116
+ # 'none': expect no Consul token (although env vars will be used if they are set)
117
+ # 'env': expect Consul token to be set in CONSUL_TOKEN or CONSUL_HTTP_TOKEN
118
+ # 'vault': read Consul token from Vault based on settings in the 'vault' section
119
+
120
+ # the vault section is only necessary if consul.token_source is set to 'vault'
121
+ vault:
122
+ # url - defaults to the value of VAULT_ADDR
123
+ # The REST API endpoint of your Vault server
124
+ url: https://your.vault.example
125
+
126
+ # path - the path to the endpoint from which to read the Consul token
127
+ # The Vault URI path to the Consul token - can be either the Consul
128
+ # dynamic backend or a KV endpoint with a static value. If the dynamic
129
+ # backend is used, the lease will be automatically revoked when
130
+ # constancy exits.
131
+ path: consul/creds/my-role
132
+
133
+ # field - name of the field in which the Consul token is stored
134
+ # Defaults to 'token' which is the field used by the dynamic backend
135
+ # but can be set to something else for static values.
136
+ field: token
137
+
115
138
  sync:
116
139
  # sync is an array of hashes of sync target configurations
117
140
  # Fields:
@@ -184,13 +207,11 @@ Constancy may be partially configured using environment variables:
184
207
  is given to `CONSUL_HTTP_TOKEN`) to set an explicit Consul token to use when
185
208
  interacting with the API. Otherwise, by default the agent's `acl_token`
186
209
  setting is used implicitly.
187
-
188
-
189
- ## Automation
190
-
191
- For version 0.1, Constancy does not fully support running non-interactively.
192
- This is primarily to ensure human observation of any changes being made while
193
- the software matures. Later versions will allow for full automation.
210
+ * `VAULT_ADDR` and `VAULT_TOKEN` - if `consul.token_source` is set to `vault`
211
+ these variables are used to authenticate to Vault. If `VAULT_TOKEN` is not
212
+ set, Constancy will attempt to read a token from `~/.vault-token`. If the
213
+ `url` field is set, it will take priority over the `VAULT_ADDR` environment
214
+ variable, but one or the other must be set.
194
215
 
195
216
 
196
217
  ## Roadmap
@@ -203,10 +224,10 @@ Constancy is very new software. There's more to be done. Some ideas:
203
224
  * Git awareness (branches, commit state, etc)
204
225
  * Automated tests
205
226
  * Logging of changes to files, syslog, other services
206
- * Allowing other means of providing a Consul token
207
227
  * Pull mode to sync from Consul to local filesystem
208
228
  * Using CAS to verify the key has not changed in the interim before updating/deleting
209
229
  * Submitting changes in batches using transactions
230
+ * Optional expansion of YAML or JSON files into multiple keys
210
231
 
211
232
 
212
233
  ## Contributing
data/constancy.gemspec CHANGED
@@ -26,4 +26,5 @@ Gem::Specification.new do |s|
26
26
 
27
27
  s.add_dependency 'imperium', '~>0.3'
28
28
  s.add_dependency 'diffy', '~>3.2'
29
+ s.add_dependency 'vault', '~>0.12'
29
30
  end
data/lib/constancy/cli.rb CHANGED
@@ -86,6 +86,15 @@ USAGE
86
86
  end
87
87
  STDERR.puts " #{e}"
88
88
  exit 1
89
+
90
+ rescue Constancy::ConsulTokenRequired => e
91
+ STDERR.puts "constancy: ERROR: No Consul token could be found: #{e}"
92
+ exit 1
93
+
94
+ rescue Constancy::VaultConfigInvalid => e
95
+ STDERR.puts "constancy: ERROR: Vault configuration invalid: #{e}"
96
+ exit 1
97
+
89
98
  end
90
99
 
91
100
  if Constancy.config.sync_targets.count < 1
@@ -3,13 +3,18 @@
3
3
  class Constancy
4
4
  class ConfigFileNotFound < RuntimeError; end
5
5
  class ConfigFileInvalid < RuntimeError; end
6
+ class ConsulTokenRequired < RuntimeError; end
7
+ class VaultConfigInvalid < RuntimeError; end
6
8
 
7
9
  class Config
8
10
  CONFIG_FILENAMES = %w( constancy.yml )
9
- VALID_CONFIG_KEYS = %w( sync consul constancy )
10
- VALID_CONSUL_CONFIG_KEYS = %w( url datacenter )
11
+ VALID_CONFIG_KEYS = %w( sync consul vault constancy )
12
+ VALID_CONSUL_CONFIG_KEYS = %w( url datacenter token_source )
13
+ VALID_VAULT_CONFIG_KEYS = %w( url path field )
11
14
  VALID_CONSTANCY_CONFIG_KEYS = %w( verbose chomp delete color )
12
15
  DEFAULT_CONSUL_URL = "http://localhost:8500"
16
+ DEFAULT_CONSUL_TOKEN_SOURCE = "none"
17
+ DEFAULT_VAULT_FIELD = "token"
13
18
 
14
19
  attr_accessor :config_file, :base_dir, :consul, :sync_targets, :target_whitelist
15
20
 
@@ -97,7 +102,83 @@ class Constancy
97
102
  end
98
103
 
99
104
  consul_url = raw['consul']['url'] || Constancy::Config::DEFAULT_CONSUL_URL
105
+
106
+ # start with a token from the environment, regardless of the token_source setting
100
107
  consul_token = ENV['CONSUL_HTTP_TOKEN'] || ENV['CONSUL_TOKEN']
108
+
109
+ case raw['consul']['token_source'] || Constancy::Config::DEFAULT_CONSUL_TOKEN_SOURCE
110
+ when "none"
111
+ # nothing to do
112
+
113
+ when "env"
114
+ if consul_token.nil? or consul_token == ""
115
+ raise Constancy::ConsulTokenRequired.new("Consul token_source is set to 'env' but neither CONSUL_TOKEN nor CONSUL_HTTP_TOKEN is set")
116
+ end
117
+
118
+ when "vault"
119
+ require 'vault'
120
+
121
+ raw['vault'] ||= {}
122
+ if not raw['vault'].is_a? Hash
123
+ raise Constancy::ConfigFileInvalid.new("'vault' must be a hash")
124
+ end
125
+
126
+ if (raw['vault'].keys - Constancy::Config::VALID_VAULT_CONFIG_KEYS) != []
127
+ raise Constancy::ConfigFileInvalid.new("Only the following keys are valid in the vault config: #{Constancy::Config::VALID_VAULT_CONFIG_KEYS.join(", ")}")
128
+ end
129
+
130
+ vault_path = raw['vault']['path']
131
+ if vault_path.nil? or vault_path == ""
132
+ raise Constancy::ConfigFileInvalid.new("vault.path must be specified to use vault as a token source")
133
+ end
134
+
135
+ # prioritize the config file over environment variables for vault address
136
+ vault_addr = raw['vault']['url'] || ENV['VAULT_ADDR']
137
+ if vault_addr.nil? or vault_addr == ""
138
+ raise Constancy::VaultConfigInvalid.new("Vault address must be set in vault.url or VAULT_ADDR")
139
+ end
140
+
141
+ vault_token = ENV['VAULT_TOKEN']
142
+ if vault_token.nil? or vault_token == ""
143
+ vault_token_file = File.expand_path("~/.vault-token")
144
+ if File.exist?(vault_token_file)
145
+ vault_token = File.read(vault_token_file)
146
+ else
147
+ raise Constancy::VaultConfigInvalid.new("Vault token must be set in ~/.vault-token or VAULT_TOKEN")
148
+ end
149
+ end
150
+
151
+ vault_field = raw['vault']['field'] || Constancy::Config::DEFAULT_VAULT_FIELD
152
+
153
+ ENV['VAULT_ADDR'] = vault_addr
154
+ ENV['VAULT_TOKEN'] = vault_token
155
+
156
+ begin
157
+ response = Vault.logical.read(vault_path)
158
+ consul_token = response.data[vault_field.to_sym]
159
+
160
+ if response.lease_id
161
+ at_exit {
162
+ begin
163
+ Vault.sys.revoke(response.lease_id)
164
+ rescue => e
165
+ # this is fine
166
+ end
167
+ }
168
+ end
169
+
170
+ rescue => e
171
+ raise Constancy::VaultConfigInvalid.new("Are you logged in to Vault?\n\n#{e}")
172
+ end
173
+
174
+ if consul_token.nil? or consul_token == ""
175
+ raise Constancy::VaultConfigInvalid.new("Could not acquire a Consul token from Vault")
176
+ end
177
+
178
+ else
179
+ raise Constancy::ConfigFileInvalid.new("Only the following values are valid for token_source: none, env, vault")
180
+ end
181
+
101
182
  self.consul = Imperium::Configuration.new(url: consul_url, token: consul_token)
102
183
 
103
184
  raw['constancy'] ||= {}
@@ -1,5 +1,5 @@
1
1
  # This software is public domain. No rights are reserved. See LICENSE for more information.
2
2
 
3
3
  class Constancy
4
- VERSION = "0.1.5"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: constancy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Adams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-29 00:00:00.000000000 Z
11
+ date: 2018-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: imperium
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: vault
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.12'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.12'
41
55
  description: Syncs content from the filesystem to the Consul KV store.
42
56
  email: daveadams@gmail.com
43
57
  executables:
@@ -77,7 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
91
  version: '0'
78
92
  requirements: []
79
93
  rubyforge_project:
80
- rubygems_version: 2.6.13
94
+ rubygems_version: 2.7.6
81
95
  signing_key:
82
96
  specification_version: 4
83
97
  summary: Simple filesystem-to-Consul KV synchronization