2015-04-05 01:40:21 +00:00
|
|
|
package appId
|
|
|
|
|
|
|
|
import (
|
2017-05-08 20:15:24 +00:00
|
|
|
"sync"
|
2015-07-01 01:09:08 +00:00
|
|
|
|
2015-07-01 00:36:12 +00:00
|
|
|
"github.com/hashicorp/vault/helper/salt"
|
2015-04-05 01:40:21 +00:00
|
|
|
"github.com/hashicorp/vault/logical"
|
|
|
|
"github.com/hashicorp/vault/logical/framework"
|
|
|
|
)
|
|
|
|
|
2015-07-01 00:45:20 +00:00
|
|
|
func Factory(conf *logical.BackendConfig) (logical.Backend, error) {
|
2015-07-01 01:09:08 +00:00
|
|
|
b, err := Backend(conf)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
if err := b.Setup(conf); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return b, nil
|
2015-04-05 01:40:21 +00:00
|
|
|
}
|
|
|
|
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
func Backend(conf *logical.BackendConfig) (*backend, error) {
|
2015-04-05 01:40:21 +00:00
|
|
|
var b backend
|
|
|
|
b.MapAppId = &framework.PolicyMap{
|
2015-04-17 17:00:48 +00:00
|
|
|
PathMap: framework.PathMap{
|
|
|
|
Name: "app-id",
|
|
|
|
Schema: map[string]*framework.FieldSchema{
|
|
|
|
"display_name": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: "A name to map to this app ID for logs.",
|
|
|
|
},
|
|
|
|
|
|
|
|
"value": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: "Policies for the app ID.",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-04-05 01:40:21 +00:00
|
|
|
DefaultKey: "default",
|
|
|
|
}
|
2015-04-17 17:00:48 +00:00
|
|
|
|
2015-04-05 01:40:21 +00:00
|
|
|
b.MapUserId = &framework.PathMap{
|
|
|
|
Name: "user-id",
|
2015-04-17 17:14:39 +00:00
|
|
|
Schema: map[string]*framework.FieldSchema{
|
|
|
|
"cidr_block": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Description: "If not blank, restricts auth by this CIDR block",
|
|
|
|
},
|
|
|
|
|
|
|
|
"value": &framework.FieldSchema{
|
|
|
|
Type: framework.TypeString,
|
2015-04-18 20:45:50 +00:00
|
|
|
Description: "App IDs that this user associates with.",
|
2015-04-17 17:14:39 +00:00
|
|
|
},
|
|
|
|
},
|
2015-04-05 01:40:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
b.Backend = &framework.Backend{
|
|
|
|
Help: backendHelp,
|
|
|
|
|
|
|
|
PathsSpecial: &logical.Paths{
|
|
|
|
Unauthenticated: []string{
|
|
|
|
"login",
|
2016-03-14 20:24:01 +00:00
|
|
|
"login/*",
|
2015-04-05 01:40:21 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Paths: framework.PathAppend([]*framework.Path{
|
|
|
|
pathLogin(&b),
|
2016-03-14 20:24:01 +00:00
|
|
|
pathLoginWithAppIDPath(&b),
|
2015-04-05 01:40:21 +00:00
|
|
|
},
|
|
|
|
b.MapAppId.Paths(),
|
|
|
|
b.MapUserId.Paths(),
|
|
|
|
),
|
2017-07-28 18:04:46 +00:00
|
|
|
AuthRenew: b.pathLoginRenew,
|
|
|
|
Invalidate: b.invalidate,
|
|
|
|
BackendType: logical.TypeCredential,
|
2015-07-01 01:09:08 +00:00
|
|
|
}
|
|
|
|
|
2017-02-16 21:29:30 +00:00
|
|
|
b.view = conf.StorageView
|
2017-06-05 14:04:54 +00:00
|
|
|
b.MapAppId.SaltFunc = b.Salt
|
|
|
|
b.MapUserId.SaltFunc = b.Salt
|
|
|
|
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
return &b, nil
|
2015-04-05 01:40:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type backend struct {
|
|
|
|
*framework.Backend
|
|
|
|
|
2017-05-09 21:51:09 +00:00
|
|
|
salt *salt.Salt
|
2017-05-08 20:15:24 +00:00
|
|
|
SaltMutex sync.RWMutex
|
2017-02-16 21:29:30 +00:00
|
|
|
view logical.Storage
|
2015-04-05 01:40:21 +00:00
|
|
|
MapAppId *framework.PolicyMap
|
|
|
|
MapUserId *framework.PathMap
|
|
|
|
}
|
|
|
|
|
2017-05-09 21:51:09 +00:00
|
|
|
func (b *backend) Salt() (*salt.Salt, error) {
|
|
|
|
b.SaltMutex.RLock()
|
|
|
|
if b.salt != nil {
|
|
|
|
defer b.SaltMutex.RUnlock()
|
|
|
|
return b.salt, nil
|
|
|
|
}
|
|
|
|
b.SaltMutex.RUnlock()
|
2017-05-08 20:15:24 +00:00
|
|
|
b.SaltMutex.Lock()
|
2017-05-09 21:51:09 +00:00
|
|
|
defer b.SaltMutex.Unlock()
|
|
|
|
if b.salt != nil {
|
|
|
|
return b.salt, nil
|
|
|
|
}
|
2017-02-16 21:29:30 +00:00
|
|
|
salt, err := salt.NewSalt(b.view, &salt.Config{
|
|
|
|
HashFunc: salt.SHA1Hash,
|
2017-05-05 19:01:52 +00:00
|
|
|
Location: salt.DefaultLocation,
|
2017-02-16 21:29:30 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
2017-05-09 21:51:09 +00:00
|
|
|
return nil, err
|
2015-07-01 01:09:08 +00:00
|
|
|
}
|
2017-05-09 21:51:09 +00:00
|
|
|
b.salt = salt
|
|
|
|
return salt, nil
|
2015-07-01 01:09:08 +00:00
|
|
|
}
|
|
|
|
|
2017-05-05 19:01:52 +00:00
|
|
|
func (b *backend) invalidate(key string) {
|
|
|
|
switch key {
|
|
|
|
case salt.DefaultLocation:
|
2017-05-09 21:51:09 +00:00
|
|
|
b.SaltMutex.Lock()
|
|
|
|
defer b.SaltMutex.Unlock()
|
|
|
|
b.salt = nil
|
2017-05-05 19:01:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-05 01:40:21 +00:00
|
|
|
const backendHelp = `
|
|
|
|
The App ID credential provider is used to perform authentication from
|
|
|
|
within applications or machine by pairing together two hard-to-guess
|
|
|
|
unique pieces of information: a unique app ID, and a unique user ID.
|
|
|
|
|
|
|
|
The goal of this credential provider is to allow elastic users
|
|
|
|
(dynamic machines, containers, etc.) to authenticate with Vault without
|
|
|
|
having to store passwords outside of Vault. It is a single method of
|
|
|
|
solving the chicken-and-egg problem of setting up Vault access on a machine.
|
|
|
|
With this provider, nobody except the machine itself has access to both
|
|
|
|
pieces of information necessary to authenticate. For example:
|
|
|
|
configuration management will have the app IDs, but the machine itself
|
|
|
|
will detect its user ID based on some unique machine property such as a
|
|
|
|
MAC address (or a hash of it with some salt).
|
|
|
|
|
|
|
|
An example, real world process for using this provider:
|
|
|
|
|
|
|
|
1. Create unique app IDs (UUIDs work well) and map them to policies.
|
|
|
|
(Path: map/app-id/<app-id>)
|
|
|
|
|
|
|
|
2. Store the app IDs within configuration management systems.
|
|
|
|
|
|
|
|
3. An out-of-band process run by security operators map unique user IDs
|
|
|
|
to these app IDs. Example: when an instance is launched, a cloud-init
|
|
|
|
system tells security operators a unique ID for this machine. This
|
|
|
|
process can be scripted, but the key is that it is out-of-band and
|
|
|
|
out of reach of configuration management.
|
|
|
|
(Path: map/user-id/<user-id>)
|
|
|
|
|
|
|
|
4. A new server is provisioned. Configuration management configures the
|
|
|
|
app ID, the server itself detects its user ID. With both of these
|
|
|
|
pieces of information, Vault can be accessed according to the policy
|
|
|
|
set by the app ID.
|
|
|
|
|
|
|
|
More details on this process follow:
|
|
|
|
|
|
|
|
The app ID is a unique ID that maps to a set of policies. This ID is
|
|
|
|
generated by an operator and configured into the backend. The ID itself
|
|
|
|
is usually a UUID, but any hard-to-guess unique value can be used.
|
|
|
|
|
|
|
|
After creating app IDs, an operator authorizes a fixed set of user IDs
|
2015-04-29 05:04:58 +00:00
|
|
|
with each app ID. When a valid {app ID, user ID} tuple is given to the
|
|
|
|
"login" path, then the user is authenticated with the configured app
|
|
|
|
ID policies.
|
2015-04-05 01:40:21 +00:00
|
|
|
|
|
|
|
The user ID can be any value (just like the app ID), however it is
|
|
|
|
generally a value unique to a machine, such as a MAC address or instance ID,
|
|
|
|
or a value hashed from these unique values.
|
2015-08-03 16:44:26 +00:00
|
|
|
|
2016-02-12 01:36:07 +00:00
|
|
|
It is possible to authorize multiple app IDs with each
|
2015-08-03 16:44:26 +00:00
|
|
|
user ID by writing them as comma-separated values to the map/user-id/<user-id>
|
2016-02-12 01:36:07 +00:00
|
|
|
path.
|
|
|
|
|
|
|
|
It is also possible to renew the auth tokens with 'vault token-renew <token>' command.
|
|
|
|
Before the token is renewed, the validity of app ID, user ID and the associated
|
|
|
|
policies are checked again.
|
2015-04-05 01:40:21 +00:00
|
|
|
`
|