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

158 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/fatih/structs"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
func pathIdentityWhitelist(b *backend) *framework.Path {
return &framework.Path{
Pattern: "identity-whitelist/" + framework.GenericNameRegex("instance_id"),
Fields: map[string]*framework.FieldSchema{
"instance_id": &framework.FieldSchema{
Type: framework.TypeString,
Description: `EC2 instance ID. A successful login operation from an EC2 instance
gets cached in this whitelist, keyed off of instance ID.`,
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: b.pathIdentityWhitelistRead,
logical.DeleteOperation: b.pathIdentityWhitelistDelete,
},
HelpSynopsis: pathIdentityWhitelistSyn,
HelpDescription: pathIdentityWhitelistDesc,
}
}
func pathListIdentityWhitelist(b *backend) *framework.Path {
return &framework.Path{
Pattern: "identity-whitelist/?",
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ListOperation: b.pathWhitelistIdentitiesList,
},
HelpSynopsis: pathListIdentityWhitelistHelpSyn,
HelpDescription: pathListIdentityWhitelistHelpDesc,
}
}
// pathWhitelistIdentitiesList is used to list all the instance IDs that are present
// in the identity whitelist. This will list both valid and expired entries.
func (b *backend) pathWhitelistIdentitiesList(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
identities, err := req.Storage.List(ctx, "whitelist/identity/")
if err != nil {
return nil, err
}
return logical.ListResponse(identities), nil
}
// Fetch an item from the whitelist given an instance ID.
func whitelistIdentityEntry(ctx context.Context, s logical.Storage, instanceID string) (*whitelistIdentity, error) {
entry, err := s.Get(ctx, "whitelist/identity/"+instanceID)
if err != nil {
return nil, err
}
if entry == nil {
return nil, nil
}
var result whitelistIdentity
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 setWhitelistIdentityEntry(ctx context.Context, s logical.Storage, instanceID string, identity *whitelistIdentity) error {
entry, err := logical.StorageEntryJSON("whitelist/identity/"+instanceID, identity)
if err != nil {
return err
}
if err := s.Put(ctx, entry); err != nil {
return err
}
return nil
}
// pathIdentityWhitelistDelete is used to delete an entry from the identity whitelist given an instance ID.
func (b *backend) pathIdentityWhitelistDelete(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, "whitelist/identity/"+instanceID)
}
// pathIdentityWhitelistRead is used to view an entry in the identity whitelist given an instance ID.
func (b *backend) pathIdentityWhitelistRead(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 := whitelistIdentityEntry(ctx, req.Storage, instanceID)
if err != nil {
return nil, err
}
if entry == nil {
return nil, nil
}
resp := &logical.Response{
Data: structs.New(entry).Map(),
}
resp.Data["creation_time"] = entry.CreationTime.Format(time.RFC3339Nano)
resp.Data["expiration_time"] = entry.ExpirationTime.Format(time.RFC3339Nano)
resp.Data["last_updated_time"] = entry.LastUpdatedTime.Format(time.RFC3339Nano)
return resp, nil
}
// Struct to represent each item in the identity whitelist.
type whitelistIdentity struct {
2016-05-13 18:31:13 +00:00
Role string `json:"role" structs:"role" mapstructure:"role"`
ClientNonce string `json:"client_nonce" structs:"client_nonce" mapstructure:"client_nonce"`
CreationTime time.Time `json:"creation_time" structs:"creation_time" mapstructure:"creation_time"`
DisallowReauthentication bool `json:"disallow_reauthentication" structs:"disallow_reauthentication" mapstructure:"disallow_reauthentication"`
PendingTime string `json:"pending_time" structs:"pending_time" mapstructure:"pending_time"`
ExpirationTime time.Time `json:"expiration_time" structs:"expiration_time" mapstructure:"expiration_time"`
LastUpdatedTime time.Time `json:"last_updated_time" structs:"last_updated_time" mapstructure:"last_updated_time"`
}
const pathIdentityWhitelistSyn = `
Read or delete entries in the identity whitelist.
`
const pathIdentityWhitelistDesc = `
Each login from an EC2 instance creates/updates an entry in the identity whitelist.
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 whitelist
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 pathListIdentityWhitelistHelpSyn = `
Lists the items present in the identity whitelist.
`
const pathListIdentityWhitelistHelpDesc = `
The entries in the identity whitelist is keyed off of the EC2 instance IDs.
This endpoint lists all the entries present in the identity whitelist, both
expired and un-expired entries. Use 'tidy/identities' endpoint to clean-up
the whitelist of identities.
`