-
Notifications
You must be signed in to change notification settings - Fork 169
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
added exempted user to guardrails #3319
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,8 +7,10 @@ import ( | |
"context" | ||
"embed" | ||
"strings" | ||
"time" | ||
|
||
configv1 "github.com/openshift/api/config/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
|
||
arov1alpha1 "github.com/Azure/ARO-RP/pkg/operator/apis/aro.openshift.io/v1alpha1" | ||
|
@@ -147,3 +149,42 @@ func (r *Reconciler) VersionLT411(ctx context.Context) (bool, error) { | |
ver411, _ := version.ParseVersion("4.11.0") | ||
return clusterVersion.Lt(ver411), nil | ||
} | ||
|
||
func (r *Reconciler) getGatekeeperDeployedNs(ctx context.Context, instance *arov1alpha1.Cluster) (string, error) { | ||
name := "" | ||
if r.kubernetescli == nil { | ||
r.log.Debug("nil kubernetescli object") | ||
return "", nil | ||
} | ||
start := time.Now() | ||
namespaces, err := r.kubernetescli.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) | ||
if err != nil { | ||
r.log.Warnf("Error retrieving namespaces: %v", err) | ||
return "", err | ||
} | ||
guardrails_namespace := instance.Spec.OperatorFlags.GetWithDefault(controllerNamespace, defaultNamespace) | ||
for _, ns := range namespaces.Items { | ||
if ns.Name == guardrails_namespace { | ||
// skip guardrails ns | ||
continue | ||
} | ||
deployments, err := r.kubernetescli.AppsV1().Deployments(ns.Name).List(ctx, metav1.ListOptions{ | ||
LabelSelector: "gatekeeper.sh/system=yes", | ||
}) | ||
Comment on lines
+171
to
+173
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be good to have a try here as well |
||
if err != nil { | ||
r.log.Warnf("Error retrieving deployments in namespace %s: %v", ns.Name, err) | ||
continue | ||
} | ||
if len(deployments.Items) > 0 { | ||
name = ns.Name | ||
break | ||
} | ||
} | ||
dura := time.Since(start) | ||
msg := "Gatekeeper not found" | ||
if name != "" { | ||
msg = "Found another gatekeeper deployed in namespace " + name | ||
} | ||
r.log.Infof("%s, search took %s.", msg, dura.String()) | ||
return name, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ import ( | |
"github.com/sirupsen/logrus" | ||
"k8s.io/apimachinery/pkg/types" | ||
"k8s.io/apimachinery/pkg/util/wait" | ||
"k8s.io/client-go/kubernetes" | ||
ctrl "sigs.k8s.io/controller-runtime" | ||
"sigs.k8s.io/controller-runtime/pkg/builder" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
|
@@ -36,9 +37,11 @@ type Reconciler struct { | |
namespace string | ||
policyTickerDone chan bool | ||
reconciliationMinutes int | ||
cleanupNeeded bool | ||
kubernetescli kubernetes.Interface | ||
} | ||
|
||
func NewReconciler(log *logrus.Entry, client client.Client, dh dynamichelper.Interface) *Reconciler { | ||
func NewReconciler(log *logrus.Entry, client client.Client, dh dynamichelper.Interface, k8scli kubernetes.Interface) *Reconciler { | ||
return &Reconciler{ | ||
log: log, | ||
|
||
|
@@ -50,6 +53,8 @@ func NewReconciler(log *logrus.Entry, client client.Client, dh dynamichelper.Int | |
|
||
readinessPollTime: 10 * time.Second, | ||
readinessTimeout: 5 * time.Minute, | ||
cleanupNeeded: false, | ||
kubernetescli: k8scli, | ||
} | ||
} | ||
|
||
|
@@ -74,9 +79,8 @@ func (r *Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl. | |
// If enabled and managed=false, remove the GuardRails deployment | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there's no need to comment how the code block works. The codes already explains what it does. |
||
// If enabled and managed is missing, do nothing | ||
if strings.EqualFold(managed, "true") { | ||
// Check if standard GateKeeper is already running | ||
if running, err := r.deployer.IsReady(ctx, "gatekeeper-system", "gatekeeper-audit"); err != nil && running { | ||
r.log.Warn("standard GateKeeper is running, skipping Guardrails deployment") | ||
if ns, err := r.getGatekeeperDeployedNs(ctx, instance); err == nil && ns != "" { | ||
r.log.Warnf("Found another GateKeeper deployed in ns %s, aborting Guardrails", ns) | ||
return reconcile.Result{}, nil | ||
} | ||
|
||
|
@@ -97,6 +101,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl. | |
if err != nil { | ||
return reconcile.Result{}, fmt.Errorf("GateKeeper deployment timed out on Ready: %w", err) | ||
} | ||
r.cleanupNeeded = true | ||
policyConfig := &config.GuardRailsPolicyConfig{} | ||
if r.gkPolicyTemplate != nil { | ||
// Deploy the GateKeeper ConstraintTemplate | ||
|
@@ -122,24 +127,38 @@ func (r *Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl. | |
// start a ticker to re-enforce gatekeeper policies periodically | ||
r.startTicker(ctx, instance) | ||
} else if strings.EqualFold(managed, "false") { | ||
if !r.cleanupNeeded { | ||
if ns, err := r.getGatekeeperDeployedNs(ctx, instance); err == nil && ns != "" { | ||
// resources were *not* created by guardrails, plus another gatekeeper deployed | ||
// | ||
// guardrails didn't get deployed most likely due to another gatekeeper is deployed by customer | ||
// this is to avoid the accidental deletion of gatekeeper CRDs that were deployed by customer | ||
// the unnamespaced gatekeeper CRDs were possibly created by a customised gatekeeper, hence cannot ramdomly delete them. | ||
r.log.Warn("Skipping cleanup as it is not safe and may destroy customer's gatekeeper resources") | ||
return reconcile.Result{}, nil | ||
} | ||
} | ||
Comment on lines
+130
to
+140
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can combine the if statement into 1 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tried that, but end up making code either less readable or have to invoke the cumbersome r.getGatekeeperDeployedNs() unnecessarily |
||
|
||
if r.gkPolicyTemplate != nil { | ||
// stop the gatekeeper policies re-enforce ticker | ||
r.stopTicker() | ||
|
||
err = r.removePolicy(ctx, gkPolicyConstraints, gkConstraintsPath) | ||
if err != nil { | ||
return reconcile.Result{}, err | ||
r.log.Warnf("failed to remove Constraints with error %s", err.Error()) | ||
} | ||
|
||
err = r.gkPolicyTemplate.Remove(ctx, config.GuardRailsPolicyConfig{}) | ||
if err != nil { | ||
return reconcile.Result{}, err | ||
r.log.Warnf("failed to remove ConstraintTemplates with error %s", err.Error()) | ||
} | ||
} | ||
err = r.deployer.Remove(ctx, config.GuardRailsDeploymentConfig{Namespace: r.namespace}) | ||
if err != nil { | ||
r.log.Warnf("failed to remove deployer with error %s", err.Error()) | ||
return reconcile.Result{}, err | ||
} | ||
r.cleanupNeeded = false | ||
} | ||
|
||
return reconcile.Result{}, nil | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want a retry here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for looking into this, didn't do that as 1) retry makes code a bit less readable, 2) in case of a failure the reconcile process will be retried.