Question
Our environment requires that each Apache Flink deployment has the least privileges it needs, and each deployment should not be able to assume privileges defined for any other Apache Flink deployment. How can I enforce fine-grained access control for Apache Flink deployments using Kubernetes Service Accounts?
Answer
Note: This section applies to Flink 1.16 with Ververica Platform 2.10 or later.
Overview
In the cases where one can manage the access control mechanism via service accounts [1], such as cloud providers (i.e., AWS) and their respective cloud resources (i.e., Kinesis), service accounts can be utilised to enforce fine grained access control. Previously, we have explored [2] a third party tool (Kyverno) in order to leverage custom policies. Ververica Platform 2.10 and later also has a mechanism to introduce an optional enforcement for a one-to-one mapping in between the Apache Flink deployment/session cluster name and the service account name [3]. Therefore, without needing an additional tool for the service account validation, Ververica Platform’s `serviceAccountNameEnforcementEnabled` feature can be used to enforce fine grained access control.
Ververica Platform Setup
For each Apache Flink deployment/session cluster, a user can specify which service account to be used both for the job manager and the task manager separately. Initially, there is no validation mechanism done by the Ververica Platform. However, once the `serviceAccountNameEnforcementEnabled` flag is set to true while installing the Ververica Platform, Ververica Platform will validate a deployment/session cluster comparing to the name of the service account if the service account name is specified.
As a rule for the validation, Ververica Platform will only consider a deployment/session cluster valid if the service account name matches the pattern deployment-${namespace}-${deploymentName} for the deployments and session-${namespace}-${sessionClusterName} for the session clusters where the ${namespace} corresponds to the Ververica Platform namespace containing the deployment/session cluster. Otherwise, it will fail to accept the change to a deployment’s/session cluster’s configuration.
This validation ensures that each Apache Flink deployment/session cluster will be enforced with the fine grained access control by having a one-to-one mapping with the deployment/session cluster name and the service account name, considering the deployment/session cluster names are unique given a Ververica Platform namespace. The exact feature flag to enable while installing the Ververica Platform is as follows:
vvp:
### Enable Service Account enforcement
accessControl:
serviceAccountNameEnforcementEnabled: true
Application Setup
In order to test a simple use case, one can simply use the following snippets to create a dummy producer (datagen) to consumer (blackhole) SQL deployment. We will also need to create the necessary role based access control on the Kubernetes level so that our deployment will be able to make use of the service account.
First run `kubectl apply -f rbac.yaml` where the content of the `rbac.yaml` file is as follow in order to prepare the service account that is to be used by the deployment. Keep in mind that this deployment will use the` default` as the Ververica Platform namespace while using `vvp-jobs` as the Kubernetes namespace.
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: deployment-default-producer-to-consumer
namespace: vvp-jobs
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployment-default-producer-to-consumer
namespace: vvp-jobs
rules:
- apiGroups: [ "" ]
resources: [ "configmaps"]
verbs: [ "create", "delete", "get", "list", "patch", "update", "watch" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: deployment-default-producer-to-consumer
namespace: vvp-jobs
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: deployment-default-producer-to-consumer
subjects:
- kind: ServiceAccount
name: deployment-default-producer-to-consumer
namespace: vvp-jobs
Secondly, run the following scripts in order to register the consumer and producer tables, as well as the SQL deployment.
curl -X POST "http://localhost:8080/sql/v1beta1/namespaces/default/sqlscripts:execute?catalog=vvp&database=default" -H "accept: application/json" -H "Content-Type: application/json" --data @consumer_table.json
curl -X POST "http://localhost:8080/sql/v1beta1/namespaces/default/sqlscripts:execute?catalog=vvp&database=default" -H "accept: application/json" -H "Content-Type: application/json" --data @producer_table.json
curl -X POST "http://localhost:8080/api/v1/namespaces/default/deployments" -H "accept: application/json" -H "Content-Type: application/json" --data @producer-to-consumer.json
where the content of the payloads are as following:
#tabs
## consumer_table.json
{
"statement": "CREATE TABLE `vvp`.`default`.`consumer` (`name` STRING) WITH ('connector' = 'blackhole');"
}
## producer_table.json
{
"statement": "CREATE TABLE `vvp`.`default`.`producer` (`name` STRING) WITH ('connector' = 'datagen', 'rows-per-second' = '10');"
}
## producer-to-consumer.json
{
"apiVersion": "v1",
"kind": "Deployment",
"metadata": {
"name": "producer-to-consumer"
},
"spec": {
"deploymentTargetName": "vvp-jobs",
"template": {
"spec": {
"artifact": {
"kind": "SQLSCRIPT",
"sqlScript": "INSERT INTO consumer SELECT * FROM producer;"
},
"kubernetes": {
"jobManagerPodTemplate": {
"spec": {
"containers": [],
"serviceAccountName": "deployment-default-producer-to-consumer"
}
},
"taskManagerPodTemplate": {
"spec": {
"containers": [],
"serviceAccountName": "deployment-default-producer-to-consumer"
}
}
}
}
}
}
}
#--
Now, one can try to change the service account name on the deployment and try to save the changes. There will be a message stating the validation failed for the service account name as in the following:
Related Information
[1] AWS doc: Introducing fine-grained IAM roles for service accounts
[2] VVP KB article: How to Enforce Fine-Grained Access Control for Apache Flink Deployments on AWS (VVP 2.9 or earlier)
[3] VVP doc: Merge Rules and System Reserved Fields