github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/authentication/agent.go (about)

     1  // Copyright 2014 Canonical Ltd. All rights reserved.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package authentication
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/juju/errors"
    10  
    11  	apiservererrors "github.com/juju/juju/apiserver/errors"
    12  	"github.com/juju/juju/state"
    13  )
    14  
    15  // EntityAuthenticator performs authentication for juju entities.
    16  type AgentAuthenticator struct{}
    17  
    18  var _ EntityAuthenticator = (*AgentAuthenticator)(nil)
    19  
    20  type taggedAuthenticator interface {
    21  	state.Entity
    22  	state.Authenticator
    23  }
    24  
    25  // Authenticate authenticates the provided entity.
    26  // It takes an entityfinder and the tag used to find the entity that requires authentication.
    27  func (*AgentAuthenticator) Authenticate(ctx context.Context, entityFinder EntityFinder, authParams AuthParams) (state.Entity, error) {
    28  	entity, err := entityFinder.FindEntity(authParams.AuthTag)
    29  	if errors.Is(err, errors.NotFound) {
    30  		logger.Debugf("cannot authenticate unknown entity: %v", authParams.AuthTag)
    31  		return nil, errors.Trace(apiservererrors.ErrBadCreds)
    32  	}
    33  	if err != nil {
    34  		return nil, errors.Trace(err)
    35  	}
    36  	authenticator, ok := entity.(taggedAuthenticator)
    37  	if !ok {
    38  		return nil, errors.Trace(apiservererrors.ErrBadRequest)
    39  	}
    40  	if !authenticator.PasswordValid(authParams.Credentials) {
    41  		return nil, errors.Trace(apiservererrors.ErrBadCreds)
    42  	}
    43  
    44  	// If this is a machine agent connecting, we need to check the
    45  	// nonce matches, otherwise the wrong agent might be trying to
    46  	// connect.
    47  	//
    48  	// NOTE(axw) with the current implementation of Login, it is
    49  	// important that we check the password before checking the
    50  	// nonce, or an unprovisioned machine in a hosted model will
    51  	// prevent a controller machine from logging into the hosted
    52  	// model.
    53  	if machine, ok := authenticator.(*state.Machine); ok {
    54  		if !machine.CheckProvisioned(authParams.Nonce) {
    55  			return nil, errors.NotProvisionedf("machine %v", machine.Id())
    56  		}
    57  	}
    58  
    59  	return entity, nil
    60  }