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":
|
case "PASSWORD_WARN":
|
||||||
oktaResponse.AddWarning("Your Okta password is in warning state and needs to be changed soon.")
|
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":
|
case "SUCCESS":
|
||||||
// Do nothing here
|
// 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
|
// 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() {
|
if b.Logger().IsDebug() {
|
||||||
b.Logger().Debug("auth/okta: authentication returned a non-success status", "status", result.Status)
|
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,
|
Type: framework.TypeDurationSecond,
|
||||||
Description: `Maximum duration after which authentication will be expired`,
|
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{
|
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{
|
resp := &logical.Response{
|
||||||
Data: map[string]interface{}{
|
Data: map[string]interface{}{
|
||||||
"organization": cfg.Org,
|
"organization": cfg.Org,
|
||||||
"org_name": cfg.Org,
|
"org_name": cfg.Org,
|
||||||
"ttl": cfg.TTL.Seconds(),
|
"ttl": cfg.TTL.Seconds(),
|
||||||
"max_ttl": cfg.MaxTTL.Seconds(),
|
"max_ttl": cfg.MaxTTL.Seconds(),
|
||||||
|
"bypass_okta_mfa": cfg.BypassOktaMFA,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if cfg.BaseURL != "" {
|
if cfg.BaseURL != "" {
|
||||||
@ -112,6 +117,10 @@ func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, d *f
|
|||||||
resp.Data["production"] = *cfg.Production
|
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
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +184,11 @@ func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, d *
|
|||||||
cfg.Production = nil
|
cfg.Production = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bypass, ok := d.GetOk("bypass_okta_mfa")
|
||||||
|
if ok {
|
||||||
|
cfg.BypassOktaMFA = bypass.(bool)
|
||||||
|
}
|
||||||
|
|
||||||
ttl, ok := d.GetOk("ttl")
|
ttl, ok := d.GetOk("ttl")
|
||||||
if ok {
|
if ok {
|
||||||
cfg.TTL = time.Duration(ttl.(int)) * time.Second
|
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, 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) {
|
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
|
// ConfigEntry for Okta
|
||||||
type ConfigEntry struct {
|
type ConfigEntry struct {
|
||||||
Org string `json:"organization"`
|
Org string `json:"organization"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
BaseURL string `json:"base_url"`
|
BaseURL string `json:"base_url"`
|
||||||
Production *bool `json:"is_production,omitempty"`
|
Production *bool `json:"is_production,omitempty"`
|
||||||
TTL time.Duration `json:"ttl"`
|
TTL time.Duration `json:"ttl"`
|
||||||
MaxTTL time.Duration `json:"max_ttl"`
|
MaxTTL time.Duration `json:"max_ttl"`
|
||||||
|
BypassOktaMFA bool `json:"bypass_okta_mfa"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathConfigHelp = `
|
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.
|
- `ttl` `(string: "")` - Duration after which authentication will be expired.
|
||||||
- `max_ttl` `(string: "")` - Maximum duration after which authentication will
|
- `max_ttl` `(string: "")` - Maximum duration after which authentication will
|
||||||
be expired.
|
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
|
### Sample Payload
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user