github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/broker/network/choria_auth.go (about)

     1  // Copyright (c) 2020-2023, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package network
     6  
     7  import (
     8  	"crypto/ed25519"
     9  	"crypto/md5"
    10  	"crypto/tls"
    11  	"encoding/base64"
    12  	"encoding/hex"
    13  	"errors"
    14  	"fmt"
    15  	"net"
    16  	"strings"
    17  	"sync"
    18  
    19  	"github.com/choria-io/tokens"
    20  	"github.com/golang-jwt/jwt/v4"
    21  	"github.com/nats-io/nats-server/v2/server"
    22  	"github.com/sirupsen/logrus"
    23  
    24  	"github.com/choria-io/go-choria/internal/util"
    25  )
    26  
    27  // ChoriaAuth implements the Nats server.Authentication interface and
    28  // allows IP limits to be configured, connections that do not match
    29  // the configured IP or CIDRs are not allowed to publish to the
    30  // network targets used by clients to request actions on nodes.
    31  //
    32  // Additionally, when the server is running in a mode where anonymous
    33  // TLS connections is accepted then servers are entirely denied and
    34  // clients are allowed but restricted based on the JWT issued by the
    35  // AAA Service. This is activated using the plugin.choria.network.client_anon_tls
    36  // setting, however this should be avoided atm.
    37  //
    38  // Clients can present a JWT token signed by the AAA service if that
    39  // token has a purpose field matching choria_client_id and if the
    40  // AAA signer is configured in the broker using plugin.choria.security.request_signing_certificate
    41  // those with valid tokens and that are fully verified can connect but
    42  // will be restricted to client only functions. These clients will not
    43  // be able to access any Choria Streams features, KV buckets etc
    44  //
    45  // Additionally when provisioning support is enabled any non mTLS connection
    46  // will be placed in the provisioning account and unable to connect to the
    47  // fleet or provisioned nodes. This is only enabled if plugin.choria.network.provisioning.signer_cert
    48  // is set
    49  type ChoriaAuth struct {
    50  	clientAllowList           []string
    51  	isTLS                     bool
    52  	denyServers               bool
    53  	provisioningTokenSigner   string
    54  	clientJwtSigners          []string
    55  	serverJwtSigners          []string
    56  	allowIssuerBasedTLSAccess bool
    57  	issuerTokens              map[string]string
    58  	choriaAccount             *server.Account
    59  	systemAccount             *server.Account
    60  	provisioningAccount       *server.Account
    61  	provPass                  string
    62  	provWithoutToken          bool
    63  	systemUser                string
    64  	systemPass                string
    65  	tokenCache                map[string]ed25519.PublicKey
    66  	log                       *logrus.Entry
    67  	mu                        sync.Mutex
    68  }
    69  
    70  const (
    71  	provisioningUser   = "provisioner"
    72  	emptyString        = ""
    73  	edDSASigningMethod = "EdDSA"
    74  )
    75  
    76  var allSubjects = []string{">"}
    77  
    78  // Check checks and registers the incoming connection
    79  func (a *ChoriaAuth) Check(c server.ClientAuthentication) bool {
    80  	var (
    81  		verified    bool
    82  		tlsVerified bool
    83  		err         error
    84  	)
    85  
    86  	log := a.log.WithField("stage", "check")
    87  	remote := c.RemoteAddress()
    88  	if remote != nil {
    89  		log = log.WithField("remote", remote.String())
    90  	}
    91  	pipeConnection := remote.String() == "pipe"
    92  
    93  	tlsc := c.GetTLSConnectionState()
    94  	if tlsc != nil {
    95  		tlsVerified = len(tlsc.VerifiedChains) > 0
    96  	}
    97  
    98  	// no tls over pipes
    99  	if !pipeConnection && a.isTLS && tlsc == nil {
   100  		a.log.Warnf("Did not receive TLS Connection State for connection %s, rejecting", remote)
   101  		return false
   102  	}
   103  
   104  	systemUser := a.isSystemUser(c)
   105  
   106  	switch {
   107  	case a.isProvisionUser(c):
   108  		verified, err = a.handleProvisioningUserConnection(c, tlsVerified)
   109  		if err != nil {
   110  			log.Warnf("Handling provisioning user connection failed, denying %s: %s", c.RemoteAddress().String(), err)
   111  		}
   112  
   113  	case systemUser && (tlsVerified || pipeConnection):
   114  		verified, err = a.handleVerifiedSystemAccount(c, log)
   115  		if err != nil {
   116  			log.Warnf("Handling system user failed, denying: %s", err)
   117  		}
   118  
   119  	case systemUser && tlsc == nil:
   120  		verified = false
   121  		log.Warnf("System user is only allowed over TLS connections")
   122  
   123  	case systemUser && !tlsVerified:
   124  		verified, err = a.handleUnverifiedSystemAccount(c, tlsc, log)
   125  		if err != nil {
   126  			log.Warnf("Handling unverified TLS system user failed, denying: %s", err)
   127  		}
   128  
   129  	default:
   130  		var dfltErr, provErr error
   131  
   132  		verified, dfltErr = a.handleDefaultConnection(c, tlsc, tlsVerified, log)
   133  		if !verified && a.isTLS && !tlsVerified {
   134  			verified, provErr = a.handleUnverifiedProvisioningConnection(c)
   135  		}
   136  
   137  		if !verified {
   138  			log.Warnf("Denying connection: verified error: %v, unverified error: %v", dfltErr, provErr)
   139  		}
   140  	}
   141  
   142  	// should be already but let's make sure
   143  	if err != nil {
   144  		verified = false
   145  	}
   146  
   147  	return verified
   148  }
   149  
   150  func (a *ChoriaAuth) verifyNonceSignature(nonce []byte, sig string, pks string, log *logrus.Entry) (bool, error) {
   151  	if sig == "" {
   152  		return false, fmt.Errorf("connection nonce was not signed")
   153  	}
   154  
   155  	if pks == "" {
   156  		return false, fmt.Errorf("no public key found in the JWT to verify nonce signature")
   157  	}
   158  
   159  	if len(nonce) == 0 {
   160  		return false, fmt.Errorf("server did not generate a nonce to verify")
   161  	}
   162  
   163  	pubK, err := hex.DecodeString(pks)
   164  	if err != nil {
   165  		return false, fmt.Errorf("invalid nonce signature")
   166  	}
   167  
   168  	sigBytes, err := base64.RawURLEncoding.DecodeString(sig)
   169  	if err != nil {
   170  		return false, fmt.Errorf("invalid url encoded signature: %s", err)
   171  	}
   172  
   173  	valid, err := a.ed25519Verify(pubK, nonce, sigBytes)
   174  	if err != nil {
   175  		return false, fmt.Errorf("could not verify nonce signature: %v", err)
   176  	}
   177  
   178  	if !valid {
   179  		return false, fmt.Errorf("nonce signature did not verify using pub key in the jwt")
   180  	}
   181  
   182  	log.Debugf("Successfully verified nonce signature")
   183  
   184  	return true, nil
   185  }
   186  
   187  // ed25519.Sha256VerifyDir() panics on bad pubkeys, this does not
   188  func (a *ChoriaAuth) ed25519Verify(publicKey ed25519.PublicKey, message []byte, sig []byte) (bool, error) {
   189  	if len(publicKey) != ed25519.PublicKeySize {
   190  		return false, fmt.Errorf("invalid public key length %d", len(publicKey))
   191  	}
   192  
   193  	return ed25519.Verify(publicKey, message, sig), nil
   194  }
   195  
   196  func (a *ChoriaAuth) verifyServerJWTBasedAuth(remote net.Addr, jwts string, nonce []byte, sig string, log *logrus.Entry) (claims *tokens.ServerClaims, err error) {
   197  	if remote == nil {
   198  		log.Errorf("no remote client information received")
   199  		return nil, fmt.Errorf("remote client information is required in anonymous TLS or JWT signing modes")
   200  	}
   201  
   202  	claims, err = a.parseServerJWT(jwts)
   203  	if err != nil {
   204  		log.Errorf("could not parse JWT from %s: %s", remote.String(), err)
   205  		return nil, fmt.Errorf("invalid JWT token")
   206  	}
   207  
   208  	_, err = a.verifyNonceSignature(nonce, sig, claims.PublicKey, log)
   209  	if err != nil {
   210  		log.Errorf("nonce signature verification failed: %s", err)
   211  		return nil, fmt.Errorf("invalid nonce signature")
   212  	}
   213  
   214  	return claims, nil
   215  }
   216  
   217  func (a *ChoriaAuth) verifyClientJWTBasedAuth(remote net.Addr, jwts string, nonce []byte, sig string, log *logrus.Entry) (claims *tokens.ClientIDClaims, err error) {
   218  	if remote == nil {
   219  		log.Errorf("no remote connection details received")
   220  		return nil, fmt.Errorf("remote client information is required in anonymous TLS or JWT signing modes")
   221  	}
   222  
   223  	claims, err = a.parseClientIDJWT(jwts)
   224  	if err != nil {
   225  		log.Errorf("could not parse JWT from %s: %s", remote.String(), err)
   226  		return nil, fmt.Errorf("invalid JWT token")
   227  	}
   228  
   229  	_, err = a.verifyNonceSignature(nonce, sig, claims.PublicKey, log)
   230  	if err != nil {
   231  		log.Errorf("nonce signature verification failed: %s", err)
   232  		return nil, fmt.Errorf("invalid nonce signature")
   233  	}
   234  
   235  	return claims, nil
   236  }
   237  
   238  func (a *ChoriaAuth) handleDefaultConnection(c server.ClientAuthentication, conn *tls.ConnectionState, tlsVerified bool, log *logrus.Entry) (bool, error) {
   239  	user := a.createUser(c)
   240  	remote := c.RemoteAddress()
   241  	opts := c.GetOpts()
   242  	nonce := c.GetNonce()
   243  	jwts := opts.Token
   244  	caller := ""
   245  	pipeConnection := remote.String() == "pipe"
   246  
   247  	var err error
   248  
   249  	log = log.WithField("mTLS", tlsVerified)
   250  	log = log.WithField("name", opts.Name)
   251  	if pipeConnection {
   252  		log = log.WithField("pipe", true)
   253  	}
   254  
   255  	if tlsVerified && len(conn.PeerCertificates) > 0 {
   256  		log = log.WithField("subject", conn.PeerCertificates[0].Subject.CommonName)
   257  	}
   258  	if user.Account != nil {
   259  		log = log.WithField("account", user.Account.Name)
   260  	}
   261  
   262  	var (
   263  		serverClaims   *tokens.ServerClaims
   264  		clientClaims   *tokens.ClientIDClaims
   265  		setClientPerms bool
   266  		setServerPerms bool
   267  	)
   268  
   269  	shouldPerformJWTBasedAuth := jwts != emptyString && conn != nil
   270  	if shouldPerformJWTBasedAuth {
   271  		purpose := tokens.TokenPurpose(jwts)
   272  		log = log.WithFields(logrus.Fields{"jwt_auth": shouldPerformJWTBasedAuth, "purpose": purpose})
   273  		log.Debugf("Performing JWT based authentication verification")
   274  
   275  		switch purpose {
   276  		case tokens.ClientIDPurpose:
   277  			if c.Kind() != server.CLIENT {
   278  				return false, fmt.Errorf("a client JWT was presented by a %d connection", c.Kind())
   279  			}
   280  
   281  			clientClaims, err = a.verifyClientJWTBasedAuth(remote, jwts, nonce, opts.Sig, log)
   282  			if err != nil {
   283  				return false, fmt.Errorf("invalid nonce signature or jwt token")
   284  			}
   285  			log = log.WithField("caller", clientClaims.CallerID)
   286  			log.Debugf("Extracted caller id %s from JWT token", clientClaims.CallerID)
   287  
   288  			caller = clientClaims.CallerID
   289  			setClientPerms = true
   290  			user.Username = caller
   291  
   292  		case tokens.ServerPurpose:
   293  			if c.Kind() != server.CLIENT {
   294  				return false, fmt.Errorf("a server JWT was presented by a %d connection", c.Kind())
   295  			}
   296  
   297  			serverClaims, err = a.verifyServerJWTBasedAuth(remote, jwts, nonce, opts.Sig, log)
   298  			if err != nil {
   299  				return false, fmt.Errorf("invalid nonce signature or jwt token")
   300  			}
   301  			log = log.WithField("identity", serverClaims.ChoriaIdentity)
   302  			log.Debugf("Extracted remote identity %s from JWT token", serverClaims.ChoriaIdentity)
   303  
   304  			setServerPerms = true
   305  			user.Username = serverClaims.ChoriaIdentity
   306  
   307  		default:
   308  			return false, fmt.Errorf("do not know how to handle %v purpose token", purpose)
   309  		}
   310  	}
   311  
   312  	switch {
   313  	case !shouldPerformJWTBasedAuth && !tlsVerified && !pipeConnection:
   314  		log.Warnf("Rejecting unverified connection without token")
   315  		return false, fmt.Errorf("unverified connection without JWT token")
   316  
   317  	// if a caller is set from the Client ID JWT we want to restrict it to just client stuff
   318  	// if a client allow list is set and the client is in the ip range we restrict it also
   319  	// else its default open like users with certs
   320  	case setClientPerms || (!setServerPerms && caller != "" && a.remoteInClientAllowList(remote)):
   321  		log.Debugf("Setting client permissions")
   322  		a.setClientPermissions(user, caller, clientClaims, log)
   323  
   324  	// Else in the case where an allow list is configured we set server permissions on other conns
   325  	case setServerPerms || len(a.clientAllowList) > 0:
   326  		a.setServerPermissions(user, serverClaims, log)
   327  
   328  	case pipeConnection:
   329  		log.Debugf("Allowing pipe connection without any limitations")
   330  
   331  	case tlsVerified && a.allowIssuerBasedTLSAccess:
   332  		log.Debugf("Allowing pub-sub access")
   333  		a.setPubSubPermissions(user)
   334  
   335  	case len(a.issuerTokens) > 0:
   336  		// In issuer mode unless mTLS is in use we do not want to allow any access to any kind of standard nats connection
   337  		// it should be really hard to reach this code at this point, I can't think of a case, but we handle the deny all
   338  		// for safety here
   339  		//
   340  		// to allow pub-sub access users must set a CA (enables mTLS) and connections must be mTLS which will mean allowIssuerBasedTLSAccess
   341  		// is true.
   342  		return false, fmt.Errorf("unknown connection received in issuer mode")
   343  
   344  	default:
   345  		// non issuer mode handled non client || server connections as an allow all
   346  		log.Debugf("Unknown connection type, allowing without restriction for legacy access")
   347  	}
   348  
   349  	if user.Account != nil {
   350  		log.Debugf("Registering user '%s' in account '%s'", user.Username, user.Account.Name)
   351  	} else {
   352  		log.Debugf("Registering user '%s' in default account", user.Username)
   353  	}
   354  
   355  	c.RegisterUser(user)
   356  
   357  	return true, nil
   358  }
   359  
   360  func (a *ChoriaAuth) handleUnverifiedSystemAccount(c server.ClientAuthentication, conn *tls.ConnectionState, log *logrus.Entry) (bool, error) {
   361  	if conn == nil {
   362  		return false, fmt.Errorf("requires TLS")
   363  	}
   364  
   365  	remote := c.RemoteAddress()
   366  	opts := c.GetOpts()
   367  	jwts := opts.Token
   368  
   369  	if jwts == emptyString {
   370  		return false, fmt.Errorf("no JWT token received")
   371  	}
   372  
   373  	purpose := tokens.TokenPurpose(jwts)
   374  	log = log.WithFields(logrus.Fields{"jwt_auth": true, "purpose": purpose, "name": opts.Name})
   375  	log.Debugf("Performing JWT based authentication verification for system account access")
   376  
   377  	if purpose != tokens.ClientIDPurpose {
   378  		return false, fmt.Errorf("client token required")
   379  	}
   380  
   381  	if c.Kind() != server.CLIENT {
   382  		return false, fmt.Errorf("a client JWT was presented by a %d connection", c.Kind())
   383  	}
   384  
   385  	claims, err := a.parseClientIDJWT(jwts)
   386  	if err != nil {
   387  		log.Errorf("could not parse JWT from %s: %s", remote.String(), err)
   388  		return false, fmt.Errorf("invalid JWT token")
   389  	}
   390  
   391  	if claims.Permissions == nil || !(claims.Permissions.SystemUser || claims.Permissions.OrgAdmin) {
   392  		return false, fmt.Errorf("no system_user or org_admin claim")
   393  	}
   394  
   395  	nonce := c.GetNonce()
   396  	_, err = a.verifyNonceSignature(nonce, opts.Sig, claims.PublicKey, log)
   397  	if err != nil {
   398  		log.Errorf("nonce signature verification failed: %s", err)
   399  		return false, fmt.Errorf("invalid nonce signature")
   400  	}
   401  
   402  	return a.handleVerifiedSystemAccount(c, log)
   403  }
   404  
   405  func (a *ChoriaAuth) handleVerifiedSystemAccount(c server.ClientAuthentication, log *logrus.Entry) (bool, error) {
   406  	if a.systemUser == "" {
   407  		return false, fmt.Errorf("system user is required")
   408  	}
   409  
   410  	if a.systemPass == "" {
   411  		return false, fmt.Errorf("system password is required")
   412  	}
   413  
   414  	if a.systemAccount == nil {
   415  		return false, fmt.Errorf("system account is not set")
   416  	}
   417  
   418  	opts := c.GetOpts()
   419  
   420  	if !(opts.Username == a.systemUser && opts.Password == a.systemPass) {
   421  		return false, fmt.Errorf("invalid system credentials")
   422  	}
   423  
   424  	user := a.createUser(c)
   425  	user.Account = a.systemAccount
   426  
   427  	log.Debugf("Registering user '%s' in account '%s'", user.Username, user.Account.Name)
   428  	c.RegisterUser(user)
   429  
   430  	return true, nil
   431  }
   432  
   433  func (a *ChoriaAuth) handleProvisioningUserConnectionWithIssuer(c server.ClientAuthentication) (bool, error) {
   434  	opts := c.GetOpts()
   435  
   436  	if opts.Token == "" && !a.provWithoutToken {
   437  		return false, fmt.Errorf("no token provided in connection")
   438  	}
   439  
   440  	if opts.Token != "" {
   441  		claims, err := a.parseClientIDJWTWithIssuer(opts.Token)
   442  		if err != nil {
   443  			return false, err
   444  		}
   445  
   446  		if claims.Permissions == nil || !claims.Permissions.ServerProvisioner {
   447  			return false, fmt.Errorf("provisioner claim is false in token with caller id '%s'", claims.CallerID)
   448  		}
   449  	}
   450  
   451  	user := a.createUser(c)
   452  	user.Account = a.provisioningAccount
   453  
   454  	a.log.Debugf("Registering user '%s' in account '%s' from claims with", user.Username, user.Account.Name)
   455  	c.RegisterUser(user)
   456  
   457  	return true, nil
   458  }
   459  
   460  func (a *ChoriaAuth) handleProvisioningUserConnectionWithTLS(c server.ClientAuthentication, tlsVerified bool) (bool, error) {
   461  	if !tlsVerified {
   462  		return false, fmt.Errorf("provisioning user is only allowed over verified TLS connections")
   463  	}
   464  
   465  	if !a.isTLS {
   466  		return false, fmt.Errorf("provisioning user access requires TLS")
   467  	}
   468  
   469  	if c.GetTLSConnectionState() == nil {
   470  		return false, fmt.Errorf("provisioning user can only connect over tls")
   471  	}
   472  
   473  	user := a.createUser(c)
   474  	user.Account = a.provisioningAccount
   475  
   476  	a.log.Debugf("Registering user '%s' in account '%s'", user.Username, user.Account.Name)
   477  	c.RegisterUser(user)
   478  
   479  	return true, nil
   480  }
   481  
   482  func (a *ChoriaAuth) handleProvisioningUserConnection(c server.ClientAuthentication, tlsVerified bool) (bool, error) {
   483  	if a.provPass == emptyString {
   484  		return false, fmt.Errorf("provisioning user password not enabled")
   485  	}
   486  
   487  	if a.provisioningAccount == nil {
   488  		return false, fmt.Errorf("provisioning account is not set")
   489  	}
   490  
   491  	opts := c.GetOpts()
   492  
   493  	if opts.Password == emptyString {
   494  		return false, fmt.Errorf("password required")
   495  	}
   496  
   497  	if a.provPass != opts.Password {
   498  		return false, fmt.Errorf("invalid provisioner password supplied")
   499  	}
   500  
   501  	if len(a.issuerTokens) > 0 {
   502  		return a.handleProvisioningUserConnectionWithIssuer(c)
   503  	}
   504  
   505  	return a.handleProvisioningUserConnectionWithTLS(c, tlsVerified)
   506  }
   507  
   508  func (a *ChoriaAuth) handleUnverifiedProvisioningConnectionWithIssuer(c server.ClientAuthentication, opts *server.ClientOpts) (bool, error) {
   509  	if a.provPass == emptyString {
   510  		return false, fmt.Errorf("provisioning is not enabled")
   511  	}
   512  
   513  	user := a.createUser(c)
   514  	user.Account = a.provisioningAccount
   515  
   516  	uclaims, err := tokens.ParseTokenUnverified(opts.Token)
   517  	if err != nil {
   518  		return false, err
   519  	}
   520  
   521  	ou := uclaims["ou"]
   522  	if ou == nil {
   523  		return false, fmt.Errorf("no ou claim in token")
   524  	}
   525  
   526  	ous, ok := ou.(string)
   527  	if !ok {
   528  		return false, fmt.Errorf("invald ou in token")
   529  	}
   530  
   531  	issuer, ok := a.issuerTokens[ous]
   532  	if !ok {
   533  		return false, fmt.Errorf("no issuer found for ou %s", ous)
   534  	}
   535  
   536  	pk, err := a.cachedEd25519Token(issuer)
   537  	if err != nil {
   538  		return false, fmt.Errorf("invalid issuer public key: %w", err)
   539  	}
   540  
   541  	_, err = tokens.ParseProvisioningToken(opts.Token, pk)
   542  	if err != nil {
   543  		return false, err
   544  	}
   545  
   546  	a.log.Debugf("Allowing a provisioning server from using issuer '%s' connecting from %s", ous, c.RemoteAddress().String())
   547  
   548  	// anything that get this far has to be a server and so we unconditionally set server
   549  	// only permissions, and only to agents provisioning would bother hosting.
   550  	//
   551  	// We also allow provisioning.registration.> to allow a mode where prov mode servers
   552  	// would be publishing some known metadata, by convention, this is the only place they
   553  	// can publish to
   554  	a.setProvisioningServerPermissions(user)
   555  
   556  	a.log.Debugf("Registering user '%s' in account '%s'", user.Username, user.Account.Name)
   557  	c.RegisterUser(user)
   558  
   559  	return true, nil
   560  }
   561  
   562  func (a *ChoriaAuth) handleUnverifiedProvisioningConnectionWithTLS(c server.ClientAuthentication, opts *server.ClientOpts) (bool, error) {
   563  	if a.provisioningTokenSigner == emptyString {
   564  		return false, fmt.Errorf("provisioning is not enabled")
   565  	}
   566  
   567  	if !util.FileExist(a.provisioningTokenSigner) {
   568  		return false, fmt.Errorf("provisioning signer certificate %s does not exist", a.provisioningTokenSigner)
   569  	}
   570  
   571  	user := a.createUser(c)
   572  	user.Account = a.provisioningAccount
   573  
   574  	_, err := tokens.ParseProvisioningTokenWithKeyfile(opts.Token, a.provisioningTokenSigner)
   575  	if err != nil {
   576  		return false, err
   577  	}
   578  
   579  	a.log.Debugf("Allowing a provisioning server from using unverified TLS connection from %s", c.RemoteAddress().String())
   580  
   581  	// anything that get this far has to be a server and so we unconditionally set server
   582  	// only permissions, and only to agents provisioning would bother hosting.
   583  	//
   584  	// We also allow provisioning.registration.> to allow a mode where prov mode servers
   585  	// would be publishing some known metadata, by convention, this is the only place they
   586  	// can publish to
   587  	a.setProvisioningServerPermissions(user)
   588  
   589  	a.log.Debugf("Registering user '%s' in account '%s'", user.Username, user.Account.Name)
   590  	c.RegisterUser(user)
   591  
   592  	return true, nil
   593  }
   594  
   595  func (a *ChoriaAuth) setProvisioningServerPermissions(user *server.User) {
   596  	user.Permissions.Subscribe = &server.SubjectPermission{
   597  		Allow: []string{
   598  			"provisioning.node.>",
   599  			"provisioning.broadcast.agent.discovery",
   600  			"provisioning.broadcast.agent.rpcutil",
   601  			"provisioning.broadcast.agent.choria_util",
   602  			"provisioning.broadcast.agent.choria_provision",
   603  		},
   604  	}
   605  
   606  	user.Permissions.Publish = &server.SubjectPermission{
   607  		Allow: []string{
   608  			"choria.lifecycle.>",
   609  			"provisioning.reply.>",
   610  			"provisioning.registration.>",
   611  		},
   612  	}
   613  }
   614  
   615  func (a *ChoriaAuth) handleUnverifiedProvisioningConnection(c server.ClientAuthentication) (bool, error) {
   616  	if a.provisioningAccount == nil {
   617  		return false, fmt.Errorf("provisioning account is not set")
   618  	}
   619  
   620  	opts := c.GetOpts()
   621  	if opts.Username == provisioningUser {
   622  		return false, fmt.Errorf("provisioning user requires a verified connection")
   623  	}
   624  
   625  	if opts.Token == emptyString {
   626  		return false, fmt.Errorf("provisioning requires a token")
   627  	}
   628  
   629  	// we only handle ed25519 signed tokens as issuer tokens
   630  	// since we support also provisioning v1 nodes we have to
   631  	// assume those might have rsa signatures - v2 ones never
   632  	//
   633  	// so we restrict the issuer based validation to ones with ed25519
   634  	// based signatures
   635  	alg, err := tokens.TokenSigningAlgorithm(opts.Token)
   636  	if err != nil {
   637  		return false, fmt.Errorf("could not determine token algorithm: %v", err)
   638  	}
   639  
   640  	if alg == edDSASigningMethod && len(a.issuerTokens) > 0 {
   641  		return a.handleUnverifiedProvisioningConnectionWithIssuer(c, opts)
   642  	}
   643  
   644  	return a.handleUnverifiedProvisioningConnectionWithTLS(c, opts)
   645  }
   646  
   647  func (a *ChoriaAuth) cachedEd25519Token(token string) (ed25519.PublicKey, error) {
   648  	a.mu.Lock()
   649  	defer a.mu.Unlock()
   650  
   651  	if a.tokenCache == nil {
   652  		a.tokenCache = make(map[string]ed25519.PublicKey)
   653  	}
   654  
   655  	pk, ok := a.tokenCache[token]
   656  	if !ok {
   657  		tok, err := hex.DecodeString(token)
   658  		if err != nil {
   659  			return nil, err
   660  		}
   661  		a.tokenCache[token] = tok
   662  		pk = tok
   663  	}
   664  
   665  	return pk, nil
   666  }
   667  
   668  func (a *ChoriaAuth) parseServerJWTWithSigners(jwts string) (claims *tokens.ServerClaims, err error) {
   669  	for _, s := range a.serverJwtSigners {
   670  		// its a token
   671  		if util.IsEncodedEd25519KeyString(s) {
   672  			var pk ed25519.PublicKey
   673  			pk, err = a.cachedEd25519Token(s)
   674  			if err != nil {
   675  				continue
   676  			}
   677  			claims, err = tokens.ParseServerToken(jwts, pk)
   678  		} else {
   679  			claims, err = tokens.ParseServerTokenWithKeyfile(jwts, s)
   680  		}
   681  
   682  		switch {
   683  		case len(a.serverJwtSigners) == 1 && err != nil:
   684  			// just a bit friendlier than saying a generic error with 1 failure
   685  			return nil, err
   686  		case errors.Is(err, jwt.ErrTokenExpired), errors.Is(err, tokens.ErrNotAServerToken):
   687  			// These are fatal errors that no further trying will resolve
   688  			return nil, err
   689  		case err != nil:
   690  			continue
   691  		}
   692  
   693  		break
   694  	}
   695  	if err != nil {
   696  		return nil, fmt.Errorf("could not parse server token with any of %d signer identities", len(a.serverJwtSigners))
   697  	}
   698  
   699  	return claims, nil
   700  }
   701  
   702  func (a *ChoriaAuth) parseServerJWTWithIssuer(jwts string) (claims *tokens.ServerClaims, err error) {
   703  	uclaims, err := tokens.ParseTokenUnverified(jwts)
   704  	if err != nil {
   705  		return nil, err
   706  	}
   707  
   708  	ou := uclaims["ou"]
   709  	if ou == nil {
   710  		return nil, fmt.Errorf("no ou claim in token")
   711  	}
   712  
   713  	ous, ok := ou.(string)
   714  	if !ok {
   715  		return nil, fmt.Errorf("invald ou in token")
   716  	}
   717  
   718  	issuer, ok := a.issuerTokens[ous]
   719  	if !ok {
   720  		return nil, fmt.Errorf("no issuer found for ou %s", ous)
   721  	}
   722  
   723  	pk, err := a.cachedEd25519Token(issuer)
   724  	if err != nil {
   725  		return nil, fmt.Errorf("invalid issuer public key: %w", err)
   726  	}
   727  
   728  	claims, err = tokens.ParseServerToken(jwts, pk)
   729  	if err != nil {
   730  		return nil, fmt.Errorf("failed to parse token issued by the %s chain: %w", ous, err)
   731  	}
   732  
   733  	return claims, nil
   734  }
   735  
   736  func (a *ChoriaAuth) parseServerJWT(jwts string) (claims *tokens.ServerClaims, err error) {
   737  	if len(a.serverJwtSigners) == 0 && len(a.issuerTokens) == 0 {
   738  		return nil, fmt.Errorf("no Server JWT signer or Organization Issuer set, denying all servers")
   739  	}
   740  
   741  	if jwts == emptyString {
   742  		return nil, fmt.Errorf("no JWT received")
   743  	}
   744  
   745  	// if we have issuer tokens we get the org from the token and then check it using the issuer for the org
   746  	if len(a.issuerTokens) > 0 {
   747  		claims, err = a.parseServerJWTWithIssuer(jwts)
   748  		if err != nil {
   749  			return nil, err
   750  		}
   751  	} else {
   752  		// if no issuer we would have signers so we check them all
   753  		claims, err = a.parseServerJWTWithSigners(jwts)
   754  		if err != nil {
   755  			return nil, err
   756  		}
   757  	}
   758  
   759  	if claims.ChoriaIdentity == emptyString {
   760  		return nil, fmt.Errorf("identity not in claims")
   761  	}
   762  
   763  	if claims.PublicKey == emptyString {
   764  		return nil, fmt.Errorf("no public key in claims")
   765  	}
   766  
   767  	return claims, nil
   768  }
   769  
   770  func (a *ChoriaAuth) parseClientJWTWithSigners(jwts string) (claims *tokens.ClientIDClaims, err error) {
   771  	for _, s := range a.clientJwtSigners {
   772  		// its a token
   773  		if util.IsEncodedEd25519KeyString(s) {
   774  			var pk ed25519.PublicKey
   775  			pk, err = a.cachedEd25519Token(s)
   776  			if err != nil {
   777  				continue
   778  			}
   779  			claims, err = tokens.ParseClientIDToken(jwts, pk, true)
   780  		} else {
   781  			claims, err = tokens.ParseClientIDTokenWithKeyfile(jwts, s, true)
   782  		}
   783  
   784  		switch {
   785  		case len(a.clientJwtSigners) == 1 && err != nil:
   786  			// just a bit friendlier than saying a generic error with 1 failure
   787  			return nil, err
   788  		case errors.Is(err, jwt.ErrTokenExpired), errors.Is(err, tokens.ErrNotAClientToken), errors.Is(err, tokens.ErrInvalidClientCallerID):
   789  			// these will tend to fail on every parse, so we try to catch them early and just error when we first hit them
   790  			return nil, err
   791  		case err != nil:
   792  			// we try the next
   793  			continue
   794  		}
   795  
   796  		break
   797  	}
   798  	// above we try to the last, if we still have an error here it failed
   799  	if err != nil {
   800  		return nil, fmt.Errorf("could not parse client token with any of %d signer identities", len(a.clientJwtSigners))
   801  	}
   802  
   803  	return claims, nil
   804  }
   805  
   806  func (a *ChoriaAuth) parseClientIDJWTWithIssuer(jwts string) (claims *tokens.ClientIDClaims, err error) {
   807  	uclaims, err := tokens.ParseTokenUnverified(jwts)
   808  	if err != nil {
   809  		return nil, err
   810  	}
   811  
   812  	ou := uclaims["ou"]
   813  	if ou == nil {
   814  		return nil, fmt.Errorf("no ou claim in token")
   815  	}
   816  
   817  	ous, ok := ou.(string)
   818  	if !ok {
   819  		return nil, fmt.Errorf("invald ou in token")
   820  	}
   821  
   822  	issuer, ok := a.issuerTokens[ous]
   823  	if !ok {
   824  		return nil, fmt.Errorf("no issuer configured for ou '%s'", ous)
   825  	}
   826  
   827  	pk, err := a.cachedEd25519Token(issuer)
   828  	if err != nil {
   829  		return nil, fmt.Errorf("invalid issuer public key: %w", err)
   830  	}
   831  
   832  	claims, err = tokens.ParseClientIDToken(jwts, pk, true)
   833  	if err != nil {
   834  		return nil, fmt.Errorf("failed to parse client token issued by the %s chain: %w", ous, err)
   835  	}
   836  
   837  	return claims, nil
   838  }
   839  
   840  func (a *ChoriaAuth) parseClientIDJWT(jwts string) (claims *tokens.ClientIDClaims, err error) {
   841  	if len(a.clientJwtSigners) == 0 && len(a.issuerTokens) == 0 {
   842  		return nil, fmt.Errorf("no Client JWT signer or Organization Issuer set, denying all clients")
   843  	}
   844  
   845  	if jwts == emptyString {
   846  		return nil, fmt.Errorf("no JWT received")
   847  	}
   848  
   849  	// if we have issuer tokens we get the org from the token and then check it using the issuer for the org
   850  	if len(a.issuerTokens) > 0 {
   851  		claims, err = a.parseClientIDJWTWithIssuer(jwts)
   852  	} else {
   853  		// else we have signers so lets check using those
   854  		claims, err = a.parseClientJWTWithSigners(jwts)
   855  	}
   856  	if err != nil {
   857  		return nil, err
   858  	}
   859  
   860  	if claims.CallerID == emptyString {
   861  		return nil, fmt.Errorf("no callerid in claims")
   862  	}
   863  
   864  	if claims.PublicKey == emptyString {
   865  		return nil, fmt.Errorf("no public key in claims")
   866  	}
   867  
   868  	return claims, nil
   869  }
   870  
   871  func (a *ChoriaAuth) setClientFleetManagementPermissions(subs []string, pubs []string) ([]string, []string) {
   872  	pubs = append(pubs,
   873  		"*.broadcast.agent.>",
   874  		"*.broadcast.service.>",
   875  		"*.node.>",
   876  		"choria.federation.*.federation",
   877  	)
   878  
   879  	return subs, pubs
   880  }
   881  
   882  func (a *ChoriaAuth) setMinimalClientPermissions(_ *server.User, caller string, subs []string, pubs []string) ([]string, []string) {
   883  	replys := "*.reply.>"
   884  	if caller != emptyString {
   885  		replys = fmt.Sprintf("*.reply.%x.>", md5.Sum([]byte(caller)))
   886  		a.log.Debugf("Creating ACLs for a private reply subject on %s", replys)
   887  	}
   888  
   889  	subs = append(subs, replys)
   890  	pubs = append(pubs, "$SYS.REQ.USER.INFO")
   891  
   892  	return subs, pubs
   893  }
   894  
   895  func (a *ChoriaAuth) setStreamsAdminPermissions(user *server.User, subs []string, pubs []string) ([]string, []string) {
   896  	if user.Account != a.choriaAccount {
   897  		return subs, pubs
   898  	}
   899  
   900  	subs = append(subs, "$JS.EVENT.>")
   901  	pubs = append(pubs, "$JS.>")
   902  
   903  	return subs, pubs
   904  }
   905  
   906  func (a *ChoriaAuth) setStreamsUserPermissions(user *server.User, subs []string, pubs []string) ([]string, []string) {
   907  	if user.Account != a.choriaAccount {
   908  		return subs, pubs
   909  	}
   910  
   911  	pubs = append(pubs,
   912  		"$JS.API.INFO",
   913  		"$JS.API.STREAM.NAMES",
   914  		"$JS.API.STREAM.LIST",
   915  		"$JS.API.STREAM.INFO.*",
   916  		"$JS.API.STREAM.MSG.GET.*",
   917  		"$JS.API.STREAM.MSG.DELETE.*",
   918  		"$JS.API.DIRECT.GET.*",
   919  		"$JS.API.DIRECT.GET.*.>",
   920  		"$JS.API.CONSUMER.CREATE.*",
   921  		"$JS.API.CONSUMER.CREATE.*.>",
   922  		"$JS.API.CONSUMER.DURABLE.CREATE.*.*",
   923  		"$JS.API.CONSUMER.DELETE.*.*",
   924  		"$JS.API.CONSUMER.NAMES.*",
   925  		"$JS.API.CONSUMER.LIST.*",
   926  		"$JS.API.CONSUMER.INFO.*.*",
   927  		"$JS.API.CONSUMER.MSG.NEXT.*.*",
   928  		"$JS.ACK.>",
   929  		"$JS.FC.>",
   930  		"$KV.>",
   931  		"$O.>",
   932  	)
   933  
   934  	return subs, pubs
   935  }
   936  
   937  func (a *ChoriaAuth) setEventsViewerPermissions(user *server.User, subs []string, pubs []string) ([]string, []string) {
   938  	switch user.Account {
   939  	case a.choriaAccount:
   940  		subs = append(subs,
   941  			"choria.lifecycle.event.>",
   942  			"choria.machine.watcher.>",
   943  			"choria.machine.transition")
   944  	case a.provisioningAccount:
   945  		// provisioner should only listen to one specific kind of event, not strictly needed but its what it is
   946  		subs = append(subs, "choria.lifecycle.event.*.provision_mode_server")
   947  	}
   948  
   949  	return subs, pubs
   950  }
   951  
   952  func (a *ChoriaAuth) setClientGovernorPermissions(user *server.User, subs []string, pubs []string) ([]string, []string) {
   953  	if user.Account != a.choriaAccount {
   954  		return subs, pubs
   955  	}
   956  
   957  	pubs = append(pubs, "*.governor.*")
   958  	pubs = append(pubs, "choria.lifecycle.event.governor.>")
   959  
   960  	return subs, pubs
   961  }
   962  
   963  func (a *ChoriaAuth) setElectionPermissions(user *server.User, subs []string, pubs []string) ([]string, []string) {
   964  	switch user.Account {
   965  	case a.choriaAccount:
   966  		pubs = append(pubs,
   967  			"$JS.API.STREAM.INFO.KV_CHORIA_LEADER_ELECTION",
   968  			"$KV.CHORIA_LEADER_ELECTION.>")
   969  	case a.provisioningAccount:
   970  		// provisioner account is special and can only access one very specific election
   971  		pubs = append(pubs,
   972  			"choria.streams.STREAM.INFO.KV_CHORIA_LEADER_ELECTION",
   973  			"$KV.CHORIA_LEADER_ELECTION.provisioner")
   974  	}
   975  
   976  	return subs, pubs
   977  }
   978  
   979  func (a *ChoriaAuth) setClientTokenPermissions(user *server.User, caller string, client *tokens.ClientIDClaims, log *logrus.Entry) (pubs []string, subs []string, pubsDeny []string, subsDeny []string, err error) {
   980  	var perms *tokens.ClientPermissions
   981  
   982  	if client != nil {
   983  		perms = client.Permissions
   984  	}
   985  
   986  	if perms != nil && perms.OrgAdmin {
   987  		log.Infof("Granting user access to all subjects (OrgAdmin)")
   988  		return allSubjects, allSubjects, nil, nil, nil
   989  	}
   990  
   991  	subs, pubs = a.setMinimalClientPermissions(user, caller, subs, pubs)
   992  
   993  	if client != nil {
   994  		subs = append(subs, client.AdditionalSubscribeSubjects...)
   995  		pubs = append(pubs, client.AdditionalPublishSubjects...)
   996  	}
   997  
   998  	if perms != nil {
   999  		var matched bool
  1000  
  1001  		// Can access full Streams Features
  1002  		if perms.StreamsAdmin {
  1003  			log.Debugf("Granting user Streams Admin access")
  1004  			matched = true
  1005  			subs, pubs = a.setStreamsAdminPermissions(user, subs, pubs)
  1006  		}
  1007  
  1008  		// Can use streams but not make new ones etc
  1009  		if perms.StreamsUser {
  1010  			log.Debugf("Granting user Streams User access")
  1011  			matched = true
  1012  			subs, pubs = a.setStreamsUserPermissions(user, subs, pubs)
  1013  		}
  1014  
  1015  		// Lifecycle and auto agent events
  1016  		if perms.EventsViewer {
  1017  			log.Debugf("Granting user Events Viewer access")
  1018  			matched = true
  1019  			subs, pubs = a.setEventsViewerPermissions(user, subs, pubs)
  1020  		}
  1021  
  1022  		// KV based elections
  1023  		if perms.ElectionUser {
  1024  			log.Debugf("Granting user Leader Election access")
  1025  			matched = true
  1026  			subs, pubs = a.setElectionPermissions(user, subs, pubs)
  1027  		}
  1028  
  1029  		if perms.Governor && (perms.StreamsUser || perms.StreamsAdmin) {
  1030  			log.Debugf("Granting user Governor access")
  1031  			matched = true
  1032  			subs, pubs = a.setClientGovernorPermissions(user, subs, pubs)
  1033  		}
  1034  
  1035  		if perms.FleetManagement || perms.SignedFleetManagement {
  1036  			log.Debugf("Granting user fleet management access")
  1037  			matched = true
  1038  			subs, pubs = a.setClientFleetManagementPermissions(subs, pubs)
  1039  		}
  1040  
  1041  		if !matched {
  1042  			if len(subs) == 0 {
  1043  				subsDeny = allSubjects
  1044  			}
  1045  			if len(pubs) == 0 {
  1046  				pubsDeny = allSubjects
  1047  			}
  1048  		}
  1049  	}
  1050  
  1051  	// we only lock down the choria account on deny all basis, not relevant today, but eventually we hope to use accounts more
  1052  	if user.Account == a.choriaAccount {
  1053  		// when an allow list is given and no deny, deny is implied.  But no allow means deny is also wide open, so this handles that case
  1054  		if len(pubs) == 0 {
  1055  			pubsDeny = allSubjects
  1056  		}
  1057  		if len(subs) == 0 {
  1058  			subsDeny = allSubjects
  1059  		}
  1060  	}
  1061  
  1062  	return pubs, subs, pubsDeny, subsDeny, nil
  1063  }
  1064  
  1065  func (a *ChoriaAuth) setClientPermissions(user *server.User, caller string, client *tokens.ClientIDClaims, log *logrus.Entry) {
  1066  	user.Permissions.Subscribe = &server.SubjectPermission{}
  1067  	user.Permissions.Publish = &server.SubjectPermission{}
  1068  
  1069  	pubs, subs, pubDeny, subDeny, err := a.setClientTokenPermissions(user, caller, client, log)
  1070  	if err != nil {
  1071  		log.Warnf("Could not determine permissions for user, denying all: %s", err)
  1072  		user.Permissions.Subscribe.Deny = allSubjects
  1073  		user.Permissions.Publish.Deny = allSubjects
  1074  	} else {
  1075  		user.Permissions.Subscribe.Allow = subs
  1076  		user.Permissions.Subscribe.Deny = subDeny
  1077  		user.Permissions.Publish.Allow = pubs
  1078  		user.Permissions.Publish.Deny = pubDeny
  1079  	}
  1080  
  1081  	log.Debugf("Setting sub permissions: %#v", user.Permissions.Subscribe)
  1082  	log.Debugf("Setting pub permissions: %#v", user.Permissions.Publish)
  1083  	if user.Permissions.Response != nil {
  1084  		log.Debugf("Setting resp permissions: %#v", user.Permissions.Response)
  1085  	}
  1086  }
  1087  
  1088  func (a *ChoriaAuth) setDenyServersPermissions(user *server.User) {
  1089  	user.Permissions.Subscribe = &server.SubjectPermission{
  1090  		Deny: allSubjects,
  1091  	}
  1092  
  1093  	user.Permissions.Publish = &server.SubjectPermission{
  1094  		Deny: allSubjects,
  1095  	}
  1096  }
  1097  
  1098  func (a *ChoriaAuth) setClaimsBasedServerPermissions(user *server.User, claims *tokens.ServerClaims, log *logrus.Entry) {
  1099  	if len(claims.Collectives) == 0 {
  1100  		log.Warnf("No collectives in server token, denying access")
  1101  		a.setDenyServersPermissions(user)
  1102  		return
  1103  	}
  1104  
  1105  	user.Permissions.Subscribe = &server.SubjectPermission{}
  1106  	user.Permissions.Publish = &server.SubjectPermission{
  1107  		Allow: []string{
  1108  			"choria.lifecycle.>",
  1109  			"choria.machine.transition",
  1110  			"choria.machine.watcher.>",
  1111  		},
  1112  	}
  1113  
  1114  	user.Permissions.Publish.Allow = append(user.Permissions.Publish.Allow, claims.AdditionalPublishSubjects...)
  1115  
  1116  	for _, c := range claims.Collectives {
  1117  		user.Permissions.Publish.Allow = append(user.Permissions.Publish.Allow,
  1118  			fmt.Sprintf("%s.reply.>", c),
  1119  			fmt.Sprintf("%s.broadcast.agent.registration", c),
  1120  			fmt.Sprintf("choria.federation.%s.collective", c),
  1121  		)
  1122  
  1123  		user.Permissions.Subscribe.Allow = append(user.Permissions.Subscribe.Allow,
  1124  			fmt.Sprintf("%s.broadcast.agent.>", c),
  1125  			fmt.Sprintf("%s.node.%s", c, claims.ChoriaIdentity),
  1126  			fmt.Sprintf("%s.reply.%x.>", c, md5.Sum([]byte(claims.ChoriaIdentity))),
  1127  		)
  1128  
  1129  		if claims.Permissions != nil {
  1130  			if claims.Permissions.ServiceHost {
  1131  				user.Permissions.Subscribe.Allow = append(user.Permissions.Subscribe.Allow,
  1132  					fmt.Sprintf("%s.broadcast.service.>", c),
  1133  				)
  1134  			}
  1135  
  1136  			if claims.Permissions.Submission {
  1137  				user.Permissions.Publish.Allow = append(user.Permissions.Publish.Allow,
  1138  					fmt.Sprintf("%s.submission.in.>", c),
  1139  				)
  1140  			}
  1141  
  1142  			if claims.Permissions.Governor && claims.Permissions.Streams {
  1143  				user.Permissions.Publish.Allow = append(user.Permissions.Publish.Allow,
  1144  					fmt.Sprintf("%s.governor.*", c),
  1145  				)
  1146  			}
  1147  		}
  1148  	}
  1149  
  1150  	if claims.Permissions != nil && claims.Permissions.Streams {
  1151  		prefix := "$JS.API"
  1152  		if claims.OrganizationUnit != "choria" {
  1153  			prefix = "choria.streams"
  1154  		}
  1155  
  1156  		user.Permissions.Publish.Allow = append(user.Permissions.Publish.Allow,
  1157  			fmt.Sprintf("%s.STREAM.INFO.*", prefix),
  1158  			fmt.Sprintf("%s.STREAM.MSG.GET.*", prefix),
  1159  			fmt.Sprintf("%s.STREAM.MSG.DELETE.*", prefix),
  1160  			fmt.Sprintf("%s.DIRECT.GET.*", prefix),
  1161  			fmt.Sprintf("%s.DIRECT.GET.*.>", prefix),
  1162  			fmt.Sprintf("%s.CONSUMER.CREATE.*", prefix),
  1163  			fmt.Sprintf("%s.CONSUMER.CREATE.*.>", prefix),
  1164  			fmt.Sprintf("%s.CONSUMER.DURABLE.CREATE.*.*", prefix),
  1165  			fmt.Sprintf("%s.CONSUMER.INFO.*.*", prefix),
  1166  			fmt.Sprintf("%s.CONSUMER.MSG.NEXT.*.*", prefix),
  1167  			"$JS.ACK.>",
  1168  			"$JS.FC.>",
  1169  		)
  1170  	}
  1171  }
  1172  
  1173  func (a *ChoriaAuth) setDefaultServerPermissions(user *server.User) {
  1174  	user.Permissions.Subscribe = &server.SubjectPermission{
  1175  		Deny: []string{
  1176  			"*.reply.>",
  1177  			"choria.federation.>",
  1178  			"choria.lifecycle.>",
  1179  		},
  1180  	}
  1181  
  1182  	user.Permissions.Publish = &server.SubjectPermission{
  1183  		Allow: allSubjects,
  1184  
  1185  		Deny: []string{
  1186  			"*.broadcast.agent.>",
  1187  			"*.broadcast.service.>",
  1188  			"*.node.>",
  1189  			"choria.federation.*.federation",
  1190  		},
  1191  	}
  1192  }
  1193  
  1194  func (a *ChoriaAuth) setPubSubPermissions(user *server.User) {
  1195  	user.Permissions.Publish = &server.SubjectPermission{
  1196  		Allow: allSubjects,
  1197  		Deny: []string{
  1198  			"*.broadcast.>",
  1199  			"*.node.>",
  1200  			"*.reply.>",
  1201  			"choria.federation.>",
  1202  			"choria.lifecycle.>",
  1203  			"choria.machine.>",
  1204  		},
  1205  	}
  1206  
  1207  	user.Permissions.Subscribe = &server.SubjectPermission{
  1208  		Allow: allSubjects,
  1209  		Deny: []string{
  1210  			"*.broadcast.>",
  1211  			"*.node.>",
  1212  			"*.reply.>",
  1213  			"choria.federation.>",
  1214  			"choria.lifecycle.>",
  1215  			"choria.machine.>",
  1216  		},
  1217  	}
  1218  }
  1219  
  1220  func (a *ChoriaAuth) setServerPermissions(user *server.User, claims *tokens.ServerClaims, log *logrus.Entry) {
  1221  	switch {
  1222  	case a.denyServers:
  1223  		log.Debugf("Setting server permissions, denying servers")
  1224  		a.setDenyServersPermissions(user)
  1225  
  1226  	case claims != nil:
  1227  		log.Debugf("Setting server permissions based on token claims")
  1228  		a.setClaimsBasedServerPermissions(user, claims, log)
  1229  
  1230  	default:
  1231  		log.Debugf("Setting default server permissions")
  1232  		a.setDefaultServerPermissions(user)
  1233  	}
  1234  }
  1235  
  1236  func (a *ChoriaAuth) remoteInClientAllowList(remote net.Addr) bool {
  1237  	if len(a.clientAllowList) == 0 {
  1238  		return true
  1239  	}
  1240  
  1241  	if remote == nil {
  1242  		return false
  1243  	}
  1244  
  1245  	host, _, err := net.SplitHostPort(remote.String())
  1246  	if err != nil {
  1247  		a.log.Warnf("Could not extract host from remote, not allowing access to client targets: '%s': %s", remote.String(), err)
  1248  
  1249  		return false
  1250  	}
  1251  
  1252  	for _, allowed := range a.clientAllowList {
  1253  		if host == allowed {
  1254  			return true
  1255  		}
  1256  
  1257  		if strings.Contains(allowed, "/") {
  1258  			_, ipnet, err := net.ParseCIDR(allowed)
  1259  			if err != nil {
  1260  				a.log.Warnf("Could not parse %s as a cidr: %s", allowed, err)
  1261  				continue
  1262  			}
  1263  
  1264  			if ipnet.Contains(net.ParseIP(host)) {
  1265  				return true
  1266  			}
  1267  		}
  1268  	}
  1269  
  1270  	return false
  1271  }
  1272  
  1273  func (a *ChoriaAuth) isProvisionUser(c server.ClientAuthentication) bool {
  1274  	opts := c.GetOpts()
  1275  	return opts.Username == provisioningUser
  1276  }
  1277  
  1278  func (a *ChoriaAuth) isSystemUser(c server.ClientAuthentication) bool {
  1279  	if a.systemUser == "" {
  1280  		return false
  1281  	}
  1282  
  1283  	opts := c.GetOpts()
  1284  	return opts.Username == a.systemUser
  1285  }
  1286  
  1287  func (a *ChoriaAuth) createUser(c server.ClientAuthentication) *server.User {
  1288  	opts := c.GetOpts()
  1289  
  1290  	acct := a.choriaAccount
  1291  
  1292  	return &server.User{
  1293  		Username:    opts.Username,
  1294  		Password:    opts.Password,
  1295  		Account:     acct,
  1296  		Permissions: &server.Permissions{},
  1297  	}
  1298  }