<a id="multi-tenancy-onboard-a-developer"></a>

# Onboard a Developer to an LKC

Grant a developer access to a provisioned Logical Kafka Cluster
(LKC), share the connection details they need, and confirm that their
client connects and sees only this LKC’s resources. `TenantAdmin`
users perform Steps 1 and 2 of this procedure one time per
developer, after a platform operator has onboarded the LKC. The
developer performs Steps 3 and 4 to confirm their own access.

## Prerequisites

Before you begin, ensure you have the following:

- An active LKC and the `TenantAdmin` role on it, assigned in
  [Step 7](onboard-a-tenant.md#multi-tenancy-onboard-step-7) of
  [Onboard an LKC to a Multi-Tenant Physical Kafka Cluster](onboard-a-tenant.md#multi-tenancy-onboard-a-tenant), and the connection details
  your platform operator shared in
  [Step 8](onboard-a-tenant.md#multi-tenancy-onboard-step-8).
- A `KafkaRestClass` in your namespace. Name it `default`, or
  reference it in the role binding manifest in
  [Step 1](#multi-tenancy-onboard-developer-step-1).
- An existing principal (user or service account) for the developer in
  the shared identity provider (IdP) of the
  Physical Kafka Cluster (PKC), or an existing client certificate for
  mutual TLS (mTLS) authentication. If the developer
  doesn’t have one yet, coordinate with your platform operator or your
  organization’s IdP administrator.
- At least one topic in the LKC for the developer to use. A platform
  operator, or a developer who already has `DeveloperManage` on the
  LKC, creates it using a standard Kafka client, the same way you
  created a test topic in
  [Step 5](onboard-a-tenant.md#multi-tenancy-onboard-step-5) of
  [Onboard an LKC to a Multi-Tenant Physical Kafka Cluster](onboard-a-tenant.md#multi-tenancy-onboard-a-tenant).
- Optional: a second identity with no role binding on this LKC, if you
  want to confirm LKC isolation as described in
  [Verify LKC isolation and quota enforcement](#multi-tenancy-onboard-developer-verify).

<a id="multi-tenancy-onboard-developer-step-1"></a>

## Step 1: Grant the developer access through RBAC

Delegate access through role-based access control (RBAC) by creating a
`ConfluentRolebinding` custom resource (CR) scoped to this LKC,
using one of the standard roles. For the permissions each role grants,
see [Use Predefined RBAC Roles in Confluent Platform](../../security/authorization/rbac/rbac-predefined-roles.md#rbac-predefined-roles).

| Role              | Typical use                                              |
|-------------------|----------------------------------------------------------|
| `DeveloperRead`   | A consumer application                                   |
| `DeveloperWrite`  | A producer application                                   |
| `DeveloperManage` | A developer who also creates or deletes their own topics |

A consumer needs `DeveloperRead` on both the topic and the consumer
group it uses, as shown in the following example manifest.

1. Create a manifest file named `developer-rolebinding.yaml`:
   ```yaml
   apiVersion: platform.confluent.io/v1beta1
   kind: ConfluentRolebinding
   metadata:
     name: <developer-binding-name>
     namespace: <your-namespace>
   spec:
     principal:
       type: user
       name: <developer-identity>
     role: <role-name>
     kafkaClusterRef:
       kind: LogicalKafkaCluster
       name: <lkc-name>
     resourcePatterns:
       - resourceType: Topic
         name: <topic-name>
         patternType: LITERAL
       - resourceType: Group
         name: <consumer-group-name>
         patternType: LITERAL
   ```

   Replace the placeholders with your values:
   - `<developer-binding-name>`: A name for the
     `ConfluentRolebinding` CR.
   - `<your-namespace>`: The namespace of the LKC’s CR.
   - `<developer-identity>`: The developer’s existing identity in
     your shared IdP, or their service account. For an mTLS identity,
     use the principal derived from the certificate’s subject
     distinguished name (DN), based on your cluster’s
     `ssl.principal.mapping.rules` configuration.
   - `<role-name>`: `DeveloperRead`, `DeveloperWrite`, or
     `DeveloperManage`, from the preceding table.
   - `<lkc-name>`: The name of the LKC’s CR.
   - `<topic-name>`: The topic to grant access to, using its
     LKC-local name, such as `orders`.
   - `<consumer-group-name>`: The consumer group to grant access to.
     Include this `resourcePatterns` entry only if the developer
     consumes from this topic.
2. Apply the configuration:
   ```bash
   kubectl apply -f developer-rolebinding.yaml
   ```

`role` accepts only one value per `ConfluentRolebinding` CR. If
the developer needs both produce and consume access, as in Step 4,
repeat this step once per role, creating a separate CR for
`DeveloperWrite` and another for `DeveloperRead`.

<a id="multi-tenancy-onboard-developer-step-2"></a>

## Step 2: Provide connection details to the developer

Share the following with the developer:

- The LKC’s bootstrap URL, in the form
  `lkc-<id>-kafka.<domain>:<port>` (the same endpoint returned in
  [Step 5](onboard-a-tenant.md#multi-tenancy-onboard-step-5) of
  [Onboard an LKC to a Multi-Tenant Physical Kafka Cluster](onboard-a-tenant.md#multi-tenancy-onboard-a-tenant)):
  ```bash
  kubectl get logicalkafkacluster <lkc-name> -n <your-namespace> \
    -o jsonpath='{.status.bootstrapEndpoint}'
  ```
- The authentication mechanism configured on the PKC, such as
  Simple Authentication and Security Layer (SASL) mechanisms
  `SASL/PLAIN` and `SASL/OAUTHBEARER`, or mTLS, and the client configuration
  it requires. For more information, see
  [Authentication in Confluent Platform](../../security/authentication/overview.md#authentication-overview) and
  [Step 3](#multi-tenancy-onboard-developer-step-3).
- The PKC’s TLS certificate authority (CA) certificate or truststore,
  so the developer’s client can validate the broker’s TLS certificate.
  For an mTLS identity, also share how the developer obtains their own
  client certificate and private key.
- The topics, consumer groups, and operations you granted in
  [Step 1](#multi-tenancy-onboard-developer-step-1).
- The LKC’s quota and limit boundaries, so the developer can size
  their application. For more information, see
  [Monitor and Manage Per-LKC Resource Quotas](manage-tenant-quotas.md#multi-tenancy-manage-tenant-quotas).
- The Confluent Control Center URL, so that the developer can monitor their own
  application’s activity.

<a id="multi-tenancy-onboard-developer-step-3"></a>

## Step 3: Connect a standard Kafka client

Connect a standard Kafka client to the LKC. A multi-tenant PKC has
two connection requirements:

- Use the LKC’s own bootstrap URL, not the PKC’s bootstrap
  URL or a broker’s IP address.
- Connect over TLS, using `SSL` or `SASL_SSL`. The LKC doesn’t
  accept `PLAINTEXT` or `SASL_PLAINTEXT` connections.

Apart from your PKC’s usual TLS and authentication settings, your
client doesn’t need any LKC-specific configuration.

#### NOTE
If your application uses a non-Java client, such as one built on
librdkafka, confirm that it sends the LKC’s bootstrap hostname as
the TLS Server Name Indication (SNI).

If your organization hasn’t set up DNS for per-LKC hostnames
yet, see the routing approach you chose in the Multi-Tenancy
Overview page for how clients resolve an LKC’s bootstrap URL.



## Step 4: Produce and consume a test message

1. Using the connection details from
   [Step 2](#multi-tenancy-onboard-developer-step-2), list topics
   with a standard Kafka Admin API client or command-line tool. Confirm
   that the list contains only the topics that you have access to
   in this LKC, using their LKC-local names, such as `orders`. None
   of another LKC’s topics should appear.
2. Produce a test message to a topic that you have `DeveloperWrite`
   on. For `kafka-console-producer` usage, see
   [Use the command-line tools](../../get-started/tutorial-multi-broker.md#ak-commands-cheat-sheet).
3. Consume that message from the topic, using a consumer group that you
   have `DeveloperRead` on. For `kafka-console-consumer` usage, see the
   same [command-line tools](../../get-started/tutorial-multi-broker.md#ak-commands-cheat-sheet) page.

<a id="multi-tenancy-onboard-developer-verify"></a>

## Verify LKC isolation and quota enforcement

- Confirm that a client with no role binding on this LKC can
  authenticate, but that `listTopics()` returns an empty set, and
  that a produce or consume attempt fails with an authorization error
  rather than a connection failure.
- If the client exceeds the LKC’s configured quota, confirm that the
  broker throttles it instead of returning an error. The client’s
  throttle metrics become nonzero and its throughput levels off. For a
  producer, check `produce-throttle-time-avg` and
  `produce-throttle-time-max`. For a consumer, check
  `fetch-throttle-time-avg` and `fetch-throttle-time-max`. For more
  information about how the broker enforces quotas, see
  [Monitor and Manage Per-LKC Resource Quotas](manage-tenant-quotas.md#multi-tenancy-manage-tenant-quotas).

## Troubleshooting

<a id="multi-tenancy-onboard-developer-troubleshoot-rbac"></a>

### RBAC scope is too broad or too narrow

- Too broad: If a developer can access resources in an LKC that they
  shouldn’t, check their `ConfluentRolebinding` resources for one
  whose `kafkaClusterRef.kind` is `Kafka` instead of
  `LogicalKafkaCluster`. Delete it and create a replacement scoped to
  the correct LKC, as described in the caution in
  [Step 1](#multi-tenancy-onboard-developer-step-1).
- Too narrow, or no role binding at all: For the expected behavior
  of a client with no matching role binding on this LKC, see
  [Verify LKC isolation and quota enforcement](#multi-tenancy-onboard-developer-verify). If every produce
  attempt fails with `ClusterAuthorizationException` specifically,
  not `TopicAuthorizationException`, the developer likely doesn’t
  have `DeveloperWrite` on any topic in the LKC.
- Role binding doesn’t seem to take effect: Confirm that the LKC
  has finished provisioning.

<a id="multi-tenancy-onboard-developer-connection-errors"></a>

### Connection and authentication errors

The PKC rejects a client that connects to its own bootstrap URL,
connects to a broker’s IP address directly, or connects over
`PLAINTEXT` or `SASL_PLAINTEXT`. For more information, see
[Step 3](#multi-tenancy-onboard-developer-step-3).

A client that uses a malformed or unrecognized LKC ID in its
bootstrap hostname, or the ID of a deactivated LKC, can’t
connect. Confirm that the bootstrap URL you shared in
[Step 2](#multi-tenancy-onboard-developer-step-2) exactly matches
the value your platform operator retrieved when they verified the LKC,
in [Step 5](onboard-a-tenant.md#multi-tenancy-onboard-step-5) of
[Onboard an LKC to a Multi-Tenant Physical Kafka Cluster](onboard-a-tenant.md#multi-tenancy-onboard-a-tenant).

## Related content

- [Onboard an LKC to a Multi-Tenant Physical Kafka Cluster](onboard-a-tenant.md#multi-tenancy-onboard-a-tenant)
- [Monitor and Manage Per-LKC Resource Quotas](manage-tenant-quotas.md#multi-tenancy-manage-tenant-quotas)
- Manage Tenant Access with RBAC
- [Use the command-line tools](../../get-started/tutorial-multi-broker.md#ak-commands-cheat-sheet)
- [Manage RBAC for Confluent Platform Using Confluent for Kubernetes](https://docs.confluent.io/operator/current/co-manage-rbac.html)


