foreman_vault 0.2.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -0
- data/app/controllers/concerns/foreman_vault/controller/parameters/vault_connection.rb +1 -1
- data/app/lib/foreman_vault/macros.rb +2 -2
- data/app/models/concerns/foreman_vault/orchestration/vault_policy.rb +12 -5
- data/app/models/concerns/foreman_vault/provisioning_template_extensions.rb +15 -0
- data/app/models/setting/vault.rb +32 -2
- data/app/models/vault_connection.rb +34 -6
- data/app/services/foreman_vault/vault_auth_method.rb +3 -3
- data/app/services/foreman_vault/vault_client.rb +13 -4
- data/app/services/foreman_vault/vault_policy.rb +1 -1
- data/app/views/unattended/provisioning_templates/VaultPolicy/default.erb +3 -3
- data/app/views/vault_connections/_form.html.erb +20 -4
- data/app/views/vault_connections/index.html.erb +21 -7
- data/db/migrate/20201203220058_add_approle_to_vault_connection.rb +8 -0
- data/lib/foreman_vault/engine.rb +2 -1
- data/lib/foreman_vault/version.rb +1 -1
- data/lib/tasks/foreman_vault_tasks.rake +44 -1
- data/test/factories/vault_connection.rb +1 -1
- data/test/factories/vault_policy_template.rb +1 -0
- data/test/lib/tasks/push_auth_methods_test.rb +49 -0
- data/test/lib/tasks/push_policies_test.rb +49 -0
- data/test/models/foreman_vault/orchestration/vault_policy_test.rb +64 -9
- data/test/models/vault_policy_template_test.rb +28 -0
- data/test/unit/services/foreman_vault/vault_auth_method_test.rb +6 -19
- data/test/unit/services/foreman_vault/vault_client_test.rb +46 -10
- data/test/unit/services/foreman_vault/vault_policy_test.rb +9 -5
- metadata +15 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39553e728b4ff3661a8b0fc008ee0959e5fdbba5f915a9f7f9d09bdd24d9d65a
|
4
|
+
data.tar.gz: 34b06a3ffc2cfdd6055356c4af15e91bb7d94de7954983d0becc20881c85fef3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04fe38f150fb63017eeb3803c14ea02fe6eb557a8a51d13f7f089bc4a7e5ca12f08182ede2c642e5dd6b47d5ab53e5adcc80e45117ad714ad6154cec2df486de
|
7
|
+
data.tar.gz: d6ecb38160b4180a137a6db4f0d9e7fa6e9e14d32ebc5e98cae09a92f18997946bacc548adc4a55f7e19107ae6f2fcdbe7e43ab5a540b0d96706239dd81aa462
|
data/README.md
CHANGED
@@ -18,11 +18,20 @@ Auth methods also get deleted after the host is removed from Foreman.
|
|
18
18
|
|
19
19
|
This allows Foreman to create everything needed to access Hashicorp Vault directly from a VM using it's Puppet certificate (e.g. for _Deferred functions_ in Puppet or other CLI tools).
|
20
20
|
|
21
|
+
## Compatibility
|
22
|
+
|
23
|
+
| Foreman Version | Plugin Version |
|
24
|
+
| --------------- | -------------- |
|
25
|
+
| >= 2.3 | ~> 1.0 |
|
26
|
+
| >= 1.23 | ~> 0.3, ~> 0.4 |
|
27
|
+
| >= 1.20 | ~> 0.2 |
|
28
|
+
|
21
29
|
## Requirements
|
22
30
|
|
23
31
|
- Foreman >= 1.20
|
24
32
|
- Working Vault instance
|
25
33
|
- with _cert_ auth enabled
|
34
|
+
- with _approle_ auth enabled
|
26
35
|
- with _kv_ secret store enabled
|
27
36
|
- valid Vault Token
|
28
37
|
|
@@ -41,6 +50,27 @@ $ vault token create -period=60m
|
|
41
50
|
[...]
|
42
51
|
```
|
43
52
|
|
53
|
+
To interact with Vault you can use Vault UI, which is available at `http://127.0.0.1:8200/ui`.
|
54
|
+
|
55
|
+
- The AppRole auth method
|
56
|
+
|
57
|
+
```
|
58
|
+
$ vault auth enable approle
|
59
|
+
$ vault write auth/approle/role/my-role policies="default"
|
60
|
+
Success! Data written to: auth/approle/role/my-role
|
61
|
+
$ vault read auth/approle/role/my-role/role-id
|
62
|
+
Key Value
|
63
|
+
--- -----
|
64
|
+
role_id 8403910c-e563-d2f2-1c77-6e26319be8b5
|
65
|
+
$ vault write -f auth/approle/role/my-role/secret-id
|
66
|
+
Key Value
|
67
|
+
--- -----
|
68
|
+
secret_id 1058434b-b4aa-bf5a-b376-a15d9efb1059
|
69
|
+
secret_id_accessor 9cc19ed7-201f-7438-782e-561edd12b2a8
|
70
|
+
```
|
71
|
+
|
72
|
+
See also [Vault CLI testing AppRole](https://gist.github.com/kamils-iRonin/d099908eaf0500de8ad9c2cea5658d01)
|
73
|
+
|
44
74
|
## Installation
|
45
75
|
|
46
76
|
See [Plugins install instructions](https://theforeman.org/plugins/) for how to install Foreman plugins.
|
@@ -4,7 +4,7 @@ module ForemanVault
|
|
4
4
|
module Macros
|
5
5
|
def vault_secret(vault_connection_name, secret_path)
|
6
6
|
vault = VaultConnection.find_by!(name: vault_connection_name)
|
7
|
-
raise VaultError.new(N_('Invalid token for %s'), vault.name)
|
7
|
+
raise VaultError.new(N_('Invalid token for %s'), vault.name) if vault.with_token? && !vault.token_valid?
|
8
8
|
|
9
9
|
vault.fetch_secret(secret_path)
|
10
10
|
rescue ActiveRecord::RecordNotFound => e
|
@@ -13,7 +13,7 @@ module ForemanVault
|
|
13
13
|
|
14
14
|
def vault_issue_certificate(vault_connection_name, secret_path, *options)
|
15
15
|
vault = VaultConnection.find_by!(name: vault_connection_name)
|
16
|
-
raise VaultError.new(N_('Invalid token for %s'), vault.name)
|
16
|
+
raise VaultError.new(N_('Invalid token for %s'), vault.name) if vault.with_token? && !vault.token_valid?
|
17
17
|
vault.issue_certificate(secret_path, *options)
|
18
18
|
rescue ActiveRecord::RecordNotFound => e
|
19
19
|
raise VaultError, e.message
|
@@ -16,6 +16,7 @@ module ForemanVault
|
|
16
16
|
|
17
17
|
def queue_vault_push
|
18
18
|
return if !managed? || errors.any?
|
19
|
+
return unless orchestration_enabled?
|
19
20
|
return unless vault_policy.valid?
|
20
21
|
return unless vault_auth_method.valid?
|
21
22
|
|
@@ -25,6 +26,8 @@ module ForemanVault
|
|
25
26
|
|
26
27
|
def queue_vault_destroy
|
27
28
|
return if !managed? || errors.any?
|
29
|
+
return unless orchestration_enabled?
|
30
|
+
return unless vault_auth_method.valid?
|
28
31
|
|
29
32
|
queue.create(name: _('Clear %s Vault data') % self, priority: 60,
|
30
33
|
action: [self, :del_vault])
|
@@ -35,11 +38,8 @@ module ForemanVault
|
|
35
38
|
logger.info "Pushing #{name} data to Vault"
|
36
39
|
|
37
40
|
vault_policy.save if vault_policy.new?
|
38
|
-
|
39
|
-
|
40
|
-
old&.vault_auth_method&.delete
|
41
|
-
vault_auth_method.save
|
42
|
-
end
|
41
|
+
vault_auth_method.save
|
42
|
+
true
|
43
43
|
rescue StandardError => e
|
44
44
|
Foreman::Logging.exception("Failed to push #{name} data to Vault.", e)
|
45
45
|
failure format(_('Failed to push %{name} data to Vault: %{message}\n '), name: name, message: e.message), e
|
@@ -54,6 +54,13 @@ module ForemanVault
|
|
54
54
|
Foreman::Logging.exception("Failed to clear #{name} Vault data", e)
|
55
55
|
failure format(_("Failed to clear %{name} Vault data: %{message}\n "), name: name, message: e.message), e
|
56
56
|
end
|
57
|
+
|
58
|
+
def orchestration_enabled?
|
59
|
+
return false unless Setting[:vault_orchestration_enabled]
|
60
|
+
return false if vault_connection.nil?
|
61
|
+
|
62
|
+
true
|
63
|
+
end
|
57
64
|
end
|
58
65
|
end
|
59
66
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ForemanVault
|
4
|
+
module ProvisioningTemplateExtensions
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
# rubocop:disable Metrics/ParameterLists
|
8
|
+
def render(renderer: Foreman::Renderer, host: nil, params: {}, variables: {}, mode: Foreman::Renderer::REAL_MODE, template_input_values: {}, source_klass: nil)
|
9
|
+
source_klass = Foreman::Renderer::Source::Database if template_kind == TemplateKind.find_by(name: 'VaultPolicy')
|
10
|
+
|
11
|
+
super
|
12
|
+
end
|
13
|
+
# rubocop:enable Metrics/ParameterLists
|
14
|
+
end
|
15
|
+
end
|
data/app/models/setting/vault.rb
CHANGED
@@ -6,19 +6,37 @@ class Setting
|
|
6
6
|
BLANK_ATTRS << 'vault_policy_template'
|
7
7
|
|
8
8
|
def self.default_settings
|
9
|
-
[set_vault_connection, set_vault_policy_template]
|
9
|
+
[set_vault_connection, set_vault_policy_template, set_vault_orchestration_enabled]
|
10
10
|
end
|
11
11
|
|
12
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
12
13
|
def self.load_defaults
|
13
14
|
# Check the table exists
|
14
15
|
return unless super
|
15
16
|
|
16
17
|
transaction do
|
17
|
-
default_settings.each
|
18
|
+
default_settings.each do |s|
|
19
|
+
setting = create! s.update(category: 'Setting::Vault')
|
20
|
+
|
21
|
+
Foreman.try(:settings)&._add(
|
22
|
+
s[:name],
|
23
|
+
s.slice(:description, :default, :full_name, :encrypted)
|
24
|
+
.merge(category: 'Setting::Vault')
|
25
|
+
.yield_self do |params|
|
26
|
+
unless Gem::Version.new(SETTINGS[:version].notag) < Gem::Version.new('2.6')
|
27
|
+
params[:context] = :vault
|
28
|
+
params[:type] = setting.settings_type
|
29
|
+
end
|
30
|
+
params
|
31
|
+
end
|
32
|
+
)
|
33
|
+
end
|
18
34
|
end
|
19
35
|
|
36
|
+
Foreman.try(:settings)&.load
|
20
37
|
true
|
21
38
|
end
|
39
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
22
40
|
|
23
41
|
def self.humanized_category
|
24
42
|
N_('Vault')
|
@@ -40,12 +58,15 @@ class Setting
|
|
40
58
|
end
|
41
59
|
|
42
60
|
def default_vault_connection
|
61
|
+
return nil unless VaultConnection.table_exists?
|
43
62
|
return unless VaultConnection.unscoped.count == 1
|
44
63
|
|
45
64
|
VaultConnection.unscoped.first.name
|
46
65
|
end
|
47
66
|
|
48
67
|
def vault_connections_collection
|
68
|
+
return [] unless VaultConnection.table_exists?
|
69
|
+
|
49
70
|
proc { Hash[VaultConnection.unscoped.all.map { |vc| [vc.name, vc.name] }] }
|
50
71
|
end
|
51
72
|
|
@@ -68,6 +89,15 @@ class Setting
|
|
68
89
|
def vault_policy_templates_collection
|
69
90
|
proc { Hash[ProvisioningTemplate.unscoped.of_kind(:VaultPolicy).map { |tmpl| [tmpl.name, tmpl.name] }] }
|
70
91
|
end
|
92
|
+
|
93
|
+
def set_vault_orchestration_enabled
|
94
|
+
set(
|
95
|
+
'vault_orchestration_enabled',
|
96
|
+
N_('Enable or disable the Vault orchestration step for managing policies and auth methods'),
|
97
|
+
false,
|
98
|
+
N_('Vault Orchestration enabled')
|
99
|
+
)
|
100
|
+
end
|
71
101
|
end
|
72
102
|
end
|
73
103
|
end
|
@@ -5,20 +5,42 @@ class VaultConnection < ApplicationRecord
|
|
5
5
|
|
6
6
|
validates_lengths_from_database
|
7
7
|
validates :name, presence: true, uniqueness: true
|
8
|
-
validates :url,
|
8
|
+
validates :url, presence: true
|
9
9
|
validates :url, format: URI.regexp(['http', 'https'])
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
validates :token, presence: true, if: -> { role_id.nil? || secret_id.nil? }
|
12
|
+
validates :token, inclusion: { in: [nil], message: _('AppRole or token must be blank') }, unless: -> { role_id.nil? || secret_id.nil? }
|
13
|
+
validates :role_id, presence: true, if: -> { token.nil? }
|
14
|
+
validates :role_id, inclusion: { in: [nil], message: _('AppRole or token must be blank') }, unless: -> { token.nil? }
|
15
|
+
validates :secret_id, presence: true, if: -> { token.nil? }
|
16
|
+
validates :secret_id, inclusion: { in: [nil], message: _('AppRole or token must be blank') }, unless: -> { token.nil? }
|
13
17
|
|
14
|
-
|
18
|
+
before_validation :normalize_blank_values
|
19
|
+
before_create :set_expire_time, unless: -> { token.nil? }
|
20
|
+
before_update :update_expire_time, unless: -> { token.nil? }
|
21
|
+
|
22
|
+
scope :with_approle, -> { where.not(role_id: nil).where.not(secret_id: nil) }
|
23
|
+
scope :with_token, -> { where.not(token: nil) }
|
24
|
+
scope :with_valid_token, -> { with_token.where(vault_error: nil).where('expire_time > ?', Time.zone.now) }
|
15
25
|
|
16
26
|
delegate :fetch_expire_time, :fetch_secret, :issue_certificate,
|
17
27
|
:policy, :policies, :put_policy, :delete_policy,
|
18
28
|
:set_certificate, :certificates, :delete_certificate, to: :client
|
19
29
|
|
30
|
+
def with_token?
|
31
|
+
token.present?
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_approle?
|
35
|
+
role_id.present? && secret_id.present?
|
36
|
+
end
|
37
|
+
|
20
38
|
def token_valid?
|
21
|
-
|
39
|
+
return false unless with_token?
|
40
|
+
return false unless vault_error.nil?
|
41
|
+
return true unless expire_time
|
42
|
+
|
43
|
+
expire_time > Time.zone.now
|
22
44
|
end
|
23
45
|
|
24
46
|
def renew_token!
|
@@ -52,7 +74,13 @@ class VaultConnection < ApplicationRecord
|
|
52
74
|
self.vault_error = e.message
|
53
75
|
end
|
54
76
|
|
77
|
+
def normalize_blank_values
|
78
|
+
attributes.each do |column, _value|
|
79
|
+
self[column].present? || self[column] = nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
55
83
|
def client
|
56
|
-
@client ||= ForemanVault::VaultClient.new(url, token)
|
84
|
+
@client ||= ForemanVault::VaultClient.new(url, token, role_id, secret_id)
|
57
85
|
end
|
58
86
|
end
|
@@ -11,9 +11,9 @@ module ForemanVault
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def name
|
14
|
-
return
|
14
|
+
return unless host
|
15
15
|
|
16
|
-
|
16
|
+
host.name.parameterize
|
17
17
|
end
|
18
18
|
|
19
19
|
def save
|
@@ -23,7 +23,7 @@ module ForemanVault
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def delete
|
26
|
-
return false unless
|
26
|
+
return false unless valid?
|
27
27
|
|
28
28
|
delete_certificate(name)
|
29
29
|
end
|
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
module ForemanVault
|
4
4
|
class VaultClient
|
5
|
-
def initialize(base_url, token)
|
5
|
+
def initialize(base_url, token, role_id, secret_id)
|
6
6
|
@base_url = base_url
|
7
7
|
@token = token
|
8
|
+
@role_id = role_id
|
9
|
+
@secret_id = secret_id
|
8
10
|
end
|
9
11
|
|
10
12
|
delegate :sys, :auth_tls, to: :client
|
@@ -13,7 +15,8 @@ module ForemanVault
|
|
13
15
|
|
14
16
|
def fetch_expire_time
|
15
17
|
response = client.auth_token.lookup_self
|
16
|
-
|
18
|
+
expire_time = response.data[:expire_time]
|
19
|
+
expire_time && Time.zone.parse(expire_time)
|
17
20
|
end
|
18
21
|
|
19
22
|
def fetch_secret(secret_path)
|
@@ -38,10 +41,16 @@ module ForemanVault
|
|
38
41
|
class VaultClientError < Foreman::Exception; end
|
39
42
|
class NoDataError < VaultClientError; end
|
40
43
|
|
41
|
-
attr_reader :base_url, :token
|
44
|
+
attr_reader :base_url, :token, :role_id, :secret_id
|
42
45
|
|
43
46
|
def client
|
44
|
-
@client ||=
|
47
|
+
@client ||= if role_id.present? && secret_id.present?
|
48
|
+
Vault::Client.new(address: base_url).tap do |client|
|
49
|
+
client.auth.approle(role_id, secret_id)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
Vault::Client.new(address: base_url, token: token)
|
53
|
+
end
|
45
54
|
end
|
46
55
|
end
|
47
56
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
# NAME: <%= @host.owner %>-<%= @host.
|
1
|
+
# NAME: <%= @host.owner %>-<%= @host.name %>
|
2
2
|
|
3
|
-
# allow access to secrets from puppet hosts from <foreman_owner>-<
|
4
|
-
path "secrets/data/<%= @host.owner %>/<%= @host.
|
3
|
+
# allow access to secrets from puppet hosts from <foreman_owner>-<hostname>
|
4
|
+
path "secrets/data/<%= @host.owner %>/<%= @host.name %>/*" {
|
5
5
|
capabilities = ["create", "read", "update"]
|
6
6
|
}
|
@@ -1,7 +1,23 @@
|
|
1
|
-
<%= form_for @vault_connection, :
|
1
|
+
<%= form_for @vault_connection, url: (@vault_connection.new_record? ? vault_connections_path : vault_connection_path(id: @vault_connection)) do |f| %>
|
2
2
|
<%= base_errors_for @vault_connection %>
|
3
|
-
<%= text_f f, :name, :
|
4
|
-
<%= text_f f, :url, :
|
5
|
-
|
3
|
+
<%= text_f f, :name, help_inline: _("Vault Connection name") %>
|
4
|
+
<%= text_f f, :url, help_inline: _("Vault Server url") %>
|
5
|
+
<div class="auth_methods">
|
6
|
+
<h4><%=_("Auth Methods")%></h4>
|
7
|
+
<%= alert(text: _('Please only fill in one auth method'), class: 'alert-info', close: false) %>
|
8
|
+
<ul class="nav nav-tabs" data-tabs="tabs">
|
9
|
+
<li class="active"><a href="#approle" data-toggle="tab"><%= _('AppRole') %></a></li>
|
10
|
+
<li><a href="#token" data-toggle="tab"><%= _('Token') %></a></li>
|
11
|
+
</ul>
|
12
|
+
<div class="tab-content">
|
13
|
+
<div class="tab-pane active" id="approle">
|
14
|
+
<%= text_f f, :role_id, label: _("Role ID"), help_inline: _("Vault Connection Role ID") %>
|
15
|
+
<%= text_f f, :secret_id, label: _("Secret ID"), help_inline: _("Vault Connection Secret ID") %>
|
16
|
+
</div>
|
17
|
+
<div class="tab-pane" id="token">
|
18
|
+
<%= text_f f, :token, help_inline: _("Vault Connection token") %>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</div>
|
6
22
|
<%= submit_or_cancel f %>
|
7
23
|
<% end %>
|
@@ -4,9 +4,11 @@
|
|
4
4
|
<table class="<%= table_css_classes 'table-fixed' %>">
|
5
5
|
<thead>
|
6
6
|
<tr>
|
7
|
-
<th class="col-md-
|
8
|
-
<th class="col-md-
|
9
|
-
<th class="col-md-
|
7
|
+
<th class="col-md-2"><%= sort :name, as: s_('Vault Connections|Name') %></th>
|
8
|
+
<th class="col-md-2"><%= _('URL') %></th>
|
9
|
+
<th class="col-md-2"><%= _('Role ID') %></th>
|
10
|
+
<th class="col-md-1"><%= _('Token Valid') %></th>
|
11
|
+
<th class="col-md-1"><%= _('Token Expire time') %></th>
|
10
12
|
<th class="col-md-1"><%= _('Actions') %></th>
|
11
13
|
</tr>
|
12
14
|
</thead>
|
@@ -14,17 +16,29 @@
|
|
14
16
|
<% @vault_connections.each do |vault_connection| %>
|
15
17
|
<tr>
|
16
18
|
<td class="ellipsis">
|
17
|
-
<%= link_to_if_authorized vault_connection.name, hash_for_edit_vault_connection_path(:
|
19
|
+
<%= link_to_if_authorized vault_connection.name, hash_for_edit_vault_connection_path(id: vault_connection) %>
|
20
|
+
</td>
|
21
|
+
<td class="ellipsis">
|
22
|
+
<code class="transparent"><%= vault_connection.url %></code>
|
23
|
+
</td>
|
24
|
+
<td class="ellipsis">
|
25
|
+
<% if vault_connection.with_approle? %>
|
26
|
+
<code class="transparent"><%= vault_connection.role_id %></code>
|
27
|
+
<% end %>
|
18
28
|
</td>
|
19
29
|
<td align='center'>
|
20
|
-
<% if vault_connection.token_valid? %>
|
30
|
+
<% vault_connection.with_token? && if vault_connection.token_valid? %>
|
21
31
|
<%= ('<span class="glyphicon glyphicon-ok"/>').html_safe %>
|
22
32
|
<% else %>
|
23
33
|
<%= ('<span class="glyphicon glyphicon-remove" title="%s"/>' % vault_connection.vault_error).html_safe %>
|
24
34
|
<% end %>
|
25
35
|
</td>
|
26
|
-
<td
|
27
|
-
|
36
|
+
<td>
|
37
|
+
<% if vault_connection.with_token? %>
|
38
|
+
<%= date_time_absolute(vault_connection.expire_time) %>
|
39
|
+
<% end %>
|
40
|
+
</td>
|
41
|
+
<td><%= action_buttons display_delete_if_authorized hash_for_vault_connection_path(id: vault_connection), data: { confirm: _("Delete %s?") % vault_connection.name } %></td>
|
28
42
|
</tr>
|
29
43
|
<% end %>
|
30
44
|
</tbody>
|
data/lib/foreman_vault/engine.rb
CHANGED
@@ -29,7 +29,7 @@ module ForemanVault
|
|
29
29
|
|
30
30
|
initializer 'foreman_vault.register_plugin', before: :finisher_hook do |_app|
|
31
31
|
Foreman::Plugin.register :foreman_vault do
|
32
|
-
requires_foreman '>=
|
32
|
+
requires_foreman '>= 2.3'
|
33
33
|
|
34
34
|
apipie_documented_controllers ["#{ForemanVault::Engine.root}/app/controllers/api/v2/*.rb"]
|
35
35
|
|
@@ -55,6 +55,7 @@ module ForemanVault
|
|
55
55
|
config.to_prepare do
|
56
56
|
begin
|
57
57
|
::Host::Managed.include(ForemanVault::HostExtensions)
|
58
|
+
::ProvisioningTemplate.include(ForemanVault::ProvisioningTemplateExtensions)
|
58
59
|
::Foreman::Renderer::Scope::Base.include(ForemanVault::Macros)
|
59
60
|
::Foreman::Renderer.configure { |c| c.allowed_generic_helpers += [:vault_secret, :vault_issue_certificate] }
|
60
61
|
rescue StandardError => e
|
@@ -3,7 +3,50 @@
|
|
3
3
|
require 'rake/testtask'
|
4
4
|
|
5
5
|
# Tasks
|
6
|
-
namespace :foreman_vault do
|
6
|
+
namespace :foreman_vault do # rubocop:disable Metrics/BlockLength
|
7
|
+
namespace :auth_methods do
|
8
|
+
desc 'Push auth methods for all hosts to Vault'
|
9
|
+
task push: :environment do
|
10
|
+
User.as_anonymous_admin do
|
11
|
+
hosts = Host::Managed.where(managed: true)
|
12
|
+
|
13
|
+
hosts.each_with_index do |host, index|
|
14
|
+
begin
|
15
|
+
result = host.reload.vault_auth_method.save
|
16
|
+
if result
|
17
|
+
puts "[#{index + 1}/#{hosts.count}] Auth-Method of \"#{host.name}\" pushed to Vault server \"#{host.vault_connection.url}\""
|
18
|
+
else
|
19
|
+
puts "[#{index + 1}/#{hosts.count}] Failed to push \"#{host.name}\": #{result}"
|
20
|
+
end
|
21
|
+
rescue StandardError => err
|
22
|
+
puts "[#{index + 1}/#{hosts.count}] Failed to push \"#{host.name}\": #{err}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
namespace :policies do
|
30
|
+
desc 'Push policies for all hosts to Vault'
|
31
|
+
task push: :environment do
|
32
|
+
User.as_anonymous_admin do
|
33
|
+
hosts = Host::Managed.where(managed: true)
|
34
|
+
|
35
|
+
hosts.each_with_index do |host, index|
|
36
|
+
begin
|
37
|
+
result = host.reload.vault_policy.save
|
38
|
+
if result
|
39
|
+
puts "[#{index + 1}/#{hosts.count}] Policy of \"#{host.name}\" pushed to Vault server \"#{host.vault_connection.url}\""
|
40
|
+
else
|
41
|
+
puts "[#{index + 1}/#{hosts.count}] Failed to push \"#{host.name}\": #{result}"
|
42
|
+
end
|
43
|
+
rescue StandardError => err
|
44
|
+
puts "[#{index + 1}/#{hosts.count}] Failed to push \"#{host.name}\": #{err}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
7
50
|
end
|
8
51
|
|
9
52
|
# Tests
|
@@ -4,6 +4,7 @@ FactoryBot.modify do
|
|
4
4
|
factory :provisioning_template do
|
5
5
|
trait :vault_policy do
|
6
6
|
name { Setting['vault_policy_template'] || 'Default Vault Policy' }
|
7
|
+
template_kind { TemplateKind.find_or_create_by(name: 'VaultPolicy') }
|
7
8
|
template { File.read(File.join(ForemanVault::Engine.root, 'app/views/unattended/provisioning_templates/VaultPolicy/default.erb')) }
|
8
9
|
end
|
9
10
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_plugin_helper'
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
module ForemanVault
|
7
|
+
class PushAuthMethodsTest < ActiveSupport::TestCase
|
8
|
+
TASK_NAME = 'foreman_vault:auth_methods:push'
|
9
|
+
|
10
|
+
let(:host) { FactoryBot.create(:host, :managed) }
|
11
|
+
let(:vault_connection) { FactoryBot.create(:vault_connection, :without_callbacks) }
|
12
|
+
|
13
|
+
setup do
|
14
|
+
Rake.application.rake_require 'tasks/foreman_vault_tasks'
|
15
|
+
|
16
|
+
Rake::Task.define_task(:environment)
|
17
|
+
Rake::Task[TASK_NAME].reenable
|
18
|
+
|
19
|
+
FactoryBot.create(:parameter, name: 'vault_connection', value: vault_connection.name)
|
20
|
+
|
21
|
+
ForemanVault::VaultAuthMethod.any_instance.stubs(:vault_policy_name).returns('vault_policy_name')
|
22
|
+
ForemanVault::VaultAuthMethod.any_instance.stubs(:certificate).returns('cert')
|
23
|
+
|
24
|
+
ForemanVault::VaultClient.any_instance.stubs(:set_certificate).returns(true)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'does successfully push auth methods' do
|
28
|
+
host
|
29
|
+
|
30
|
+
stdout, _stderr = capture_io do
|
31
|
+
Rake::Task[TASK_NAME].invoke
|
32
|
+
end
|
33
|
+
|
34
|
+
assert_match("[1/1] Auth-Method of \"#{host.name}\" pushed to Vault server \"#{host.vault_connection.url}\"", stdout)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'does throw an error when host was deleted' do
|
38
|
+
host
|
39
|
+
|
40
|
+
Host::Managed.any_instance.stubs(:reload).raises(ActiveRecord::RecordNotFound)
|
41
|
+
|
42
|
+
stdout, _stderr = capture_io do
|
43
|
+
Rake::Task[TASK_NAME].invoke
|
44
|
+
end
|
45
|
+
|
46
|
+
assert_match("[1/1] Failed to push \"#{host.name}\"", stdout)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_plugin_helper'
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
module ForemanVault
|
7
|
+
class PushPoliciesTest < ActiveSupport::TestCase
|
8
|
+
TASK_NAME = 'foreman_vault:policies:push'
|
9
|
+
|
10
|
+
let(:host) { FactoryBot.create(:host, :managed) }
|
11
|
+
let(:vault_connection) { FactoryBot.create(:vault_connection, :without_callbacks) }
|
12
|
+
|
13
|
+
setup do
|
14
|
+
Rake.application.rake_require 'tasks/foreman_vault_tasks'
|
15
|
+
|
16
|
+
Rake::Task.define_task(:environment)
|
17
|
+
Rake::Task[TASK_NAME].reenable
|
18
|
+
|
19
|
+
FactoryBot.create(:parameter, name: 'vault_connection', value: vault_connection.name)
|
20
|
+
|
21
|
+
ForemanVault::VaultPolicy.any_instance.stubs(:name).returns('vault_policy_name')
|
22
|
+
ForemanVault::VaultPolicy.any_instance.stubs(:rules).returns('rules')
|
23
|
+
|
24
|
+
ForemanVault::VaultClient.any_instance.stubs(:put_policy).returns(true)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'does successfully push policies' do
|
28
|
+
host
|
29
|
+
|
30
|
+
stdout, _stderr = capture_io do
|
31
|
+
Rake::Task[TASK_NAME].invoke
|
32
|
+
end
|
33
|
+
|
34
|
+
assert_match("[1/1] Policy of \"#{host.name}\" pushed to Vault server \"#{host.vault_connection.url}\"", stdout)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'does throw an error when host was deleted' do
|
38
|
+
host
|
39
|
+
|
40
|
+
Host::Managed.any_instance.stubs(:reload).raises(ActiveRecord::RecordNotFound)
|
41
|
+
|
42
|
+
stdout, _stderr = capture_io do
|
43
|
+
Rake::Task[TASK_NAME].invoke
|
44
|
+
end
|
45
|
+
|
46
|
+
assert_match("[1/1] Failed to push \"#{host.name}\"", stdout)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -10,11 +10,18 @@ module ForemanVault
|
|
10
10
|
let(:queue) { mock('queue') }
|
11
11
|
let(:vault_policy) { mock('vault_policy') }
|
12
12
|
let(:vault_auth_method) { mock('vault_auth_method') }
|
13
|
+
let(:vault_connection) { FactoryBot.create(:vault_connection, :without_callbacks) }
|
13
14
|
|
14
15
|
setup do
|
15
16
|
host.stubs(:queue).returns(queue)
|
16
17
|
host.stubs(:vault_policy).returns(vault_policy)
|
17
18
|
host.stubs(:vault_auth_method).returns(vault_auth_method)
|
19
|
+
FactoryBot.create(:parameter, name: 'vault_connection', value: vault_connection.name)
|
20
|
+
if Setting.find_by(name: 'vault_orchestration_enabled')
|
21
|
+
Setting['vault_orchestration_enabled'] = true
|
22
|
+
else
|
23
|
+
FactoryBot.create(:setting, name: :vault_orchestration_enabled, value: true)
|
24
|
+
end
|
18
25
|
end
|
19
26
|
|
20
27
|
test 'should queue Vault orchestration' do
|
@@ -50,9 +57,50 @@ module ForemanVault
|
|
50
57
|
end
|
51
58
|
end
|
52
59
|
|
60
|
+
describe '#queue_vault_destroy' do
|
61
|
+
let(:host) { FactoryBot.create(:host, :managed) }
|
62
|
+
let(:queue) { mock('queue') }
|
63
|
+
let(:vault_policy) { mock('vault_policy') }
|
64
|
+
let(:vault_auth_method) { mock('vault_auth_method') }
|
65
|
+
let(:vault_connection) { FactoryBot.create(:vault_connection, :without_callbacks) }
|
66
|
+
|
67
|
+
setup do
|
68
|
+
host.stubs(:queue).returns(queue)
|
69
|
+
host.stubs(:vault_policy).returns(vault_policy)
|
70
|
+
host.stubs(:vault_auth_method).returns(vault_auth_method)
|
71
|
+
FactoryBot.create(:parameter, name: 'vault_connection', value: vault_connection.name)
|
72
|
+
if Setting.find_by(name: 'vault_orchestration_enabled')
|
73
|
+
Setting['vault_orchestration_enabled'] = true
|
74
|
+
else
|
75
|
+
FactoryBot.create(:setting, name: :vault_orchestration_enabled, value: true)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when auth_method is valid' do
|
80
|
+
test 'should queue del_vault' do
|
81
|
+
vault_auth_method.stubs(:valid?).returns(true)
|
82
|
+
|
83
|
+
queue.expects(:create).with(
|
84
|
+
name: "Clear #{host} Vault data",
|
85
|
+
priority: 60,
|
86
|
+
action: [host, :del_vault]
|
87
|
+
).once
|
88
|
+
host.send(:queue_vault_destroy)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when auth_method is not valid' do
|
93
|
+
test 'should not queue del_vault' do
|
94
|
+
vault_auth_method.stubs(:valid?).returns(false)
|
95
|
+
|
96
|
+
queue.expects(:create).never
|
97
|
+
host.send(:queue_vault_destroy)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
53
102
|
describe '#set_vault' do
|
54
|
-
let(:
|
55
|
-
let(:host) { FactoryBot.create(:host, :managed, environment: environment) }
|
103
|
+
let(:host) { FactoryBot.create(:host, :managed) }
|
56
104
|
let(:vault_connection) { FactoryBot.create(:vault_connection, :without_callbacks) }
|
57
105
|
let(:new_owner) { FactoryBot.create(:usergroup, name: 'MyOwner') }
|
58
106
|
|
@@ -64,16 +112,16 @@ module ForemanVault
|
|
64
112
|
)
|
65
113
|
end
|
66
114
|
|
67
|
-
let(:new_policy_name) { "#{new_owner}-#{host.
|
115
|
+
let(:new_policy_name) { "#{new_owner}-#{host.name}".parameterize }
|
68
116
|
let(:put_policy_request) do
|
69
117
|
url = "#{vault_connection.url}/v1/sys/policy/#{new_policy_name}"
|
70
118
|
# rubocop:disable Metrics/LineLength
|
71
|
-
rules = "# allow access to secrets from puppet hosts from <foreman_owner>-<
|
119
|
+
rules = "# allow access to secrets from puppet hosts from <foreman_owner>-<hostname>\npath \"secrets/data/MyOwner/#{host.name}/*\" {\n capabilities = [\"create\", \"read\", \"update\"]\n}\n"
|
72
120
|
# rubocop:enable Metrics/LineLength
|
73
121
|
stub_request(:put, url).with(body: JSON.fast_generate(rules: rules)).to_return(status: 200)
|
74
122
|
end
|
75
123
|
|
76
|
-
let(:new_auth_method_name) {
|
124
|
+
let(:new_auth_method_name) { host.name.parameterize }
|
77
125
|
let(:post_auth_method_request) do
|
78
126
|
url = "#{vault_connection.url}/v1/auth/cert/certs/#{new_auth_method_name}"
|
79
127
|
stub_request(:post, url).with(
|
@@ -85,14 +133,23 @@ module ForemanVault
|
|
85
133
|
).to_return(status: 200)
|
86
134
|
end
|
87
135
|
|
88
|
-
let(:
|
136
|
+
let(:override_old_auth_method_request) do
|
89
137
|
url = "#{vault_connection.url}/v1/auth/cert/certs/#{host.vault_auth_method.name}"
|
90
138
|
stub_request(:delete, url).to_return(status: 200)
|
91
139
|
end
|
92
140
|
|
93
141
|
setup do
|
94
142
|
Setting.find_by(name: 'ssl_ca_file').update(value: File.join(ForemanVault::Engine.root, 'test/fixtures/ca.crt'))
|
95
|
-
|
143
|
+
if Setting.find_by(name: 'vault_orchestration_enabled')
|
144
|
+
Setting['vault_orchestration_enabled'] = true
|
145
|
+
else
|
146
|
+
FactoryBot.create(:setting, name: :vault_orchestration_enabled, value: true)
|
147
|
+
end
|
148
|
+
if Setting.find_by(name: 'vault_policy_template')
|
149
|
+
Setting['vault_policy_template'] = 'Default Vault Policy'
|
150
|
+
else
|
151
|
+
FactoryBot.create(:setting, :vault_policy)
|
152
|
+
end
|
96
153
|
FactoryBot.create(:provisioning_template, :vault_policy, name: Setting['vault_policy_template'])
|
97
154
|
FactoryBot.create(:parameter, name: 'vault_connection', value: vault_connection.name)
|
98
155
|
host.stubs(:skip_orchestration_for_testing?).returns(false)
|
@@ -100,13 +157,11 @@ module ForemanVault
|
|
100
157
|
get_policies_request
|
101
158
|
put_policy_request
|
102
159
|
post_auth_method_request
|
103
|
-
delete_old_auth_method_request
|
104
160
|
|
105
161
|
host.update(owner: new_owner)
|
106
162
|
end
|
107
163
|
|
108
164
|
it { assert_requested(post_auth_method_request) }
|
109
|
-
it { assert_requested(delete_old_auth_method_request) }
|
110
165
|
|
111
166
|
context 'when policy already exists on Vault' do
|
112
167
|
let(:vault_policies) { [new_policy_name] }
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_plugin_helper'
|
4
|
+
|
5
|
+
class VaultPolicyTemplateTest < ActiveSupport::TestCase
|
6
|
+
let(:host) { FactoryBot.create(:host, :managed) }
|
7
|
+
let(:template) { FactoryBot.create(:provisioning_template, :vault_policy) }
|
8
|
+
|
9
|
+
it 'is rendered from a database' do
|
10
|
+
Foreman::Renderer.expects(:get_source).with(has_entry(klass: Foreman::Renderer::Source::Database))
|
11
|
+
Foreman::Renderer.stubs(:get_scope)
|
12
|
+
Foreman::Renderer.stubs(:render)
|
13
|
+
|
14
|
+
template.render
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'render in default mode' do
|
18
|
+
assert_nothing_raised { template.render(host: host) }
|
19
|
+
end
|
20
|
+
|
21
|
+
test 'render in safe mode' do
|
22
|
+
assert_nothing_raised { template.render(renderer: Foreman::Renderer::SafeModeRenderer, host: host) }
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'render in unsafe mode' do
|
26
|
+
assert_nothing_raised { template.render(renderer: Foreman::Renderer::UnsafeModeRenderer, host: host) }
|
27
|
+
end
|
28
|
+
end
|
@@ -8,26 +8,13 @@ class VaultAuthMethodTest < ActiveSupport::TestCase
|
|
8
8
|
let(:host) { FactoryBot.create(:host, :managed) }
|
9
9
|
|
10
10
|
describe '#name' do
|
11
|
-
context 'with host
|
12
|
-
|
13
|
-
subject.stubs(:vault_policy_name).returns('vault_policy_name')
|
14
|
-
end
|
15
|
-
|
16
|
-
it { assert_equal "#{host}-vault_policy_name".parameterize, subject.name }
|
11
|
+
context 'with host' do
|
12
|
+
it { assert_equal host.name.parameterize, subject.name }
|
17
13
|
end
|
18
14
|
|
19
15
|
context 'without host' do
|
20
16
|
setup do
|
21
17
|
subject.stubs(:host).returns(nil)
|
22
|
-
subject.stubs(:vault_policy_name).returns('vault_policy_name')
|
23
|
-
end
|
24
|
-
|
25
|
-
it { assert_nil subject.name }
|
26
|
-
end
|
27
|
-
|
28
|
-
context 'without vault_policy_name' do
|
29
|
-
setup do
|
30
|
-
subject.stubs(:vault_policy_name).returns(nil)
|
31
18
|
end
|
32
19
|
|
33
20
|
it { assert_nil subject.name }
|
@@ -91,18 +78,18 @@ class VaultAuthMethodTest < ActiveSupport::TestCase
|
|
91
78
|
end
|
92
79
|
|
93
80
|
describe '#delete' do
|
94
|
-
context '
|
81
|
+
context 'when valid' do
|
95
82
|
it 'deletes Certificate' do
|
96
|
-
subject.stubs(:
|
83
|
+
subject.stubs(:valid?).returns(true)
|
97
84
|
|
98
85
|
subject.expects(:delete_certificate).once.with(subject.name)
|
99
86
|
subject.delete
|
100
87
|
end
|
101
88
|
end
|
102
89
|
|
103
|
-
context '
|
90
|
+
context 'when not valid' do
|
104
91
|
it 'does not delete Certificate' do
|
105
|
-
subject.stubs(:
|
92
|
+
subject.stubs(:valid?).returns(false)
|
106
93
|
|
107
94
|
subject.expects(:delete_certificate).never
|
108
95
|
subject.delete
|
@@ -3,10 +3,46 @@
|
|
3
3
|
require 'test_plugin_helper'
|
4
4
|
|
5
5
|
class VaultClientTest < ActiveSupport::TestCase
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
subject do
|
7
|
+
ForemanVault::VaultClient.new(base_url, token, nil, nil).tap do |vault_client|
|
8
|
+
vault_client.instance_variable_set(:@client, client)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:client) { Vault::Client }
|
13
|
+
let(:base_url) { 'http://127.0.0.1:8200' }
|
14
|
+
let(:token) { 's.opkr0MAqme5e5nr3i2or5wZC' }
|
15
|
+
|
16
|
+
describe 'auth with AppRole' do
|
17
|
+
subject { ForemanVault::VaultClient.new(base_url, nil, role_id, secret_id) }
|
18
|
+
|
19
|
+
let(:role_id) { '8403910c-e563-d2f2-1c77-6e26319be8b5' }
|
20
|
+
let(:secret_id) { '1058434b-b4aa-bf5a-b376-a15d9efb1059' }
|
21
|
+
|
22
|
+
setup do
|
23
|
+
stub_request(:post, "#{base_url}/v1/auth/approle/login").with(
|
24
|
+
body: {
|
25
|
+
role_id: role_id,
|
26
|
+
secret_id: secret_id
|
27
|
+
}
|
28
|
+
).to_return(
|
29
|
+
status: 200,
|
30
|
+
headers: { 'Content-Type': 'application/json' },
|
31
|
+
body: {
|
32
|
+
auth: {
|
33
|
+
client_token: token
|
34
|
+
}
|
35
|
+
}.to_json
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
it { assert_equal token, subject.send(:client).token }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'auth with token' do
|
43
|
+
subject { ForemanVault::VaultClient.new(base_url, token, nil, nil) }
|
44
|
+
|
45
|
+
it { assert_equal token, subject.send(:client).token }
|
10
46
|
end
|
11
47
|
|
12
48
|
describe '#fetch_expire_time' do
|
@@ -14,11 +50,11 @@ class VaultClientTest < ActiveSupport::TestCase
|
|
14
50
|
@time = '2018-08-01T20:08:55.525830559+02:00'
|
15
51
|
response = OpenStruct.new(data: { expire_time: @time })
|
16
52
|
auth_token = mock.tap { |object| object.expects(:lookup_self).once.returns(response) }
|
17
|
-
|
53
|
+
client.expects(:auth_token).once.returns(auth_token)
|
18
54
|
end
|
19
55
|
|
20
56
|
test 'should return expire time' do
|
21
|
-
assert_equal Time.zone.parse(@time),
|
57
|
+
assert_equal Time.zone.parse(@time), subject.fetch_expire_time
|
22
58
|
end
|
23
59
|
end
|
24
60
|
|
@@ -29,11 +65,11 @@ class VaultClientTest < ActiveSupport::TestCase
|
|
29
65
|
response = OpenStruct.new(data: @data)
|
30
66
|
logical = mock.tap { |object| object.expects(:read).once.with(@secret_path).returns(response) }
|
31
67
|
|
32
|
-
|
68
|
+
client.expects(:logical).once.returns(logical)
|
33
69
|
end
|
34
70
|
|
35
71
|
test 'should return expire time' do
|
36
|
-
assert_equal @data,
|
72
|
+
assert_equal @data, subject.fetch_secret(@secret_path)
|
37
73
|
end
|
38
74
|
end
|
39
75
|
|
@@ -52,11 +88,11 @@ class VaultClientTest < ActiveSupport::TestCase
|
|
52
88
|
response = OpenStruct.new(data: @data)
|
53
89
|
logical = mock.tap { |object| object.expects(:write).once.with(@pki_path).returns(response) }
|
54
90
|
|
55
|
-
|
91
|
+
client.expects(:logical).once.returns(logical)
|
56
92
|
end
|
57
93
|
|
58
94
|
test 'should return new certificate' do
|
59
|
-
assert_equal @data,
|
95
|
+
assert_equal @data, subject.issue_certificate(@pki_path)
|
60
96
|
end
|
61
97
|
end
|
62
98
|
end
|
@@ -8,7 +8,11 @@ class VaultPolicyTest < ActiveSupport::TestCase
|
|
8
8
|
let(:host) { FactoryBot.create(:host, :managed) }
|
9
9
|
|
10
10
|
setup do
|
11
|
-
|
11
|
+
if Setting.find_by(name: 'vault_policy_template')
|
12
|
+
Setting['vault_policy_template'] = 'Default Vault Policy'
|
13
|
+
else
|
14
|
+
FactoryBot.create(:setting, name: 'vault_policy_template', value: 'Default Vault Policy')
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
describe 'valid?' do
|
@@ -112,18 +116,18 @@ class VaultPolicyTest < ActiveSupport::TestCase
|
|
112
116
|
end
|
113
117
|
|
114
118
|
describe '#delete' do
|
115
|
-
context '
|
119
|
+
context 'when valid' do
|
116
120
|
it 'deletes Vault Policy' do
|
117
|
-
subject.stubs(:
|
121
|
+
subject.stubs(:valid?).returns(true)
|
118
122
|
|
119
123
|
subject.expects(:delete_policy).once.with(subject.name)
|
120
124
|
subject.delete
|
121
125
|
end
|
122
126
|
end
|
123
127
|
|
124
|
-
context '
|
128
|
+
context 'when not valid' do
|
125
129
|
it 'does not delete Vault Policy' do
|
126
|
-
subject.stubs(:
|
130
|
+
subject.stubs(:valid?).returns(false)
|
127
131
|
|
128
132
|
subject.expects(:delete_policy).never
|
129
133
|
subject.delete
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_vault
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dmTECH GmbH
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: vault
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.54.0
|
55
|
-
description:
|
55
|
+
description:
|
56
56
|
email:
|
57
57
|
- opensource@dm.de
|
58
58
|
executables: []
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- app/lib/foreman_vault/macros.rb
|
71
71
|
- app/models/concerns/foreman_vault/host_extensions.rb
|
72
72
|
- app/models/concerns/foreman_vault/orchestration/vault_policy.rb
|
73
|
+
- app/models/concerns/foreman_vault/provisioning_template_extensions.rb
|
73
74
|
- app/models/setting/vault.rb
|
74
75
|
- app/models/vault_connection.rb
|
75
76
|
- app/services/foreman_vault/vault_auth_method.rb
|
@@ -91,6 +92,7 @@ files:
|
|
91
92
|
- config/routes.rb
|
92
93
|
- db/migrate/20180725072913_create_vault_connection.foreman_vault.rb
|
93
94
|
- db/migrate/20180809172407_rename_vault_status_to_vault_error.foreman_vault.rb
|
95
|
+
- db/migrate/20201203220058_add_approle_to_vault_connection.rb
|
94
96
|
- db/seeds.d/103-provisioning_templates.rb
|
95
97
|
- lib/foreman_vault.rb
|
96
98
|
- lib/foreman_vault/engine.rb
|
@@ -107,8 +109,11 @@ files:
|
|
107
109
|
- test/functional/api/v2/vault_connections_controller_test.rb
|
108
110
|
- test/jobs/refresh_vault_token_test.rb
|
109
111
|
- test/jobs/refresh_vault_tokens_test.rb
|
112
|
+
- test/lib/tasks/push_auth_methods_test.rb
|
113
|
+
- test/lib/tasks/push_policies_test.rb
|
110
114
|
- test/models/foreman_vault/orchestration/vault_policy_test.rb
|
111
115
|
- test/models/vault_connection_test.rb
|
116
|
+
- test/models/vault_policy_template_test.rb
|
112
117
|
- test/test_plugin_helper.rb
|
113
118
|
- test/unit/lib/foreman_vault/macros_test.rb
|
114
119
|
- test/unit/services/foreman_vault/vault_auth_method_test.rb
|
@@ -118,7 +123,7 @@ homepage: https://github.com/dm-drogeriemarkt/foreman_vault
|
|
118
123
|
licenses:
|
119
124
|
- GPL-3.0
|
120
125
|
metadata: {}
|
121
|
-
post_install_message:
|
126
|
+
post_install_message:
|
122
127
|
rdoc_options: []
|
123
128
|
require_paths:
|
124
129
|
- lib
|
@@ -133,8 +138,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
138
|
- !ruby/object:Gem::Version
|
134
139
|
version: '0'
|
135
140
|
requirements: []
|
136
|
-
rubygems_version: 3.
|
137
|
-
signing_key:
|
141
|
+
rubygems_version: 3.2.28
|
142
|
+
signing_key:
|
138
143
|
specification_version: 4
|
139
144
|
summary: Adds support for using credentials from Hashicorp Vault
|
140
145
|
test_files:
|
@@ -142,11 +147,14 @@ test_files:
|
|
142
147
|
- test/unit/services/foreman_vault/vault_client_test.rb
|
143
148
|
- test/unit/services/foreman_vault/vault_policy_test.rb
|
144
149
|
- test/unit/services/foreman_vault/vault_auth_method_test.rb
|
150
|
+
- test/models/vault_policy_template_test.rb
|
145
151
|
- test/models/vault_connection_test.rb
|
146
152
|
- test/models/foreman_vault/orchestration/vault_policy_test.rb
|
147
153
|
- test/factories/vault_policy_template.rb
|
148
154
|
- test/factories/vault_connection.rb
|
149
155
|
- test/factories/vault_setting.rb
|
156
|
+
- test/lib/tasks/push_policies_test.rb
|
157
|
+
- test/lib/tasks/push_auth_methods_test.rb
|
150
158
|
- test/fixtures/ca.crt
|
151
159
|
- test/test_plugin_helper.rb
|
152
160
|
- test/jobs/refresh_vault_tokens_test.rb
|