Documentation
¶
Overview ¶
Package auth authenticates requests and seeds the built-in principals (decision 0005). Passwords are Argon2id hashes in PHC string form, so the cost parameters travel with each hash and can be raised without breaking the hashes already stored.
Index ¶
- Constants
- Variables
- func AccessLockSettings(ctx context.Context, settings store.SettingsStore) (types.AccessLockSettings, error)
- func BasicAuthEnabled(ctx context.Context, settings store.SettingsStore) (bool, error)
- func CheckPassword(stored []byte, password string) (bool, error)
- func ExpirationPolicy(ctx context.Context, settings store.SettingsStore) (types.PasswordExpirationPolicy, error)
- func HashPassword(password string) ([]byte, error)
- func HashPasswordWith(p HashParams, password string) ([]byte, error)
- func LockPolicy(ctx context.Context, settings store.SettingsStore) (types.UserLockPolicy, error)
- func LooksLikeToken(s string) bool
- func PasswordExpired(u types.User, p types.PasswordExpirationPolicy, now time.Time) bool
- func Seed(ctx context.Context, st store.Store, adminPassword string, now time.Time) (bool, error)
- func SeedHashed(ctx context.Context, st store.Store, adminHash []byte, now time.Time) (bool, error)
- func Seeded(ctx context.Context, st store.Store) (bool, error)
- func WithExpiredToken(ctx context.Context, r Refresher) context.Context
- func WithPrincipal(ctx context.Context, p Principal) context.Context
- type Authenticator
- func (a *Authenticator) AnonymousAllowed(ctx context.Context) (bool, error)
- func (a *Authenticator) Basic(ctx context.Context, name, password string) (Principal, error)
- func (a *Authenticator) ExpiredToken(ctx context.Context, raw string) (Refresher, bool)
- func (a *Authenticator) ForgetPolicies()
- func (a *Authenticator) Token(ctx context.Context, raw, user string) (Principal, error)
- type ExpiredVerifier
- type HashParams
- type Options
- type Principal
- type Refresher
- type TokenVerifier
Constants ¶
const ( // DefaultCacheSize bounds the verified-credentials cache. An entry is a // 32-byte key and an expiry, so the bound costs well under a megabyte. DefaultCacheSize = 10_000 // DefaultCacheTTL is how long a verified password skips Argon2. The JFrog // CLI sends Basic credentials on every request, so without the cache a // large upload would pay 64 MiB and tens of milliseconds per call. DefaultCacheTTL = 5 * time.Minute )
Defaults for the zero Options fields.
const ( DefaultLoginAttempts = 5 DefaultPasswordMaxAgeDays = 60 )
The policies' defaults when nothing is stored, as Artifactory ships them.
const ( AdminUser = "admin" ReadersGroup = "readers" AnythingPermission = "Anything" // AnyRemotePermission covers every remote repository and grants no one // anything. Artifactory has shipped it without anonymous since 7.84.3, so // a request without credentials reaches remote content only through a // permission an administrator writes for anonymous. AnyRemotePermission = "Any Remote" )
Names of the built-in principals Artifactory ships (research 05).
const AnonymousUser = "anonymous"
AnonymousUser is the name of the built-in anonymous user.
Variables ¶
var ( // ErrBadCredentials answers credentials that do not verify. ErrBadCredentials = apierror.New(http.StatusUnauthorized, "Bad credentials") // ErrUnauthenticated answers a request that needs a user and has none. ErrUnauthenticated = apierror.New(http.StatusUnauthorized, "Authentication is required") // ErrForbidden answers an authenticated user without the right. ErrForbidden = apierror.New(http.StatusForbidden, "Forbidden") )
The messages JFrog clients print. No public source documents Artifactory's exact wording; jfrog-client-go shows errors[].message as it comes.
var Anonymous = Principal{Name: AnonymousUser, Anonymous: true}
Anonymous is the principal of a request without credentials when anonymous access is on.
var ErrAccountLocked = apierror.New(http.StatusForbidden,
"User is Locked.\nContact System Administrator to Unlock The Account.")
ErrAccountLocked answers any password for a locked account. 403, as Artifactory's entry point answers a locked user, with the message of its UserLockedException, newline included (OSS 6.20; decision 0005). It differs from the temporary suspension's 403 (suspension.go), which ends by itself, where this lasts until an administrator unlocks the account.
var ErrBasicAuthDisabled = apierror.New(http.StatusUnauthorized,
"Basic authentication with a password is disabled; use an access token")
ErrBasicAuthDisabled answers a user name and password while the platform accepts only tokens (basic_authentication_enabled is false).
var ErrHashFormat = errors.New("auth: unsupported password hash")
ErrHashFormat reports a stored password hash that is not an Argon2id PHC string this package can verify.
var ErrInvalidToken = errors.New("invalid token")
ErrInvalidToken reports a token that does not verify: malformed, badly signed, expired, revoked, or of a subject that is not a user. Verifiers wrap it; the request answers ErrBadCredentials.
var ErrLoginSuspended = errors.New("auth: login temporarily suspended")
ErrLoginSuspended reports a Basic login refused because its user name is suspended. The error also carries the 403 the client gets.
var ErrPasswordExpired = apierror.New(http.StatusForbidden, "Password has expired")
ErrPasswordExpired answers a correct password the expiration policy, or an administrator, has expired. It is reported only after the password verifies, so it tells nothing to someone without it. 403 rather than 401, with Artifactory's message: its entry point answers a CredentialsExpiredException as it does a locked account (decision 0005).
Functions ¶
func AccessLockSettings ¶
func AccessLockSettings( ctx context.Context, settings store.SettingsStore, ) (types.AccessLockSettings, error)
AccessLockSettings returns the stored Access user lock settings, or types.DefaultAccessLockSettings.
func BasicAuthEnabled ¶
BasicAuthEnabled reports whether user names and passwords are accepted over HTTP Basic. Unset means on, as Artifactory ships.
func CheckPassword ¶
CheckPassword reports whether password matches the stored hash.
func ExpirationPolicy ¶
func ExpirationPolicy( ctx context.Context, settings store.SettingsStore, ) (types.PasswordExpirationPolicy, error)
ExpirationPolicy returns the stored password expiration policy, or the default.
func HashPassword ¶
HashPassword returns the Argon2id hash of password in PHC form, with the production parameters.
func HashPasswordWith ¶
func HashPasswordWith(p HashParams, password string) ([]byte, error)
HashPasswordWith is HashPassword with the given parameters.
func LockPolicy ¶
func LockPolicy(ctx context.Context, settings store.SettingsStore) (types.UserLockPolicy, error)
LockPolicy returns the stored user lock policy, or the default.
func LooksLikeToken ¶
LooksLikeToken reports whether a Basic password is an access or reference token rather than a password: the JFrog CLI sends tokens as the password of a Basic credential.
func PasswordExpired ¶
PasswordExpired reports whether u must set a new password. An administrator's expiry applies whatever the policy; age counts only from a recorded change, so users whose password predates the record (the seeded admin of an older install) are not locked out by enabling it.
func Seed ¶
Seed creates, in one transaction, the admin user with adminPassword, the anonymous user, the readers group, the Anything and Any Remote permissions and the artifactory-build-info repository, then marks the store seeded. It reports whether this call seeded: false when the store already was, including when another instance sharing the database won a race to seed it first.
func SeedHashed ¶
func SeedHashed( ctx context.Context, st store.Store, adminHash []byte, now time.Time, ) (bool, error)
SeedHashed is Seed with the admin password already hashed (HashPassword or HashPasswordWith).
func WithExpiredToken ¶
WithExpiredToken returns ctx carrying the expired access token a refresh request presented as its credential (Authenticator.ExpiredToken).
Types ¶
type Authenticator ¶
type Authenticator struct {
// contains filtered or unexported fields
}
Authenticator verifies credentials against the user store.
func NewAuthenticator ¶
func NewAuthenticator( users store.UserStore, settings store.SettingsStore, o Options, ) (*Authenticator, error)
NewAuthenticator returns an Authenticator over users and settings.
func (*Authenticator) AnonymousAllowed ¶
func (a *Authenticator) AnonymousAllowed(ctx context.Context) (bool, error)
AnonymousAllowed reports whether requests without credentials act as the anonymous user. The setting is a JSON boolean; unset means off, as in Artifactory.
func (*Authenticator) Basic ¶
Basic verifies a user name and password. Wrong credentials, an unknown or disabled user, and a user without an internal password all answer ErrBadCredentials alike; while basic authentication is switched off, every password answers ErrBasicAuthDisabled. A locked account answers ErrAccountLocked whatever the password. A correct but expired password answers ErrPasswordExpired with the principal, marked PasswordExpired. While the name is temporarily suspended after failed logins, every password answers ErrLoginSuspended (suspension.go).
func (*Authenticator) ExpiredToken ¶
ExpiredToken verifies raw as an access token whatever its expiry, and whose user is still enabled. Only the refresh grant asks: the JFrog CLI refreshes with the access token it is replacing, by then often expired, as the Bearer credential (Access) or the access_token form field (legacy).
func (*Authenticator) ForgetPolicies ¶
func (a *Authenticator) ForgetPolicies()
ForgetPolicies drops the cached policies, so a change made through this instance applies to its next login.
func (*Authenticator) Token ¶
Token verifies a token presented as Bearer, as X-JFrog-Art-Api, or as the password of a Basic credential whose user name is user ("" for the first two). A Basic user name must name the token's subject (decision 0005). The subject must still be an enabled user: disabling a user disables their tokens.
type ExpiredVerifier ¶
type ExpiredVerifier interface {
VerifyExpired(ctx context.Context, raw string) (types.Token, error)
}
ExpiredVerifier is a TokenVerifier that also verifies an access token whose only fault is its expiry. internal/auth/token implements it.
type HashParams ¶
HashParams are Argon2id's cost parameters. The zero value means the production parameters; the only other use is tests, which hash with tiny costs to stay fast. Nothing in configuration or on the command line can set them: verification reads the cost from each stored hash, so a cheap hash only ever comes from code that asked for one.
type Options ¶
type Options struct {
CacheSize int
CacheTTL time.Duration
// Concurrency bounds the password hashes computed at once; zero means
// GOMAXPROCS. Each costs the hash's memory parameter, so without a bound
// a flood of wrong passwords could exhaust memory.
Concurrency int
// Now supplies the time; nil means time.Now.
Now func() time.Time
// Hash is the cost of the dummy hash checked for unknown users; the
// zero value means the production parameters. Tests set tiny costs.
Hash HashParams
// Tokens verifies access and reference tokens; nil refuses every token.
Tokens TokenVerifier
// Groups names the groups new users join automatically, which the
// transient user of a transient token joins (types.IdentityTransient);
// nil means none.
Groups store.GroupStore
}
Options configures NewAuthenticator.
type Principal ¶
type Principal struct {
Name string
Admin bool
Anonymous bool
Groups []string
// Scope is the scope of the access token the request presented; empty
// for a password or anonymous request, which act with the user's full
// permissions. Scopes only narrow (decision 0005); the permission
// evaluator applies them.
Scope types.Scope
// TokenID is the id of the access or reference token the request
// presented; empty for a password or anonymous request. The token API's
// "me" resolves to it, and encryptedPassword refuses token callers.
TokenID string
// TokenExpires is when that token expires; zero for a password, an
// anonymous request or a token that never expires. A registry token
// obtained with a token lives no longer (decision 0005).
TokenExpires time.Time
// Registry is what a registry token grants, nil for any other
// credential. Such a principal reaches the registry's routes alone.
Registry *types.RegistryAccess
// Identity is how the token's subject resolved to a user: transient or
// synthetic for a token from an OIDC exchange, transient for one an
// administrator minted for a name that is no stored user; a registry
// token obtained with it keeps it (decision 0005).
Identity types.TokenIdentity
// TokenParent is, for a registry token, the stored token it descends
// from: a registry token it obtains descends from the same one.
TokenParent string
// PasswordExpired marks a principal whose correct password has expired.
// The middleware lets it through only to change its own password.
PasswordExpired bool
// Password marks a principal that a user name and password
// authenticated, which the Access token API refuses while
// token.allow_basic_auth is off (#385). An empty TokenID cannot stand
// for it: anonymous and hand-built principals have none either.
Password bool
// contains filtered or unexported fields
}
Principal is who a request acts as.
func Authorize ¶
Authorize evaluates p's permissions once for the request (decision 0006) and returns p with Admin and Groups set to what the evaluator decides: a token scope can remove the admin flag and narrow the groups, and an admin-privilege group makes a member an administrator. Handlers then ask Access() every permission question.
func FromContext ¶
FromContext returns the request's principal; ok is false when the request is unauthenticated (no credentials and anonymous access off).
func RequireAdmin ¶
RequireAdmin returns ErrUnauthenticated without a user and ErrForbidden for a user who is not an administrator, the split Artifactory makes between 401 and 403.
func RequireAuthenticated ¶
RequireAuthenticated returns ErrUnauthenticated unless the request carries a user other than anonymous.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package idtoken verifies ID tokens that an external OpenID Connect provider, typically a CI system, signed: the subject tokens of the Access OIDC token exchange (POST /access/api/v1/oidc/token, research 21).
|
Package idtoken verifies ID tokens that an external OpenID Connect provider, typically a CI system, signed: the subject tokens of the Access OIDC token exchange (POST /access/api/v1/oidc/token, research 21). |
|
idtokentest
Package idtokentest is a fake OpenID Connect provider for tests: it serves a discovery document and a JWKS, as GitHub Actions, GitLab and other CI systems do, and mints ID tokens signed with its current key.
|
Package idtokentest is a fake OpenID Connect provider for tests: it serves a discovery document and a JWKS, as GitHub Actions, GitLab and other CI systems do, and mints ID tokens signed with its current key. |
|
Package token issues and verifies Access tokens (decision 0005): RS256 JWTs signed with a per-instance key, reference tokens and refresh tokens.
|
Package token issues and verifies Access tokens (decision 0005): RS256 JWTs signed with a per-instance key, reference tokens and refresh tokens. |