Skip to content

feat(inputs.x509_cert): Add support for JKS and PKCS#12 keystores#16508

Merged
mstrandboge merged 40 commits into
influxdata:masterfrom
paulojmdias:keystore_cert
Mar 10, 2025
Merged

feat(inputs.x509_cert): Add support for JKS and PKCS#12 keystores#16508
mstrandboge merged 40 commits into
influxdata:masterfrom
paulojmdias:keystore_cert

Conversation

@paulojmdias

Copy link
Copy Markdown
Contributor

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

  • No AI generated code was used in this PR

Related issues

resolves #7013

Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
@telegraf-tiger telegraf-tiger Bot added feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin plugin/input 1. Request for new input plugins 2. Issues/PRs that are related to input plugins labels Feb 12, 2025
@srebhan

srebhan commented Feb 12, 2025

Copy link
Copy Markdown
Member

@paulojmdias please check the linter issues. You can reproduce them locally using make check-deps.

@srebhan srebhan self-assigned this Feb 12, 2025
Signed-off-by: Paulo Dias <paulodias.gm@gmail.com>
@paulojmdias

Copy link
Copy Markdown
Contributor Author

@paulojmdias please check the linter issues. You can reproduce them locally using make check-deps.

Fixed 🙌

@paulojmdias paulojmdias changed the title feat(inputs.x509_cert): add support for JKS and PKCS#12 keystors feat(inputs.x509_cert): add support for JKS and PKCS#12 keystores Feb 13, 2025

@srebhan srebhan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution @paulojmdias! This is very much appreciated! I do have some comments in the code...

Comment thread plugins/inputs/x509_cert/sample.conf Outdated
Comment thread plugins/inputs/x509_cert/x509_cert.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert_test.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert_test.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert_test.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert_test.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert_test.go Outdated
@srebhan srebhan changed the title feat(inputs.x509_cert): add support for JKS and PKCS#12 keystores feat(inputs.x509_cert): Add support for JKS and PKCS#12 keystores Feb 17, 2025
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 srebhan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@paulojmdias some more comments...

Comment thread plugins/inputs/x509_cert/java_key_store.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert_test.go Outdated
Comment thread plugins/inputs/x509_cert/x509_cert_test.go Outdated
err = jks.Store(output, []byte("test-password"))
require.NoError(t, err)

return "jks://" + jksPath

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work on Windows, you should do

Suggested change
return "jks://" + jksPath
jksPath = filepath.ToSlash(jksPath)
if !strings.HasPrefix(jksPath, "/") {
jksPath = "/" + jksPath
}
return "jks://" + jksPath

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed also pkcs12Path

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@srebhan i fixed in the commit 0824e05

Your suggestion also does not work, so I have included the following.

pkcs12Path = filepath.ToSlash(pkcs12Path)
if runtime.GOOS == "windows" {
	pkcs12Path = strings.TrimPrefix(pkcs12Path, "/")
}

return "pkcs12://" + pkcs12Path

Please review and let me know.

paulojmdias and others added 13 commits February 18, 2025 17:13
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>
paulojmdias and others added 11 commits February 21, 2025 01:09
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 srebhan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @paulojmdias, this looks really nice already. Some more comments regarding the test code but we are almost there.

Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment on lines +137 to +139
if runtime.GOOS == "windows" {
jksPath = strings.TrimPrefix(jksPath, "/")
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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!

Comment on lines +104 to +106
if runtime.GOOS == "windows" {
pkcs12Path = strings.TrimPrefix(pkcs12Path, "/")
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answered above

Comment on lines +144 to +193
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)
}
})
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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")!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@srebhan added on commit 17e0dfa

Please take a look and let me know WDYT.

Comment thread plugins/inputs/x509_cert/x509_cert.go Outdated
paulojmdias and others added 4 commits March 4, 2025 17:37
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 srebhan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store.go
Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
Comment thread plugins/inputs/x509_cert/java_key_store_test.go Outdated
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>
@telegraf-tiger

telegraf-tiger Bot commented Mar 6, 2025

Copy link
Copy Markdown
Contributor

@srebhan srebhan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! Thanks a lot for your contribution and patience @paulojmdias!

@srebhan srebhan added the ready for final review This pull request has been reviewed and/or tested by multiple users and is ready for a final review. label Mar 7, 2025
@srebhan srebhan assigned mstrandboge and unassigned srebhan Mar 7, 2025
@mstrandboge mstrandboge merged commit d231442 into influxdata:master Mar 10, 2025
@github-actions github-actions Bot added this to the v1.34.0 milestone Mar 10, 2025
@paulojmdias paulojmdias deleted the keystore_cert branch March 10, 2025 08:02
asaharn pushed a commit to asaharn/telegraf that referenced this pull request Mar 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin plugin/input 1. Request for new input plugins 2. Issues/PRs that are related to input plugins ready for final review This pull request has been reviewed and/or tested by multiple users and is ready for a final review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for JKS files to x509_cert plugin

3 participants