Skip to content

Add support for enhanced security#692

Merged
mergify[bot] merged 1 commit into
csi-addons:mainfrom
bipuladh:tls
Dec 20, 2024
Merged

Add support for enhanced security#692
mergify[bot] merged 1 commit into
csi-addons:mainfrom
bipuladh:tls

Conversation

@bipuladh

@bipuladh bipuladh commented Oct 28, 2024

Copy link
Copy Markdown
Contributor

Changes

  • Adds a auth header check for bearer tokens on the Sidecar Pods
  • Generates self signed certs on the sidecar pods for SSL security.
  • Adds a bearer token to the request headers on the manager.(Taken from corresponding SA)
  • Introduces a new arg in both manager and sidecar named enable-auth(disabled by default. If enabled it will start checking for auth headers in Request objects and enables TLS for grpc connections.

Requirements for the above features to work correctly:

  • TokenReview create and get access for all sidecar containers

.

Images for testing:

  • Sidecar: quay.io/badhikar/k8s-sidecar:rc-5
  • Controller: quay.io/badhikar/k8s-controller:rc-5

Test logs

2024-11-11T18:12:00.948Z INFO Successfully connected to sidecar {"controller": "csiaddonsnode", "controllerGroup": "csiaddons.openshift.io", "controllerKind": "CSIAddonsNode", "CSIAddonsNode": {"name":"csi-rbdplugin-gbr85","namespace":"openshift-storage"}, "namespace": "openshift-storage", "name": "csi-rbdplugin-gbr85", "reconcileID": "964eea1e-324b-4957-984d-2611972645ed", "NodeID": "ip-10-0-50-177.us-east-2.compute.internal", "DriverName": "openshift-storage.rbd.csi.ceph.com", "EndPoint": "10.0.50.177:9070"}

@nixpanic nixpanic left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

left a few minor comments for improving, looks pretty good to me already. Thanks!

Comment thread internal/kubernetes/namespace.go Outdated
Comment thread tools/go.mod Outdated
Comment thread internal/kubernetes/token/grpc.go Outdated
Comment thread internal/kubernetes/token/grpc.go Outdated
@bipuladh bipuladh changed the title [WIP] Add support for TLS Add support for TLS Nov 11, 2024
@bipuladh bipuladh requested a review from nixpanic November 11, 2024 13:15
@bipuladh

Copy link
Copy Markdown
Contributor Author

@nixpanic should we disable it by default for easy opt-in for users?

Comment thread sidecar/main.go Outdated
Comment thread config/manager/manager.yaml Outdated
@nixpanic

Copy link
Copy Markdown
Member

@nixpanic should we disable it by default for easy opt-in for users?

If it works on current Kubernetes installations by default, it can be enabled by default IMHO. You may want to add a note in https://github.com/csi-addons/kubernetes-csi-addons/blob/main/docs/deploy-controller.md on the requirements of Kubernetes services, and how to disable it in case those services are unavailable.

@bipuladh bipuladh requested a review from nixpanic November 11, 2024 18:21
@bipuladh

Copy link
Copy Markdown
Contributor Author

@Madhu-1

Madhu-1 commented Nov 12, 2024

Copy link
Copy Markdown
Member

@Madhu-1 my PR fails until I revert code introduced at https://github.com/csi-addons/kubernetes-csi-addons/pull/695/files#diff-03e0410a78ce106bc8ee10f594661c87995994955bfb6b07972d8fde2ec8a555R125-R146 Could you PTAL?

@bipuladh please use latest yamls from master branch in Rook

@Madhu-1 Madhu-1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please add a documentation about this feature and as its enabled by default i assume upgraded works as it is (in kubernetes)

}
tlsConfig := &tls.Config{
RootCAs: caCertPool, // The CA certificates to verify the server
InsecureSkipVerify: true,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

dont we need to set it to true?

@bipuladh bipuladh Nov 12, 2024

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

By default setting it to false but making it configurable by users from args

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

After having discussions we need the ability to configure this to support certificates. We currently resolve the IP address and use that instead of host name. This causes certificate mismatch.

Comment thread internal/connection/connection.go Outdated
Comment thread internal/connection/connection.go Outdated
Comment thread internal/kubernetes/token/grpc.go Outdated
Comment on lines +78 to +91
return status.Errorf(codes.Unauthenticated, "missing metadata")
}

authHeader, ok := md["authorization"]
if !ok || len(authHeader) == 0 {
return status.Errorf(codes.Unauthenticated, "missing authorization token")
}

token := authHeader[0]
isValidated, err := validateBearerToken(ctx, token, kubeclient)
if !isValidated || (err != nil) {
return status.Errorf(codes.Unauthenticated, "invalid token")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i think you can use status.Error instead of status.Errorf

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

return the err message as well for better debugging

Comment thread internal/kubernetes/token/grpc.go Outdated
Comment on lines +52 to +62
file, err := os.Open(tokenPath)
if err != nil {
return "", err
}
defer file.Close()

data, err := io.ReadAll(file)
if err != nil {
return "", err
}
return string(data), nil

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

make use of readfile function which is doing the same thing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ioutil readFile is deprecated.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i meant readFile we have below in this file

Comment thread sidecar/internal/server/server.go Outdated
ss.server = grpc.NewServer(grpc.UnaryInterceptor(token.AuthorizationInterceptor(ss.client)), grpc.Creds(creds))
}
if !ss.enableTLS {
ss.server = grpc.NewServer(grpc.UnaryInterceptor(token.AuthorizationInterceptor(ss.client)))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

if tls is not enabled why we need to have add UnaryInterceptor here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think this is something we need to decide. Should we disable auth token verification if TLS is disabled?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removing Interceptor when TLS not used.

Comment thread cmd/manager/main.go Outdated
}
tlsConfig := &tls.Config{
RootCAs: caCertPool, // The CA certificates to verify the server
InsecureSkipVerify: true,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn't it be set to false?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

By default setting it to false but making it configurable by users from args

Comment thread internal/kubernetes/token/grpc.go Outdated
Comment thread internal/kubernetes/token/grpc.go Outdated
return nil
}

