Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# OauthAuthorizationST

**Description:** Test suite for verifying OAuth 2.0 authorization using Keycloak as an external authorizer with OAUTHBEARER mechanism over a TLS listener, validating topic-level access control policies for different client teams.

**Before test execution steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Deploy Cluster Operator, Keycloak, and necessary OAuth secrets. | Cluster Operator and Keycloak are deployed and ready. |
| 2. | Deploy Kafka cluster with custom OAuth authentication and Keycloak authorization over TLS listener. | Kafka cluster is deployed and ready with OAuth authentication and Keycloak authorization configured. |
| 3. | Create TLS users for team-a-client and team-b-client. | TLS users are created and ready. |

**Labels:**

* [security](labels/security.md)

<hr style="border:1px solid">

## smokeTestForClients

**Description:** Test verifying that team A OAuth client can produce and consume messages on topics starting with 'a-' using OAUTHBEARER mechanism over TLS listener.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Create a topic starting with 'a-' prefix. | Topic is created. |
| 2. | Deploy team A OAuth producer and consumer over TLS. | Producer and consumer successfully authenticate and exchange messages. |

**Labels:**

* [security](labels/security.md)


## testTeamAReadFromTopic

**Description:** Test verifying that team A OAuth client can only consume messages using a consumer group starting with 'a-', and is denied when using an unauthorized consumer group.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Produce messages to a topic starting with 'a-' as team A. | Messages are produced successfully. |
| 2. | Attempt to consume messages using an unauthorized consumer group. | Consumer fails due to authorization denial. |
| 3. | Consume messages using a consumer group starting with 'a-'. | Consumer successfully receives messages. |

**Labels:**

* [security](labels/security.md)


## testTeamAWriteToTopic

**Description:** Test verifying that team A OAuth client is denied writing to unauthorized topics, can write to existing topics starting with 'x-', and can write to topics starting with 'a-'.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Attempt to produce messages to an unauthorized topic as team A. | Producer fails due to authorization denial. |
| 2. | Attempt to produce messages to a non-existent topic starting with 'x-' as team A. | Producer fails because team A cannot create 'x-' topics. |
| 3. | Create topic starting with 'x-' and produce messages as team A. | Producer successfully sends messages to the existing 'x-' topic. |
| 4. | Produce messages to a topic starting with 'a-' as team A. | Producer successfully sends messages to the 'a-' topic. |

**Labels:**

* [security](labels/security.md)


## testTeamAWriteToTopicStartingWithXAndTeamBReadFromTopicStartingWithX

**Description:** Test verifying that team A OAuth client can write to topics starting with 'x-' and team B OAuth client can read from those topics, validating cross-team topic access policies.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Create a topic starting with 'x-' and produce messages as team A. | Producer successfully sends messages to the 'x-' topic. |
| 2. | Consume messages from the 'x-' topic as team B. | Consumer successfully receives messages from the 'x-' topic. |

**Labels:**

* [security](labels/security.md)


## testTeamBWriteToTopic

**Description:** Test verifying that team B OAuth client is denied writing to unauthorized topics, and can write and read from topics starting with 'b-'.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Attempt to produce messages to an unauthorized topic as team B. | Producer fails due to authorization denial. |
| 2. | Produce and consume messages on a topic starting with 'b-' as team B. | Producer and consumer successfully exchange messages on the 'b-' topic. |

**Labels:**

* [security](labels/security.md)

Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# OauthPlainST

**Description:** Test suite for verifying OAuth 2.0 authentication using OAUTHBEARER and PLAIN SASL mechanisms over a plain (i.e., non-TLS) listener, including producer, consumer, KafkaConnect, KafkaMirrorMaker2, and KafkaBridge components with OAuth metrics validation.

**Before test execution steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Deploy Cluster Operator, Keycloak, and necessary OAuth secrets. | Cluster Operator and Keycloak are deployed and ready. |
| 2. | Deploy Kafka cluster with custom OAuth authentication listener supporting OAUTHBEARER and PLAIN mechanisms, and OAuth metrics enabled. | Kafka cluster is deployed and ready with OAuth listener configured. |
| 3. | Verify OAuth listener configuration is propagated to Kafka broker logs. | Kafka broker logs contain expected OAuth configuration. |

**Labels:**

* [security](labels/security.md)

<hr style="border:1px solid">

## testProducerConsumerBridgeWithOauthMetrics

**Description:** Test verifying that KafkaBridge with OAuth authentication can produce messages to a Kafka topic via the bridge HTTP endpoint, and that OAuth metrics are exposed by the KafkaBridge component.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Deploy OAuth producer and consumer and verify message exchange. | Messages are produced and consumed successfully. |
| 2. | Deploy KafkaBridge with custom OAuth OAUTHBEARER authentication over plain listener. | KafkaBridge is deployed and authenticates successfully. |
| 3. | Verify OAuth configuration in KafkaBridge logs. | OAuth configuration is present in the logs. |
| 4. | Produce messages via bridge HTTP endpoint and verify delivery. | Messages are produced via the bridge and delivered successfully. |
| 5. | Collect and verify OAuth metrics from KafkaBridge Pods. | OAuth metrics are present in the collected metrics data. |

