-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
[feat][fn] PIP-257: Support mounting k8s ServiceAccount for OIDC auth #19888
[feat][fn] PIP-257: Support mounting k8s ServiceAccount for OIDC auth #19888
Conversation
} | ||
|
||
@Override | ||
public void initialize(CoreV1Api coreClient) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method is not meant to be called, I suggest to throw an exception here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Pulsar Function Worker does not call this method. We could probably deprecate now and remove it later, if we want. It is used in another implementation here:
Lines 40 to 45 in 01a4992
default void initialize(CoreV1Api coreClient, byte[] caBytes, | |
java.util.function.Function<Function.FunctionDetails, String> namespaceCustomizerFunc) { | |
setCaBytes(caBytes); | |
setNamespaceProviderFunc(namespaceCustomizerFunc); | |
initialize(coreClient); | |
} |
From an API design perspective, it seems like we only need the initialize
method and could deprecate the setCaBytes
and setNamespaceProviderFunc
methods as well since they are only called in the initialize
method and never outside of the class.
@FieldContext( | ||
doc = "The Kubernetes secret containing the broker's trust certs. If it is not set, the function will not" | ||
+ " use a custom trust store. The secret must already exist in each function's target namespace." | ||
+ " The secret must contain a key named `ca.crt` with the trust certs." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there any expectations about the "format" of the file ?
should we have an entry which describes the format used to create the file ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great question. First, I think I might have needed to use ca.pem
. Would that clear things up?
Second, the current design reads the bytes from the file at this path:
pulsar/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/worker/WorkerConfig.java
Lines 788 to 799 in 9bb3a21
public byte[] getTlsTrustChainBytes() { | |
if (StringUtils.isNotEmpty(getBrokerClientTrustCertsFilePath()) | |
&& Files.exists(Paths.get(getBrokerClientTrustCertsFilePath()))) { | |
try { | |
return Files.readAllBytes(Paths.get(getBrokerClientTrustCertsFilePath())); | |
} catch (IOException e) { | |
throw new IllegalStateException("Failed to read CA bytes", e); | |
} | |
} else { | |
return null; | |
} | |
} |
and that relies on:
pulsar/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/worker/WorkerConfig.java
Lines 615 to 629 in 9bb3a21
@FieldContext( | |
category = CATEGORY_CLIENT_SECURITY, | |
doc = "The path to trusted certificates used by the Pulsar client to authenticate with Pulsar brokers" | |
) | |
private String brokerClientTrustCertsFilePath; | |
public String getBrokerClientTrustCertsFilePath() { | |
// for compatible, if user do not define brokerClientTrustCertsFilePath, we will use tlsTrustCertsFilePath, | |
// otherwise we will use brokerClientTrustCertsFilePath | |
if (StringUtils.isNotBlank(brokerClientTrustCertsFilePath)) { | |
return brokerClientTrustCertsFilePath; | |
} else { | |
return tlsTrustCertsFilePath; | |
} | |
} |
So we do not allow for configuration at the moment, and we expect users to provide the right format already. We can, of course, improve on that design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good stuff!
/pulsarbot rerun-failure-checks |
…worker-k8s-service-account
Codecov Report
@@ Coverage Diff @@
## master #19888 +/- ##
============================================
+ Coverage 71.70% 72.85% +1.15%
- Complexity 31368 31611 +243
============================================
Files 1848 1862 +14
Lines 137151 137453 +302
Branches 15111 15133 +22
============================================
+ Hits 98338 100138 +1800
+ Misses 30904 29357 -1547
- Partials 7909 7958 +49
Flags with carried forward coverage won't be shown. Click here to find out more.
|
Hi @michaeljmarshall thanks for bringing this feature! I see this PR is labeled with doc-required, for these new configurations, do we need to add some instructions and usage examples to function docs? If so, feel free to add docs and ping me review. Thank you! |
…20144) PIP: #19849 ### Motivation The new `KubernetesServiceAccountTokenAuthProvider` introduced by #19888 does not configure the authentication for download because there is an unnecessary check that the `getFunctionAuthenticationSpec` is not `null`. Given that we do not use this spec in creating the auth, it is unnecessary to use here. Further, when we construct the function's authentication, we do not have this null check. See: https://github.com/apache/pulsar/blob/ec102fb024a6ea2b195826778300f20e330dff06/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/RuntimeUtils.java#L411-L417 ### Modifications * Update the `KubernetesRuntime` to add authentication params to the download command when provided. ### Verifying this change A new test is added. ### Documentation - [x] `doc-not-needed` ### Matching PR in forked repository PR in forked repository: Skipping for this trivial PR
…apache#19888) PIP: apache#19771 In order to make OIDC work with functions, we must give them a way to authenticate with the broker using tokens that are able to be validated by an using an Authorization Server. This PR introduces the `KubernetesServiceAccountAuthProvider`. * Create an `KubernetesServiceAccountAuthProvider` implementation. It adds a service account token volume projection as defined in the k8s docs [here](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-token-volume-projection). The implementation provides a way to specify the expiration time that the token will receive. * Instead of creating a secret with the broker's trusted `ca.crt` in it, this new `KubernetesServiceAccountAuthProvider` expects a secret to already exist with the `ca.crt`. The major advantage for this implementation is that when the `ca.crt` is rotated, we can refresh it (assuming the client is configured to observe the updated file). * Add support for specifying the token's expiration and audience. * One point of divergence from the `KubernetesSecretsTokenAuthProvider` implementation is that I did not provide a way for functions to authenticate as the anonymous role. It seems like a stretch that functions would use such authentication because it will not be multi-tenant. However, if that is a concern, we can add the support. * The feature will be configured with the following yaml: ```yaml functionRuntimeFactoryConfigs: kubernetesFunctionAuthProviderConfig: brokerClientTrustCertsSecretName: "secret-name" serviceAccountTokenExpirationSeconds: 3600 serviceAccountTokenAudience: "pulsar-cluster-audience" ``` I verified the correctness of the code with unit tests. I'll verify the integration with k8s once we've determined this PR's design is correct. This adds new configuration options to the function worker. - [x] `doc-required` PR in forked repository: #36 (cherry picked from commit 067e3c0)
…20144) PIP: #19849 ### Motivation The new `KubernetesServiceAccountTokenAuthProvider` introduced by #19888 does not configure the authentication for download because there is an unnecessary check that the `getFunctionAuthenticationSpec` is not `null`. Given that we do not use this spec in creating the auth, it is unnecessary to use here. Further, when we construct the function's authentication, we do not have this null check. See: https://github.com/apache/pulsar/blob/ec102fb024a6ea2b195826778300f20e330dff06/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/RuntimeUtils.java#L411-L417 ### Modifications * Update the `KubernetesRuntime` to add authentication params to the download command when provided. ### Verifying this change A new test is added. ### Documentation - [x] `doc-not-needed` ### Matching PR in forked repository PR in forked repository: Skipping for this trivial PR (cherry picked from commit 4f2b8e2)
…pache#20144) PIP: apache#19849 ### Motivation The new `KubernetesServiceAccountTokenAuthProvider` introduced by apache#19888 does not configure the authentication for download because there is an unnecessary check that the `getFunctionAuthenticationSpec` is not `null`. Given that we do not use this spec in creating the auth, it is unnecessary to use here. Further, when we construct the function's authentication, we do not have this null check. See: https://github.com/apache/pulsar/blob/ec102fb024a6ea2b195826778300f20e330dff06/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/RuntimeUtils.java#L411-L417 ### Modifications * Update the `KubernetesRuntime` to add authentication params to the download command when provided. ### Verifying this change A new test is added. ### Documentation - [x] `doc-not-needed` ### Matching PR in forked repository PR in forked repository: Skipping for this trivial PR (cherry picked from commit 4f2b8e2)
Docs added here: apache/pulsar-site#570 |
PIP: #19771
Motivation
In order to make OIDC work with functions, we must give them a way to authenticate with the broker using tokens that are able to be validated by an using an Authorization Server. This PR introduces the
KubernetesServiceAccountAuthProvider
.Modifications
Create an
KubernetesServiceAccountAuthProvider
implementation. It adds a service account token volume projection as defined in the k8s docs here. The implementation provides a way to specify the expiration time that the token will receive.Instead of creating a secret with the broker's trusted
ca.crt
in it, this newKubernetesServiceAccountAuthProvider
expects a secret to already exist with theca.crt
. The major advantage for this implementation is that when theca.crt
is rotated, we can refresh it (assuming the client is configured to observe the updated file).Add support for specifying the token's expiration and audience.
One point of divergence from the
KubernetesSecretsTokenAuthProvider
implementation is that I did not provide a way for functions to authenticate as the anonymous role. It seems like a stretch that functions would use such authentication because it will not be multi-tenant. However, if that is a concern, we can add the support.The feature will be configured with the following yaml:
Verifying this change
I verified the correctness of the code with unit tests. I'll verify the integration with k8s once we've determined this PR's design is correct.
Does this pull request potentially affect one of the following parts:
This adds new configuration options to the function worker.
Documentation
doc-required
Matching PR in forked repository
PR in forked repository: michaeljmarshall#36