Skip to content
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

Supply a custom Java Security File #259

Closed
tuckeremulls opened this issue Feb 24, 2023 · 10 comments
Closed

Supply a custom Java Security File #259

tuckeremulls opened this issue Feb 24, 2023 · 10 comments
Labels
type:question A user question

Comments

@tuckeremulls
Copy link

tuckeremulls commented Feb 24, 2023

Hello team, I am looking for a way to set the networkaddress.cache.ttl java security property for a Spring Boot app that we containerize with buidpacks without setting it in application code.

Unfortunately this property cannot just be set by passing it as a JVM argument through the $JAVA_TOOL_OPTIONS environment variable supplied by bellsoft-liberica. It must be set in the java.security file. Is there any way to supply a custom file with properties that can override the java.security file of the jdk that bellsoft-liberica builds into the image? Does this functionality already exist or would it be a new feature?

Describe the Enhancement

Some method of supplying a file to override certain properties of the jdk's java.security file.

Possible Solution

Provided through an environment variable possibly for ease of access.

Motivation

This specific property networkaddress.cache.ttl can be altered to disable DNS caching, so that if DNS rules change, an application will be able to pick up the new resolutions rather than using an older incorrect one. Beyond just this property, there are many others that can be customized in the java.security file that may serve important usage to developers containerizing their apps.

@dmikusa
Copy link
Contributor

dmikusa commented Mar 6, 2023

Sorry for the delay. I had to look some of this up because we don't have it documented. Apologizes for that.

  1. If your DNS configuration is set to a link local unicast IP then it will automatically disable DNS caching. The helper, which runs before your app starts up at runtime, will check this and adjust the java.security file setting networkaddress.cache.ttl to 0. It does not support arbitrarily disabling DNS caching, but that is possibly something we could add.

  2. There is support in the buildpack for adding additional security providers. Not what you're looking for here, but it's an advanced feature that one might need to write to java.security file to accomplish and is already supported in the buildpack.

  3. The buildpack is setting an env variable called JAVA_SECURITY_PROPERTIES that points to the java.security file which is configured. This file is appended to the default settings file provided by the JVM as is the JVM's default behavior, so the buildpack makes it an empty file at build-time. Some other buildpack features like 1.) above may write to this file but it's often empty. We then set -Djava.security.properties=/same/path to point to the same file as JAVA_SECURITY_PROPERTIES. You could try adding another -Djava.security.properties=/your/file argument to JAVA_TOOL_OPTIONS. I didn't try this, so it may not work but often the JVM will take the last property (it seems to read left-to-right) to be set when there are multiple of the same property set, so it's possible that your value may override the buildpack just because the JVM reads it last. It's also possible, again, I didn't check that the JVM might support this property being set multiple times (since it is appending its contents to the default security file), although I'm skeptical of that. Anyway, if you have a chance to try this and report your findings we can go from there.


My initial thought is to not allow generically modifying the security file, at least not having a way in the buildpack to do it, but that we could enable specific use cases like disabling DNS, adding security providers, or whatever other concrete use cases come up. My rationale is a.) it's easy to mess things up in this file and that can result in extra support burden for buildpacks b.) it's nice to have this capability as a developer, but if you switch perspective to a sysadmin/infosec point of view, maybe it's not so great, and having controlled/limited access is more appealing. Anyway, I'm certainly open to hearing more on this topic though.

@dmikusa dmikusa added the type:enhancement A general enhancement label Mar 6, 2023
@gudatcomputers
Copy link

Sorry for the delay. I had to look some of this up because we don't have it documented. Apologizes for that.

