-
Notifications
You must be signed in to change notification settings - Fork 36
Operator overrides of role capabilities
Some public cloud system require some pods to have more privileges than they are given by default through the role manifest and helm chart generated for it.
This document specifies a number of changes to the generated helm charts which will allow operators to perform scriptable extensions of the default privileges as needed.
The basics of the change are to provide operators with new keys in the values.yaml
they can edit. In their default state the chart will simply use the security context generated from the manifest (SCM). When edited the chart will use the SCM and merge the operator information into it.
-
values.yaml
is extended with keys of the formsizing.<rolename>.capabilities
. The key is of type list, taking the operator-defined set of capabilities, orALL
. The default is the empty list ([]
). Notnil
. The list functionhas
crashes on anil
-haystack. To usedefault
we ned something to generate an empty list. The list functionlist
generatesnil
when called without arguments, not an empty list. It is not possible to use[]
indefault
, i.e.default .foo []
is a syntax error. -
When capabilities are added to the key for a role they are merged by the role's template into its SCM. The exact rules are dependent on the form of the SCM, of which there are three, called
privileged
,nil
, andcap-list
. The list below will show these forms in the named order, and the new forms to be generated by the modified fissile for them to accomplish the merge.
-
Original SCM is
privileged
, i.e.- securityContext: privileged: true
- In this case no merging is necessary, because that role is already at the highest possible privilege.
- Fissile will keep emitting the original SCM.
-
Original SCM is
nil
, i.e.- securityContext: ~
- Any capabilities added can be taken as-is, mostly. The only special case case is the capability
ALL
, which has to be translated toprivileged
when present, regardless of any other. - Fissile is changed to emit
- securityContext: {{ if has "ALL" .Values.sizing.<role>.capabilities -}} privileged: true {{- end }} {{ if not (has "ALL" .Values.sizing.<role>.capabilities) -}} capabilities: add: {{ .Values.sizing.<role>.capabilities }} {{- end }}
- Any capabilities added can be taken as-is, mostly. The only special case case is the capability
-
Original SCM is
cap-list
, i.e:- securityContext: capabilities: add: - <<role manifest cap 1>>
- Presence of the capability
ALL
is done like fornil
, see above. - There is no need to check if the manifest capabilities contain
ALL
. This is case 2 above. - The merging of the user's capability list is done via a
range
iteration. Note, this may cause duplicate capabilities in the output. These duplicates however do not matter, and while it is possible to concatenate two lists the code for that is very convoluted and non-obvious. See later section. - Fissile is changed to emit
- securityContext: {{ if has "ALL" .Values.sizing.<role>.capabilities -}} privileged: true {{- end }} {{ if not (has "ALL" .Values.sizing.<role>.capabilities) -}} capabilities: add: - <<role manifest cap 1>> (...) {{- range .Values.sizing.<role>.capabilities }} - {{ . }} {{- end }} {{- end }}
- Presence of the capability
Notes:
- As specified the operator-provided capabilities in the
values.yaml
have to be all uppercase. The templates will not accept mixed-case, nor lower-case. This is different from the manifest where capabilities can be specified in any case, with fissile converting to the all-uppercase form.
The code to concatenate two lists, to allow feeding through uniq
is
{{ $myList := list "11" "12" "31" "14" "15" }}
{{ $myList2 := list "12" "22" "23" "24" "25" }}
{{ $concated := (( list ($myList | join ":") ($myList2 | join ":") ) | join ":") | splitList ":" }}
{{ $mys := printf "%+v" ( uniq ((dict "values" $concated) | toJson | fromJson ).values ) }}
{{ fail $mys }}
The two lists are joined into two strings, placed into a list, joined into string. The resulting single string is flat, and can be split back into one list. This song and dance is all necessary because sprig does not have a plain list concat function.