Enhance NATS provider to support multiple authentication methods#1222
Enhance NATS provider to support multiple authentication methods#1222latchmihay wants to merge 1 commit intofluxcd:mainfrom
Conversation
|
@cappyzawa fixed it, its pointing to main now |
|
Thanks for the contribution! Please run |
|
One suggestion: the auth decision in This keeps Something like: type natsClient struct {
server string
authFn func() (nats.Option, func(), error)
}
func NewNATS(...) (*NATS, error) {
client := &natsClient{server: server}
if len(credsData) > 0 {
client.authFn = func() (nats.Option, func(), error) {
return nats.UserCredentialBytes(credsData), nil, nil
}
} else if len(nkeySeed) > 0 {
client.authFn = func() (nats.Option, func(), error) {
kp, err := nkeys.FromSeed(nkeySeed)
if err != nil {
return nil, nil, fmt.Errorf("error parsing nkey seed: %w", err)
}
pubKey, err := kp.PublicKey()
if err != nil {
kp.Wipe()
return nil, nil, fmt.Errorf("error getting public key: %w", err)
}
sigCB := func(nonce []byte) ([]byte, error) {
return kp.Sign(nonce)
}
return nats.Nkey(pubKey, sigCB), kp.Wipe, nil
}
} else if username != "" && password != "" {
client.authFn = func() (nats.Option, func(), error) {
return nats.UserInfo(username, password), nil, nil
}
}
// ...
}
func (n *natsClient) publish(...) error {
opts := []nats.Option{nats.Name("NATS Provider Publisher")}
if n.authFn != nil {
authOpt, cleanup, err := n.authFn()
if err != nil {
return err
}
if cleanup != nil {
defer cleanup()
}
opts = append(opts, authOpt)
}
nc, err := nats.Connect(n.server, opts...)
// ...
}The cleanup func handles Not a blocker, just a suggestion for cleaner separation. |
cappyzawa
left a comment
There was a problem hiding this comment.
The authFn refactoring looks clean! 👍
One thing I noticed: the current test checks authFn != nil, but doesn't actually call authFn() to verify it returns the correct auth type. Since we moved away from storing fields directly, it'd be nice to confirm the returned nats.Option actually sets the right authentication.
Also, the "credentials file data is stored" and "nkey seed data is stored" cases could double as priority tests by adding the other auth params - this way we can verify creds > nkey > userpass priority works correctly.
Here's a minimal diff that adds this verification:
+ "github.com/nats-io/nats.go"
+ // Priority tests: creds > nkey > userpass
{
- name: "credentials file data is stored",
+ name: "creds takes priority over nkey and userpass",
subject: "test",
server: "nats",
+ username: "user",
+ password: "pass",
credsData: []byte("credentials-content"),
+ nkeySeed: []byte("SUAGMJH5XLGZKQQWAWKRZJIGMOU4HPFUYLXJMXOO5NLFEO2OOQJ5LPRDPM"),
expectedSubject: "test",
expectedCreds: true,
},
{
- name: "nkey seed data is stored",
+ name: "nkey takes priority over userpass",
subject: "test",
server: "nats",
+ username: "user",
+ password: "pass",
nkeySeed: []byte("SUAGMJH5XLGZKQQWAWKRZJIGMOU4HPFUYLXJMXOO5NLFEO2OOQJ5LPRDPM"),
expectedSubject: "test",
expectedNkey: true,
},And add verification logic after checking client.authFn:
// Verify authFn returns valid option and correct auth type
if client.authFn != nil {
opt, cleanup, err := client.authFn()
g.Expect(err).To(BeNil(), "authFn should not return error")
g.Expect(opt).NotTo(BeNil(), "authFn should return a valid option")
if cleanup != nil {
defer cleanup()
}
// Apply option to verify which auth method was selected
var opts nats.Options
g.Expect(opt(&opts)).To(Succeed())
if tt.expectedCreds {
g.Expect(opts.UserJWT).NotTo(BeNil(), "creds auth should set UserJWT")
} else if tt.expectedNkey {
g.Expect(opts.Nkey).NotTo(BeEmpty(), "nkey auth should set Nkey")
g.Expect(opts.SignatureCB).NotTo(BeNil(), "nkey auth should set SignatureCB")
} else if tt.expectedUsername != "" {
g.Expect(opts.User).To(Equal(tt.expectedUsername), "userpass auth should set User")
g.Expect(opts.Password).To(Equal(tt.expectedPassword), "userpass auth should set Password")
}
}This keeps the existing test structure while adding actual auth type verification. What do you think?
Thank you for the suggestions, they have been added :) |
cappyzawa
left a comment
There was a problem hiding this comment.
LGTM! Thanks for implementing the test improvements - the priority tests and authFn verification look great. 🎉
matheuscscp
left a comment
There was a problem hiding this comment.
Thanks for this PR, @latchmihay!
We should strive to use the standard fields when possible:
type notifierOptions struct {
Context context.Context
URL string
ProxyURL string
Username string
Channel string
Token string
Headers map[string]string
// CertPool is kept for Git platform providers (GitHub, GitLab, etc.) that use third-party SDKs.
// TODO: Remove this field once all notifiers support client certificate authentication via TLSConfig.
CertPool *x509.CertPool
TLSConfig *tls.Config
Password string
CommitStatus string
ProviderName string
ProviderNamespace string
SecretData map[string][]byte
ServiceAccountName string
TokenCache *cache.TokenCache
TokenClient client.Client
}From what I understand, what you are adding here in creds could be a good fit for Token?
We will release Flux 2.8 at the end of the month, let's try to work on this PR so it can make it to the release 🙏
|
Also, please rebase 🙏 |
|
No merge commits please. Use rebase and force-push. Also, please squash, this PR should have a single commit |
@matheuscscp I agree that we should use the standard fields when possible, in this particular case its not a typical token.
apiVersion: v1
kind: Secret
metadata:
name: nats-provider-creds
namespace: desired-namespace
stringData:
creds: |
-----BEGIN NATS USER JWT-----
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5...
------END NATS USER JWT------
************************* IMPORTANT *************************
NKEY Seed printed below can be used to sign and prove identity.
NKEYs are sensitive and should be treated as secrets.
-----BEGIN USER NKEY SEED-----
SUAGMJH5XLGZKQQWAWKRZJIGMOU4HPFUYLXJMXOO5NLFEO2OOQJ5LPRDPM
------END USER NKEY SEED------ |
7126104 to
193cca6
Compare
193cca6 to
679a02e
Compare
…uding JWT, NKey, and Username/Password. Signed-off-by: Latch Mihay <latch@mihay.net>
679a02e to
bee56b8
Compare
Enhance NATS provider to support multiple authentication methods including JWT, NKey, and Username/Password.
This would allow the notification-controller to support the recommended NATS 2.0+ authentication paradigms.