feat(inputs.x509_cert): Add support for JKS and PKCS#12 keystores#16508
Conversation
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
|
@paulojmdias please check the linter issues. You can reproduce them locally using |
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Fixed 🙌 |
srebhan
left a comment
There was a problem hiding this comment.
Thanks for your contribution @paulojmdias! This is very much appreciated! I do have some comments in the code...
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
srebhan
left a comment
There was a problem hiding this comment.
@paulojmdias some more comments...
| err = jks.Store(output, []byte("test-password")) | ||
| require.NoError(t, err) | ||
|
|
||
| return "jks://" + jksPath |
There was a problem hiding this comment.
This doesn't work on Windows, you should do
| return "jks://" + jksPath | |
| jksPath = filepath.ToSlash(jksPath) | |
| if !strings.HasPrefix(jksPath, "/") { | |
| jksPath = "/" + jksPath | |
| } | |
| return "jks://" + jksPath |
There was a problem hiding this comment.
Fixed also pkcs12Path
There was a problem hiding this comment.
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
…keystore_cert Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
srebhan
left a comment
There was a problem hiding this comment.
Thanks @paulojmdias, this looks really nice already. Some more comments regarding the test code but we are almost there.
| if runtime.GOOS == "windows" { | ||
| jksPath = strings.TrimPrefix(jksPath, "/") | ||
| } |
There was a problem hiding this comment.
There was a problem hiding this comment.
Hmmm what if in Windows I use a path like \TEMP\foo which is an absolute path, won't this be converted to TEMP/foo instead of /TEMP/foo?
There was a problem hiding this comment.
Ok I see the issue now. The problem is that you do solve something in the test which must be solved in the actual code. Imagine the user wants to specify a JKS path of C:\MyCerts\foo.jks, then he has to set
[[inputs.x509_cert]]
sources = ["jks:///C:/MyCerts/foo.jks"]and then you need to remove the leading slash in your regular code if (and only if) you get a drive letter. Please see line 282 and following for how to do this!
| if runtime.GOOS == "windows" { | ||
| pkcs12Path = strings.TrimPrefix(pkcs12Path, "/") | ||
| } |
| func TestGatherKeystores(t *testing.T) { | ||
| pkcs12Path, jksPath := generateTestKeystores(t) | ||
|
|
||
| tests := []struct { | ||
| name string | ||
| mode os.FileMode | ||
| content string | ||
| password string | ||
| error bool | ||
| }{ | ||
| {name: "valid PKCS12 keystore", mode: 0640, content: pkcs12Path, password: "test-password"}, | ||
| {name: "valid JKS keystore", mode: 0640, content: jksPath, password: "test-password"}, | ||
| {name: "missing password PKCS12", mode: 0640, content: pkcs12Path, error: true}, | ||
| {name: "missing password JKS", mode: 0640, content: jksPath, error: true}, | ||
| {name: "wrong password PKCS12", mode: 0640, content: pkcs12Path, password: "wrong-password", error: true}, | ||
| {name: "wrong password JKS", mode: 0640, content: jksPath, password: "wrong-password", error: true}, | ||
| } | ||
|
|
||
| for _, test := range tests { | ||
| t.Run(test.name, func(t *testing.T) { | ||
| if runtime.GOOS != "windows" { | ||
| // To be Reviewed | ||
| path := strings.TrimPrefix(test.content, "pkcs12://") | ||
| path = strings.TrimPrefix(path, "jks://") | ||
| require.NoError(t, os.Chmod(path, test.mode)) | ||
| } | ||
|
|
||
| sc := X509Cert{ | ||
| Sources: []string{test.content}, | ||
| Log: testutil.Logger{}, | ||
| } | ||
|
|
||
| // Set password if provided | ||
| if test.password != "" { | ||
| sc.Password = config.NewSecret([]byte(test.password)) | ||
| } else { | ||
| sc.Password = config.NewSecret(nil) | ||
| } | ||
|
|
||
| require.NoError(t, sc.Init()) | ||
|
|
||
| acc := testutil.Accumulator{} | ||
| err := sc.Gather(&acc) | ||
|
|
||
| if (len(acc.Errors) > 0) != test.error { | ||
| t.Errorf("%s", err) | ||
| } | ||
| }) | ||
| } | ||
| } |
There was a problem hiding this comment.
How about splitting this function into one testing for failures (those with error: true) and another one where we don't expect errors. This has the advantage of simplifying the code and it is easier to follow as the function will set the context.
Please also test for the error message with require.ErrorContains(t, err, "essential part of the expected error message")!
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
There was a problem hiding this comment.
Thanks @paulojmdias! You need to fix the path handling on Windows. Currently your tests will pass but any real Windows path will fail as you need to remove the leading slash for the path contains a drive-letter.
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
…keystore_cert Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
|
Download PR build artifacts for linux_amd64.tar.gz, darwin_arm64.tar.gz, and windows_amd64.zip. 📦 Click here to get additional PR build artifactsArtifact URLs |
srebhan
left a comment
There was a problem hiding this comment.
Awesome! Thanks a lot for your contribution and patience @paulojmdias!
…fluxdata#16508) Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Summary
I initially thought about creating a separate input plugin for JKS & PKCS12 key stores but decided to integrate it into x509_cert since the changes were minimal. This update allows x509_cert to automatically detect and parse JKS & PKCS12 files while maintaining the existing certificate validation and metric collection logic. I also added tests to ensure everything works smoothly without overcomplicating the code.
Please evaluate if make sense and let me know what changes you feel are needed to accommodate this feature.
Checklist
Related issues
resolves #7013