Skip to content

Commit

Permalink
Allow extra manually added pull secrets to managed SA (#418)
Browse files Browse the repository at this point in the history
* feat: add annotation on SA to keep track of pull secrets

Add an annotation to keep track of managed pullsecrets on the created service account

* feat: use actual pull secret comparision instead of annotations

* feat: tidy current e2e tests and add cleanups

* fix: add banner

* feat: add e2e service account tests

* fix: yq syntax fix

* fix: yq eval environment variable

* fix: e2e scripts base_dir reference

* Revert "fix: e2e scripts base_dir reference"

This reverts commit e070403.

* fix: copy missing tests folder into e2e container

* feat: bump rok8s to @13 and ci-images to v13
  • Loading branch information
eryalito committed Sep 25, 2023
1 parent 5944588 commit da61a87
Show file tree
Hide file tree
Showing 15 changed files with 300 additions and 46 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: 2.1

orbs:
rok8s: fairwinds/rok8s-scripts@11
rok8s: fairwinds/rok8s-scripts@13
oss-docs: fairwinds/oss-docs@0

references:
Expand All @@ -18,7 +18,7 @@ references:
e2e_configuration: &e2e_configuration
pre_script: e2e/pre.sh
script: e2e/test.sh
command_runner_image: quay.io/reactiveops/ci-images:v12-buster
command_runner_image: quay.io/reactiveops/ci-images:v13-buster
enable_docker_layer_caching: true
attach-workspace: true
requires:
Expand Down
8 changes: 5 additions & 3 deletions e2e/pre.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -e

wget -O /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/download/2.4.0/yq_linux_amd64"
wget -O /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/download/v4.35.1/yq_linux_amd64"
chmod +x /usr/local/bin/yq

if [ -z "$CI_SHA1" ]; then
Expand All @@ -26,8 +26,10 @@ echo "** END LOADING IMAGE **"
echo "********************************************************************"
printf "\n\n"

yq w -i deploy/3_deployment.yaml 'spec.template.spec.containers[0].image' "quay.io/reactiveops/rbac-manager:${CI_SHA1}-amd64"
yq w -i deploy/3_deployment.yaml 'spec.template.spec.containers[0].imagePullPolicy' "IfNotPresent"
export newImage=quay.io/reactiveops/rbac-manager:${CI_SHA1}-amd64
yq -i '.spec.template.spec.containers[0].image = env(newImage)' deploy/3_deployment.yaml
yq -i '.spec.template.spec.containers[0].imagePullPolicy = "IfNotPresent"' deploy/3_deployment.yaml
cat deploy/3_deployment.yaml

docker cp deploy e2e-command-runner:/
docker cp e2e/rbacdefinition e2e-command-runner:/
2 changes: 2 additions & 0 deletions e2e/rbacdefinition/cluterrolebindings/cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
kubectl delete clusterrole test-rbac-manager --ignore-not-found
kubectl delete RBACDefinition rbac-manager-definition --ignore-not-found
21 changes: 21 additions & 0 deletions e2e/rbacdefinition/cluterrolebindings/main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
BASE_DIR=$(dirname $BASH_SOURCE)

printf "\n\n"
echo "********************************************************************"
echo "** Test clusterrolebindings **"
echo "********************************************************************"
printf "\n\n"

# Execute the setup, then execute the tests just if the setup contains no errors.
# Finally always execute the cleanup and return the whole error of the steps
error=$((0))
bash "$BASE_DIR/setup.sh"
error=$(( error | $? ))

if [ $error -eq 0 ]; then
bash "$BASE_DIR/tests.sh"
error=$(( error | $? ))
fi

bash "$BASE_DIR/cleanup.sh"
exit $(( error | $? ))
16 changes: 16 additions & 0 deletions e2e/rbacdefinition/cluterrolebindings/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
kubectl create clusterrole test-rbac-manager --verb="create" --resource=deployment

cat <<EOF | kubectl create -f -
apiVersion: rbacmanager.reactiveops.io/v1beta1
kind: RBACDefinition
metadata:
name: rbac-manager-definition
rbacBindings:
- name: admins
subjects:
- kind: ServiceAccount
name: test-rbac-manager
namespace: rbac-manager
clusterRoleBindings:
- clusterRole: test-rbac-manager
EOF
10 changes: 10 additions & 0 deletions e2e/rbacdefinition/cluterrolebindings/tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# wait up to 2 minutes for rbac-manager to create the binding
counter=0
until kubectl get clusterrolebinding/rbac-manager-definition-admins-test-rbac-manager; do
let "counter=counter+1"
sleep 10
if [ $counter -gt 11 ]; then
break
fi
done
kubectl auth can-i create deployments --as=system:serviceaccount:rbac-manager:test-rbac-manager
18 changes: 18 additions & 0 deletions e2e/rbacdefinition/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
BASE_DIR=$(dirname $BASH_SOURCE)

printf "\n\n"
echo "********************************************************************"
echo "** Test rbacDefinition **"
echo "********************************************************************"
printf "\n\n"


bash "$BASE_DIR/cluterrolebindings/main.sh"
if [ $? -ne 0 ]; then
exit 1
fi

bash "$BASE_DIR/serviceaccounts/main.sh"
if [ $? -ne 0 ]; then
exit 1
fi
2 changes: 2 additions & 0 deletions e2e/rbacdefinition/serviceaccounts/cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
kubectl delete clusterrole test-rbac-manager --ignore-not-found
kubectl delete RBACDefinition rbac-manager-definition-1 --ignore-not-found
21 changes: 21 additions & 0 deletions e2e/rbacdefinition/serviceaccounts/main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
BASE_DIR=$(dirname $BASH_SOURCE)

printf "\n\n"
echo "********************************************************************"
echo "** Test serviceaccounts **"
echo "********************************************************************"
printf "\n\n"

# Execute the setup, then execute the tests just if the setup contains no errors.
# Finally always execute the cleanup and return the whole error of the steps
error=$((0))
bash "$BASE_DIR/setup.sh"
error=$(( error | $? ))

if [ $error -eq 0 ]; then
bash "$BASE_DIR/tests.sh"
error=$(( error | $? ))
fi

bash "$BASE_DIR/cleanup.sh"
exit $(( error | $? ))
18 changes: 18 additions & 0 deletions e2e/rbacdefinition/serviceaccounts/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
kubectl create clusterrole test-rbac-manager --verb="create" --resource=deployment

cat <<EOF | kubectl create -f -
apiVersion: rbacmanager.reactiveops.io/v1beta1
kind: RBACDefinition
metadata:
name: rbac-manager-definition-1
rbacBindings:
- name: admins
subjects:
- kind: ServiceAccount
name: test-rbac-manager
namespace: rbac-manager
imagePullSecrets:
- robot-secret
clusterRoleBindings:
- clusterRole: test-rbac-manager
EOF
68 changes: 68 additions & 0 deletions e2e/rbacdefinition/serviceaccounts/tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# wait up to 2 minutes for rbac-manager to create the binding
counter=0
error=$((0))
until kubectl get -n rbac-manager serviceaccount/test-rbac-manager; do
let "counter=counter+1"
sleep 10
if [ $counter -gt 11 ]; then
break
fi
done

kubectl get -n rbac-manager serviceaccount/test-rbac-manager
error=$(( error | $? ))
if [ "$error" -eq 1 ]; then
>&2 echo "error: The Service account must exists"
fi
kubectl delete -n rbac-manager serviceaccount/test-rbac-manager
kubectl get -n rbac-manager serviceaccount/test-rbac-manager
error=$(( error | $? ))
if [ "$error" -eq 1 ]; then
>&2 echo "error: The Service account must be recreated"
fi

# ImagePullSecret is created
contents=$(kubectl get -n rbac-manager serviceaccount/test-rbac-manager -oyaml | yq 'select(.imagePullSecrets[] | .name == "robot-secret")')
if [ -z "$contents" ]; then
error=$(( error | 1 ))
fi
if [ "$error" -eq 1 ]; then
>&2 echo "error: ImagePullSecret \"robot-secret\" must exists"
fi

# ImagePullSecret is re-created if deleted
cat <<EOF | kubectl patch -n rbac-manager serviceaccount/test-rbac-manager --type=merge -p "$(cat -)"
{
"imagePullSecrets": []
}
EOF
contents=$(kubectl get -n rbac-manager serviceaccount/test-rbac-manager -oyaml | yq 'select(.imagePullSecrets[] | .name == "robot-secret")')
if [ -z "$contents" ]; then
error=$(( error | 1 ))
fi
if [ "$error" -eq 1 ]; then
>&2 echo "error: ImagePullSecret \"robot-secret\" must be re-created"
fi

# If ImagePullSecret is added it should not be removed

cat <<EOF | kubectl patch -n rbac-manager serviceaccount/test-rbac-manager --type=json -p "$(cat -)"
[
{
"op": "add",
"path": "/imagePullSecrets/-",
"value": {
"name": "new-secret-name"
}
}
]
EOF
contents=$(kubectl get -n rbac-manager serviceaccount/test-rbac-manager -oyaml | yq 'select(.imagePullSecrets[] | .name == "new-secret-name")')
if [ -z "$contents" ]; then
error=$(( error | 1 ))
fi
if [ "$error" -eq 1 ]; then
>&2 echo "error: ImagePullSecret \"new-secret-name\" must be kept"
fi

exit $error
39 changes: 5 additions & 34 deletions e2e/test.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash


BASE_DIR=$(dirname $BASH_SOURCE)

printf "\n\n"
echo "**************************"
Expand All @@ -20,36 +20,7 @@ printf "\n\n"
kubectl apply -f deploy/
kubectl -n rbac-manager wait deployment/rbac-manager --timeout=120s --for condition=available


printf "\n\n"
echo "********************************************************************"
echo "** Test rbacDefinition **"
echo "********************************************************************"
printf "\n\n"
kubectl create clusterrole test-rbac-manager --verb="create" --resource=deployment

cat <<EOF | kubectl create -f -
apiVersion: rbacmanager.reactiveops.io/v1beta1
kind: RBACDefinition
metadata:
name: rbac-manager-definition
rbacBindings:
- name: admins
subjects:
- kind: ServiceAccount
name: test-rbac-manager
namespace: rbac-manager
clusterRoleBindings:
- clusterRole: test-rbac-manager
EOF

# wait up to 2 minutes for rbac-manager to create the binding
counter=0
until kubectl get clusterrolebinding/rbac-manager-definition-admins-test-rbac-manager; do
let "counter=counter+1"
sleep 10
if [ $counter -gt 11 ]; then
break
fi
done
kubectl auth can-i create deployments --as=system:serviceaccount:rbac-manager:test-rbac-manager
bash "$BASE_DIR/rbacdefinition/run.sh"
if [ $? -ne 0 ]; then
exit 1
fi
35 changes: 28 additions & 7 deletions pkg/reconciler/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
package reconciler

import (
"reflect"

v1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -53,13 +51,36 @@ func rbMatches(existingRB *rbacv1.RoleBinding, requestedRB *rbacv1.RoleBinding)
}

func saMatches(existingSA *v1.ServiceAccount, requestedSA *v1.ServiceAccount) bool {
if metaMatches(&existingSA.ObjectMeta, &requestedSA.ObjectMeta) {
if len(requestedSA.ImagePullSecrets) < 1 && existingSA.ImagePullSecrets == nil {
return true
if !metaMatches(&existingSA.ObjectMeta, &requestedSA.ObjectMeta) {
return false
}
requestedSAManagedPullSecretsAnnotation, exists := requestedSA.Annotations[ManagedPullSecretsAnnotationKey]
if !exists {
return false
}

existingSAManagedPullSecretsAnnotation, exists := existingSA.Annotations[ManagedPullSecretsAnnotationKey]
if !exists {
return false
}

if requestedSAManagedPullSecretsAnnotation != existingSAManagedPullSecretsAnnotation {
return false
}

for _, requestedSAImagePullSecrets := range requestedSA.ImagePullSecrets {
matches := false
for _, existingSAPullSecret := range existingSA.ImagePullSecrets {
if requestedSAImagePullSecrets.Name == existingSAPullSecret.Name {
matches = true
}
}
if !matches {
return false
}
return reflect.DeepEqual(&existingSA.ImagePullSecrets, &requestedSA.ImagePullSecrets)
}
return false

return true
}

func metaMatches(existingMeta *metav1.ObjectMeta, requestedMeta *metav1.ObjectMeta) bool {
Expand Down

0 comments on commit da61a87

Please sign in to comment.