**Labels:**

* [security](labels/security.md)


## testProducerConsumerConnectWithOauthMetrics

**Description:** Test verifying that KafkaConnect with OAuth authentication can sink messages from a Kafka topic, and that OAuth metrics are exposed by the KafkaConnect component.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Deploy OAuth producer and consumer and verify message exchange. | Messages are produced and consumed successfully. |
| 2. | Deploy KafkaConnect with custom OAuth OAUTHBEARER authentication over plain listener. | KafkaConnect is deployed and authenticates successfully. |
| 3. | Create a FileSink connector and verify messages are sinked. | Messages appear in the KafkaConnect file sink. |
| 4. | Verify OAuth configuration in KafkaConnect logs. | OAuth configuration is present in the logs. |
| 5. | Collect and verify OAuth metrics from KafkaConnect Pods. | OAuth metrics are present in the collected metrics data. |

**Labels:**

* [security](labels/security.md)


## testProducerConsumerMirrorMaker2WithOauthMetrics

**Description:** Test verifying that KafkaMirrorMaker2 with OAuth authentication can mirror messages between two Kafka clusters, and that OAuth metrics are exposed by the KafkaMirrorMaker2 component.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Deploy OAuth producer and consumer and verify message exchange on source cluster. | Messages are produced and consumed successfully on source cluster. |
| 2. | Deploy target Kafka cluster with custom OAuth authentication. | Target Kafka cluster is deployed and ready. |
| 3. | Deploy KafkaMirrorMaker2 with custom OAuth OAUTHBEARER authentication for both source and target clusters. | KafkaMirrorMaker2 is deployed and authenticates successfully. |
| 4. | Verify OAuth configuration in KafkaMirrorMaker2 logs. | OAuth configuration is present in the logs. |
| 5. | Wait for messages to be mirrored to the target cluster and verify. | Messages are mirrored successfully to the target cluster. |
| 6. | Collect and verify OAuth metrics from KafkaMirrorMaker2 Pods. | OAuth metrics are present in the collected metrics data. |

**Labels:**

* [security](labels/security.md)


## testProducerConsumerWithOauthMetrics

**Description:** Test verifying that an OAuth producer can produce and an OAuth consumer can consume messages from Kafka using OAUTHBEARER mechanism, and that OAuth metrics are exposed by the Kafka brokers.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Create a topic for the test. | Topic is created. |
| 2. | Deploy OAuth producer and consumer using OAUTHBEARER mechanism over plain listener. | Producer and consumer successfully authenticate and exchange messages. |
| 3. | Collect and verify OAuth metrics from Kafka broker Pods. | OAuth metrics are present in the collected metrics data. |

**Labels:**

* [security](labels/security.md)


## testSaslPlainProducerConsumer

**Description:** Test verifying that an OAuth producer and consumer can authenticate using SASL PLAIN mechanism backed by OAuth token endpoint.

**Steps:**

| Step | Action | Result |
| - | - | - |
| 1. | Deploy OAuth producer using SASL PLAIN mechanism with audience credentials. | Producer successfully authenticates and sends messages. |
| 2. | Deploy OAuth consumer using SASL PLAIN mechanism with audience credentials. | Consumer successfully authenticates and receives messages. |

**Labels:**

* [security](labels/security.md)

