-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
355 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
# @summary | ||
# Manage a podman secret. Create and remove secrets, it cannot replace. | ||
# | ||
# @param ensure | ||
# State of the resource must be either 'present' or 'absent'. | ||
# | ||
# @param path | ||
# Load secret from an existing file path | ||
# The secret and path parameters are mutually exclusive. | ||
# | ||
# @param secret | ||
# A secret to be stored - can be set as a Deferred function. If the secret is | ||
# changed the secret will **NOT** be modified. Best to set a secret version | ||
# as a label. | ||
# The secret and path parameters are mutually exclusive. | ||
# | ||
# @param flags | ||
# All flags for the 'podman secret create' command are supported as part of the | ||
# 'flags' hash, using only the long form of the flag name. The value for any | ||
# defined flag in the 'flags' hash must be entered as a string. | ||
# If the flags for a secret are modified the secret will be recreated. | ||
# | ||
# @param user | ||
# Optional user for running rootless containers. When using this parameter, | ||
# the user must also be defined as a Puppet resource and must include the | ||
# 'uid', 'gid', and 'home' | ||
# | ||
# @example Set a secret with a version from puppet directly | ||
# podman::secret{'db_password': | ||
# secret => Sensitive('NeverGuess'), | ||
# flags => { | ||
# label => [ | ||
# 'version=20230615', | ||
# ] | ||
# } | ||
# } | ||
# | ||
# @example Set a secret from a file | ||
# podman::secret{'db_password': | ||
# path => '/etc/passwd', | ||
# } | ||
# | ||
# @example Set a secret from a deferred function call. | ||
# podman::secret{'ora_password': | ||
# secret => Sensitive(Deferred('secret_lookup',['ora_password'])), | ||
# flags => { | ||
# labels => ['version=20230615'], | ||
# } | ||
# user => 'rootless user', | ||
# } | ||
# | ||
define podman::secret ( | ||
Enum['present','absent'] $ensure = 'present', | ||
Optional[Sensitive[String]] $secret = undef, | ||
Optional[Stdlib::Unixpath] $path = undef, | ||
Optional[String[1]] $user = undef, | ||
Hash $flags = {}, | ||
) { | ||
require podman::install | ||
|
||
# Do not encode and store the secret | ||
$flags_base64 = base64('encode',String($flags.delete('secret')),'strict') | ||
|
||
# Add the default name and a custom label using the base64 encoded flags | ||
if 'label' in $flags { | ||
$label = $flags['label'] + "puppet_resource_flags=${flags_base64}" | ||
$no_label = $flags.delete('label') | ||
} else { | ||
$label = "puppet_resource_flags=${flags_base64}" | ||
$no_label = $flags | ||
} | ||
|
||
# If a secret name is not set, use the Puppet resource name | ||
$merged_flags = merge({ label => $label }, $no_label ) | ||
|
||
# Convert $flags hash to command arguments | ||
$_flags = $merged_flags.reduce('') |$mem, $flag| { | ||
if $flag[1] =~ String { | ||
"${mem} --${flag[0]} '${flag[1]}'" | ||
} elsif $flag[1] =~ Undef { | ||
"${mem} --${flag[0]}" | ||
} else { | ||
$dup = $flag[1].reduce('') |$mem2, $value| { | ||
"${mem2} --${flag[0]} '${value}'" | ||
} | ||
"${mem} ${dup}" | ||
} | ||
} | ||
|
||
if $user { | ||
ensure_resource('podman::rootless', $user, {}) | ||
|
||
# Set execution environment for the rootless user | ||
$exec_defaults = { | ||
path => '/sbin:/usr/sbin:/bin:/usr/bin', | ||
environment => [ | ||
"HOME=${User[$user]['home']}", | ||
"XDG_RUNTIME_DIR=/run/user/${User[$user]['uid']}", | ||
], | ||
cwd => User[$user]['home'], | ||
provider => 'shell', | ||
user => $user, | ||
require => [ | ||
Podman::Rootless[$user], | ||
Service['podman systemd-logind'], | ||
], | ||
} | ||
} else { | ||
$exec_defaults = { | ||
path => '/sbin:/usr/sbin:/bin:/usr/bin', | ||
provider => 'shell', | ||
} | ||
} | ||
|
||
if $secret and $path { | ||
fail('Only one of the parameters path or secret to podman::secret must be set') | ||
} elsif $secret { | ||
$_command = Sensitive(stdlib::deferrable_epp('podman/set_secret_from_stdin.epp', { | ||
'secret' => $secret , | ||
'title' => $title, | ||
'flags' => $_flags, | ||
})) | ||
} elsif $path { | ||
$_command = "podman secret create${_flags} ${title} ${path}" | ||
} else { | ||
fail('One of the parameters path or secret to podman::secret must be set') | ||
} | ||
|
||
case $ensure { | ||
'present': { | ||
Exec { "create_secret_${title}": | ||
command => $_command, | ||
unless => "test \"$(podman secret inspect ${title} --format ''{{.Spec.Labels.puppet_resource_flags}}'')\" = \"${flags_base64}\"", | ||
* => $exec_defaults, | ||
} | ||
} | ||
default: { | ||
Exec { "create_secret_${title}": | ||
command => $_command, | ||
unless => "podman secret rm ${title}", | ||
onlyif => "podman secret inspect ${title}", | ||
* => $exec_defaults, | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
require 'spec_helper' | ||
|
||
describe 'podman::secret' do | ||
let(:title) { 'root_password' } | ||
let(:params) do | ||
{ | ||
ensure: 'present', | ||
} | ||
end | ||
let(:pre_condition) do | ||
'user {"testuser": | ||
ensure => "present", | ||
home => "/home/testuser", | ||
uid => 5000, | ||
gid => 5000, | ||
managehome => true, | ||
} | ||
file {"/home/testuser": | ||
ensure => "directory", | ||
} | ||
class {"podman": | ||
podman_pkg => "podman", | ||
skopeo_pkg => "skopeo", | ||
buildah_pkg => "buildah", | ||
buildah_pkg_ensure => "installed", | ||
podman_docker_pkg_ensure => "installed", | ||
podman_docker_pkg => "podman-docker", | ||
manage_subuid => true, | ||
file_header => " FILE MANAGED BY PUPPET", | ||
match_subuid_subgid => true, | ||
subid => { | ||
testuser => { | ||
subuid => 5000000, | ||
count => 1000, | ||
}, | ||
}, | ||
nodocker => "file", | ||
}' | ||
end | ||
|
||
on_supported_os.each do |os, os_facts| | ||
context "on #{os}" do | ||
let(:facts) { os_facts } | ||
|
||
it { is_expected.to compile.and_raise_error(%r{One of the parameters path or secret}) } | ||
context 'with secret and path parameter set' do | ||
let(:params) do | ||
super().merge(secret: sensitive('tiptop'), path: '/bin/fail') | ||
end | ||
|
||
it { is_expected.to compile.and_raise_error(%r{Only one of the parameters path or secret}) } | ||
end | ||
context 'with secret parameter set' do | ||
let(:params) do | ||
super().merge(secret: sensitive('tiptop')) | ||
end | ||
|
||
it { is_expected.to compile } | ||
it { is_expected.to contain_exec('create_secret_root_password') } | ||
it { | ||
is_expected.to contain_exec('create_secret_root_password') | ||
.with_command(sensitive("printf 'tiptop' | podman secret create --label 'puppet_resource_flags=e30=' root_password -\n")) | ||
.with_unless("test \"\$(podman secret inspect root_password --format ''{{.Spec.Labels.puppet_resource_flags}}'')\" = \"e30=\"") | ||
} | ||
end | ||
context 'with path parameter set' do | ||
let(:params) do | ||
super().merge(path: '/tmp/my_root') | ||
end | ||
|
||
it { is_expected.to compile } | ||
it { | ||
is_expected.to contain_exec('create_secret_root_password') | ||
.with_command("podman secret create --label 'puppet_resource_flags=e30=' root_password /tmp/my_root") | ||
} | ||
context 'with a label set' do | ||
let(:params) do | ||
super().merge(flags: { label: ['trust=this'] }) | ||
end | ||
|
||
it { | ||
is_expected.to contain_exec('create_secret_root_password') | ||
.with_command("podman secret create --label 'trust=this' --label 'puppet_resource_flags=eydsYWJlbCcgPT4gWyd0cnVzdD10aGlzJ119' root_password /tmp/my_root") | ||
.with_unless("test \"\$(podman secret inspect root_password --format ''{{.Spec.Labels.puppet_resource_flags}}'')\" = \"eydsYWJlbCcgPT4gWyd0cnVzdD10aGlzJ119\"") | ||
} | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.