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

chore: Authenticating api server against webhook #2359

Merged
merged 5 commits into from
Nov 1, 2022

Conversation

JaydipGabani
Copy link
Contributor

@JaydipGabani JaydipGabani commented Oct 25, 2022

Signed-off-by: Jaydip Gabani gabanijaydip@gmail.com

What this PR does / why we need it:
To authenticate incoming requests from api-server to webhook

Which issue(s) this PR fixes (optional, using fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when the PR gets merged):
Fixes #1294

Special notes for your reviewer:

@codecov-commenter
Copy link

codecov-commenter commented Oct 25, 2022

Codecov Report

Base: 53.58% // Head: 53.44% // Decreases project coverage by -0.14% ⚠️

Coverage data is based on head (109db1f) compared to base (4ec4f34).
Patch coverage: 0.00% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2359      +/-   ##
==========================================
- Coverage   53.58%   53.44%   -0.15%     
==========================================
  Files         117      117              
  Lines       10229    10230       +1     
==========================================
- Hits         5481     5467      -14     
- Misses       4331     4343      +12     
- Partials      417      420       +3     
Flag Coverage Δ
unittests 53.44% <0.00%> (-0.15%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
pkg/webhook/common.go 59.32% <0.00%> (-7.99%) ⬇️
pkg/webhook/mutation.go 25.51% <0.00%> (+0.34%) ⬆️
pkg/webhook/namespacelabel.go 70.00% <0.00%> (+3.33%) ⬆️
pkg/webhook/policy.go 40.50% <0.00%> (+0.18%) ⬆️
...onstrainttemplate/constrainttemplate_controller.go 55.50% <0.00%> (-3.35%) ⬇️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

Copy link
Contributor

@maxsmythe maxsmythe left a comment

Choose a reason for hiding this comment

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

Thank you for the PR! I'm glad to have the ground work for verifying the K8s API server.

One thought around decoupling this from disabling cert rotation.


To have requests coming from apiserver authenticated by webhook, following configuration can be made:

1. Deploy gatekeeper with cert rotator disabled and with a client ca name. Provide name of the client ca with the flag `--client-cert-name`. The same name will be used to read certificate from the webhook secret. The webhook will only authenticate apiserver requests if both - cert rotator disabled and client ca name is provided with flag - of the criteria are met.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason cert rotation needs to be disabled for this to work? Is there a way to make this orthogonal? Maybe store the cert in a separate secret/configmap (IIUI WRT secret vs. configmap the cert is not sensitive)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interesting. Why can't we use the same secret? does cert rotator delete and creates new secret while rotating cert or does it just update the whole data field making it impossible to persist manually added entries to data map?

Copy link
Contributor

Choose a reason for hiding this comment

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

TBH I can't remember how cert-rotator behaves, but I wouldn't be surprised if it clobbered the whole data field.

In any case, if we could use the same secret I'd still like to enable/disable either option separately for operational flexibility.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like cert rotator is not rewriting whole data map blindly, so we should be able to use the same secret

@@ -90,6 +90,9 @@ func AddMutatingWebhook(mgr manager.Manager, deps Dependencies) error {
}
server := mgr.GetWebhookServer()
server.TLSMinVersion = *tlsMinVersion
if *DisableCertRotation && *clientCAName != "" {
server.ClientCAName = *clientCAName
Copy link
Contributor

Choose a reason for hiding this comment

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

We should also add this to the policy.go webhook file, in case the user has disabled the mutation webhook (or refactor the initialization pipeline so we set global server configurations in a single place).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should we also add this to namespacelabel.go as well?

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 good call

@@ -145,6 +145,7 @@ controllerManager:
priorityClassName: system-cluster-critical
disableCertRotation: false
tlsMinVersion: 1.3
certName: ""
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to modify this value, it will get updated automatically on the next release.

@@ -145,6 +145,7 @@ controllerManager:
priorityClassName: system-cluster-critical
disableCertRotation: false
tlsMinVersion: 1.3
certName: ""
Copy link
Contributor

Choose a reason for hiding this comment

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

@@ -145,6 +145,7 @@ controllerManager:
priorityClassName: system-cluster-critical
disableCertRotation: false
tlsMinVersion: 1.3
certName: ""
Copy link
Member

@sozercan sozercan Oct 26, 2022

Choose a reason for hiding this comment

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

let's call this

Suggested change
certName: ""
clientCAName: ""

@@ -59,6 +59,8 @@ var (
emitAdmissionEvents = flag.Bool("emit-admission-events", false, "(alpha) emit Kubernetes events in gatekeeper namespace for each admission violation")
tlsMinVersion = flag.String("tls-min-version", "1.3", "minimum version of TLS supported")
serviceaccount = fmt.Sprintf("system:serviceaccount:%s:%s", util.GetNamespace(), serviceAccountName)
clientCAName = flag.String("client-cert-name", "", "name of the client certificate to authenticate apiserver requrest against")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
clientCAName = flag.String("client-cert-name", "", "name of the client certificate to authenticate apiserver requrest against")
clientCAName = flag.String("client-cert-name", "", "name of the client certificate to authenticate apiserver request against")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch!

@JaydipGabani JaydipGabani force-pushed the master branch 5 times, most recently from f0def98 to edb9df1 Compare October 27, 2022 19:14
@JaydipGabani JaydipGabani requested review from sozercan and maxsmythe and removed request for sozercan October 27, 2022 19:15
Copy link
Contributor

@maxsmythe maxsmythe left a comment

Choose a reason for hiding this comment

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

Minor nits, but other than that LGTM!

main.go Outdated
@@ -194,7 +193,7 @@ func main() {

// Make sure certs are generated and valid if cert rotation is enabled.
setupFinished := make(chan struct{})
if !*disableCertRotation {
if !*webhook.DisableCertRotation {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I would leave this flag in main.go since that is where the value is consumed (and it looks like webhooks no longer use this value)


To have requests coming from apiserver authenticated by webhook, following configuration can be made:

1. Deploy gatekeeper a client ca name. Provide name of the client ca with the flag `--client-cert-name`. The same name will be used to read certificate from the webhook secret. The webhook will only authenticate apiserver requests if both client ca name is provided with flag.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit "ca" -> "CA"

namespace: gatekeeper-system
type: Opaque
```
3. You will need to make sure that apiserver includes appropriate certificate while sending requests to apiserver, otherwise webhook will not accept these requests and will log error of `tls client didn't provide a certificate`. To make sure apiserver attaches correct certificate to requests being sent to webhook, you must specify the location of the admission control configuration file via the `--admission-control-config-file` flag while starting apiserver. Here is an example admission control configuration file
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: add a colon (:) at the end of the line

clusters:
- cluster:
certificate-authority-data: <clientca.crt> # same value as provided in gatekeeper webhook secret's clientca.crt
server: https://gatekeeper-webhook-service.gatekeeper-system.svc:443
Copy link
Member

Choose a reason for hiding this comment

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

can we add note about service or namespace name and it should be updated if it's different

metadata:
...
name: gatekeeper-webhook-server-cert
namespace: gatekeeper-system
Copy link
Member

Choose a reason for hiding this comment

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

let's update here too re: name and namespace

@@ -145,6 +145,7 @@ controllerManager:
priorityClassName: system-cluster-critical
disableCertRotation: false
tlsMinVersion: 1.3
clientCAName: ""
Copy link
Member

Choose a reason for hiding this comment

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

do we need to update the helm chart to set this value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yip! Missed that. Updating chart as well

Signed-off-by: Jaydip Gabani <gabanijaydip@gmail.com>
Copy link
Member

@sozercan sozercan left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@maxsmythe maxsmythe left a comment

Choose a reason for hiding this comment

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

LGTM, thank you for the PR!


To have requests coming from apiserver authenticated by webhook, following configuration can be made:

1. Deploy gatekeeper a client CA name. Provide name of the client ca with the flag `--client-cert-name`. The same name will be used to read certificate from the webhook secret. The webhook will only authenticate apiserver requests if both client ca name is provided with flag.
Copy link
Member

@ritazh ritazh Nov 1, 2022

Choose a reason for hiding this comment

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

Suggested change
1. Deploy gatekeeper a client CA name. Provide name of the client ca with the flag `--client-cert-name`. The same name will be used to read certificate from the webhook secret. The webhook will only authenticate apiserver requests if both client ca name is provided with flag.
1. Deploy gatekeeper with a client CA cert name. Provide name of the client CA with the flag `--client-cert-name`. The same name will be used to read certificate from the webhook secret. The webhook will only authenticate apiserver requests if both client CA name is provided with flag.

Copy link
Member

Choose a reason for hiding this comment

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

if both client CA name is provided with flag

what do you mean by "both" here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ohh! "both" isn't supposed to be here.

namespace: <gatekeeper-namespace>
type: Opaque
```
3. You will need to make sure that apiserver includes appropriate certificate while sending requests to apiserver, otherwise webhook will not accept these requests and will log error of `tls client didn't provide a certificate`. To make sure apiserver attaches correct certificate to requests being sent to webhook, you must specify the location of the admission control configuration file via the `--admission-control-config-file` flag while starting apiserver. Here is an example admission control configuration file:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
3. You will need to make sure that apiserver includes appropriate certificate while sending requests to apiserver, otherwise webhook will not accept these requests and will log error of `tls client didn't provide a certificate`. To make sure apiserver attaches correct certificate to requests being sent to webhook, you must specify the location of the admission control configuration file via the `--admission-control-config-file` flag while starting apiserver. Here is an example admission control configuration file:
3. You will need to make sure that apiserver includes appropriate certificate while sending requests to the webhook, otherwise webhook will not accept these requests and will log error of `tls client didn't provide a certificate`. To make sure apiserver attaches correct certificate to requests being sent to webhook, you must specify the location of the admission control configuration file via the `--admission-control-config-file` flag while starting apiserver. Here is an example admission control configuration file:


### Authenticate API server against Webhook (Self managed kube cluster only)

To have requests coming from apiserver authenticated by webhook, following configuration can be made:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
To have requests coming from apiserver authenticated by webhook, following configuration can be made:
To ensure a request to the Gatekeeper webhook is coming from the api server, Gatekeeper needs to validate the client cert in the request. To enable authenticate api server, the following configuration can be made:

@ritazh
Copy link
Member

ritazh commented Nov 1, 2022

To clarify, this issue addresses the first bullet of #1294 to do this manually. Might be good to add a comment that currently there is no way to do this automatically and for managed k8s.

To enable authenticate api server requires modifying cluster resources that may not be possible in managed K8s cluster

Copy link
Member

@ritazh ritazh left a comment

Choose a reason for hiding this comment

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

LGTM

@ritazh ritazh merged commit 65f8245 into open-policy-agent:master Nov 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Authenticate API Server for Gatekeeper webhook
5 participants