Skip to content

Conversation

@JonahRosenblumHPE
Copy link

@JonahRosenblumHPE JonahRosenblumHPE commented Aug 29, 2025

The DAOS agent currently authenticates users using Unix Domain Sockets (UDS). While this works for many users, there is a growing demand for alternative authentication methods. This pull request reworks the DAOS agent code to make it simple to implement new sources of authentication for use in addition to/besides UDS. We also added a new example alternative authentication method in use at our company (part of a project soon to be open-sourced), and are happy to leave it in the codebase as an example.

Steps for the author:

  • Commit message follows the guidelines.
  • Appropriate Features or Test-tag pragmas were used.
  • Appropriate Functional Test Stages were run.
  • At least two positive code reviews including at least one code owner from each category referenced in the PR.
  • Testing is complete. If necessary, forced-landing label added and a reason added in a comment.

After all prior steps are complete:

  • Gatekeeper requested (daos-gatekeeper added as a reviewer).

@JonahRosenblumHPE
Copy link
Author

A specification we wrote about DAOS Agent authentication.

@github-actions
Copy link

Errors are component not formatted correctly,Ticket number prefix incorrect,PR title is malformatted. See https://daosio.atlassian.net/wiki/spaces/DC/pages/11133911069/Commit+Comments,Unable to load ticket data
https://daosio.atlassian.net/browse/Modify

Copy link
Contributor

@tanabarr tanabarr left a comment

Choose a reason for hiding this comment

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

Looks like a great contribution thank you very much. The changes look good to me, I would like to see some unit testing including some basics on using the access manager. Some documentation on adding new authentication methods and a walk-through of using the access manager example would be good from a usability perspective. I think the original author of the code @kjacque should also take a look to see if I've missed anything.

}
validAuthMethods[method] = true
}
if len(cfg.credentials.ValidAuthMethods) == 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

So if ValidAuthMethods are specified in the config the default UDS method won't be automatically included and has to be specified within the config? Shouldn't we always provide UDS as a valid method regardless of what extra methods have been added?

Copy link
Author

Choose a reason for hiding this comment

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

So if ValidAuthMethods are specified in the config the default UDS method won't be automatically included and has to be specified within the config?

Yes

Shouldn't we always provide UDS as a valid method regardless of what extra methods have been added?

Personally, I don't think so. If I create my own personal authentication method that I trust, and I don't want to consider "did I configure my Unix groups properly?", it would be nice to disable UDS. I am open to changing my opinion on this, but having more control over valid authentication methods for the agent seems better to me.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, that sounds okay as long as it's properly documented and understood.

var args authArgs
reqbSize := len(reqb)
if reqbSize == 0 {
args.tag = auth.CredentialRequestUnix{}.GetAuthName()
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems to imply that UDS should always be available as an authentication option.

Copy link
Author

Choose a reason for hiding this comment

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

I wanted this code to be backward compatible. "Authentication type" was never specified before this feature because the only option was UDS. By assuming that an empty body means the client wants to use UDS, this feature maintains compatibility with old clients. However, it is possible to disable UDS in the agent through the agent configuration file.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there some unit test coverage that covers the cases where 1) empty body results in UDS (this line being executed) and 2) UDS is specified in the config auth types and so args.tag get set as UDS 3) UDS not specified in the config auth types therefore body is not ever empty and another type gets used? Basically it would be good to get decent unit test coverage on this method to ensure all existing authentication types work as expected.

Copy link
Author

Choose a reason for hiding this comment

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

This makes sense. Is security_rpc_test.go the appropriate location to add these unit tests?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes it is but I think it might be best to arrange a sync-up with @kjacque before writing tests just in case any design changes need to be made.

args.tag = auth.CredentialRequestUnix{}.GetAuthName()
} else if reqbSize >= auth.AuthTagSize {
copy(args.tag[:], reqb)
args.reqBody = reqb[auth.AuthTagSize:]
Copy link
Contributor

@tanabarr tanabarr Sep 2, 2025

Choose a reason for hiding this comment

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

How does the concatenation of the request body work?

Copy link
Author

Choose a reason for hiding this comment

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

I'm not sure I follow the question, likely stemming from my inexperience with Golang. The purpose of this code is to parse the raw message into the authTag, which identifies the authentication method, and the body of the request into a struct.

I took an approach that is similar to memcpy in C, although I suspect there is a more "Golang-style" way of doing this.

If this does not answer your question, I apologize.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm happy if it's got good unit test coverage to give us confidence in the implementation. You could probably use Marshal/Unmarshal for this kind of parsing.

Copy link
Author

Choose a reason for hiding this comment

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

I will look into using Marshal/Unmarshal and add unit tests.

)

