-
Notifications
You must be signed in to change notification settings - Fork 2k
feat: add support for FIPS bouncy castle #3590 #3595
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
Conversation
|
Welcome @robhafner! |
Thanks for the PR. Instead of this approach, I think I would prefer to keep the default and then use some sort of |
So we have the bc-fips-1.0.2.4.jar on our classpath and it has a META-INF/services/java.security.Provider file with the "org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider" class defined in it. I would expect that file would trigger loading the required fips provider. It's a bit unclear to me if there is a security risk with attempting to load the non fips provider class as well (in the event that the non fips provider class ended up on our classpath). We've chosen to only support FIPS compliant algorithms in our software. This change is based on what we noticed in another project with respect to how they check the provider class. |
ok, how about something like static {
String className = System.getProperty("io.kubernetes.SecurityProvider");
if (className == null) {
className == <non-fips-provider>;
}
Security.Provider = Class.forName(className);
} |
Thinking about this a bit more, would the right thing to do in this case be to let the BouncyCastle jars register the provider via the Java Service Provider Interface (SPI)?
For example:
- The bc-fips-1.0.2.4.jar defines a META-INF/services/java.security.Provider file with a value of org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider.
- The bcprov-jdk18on-1.76.jar defines a META-INF/services/java.security.Provider file with the following values:
org.bouncycastle.jce.provider.BouncyCastleProvider
org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider
Note, the bcprov-jdk18on-1.76.jar is pulled in when adding the following dependency in gradle.
implementation("io.kubernetes:client-java:19.0.1")
We currently exclude the non-fips bouncy castle jars in our build.gradle file like this:
implementation("io.kubernetes:client-java:19.0.1") {
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk18on'
exclude group: 'org.bouncycastle', module: 'bcprov-jdk18on'
exclude group: 'org.bouncycastle', module: 'bcutil-jdk18on
}
And add the following dependencies to include the fips version.
// bouncycastle FIPS jars
implementation "org.bouncycastle:bc-fips"
implementation "org.bouncycastle:bcpkix-fips"
Given this, I think a better fix might be to remove the static block of code initializing the provider in the Kubernetes Java client and let the bouncy castles jars perform the registration via Java SPI. This would allow a user of the Kubernetes Java Client to pick the bouncy castle provider they wish to use based on the jars that they include in their project.
From: Brendan Burns ***@***.***>
Date: Thursday, July 25, 2024 at 5:17 PM
To: kubernetes-client/java ***@***.***>
Cc: Robert Hafner ***@***.***>, Mention ***@***.***>
Subject: Re: [kubernetes-client/java] feat: add support for FIPS bouncy castle #3590 (PR #3595)
ok, how about something like
static {
String className = System.getProperty("io.kubernetes.SecurityProvider");
if (className == null) {
className == <non-fips-provider>;
}
Security.Provider = Class.forName(className);
}
—
Reply to this email directly, view it on GitHub<#3595 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AB3UX6AMVURFXILWQD3UVWTZOFTPDAVCNFSM6AAAAABLOV2LU6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENJRGQYTCNRZGA>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Forgot to mention, the kubernetes java client may need to invoke the ServiceLoader to load the provider classes when removing the static code block.
ServiceLoader<Provider> services = ServiceLoader.load(java.security.Provider.class);
for (Provider service : services) {
logger.info("Found: " + service.getName());
}
Based on the documentation I see here:
https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html
From: Robert Hafner ***@***.***>
Date: Wednesday, July 31, 2024 at 9:01 AM
To: kubernetes-client/java ***@***.***>, kubernetes-client/java ***@***.***>
Cc: Mention ***@***.***>
Subject: Re: [kubernetes-client/java] feat: add support for FIPS bouncy castle #3590 (PR #3595)
Thinking about this a bit more, would the right thing to do in this case be to let the BouncyCastle jars register the provider via the Java Service Provider Interface (SPI)?
For example:
- The bc-fips-1.0.2.4.jar defines a META-INF/services/java.security.Provider file with a value of org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider.
- The bcprov-jdk18on-1.76.jar defines a META-INF/services/java.security.Provider file with the following values:
org.bouncycastle.jce.provider.BouncyCastleProvider
org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider
Note, the bcprov-jdk18on-1.76.jar is pulled in when adding the following dependency in gradle.
implementation("io.kubernetes:client-java:19.0.1")
We currently exclude the non-fips bouncy castle jars in our build.gradle file like this:
implementation("io.kubernetes:client-java:19.0.1") {
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk18on'
exclude group: 'org.bouncycastle', module: 'bcprov-jdk18on'
exclude group: 'org.bouncycastle', module: 'bcutil-jdk18on
}
And add the following dependencies to include the fips version.
// bouncycastle FIPS jars
implementation "org.bouncycastle:bc-fips"
implementation "org.bouncycastle:bcpkix-fips"
Given this, I think a better fix might be to remove the static block of code initializing the provider in the Kubernetes Java client and let the bouncy castles jars perform the registration via Java SPI. This would allow a user of the Kubernetes Java Client to pick the bouncy castle provider they wish to use based on the jars that they include in their project.
From: Brendan Burns ***@***.***>
Date: Thursday, July 25, 2024 at 5:17 PM
To: kubernetes-client/java ***@***.***>
Cc: Robert Hafner ***@***.***>, Mention ***@***.***>
Subject: Re: [kubernetes-client/java] feat: add support for FIPS bouncy castle #3590 (PR #3595)
ok, how about something like
static {
String className = System.getProperty("io.kubernetes.SecurityProvider");
if (className == null) {
className == <non-fips-provider>;
}
Security.Provider = Class.forName(className);
}
—
Reply to this email directly, view it on GitHub<#3595 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AB3UX6AMVURFXILWQD3UVWTZOFTPDAVCNFSM6AAAAABLOV2LU6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENJRGQYTCNRZGA>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
I think we need to make sure that this works without anyone doing anything special. I'm worried that if we don't explicitly load the provider that it won't be as easy for the users to use the client. I want it to be feasible for FIPS users to change their providers, but I don't want to make it harder for the average user. |
I agree with you with respect to it being easy and the user shouldn’t have to anything special.
I found this doc which suggests a way to dynamically load the providers using Java SPI.
https://docs.oracle.com/en/java/javase/11/security/howtoimplaprovider.html#GUID-FB9C6DB2-DE9A-4EFE-89B4-C2C168C5982D
Relevant section from the doc below:
Alternatively, you can register providers dynamically. To do so, a program (such as your test program, to be written in Step 9: Write and Compile Your Test Programs<https://docs.oracle.com/en/java/javase/11/security/howtoimplaprovider.html#GUID-C6054169-FE6E-4837-B2BD-382DFEB955C0>) call either the addProvider or insertProviderAt method in the Securityclass:
ServiceLoader<Provider> sl = ServiceLoader.load(java.security.Provider.class);
for (Provider p : sl) {
System.out.println(p);
if (p.getName().equals("MyProvider")) {
Security.addProvider(p);
}
}
I’ll try updating SSLUtils.java in the following manner. Assuming it does, I’ll update my PR.
public class SSLUtils {
private static final Logger log = LoggerFactory.getLogger(SSLUtils.class);
static {
ServiceLoader<Provider> services = ServiceLoader.load(java.security.Provider.class);
for (Provider service : services) {
log.info("Found security provider: " + service.getName());
Security.addProvider(service);
}
}
From: Brendan Burns ***@***.***>
Date: Wednesday, July 31, 2024 at 2:55 PM
To: kubernetes-client/java ***@***.***>
Cc: Robert Hafner ***@***.***>, Mention ***@***.***>
Subject: Re: [kubernetes-client/java] feat: add support for FIPS bouncy castle #3590 (PR #3595)
I think we need to make sure that this works without anyone doing anything special. I'm worried that if we don't explicitly load the provider that it won't be as easy for the users to use the client.
I want it to be feasible for FIPS users to change their providers, but I don't want to make it harder for the average user.
—
Reply to this email directly, view it on GitHub<#3595 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AB3UX6CT4RDQYEEEHCJ6TI3ZPEXHVAVCNFSM6AAAAABLOV2LU6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENRRGE4TKNZVGM>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Dynamically load security providers using the Java Service Provider Interface. This allows the user to pick the provider based upon the dependencies it has on its classpath.
I’ve updated the PR with the logic described in my last message. This logic works fine in my test environment. Assuming it provides the simplicity and flexibility that you are looking for I think we can move forward with it.
From: Robert Hafner ***@***.***>
Date: Wednesday, July 31, 2024 at 4:00 PM
To: kubernetes-client/java ***@***.***>, kubernetes-client/java ***@***.***>
Cc: Mention ***@***.***>
Subject: Re: [kubernetes-client/java] feat: add support for FIPS bouncy castle #3590 (PR #3595)
I agree with you with respect to it being easy and the user shouldn’t have to anything special.
I found this doc which suggests a way to dynamically load the providers using Java SPI.
https://docs.oracle.com/en/java/javase/11/security/howtoimplaprovider.html#GUID-FB9C6DB2-DE9A-4EFE-89B4-C2C168C5982D
Relevant section from the doc below:
Alternatively, you can register providers dynamically. To do so, a program (such as your test program, to be written in Step 9: Write and Compile Your Test Programs<https://docs.oracle.com/en/java/javase/11/security/howtoimplaprovider.html#GUID-C6054169-FE6E-4837-B2BD-382DFEB955C0>) call either the addProvider or insertProviderAt method in the Securityclass:
ServiceLoader<Provider> sl = ServiceLoader.load(java.security.Provider.class);
for (Provider p : sl) {
System.out.println(p);
if (p.getName().equals("MyProvider")) {
Security.addProvider(p);
}
}
I’ll try updating SSLUtils.java in the following manner. Assuming it does, I’ll update my PR.
public class SSLUtils {
private static final Logger log = LoggerFactory.getLogger(SSLUtils.class);
static {
ServiceLoader<Provider> services = ServiceLoader.load(java.security.Provider.class);
for (Provider service : services) {
log.info("Found security provider: " + service.getName());
Security.addProvider(service);
}
}
From: Brendan Burns ***@***.***>
Date: Wednesday, July 31, 2024 at 2:55 PM
To: kubernetes-client/java ***@***.***>
Cc: Robert Hafner ***@***.***>, Mention ***@***.***>
Subject: Re: [kubernetes-client/java] feat: add support for FIPS bouncy castle #3590 (PR #3595)
I think we need to make sure that this works without anyone doing anything special. I'm worried that if we don't explicitly load the provider that it won't be as easy for the users to use the client.
I want it to be feasible for FIPS users to change their providers, but I don't want to make it harder for the average user.
—
Reply to this email directly, view it on GitHub<#3595 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AB3UX6CT4RDQYEEEHCJ6TI3ZPEXHVAVCNFSM6AAAAABLOV2LU6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENRRGE4TKNZVGM>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Thanks for digging in here. Assuming tests pass, this looks good to me. |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: brendandburns, robhafner The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
hi, two questions if I may
So I have 3 providers, nothing more or less. I used this small code snippet: `public static void listProviders() {
And the result is kind of surprising: Process finished with exit code 0 Which makes me think that the fix you made is not going to work because that loop is returning something else than expected, or do I missed something here? In that context may I interest you in the netty solution to the problem? |
I think that you need to make sure that those other providers are not in your classpath. |
Prefer FIPS version of bouncy castle if available. Otherwise, fallback to non FIPS version.