foreman_vault 0.2.0 → 1.1.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 +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
|