Generate the nonce by default

This commit is contained in:
vishalnayak 2016-09-14 11:17:45 -04:00
parent eece4e047b
commit 53c919b1d0
2 changed files with 68 additions and 27 deletions

View File

@ -9,6 +9,7 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2"
"github.com/fullsailor/pkcs7" "github.com/fullsailor/pkcs7"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/helper/jsonutil" "github.com/hashicorp/vault/helper/jsonutil"
"github.com/hashicorp/vault/helper/strutil" "github.com/hashicorp/vault/helper/strutil"
"github.com/hashicorp/vault/logical" "github.com/hashicorp/vault/logical"
@ -110,6 +111,12 @@ func validateMetadata(clientNonce, pendingTime string, storedIdentity *whitelist
return err return err
} }
// For sanity
if !storedIdentity.DisallowReauthentication &&
storedIdentity.ClientNonce == "" {
return fmt.Errorf("client nonce missing in stored identity")
}
// When the presented client nonce does not match the cached entry, it is // When the presented client nonce does not match the cached entry, it is
// either that a rogue client is trying to login or that a valid client // either that a rogue client is trying to login or that a valid client
// suffered a migration. The migration is detected via pendingTime in the // suffered a migration. The migration is detected via pendingTime in the
@ -289,6 +296,15 @@ func (b *backend) pathLoginUpdate(
} }
} }
// If the clientNonce is empty at this point, it means that its a first
// time login and that a nonce is not supplied. Create a random nonce
// to be associated for the instance ID.
if clientNonce == "" {
if clientNonce, err = uuid.GenerateUUID(); err != nil {
return nil, fmt.Errorf("failed to generate random nonce")
}
}
// Load the current values for max TTL and policies from the role entry, // Load the current values for max TTL and policies from the role entry,
// before checking for overriding max TTL in the role tag. The shortest // before checking for overriding max TTL in the role tag. The shortest
// max TTL is used to cap the token TTL; the longest max TTL is used to // max TTL is used to cap the token TTL; the longest max TTL is used to
@ -367,19 +383,26 @@ func (b *backend) pathLoginUpdate(
} }
} }
// DisallowReauthentication, PendingTime, LastUpdatedTime and ExpirationTime may change. // DisallowReauthentication, PendingTime, LastUpdatedTime and
// ExpirationTime may change.
storedIdentity.LastUpdatedTime = currentTime storedIdentity.LastUpdatedTime = currentTime
storedIdentity.ExpirationTime = currentTime.Add(longestMaxTTL) storedIdentity.ExpirationTime = currentTime.Add(longestMaxTTL)
storedIdentity.PendingTime = identityDoc.PendingTime storedIdentity.PendingTime = identityDoc.PendingTime
storedIdentity.DisallowReauthentication = disallowReauthentication storedIdentity.DisallowReauthentication = disallowReauthentication
// Performing the clientNonce empty check after determining the DisallowReauthentication // Performing the clientNonce empty check after determining the
// option. This is to make clientNonce optional when DisallowReauthentication is set. // DisallowReauthentication option. This is to make clientNonce
// optional when DisallowReauthentication is set.
if clientNonce == "" && !storedIdentity.DisallowReauthentication { if clientNonce == "" && !storedIdentity.DisallowReauthentication {
return logical.ErrorResponse("missing nonce"), nil return logical.ErrorResponse("missing nonce"), nil
} }
// Limit the nonce to a reasonable length. // Don't cache the nonce if DisallowReauthentication is set
if storedIdentity.DisallowReauthentication {
storedIdentity.ClientNonce = ""
}
// Sanitize the nonce to a reasonable length
if len(clientNonce) > 128 && !storedIdentity.DisallowReauthentication { if len(clientNonce) > 128 && !storedIdentity.DisallowReauthentication {
return logical.ErrorResponse("client nonce exceeding the limit of 128 characters"), nil return logical.ErrorResponse("client nonce exceeding the limit of 128 characters"), nil
} }
@ -397,6 +420,11 @@ func (b *backend) pathLoginUpdate(
"role_tag_max_ttl": rTagMaxTTL.String(), "role_tag_max_ttl": rTagMaxTTL.String(),
"role": roleName, "role": roleName,
"ami_id": identityDoc.AmiID, "ami_id": identityDoc.AmiID,
// Echo the client nonce back. If nonce was not
// supplied to the endpoint, callers should
// extract out the nonce from this field for
// reauthentication requests.
"nonce": clientNonce,
}, },
LeaseOptions: logical.LeaseOptions{ LeaseOptions: logical.LeaseOptions{
Renewable: true, Renewable: true,

View File

@ -85,14 +85,17 @@ as it means that once a token has expired, subsequent authentication attempts
would fail. By default, reauthentication is enabled in this backend, and can be would fail. By default, reauthentication is enabled in this backend, and can be
turned off using 'disallow_reauthentication' parameter on the registered role. turned off using 'disallow_reauthentication' parameter on the registered role.
In the default method of operation, the client supplies a unique nonce during In the default method of operation, the backend will return a unique nonce
the first authentication attempt, storing this nonce in the client's memory for during the first authentication attempt, as part of auth `metadata`. Clients
future use. This nonce is stored in the whitelist, tied to the instance ID. should present this `nonce` for subsequent login attempts and it should match
Subsequent authentication attempts by the client require the nonce to match; the `nonce` cached at the identity-whitelist entry at the backend. Since only
since only the original client knows the nonce, only the original client is the original client knows the `nonce`, only the original client is allowed to
allowed to reauthenticate. (This is the reason that this is a whitelist rather reauthenticate. (This is the reason that this is a whitelist rather than a
than a blacklist; by default, it's keeping track of clients allowed to blacklist; by default, it's keeping track of clients allowed to reauthenticate,
reauthenticate, rather than those that are not.) rather than those that are not.). Clients can choose to provide a `nonce` even
for the first login attempt, in which case the provided `nonce` will be tied to
the cached identity-whitelist entry. It is recommended to use a strong `nonce`
value in this case.
It is up to the client to behave correctly with respect to the nonce; if the It is up to the client to behave correctly with respect to the nonce; if the
client stores the nonce on disk it can survive reboots, but could also give client stores the nonce on disk it can survive reboots, but could also give
@ -287,7 +290,8 @@ $ vault write auth/aws-ec2/role/dev-role bound_ami_id=ami-fce3c696 policies=prod
#### Perform the login operation #### Perform the login operation
``` ```
$ vault write auth/aws-ec2/login role=dev-role pkcs7=MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEggGmewogICJkZXZwYXlQcm9kdWN0Q29kZXMiIDogbnVsbCwKICAicHJpdmF0ZUlwIiA6ICIxNzIuMzEuNjMuNjAiLAogICJhdmFpbGFiaWxpdHlab25lIiA6ICJ1cy1lYXN0LTFjIiwKICAidmVyc2lvbiIgOiAiMjAxMC0wOC0zMSIsCiAgImluc3RhbmNlSWQiIDogImktZGUwZjEzNDQiLAogICJiaWxsaW5nUHJvZHVjdHMiIDogbnVsbCwKICAiaW5zdGFuY2VUeXBlIiA6ICJ0Mi5taWNybyIsCiAgImFjY291bnRJZCIgOiAiMjQxNjU2NjE1ODU5IiwKICAiaW1hZ2VJZCIgOiAiYW1pLWZjZTNjNjk2IiwKICAicGVuZGluZ1RpbWUiIDogIjIwMTYtMDQtMDVUMTY6MjY6NTVaIiwKICAiYXJjaGl0ZWN0dXJlIiA6ICJ4ODZfNjQiLAogICJrZXJuZWxJZCIgOiBudWxsLAogICJyYW1kaXNrSWQiIDogbnVsbCwKICAicmVnaW9uIiA6ICJ1cy1lYXN0LTEiCn0AAAAAAAAxggEXMIIBEwIBATBpMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQwIJAJa6SNnlXhpnMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNjA0MDUxNjI3MDBaMCMGCSqGSIb3DQEJBDEWBBRtiynzMTNfTw1TV/d8NvfgVw+XfTAJBgcqhkjOOAQDBC4wLAIUVfpVcNYoOKzN1c+h1Vsm/c5U0tQCFAK/K72idWrONIqMOVJ8Uen0wYg4AAAAAAAA nonce=vault-client-nonce $ vault write auth/aws-ec2/login role=dev-role
pkcs7=MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEggGmewogICJkZXZwYXlQcm9kdWN0Q29kZXMiIDogbnVsbCwKICAicHJpdmF0ZUlwIiA6ICIxNzIuMzEuNjMuNjAiLAogICJhdmFpbGFiaWxpdHlab25lIiA6ICJ1cy1lYXN0LTFjIiwKICAidmVyc2lvbiIgOiAiMjAxMC0wOC0zMSIsCiAgImluc3RhbmNlSWQiIDogImktZGUwZjEzNDQiLAogICJiaWxsaW5nUHJvZHVjdHMiIDogbnVsbCwKICAiaW5zdGFuY2VUeXBlIiA6ICJ0Mi5taWNybyIsCiAgImFjY291bnRJZCIgOiAiMjQxNjU2NjE1ODU5IiwKICAiaW1hZ2VJZCIgOiAiYW1pLWZjZTNjNjk2IiwKICAicGVuZGluZ1RpbWUiIDogIjIwMTYtMDQtMDVUMTY6MjY6NTVaIiwKICAiYXJjaGl0ZWN0dXJlIiA6ICJ4ODZfNjQiLAogICJrZXJuZWxJZCIgOiBudWxsLAogICJyYW1kaXNrSWQiIDogbnVsbCwKICAicmVnaW9uIiA6ICJ1cy1lYXN0LTEiCn0AAAAAAAAxggEXMIIBEwIBATBpMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQwIJAJa6SNnlXhpnMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNjA0MDUxNjI3MDBaMCMGCSqGSIb3DQEJBDEWBBRtiynzMTNfTw1TV/d8NvfgVw+XfTAJBgcqhkjOOAQDBC4wLAIUVfpVcNYoOKzN1c+h1Vsm/c5U0tQCFAK/K72idWrONIqMOVJ8Uen0wYg4AAAAAAAA nonce=5defbf9e-a8f9-3063-bdfc-54b7a42a1f95
``` ```
@ -314,7 +318,9 @@ curl -X POST -H "x-vault-token:123" "http://127.0.0.1:8200/v1/auth/aws-ec2/role/
#### Perform the login operation #### Perform the login operation
``` ```
curl -X POST "http://127.0.0.1:8200/v1/auth/aws-ec2/login" -d '{"role":"dev-role","pkcs7":"$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/pkcs7 | tr -d '\n')","nonce":"vault-client-nonce"}' curl -X POST "http://127.0.0.1:8200/v1/auth/aws-ec2/login" -d
'{"role":"dev-role","pkcs7":"$(curl -s
http://169.254.169.254/latest/dynamic/instance-identity/pkcs7 | tr -d '\n')","nonce":"5defbf9e-a8f9-3063-bdfc-54b7a42a1f95"}'
``` ```
@ -324,26 +330,30 @@ The response will be in JSON. For example:
{ {
"auth": { "auth": {
"renewable": true, "renewable": true,
"lease_duration": 1800000, "lease_duration": 72000,
"metadata": { "metadata": {
"role_tag_max_ttl": "0", "role_tag_max_ttl": "0s",
"instance_id": "i-de0f1344" "role": "ami-f083709d",
"ami_id": "ami-fce3c696" "region": "us-east-1",
"role": "dev-prod" "nonce": "5defbf9e-a8f9-3063-bdfc-54b7a42a1f95",
"instance_id": "i-a832f734",
"ami_id": "ami-f083709d"
}, },
"policies": [ "policies": [
"default", "default",
"dev", "dev",
"prod" "prod"
], ],
"accessor": "20b89871-e6f2-1160-fb29-31c2f6d4645e", "accessor": "5cd96cd1-58b7-2904-5519-75ddf957ec06",
"client_token": "c9368254-3f21-aded-8a6f-7c818e81b17a" "client_token": "150fc858-2402-49c9-56a5-f4b57f2c8ff1"
}, },
"warnings": null, "warnings": null,
"wrap_info": null,
"data": null, "data": null,
"lease_duration": 0, "lease_duration": 0,
"renewable": false, "renewable": false,
"lease_id": "" "lease_id": "",
"request_id": "d7d50c06-56b8-37f4-606c-ccdc87a1ee4c"
} }
``` ```
@ -1122,10 +1132,13 @@ in its identity document to match the one specified by this parameter.
<ul> <ul>
<li> <li>
<span class="param">nonce</span> <span class="param">nonce</span>
<span class="param-flags">required/optional, depends</span> <span class="param-flags">optional</span>
The `nonce` created by a client of this backend. When `disallow_reauthentication` The `nonce` to be used for reauthentication requests. By default, the backend
option is enabled on either the role or the role tag, then `nonce` parameter is generates a `nonce` if it is not supplied and returns it as part of auth `metadata`.
optional. It is a required parameter otherwise. If a custom nonce is desired, this field can be supplied during the first login
attempt. Usage of strong `nonce` value is recommended. Note that, when
`disallow_reauthentication` option is enabled on either the role or the role
tag, the `nonce` holds no significance.
</li> </li>
</ul> </ul>
</dd> </dd>
@ -1370,7 +1383,7 @@ in its identity document to match the one specified by this parameter.
"pending_time": "2016-04-14T01:01:41Z", "pending_time": "2016-04-14T01:01:41Z",
"expiration_time": "2016-05-05 10:09:16.67077232 +0000 UTC", "expiration_time": "2016-05-05 10:09:16.67077232 +0000 UTC",
"creation_time": "2016-04-14 14:09:16.67077232 +0000 UTC", "creation_time": "2016-04-14 14:09:16.67077232 +0000 UTC",
"client_nonce": "vault-client-nonce", "client_nonce": "5defbf9e-a8f9-3063-bdfc-54b7a42a1f95",
"role": "dev-role" "role": "dev-role"
}, },
"lease_duration": 0, "lease_duration": 0,