10 changes: 10 additions & 0 deletions development-docs/systemtests/labels/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,24 @@ They cover authentication and authorization mechanisms (OAuth, ACLs, OPA integra

<!-- generated part -->
**Tests:**
- [smokeTestForClients](../io.strimzi.systemtest.security.oauth.OauthAuthorizationST.md)
- [testAclRuleReadAndWrite](../io.strimzi.systemtest.security.custom.CustomAuthorizerST.md)
- [testAclWithSuperUser](../io.strimzi.systemtest.security.custom.CustomAuthorizerST.md)
- [testCustomCaTrustChainOnInternalPort](../io.strimzi.systemtest.security.custom.CustomCaChainST.md)
- [testCustomClusterCaAndClientsCaCertificates](../io.strimzi.systemtest.security.custom.CustomCaST.md)
- [testKafkaConnectTrustWithCustomCaChain](../io.strimzi.systemtest.security.custom.CustomCaChainST.md)
- [testMultistageCustomCaTrustChainEstablishment](../io.strimzi.systemtest.security.custom.CustomCaChainST.md)
- [testMultistageCustomCaUserCertificateAuthentication](../io.strimzi.systemtest.security.custom.CustomCaChainST.md)
- [testProducerConsumerBridgeWithOauthMetrics](../io.strimzi.systemtest.security.oauth.OauthPlainST.md)
- [testProducerConsumerConnectWithOauthMetrics](../io.strimzi.systemtest.security.oauth.OauthPlainST.md)
- [testProducerConsumerMirrorMaker2WithOauthMetrics](../io.strimzi.systemtest.security.oauth.OauthPlainST.md)
- [testProducerConsumerWithOauthMetrics](../io.strimzi.systemtest.security.oauth.OauthPlainST.md)
- [testReplaceCustomClientsCACertificateValidityToInvokeRenewalProcess](../io.strimzi.systemtest.security.custom.CustomCaST.md)
- [testReplaceCustomClusterCACertificateValidityToInvokeRenewalProcess](../io.strimzi.systemtest.security.custom.CustomCaST.md)
- [testReplacingCustomClientsKeyPairToInvokeRenewalProcess](../io.strimzi.systemtest.security.custom.CustomCaST.md)
- [testReplacingCustomClusterKeyPairToInvokeRenewalProcess](../io.strimzi.systemtest.security.custom.CustomCaST.md)
- [testSaslPlainProducerConsumer](../io.strimzi.systemtest.security.oauth.OauthPlainST.md)
- [testTeamAReadFromTopic](../io.strimzi.systemtest.security.oauth.OauthAuthorizationST.md)
- [testTeamAWriteToTopic](../io.strimzi.systemtest.security.oauth.OauthAuthorizationST.md)
- [testTeamAWriteToTopicStartingWithXAndTeamBReadFromTopicStartingWithX](../io.strimzi.systemtest.security.oauth.OauthAuthorizationST.md)
- [testTeamBWriteToTopic](../io.strimzi.systemtest.security.oauth.OauthAuthorizationST.md)
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

import io.fabric8.kubernetes.api.model.SecretVolumeSourceBuilder;
import io.fabric8.kubernetes.api.model.VolumeMountBuilder;
import io.skodjob.annotations.Desc;
import io.skodjob.annotations.Label;
import io.skodjob.annotations.Step;
import io.skodjob.annotations.SuiteDoc;
import io.skodjob.annotations.TestDoc;
import io.skodjob.kubetest4j.resources.KubeResourceManager;
import io.strimzi.api.kafka.model.common.template.AdditionalVolumeBuilder;
import io.strimzi.api.kafka.model.kafka.KafkaResources;
Expand All @@ -15,6 +20,7 @@
import io.strimzi.systemtest.TestConstants;
import io.strimzi.systemtest.annotations.FIPSNotSupported;
import io.strimzi.systemtest.annotations.ParallelTest;
import io.strimzi.systemtest.docs.TestDocsLabels;
import io.strimzi.systemtest.kafkaclients.internalClients.KafkaOauthClients;
import io.strimzi.systemtest.kafkaclients.internalClients.KafkaOauthClientsBuilder;
import io.strimzi.systemtest.keycloak.KeycloakInstance;
Expand Down Expand Up @@ -43,6 +49,17 @@
@Tag(REGRESSION)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@FIPSNotSupported("Keycloak is not customized to run on FIPS env - https://github.com/strimzi/strimzi-kafka-operator/issues/8331")
@SuiteDoc(
description = @Desc("Test suite for verifying OAuth 2.0 authorization using Keycloak as an external authorizer with OAUTHBEARER mechanism over a TLS listener, validating topic-level access control policies for different client teams."),
beforeTestSteps = {
@Step(value = "Deploy Cluster Operator, Keycloak, and necessary OAuth secrets.", expected = "Cluster Operator and Keycloak are deployed and ready."),
@Step(value = "Deploy Kafka cluster with custom OAuth authentication and Keycloak authorization over TLS listener.", expected = "Kafka cluster is deployed and ready with OAuth authentication and Keycloak authorization configured."),
@Step(value = "Create TLS users for team-a-client and team-b-client.", expected = "TLS users are created and ready.")
},
labels = {
@Label(value = TestDocsLabels.SECURITY)
}
)
public class OauthAuthorizationST extends OauthAbstractST {
protected static final Logger LOGGER = LogManager.getLogger(OauthAuthorizationST.class);

Expand All @@ -65,9 +82,16 @@ public class OauthAuthorizationST extends OauthAbstractST {

private static final String TEST_REALM = "kafka-authz";

/**
* As a member of team A, I should be able to read and write to all topics starting with a-.
*/
@TestDoc(
description = @Desc("Test verifying that team A OAuth client can produce and consume messages on topics starting with 'a-' using OAUTHBEARER mechanism over TLS listener."),
steps = {
@Step(value = "Create a topic starting with 'a-' prefix.", expected = "Topic is created."),
@Step(value = "Deploy team A OAuth producer and consumer over TLS.", expected = "Producer and consumer successfully authenticate and exchange messages.")
},
labels = {
@Label(value = TestDocsLabels.SECURITY)
}
)
@ParallelTest
@Order(1)
void smokeTestForClients() {
Expand Down Expand Up @@ -98,10 +122,18 @@ void smokeTestForClients() {
ClientUtils.waitForClientSuccess(Environment.TEST_SUITE_NAMESPACE, teamAConsumerName, testStorage.getMessageCount());
}

/**
* As a member of team A, I should be able to write to topics that starts with x- on any cluster and " +
* and should also write and read to topics starting with 'a-'.
*/
@TestDoc(
description = @Desc("Test verifying that team A OAuth client is denied writing to unauthorized topics, can write to existing topics starting with 'x-', and can write to topics starting with 'a-'."),
steps = {
@Step(value = "Attempt to produce messages to an unauthorized topic as team A.", expected = "Producer fails due to authorization denial."),
@Step(value = "Attempt to produce messages to a non-existent topic starting with 'x-' as team A.", expected = "Producer fails because team A cannot create 'x-' topics."),
@Step(value = "Create topic starting with 'x-' and produce messages as team A.", expected = "Producer successfully sends messages to the existing 'x-' topic."),
@Step(value = "Produce messages to a topic starting with 'a-' as team A.", expected = "Producer successfully sends messages to the 'a-' topic.")
},
labels = {
@Label(value = TestDocsLabels.SECURITY)
}
)
@ParallelTest
@Order(2)
void testTeamAWriteToTopic() {
Expand Down Expand Up @@ -164,9 +196,17 @@ void testTeamAWriteToTopic() {
ClientUtils.waitForClientSuccess(Environment.TEST_SUITE_NAMESPACE, teamAProducerName, testStorage.getMessageCount());
}

/**
* As a member of team A, I should be able only read from consumer that starts with a_.
*/
@TestDoc(
description = @Desc("Test verifying that team A OAuth client can only consume messages using a consumer group starting with 'a-', and is denied when using an unauthorized consumer group."),
steps = {
@Step(value = "Produce messages to a topic starting with 'a-' as team A.", expected = "Messages are produced successfully."),
@Step(value = "Attempt to consume messages using an unauthorized consumer group.", expected = "Consumer fails due to authorization denial."),
@Step(value = "Consume messages using a consumer group starting with 'a-'.", expected = "Consumer successfully receives messages.")
},
labels = {
@Label(value = TestDocsLabels.SECURITY)
}
)
@ParallelTest
@Order(3)
void testTeamAReadFromTopic() {
Expand Down Expand Up @@ -217,9 +257,16 @@ void testTeamAReadFromTopic() {
ClientUtils.waitForClientSuccess(Environment.TEST_SUITE_NAMESPACE, teamAProducerName, testStorage.getMessageCount());
}

/**
* As a member of team B, I should be able to write and read from topics that starts with b-.
*/
@TestDoc(
description = @Desc("Test verifying that team B OAuth client is denied writing to unauthorized topics, and can write and read from topics starting with 'b-'."),
steps = {
@Step(value = "Attempt to produce messages to an unauthorized topic as team B.", expected = "Producer fails due to authorization denial."),
@Step(value = "Produce and consume messages on a topic starting with 'b-' as team B.", expected = "Producer and consumer successfully exchange messages on the 'b-' topic.")
},
labels = {
@Label(value = TestDocsLabels.SECURITY)
}
)
@ParallelTest
@Order(4)
void testTeamBWriteToTopic() {
Expand Down Expand Up @@ -263,9 +310,16 @@ void testTeamBWriteToTopic() {
ClientUtils.waitForClientsSuccess(Environment.TEST_SUITE_NAMESPACE, teamBConsumerName, teamBProducerName, testStorage.getMessageCount());
}

/**
* As a member of team A, I can write to topics starting with 'x-' and as a member of team B can read from topics starting with 'x-'.
*/
@TestDoc(
description = @Desc("Test verifying that team A OAuth client can write to topics starting with 'x-' and team B OAuth client can read from those topics, validating cross-team topic access policies."),
steps = {
@Step(value = "Create a topic starting with 'x-' and produce messages as team A.", expected = "Producer successfully sends messages to the 'x-' topic."),
@Step(value = "Consume messages from the 'x-' topic as team B.", expected = "Consumer successfully receives messages from the 'x-' topic.")
},
labels = {
@Label(value = TestDocsLabels.SECURITY)
}
)
@ParallelTest
@Order(5)
void testTeamAWriteToTopicStartingWithXAndTeamBReadFromTopicStartingWithX() {
Expand Down
Loading
Loading