mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-19 05:31:10 +02:00
Adds the ability to bypass Okta MFA checks. (#3944)
* Adds the ability to bypass Okta MFA checks. Unlike before, the administrator opts-in to this behavior, and is suitably warned. Fixes #3872
This commit is contained in:
parent
65328e9c12
commit
a9a322aa39
@ -115,6 +115,11 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri
|
||||
case "PASSWORD_WARN":
|
||||
oktaResponse.AddWarning("Your Okta password is in warning state and needs to be changed soon.")
|
||||
|
||||
case "MFA_REQUIRED", "MFA_ENROLL":
|
||||
if !cfg.BypassOktaMFA {
|
||||
return nil, logical.ErrorResponse("okta mfa required for this account but mfa bypass not set in config"), nil, nil
|
||||
}
|
||||
|
||||
case "SUCCESS":
|
||||
// Do nothing here
|
||||
|
||||
@ -126,7 +131,13 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri
|
||||
}
|
||||
|
||||
// Verify result status again in case a switch case above modifies result
|
||||
if result.Status != "SUCCESS" && result.Status != "PASSWORD_WARN" {
|
||||
switch {
|
||||
case result.Status == "SUCCESS",
|
||||
result.Status == "PASSWORD_WARN",
|
||||
result.Status == "MFA_REQUIRED" && cfg.BypassOktaMFA,
|
||||
result.Status == "MFA_ENROLL" && cfg.BypassOktaMFA:
|
||||
// Allowed
|
||||
default:
|
||||
if b.Logger().IsDebug() {
|
||||
b.Logger().Debug("auth/okta: authentication returned a non-success status", "status", result.Status)
|
||||
}
|
||||
|
@ -54,6 +54,10 @@ func pathConfig(b *backend) *framework.Path {
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: `Maximum duration after which authentication will be expired`,
|
||||
},
|
||||
"bypass_okta_mfa": &framework.FieldSchema{
|
||||
Type: framework.TypeBool,
|
||||
Description: `When set true, requests by Okta for a MFA check will be bypassed. This also disallows certain status checks on the account, such as whether the password is expired.`,
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
@ -99,10 +103,11 @@ func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, d *f
|
||||
|
||||
resp := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"organization": cfg.Org,
|
||||
"org_name": cfg.Org,
|
||||
"ttl": cfg.TTL.Seconds(),
|
||||
"max_ttl": cfg.MaxTTL.Seconds(),
|
||||
"organization": cfg.Org,
|
||||
"org_name": cfg.Org,
|
||||
"ttl": cfg.TTL.Seconds(),
|
||||
"max_ttl": cfg.MaxTTL.Seconds(),
|
||||
"bypass_okta_mfa": cfg.BypassOktaMFA,
|
||||
},
|
||||
}
|
||||
if cfg.BaseURL != "" {
|
||||
@ -112,6 +117,10 @@ func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, d *f
|
||||
resp.Data["production"] = *cfg.Production
|
||||
}
|
||||
|
||||
if cfg.BypassOktaMFA {
|
||||
resp.AddWarning("Okta MFA bypass is configured. In addition to ignoring Okta MFA requests, certain other account statuses will not be seen, such as PASSWORD_EXPIRED. Authentication will succeed in these cases.")
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@ -175,6 +184,11 @@ func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, d *
|
||||
cfg.Production = nil
|
||||
}
|
||||
|
||||
bypass, ok := d.GetOk("bypass_okta_mfa")
|
||||
if ok {
|
||||
cfg.BypassOktaMFA = bypass.(bool)
|
||||
}
|
||||
|
||||
ttl, ok := d.GetOk("ttl")
|
||||
if ok {
|
||||
cfg.TTL = time.Duration(ttl.(int)) * time.Second
|
||||
@ -197,7 +211,13 @@ func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, d *
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
var resp *logical.Response
|
||||
if cfg.BypassOktaMFA {
|
||||
resp = new(logical.Response)
|
||||
resp.AddWarning("Okta MFA bypass is configured. In addition to ignoring Okta MFA requests, certain other account statuses will not be seen, such as PASSWORD_EXPIRED. Authentication will succeed in these cases.")
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (b *backend) pathConfigExistenceCheck(ctx context.Context, req *logical.Request, d *framework.FieldData) (bool, error) {
|
||||
@ -228,12 +248,13 @@ func (c *ConfigEntry) OktaClient() *okta.Client {
|
||||
|
||||
// ConfigEntry for Okta
|
||||
type ConfigEntry struct {
|
||||
Org string `json:"organization"`
|
||||
Token string `json:"token"`
|
||||
BaseURL string `json:"base_url"`
|
||||
Production *bool `json:"is_production,omitempty"`
|
||||
TTL time.Duration `json:"ttl"`
|
||||
MaxTTL time.Duration `json:"max_ttl"`
|
||||
Org string `json:"organization"`
|
||||
Token string `json:"token"`
|
||||
BaseURL string `json:"base_url"`
|
||||
Production *bool `json:"is_production,omitempty"`
|
||||
TTL time.Duration `json:"ttl"`
|
||||
MaxTTL time.Duration `json:"max_ttl"`
|
||||
BypassOktaMFA bool `json:"bypass_okta_mfa"`
|
||||
}
|
||||
|
||||
const pathConfigHelp = `
|
||||
|
@ -37,6 +37,9 @@ distinction between the `create` and `update` capabilities inside ACL policies.
|
||||
- `ttl` `(string: "")` - Duration after which authentication will be expired.
|
||||
- `max_ttl` `(string: "")` - Maximum duration after which authentication will
|
||||
be expired.
|
||||
- `bypass_okta_mfa` `(bool: false)` - Whether to bypass an Okta MFA request.
|
||||
Useful if using one of Vault's built-in MFA mechanisms, but this will also
|
||||
cause certain other statuses to be ignored, such as `PASSWORD_EXPIRED`.
|
||||
|
||||
### Sample Payload
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user