1. If your DNS configuration is set to a [link local unicast IP](https://en.wikipedia.org/wiki/Link-local_address) then it will automatically disable DNS caching. The helper, which runs before your app starts up at runtime, will check this and [adjust the `java.security` file setting `networkaddress.cache.ttl` to 0](https://github.com/paketo-buildpacks/libjvm/blob/main/helper/link_local_dns.go#L56-L59). It does not support arbitrarily disabling DNS caching, but that is possibly something we could add.

2. There is support in the buildpack for adding additional security providers. Not what you're looking for here, but it's an advanced feature that one might need to write to `java.security` file to accomplish and is already supported in the buildpack.

3. The buildpack is setting an env variable called `JAVA_SECURITY_PROPERTIES` that points to the `java.security` file which is configured. This file is appended to the default settings file provided by the JVM as is the JVM's default behavior, so the buildpack makes it an empty file at build-time. Some other buildpack features like 1.) above may write to this file but it's often empty. We then set `-Djava.security.properties=/same/path` to point to the same file as `JAVA_SECURITY_PROPERTIES`. You could try adding another `-Djava.security.properties=/your/file` argument to `JAVA_TOOL_OPTIONS`. I didn't try this, so it may not work but often the JVM will take the last property (it seems to read left-to-right) to be set when there are multiple of the same property set, so it's possible that your value may override the buildpack just because the JVM reads it last. It's also possible, again, I didn't check that the JVM might support this property being set multiple times (since it is appending its contents to the default security file), although I'm skeptical of that. Anyway, if you have a chance to try this and report your findings we can go from there.

My initial thought is to not allow generically modifying the security file, at least not having a way in the buildpack to do it, but that we could enable specific use cases like disabling DNS, adding security providers, or whatever other concrete use cases come up. My rationale is a.) it's easy to mess things up in this file and that can result in extra support burden for buildpacks b.) it's nice to have this capability as a developer, but if you switch perspective to a sysadmin/infosec point of view, maybe it's not so great, and having controlled/limited access is more appealing. Anyway, I'm certainly open to hearing more on this topic though.

Hey, developer here... I'll say that our concrete use case is configuring our workload to run with BouncyCastle on the JCA/JSSE side. Without a facility to hook this up we have a much harder time moving toward FIPS compliance

@gudatcomputers
Copy link

There is support in the buildpack for adding additional security providers. Not what you're looking for here, but it's an advanced feature that one might need to write to java.security file to accomplish and is already supported in the buildpack.

@dmikusa since it's not well documented can you point me in the direction of the code responsible for this? I'd like to see how we might accomplish

@dmikusa
Copy link
Contributor

dmikusa commented Mar 7, 2023

Hey, developer here... I'll say that our concrete use case is configuring our workload to run with BouncyCastle on the JCA/JSSE side. Without a facility to hook this up we have a much harder time moving toward FIPS compliance

You're in luck. The buildpack can do this right now. It is not documented, apologize for that. We've had a story to document for a while and it keeps slipping.

SECURITY_PROVIDERS is the way to add something like Bouncy Castle. See code here.

@dmikusa dmikusa transferred this issue from paketo-buildpacks/bellsoft-liberica Mar 7, 2023
@gudatcomputers
Copy link

gudatcomputers commented Mar 7, 2023

Hey, developer here... I'll say that our concrete use case is configuring our workload to run with BouncyCastle on the JCA/JSSE side. Without a facility to hook this up we have a much harder time moving toward FIPS compliance

You're in luck. The buildpack can do this right now. It is not documented, apologize for that. We've had a story to document for a while and it keeps slipping.

SECURITY_PROVIDERS is the way to add something like Bouncy Castle. See code here.

super helpful thanks.. I think the code will break for my specific use case because it expects SECURITY_PROVIDERS to be space delimited. and we need to set 2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS which would break and not properly set fips:BCFIPS unless I'm not reading properly. A potential solution is to swap to a comma delimiter. I realize that's a breaking change. Would you be open to this kind of PR?

This is under the assumption that a SECURITY_PROVIDERS value should look like 1=myFirstProvider 2=mySecondPRovider effectively taking the lines from a java.security.properties file and putting them into a single value with space delimiters

@dmikusa
Copy link
Contributor

dmikusa commented Mar 7, 2023

This is under the assumption that a SECURITY_PROVIDERS value should look like 1=myFirstProvider 2=mySecondPRovider effectively taking the lines from a java.security.properties file and putting them into a single value with space delimiters

It is space-delimited, but it should be <position>|<provider>, at least last time I looked.

For example, if you set security providers: 1|FOXTROT|2|DELTA ECHO

You end up with the following java.security file:

security.provider.1=FOXTROT
security.provider.2=DELTA
security.provider.3=ECHO

I think the code will break for my specific use case because it expects SECURITY_PROVIDERS to be space delimited. and we need to set 2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider fips:BCFIPS which would break and not properly set fips:BCFIPS unless I'm not reading properly

