0

Hi StackOverflow community,

I am writing an ansible playbook which automatically stores encrypted secrets with ansible vault that the play will generate.

You know the kind of thing I am talking about, looks like:

---
my_secret_thing: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          64356439663234656438636635316531623966623736396235376562613039356435623135366164
          3939626637326538663934636637643761etcetcetc

When a change occurs to a secret I want to comment out that entire secret and add a new one. Originally I used the following ansible task to comment out the section:

  - name: Comment out previous secret
    run_once: True
    ansible.builtin.shell: "grep '^my_secret_thing' $PWD/{{ env }}_group_vars/secrets.yml && START=$(cat $PWD/{{ env }}_group_vars/secrets.yml |grep -n '^my_secret_thing'|cut -d ':' -f 1) && END=$(expr $START + 10) && sed -i \"$START,$END s/^/#/\" $PWD/{{ env }}_group_vars/secrets.yml"
    delegate_to: 127.0.0.1
    ignore_errors: True # Otherwise will 'fail' if no token is currently stored

When I first wrote this it seemed that the each secret took up the same amount of lines so pretty much 'ind the matching line of the var name and comment out x amount of lines'. However, it seems that assumption was incorrect.

So how can I, in as simple a way as possible, replace that shell command with one that will comment out the line matching the var name and all the lines starting with whitespace (10 spaces) following a match of the var name and comment them all out UNTIL the next line that is a var name i.e. no whitespace at the beginning.

Any suggestions?

TIA :)

Update: This is what I came up with but I was hoping for something shorter and sweeter:

#!/bin/bash

MATCH=0
COUNT=0
IFS=$'\n'
for LINE in `cat secrets.yml`;
do
  if [ $MATCH -eq 0 ];
  then
    if [ `echo $LINE |grep '^my_secret_stuff:'` ];
    then
      MATCH=1
      continue
    else
      continue
    fi
  fi
  if [ $MATCH -eq 1 ];
  then
    if [ $MATCH -eq 1 ] && [ `echo $LINE |grep '^ \{10\}'` ];
    then
      let COUNT++
      continue
    elif [ `echo $LINE |grep '^[a-z_]*:'` ];
    then
      break
    fi
  fi
done
unset IFS
echo $COUNT

Using the above I could set $END as the result and keep the same essential format but I can't help feel there must be a shorter way i.e. something that can be a one liner.

  • 3
    I think I would store each secret in a separate file and then just rename the file to a different directory when it has expired That seems far less complex than the logic you've got going on here. – larsks Sep 20 '22 at 02:16
  • 1
    To edit YAML, use a tool which understands the format, like `yq` – tripleee Sep 20 '22 at 09:35

0 Answers0