Targeting sensitive pillar data per minion: "minion id top-file matcher" versus "jinja conditionals around minion id"

67 views
Skip to first unread message

Alexey Pakseykin

unread,
Jul 23, 2016, 11:02:20 AM7/23/16
to Salt-users

I first posted the question on stackoverflow (as it allows fixing/updating the post and techier markdown editing), but reposting the question here may reach larger audience:

(coped and pasted)

Consider two approaches to distribute selected pillar keys to specific minion.

 

1. Top-file matcher using minion id.

 

In this case, top file has to know assignments of pillar sls files to their minions.

 

/srv/pillar/top.sls:

base:
  'minion_1':
    - key1
  'minion_2':
    - key2

/srv/pillar/key1.sls:

key1: value1

/srv/pillar/key2.sls:

key2: value2

 

2. Jinja conditional using if/else with minion id.

 

In this case, top file need to know nothing.

Instead, pillar sls files know themselves which minion can read them.

 

/srv/pillar/top.sls:

base:
  '*':
    - key1
    - key2

/srv/pillar/key1.sls:

{% if grains['id'] == 'minion_1' %}
key1: value1
{% endif %}

/srv/pillar/key2.sls:

{% if grains['id'] == 'minion_2' %}
key2: value2
{% endif %}

 

Question

 

Are there any security preferences using the 1st or the 2nd approach?

 

Personally, I prefer the 2nd approach - it is more flexible (allows any logic in jinja templates). In the 1st approach, there is a problem - top-files are not templates and cannot be parameterized.

 

While writing this I also clarified an important Salt design aspect - pillar sls files are only compiled on Salt master in either cases (see this answer). Therefore, in both cases minions will never be given all pillar data anyway (to filter, select, and present resulted pillar for state rendering on their own). Compare it with states - AFAIK, they are rendered on minon side.

 

Christopher Baklid

unread,
Jul 23, 2016, 3:00:16 PM7/23/16
to Salt-users
This is interesting, and I don't see a security problem for either approach to be honest, I think this is more a question of remembering where you set your access to pillar data.

So, I had a little fun with the top file and did this:

/srv/pillar/top.sls


{% set server = salt['grains.get']('id').lower() %}
base:
 
'id:{{ server }}':
   
- match: grain
   
- {{ server }}


now if you name your pillar file the same as the minion id in lowercase, it'll access that minions pillar file

so if your minion is called "MyMinion01" you name your pillar file "/srv/pillar/myminion01.sls" then it renders the pillar file for that specific minion

I have no idea what kind of security concerns this could bring about though!

I hope someone has a more valid answer for your question

Steve Hajducko

unread,
Jul 23, 2016, 4:12:50 PM7/23/16
to Salt-users
The concern about targeting pillar off of grains is that it's insecure, as grains are controlled on the minion side. So a compromised minion could change its grains in order to get access to different pillar values, and if those pillars have sensitive information, then they'd get that.

You can also write your own master tops module or use external pillars that generally work more on a per minion id basis.

--
You received this message because you are subscribed to the Google Groups "Salt-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to salt-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alexey Pakseykin

unread,
Jul 24, 2016, 1:11:39 AM7/24/16
to Salt-users
Steve,

You are right about targeting minions using grains being insecure except minion `id` grain.
Minion id cannot be changed without re-accepting its public key on the Master.
So, grain `id` can be perfectly used securely.

Christopher,

This looks like a good trick which adds dedicated pillar data to any minion regardless of their number without top file modification.

Florian Ermisch

unread,
Jul 24, 2016, 4:02:29 AM7/24/16
to salt-...@googlegroups.com
Hi all,

AFAIK `grains[id]` is just a grain and to get the id the minion
was accepted under one should use `opts.id`.

To set minion specific pillar values I use this in my topfiles:
```
base:
'*':
- hosts.{{ opts.id }}
[…]
```

As all our minions have their nodename set as their id
I have no need to add `.lower ()` or something anyway.
I used the FQDN as id in the beginning which turned out
to be quite cumbersome. It also required more jinja to
handle those minion-specific includes.

Regards, Florian

Am 24. Juli 2016 07:11:38 MESZ, schrieb Alexey Pakseykin <uvs...@gmail.com>:
> Steve,
>
> You are right about targeting minions using grains being insecure
> *except* minion
> `id` grain.
> Minion id cannot be changed without re-accepting its public key on the
>
> Master.
> So, grain `id` can be perfectly used securely.
>
> Christopher,
>
> This looks like a good trick which adds dedicated pillar data to any
> minion
> regardless of their number without top file modification.
>
> On Sunday, July 24, 2016 at 4:12:50 AM UTC+8, Steve Hajducko wrote:
> >
> > The concern about targeting pillar off of grains is that it's
> insecure, as
> > grains are controlled on the minion side. So a compromised minion
> could
> > change its grains in order to get access to different pillar values,
> and if
> > those pillars have sensitive information, then they'd get that.
> >
> > You can also write your own master tops module or use external
> pillars
> > that generally work more on a per minion id basis.
> >
> > On Sat, Jul 23, 2016 at 12:00 PM Christopher Baklid
> <cba...@gmail.com
> >>> */srv/pillar/top.sls:*
> >>>
> >>> base:
> >>> 'minion_1':
> >>> - key1
> >>> 'minion_2':
> >>> - key2
> >>>
> >>> */srv/pillar/key1.sls:*
> >>>
> >>> key1: value1
> >>>
> >>> */srv/pillar/key2.sls:*
> >>>
> >>> key2: value2
> >>>
> >>>
> >>>
> >>> 2. Jinja conditional using if/else with minion id.
> >>>
> >>>
> >>>
> >>> In this case, top file need to know nothing.
> >>>
> >>> Instead, pillar sls files know themselves which minion can read
> them.
> >>>
> >>>
> >>>
> >>> */srv/pillar/top.sls:*
> >>>
> >>> base:
> >>> '*':
> >>> - key1
> >>> - key2
> >>>
> >>> */srv/pillar/key1.sls:*
> >>>
> >>> {% if grains['id'] == 'minion_1' %}
> >>> key1: value1
> >>> {% endif %}
> >>>
> >>> */srv/pillar/key2.sls:*
> >>>
> >>> {% if grains['id'] == 'minion_2' %}
> >>> key2: value2
> >>> {% endif %}
> >>>
> >>>
> >>>
> >>> Question
> >>>
> >>>
> >>>
> >>> *Are there any security preferences using the 1st or the 2nd
> approach?*
> >>>
> >>>
> >>>
> >>> Personally, I prefer the 2nd approach - it is more flexible
> (allows any
> >>> logic in jinja templates). In the 1st approach, there is a problem
> -
> >>> top-files are not templates and cannot be parameterized.
> >>>
> >>>
> >>>
> >>> While writing this I also clarified an important Salt design
> aspect -
> >>> pillar sls files are only compiled on Salt master in either cases
> (see this
> >>> answer <http://stackoverflow.com/a/23018714/441652>). Therefore,
> in
> >>> both cases minions will never be given all pillar data anyway (to
> filter,
> >>> select, and present resulted pillar for state rendering on their
> own).
> >>> Compare it with states - AFAIK, they are rendered on minon side.
> >>>
> >>>
> >>>
> >> --
> >> You received this message because you are subscribed to the Google
> Groups
> >> "Salt-users" group.
> >> To unsubscribe from this group and stop receiving emails from it,
> send an
> >> email to salt-users+...@googlegroups.com <javascript:>.

Seth House

unread,
Jul 25, 2016, 1:03:34 PM7/25/16
to salt users list
Also take a look at `match.filter_by` for the 'Option 2' workflow.
It's a nice way to avoid multiple if-statements when you're working
within a single file.

https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.match.html#salt.modules.match.filter_by

E.g., the example in OP might look like this:

# /srv/pillar/key1_or_2.sls:

{% set values = salt['match.filter_by']({
'minion_1': {
'key1: 'value1',
},
'minion_2': {
'key2: 'value2',
},
}) %}

# Make the result available to YAML:
values: {{ values | yaml(true) }}
> To unsubscribe from this group and stop receiving emails from it, send an email to salt-users+...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages