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

Enable per kafka listener sasl #6940

Conversation

RafalKorepta
Copy link
Contributor

@RafalKorepta RafalKorepta commented Oct 26, 2022

Cover letter

Uptake the following features from core:

Fixes #ISSUE-NUMBER, Fixes #ISSUE-NUMBER, ...

Backport Required

  • not a bug fix
  • issue does not exist in previous branches
  • papercut/not impactful enough to backport
  • v22.2.x
  • v22.1.x
  • v21.11.x

UX changes

Similar to core configuration changes.

Release notes

Features

  • Allow authentication method per kafka listener.
  • Allow http basic authentication method for schema registry and panda proxy.

Copy link
Member

@nicolaferraro nicolaferraro left a comment

Choose a reason for hiding this comment

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

Left some comments...

@@ -1130,3 +1130,10 @@ func defaultTLSConfig() *TLSConfig {
NodeSecretRef: nil,
}
}

func (s Cluster) SASLAuthorizationEnabled() bool {
return s.Spec.KafkaEnableAuthorization ||
Copy link
Member

Choose a reason for hiding this comment

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

Wonder if this new flag is needed. Setting authenticationMethod on the listener may be enough.

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 followed @BenPope implementation from #5292

In operator we don't have unlimited listener list, so your comment seem right. We have opinionated subset of Redpanda configuration, so I would like to defer this decision to @vladoschreiner.

Copy link
Member

Choose a reason for hiding this comment

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

My implementation is tri-state for kafka_enable_authorization. I.e., if kafka_enable_authorization is false or true, then enable_sasl has no effect.

func (s Cluster) SASLAuthorizationEnabled() bool {
return s.Spec.KafkaEnableAuthorization ||
s.Spec.EnableSASL ||
s.InternalListener().AuthenticationMethod == "sasl" ||
Copy link
Member

Choose a reason for hiding this comment

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

Only internal listener?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The SASLAutorizationEnabled function is used only internally to configure:

  • pandaproxy talking to kafka listener
  • schema registry talking to kafka listener
  • console talking to kafka listener

In the code we have assumption to not talk over external listeners.

Copy link
Contributor

Choose a reason for hiding this comment

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

let's encode that assumption in the method name then? 🙏 IsSASLOnInternalEnabled for example

external := r.pandaCluster.PandaproxyAPIExternal()
if external != nil {
if external.AuthenticationMethod != "" {
externalAuthN = &internal.AuthenticationMethod
Copy link
Member

Choose a reason for hiding this comment

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

Probably you meant external

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you. Copy-pasta error

@RafalKorepta RafalKorepta force-pushed the rk/gh-1959/enable-per-kafka-listener-sasl branch 3 times, most recently from 8a29f1a to 4deeb03 Compare October 26, 2022 10:36
Copy link
Contributor

@alenkacz alenkacz left a comment

Choose a reason for hiding this comment

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

Added some initial questions/comments

// - `false`: authorization is disabled;
//
// See also `enableSasl` and `configuration.kafkaApi[].authenticationMethod`
KafkaEnableAuthorization bool `json:"kafkaEnableAuthorization,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need to have this global flag? Why configuration.kafkaApi[].authenticationMethod is not enough? 🤔

Copy link
Member

Choose a reason for hiding this comment

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

enable_sasl used to:

  • Enable sasl AuthN on every listener
  • Enable AuthZ globally.

In order allow different AuthN per listener, but also allow disabling AuthZ with cluster config (on the fly), and keep backwards compatibility, both flags are needed.

@@ -562,6 +581,9 @@ type SchemaRegistryAPI struct {
External *SchemaRegistryExternalConnectivityConfig `json:"external,omitempty"`
// TLS is the configuration for schema registry
TLS *SchemaRegistryAPITLS `json:"tls,omitempty"`
// AuthenticationMethod can enable authentication method per schema registry
// listener. Available options are: none, http_basic.
AuthenticationMethod string `json:"authenticationMethod,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

for schema registry it enables it on all listeners, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have only one listener.

func (s Cluster) SASLAuthorizationEnabled() bool {
return s.Spec.KafkaEnableAuthorization ||
s.Spec.EnableSASL ||
s.InternalListener().AuthenticationMethod == "sasl" ||
Copy link
Contributor

Choose a reason for hiding this comment

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

let's encode that assumption in the method name then? 🙏 IsSASLOnInternalEnabled for example

// AuthenticationMethod can enable authentication method per Kafka
// listener. Available options are: none, sasl, mtls_identity.
// https://docs.redpanda.com/docs/security/authentication/
AuthenticationMethod string `json:"authenticationMethod,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to see webhook validation for the allowed values in AuthenticationMethod 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok will add

@@ -224,18 +224,34 @@ func (r *ConfigMapResource) CreateConfiguration(
cr := &cfg.NodeConfiguration.Redpanda

internalListener := r.pandaCluster.InternalListener()
var internalAuthN *string
Copy link
Contributor

Choose a reason for hiding this comment

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

can we add something to configmap_test for these?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok I will add

@RafalKorepta RafalKorepta force-pushed the rk/gh-1959/enable-per-kafka-listener-sasl branch 6 times, most recently from 16c438d to a7dd26d Compare October 27, 2022 00:50
Copy link
Member

@nicolaferraro nicolaferraro left a comment

Choose a reason for hiding this comment

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

Looks good overall, just a minor issue and rebasing needed.

EnableSASL bool `json:"enableSasl,omitempty"`
// Enable authorization for Kafka connections. Values are:
//
// - `nil`: Ignored. Authorization is enabled with `enable_sasl: true`
Copy link
Member

Choose a reason for hiding this comment

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

It's a bool, can't be nil.

Copy link
Contributor Author

@RafalKorepta RafalKorepta Oct 27, 2022

Choose a reason for hiding this comment

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

I changed it to *bool

@RafalKorepta RafalKorepta force-pushed the rk/gh-1959/enable-per-kafka-listener-sasl branch 2 times, most recently from 07b1f0c to 62e30a5 Compare October 27, 2022 11:06
nicolaferraro
nicolaferraro previously approved these changes Oct 27, 2022
alenkacz
alenkacz previously approved these changes Oct 27, 2022
Copy link
Contributor

@alenkacz alenkacz left a comment

Choose a reason for hiding this comment

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

Just two small comments otherwise LGTM

@@ -44,6 +44,10 @@ const (
transactionCoordinatorReplicationKey = "redpanda.transaction_coordinator_replication"
idAllocatorReplicationKey = "redpanda.id_allocator_replication"

noneAuthorizationMechanism = "none"
Copy link
Contributor

Choose a reason for hiding this comment

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

I was expecting to see also http_basic here 🤔

@@ -129,7 +129,19 @@ type ClusterSpec struct {
// List of superusers
Superusers []Superuser `json:"superUsers,omitempty"`
// SASL enablement flag
// +optional
// Deprecated: replaced by "kafkaEnableAuthorization"
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 probably either:

  • verify in webhook someone is not running something like EnableSASL: true, KafkaEnableAuthorization:false

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is unfortunately not possible to prevent from happening. The combination of EnableSASL: true, KafkaEnableAuthorization:false will be possible until core removes enableSASL configuration option.

@r-vasquez
Copy link
Contributor

LGTM (rpk- side ) 👍

@RafalKorepta RafalKorepta force-pushed the rk/gh-1959/enable-per-kafka-listener-sasl branch from 62e30a5 to 333ad64 Compare October 28, 2022 11:24
nicolaferraro
nicolaferraro previously approved these changes Oct 28, 2022
@RafalKorepta RafalKorepta force-pushed the rk/gh-1959/enable-per-kafka-listener-sasl branch 2 times, most recently from 27ffbde to 725212d Compare October 30, 2022 21:11
Rafal Korepta added 7 commits October 30, 2022 23:00
The gofumpt is used now.

REF: redpanda-data#4665
When console configuration or config map metadata should be change, then
tracing that is hard based on only operator logs. This change adds context to
action that are taken in reconciliation function.l
In not so much good internet connection, waiting 2 minutes for config manager
to became ready is not enough.
When deployment was changed, so that it uses new kustomize overlay, then the
decommission deployment needs to be adjusted as containers where reorder and
bring back the 'good' configuration was not valid anymore.
As the current e2e test setup is using localhost/configurator:dev container
image definition, the previous step to add configurator tag command argument
was not valid anymore. It was easier to not fight with `kubectl patch` command,
but declare whole operator deployment to correctly set the configurator image.
The console secret synchronizer was not able to update schema registry secret
after cert manager updated schema registry secret for Redpanda cluster.

REF:
```
2022-10-30T21:32:49.741Z	ERROR	controller.console	Reconciler error	{"reconciler group": "redpanda.vectorized.io", "reconciler kind": "Console", "name": "console", "namespace": "console", "error": "updating Console synced secret &Secret{ObjectMeta:{console-schema-registry  console   2331 0 0001-01-01 00:00:00 +0000 UTC <nil> <nil> map[app.kubernetes.io/component:console app.kubernetes.io/instance:console app.kubernetes.io/managed-by:redpanda-operator app.kubernetes.io/name:redpanda-console app.kubernetes.io/part-of:redpanda-console test.redpanda.vectorized.io/name:updating-console] map[banzaicloud.com/last-applied:UEsDBBQACAAIAAAAAAAAAAAAAAAAAAAAAAAIAAAAb3JpZ2luYWyEkcFO8zAQhN9lz3F+NepPSq5wRwKJC+KwtqetVce27E1RqfLuKNBWpSpws8bf7Oxq9sTJPSMXFwN1tJ1RRRsXLHX0BJMhVFEPYcvC1O3Js4Yv04tTqjeDRg4QlNrFfyb2KQYEoY5MDCV6UHWFc6EIB4M/sJ4Dr2CV3lFHGTZxsKxiQmaJ+aolcI9z+LfxibOouLyOC4rUR73ewkjM7h32LGRIlsWF1ck1VnT4OiiqmDV6VhkrVyTv6AsoiS9uj28B+RFLZASDQt3LRS0/bLKdsU9rnjrTPprNwzTnHh7yaZM8oJpiJEfvkY/Kod+7U/73tamiwU1AaxbNvGla1WozV/NFo5VuWyj9f3FrGTctL1saX8fxIwAA//9QSwcIaDwarhoBAABFAgAAUEsBAhQAFAAIAAgAAAAAAGg8Gq4aAQAARQIAAAgAAAAAAAAAAAAAAAAAAAAAAG9yaWdpbmFsUEsFBgAAAAABAAEANgAAAFABAAAAAA==] [{redpanda.vectorized.io/v1alpha1 Console console 7c824227-7bc4-482b-b77e-b589dae67af7 0xc000db6e01 0xc000db6e00}] []  []},Data:map[string][]byte{},Type:,StringData:map[string]string{},Immutable:nil,}: failed to update resource: secrets \"console-schema-registry\" is forbidden: User \"system:serviceaccount:redpanda-system:default\" cannot update resource \"secrets\" in API group \"\" in the namespace \"console\""}
```
The console config map is immutable and any change into console resource spec
will increment console resource generation. That will trigger a operator
reconciliation loop which will create new configmap and delete old one if there
will be no errors between k8s api server and operator.

REF:
```
2022-10-30T21:52:05.336Z	ERROR	controller.console	Reconciler error	{"reconciler group": "redpanda.vectorized.io", "reconciler kind": "Console", "name": "console", "namespace": "console", "error": "deleting unused configmaps: configmaps \"console-7wtlg\" is forbidden: User \"system:serviceaccount:redpanda-system:default\" cannot delete resource \"configmaps\" in API group \"\" in the namespace \"console\""}
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2
	/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.9.7/pkg/internal/controller/controller.go:214
```
@RafalKorepta RafalKorepta force-pushed the rk/gh-1959/enable-per-kafka-listener-sasl branch from 725212d to b65e9a1 Compare October 30, 2022 22:07
Copy link
Contributor

@alenkacz alenkacz 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

Copy link
Member

@nicolaferraro nicolaferraro left a comment

Choose a reason for hiding this comment

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

Some comments on the validity of the Kuttl tests. I think that they pass even if the API does not reply correctly

name: schema-registry-schema-registry-sasl
key: password
command:
- curl
Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately curl does not fail if the status code is not 2xx, you may need to check it manually

name: schema-registry-schema-registry-sasl
key: password
command:
- curl
Copy link
Member

Choose a reason for hiding this comment

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

Same, should check http code

- -c
args:
- >
curl -vv --silent --cacert /etc/tls/certs/schema-registry/ca.crt
Copy link
Member

Choose a reason for hiding this comment

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

Same, should check http code

- -c
args:
- >
curl -vv --silent --cacert /etc/tls/certs/schema-registry/ca.crt
Copy link
Member

Choose a reason for hiding this comment

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

Same, should check http code

- -c
args:
- >
curl -vv --silent --cacert /etc/tls/certs/schema-registry/ca.crt
Copy link
Member

Choose a reason for hiding this comment

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

Same, should check http code

- -c
args:
- >
curl -vv --silent
Copy link
Member

Choose a reason for hiding this comment

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

Same, should check http code

- -c
args:
- >
curl -vv --silent
Copy link
Member

Choose a reason for hiding this comment

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

Same, should check http code

- -c
args:
- >
curl -vv --silent
Copy link
Member

Choose a reason for hiding this comment

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

Same, should check http code

Copy link
Member

@BenPope BenPope left a comment

Choose a reason for hiding this comment

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

Sorry, late review.

Comment on lines +47 to +49
noneAuthorizationMechanism = "none"
saslAuthorizationMechanism = "sasl"
mTLSIdentityAuthorizationMechanism = "mtls_identity"
Copy link
Member

Choose a reason for hiding this comment

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

These are authentication mechanisms.


for i := range r.Spec.Configuration.KafkaAPI {
if r.Spec.Configuration.KafkaAPI[i].AuthenticationMethod == "" {
r.Spec.Configuration.KafkaAPI[i].AuthenticationMethod = noneAuthorizationMechanism
Copy link
Member

Choose a reason for hiding this comment

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

There's some difficulty here. The configuration makes this field optional. See: 1c9155a#diff-37dfa5396e57820190992de850ada07cfb605311413bc76aa25d112eccc106d3R469-R495.

Leaving the authentication mechanism as unspecified means:

if kafka_enable_authorization is null:
   sasl if enable_sasl else none

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

Successfully merging this pull request may close these issues.

5 participants