open-vault/builtin/credential/aws/path_identity_accesslist.go

168 lines
5.7 KiB
Go
Raw Normal View History

Create unified aws auth backend (#2441) * Rename builtin/credential/aws-ec2 to aws The aws-ec2 authentication backend is being expanded and will become the generic aws backend. This is a small rename commit to keep the commit history clean. * Expand aws-ec2 backend to more generic aws This adds the ability to authenticate arbitrary AWS IAM principals using AWS's sts:GetCallerIdentity method. The AWS-EC2 auth backend is being to just AWS with the expansion. * Add missing aws auth handler to CLI This was omitted from the previous commit * aws auth backend general variable name cleanup Also fixed a bug where allowed auth types weren't being checked upon login, and added tests for it. * Update docs for the aws auth backend * Refactor aws bind validation * Fix env var override in aws backend test Intent is to override the AWS environment variables with the TEST_* versions if they are set, but the reverse was happening. * Update docs on use of IAM authentication profile AWS now allows you to change the instance profile of a running instance, so the use case of "a long-lived instance that's not in an instance profile" no longer means you have to use the the EC2 auth method. You can now just change the instance profile on the fly. * Fix typo in aws auth cli help * Respond to PR feedback * More PR feedback * Respond to additional PR feedback * Address more feedback on aws auth PR * Make aws auth_type immutable per role * Address more aws auth PR feedback * Address more iam auth PR feedback * Rename aws-ec2.html.md to aws.html.md Per PR feedback, to go along with new backend name. * Add MountType to logical.Request * Make default aws auth_type dependent upon MountType When MountType is aws-ec2, default to ec2 auth_type for backwards compatibility with legacy roles. Otherwise, default to iam. * Pass MountPoint and MountType back up to the core Previously the request router reset the MountPoint and MountType back to the empty string before returning to the core. This ensures they get set back to the correct values.
2017-04-24 19:15:50 +00:00
package awsauth
import (
"context"
"time"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
const identityAccessListStorage = "whitelist/identity/"
func (b *backend) pathIdentityAccessList() *framework.Path {
return &framework.Path{
Pattern: "identity-accesslist/" + framework.GenericNameRegex("instance_id"),
Fields: map[string]*framework.FieldSchema{
"instance_id": {
Type: framework.TypeString,
Description: `EC2 instance ID. A successful login operation from an EC2 instance
gets cached in this accesslist, keyed off of instance ID.`,
},
},
Operations: map[logical.Operation]framework.OperationHandler{
logical.ReadOperation: &framework.PathOperation{
Callback: b.pathIdentityAccesslistRead,
},
logical.DeleteOperation: &framework.PathOperation{
Callback: b.pathIdentityAccesslistDelete,
},
},
HelpSynopsis: pathIdentityAccessListSyn,
HelpDescription: pathIdentityAccessListDesc,
}
}
func (b *backend) pathListIdentityAccessList() *framework.Path {
return &framework.Path{
Pattern: "identity-accesslist/?",
Operations: map[logical.Operation]framework.OperationHandler{
logical.ListOperation: &framework.PathOperation{
Callback: b.pathAccessListIdentitiesList,
},
},
HelpSynopsis: pathListIdentityAccessListHelpSyn,
HelpDescription: pathListIdentityAccessListHelpDesc,
}
}
// pathAccessListIdentitiesList is used to list all the instance IDs that are present
// in the identity access list. This will list both valid and expired entries.
func (b *backend) pathAccessListIdentitiesList(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
identities, err := req.Storage.List(ctx, identityAccessListStorage)
if err != nil {
return nil, err
}
return logical.ListResponse(identities), nil
}
// Fetch an item from the access list given an instance ID.
func accessListIdentityEntry(ctx context.Context, s logical.Storage, instanceID string) (*accessListIdentity, error) {
entry, err := s.Get(ctx, identityAccessListStorage+instanceID)
if err != nil {
return nil, err
}
if entry == nil {
return nil, nil
}
var result accessListIdentity
if err := entry.DecodeJSON(&result); err != nil {
return nil, err
}
return &result, nil
}
// Stores an instance ID and the information required to validate further login/renewal attempts from
// the same instance ID.
func setAccessListIdentityEntry(ctx context.Context, s logical.Storage, instanceID string, identity *accessListIdentity) error {
entry, err := logical.StorageEntryJSON(identityAccessListStorage+instanceID, identity)
if err != nil {
return err
}
if err := s.Put(ctx, entry); err != nil {
return err
}
return nil
}
// pathIdentityAccesslistDelete is used to delete an entry from the identity access list given an instance ID.
func (b *backend) pathIdentityAccesslistDelete(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
instanceID := data.Get("instance_id").(string)
if instanceID == "" {
return logical.ErrorResponse("missing instance_id"), nil
}
return nil, req.Storage.Delete(ctx, identityAccessListStorage+instanceID)
}
// pathIdentityAccesslistRead is used to view an entry in the identity access list given an instance ID.
func (b *backend) pathIdentityAccesslistRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
instanceID := data.Get("instance_id").(string)
if instanceID == "" {
return logical.ErrorResponse("missing instance_id"), nil
}
entry, err := accessListIdentityEntry(ctx, req.Storage, instanceID)
if err != nil {
return nil, err
}
if entry == nil {
return nil, nil
}
2018-02-27 18:22:47 +00:00
return &logical.Response{
Data: map[string]interface{}{
"role": entry.Role,
"client_nonce": entry.ClientNonce,
"creation_time": entry.CreationTime.Format(time.RFC3339Nano),
"disallow_reauthentication": entry.DisallowReauthentication,
"pending_time": entry.PendingTime,
"expiration_time": entry.ExpirationTime.Format(time.RFC3339Nano),
"last_updated_time": entry.LastUpdatedTime.Format(time.RFC3339Nano),
},
}, nil
}
// Struct to represent each item in the identity access list.
type accessListIdentity struct {
Role string `json:"role"`
ClientNonce string `json:"client_nonce"`
CreationTime time.Time `json:"creation_time"`
DisallowReauthentication bool `json:"disallow_reauthentication"`
PendingTime string `json:"pending_time"`
ExpirationTime time.Time `json:"expiration_time"`
LastUpdatedTime time.Time `json:"last_updated_time"`
}
const pathIdentityAccessListSyn = `
Read or delete entries in the identity access list.
`
const pathIdentityAccessListDesc = `
Each login from an EC2 instance creates/updates an entry in the identity access list.
Entries in this list can be viewed or deleted using this endpoint.
By default, a cron task will periodically look for expired entries in the access list
and deletes them. The duration to periodically run this, is one hour by default.
However, this can be configured using the 'config/tidy/identities' endpoint. This tidy
action can be triggered via the API as well, using the 'tidy/identities' endpoint.
`
const pathListIdentityAccessListHelpSyn = `
Lists the items present in the identity access list.
`
const pathListIdentityAccessListHelpDesc = `
The entries in the identity access list is keyed off of the EC2 instance IDs.
This endpoint lists all the entries present in the identity access list, both
expired and un-expired entries. Use 'tidy/identities' endpoint to clean-up
the access list of identities.
`