Closed ggmoy-tt closed 2 years ago
Thanks for reporting the issue @ggmoy-tt and providing so many details to help us debug the issue!
Could you switch to 0.4.0
version of TF Provider for Confluent Cloud and reapply your configuration? This way you should be able to see a more descriptive error message (vs just stack trace) and share with us the findings?
Could you double check you set the following env variables:
export CONFLUENT_CLOUD_API_KEY="<cloud_api_key>"
export CONFLUENT_CLOUD_API_SECRET="<cloud_api_secret>"
I re-created the environment, cluster and service account using v0.4.0. Now, the error is the following:
$ terraform apply
confluentcloud_environment.default: Refreshing state... [id=env-3y5do]
confluentcloud_environment.stack_trace: Refreshing state... [id=env-qm5g7]
confluentcloud_service_account.tessitura_integration: Refreshing state... [id=sa-22g2dq]
confluentcloud_service_account.stack_trace: Refreshing state... [id=sa-nvmyx3]
confluentcloud_kafka_cluster.default: Refreshing state... [id=lkc-w7769j]
confluentcloud_kafka_cluster.stack_trace: Refreshing state... [id=lkc-yoowmk]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# confluentcloud_kafka_acl.describe_cluster will be created
+ resource "confluentcloud_kafka_acl" "describe_cluster" {
+ host = "*"
+ http_endpoint = "https://pkc-6ojv2.us-west4.gcp.confluent.cloud:443"
+ id = (known after apply)
+ kafka_cluster = "lkc-yoowmk"
+ operation = "DESCRIBE"
+ pattern_type = "LITERAL"
+ permission = "ALLOW"
+ principal = "User:sa-nvmyx3"
+ resource_name = "kafka-cluster"
+ resource_type = "CLUSTER"
+ credentials {
+ key = (sensitive value)
+ secret = (sensitive value)
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
confluentcloud_kafka_acl.describe_cluster: Creating...
╷
│ Error: 403 Forbidden
│
│ with confluentcloud_kafka_acl.describe_cluster,
│ on stack_trace.tf line 22, in resource "confluentcloud_kafka_acl" "describe_cluster":
│ 22: resource "confluentcloud_kafka_acl" "describe_cluster" {
│
╵
And, as to the environment variables CONFLUENT_CLOUD_API_KEY
and CONFLUENT_CLOUD_API_SECRET
, the are in place. Otherwise, the Terraform provider would not be able to create any resource.
Thanks for sending these details @ggmoy-tt!
So the issue is related to step #3:
confluent api-key create \
--service-account $(terraform output -raw service_account_id) \
--environment $(terraform output -raw environment_id) \
--resource $(terraform output -raw cluster_id)
As of right now, even if the owner of Kafka API Key is a service account (and not a user) and even if its role is OrganizationAdmin
its permissions doesn't "apply" on a cluster level (which is why you're getting 403
for ACL / topic creation) so there're 2 simple options:
confluent api-key create \
--environment $(terraform output -raw environment_id) \
--resource $(terraform output -raw cluster_id)
that will be linked to your account (instead of a service account). Later on, you'll be able to rotate Kafka API Keys by following this note. As a matter of fact, we're working on api_key
TF resource and we'll release a corresponding tutorial / sample TF configs to make things easier.
Let me know if it helps at all.
Thanks for your time, @linouk23!
I think we'll wait for the fix. We don't like the idea of using user accounts because, as stated in the Access Control List documentation, anyone with access to a particular cluster while using the Cloud Console browser has full access to all resources in that cluster (which is the same as having super user access).
Sounds good, I'll keep this issue open and update you as soon as Kafka RBAC goes GA such that your Kafka API Key created with:
confluent api-key create \
--environment $(terraform output -raw environment_id) \
--resource $(terraform output -raw cluster_id)
will stop returning 403
👌
Actually, the command used to create the API Key is the following:
confluent api-key create \
--service-account $(terraform output -raw service_account_id) \
--environment $(terraform output -raw environment_id) \
--resource $(terraform output -raw cluster_id)
Oh right, that's a typo (I meant Kafka API Key owned by a service account with CloudClusterAdmin
role assigned), sorry about that! Here's the updated message:
Sounds good, I'll keep this issue open and update you as soon as Kafka RBAC goes GA such that your Kafka API Key created with:
confluent api-key create \ --service-account $(terraform output -raw service_account_id) \ --environment $(terraform output -raw environment_id) \ --resource $(terraform output -raw cluster_id)
will stop returning
403
👌
@ggmoy-tt fyi Granular role-based access control (RBAC) for Kafka resources has been promoted to General Availability today (see here for more details).
Let me know if it works now.
@linouk23, I'm still receiving a 403
trying to create confluentcloud_kafka_acl
.
@ggmoy-tt, right, what's happening is the owner of your Kafka API Key:
confluent api-key create \
--service-account $(terraform output -raw service_account_id) \
--environment $(terraform output -raw environment_id) \
--resource $(terraform output -raw cluster_id)
is a "fresh" service account without any permissions (let alone "create ACLs" permission).
The expected design would be to have
app-manager
service account that has an admin permissions for a cluster and its Kafka API Key will be used for topic / ACL creation for app-consumer
and app-producer
service accounts.app-consumer
service account -- use its Kafka API Key to consume data from a specific topicapp-producer
service account -- use its Kafka API Key to produce data to a specific topicSo first you need to add a CloudClusterAdmin
role to it (and use it as an app-manager
service account or create a separate app-manager
):
// 'app-manager' service account is required in this configuration to create 'orders' topic and grant ACLs
// to 'app-producer' and 'app-consumer' service accounts.
resource "confluentcloud_service_account" "app-manager" {
display_name = "app-manager"
description = "Service account to manage 'inventory' Kafka cluster"
}
resource "confluentcloud_role_binding" "app-manager-kafka-cluster-admin" {
principal = "User:${confluentcloud_service_account.app-manager.id}"
role_name = "CloudClusterAdmin"
crn_pattern = confluentcloud_kafka_cluster.stack_trace.rbac_crn
}
and then
confluent api-key create \
# or use app-manager's service account ID
--service-account $(terraform output -raw service_account_id) \
--environment $(terraform output -raw environment_id) \
--resource $(terraform output -raw cluster_id)
and then you might need to create a separate app-consumer
service account:
resource "confluentcloud_service_account" "app-consumer" {
display_name = "app-consumer"
description = "Service account to consume from 'X' topic of 'Y' Kafka cluster"
}
resource "confluentcloud_kafka_acl" "describe_cluster" {
kafka_cluster = confluentcloud_kafka_cluster.stack_trace.id
http_endpoint = confluentcloud_kafka_cluster.stack_trace.http_endpoint
resource_type = "CLUSTER"
resource_name = "kafka-cluster"
pattern_type = "LITERAL"
principal = "User:${confluentcloud_service_account.app-consumer.id}"
host = "*"
operation = "DESCRIBE"
permission = "ALLOW"
credentials {
# app-manager's credentials
key = "XXX_api_key_here_XXX"
secret = "XXX_secret_here_XXX"
}
}
Unfortunately api_key
resource isn't ready yet but will be available soon 🤞 so you can't avoid this manual step at the moment. Later on, you'll be able to do it all in a single terraform apply
.
Btw not sure whether it's helpful but just in case here's a complete set of ACLs you might need to create:
// Note that in order to consume from a topic, the principal of the consumer ('app-consumer' service account)
// needs to be authorized to perform 'READ' operation on both Topic and Group resources:
// confluentcloud_kafka_acl.app-consumer-read-on-topic, confluentcloud_kafka_acl.app-consumer-read-on-group.
// https://docs.confluent.io/platform/current/kafka/authorization.html#using-acls
resource "confluentcloud_kafka_acl" "app-consumer-read-on-topic" {
kafka_cluster = confluentcloud_kafka_cluster.basic.id
resource_type = "TOPIC"
resource_name = confluentcloud_kafka_topic.orders.topic_name
pattern_type = "LITERAL"
principal = "User:${confluentcloud_service_account.app-consumer.id}"
operation = "READ"
permission = "ALLOW"
http_endpoint = confluentcloud_kafka_cluster.basic.http_endpoint
credentials {
key = confluentcloud_api_key.app-manager-kafka-api-key.id
secret = confluentcloud_api_key.app-manager-kafka-api-key.secret
}
}
resource "confluentcloud_kafka_acl" "app-consumer-read-on-group" {
kafka_cluster = confluentcloud_kafka_cluster.basic.id
resource_type = "GROUP"
// The existing values of resource_name, pattern_type attributes are set up to match Confluent CLI's default consumer group ID ("confluent_cli_consumer_<uuid>").
// https://docs.confluent.io/confluent-cli/current/command-reference/kafka/topic/confluent_kafka_topic_consume.html
// Update the values of resource_name, pattern_type attributes to match your target consumer group ID.
// https://docs.confluent.io/platform/current/kafka/authorization.html#prefixed-acls
resource_name = "confluent_cli_consumer_"
pattern_type = "PREFIXED"
principal = "User:${confluentcloud_service_account.app-consumer.id}"
operation = "READ"
permission = "ALLOW"
http_endpoint = confluentcloud_kafka_cluster.basic.http_endpoint
credentials {
key = confluentcloud_api_key.app-manager-kafka-api-key.id
secret = confluentcloud_api_key.app-manager-kafka-api-key.secret
}
}
resource "confluentcloud_kafka_acl" "app-producer-write-to-topic" {
kafka_cluster = confluentcloud_kafka_cluster.basic.id
resource_type = "TOPIC"
resource_name = confluentcloud_kafka_topic.orders.topic_name
pattern_type = "LITERAL"
principal = "User:${confluentcloud_service_account.app-producer.id}"
operation = "WRITE"
permission = "ALLOW"
http_endpoint = confluentcloud_kafka_cluster.basic.http_endpoint
credentials {
key = confluentcloud_api_key.app-manager-kafka-api-key.id
secret = confluentcloud_api_key.app-manager-kafka-api-key.secret
}
}
@ggmoy-tt did you have a chance to test it out again?
Yes, I could test it. I confirm that, following your instructions, it is working.
Thanks so much for your help!
I'm closing the issue because the underlying problem is resolved, NPE exception itself will be fixed in the next release 👌
@ggmoy-tt we're very excited to let you know we've just published a new version of TF Provider that includes a fix for this issue among other very exciting improvements: it enables fully automated provisioning of our key Kafka workflows (see the demo) with no more manual intervention and makes it our biggest and most impactful release.
The only gotcha we've renamed it from confluentinc/confluentcloud
to confluentinc/confluent
but we published a migration guide so it should be fairly straightforward. The existing confluentinc/confluentcloud
will be deprecated soon so we'd recommend switching as soon as possible.
New confluentinc/confluent
provider also includes a lot of sample configurations so you won't need to write them from scratch. You can find them here, find a full list of changes here.
Hey Folks,
I'm getting the following stack trace trying to create a Kafka ACL using Confluent Terraform provider v0.5.0:
How to reproduce?
terraform apply
:Using the API Key and Secret from previous command output, add the following code to the Terraform file created in point 1:
Finally, run
terraform apply
again to get the stack trace:Additional information