type (
CredentialRequestAM struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

This file seems to be missing comments to describe exported symbols.

// an instance to the CredentialRequests list.
// The agent must be configured to allow an authentication method when it is initalized.
// By default, only Unix authentication is enabled.
var CredentialRequests = []CredentialRequestFactory{&CredentialRequestUnix{}, &CredentialRequestAM{}}
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment "by default, only unix authentication is enabled" doesn't match the code. List also contains CredentialRequestAM.

Copy link
Author

Choose a reason for hiding this comment

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

by default, only unix authentication is enabled

I think this comment is misleading. CredentialRequests is a list containing every implementation of an authentication method.

This method is where the agent determines which authentication is enabled and this is where the "by default, only unix authentication is enabled" portion is relevant.

The reason for including this comment in the first place is to help developers, but I think they should instead refer to my specification for how to add new authentication and I should remove this portion of the comment. Do you agree?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes that sounds good, thanks.

if req.DomainInfo == nil {
return nil, err
}
if err := func() error {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: the style seems to introduce unnecessary nesting, I would prefer to add a defer func() {log.Error(...)} using the err variable defined in the function signature return types (cred *Credential, err error) to provide error-logging for each of the errors returned (which seems to be the purpose of the func() error syntax. Alternatively it would be fine to not supply a logger to the function and instead log the error in the caller of GetSignedCredential().

Copy link
Author

Choose a reason for hiding this comment

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

My design choice with the nesting in this function is related to how unit testing is done here. I'm not sure if your suggestion is compatible with this unit test, or if I should just rewrite the unit test.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I didn't realise the test was dependent on this paradigm. It's only a style related comment so can leave it as is, thanks.

Copy link
Author

Choose a reason for hiding this comment

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

I didn't document this strange design choice in my code, which understandably raises eyebrows. I will add a short comment highlighting this for future developers.

Copy link
Contributor

Choose a reason for hiding this comment

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

Seconding the initial comment. I don't see why you can't define the closure as a named function (either within this function or outside it). You can pass req into it.

// Using information stored in the agent's security config, the session/socket, request body, and the agent's signing key,
// initalize the state of the Credential Request so that it can sign a credential in the future. Return an error if
// a problem occurs during initializiation.
InitCredentialRequest(log logging.Logger, sec_cfg *security.CredentialConfig, session *drpc.Session, req_body []byte, key crypto.PrivateKey) error
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to be passing a logger into credential methods, don't we want to just log the error in the caller. This might reduce the chance of logging information that might be useful to an attacker.

Copy link
Author

Choose a reason for hiding this comment

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

I don't have much experience with Golang logging. How can I refactor this to log the error in the caller - should I initialize a "default logger" in the caller body?

Copy link
Contributor

Choose a reason for hiding this comment

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

You already have a logger in the only call I can see: https://github.com/daos-stack/daos/pull/16788/files#diff-3aa160ba407c1ca20c5bc486aa45370dd185a0f0f1eb5eddbebd57293fe9e8a8R221 just log the error after the call if you want to (otherwise just return the error which should be sufficient in most cases, we don't tend to log an error and return it, normally just do one or the other and if returning error use errors.Wrap() et al. to add context to the returned error).

InitCredentialRequest(log logging.Logger, sec_cfg *security.CredentialConfig, session *drpc.Session, req_body []byte, key crypto.PrivateKey) error
// Contact a source of authenticity (e.g. domain socket, access manager) using the initalized state of the CredentialRequest
// to construct a Credential object.
GetSignedCredential(log logging.Logger, ctx context.Context) (*Credential, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

As above.

Copy link
Contributor

@kjacque kjacque left a comment

Choose a reason for hiding this comment

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

Thanks for submitting this PR. It's a good start, but I think we should chat in-depth about the overall design. Right now it seems like the new AM authentication method is a bit jumbled up with the AUTH_SYS (unix) method, and changes are a bit less compartmentalized than I'd like. The initial design was intended to make auth types modular, down to the messages passed via dRPC (see src/proto/security/auth.proto). We also need to be very careful about how tokens and credentials are passed around and who they are accessible to.

If you have any public (or private, I'm at HPE too) specs for the sample access manager, I'd be happy to help with the high level design of this addition. We definitely need to ensure appropriate testing for all the new logic, too.

Comment on lines 21 to 22
/** Constant that represents the name of the Unix authentication method. */
#define AGENT_AUTH_METHOD_AM "acma"
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like the comment wasn't updated. AM/acma == access manager? The name is a bit vague, but if that's what the project is called, no problem with the name.

int rc;
uint8_t *token_buffer = NULL;
unsigned int token_buffer_length = 0;
char *delegation_token_path = getenv("TOKEN_PATH");
Copy link
Contributor

Choose a reason for hiding this comment

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

This is something I'd expect the agent to know about (maybe part of the agent config?) and return to us in the credential payload.

Without knowing more about the Access Manager protocol, it is tricky to offer specific advice on how we should handle this and where. The agent is the secure component on the client side though. From the libdaos perspective, the agent hands us an appropriate credential, and we blindly send it along to the daos_engine. The daos_engine verifies the cred with the daos_server and stashes it.

uint8_t *token_buffer = NULL;
unsigned int token_buffer_length = 0;
char *delegation_token_path = getenv("TOKEN_PATH");
int use_access_manager = delegation_token_path != NULL && strcmp(delegation_token_path, "");
Copy link
Contributor

Choose a reason for hiding this comment

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

The agent should return a structure based on the supported auth type. I don't think libdaos should care about details like this.

Choose a reason for hiding this comment

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

The client should ping the agent to learn what authentication method(s) it should use. If multiple are provided, it will default to the first option.

Separate AUTH_SYS vs AUTH_ACCMAN into different functions.

Switch statement for flavor, make it easy to add new authentication.

return errors.Wrap(err, "token verification Failed")
}

func sysNameToPrincipalName(name string) string {
Copy link
Contributor

Choose a reason for hiding this comment

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

This file was intended to encapsulate the AUTH_SYS authentication token type (i.e. using unix usernames/groups). Rather than breaking this up, I think you should consider the flow for this new authentication type separately. If you're free to share any details on the protocol for the access manager, I'd be happy to collaborate.


var _ cache.ExpirableItem = (*cachedCredential)(nil)

func getValidAuthMethods(cfg *securityConfig) (AuthValidSet, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a dangling question here: Why would a single DAOS system want to depend on multiple auth types? Unless there's a compelling use case for allowing this, it seems unnecessarily complex, and maybe easier for a user to mess up. I think the auth type needs to be a single type defined in the server config, as a central source. The agent can get this information from the servers.

func (m *SecurityModule) getCredential(ctx context.Context, session *drpc.Session) ([]byte, error) {
if session == nil {
return nil, drpc.NewFailureWithMessage("session is nil")
func (m *SecurityModule) HandleCall(ctx context.Context, session *drpc.Session, method drpc.Method, reqb []byte) ([]byte, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The additions in this function seem like they really belong in the GetCredential logic, rather than in the overall SecurityModule.

Comment on lines 320 to 362
CredentialRequestGetSignedTesting := func(ctx context.Context, log logging.Logger, req auth.CredentialRequest) (*auth.Credential, error) {
r, ok := req.(*auth.CredentialRequestUnix)
if !ok {
return nil, errors.New("Testing fn used with non-unix credential request")
}
}()
testing_fn := func() auth.GetSignedCredentialInternalFn {
var idx int
return func(_ context.Context, _ *auth.CredentialRequestUnix) (*auth.Credential, error) {
defer func() {
if idx < len(tc.responses)-1 {
idx++
}
}()
t.Logf("returning response %d: %+v", idx, tc.responses[idx])
return tc.responses[idx].cred, tc.responses[idx].err
}
}()
r.GetSignedCredentialInternal = testing_fn
return r.GetSignedCredential(log, ctx)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This feels a bit over-complex for a mock function. It seems like testing_fn is what you're really trying to inject here. Worth re-thinking the design approach here I think. Best to design the code to be easy to test.

if req.DomainInfo == nil {
return nil, err
}
if err := func() error {
Copy link
Contributor

Choose a reason for hiding this comment

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

Seconding the initial comment. I don't see why you can't define the closure as a named function (either within this function or outside it). You can pass req into it.

@JonahRosenblumHPE JonahRosenblumHPE force-pushed the master branch 2 times, most recently from ee2bcc3 to 18a1855 Compare October 20, 2025 15:22
@kjacque kjacque self-requested a review November 5, 2025 21:37
bool replace = 13; // Rank's engine instance metadata to be replaced
}

message JoinResp {

Choose a reason for hiding this comment

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

Revert changes to this file - all whitespace.

string origin = 3; // the agent that created this credential
}

message AuthArgs

Choose a reason for hiding this comment

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

This is GetCredReq.

AUTH_NONE = 0;
AUTH_SYS = 1;
AUTH_SYS = 1;
AUTH_AM = 2;

Choose a reason for hiding this comment

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

AM is vague; be more explicit (e.g. AccMan). Add comments along with the proto, it gets exported into generated code.

Choose a reason for hiding this comment

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

Add detail for AUTH_SYS/AUTH_UNIX as well.

"net"
"os/user"
<<<<<<< HEAD
=======

Choose a reason for hiding this comment

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

Fix merge issue!

thisscriptname="$(basename "$0")"
thisscriptpath="$(dirname "$(readlink -f "$0")")"

echo "start of script: $thisscriptpath/$thisscriptname"

Choose a reason for hiding this comment

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

Revert this change.

}

func newMgmtSvc(h *EngineHarness, m *system.Membership, s *raft.Database, c control.UnaryInvoker, p *events.PubSub) *mgmtSvc {
func newMgmtSvc(h *EngineHarness, m *system.Membership, s *raft.Database, c control.UnaryInvoker, p *events.PubSub, v []uint32) *mgmtSvc {

Choose a reason for hiding this comment

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

Change v to a (authentication!)

Choose a reason for hiding this comment

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

Look into importing auth in the server, and then making this an auth.Flavor type.

// versions:
// protoc-gen-go v1.34.1
// protoc v3.21.12
// source: security/auth.proto

Choose a reason for hiding this comment

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

Remove this, added accidentally.

groupNames, err := r.getGroupNames(r)
if err != nil {
return nil, errors.Wrap(err, "failed to get group names")
func ParseValidAuthFlavors(authStrings []string) ([]uint32, error) {

Choose a reason for hiding this comment

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

Rename file to just "auth.go", auth_sys is one flavor of auth not the entire thing anymore!

Choose a reason for hiding this comment

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

Make this parsing case-insensitive.

Choose a reason for hiding this comment

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

Another option: let them start their string with "auth" if they want.

strings.StartsWith("AUTH_") -> just pass the raw string in. Still handle case sensitivity for them.

Choose a reason for hiding this comment

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

Also, update the example config to show how to specify auth type.

Choose a reason for hiding this comment

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

For public methods, include a documentation comment explaining what the method does!

return r.getGroup(strconv.Itoa(int(r.DomainInfo.Gid())))
func CredentialRequestGetSigned(ctx context.Context, log logging.Logger, req CredentialRequest) (*Credential, error) {
return req.GetSignedCredential(log, ctx)
}

Choose a reason for hiding this comment

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

Probably move this to the agent since this is a workaround for an agent-specific issue.


// Check our verifier
err = auth.VerifyToken(key, cred.GetToken(), cred.GetVerifier().GetData())
err = auth.VerifyToken(key, cred.GetToken(), cred.GetVerifier().GetData(), m.validAuthFlavors)

Choose a reason for hiding this comment

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

Could remove the parameter from VerifyToken and do the check of "is this flavor valid" in the body of this function.

"github.com/daos-stack/daos/src/control/lib/hardware/defaults/topology"
"github.com/daos-stack/daos/src/control/logging"
"github.com/daos-stack/daos/src/control/security"
"github.com/daos-stack/daos/src/control/security/auth"

Choose a reason for hiding this comment

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

You're including auth here, so why can't you use auth.Flavor?!


harness := NewEngineHarness(log).WithFaultDomain(faultDomain)

validAuthFlavors, err := auth.ParseValidAuthFlavors(cfg.TransportConfig.AuthenticationConfig.ValidAuth)

Choose a reason for hiding this comment

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

Parse this once, find a way to pass this to the security service AND the management service.

#include <daos_prop.h>

/** Constant that represents the upper bound size of a string encoded delegation credential token for the access manager. */
#define MAX_DELEGATION_TOKEN_SIZE 10000

Choose a reason for hiding this comment

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

Move to the function that the client uses to package an "access manager" request to the agent. It is not used anywhere else.

CacheExpiration time.Duration `yaml:"cache_expiration,omitempty"`
ClientUserMap ClientUserMap `yaml:"client_user_map,omitempty"`
ValidAuthMethods []string `yaml:"valid_auth_methods,omitempty"`
AMConfig AccessManagerConfig `yaml:"access_manager_config,omitempty"`

Choose a reason for hiding this comment

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

These should not be in the agent!

AllowInsecure bool `yaml:"allow_insecure"`
CertificateConfig `yaml:",inline"`
// authentication
AuthenticationConfig *AuthenticationConfig `yaml:"auth_config"`

Choose a reason for hiding this comment

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

This should be directly part of the server config file!


func DefaultAuthenticationConfig() *AuthenticationConfig {
return &AuthenticationConfig{
ValidAuth: []string{"SYS"},

Choose a reason for hiding this comment

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

Use the actual default string "AUTH_SYS" generated by the protobuf.

Choose a reason for hiding this comment

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

And move to the server file.

Choose a reason for hiding this comment

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

rename this to auth_accman.go, and the other to auth_sys.go. The current auth_sys.go is now the "generic auth" file so that should just be auth.go.

getGroupNamesFn func(*CredentialRequestUnix) ([]string, error)

// CredentialRequest defines the request parameters for GetSignedCredential.
CredentialRequestUnix struct {

Choose a reason for hiding this comment

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

Rename: AuthSysCredentialRequest. (Obviously change the acc man one too)

// Using information stored in the agent's security config, the session/socket, request body, and the agent's signing key,
// initalize the state of the Credential Request so that it can sign a credential in the future. Return an error if
// a problem occurs during initializiation.
InitCredentialRequest(log logging.Logger, sec_cfg *security.CredentialConfig, session *drpc.Session, req_body []byte, key crypto.PrivateKey) error

Choose a reason for hiding this comment

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

Rename this to just "init"


CredentialRequestFactory interface {
// Allocate, and return, an instance of the type that implements CredentialRequest interface.
AllocCredentialRequest() CredentialRequest

Choose a reason for hiding this comment

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

See if factory can do the initialization! Seems redundant to do alloc then init.

CredentialRequestFactory interface {
// Allocate, and return, an instance of the type that implements CredentialRequest interface.
AllocCredentialRequest() CredentialRequest
// Returns a unique 4 character identifier (AuthTag) that refers to the CredentialRequest implementation.

Choose a reason for hiding this comment

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

This comment is outdated, update.

// Returns a key, as a string, representing a unique identifer specific to the request. This key is used by the cache
// to remember credentials. It is vital for security that this identifer cannot be forged or easily guessed by the client -
// otherwise cached credentials can be "stolen".
CredReqKey() string

Choose a reason for hiding this comment

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

Rename to "GetKey"

}
return sysToken, nil
}
var CredentialRequests = []CredentialRequestFactory{&CredentialRequestUnix{}, &CredentialRequestAM{}}

Choose a reason for hiding this comment

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

Revisit why I implemented it this way. Can this be simplified? Maybe just a function with a mapping/switch statement between flavors and factories.

Choose a reason for hiding this comment

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

Split the factory and the request into two separate things. The requests should not double as factories; the factories should exist only to generate requests!

}

// Craft AuthToken
sys := Sys{

Choose a reason for hiding this comment

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

Add parsing on the server side to determine what to do with non-Sys tokens.

Choose a reason for hiding this comment

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

Add new token for AccMan!

Choose a reason for hiding this comment

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

In token definition, call things by their name in the AM (i.e. "roles" not "groups")

Copy link
Author

@JonahRosenblumHPE JonahRosenblumHPE Dec 26, 2025

Choose a reason for hiding this comment

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

My conjecture is that every auth flavor will implement a very similar (if not identical) token structure. I propose that there ought to be a single generic token, and each auth flavor is responsible for implementing GetSignedCredential in a way that conforms to the generic token. I am holding off on making this change until we agree on this design choice.

return nil, err
}

machine_name, identity, err := seperate(authInfo.Identity)

Choose a reason for hiding this comment

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

Use camel case for names.

ClientNetHint ClientNetworkHint `json:"client_net_hint"`
AlternateClientNetHints []ClientNetworkHint `json:"secondary_client_net_hints"`
BuildInfo BuildInfo `json:"build_info"`
ValidAuthFlavors []uint32 `json:"valid_auth_flavors"`

Choose a reason for hiding this comment

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

Try to change to auth.Flavor

signCredential credSignerFn
credCache *credentialCache
config *securityConfig
validAuthFlavors []auth.Flavor

Choose a reason for hiding this comment

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

This is in the info cache... why am I reading it here?

}

config *securityConfig
authArgs struct {

Choose a reason for hiding this comment

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

This should be removed.


var _ cache.ExpirableItem = (*cachedCredential)(nil)

func getAuthArgs(reqb []byte) (*auth.AuthArgs, error) {

Choose a reason for hiding this comment

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

The caller should pass the flavor I am using, I can change the client logic to ping the agent and ask which flavor to use.


// NewSecurityModule creates a new module with the given initialized TransportConfig.
func NewSecurityModule(log logging.Logger, cfg *securityConfig) *SecurityModule {
func NewSecurityModule(log logging.Logger, cfg *securityConfig) (*SecurityModule, error) {

Choose a reason for hiding this comment

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

This can no longer return errors.


return m.getCredential(ctx, session)
}
m.validAuthFlavors = make([]auth.Flavor, len(resp.ValidAuthFlavors))

Choose a reason for hiding this comment

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

Should just look in the cache instead of using a second member variable.

// getCredentials generates a signed user credential based on the authentication method requested.
func (m *SecurityModule) getCredential(ctx context.Context, session *drpc.Session, args *auth.AuthArgs, req auth.CredentialRequest) ([]byte, error) {
if len(m.validAuthFlavors) == 0 {
err := m.retrieveAuthFromServer(ctx)

Choose a reason for hiding this comment

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

Just ask the cache!

}(); err != nil {
m.log.Errorf("%s: failed to get user credential: %s", info, err)
return m.credRespWithStatus(daos.MiscError)
if errors.Is(err, daos.MiscError) {

Choose a reason for hiding this comment

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

Add new DAOS error code for this specific situation.

Choose a reason for hiding this comment

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

include/daos_error.h
and
src/control/lib/daos/

and also documentation where needed.

}

func (m *SecurityModule) getValidAuthFlavors(ctx context.Context) ([]byte, error) {
if len(m.validAuthFlavors) == 0 {

Choose a reason for hiding this comment

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

Get it from the cache!

numaGetter hardware.ProcessNUMAProvider
providerIdx uint

validAuthFlavors []uint32

Choose a reason for hiding this comment

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

Invesigate if this is necesary!

@JonahRosenblumHPE JonahRosenblumHPE force-pushed the master branch 3 times, most recently from 1aa6045 to dbf9d36 Compare December 26, 2025 18:10
BuildInfo build_info = 9; // Structured server build information
repeated FabricInterfaces numa_fabric_interfaces =
10; // Usable fabric interfaces by NUMA node (populated by agent)
repeated uint32 valid_auth_flavors = 11; // Authentication flavors allowed by the server
Copy link
Author

Choose a reason for hiding this comment

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

I spent hours trying to get this to be an auth.Flavor. I cannot for the life of me figure out the SConscript build system. I defer to the maintainers - it would be unproductive for me to try any longer to make this change myself.

Signed-off-by: JonahRosenblumHPE <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants