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

Feature/admission controller #226

Merged
merged 37 commits into from
Jul 16, 2024
Merged

Conversation

amitschendel
Copy link
Contributor

@amitschendel amitschendel commented Jun 18, 2024

Overview

This PR fixes #

Signed Commits

  • Yes, I signed my commits.

Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Copy link

Summary:

  • License scan: failure
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
@amitschendel amitschendel marked this pull request as ready for review June 19, 2024 08:29
Copy link

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

Copy link
Contributor

@matthyx matthyx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting... some clarifications needed, but overall good
did you follow any example for the admission controller that you could document?

admissionController := webhook.New(addr, "/etc/certs/tls.crt", "/etc/certs/tls.key", runtime.NewScheme(), webhook.NewAdmissionValidator(k8sApi, exporter))
// Start HTTP REST server for webhook
waitGroup.Add(1)
go func() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that @kooomix used https://pkg.go.dev/golang.org/x/sync/errgroup#Group.Go in the backend and I found it super elegant... consider it here maybe?

main.go Outdated
@@ -136,6 +142,36 @@ func main() {
}(mainHandler)
}

if operatorConfig.AdmissionControllerEnabled() {
// Handle SIGINT and SIGTERM by cancelling the root context
admissionContext, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can move this outside of the flag? why only SIGINT with admission controller?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return
}

// discard the body
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still not convinced this is needed... do you have some pointers (I know we do it in different places, just curious)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to do it anyway to avoid potential leaks.

admission/webhook/server.go Show resolved Hide resolved
return true
}

func (av *AdmissionValidator) validateAdminRoleBinding(attrs admission.Attributes) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think at some point these will reside as separate rules, such as in node-agent?

Copy link
Contributor Author

@amitschendel amitschendel Jun 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe at some point but not now.

Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Copy link

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Copy link

@dwertent dwertent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some comments.

Here are my overall comments:

  1. What are the 'rules'? Why are they not defined as rules, but rather as "if" statements in a large function?
  2. How can the user interact with this system?
  3. This code is missing unit tests.
  4. Some conditions, such as capabilities, are hard-coded. Consider implementing a more flexible solution.

I don't know the full context, but if this is just a POC, I don't see a reason to merge it into the main branch. You should continue working on it, and once it is more complete (at least the basics), we can consider merging it into the main branch.

main.go Outdated
}()

cancellationReason := admissionController.Run(serverContext)
logger.L().Ctx(ctx).Error("server stopped", helpers.Error(cancellationReason))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logger.L().Ctx(ctx).Error("server stopped", helpers.Error(cancellationReason))
logger.L().Ctx(ctx).Fatal("server stopped", helpers.Error(cancellationReason))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

main.go Outdated
waitGroup.Done()
}()

cancellationReason := admissionController.Run(serverContext)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cancellationReason := admissionController.Run(serverContext)
err := admissionController.Run(serverContext)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

main.go Outdated
admissionContext, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()

waitGroup := sync.WaitGroup{}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should "kill" the main process if there is an issue initializing the admission controller.
This being said, I don't think we need here a waiting group.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed it but I think it's good to have for scaling.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean by the "scaling", what is the scenario?

}
// create the HTTPAlertsList struct
httpAlertsList := HTTPAlertsList{
Kind: "RuntimeAlerts",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this runtimeAlerts? I dont think so.
I believe this should have a different kind so it can be treated as admission controller alerts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a RuntimeAlert the admission kind is passed in other place.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same kind of alert as coming from the node-agent, in other words, we will not know "down the line" the source of the alert. And I think we will want to know...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

func (exporter *HTTPExporter) SendAdmissionAlert(admissionAttrs *admission.Attributes, ruleID string, RuleDescription string) {
isLimitReached := exporter.checkAlertLimit()
if isLimitReached {
exporter.sendAlertLimitReached()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sends an alert every time the limit is reached. Instead of sending multiple alerts for each instance that reaches the limit, we should send a single alert indicating that the limit has been reached. This can be managed by wrapping the alert logic in a boolean condition to ensure the 'limit reached' alert is sent only once.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

func (av *AdmissionValidator) validatePods(attrs admission.Attributes) error {
var errs error

// Check if the request is for pod exec or attach.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not "pod validation". You should have a different function for this

errs = errors.Join(errs, admission.NewForbidden(attrs, fmt.Errorf("exec to pod is audited")))
}

if attrs.GetSubresource() == "attach" {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, not pod validation

admission/webhook/validator.go Outdated Show resolved Hide resolved
}

// Check if the request is for port-forwarding.
if attrs.GetSubresource() == "portforward" {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, not pod validation

admission/webhook/validator.go Outdated Show resolved Hide resolved
Copy link

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

@amitschendel
Copy link
Contributor Author

amitschendel commented Jun 19, 2024

@dwertent

  1. What are the 'rules'? Why are they not defined as rules, but rather as "if" statements in a large function?

Do you think we should use the rules packages from the node-agent?

  1. How can the user interact with this system?

Which kind of interaction do you expect? rule bindings?

Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Copy link

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Copy link

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

@dwertent
Copy link

dwertent commented Jun 20, 2024

@amitschendel

Do you think we should use the rules packages from the node-agent?

Not really, because here this is a different set of rules, but I will expect to see a similar code structure, there are different restrictions so I don't think there is a need for a Factory design pattern, but I think there should be a package with rules etc.
Consider using the same rule IDs as the regolibrary, meaning the isPrivileged should have the same control ID as we have with compliance scanning. This should be considered, I'm not sure we want it.

Which kind of interaction do you expect? rule bindings?

Possibly. What were the requirements and design for the admission controller?

Also, as I wrote, I'm unfamiliar with the big picture, but I believe we will add rules and possibly block user actions. I don't see how all this can "fit" in the current code structure without the need of refactoring it all in the future, so I will recommend writing the admission controller infrastructure in a way that future modifications and requirements could be met without refactoring. This being said, if the scope here is a POC and not actual product development, I don't see a need to merge it into the main branch.

@dwertent dwertent marked this pull request as draft June 20, 2024 08:56
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
@amitschendel amitschendel marked this pull request as ready for review July 2, 2024 14:11
Copy link

github-actions bot commented Jul 2, 2024

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Copy link

github-actions bot commented Jul 4, 2024

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Copy link
Contributor

@matthyx matthyx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. fix the conflicts with go.mod
  2. remove github.com/zeebo/assert and use testify instead (as everywhere)
  3. improve some of the test coverage (for example the cache)
  4. I wonder if we should have a component test or something testing the full functionality of the webhook (outside of the system tests that you will add)

"github.com/stretchr/testify/assert"
)

func TestNewCache(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol, maybe we could add useful tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestResourcesToWatch(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, maybe use real data?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

import (
"testing"

"github.com/zeebo/assert"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we're not using testify?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Copy link

gitguardian bot commented Jul 14, 2024

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
13049693 Triggered Generic Private Key 7c7c360 admission/webhook/testdata/key.pem View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Copy link

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

matthyx
matthyx previously approved these changes Jul 15, 2024
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
Copy link

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

@amitschendel amitschendel added the release Create release label Jul 16, 2024
Signed-off-by: Amit Schendel <amitschendel@gmail.com>
@amitschendel amitschendel merged commit 0ae2750 into main Jul 16, 2024
5 of 7 checks passed
@amitschendel amitschendel deleted the feature/admission-controller branch July 16, 2024 09:27
Copy link

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: success
  • Unit test: success
  • Go linting: failure

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release Create release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants