I want to create SSL certificate and try to secure this operation.
I am using Puppet 5.5.2 and gem hiera-eyaml.
Created simple manifest
cat /etc/puppetlabs/code/environments/production/manifests/site.pp
package { 'tree':
ensure => installed,
}
package { 'httpd':
ensure => installed,
}
$filecrt = lookup('files')
create_resources( 'file', $filecrt )
Hiera config
---
version: 5
defaults:
# The default value for "datadir" is "data" under the same directory as the hiera.yaml
# file (this file)
# When specifying a datadir, make sure the directory exists.
# See https://puppet.com/docs/puppet/latest/environments_about.html for further details on environments.
datadir: data
data_hash: yaml_data
hierarchy:
- name: "Secret data: per-node, per-datacenter, common"
lookup_key: eyaml_lookup_key # eyaml backend
paths:
- "nodes/%{facts.fqdn}.eyaml"
- "nodes/%{trusted.certname}.eyaml" # Include explicit file extension
- "location/%{facts.whereami}.eyaml"
- "common.eyaml"
options:
pkcs7_private_key: /etc/puppetlabs/puppet/eyaml/keys/private_key.pkcs7.pem
pkcs7_public_key: /etc/puppetlabs/puppet/eyaml/keys/public_key.pkcs7.pem
- name: "YAML hierarchy levels"
paths:
- "common.yaml"
- "nodes/%{facts.fqdn}.yaml"
- "nodes/%{::trusted.certname}.yaml"
And common.yaml
---
files:
'/etc/httpd/conf/server.crt':
ensure: present
mode: '0600'
owner: 'root'
group: 'root'
content: 'ENC[PKCS7,{LOT_OF_STRING_SKIPPED}+uaCmcHgDAzsPD51soM+AIkIlv0ANpUXzBpwM3tqQ3ysFtz81S0xuVbKvslK]'
But have en error while applying manifest
Error: Evaluation Error: Error while evaluating a Function Call, create_resources(): second argument must be a hash (file: /etc/puppetlabs/code/environments/production/manifests/site.pp, line: 12, column: 1) on node test1.com
I really dont know what to do )
The problem appears to be that the indentation in common.yaml isn't right - currently, file will be null rather than a hash, which explains the error message. Also, the file should be called common.eyaml, otherwise the ENC string won't be decrypted. Try
---
files:
'/etc/httpd/conf/server.crt':
ensure: present
mode: '0600'
owner: 'root'
group: 'root'
content: 'ENC[PKCS7{LOTS_OF_STRING_SKIPPED}UXzBpwM3tqQ3ysFtz81S0xuVbKvslK]'
There is an online YAML parser at http://yaml-online-parser.appspot.com/ if you want to see the difference the indentation makes.
Found another solution.
Its was a problem with lookup and hashes. When I have multiply lines in hiera hash, I must specify them https://docs.puppet.com/puppet/4.5/function.html#lookup
So i decided use only 'content' variable to lookup
cat site.pp
$filecrt = lookup('files')
file { 'server.crt':
ensure => present,
path => '/etc/httpd/conf/server.crt',
content => $filecrt,
owner => 'root',
group => 'root',
mode => '0600',
}
and Hiera
---
files:'ENC[PKCS7{LOT_OF_STRING_SKIPPED}+uaCmcHgDAzsPD51soM+AIkIlv0ANpUXzBpwM3tqQ3ysFtz81S0xuVbKvslK]'
Related
I wrote a python script which gets executed via my ansible playbook and returns the following output via stdout:
- { username: ansible, admin: yes}
- { username: test, admin: no }
The output then should get saved in the variable "users" and with the "with_items" (or the newer "loop" conditional) I want to iterate through the variable in order to assign the right permissions for each user separately:
- name: execute python script
command: "python3 /tmp/parse_string.py --user_permissions={{ user_permissions }}"
register: output
- name: register
set_fact:
users: "{{ output.stdout }}"
- name: output
debug: msg="{{ users }}"
- name: Add user to group -admin
user:
name={{ item.username }}
groups=admin
append=yes
state=present
when: "item.admin == yes"
with_items: '{{users}}
However when launching the playbook it says that the variable "users" has no attribute "username".
TASK [create_users : output] ***************************************************
ok: [ansible] => {
"msg": "- { username: ansible, admin: yes }\n- { username: test, admin: no }\n- { username: test2, admin: no }"
}
TASK [create_users : Add user to group -admin ***************
fatal: [ansible]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'username'\n\nThe error appears to be in '***': line 29, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: \n ^ here\n"}
Can anyone help me with this case?
BR
You are setting your users var to a string. It happens that this string is a yaml representation of a datastructure but ansible has no clue about that at this point.
To achieve your requirement, you need to parse that string as yaml and register the result. Luckily, there is a from_yaml filter for that purpose
You just have to modify your set_fact task as the following and everything should work as expected:
- name: register
set_fact:
users: "{{ output.stdout | from_yaml }}"
I use ansible-module-vcloud, and I want to create VMs via Ansible. For example, I want to create easiest playbook.
I have this code:
---
- name: vCloudDirectorAnsible
hosts: localhost
environment:
env_user: admin
env_password: admin
env_host: vcloud.vmware.ru
env_org: test
env_api_version: 30.0
env_verify_ssl_certs: false
- name: create catalog
vcd_catalog:
catalog_name: "test"
catalog_description: "test_Descr"
state: "present"
But I got error:
ERROR! 'vcd_catalog' is not a valid attribute for a Play
The error appears to have been in '/root/ansible-module-vcloud-director/main.yml': line 14, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: create catalog
^ here
If I delete this part:
- name: create catalog
vcd_catalog:
catalog_name: "test"
catalog_description: "test_Descr"
state: "present"
My playbook will run and successfully completed.
How to fix this?
You missed the tasks keyword.
---
- name: vCloudDirectorAnsible
hosts: localhost
environment:
env_user: admin
env_password: admin
env_host: vcloud.vmware.ru
env_org: test
env_api_version: 30.0
env_verify_ssl_certs: false
tasks:
- name: create catalog
vcd_catalog:
catalog_name: "test"
catalog_description: "test_Descr"
state: "present"
I am attempting to define my user accounts as Hashes in Hiera, like this:
---
accounts::user:
jack:
ensure: present
bashrc_content: file('accounts/shell/bashrc')
bash_profile_content: file('accounts/shell/bash_profile')
It works fine if I define them in my *.pp files.
Please, find more details about hiera.yaml, manifest and users.yamal on Gist
Why doesn't this work?
P.S. This question continues to,
No, what you are trying to do is not possible.
I have a few options for you. In Hiera, you could have all of the data other than the call to the file() function:
---
accounts::user:
jack:
locked: false
comment: Jack Doe
ensure: present
groups:
- admins
- sudo
shell: '/bin/bash'
home_mode: '0700'
purge_sshkeys: false
managehome: true
managevim: false
sshkeys:
- ssh-rsa AAAA
password: '70'
And then in your manifest:
$defaults = {
'bashrc_content' => file('accounts/shell/bashrc'),
'bash_profile_content' => file('accounts/shell/bash_profile'),
}
$user_data = lookup('accounts::user', Hash[String,Hash], 'hash', {})
$user_data.each |$user,$props| {
accounts::user { $user: * => $props + $defaults }
}
Another option is to simply include your file content in the YAML data, i.e.
---
accounts::user:
jack:
locked: false
comment: Jack Doe
ensure: present
groups:
- admins
- sudo
shell: '/bin/bash'
home_mode: '0700'
purge_sshkeys: false
managehome: true
managevim: false
bashrc_content: |
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
if [ -f /etc/bashrc ]; then
. /etc/bashrc # --> Read /etc/bashrc, if present.
fi
...
bash_profile_content: ...
sshkeys:
- ssh-rsa AAAA
password: '70'
Then you won't need the file function or the files at all.
For more info:
On what you can interpolate in Hiera data.
The splat operator (*) and a useful blog on how to use it.
On multiline-strings in YAML.
I encrypted password using hiera:
dsc_xADUser {'FirstUser':
dsc_ensure => 'present',
dsc_domainname => 'ad.contoso.com',
dsc_username => 'tfl',
dsc_userprincipalname => 'tfl#ad.contoso.com',
dsc_password => {
'user' => 'tfl#ad.contoso.com',
'password' => Sensitive(lookup('password'))
},
dsc_passwordneverexpires => true,
dsc_domainadministratorcredential => {
'user' => 'Administrator#ad.contoso.com',
'password' => Sensitive(lookup('password'))
},
}
but on node,when running agent -t -v password is shown as plain text in agent output and in catalog JSON file.
I also tried node_encrypt(lookup('password')) then getting content of my encrypted password (which is good) and windows complains that password doesn't meet password complexity (bad-because it's trying to set all below as password)
'password' = '-----BEGIN PKCS7-----
MIIMyQYJKoZIhvcNAQcDoIIMujCCDLYCAQAxggKdMIICmQIBADCBgjB9MXsweQYD
VQQDDHJQdXBwZXQgRW50ZXJwcmlzZSBDQSBnZW5lcmF0ZWQgb24gbXlwdXBwZXQt
eGwwZGJ5a212Z2xrYnl2eS5ldS13ZXN0LTEub3Bzd29ya3MtY20uaW8gYXQgKzIw
MTgtMTEtMDIgMTQ6MDQ6MDAgKzAwMDACAQUwCwYJKoZIhvcNAQEBBIICABkJDfGb
4CdHUntrVR1E......
hiera config:
---
version: 5
defaults:
datadir: data
data_hash: yaml_data
hierarchy:
- name: "Eyaml hierarchy"
lookup_key: eyaml_lookup_key # eyaml backend
paths:
- "nodes/%{trusted.certname}.yaml"
- "windowspass.eyaml"
options:
pkcs7_private_key: "/etc/puppetlabs/puppet/keys/private_key.pkcs7.pem"
pkcs7_public_key: "/etc/puppetlabs/puppet/keys/public_key.pkcs7.pem"
EDIT: just found this, it seems it's opened issue and related to Windows only
UPDATE: i managed to configure puppet not to cache catalog file on Windows client (adding catalog_cache_terminus="" to puppet config file on windows so i'll use this as "workaround", it seems no way to remove passwords from agent debug output
I have created a proxy_match.yaml file as a hiera source file in
default hiera datalocation.
The proxy_match.yaml is added in hiera hierarchy
Looking up hiera data in profile
Where and what am I missing, I am not able to receive the hiera data
value and thus the error appears mentioned bellow.
Where,
proxy_match is the new environment created
hierafile 1
/etc/puppetlabs/code/environments/proxy_match/hiera.yaml
version: 5
defaults:
# The default value for "datadir" is "data" under the same directory as the hiera.yaml
# file (this file)
# When specifying a datadir, make sure the directory exists.
# See https://docs.puppet.com/puppet/latest/environments.html for further details on environments.
# datadir: data
# data_hash: yaml_data
hierarchy:
- name: "environment specific yaml"
path: "proxy_match.yaml"
- name: "Per-node data (yaml version)"
path: "nodes/%{::trusted.certname}.yaml"
- name: "Other YAML hierarchy levels"
paths:
- "common.yaml"
proxy_match.yaml hiera data source file
This is the yaml hiera source named as proxy_match.yaml as in herarchy
/etc/puppetlabs/code/environments/proxy_match/data/proxy-match.yaml
---
profiles::apache::servername: "taraserver.com"
profiles::apache::port: "80"
profiles::apache::docroot: "/var/www/tarahost"
hiera lookup in profile
$servername = hiera('profiles::apache::servername',{})
$port = hiera('profiles::apache::port',{})
$docroot = hiera('profiles::apache::docroot',{})
class profile::apache{
#configure apache
include apache
apache::vhost{$servername:
port => $port,
docroot => $docroot,
}
}
#ERROR:
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: {"message":"Server Error: Evaluation Error: Error while evaluating a Resource Statement, Apache::Vhost[7fba80ae621c.domain.name]: parameter 'docroot' expects a value of type Boolean or String, got Undef at /etc/puppetlabs/code/environments/proxy_match/modules/profile/manifests/apache.pp:29 on node 94707b03ff05.domain.name","issue_kind":"RUNTIME_ERROR"}
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run
You are defining the variables outside the class definition. When Puppet loads that class, those lines you have before the class are ignored.
What you should have in your profile class is:
class profiles::apache (
String $servername,
Integer $port,
String $docroot,
) {
include apache
apache::vhost { $servername:
port => $port,
docroot => $docroot,
}
}
Note that I used the automatic parameter lookup feature to set your variables, instead of explicit calls to the hiera function.