Merge pull request #1209 from hashicorp/issue-424
Add the ability to specify the app-id in the login path.
This commit is contained in:
commit
8f22dbc5d3
|
@ -68,11 +68,13 @@ func Backend(conf *logical.BackendConfig) (*framework.Backend, error) {
|
|||
PathsSpecial: &logical.Paths{
|
||||
Unauthenticated: []string{
|
||||
"login",
|
||||
"login/*",
|
||||
},
|
||||
},
|
||||
|
||||
Paths: framework.PathAppend([]*framework.Path{
|
||||
pathLogin(&b),
|
||||
pathLoginWithAppIDPath(&b),
|
||||
},
|
||||
b.MapAppId.Paths(),
|
||||
b.MapUserId.Paths(),
|
||||
|
|
|
@ -15,6 +15,7 @@ func TestBackend_basic(t *testing.T) {
|
|||
testAccStepMapAppId(t),
|
||||
testAccStepMapUserId(t),
|
||||
testAccLogin(t, ""),
|
||||
testAccLoginAppIDInPath(t, ""),
|
||||
testAccLoginInvalid(t),
|
||||
testAccStepDeleteUserId(t),
|
||||
testAccLoginDeleted(t),
|
||||
|
@ -42,6 +43,7 @@ func TestBackend_displayName(t *testing.T) {
|
|||
testAccStepMapAppIdDisplayName(t),
|
||||
testAccStepMapUserId(t),
|
||||
testAccLogin(t, "tubbin"),
|
||||
testAccLoginAppIDInPath(t, "tubbin"),
|
||||
testAccLoginInvalid(t),
|
||||
testAccStepDeleteUserId(t),
|
||||
testAccLoginDeleted(t),
|
||||
|
@ -175,7 +177,30 @@ func testAccLogin(t *testing.T, display string) logicaltest.TestStep {
|
|||
Unauthenticated: true,
|
||||
|
||||
Check: logicaltest.TestCheckMulti(
|
||||
logicaltest.TestCheckAuth([]string{"bar", "foo"}),
|
||||
logicaltest.TestCheckAuth([]string{"bar", "default", "foo"}),
|
||||
logicaltest.TestCheckAuthDisplayName(display),
|
||||
checkTTL,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func testAccLoginAppIDInPath(t *testing.T, display string) logicaltest.TestStep {
|
||||
checkTTL := func(resp *logical.Response) error {
|
||||
if resp.Auth.LeaseOptions.TTL.String() != "720h0m0s" {
|
||||
return fmt.Errorf("invalid TTL")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return logicaltest.TestStep{
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "login/foo",
|
||||
Data: map[string]interface{}{
|
||||
"user_id": "42",
|
||||
},
|
||||
Unauthenticated: true,
|
||||
|
||||
Check: logicaltest.TestCheckMulti(
|
||||
logicaltest.TestCheckAuth([]string{"bar", "default", "foo"}),
|
||||
logicaltest.TestCheckAuthDisplayName(display),
|
||||
checkTTL,
|
||||
),
|
||||
|
@ -185,7 +210,7 @@ func testAccLogin(t *testing.T, display string) logicaltest.TestStep {
|
|||
func testAccLoginCidr(t *testing.T, ip string, err bool) logicaltest.TestStep {
|
||||
check := logicaltest.TestCheckError()
|
||||
if !err {
|
||||
check = logicaltest.TestCheckAuth([]string{"bar", "foo"})
|
||||
check = logicaltest.TestCheckAuth([]string{"bar", "default", "foo"})
|
||||
}
|
||||
|
||||
return logicaltest.TestStep{
|
||||
|
|
|
@ -14,9 +14,33 @@ import (
|
|||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
||||
func pathLoginWithAppIDPath(b *backend) *framework.Path {
|
||||
return &framework.Path{
|
||||
Pattern: "login/(?P<app_id>.+)",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"app_id": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: "The unique app ID",
|
||||
},
|
||||
|
||||
"user_id": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: "The unique user ID",
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: b.pathLogin,
|
||||
},
|
||||
|
||||
HelpSynopsis: pathLoginSyn,
|
||||
HelpDescription: pathLoginDesc,
|
||||
}
|
||||
}
|
||||
|
||||
func pathLogin(b *backend) *framework.Path {
|
||||
return &framework.Path{
|
||||
Pattern: "login",
|
||||
Pattern: "login$",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"app_id": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
|
|
|
@ -10,65 +10,63 @@ description: |-
|
|||
|
||||
Name: `app-id`
|
||||
|
||||
The App ID auth backend is a mechanism for machines to authenticate with
|
||||
Vault. It works by requiring two hard-to-guess unique pieces of information:
|
||||
a unique app ID, and a unique user ID.
|
||||
The App ID auth backend is a mechanism for machines to authenticate with Vault.
|
||||
It works by requiring 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).
|
||||
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>)
|
||||
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>)
|
||||
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.
|
||||
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.
|
||||
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
|
||||
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.
|
||||
After creating app IDs, an operator authorizes a fixed set of user IDs 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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
## Authentication
|
||||
|
||||
#### Via the CLI
|
||||
|
||||
App ID authentication is not allowed via the CLI.
|
||||
Use `vault write`, for example: `vault write auth/app-id/login/[app-id] user_id=[user-id]`
|
||||
|
||||
#### Via the API
|
||||
|
||||
The endpoint for the App ID login is `auth/app-id/login`. The client is expected
|
||||
to provide the `app_id` and `user_id` parameters as part of the request.
|
||||
The endpoint for the App ID login is `auth/app-id/login/[app_id]`. The client is expected
|
||||
to provide the `user_id` parameter as part of the request.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
Loading…
Reference in a new issue