Skip to content

Commit

Permalink
add vault password
Browse files Browse the repository at this point in the history
  • Loading branch information
vcmirko committed Jun 5, 2024
1 parent ac7d9db commit 87659e0
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Now allowing string (credential name) or array (of names) as dbConfig (dbtype is fetched from the database, with mysql fallback)
When using array, the resultsets are merged.
- Added ytt implementation to template yaml files (credits mdaugs)
- Vault credentials, pass a vault password to ansible playbook.

### Changed

Expand Down
14 changes: 13 additions & 1 deletion docs/_data/help.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,14 @@
short: Pass ansible_user and ansible_password to ansible playbook using stored credentials
description: |
Ansible allows to pass default ansible credentials in the form of 2 extravars ansible_user and ansible_password
- name: vaultCredentials
type: string
group: basic
version: 5.0.2
allowed: a local credentialname
short: Pass vault password to ansible playbook using stored credentials
description: |
Ansible can encrypt variables in a vault, to unlock the vault a password is needed. This password can be stored in Ansible Forms (as credential) and passed to the playbook..
- name: steps
type: array
with_types: multistep
Expand Down Expand Up @@ -4251,8 +4259,12 @@
- name: Enable ytt
short: Enable ytt
description: |
In the case you want to use ytt, tt can be enabled by setting `USE_YTT=1`.
In the case you want to use ytt, it can be enabled by setting `USE_YTT=1`.
Read more info about ytt (https://carvel.dev/ytt/).
**NOTE** : when using ytt, you must disable the designer, the designer will convert the yaml files to intermediate json and will drop the ytt syntax (which is yaml comments).
A `lib` directory needs to exist within the root directory and is automatically included for the ytt call.
Data can be provided globally by setting prefixed environment variables:
Expand Down
13 changes: 7 additions & 6 deletions server/schema/forms_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
"type": {
"enum": ["awx"]
},
"vaultCredentials": {"not":{}},
"playbook": {"not":{}},
"ansibleCredentials": {"not":{}},
"steps": {"not":{}}
Expand All @@ -133,6 +134,7 @@
"enum": ["multistep"]
},
"playbook": {"not":{}},
"vaultCredentials": {"not":{}},
"template": {"not":{}},
"inventory": {"not":{}},
"awxCredentials": {"not":{}},
Expand Down Expand Up @@ -334,6 +336,7 @@
"enum": ["awx"]
},
"playbook": {"not":{}},
"vaultCredentials": {"not":{}},
"ansibleCredentials": {"not":{}},
"steps": {"not":{}}
},
Expand Down Expand Up @@ -367,9 +370,8 @@
"additionalProperties": false,
"uniqueProperties": true
},
"ansibleCredentials": {
"type": "string"
},
"ansibleCredentials": {"type": "string"},
"vaultCredentials": {"type": "string"},
"inventory": {"type": "string"},
"tags": {"type": "string"},
"check": {"type": "boolean"},
Expand Down Expand Up @@ -467,9 +469,8 @@
"default": ""
}
},
"ansibleCredentials":{
"type": "string"
},
"ansibleCredentials": {"type": "string"},
"vaultCredentials": {"type": "string"},
"inventory": {"type": "string"},
"executionEnvironment": {"type": "string"},
"instanceGroups": {
Expand Down
5 changes: 4 additions & 1 deletion server/src/lib/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,13 @@ Helpers.checkAdminMiddleware = (req, res, next) => {
}
// checks for passwords from credentials and masks them
Helpers.logSafe = (v)=>{
var result
if(!v){
return ""
}
return v.replace(/"password":"[^"]+"/g,'"password":"**NOLOG**"')
result = v.replaceAll(/"password":"[^"]+"/g,'"password":"**NOLOG**"')
result = result.replace(/echo .* base64 --decode/g,"echo **NOLOG**")
return result
}
// a smart object placeholder replacer
Helpers.replacePlaceholders = (msg,extravars)=>{
Expand Down
43 changes: 33 additions & 10 deletions server/src/models/job.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function pushForminfoToExtravars(formObj,extravars,creds={}){
// push top form fields to extravars
// change in 4.0.16 => easier to process & available in playbook, might be handy
// no credentials added here, because then can also come from asCredential property and these would get lost.
const topFields=['template','playbook','tags','limit','executionEnvironment','check','diff','verbose','keepExtravars','credentials','inventory','awxCredentials','ansibleCredentials','instanceGroups']
const topFields=['template','playbook','tags','limit','executionEnvironment','check','diff','verbose','keepExtravars','credentials','inventory','awxCredentials','ansibleCredentials','vaultCredentials','instanceGroups']
for (const fieldName of topFields) {
// Check if the field exists in formObj and if the property is not present in extravars
if (formObj.hasOwnProperty(fieldName) && extravars[`__${fieldName}__`] === undefined) {
Expand Down Expand Up @@ -901,6 +901,7 @@ Ansible.launch=async (ev,credentials,jobid,counter,approval,approved=false)=>{
var keepExtravars = extravars?.__keepExtravars__ || false
var diff = extravars?.__diff__ || false
var ansibleCredentials = extravars?.__ansibleCredentials__ || ""
var vaultCredentials = extravars?.__vaultCredentials__ || ""
if(approval){
if(!approved){
await Job.sendApprovalNotification(approval,ev,jobid)
Expand All @@ -917,22 +918,44 @@ Ansible.launch=async (ev,credentials,jobid,counter,approval,approved=false)=>{
extravars = JSON.stringify(extravars)
// define hiddenExtravars
var hiddenExtravars={}
if(ansibleCredentials){
const runCredential = await Credential.findByName(ansibleCredentials)
hiddenExtravars.ansible_user = runCredential.user
hiddenExtravars.ansible_password = runCredential.password
try{
if(ansibleCredentials){
const runCredential = await Credential.findByName(ansibleCredentials)
hiddenExtravars.ansible_user = runCredential.user
hiddenExtravars.ansible_password = runCredential.password
}
// convert to string for the command
hiddenExtravars = JSON.stringify(hiddenExtravars)
}catch(err){
logger.error("Failed to get ansible credentials : ",err)
await Job.endJobStatus(jobid,++counter,"stderr","failed","[ERROR]: Failed to get ansible credentials")
return false
}
// define vaultPassword
var vaultPassword=""
try{
if(vaultCredentials){
const vaultCredential = await Credential.findByName(vaultCredentials)
vaultPassword = vaultCredential.password
}
}catch(err){
logger.error("Failed to get vault credentials : ",err)
await Job.endJobStatus(jobid,++counter,"stderr","failed","[ERROR]: Failed to get vault credentials")
return false
}
// convert to string for the command
hiddenExtravars = JSON.stringify(hiddenExtravars)

// make extravars file
const extravarsFileName = `extravars_${jobid}.json`;
const hiddenExtravarsFileName = `he_${extravarsFileName}`
logger.debug(`Extravars File: ${extravarsFileName}`);
// prepare my ansible command

var command = `ansible-playbook -e '@${extravarsFileName}' -e '@${hiddenExtravarsFileName}'`

var command
if(!vaultPassword){
command = `ansible-playbook -e '@${extravarsFileName}' -e '@${hiddenExtravarsFileName}'`
}else{
command = `echo ${Buffer.from(vaultPassword).toString('base64')} | base64 --decode | ansible-playbook -e '@${extravarsFileName}' -e '@${hiddenExtravarsFileName}' --vault-password-file=/bin/cat`
}

inventory.forEach((item, i) => { command += ` -i '${item}'` });
if(tags){ command += ` -t '${tags}'` }
if(check){ command += ` --check` }
Expand Down

0 comments on commit 87659e0

Please sign in to comment.