I think you're right. I was digging through my notes, cause I've set Bouncy Castle up with this before and this is what I had previously done.

  1. In my application, I added src/main/resources/java-security.properties. In it put the following, but adjust to your needs.

    security.provider.1=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
    security.provider.2=com.sun.net.ssl.internal.ssl.Provider BCFIPS
    security.provider.3=sun.security.provider.Sun 
  2. Add the Bouncy Castle FIPS JAR to my project.

    <dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bc-fips</artifactId>
      <version>1.0.2.1</version>
    </dependency>
  3. (Optional) Check it's all working. Run ./mvnw package. The JAR will be packaged within your app.

  4. Build an image. Run pack build maven -e BPE_DELIM_JAVA_TOOL_OPTIONS=' ' -e BPE_APPEND_JAVA_TOOL_OPTIONS='-Djava.security.properties=/workspace/BOOT-INF/classes/java-security.properties'.

    The second two arguments will set a JAVA_TOOL_OPTIONS env variable on the image. It appends -Djava.security.properties and points to the file we created in the first step. This isn't the normal way you'd do this, but there is a specific reason why we have to at the moment to make this work (I couldn't find what I was referencing in my notes, but it might be your point above about space delimiters).

  5. Run with docker run --rm -it -p 8080:8080 apps/maven.

A potential solution is to swap to a comma delimiter. I realize that's a breaking change. Would you be open to this kind of PR?

I don't think we could change from space to comma as that could break apps out there, but we could accept a PR that makes the delimiter configurable with a space being the default. You could then override that with a comma. I think that would be sufficient to make things work with SECURITY_PROVIDERS.

@tuckeremulls
Copy link
Author

  1. The buildpack is setting an env variable called JAVA_SECURITY_PROPERTIES that points to the java.security file which is configured. This file is appended to the default settings file provided by the JVM as is the JVM's default behavior, so the buildpack makes it an empty file at build-time. Some other buildpack features like 1.) above may write to this file but it's often empty. We then set -Djava.security.properties=/same/path to point to the same file as JAVA_SECURITY_PROPERTIES. You could try adding another -Djava.security.properties=/your/file argument to JAVA_TOOL_OPTIONS.

I want to attempt this but just am not sure what filepath I would provide to -Djava.security.properties. Let's say I place a java.security file in src/main/resources, then what would the filepath to that file be since buildpacks is running the packaged jar in a container?

@gudatcomputers
Copy link

  1. The buildpack is setting an env variable called JAVA_SECURITY_PROPERTIES that points to the java.security file which is configured. This file is appended to the default settings file provided by the JVM as is the JVM's default behavior, so the buildpack makes it an empty file at build-time. Some other buildpack features like 1.) above may write to this file but it's often empty. We then set -Djava.security.properties=/same/path to point to the same file as JAVA_SECURITY_PROPERTIES. You could try adding another -Djava.security.properties=/your/file argument to JAVA_TOOL_OPTIONS.

I want to attempt this but just am not sure what filepath I would provide to -Djava.security.properties. Let's say I place a java.security file in src/main/resources, then what would the filepath to that file be since buildpacks is running the packaged jar in a container?

So this is what I'm doing today, and it is HIGHLY dependent on how your deployed environment works. because that path to the java.security file is going to be a relative path. That is relative to the pwd of the process that is running your app. In my case it was a directory above where I expected... so I had to know the relative path on disk and set it at build time based on environment variables only available on CI. I can confirm this works in terms of enabling the custom java.security file

@dmikusa
Copy link
Contributor

dmikusa commented Mar 9, 2023

I want to attempt this but just am not sure what filepath I would provide to -Djava.security.properties. Let's say I place a java.security file in src/main/resources, then what would the filepath to that file be since buildpacks is running the packaged jar in a container?

@tuckeremulls See this note #259 (comment) it's doing exactly that. Step 4.) is where it sets the path. It's using /workspace/... which is where your app files end up in the run image. Just note that the remainder of the path is the location of the file within the app's JAR not your source code.

Relative paths would work as well. The working directory for an app is going to be /workspace/.

@tuckeremulls
Copy link
Author

tuckeremulls commented Mar 27, 2023

@tuckeremulls See this note #259 (comment) it's doing exactly that. Step 4.) is where it sets the path. It's using /workspace/... which is where your app files end up in the run image. Just note that the remainder of the path is the location of the file within the app's JAR not your source code.

Relative paths would work as well. The working directory for an app is going to be /workspace/.

I can confirm that this works when using the maven build-image goal and you have a custom security file in src/main/resources! I supply a custom java security file by specifying:

<env>
    <BPE_APPEND_JAVA_TOOL_OPTIONS>-Djava.security.properties=/workspace/BOOT-INF/classes/ENTER_YOUR_CUSTOM_JAVA_SECURITY_FILENAME</BPE_APPEND_JAVA_TOOL_OPTIONS>
    <BPE_DELIM_JAVA_TOOL_OPTIONS xml:space="preserve"> </BPE_DELIM_JAVA_TOOL_OPTIONS>
</env>

in the spring-boot-maven-plugin configuration in the pom.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:question A user question
Projects
None yet
Development

No branches or pull requests

3 participants