Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow extra manually added pull secrets to managed SA #418

Merged
merged 11 commits into from
Sep 25, 2023
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
Loading