func removeBearer(authHeader string) string {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
func removeBearer(authHeader string) string {
func extractToken(authHeader string) string {

since the function just extracts the token, this naming is more suitable?

Comment thread sidecar/internal/server/server.go Outdated
Comment thread sidecar/main.go Outdated
@bipuladh

Copy link
Copy Markdown
Contributor Author

Please add a documentation about this feature and as its enabled by default i assume upgraded works as it is (in kubernetes)

@Madhu-1 @nixpanic for a smoother upgrade experience, should we disable by default? As mentioned in the PR description the sidecar deployer will have to create a certificate and mount it if not done the sidecar would go to CLBO. I can add this setup procedure on the readme files for reference.
I was thinking in the absence of certs we could automatically disable TLS but this could end up becoming a debugging nightmare. Perhaps logging could help, not sure.

@nixpanic

Copy link
Copy Markdown
Member

@Madhu-1 @nixpanic for a smoother upgrade experience, should we disable by default? As mentioned in the PR description the sidecar deployer will have to create a certificate and mount it if not done the sidecar would go to CLBO. I can add this setup procedure on the readme files for reference. I was thinking in the absence of certs we could automatically disable TLS but this could end up becoming a debugging nightmare. Perhaps logging could help, not sure.

Yes, users should not need to do anything extra for upgrading. If there are manual steps to configure certificates, disable the feature by default.

@nixpanic nixpanic left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good to me. Please squash all the commits together so that the Mergify automation can merge it when all approvals are in.

Comment thread internal/kubernetes/token/grpc.go Outdated
isValidated, err := validateBearerToken(ctx, token, kubeclient)
if !isValidated || (err != nil) {
return status.Errorf(codes.Unauthenticated, "invalid token")
return status.Error(codes.Unauthenticated, fmt.Sprint("invalid token: %w", err))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this is where status.Errorf() can be used so that fmt.Sprintf() is not needed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you please address this as well?

Comment thread cmd/manager/main.go Outdated
flag.BoolVar(&showVersion, "version", false, "Print Version details")
flag.StringVar(&cfg.SchedulePrecedence, "schedule-precedence", "", "The order of precedence in which schedule of reclaimspace and keyrotation is considered. Possible values are sc-only")
flag.BoolVar(&enableTLS, "enable-tls", false, "Enable TLS(enabled by default)")
flag.BoolVar(&skipInsecureVerify, "insecure-skip-tls-verify", false, "skip the certificate check")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
flag.BoolVar(&skipInsecureVerify, "insecure-skip-tls-verify", false, "skip the certificate check")
flag.BoolVar(&skipInsecureVerify, "insecure-skip-tls-verify", false, "skip server certificate verification")

@Madhu-1 Madhu-1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please add/update the documentation on how to enable this functionality

Comment thread cmd/manager/main.go Outdated
flag.BoolVar(&enableAdmissionWebhooks, "enable-admission-webhooks", false, "[DEPRECATED] Enable the admission webhooks")
flag.BoolVar(&showVersion, "version", false, "Print Version details")
flag.StringVar(&cfg.SchedulePrecedence, "schedule-precedence", "", "The order of precedence in which schedule of reclaimspace and keyrotation is considered. Possible values are sc-only")
flag.BoolVar(&enableTLS, "enable-tls", false, "Enable TLS(enabled by default)")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

need to update the comment as its disabled by default

Comment thread internal/connection/connection.go
Comment thread internal/connection/connection.go Outdated
grpc.WithIdleTimeout(time.Duration(0)),
}

opts = append(opts, token.WithServiceAccountToken())

Copy link
Copy Markdown
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 move this inside the if check when TLS is enabled?

Comment thread internal/connection/connection.go Outdated

caFile, caError := token.GetCACert()
if caError != nil {
return nil, (fmt.Errorf("failed to get server cert %w", caError))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
return nil, (fmt.Errorf("failed to get server cert %w", caError))
return nil, fmt.Errorf("failed to get server cert %w", caError)

Comment thread internal/kubernetes/token/grpc.go Outdated
Comment on lines +52 to +62
file, err := os.Open(tokenPath)
if err != nil {
return "", err
}
defer file.Close()

data, err := io.ReadAll(file)
if err != nil {
return "", err
}
return string(data), nil

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i meant readFile we have below in this file

Comment on lines +96 to +98
func parseToken(authHeader string) string {
if strings.HasPrefix(authHeader, bearerPrefix) {
return strings.TrimPrefix(authHeader, bearerPrefix)
}
return authHeader
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If the goal is to just to parse, we can remove the if check and trim it

func parseToken(authHeader string) string {
	return strings.TrimPrefix(authHeader, bearerPrefix)
}

result, err := kubeclient.AuthenticationV1().TokenReviews().Create(ctx, tokenReview, metav1.CreateOptions{})
if err != nil {
return false, fmt.Errorf("failed to review token %w", err)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Dont we need RBAC for this one? am not sure we have this RBAC already

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes we require. Whoever deploys the sidecar should be responsible to have this.

Comment thread sidecar/internal/server/server.go Outdated
// create the gRPC server and register services
ss.server = grpc.NewServer()
if ss.enableTLS {
creds, err := credentials.NewServerTLSFromFile("/etc/tls/tls.crt", "/etc/tls/tls.key")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

"/etc/tls/tls.crt", "/etc/tls/tls.key" Are we going to have these two files in all the pods in same location when TLS is enabled?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ideally yes. But I guess we can make it configurable later on if that is preferred.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

adding these as parameters

Comment thread sidecar/internal/server/server.go Outdated
if ss.enableTLS {
creds, err := credentials.NewServerTLSFromFile("/etc/tls/tls.crt", "/etc/tls/tls.key")
if err != nil {
klog.Fatalf("Could not find TLS file: %v", err)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
klog.Fatalf("Could not find TLS file: %v", err)
klog.Fatalf("failed to load TLS certificate and key: %v", err)

@mergify mergify Bot added the api Change to the API, requires extra care label Nov 13, 2024
@bipuladh

Copy link
Copy Markdown
Contributor Author

@nixpanic @Madhu-1 tested with both enabled and disabled mode. Works fine.

@bipuladh bipuladh changed the title Add support for TLS Add support for enhanced security Dec 20, 2024
Comment thread internal/kubernetes/token/grpc.go Outdated
Comment thread internal/kubernetes/token/grpc.go Outdated
Comment thread internal/kubernetes/token/grpc.go Outdated
Comment thread sidecar/internal/server/server.go Outdated
nixpanic
nixpanic previously approved these changes Dec 20, 2024

@nixpanic nixpanic left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, many thanks!

@bipuladh bipuladh requested a review from Rakshith-R December 20, 2024 10:00
@mergify mergify Bot dismissed nixpanic’s stale review December 20, 2024 10:00

Pull request has been modified.

nixpanic
nixpanic previously approved these changes Dec 20, 2024
Comment thread internal/kubernetes/token/grpc.go Outdated
@mergify mergify Bot dismissed nixpanic’s stale review December 20, 2024 10:17

Pull request has been modified.

@Rakshith-R Rakshith-R left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

one small nit,
rest looks good to me.

Comment thread internal/kubernetes/token/grpc.go Outdated
Signed-off-by: Bipul Adhikari <badhikar@redhat.com>

@Rakshith-R Rakshith-R left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks

@Rakshith-R

Copy link
Copy Markdown
Member

@Mergifyio queue

@mergify

mergify Bot commented Dec 20, 2024

Copy link
Copy Markdown

queue

✅ The pull request has been merged automatically

Details

The pull request has been merged automatically at ae2ede2

@Rakshith-R Rakshith-R dismissed Madhu-1’s stale review December 20, 2024 12:31

requested changes are addressed

@Rakshith-R

Copy link
Copy Markdown
Member

@Mergifyio refresh

@mergify

mergify Bot commented Dec 20, 2024

Copy link
Copy Markdown

refresh

✅ Pull request refreshed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Change to the API, requires extra care

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants