2017-04-24 19:15:50 +00:00
package awsauth
2016-05-03 16:14:07 +00:00
import (
2018-01-08 18:31:38 +00:00
"context"
2016-05-03 16:14:07 +00:00
"fmt"
"strings"
"time"
2018-04-05 15:49:21 +00:00
"github.com/hashicorp/errwrap"
2016-05-03 16:14:07 +00:00
"github.com/hashicorp/go-uuid"
2018-03-02 16:09:14 +00:00
"github.com/hashicorp/vault/helper/consts"
2016-05-03 16:14:07 +00:00
"github.com/hashicorp/vault/helper/policyutil"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
2018-03-02 16:09:14 +00:00
var (
2018-03-18 01:24:49 +00:00
currentRoleStorageVersion = 2
2018-03-02 16:09:14 +00:00
)
2016-05-03 16:14:07 +00:00
func pathRole ( b * backend ) * framework . Path {
return & framework . Path {
2016-05-13 18:31:13 +00:00
Pattern : "role/" + framework . GenericNameRegex ( "role" ) ,
2016-05-03 16:14:07 +00:00
Fields : map [ string ] * framework . FieldSchema {
2016-08-09 21:29:45 +00:00
"role" : {
2016-05-03 16:14:07 +00:00
Type : framework . TypeString ,
Description : "Name of the role." ,
} ,
2017-04-24 19:15:50 +00:00
"auth_type" : {
Type : framework . TypeString ,
Description : ` The auth_type permitted to authenticate to this role . Must be one of
iam or ec2 and cannot be changed after role creation . ` ,
} ,
2016-08-09 21:29:45 +00:00
"bound_ami_id" : {
2018-03-02 16:09:14 +00:00
Type : framework . TypeCommaStringSlice ,
2016-05-12 11:19:29 +00:00
Description : ` If set , defines a constraint on the EC2 instances that they should be
2018-03-02 16:09:14 +00:00
using one of the AMI IDs specified by this parameter . This is only applicable
when auth_type is ec2 or inferred_entity_type is ec2_instance . ` ,
2016-05-03 16:14:07 +00:00
} ,
2016-08-09 21:29:45 +00:00
"bound_account_id" : {
2018-03-02 16:09:14 +00:00
Type : framework . TypeCommaStringSlice ,
2016-06-14 15:58:19 +00:00
Description : ` If set , defines a constraint on the EC2 instances that the account ID
2018-03-02 16:09:14 +00:00
in its identity document to match one of the IDs specified by this parameter .
This is only applicable when auth_type is ec2 or inferred_entity_type is
ec2_instance . ` ,
2017-04-24 19:15:50 +00:00
} ,
"bound_iam_principal_arn" : {
2018-03-02 16:09:14 +00:00
Type : framework . TypeCommaStringSlice ,
Description : ` ARN of the IAM principals to bind to this role . Only applicable when
2017-04-24 19:15:50 +00:00
auth_type is iam . ` ,
2016-09-23 16:47:35 +00:00
} ,
2017-02-24 19:19:10 +00:00
"bound_region" : {
2018-03-02 16:09:14 +00:00
Type : framework . TypeCommaStringSlice ,
2017-04-24 19:15:50 +00:00
Description : ` If set , defines a constraint on the EC2 instances that the region in
2018-03-02 16:09:14 +00:00
its identity document match one of the regions specified by this parameter . This is only
2017-10-23 14:53:09 +00:00
applicable when auth_type is ec2 . ` ,
2017-02-24 19:19:10 +00:00
} ,
2016-09-23 16:47:35 +00:00
"bound_iam_role_arn" : {
2018-03-02 16:09:14 +00:00
Type : framework . TypeCommaStringSlice ,
2016-09-28 22:30:32 +00:00
Description : ` If set , defines a constraint on the authenticating EC2 instance
2018-03-02 16:09:14 +00:00
that it must match one of the IAM role ARNs specified by this parameter .
2016-09-28 22:30:32 +00:00
The value is prefix - matched ( as though it were a glob ending in
'*' ) . The configured IAM user or EC2 instance role must be allowed
2017-10-23 14:53:09 +00:00
to execute the ' iam : GetInstanceProfile ' action if this is specified . This is
only applicable when auth_type is ec2 or inferred_entity_type is
ec2_instance . ` ,
2016-06-14 15:58:19 +00:00
} ,
2016-09-23 15:22:23 +00:00
"bound_iam_instance_profile_arn" : {
2018-03-02 16:09:14 +00:00
Type : framework . TypeCommaStringSlice ,
2016-09-28 22:30:32 +00:00
Description : ` If set , defines a constraint on the EC2 instances to be associated
with an IAM instance profile ARN which has a prefix that matches
2018-03-02 16:09:14 +00:00
one of the values specified by this parameter . The value is prefix - matched
2017-10-23 14:53:09 +00:00
( as though it were a glob ending in '*' ) . This is only applicable when
auth_type is ec2 or inferred_entity_type is ec2_instance . ` ,
2018-03-15 16:19:28 +00:00
} ,
"bound_ec2_instance_id" : {
Type : framework . TypeCommaStringSlice ,
Description : ` If set , defines a constraint on the EC2 instances to have one of the
given instance IDs . Can be a list or comma - separated string of EC2 instance
IDs . This is only applicable when auth_type is ec2 or inferred_entity_type is
ec2_instance . ` ,
2017-06-07 14:27:11 +00:00
} ,
"resolve_aws_unique_ids" : {
Type : framework . TypeBool ,
Default : true ,
Description : ` If set , resolve all AWS IAM ARNs into AWS ' s internal unique IDs .
When an IAM entity ( e . g . , user , role , or instance profile ) is deleted , then all references
to it within the role will be invalidated , which prevents a new IAM entity from being created
with the same name and matching the role ' s IAM binds . Once set , this cannot be unset . ` ,
2017-04-24 19:15:50 +00:00
} ,
"inferred_entity_type" : {
Type : framework . TypeString ,
Description : ` When auth_type is iam , the
AWS entity type to infer from the authenticated principal . The only supported
value is ec2_instance , which will extract the EC2 instance ID from the
authenticated role and apply the following restrictions specific to EC2
instances : bound_ami_id , bound_account_id , bound_iam_role_arn ,
bound_iam_instance_profile_arn , bound_vpc_id , bound_subnet_id . The configured
EC2 client must be able to find the inferred instance ID in the results , and the
instance must be running . If unable to determine the EC2 instance ID or unable
to find the EC2 instance ID among running instances , then authentication will
fail . ` ,
} ,
"inferred_aws_region" : {
Type : framework . TypeString ,
Description : ` When auth_type is iam and
inferred_entity_type is set , the region to assume the inferred entity exists in . ` ,
2017-02-24 19:19:10 +00:00
} ,
"bound_vpc_id" : {
2018-03-02 16:09:14 +00:00
Type : framework . TypeCommaStringSlice ,
2017-02-24 19:19:10 +00:00
Description : `
2018-03-02 16:09:14 +00:00
If set , defines a constraint on the EC2 instance to be associated with a VPC
ID that matches one of the value specified by this parameter . This is only
applicable when auth_type is ec2 or inferred_entity_type is ec2_instance . ` ,
2017-02-24 19:19:10 +00:00
} ,
"bound_subnet_id" : {
2018-03-02 16:09:14 +00:00
Type : framework . TypeCommaStringSlice ,
2017-02-24 19:19:10 +00:00
Description : `
If set , defines a constraint on the EC2 instance to be associated with the
2018-03-02 16:09:14 +00:00
subnet ID that matches one of the values specified by this parameter . This is
only applicable when auth_type is ec2 or inferred_entity_type is
ec2_instance . ` ,
2016-06-14 14:49:36 +00:00
} ,
2016-08-09 21:29:45 +00:00
"role_tag" : {
2017-04-24 19:15:50 +00:00
Type : framework . TypeString ,
Default : "" ,
Description : ` If set , enables the role tags for this role . The value set for this
field should be the ' key ' of the tag on the EC2 instance . The ' value '
of the tag should be generated using ' role / < role > / tag ' endpoint .
Defaults to an empty string , meaning that role tags are disabled . This
is only allowed if auth_type is ec2 . ` ,
2016-05-03 16:14:07 +00:00
} ,
2017-02-02 18:28:01 +00:00
"period" : & framework . FieldSchema {
Type : framework . TypeDurationSecond ,
Default : 0 ,
Description : `
2017-10-23 14:53:09 +00:00
If set , indicates that the token generated using this role should never expire .
The token should be renewed within the duration specified by this value . At
each renewal , the token ' s TTL will be set to the value of this parameter . ` ,
2017-02-02 18:28:01 +00:00
} ,
2016-08-09 21:29:45 +00:00
"ttl" : {
Type : framework . TypeDurationSecond ,
Default : 0 ,
Description : ` Duration in seconds after which the issued token should expire . Defaults
to 0 , in which case the value will fallback to the system / mount defaults . ` ,
} ,
"max_ttl" : {
2016-05-03 16:14:07 +00:00
Type : framework . TypeDurationSecond ,
Default : 0 ,
2016-05-12 11:19:29 +00:00
Description : "The maximum allowed lifetime of tokens issued using this role." ,
2016-05-03 16:14:07 +00:00
} ,
2016-08-09 21:29:45 +00:00
"policies" : {
2017-09-13 15:36:52 +00:00
Type : framework . TypeCommaStringSlice ,
2016-05-03 16:14:07 +00:00
Default : "default" ,
2016-05-12 11:19:29 +00:00
Description : "Policies to be set on tokens issued using this role." ,
2016-05-03 16:14:07 +00:00
} ,
2016-08-09 21:29:45 +00:00
"allow_instance_migration" : {
2017-04-24 19:15:50 +00:00
Type : framework . TypeBool ,
Default : false ,
Description : ` If set , allows migration of the underlying instance where the client
resides . This keys off of pendingTime in the metadata document , so
essentially , this disables the client nonce check whenever the
instance is migrated to a new host and pendingTime is newer than the
previously - remembered time . Use with caution . This is only checked when
auth_type is ec2 . ` ,
2016-05-03 16:14:07 +00:00
} ,
2016-08-09 21:29:45 +00:00
"disallow_reauthentication" : {
2017-10-23 14:53:09 +00:00
Type : framework . TypeBool ,
Default : false ,
Description : ` If set , only allows a single token to be granted per
instance ID . In order to perform a fresh login , the entry in whitelist
for the instance ID needs to be cleared using
' auth / aws - ec2 / identity - whitelist / < instance_id > ' endpoint . This is only
applicable when auth_type is ec2 . ` ,
2016-05-03 16:14:07 +00:00
} ,
} ,
ExistenceCheck : b . pathRoleExistenceCheck ,
Callbacks : map [ logical . Operation ] framework . OperationFunc {
logical . CreateOperation : b . pathRoleCreateUpdate ,
logical . UpdateOperation : b . pathRoleCreateUpdate ,
logical . ReadOperation : b . pathRoleRead ,
logical . DeleteOperation : b . pathRoleDelete ,
} ,
HelpSynopsis : pathRoleSyn ,
HelpDescription : pathRoleDesc ,
}
}
2016-05-05 18:51:09 +00:00
func pathListRole ( b * backend ) * framework . Path {
return & framework . Path {
Pattern : "role/?" ,
Callbacks : map [ logical . Operation ] framework . OperationFunc {
logical . ListOperation : b . pathRoleList ,
} ,
HelpSynopsis : pathListRolesHelpSyn ,
HelpDescription : pathListRolesHelpDesc ,
}
}
2016-05-03 16:14:07 +00:00
func pathListRoles ( b * backend ) * framework . Path {
return & framework . Path {
Pattern : "roles/?" ,
Callbacks : map [ logical . Operation ] framework . OperationFunc {
logical . ListOperation : b . pathRoleList ,
} ,
HelpSynopsis : pathListRolesHelpSyn ,
HelpDescription : pathListRolesHelpDesc ,
}
}
// Establishes dichotomy of request operation between CreateOperation and UpdateOperation.
// Returning 'true' forces an UpdateOperation, CreateOperation otherwise.
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathRoleExistenceCheck ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( bool , error ) {
2018-01-19 06:44:44 +00:00
entry , err := b . lockedAWSRole ( ctx , req . Storage , strings . ToLower ( data . Get ( "role" ) . ( string ) ) )
2016-05-03 16:14:07 +00:00
if err != nil {
return false , err
}
return entry != nil , nil
}
2016-09-23 15:22:23 +00:00
// lockedAWSRole returns the properties set on the given role. This method
// acquires the read lock before reading the role from the storage.
2018-01-19 06:44:44 +00:00
func ( b * backend ) lockedAWSRole ( ctx context . Context , s logical . Storage , roleName string ) ( * awsRoleEntry , error ) {
2016-09-23 15:22:23 +00:00
if roleName == "" {
return nil , fmt . Errorf ( "missing role name" )
}
2016-05-05 18:51:09 +00:00
b . roleMutex . RLock ( )
2018-01-19 06:44:44 +00:00
roleEntry , err := b . nonLockedAWSRole ( ctx , s , roleName )
2017-04-24 19:15:50 +00:00
// we manually unlock rather than defer the unlock because we might need to grab
// a read/write lock in the upgrade path
b . roleMutex . RUnlock ( )
if err != nil {
return nil , err
}
if roleEntry == nil {
return nil , nil
}
2018-01-19 06:44:44 +00:00
needUpgrade , err := b . upgradeRoleEntry ( ctx , s , roleEntry )
2017-04-24 19:15:50 +00:00
if err != nil {
2018-04-05 15:49:21 +00:00
return nil , errwrap . Wrapf ( "error upgrading roleEntry: {{err}}" , err )
2017-04-24 19:15:50 +00:00
}
2018-03-02 16:09:14 +00:00
if needUpgrade && ( b . System ( ) . LocalMount ( ) || ! b . System ( ) . ReplicationState ( ) . HasState ( consts . ReplicationPerformanceSecondary ) ) {
2017-04-24 19:15:50 +00:00
b . roleMutex . Lock ( )
defer b . roleMutex . Unlock ( )
// Now that we have a R/W lock, we need to re-read the role entry in case it was
// written to between releasing the read lock and acquiring the write lock
2018-01-19 06:44:44 +00:00
roleEntry , err = b . nonLockedAWSRole ( ctx , s , roleName )
2017-04-24 19:15:50 +00:00
if err != nil {
return nil , err
}
// somebody deleted the role, so no use in putting it back
if roleEntry == nil {
return nil , nil
}
// now re-check to see if we need to upgrade
2018-01-19 06:44:44 +00:00
if needUpgrade , err = b . upgradeRoleEntry ( ctx , s , roleEntry ) ; err != nil {
2018-04-05 15:49:21 +00:00
return nil , errwrap . Wrapf ( "error upgrading roleEntry: {{err}}" , err )
2017-04-24 19:15:50 +00:00
}
if needUpgrade {
2018-01-19 06:44:44 +00:00
if err = b . nonLockedSetAWSRole ( ctx , s , roleName , roleEntry ) ; err != nil {
2018-04-05 15:49:21 +00:00
return nil , errwrap . Wrapf ( "error saving upgraded roleEntry: {{err}}" , err )
2017-04-24 19:15:50 +00:00
}
}
}
return roleEntry , nil
2016-09-23 15:22:23 +00:00
}
// lockedSetAWSRole creates or updates a role in the storage. This method
// acquires the write lock before creating or updating the role at the storage.
2018-01-19 06:44:44 +00:00
func ( b * backend ) lockedSetAWSRole ( ctx context . Context , s logical . Storage , roleName string , roleEntry * awsRoleEntry ) error {
2016-09-23 15:22:23 +00:00
if roleName == "" {
return fmt . Errorf ( "missing role name" )
}
if roleEntry == nil {
return fmt . Errorf ( "nil role entry" )
}
b . roleMutex . Lock ( )
defer b . roleMutex . Unlock ( )
2018-01-19 06:44:44 +00:00
return b . nonLockedSetAWSRole ( ctx , s , roleName , roleEntry )
2016-09-23 15:22:23 +00:00
}
// nonLockedSetAWSRole creates or updates a role in the storage. This method
// does not acquire the write lock before reading the role from the storage. If
// locking is desired, use lockedSetAWSRole instead.
2018-01-19 06:44:44 +00:00
func ( b * backend ) nonLockedSetAWSRole ( ctx context . Context , s logical . Storage , roleName string ,
2016-09-23 15:22:23 +00:00
roleEntry * awsRoleEntry ) error {
if roleName == "" {
return fmt . Errorf ( "missing role name" )
}
if roleEntry == nil {
return fmt . Errorf ( "nil role entry" )
}
entry , err := logical . StorageEntryJSON ( "role/" + strings . ToLower ( roleName ) , roleEntry )
if err != nil {
return err
}
2018-01-19 06:44:44 +00:00
if err := s . Put ( ctx , entry ) ; err != nil {
2016-09-23 15:22:23 +00:00
return err
}
return nil
2016-05-05 18:51:09 +00:00
}
2017-04-24 19:15:50 +00:00
// If needed, updates the role entry and returns a bool indicating if it was updated
// (and thus needs to be persisted)
2018-01-19 06:44:44 +00:00
func ( b * backend ) upgradeRoleEntry ( ctx context . Context , s logical . Storage , roleEntry * awsRoleEntry ) ( bool , error ) {
2017-04-24 19:15:50 +00:00
if roleEntry == nil {
return false , fmt . Errorf ( "received nil roleEntry" )
}
2018-03-18 01:24:49 +00:00
upgraded := roleEntry . Version < currentRoleStorageVersion
2018-03-02 16:09:14 +00:00
switch roleEntry . Version {
case 0 :
// Check if the value held by role ARN field is actually an instance profile ARN
if roleEntry . BoundIamRoleARN != "" && strings . Contains ( roleEntry . BoundIamRoleARN , ":instance-profile/" ) {
// If yes, move it to the correct field
roleEntry . BoundIamInstanceProfileARN = roleEntry . BoundIamRoleARN
2017-04-24 19:15:50 +00:00
2018-03-02 16:09:14 +00:00
// Reset the old field
roleEntry . BoundIamRoleARN = ""
}
2017-04-24 19:15:50 +00:00
2018-03-02 16:09:14 +00:00
// Check if there was no pre-existing AuthType set (from older versions)
if roleEntry . AuthType == "" {
// then default to the original behavior of ec2
roleEntry . AuthType = ec2AuthType
}
2017-04-24 19:15:50 +00:00
2018-03-02 16:09:14 +00:00
// Check if we need to resolve the unique ID on the role
if roleEntry . AuthType == iamAuthType &&
roleEntry . ResolveAWSUniqueIDs &&
roleEntry . BoundIamPrincipalARN != "" &&
roleEntry . BoundIamPrincipalID == "" &&
! strings . HasSuffix ( roleEntry . BoundIamPrincipalARN , "*" ) {
principalId , err := b . resolveArnToUniqueIDFunc ( ctx , s , roleEntry . BoundIamPrincipalARN )
if err != nil {
return false , err
}
roleEntry . BoundIamPrincipalID = principalId
// Not setting roleEntry.BoundIamPrincipalARN to "" here so that clients can see the original
// ARN that the role was bound to
}
// Check if we need to convert individual string values to lists
if roleEntry . BoundAmiID != "" {
roleEntry . BoundAmiIDs = [ ] string { roleEntry . BoundAmiID }
roleEntry . BoundAmiID = ""
}
if roleEntry . BoundAccountID != "" {
roleEntry . BoundAccountIDs = [ ] string { roleEntry . BoundAccountID }
roleEntry . BoundAccountID = ""
}
if roleEntry . BoundIamPrincipalARN != "" {
roleEntry . BoundIamPrincipalARNs = [ ] string { roleEntry . BoundIamPrincipalARN }
roleEntry . BoundIamPrincipalARN = ""
}
if roleEntry . BoundIamPrincipalID != "" {
roleEntry . BoundIamPrincipalIDs = [ ] string { roleEntry . BoundIamPrincipalID }
roleEntry . BoundIamPrincipalID = ""
}
if roleEntry . BoundIamRoleARN != "" {
roleEntry . BoundIamRoleARNs = [ ] string { roleEntry . BoundIamRoleARN }
roleEntry . BoundIamRoleARN = ""
}
if roleEntry . BoundIamInstanceProfileARN != "" {
roleEntry . BoundIamInstanceProfileARNs = [ ] string { roleEntry . BoundIamInstanceProfileARN }
roleEntry . BoundIamInstanceProfileARN = ""
}
if roleEntry . BoundRegion != "" {
roleEntry . BoundRegions = [ ] string { roleEntry . BoundRegion }
roleEntry . BoundRegion = ""
2017-06-07 14:27:11 +00:00
}
2018-03-02 16:09:14 +00:00
if roleEntry . BoundSubnetID != "" {
roleEntry . BoundSubnetIDs = [ ] string { roleEntry . BoundSubnetID }
roleEntry . BoundSubnetID = ""
}
if roleEntry . BoundVpcID != "" {
roleEntry . BoundVpcIDs = [ ] string { roleEntry . BoundVpcID }
roleEntry . BoundVpcID = ""
}
roleEntry . Version = 1
fallthrough
2018-03-18 01:24:49 +00:00
case 1 :
// Make BoundIamRoleARNs and BoundIamInstanceProfileARNs explicitly prefix-matched
for i , arn := range roleEntry . BoundIamRoleARNs {
roleEntry . BoundIamRoleARNs [ i ] = fmt . Sprintf ( "%s*" , arn )
}
for i , arn := range roleEntry . BoundIamInstanceProfileARNs {
roleEntry . BoundIamInstanceProfileARNs [ i ] = fmt . Sprintf ( "%s*" , arn )
}
roleEntry . Version = 2
fallthrough
2018-03-02 16:09:14 +00:00
case currentRoleStorageVersion :
default :
return false , fmt . Errorf ( "unrecognized role version: %q" , roleEntry . Version )
2017-06-07 14:27:11 +00:00
}
2017-04-24 19:15:50 +00:00
return upgraded , nil
}
2016-09-23 15:22:23 +00:00
// nonLockedAWSRole returns the properties set on the given role. This method
// does not acquire the read lock before reading the role from the storage. If
// locking is desired, use lockedAWSRole instead.
2017-04-24 19:15:50 +00:00
// This method also does NOT check to see if a role upgrade is required. It is
// the responsibility of the caller to check if a role upgrade is required and,
// if so, to upgrade the role
2018-01-19 06:44:44 +00:00
func ( b * backend ) nonLockedAWSRole ( ctx context . Context , s logical . Storage , roleName string ) ( * awsRoleEntry , error ) {
2016-09-23 15:22:23 +00:00
if roleName == "" {
return nil , fmt . Errorf ( "missing role name" )
}
2018-01-19 06:44:44 +00:00
entry , err := s . Get ( ctx , "role/" + strings . ToLower ( roleName ) )
2016-05-03 16:14:07 +00:00
if err != nil {
return nil , err
}
if entry == nil {
return nil , nil
}
var result awsRoleEntry
if err := entry . DecodeJSON ( & result ) ; err != nil {
return nil , err
}
2016-09-23 15:22:23 +00:00
2016-05-03 16:14:07 +00:00
return & result , nil
}
// pathRoleDelete is used to delete the information registered for a given AMI ID.
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathRoleDelete ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2016-05-13 18:31:13 +00:00
roleName := data . Get ( "role" ) . ( string )
2016-05-03 16:14:07 +00:00
if roleName == "" {
2016-05-13 18:31:13 +00:00
return logical . ErrorResponse ( "missing role" ) , nil
2016-05-03 16:14:07 +00:00
}
2016-05-05 18:51:09 +00:00
b . roleMutex . Lock ( )
defer b . roleMutex . Unlock ( )
2018-01-19 06:44:44 +00:00
return nil , req . Storage . Delete ( ctx , "role/" + strings . ToLower ( roleName ) )
2016-05-03 16:14:07 +00:00
}
// pathRoleList is used to list all the AMI IDs registered with Vault.
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathRoleList ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2016-05-05 18:51:09 +00:00
b . roleMutex . RLock ( )
defer b . roleMutex . RUnlock ( )
2018-01-19 06:44:44 +00:00
roles , err := req . Storage . List ( ctx , "role/" )
2016-05-03 16:14:07 +00:00
if err != nil {
return nil , err
}
return logical . ListResponse ( roles ) , nil
}
// pathRoleRead is used to view the information registered for a given AMI ID.
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathRoleRead ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2018-01-19 06:44:44 +00:00
roleEntry , err := b . lockedAWSRole ( ctx , req . Storage , strings . ToLower ( data . Get ( "role" ) . ( string ) ) )
2016-05-03 16:14:07 +00:00
if err != nil {
return nil , err
}
if roleEntry == nil {
return nil , nil
}
2016-09-23 16:47:35 +00:00
return & logical . Response {
2018-03-02 16:09:14 +00:00
Data : roleEntry . ToResponseData ( ) ,
2016-09-23 16:47:35 +00:00
} , nil
2016-05-03 16:14:07 +00:00
}
// pathRoleCreateUpdate is used to associate Vault policies to a given AMI ID.
2018-01-08 18:31:38 +00:00
func ( b * backend ) pathRoleCreateUpdate ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2016-05-13 18:31:13 +00:00
roleName := strings . ToLower ( data . Get ( "role" ) . ( string ) )
2016-05-03 16:14:07 +00:00
if roleName == "" {
2016-05-13 18:31:13 +00:00
return logical . ErrorResponse ( "missing role" ) , nil
2016-05-03 16:14:07 +00:00
}
2016-05-05 18:51:09 +00:00
b . roleMutex . Lock ( )
defer b . roleMutex . Unlock ( )
2018-01-19 06:44:44 +00:00
roleEntry , err := b . nonLockedAWSRole ( ctx , req . Storage , roleName )
2016-05-03 16:14:07 +00:00
if err != nil {
return nil , err
}
if roleEntry == nil {
2018-03-02 16:09:14 +00:00
roleEntry = & awsRoleEntry {
Version : currentRoleStorageVersion ,
}
2017-04-24 19:15:50 +00:00
} else {
2018-01-19 06:44:44 +00:00
needUpdate , err := b . upgradeRoleEntry ( ctx , req . Storage , roleEntry )
2017-04-24 19:15:50 +00:00
if err != nil {
return logical . ErrorResponse ( fmt . Sprintf ( "failed to update roleEntry: %v" , err ) ) , nil
}
if needUpdate {
2018-01-19 06:44:44 +00:00
err = b . nonLockedSetAWSRole ( ctx , req . Storage , roleName , roleEntry )
2017-04-24 19:15:50 +00:00
if err != nil {
return logical . ErrorResponse ( fmt . Sprintf ( "failed to save upgraded roleEntry: %v" , err ) ) , nil
}
}
2016-05-03 16:14:07 +00:00
}
2016-09-23 16:47:35 +00:00
// Fetch and set the bound parameters. There can't be default values
// for these.
2016-06-14 15:58:19 +00:00
if boundAmiIDRaw , ok := data . GetOk ( "bound_ami_id" ) ; ok {
2018-03-02 16:09:14 +00:00
roleEntry . BoundAmiIDs = boundAmiIDRaw . ( [ ] string )
2016-06-14 15:58:19 +00:00
}
if boundAccountIDRaw , ok := data . GetOk ( "bound_account_id" ) ; ok {
2018-03-02 16:09:14 +00:00
roleEntry . BoundAccountIDs = boundAccountIDRaw . ( [ ] string )
2016-05-03 16:14:07 +00:00
}
2017-02-24 19:19:10 +00:00
if boundRegionRaw , ok := data . GetOk ( "bound_region" ) ; ok {
2018-03-02 16:09:14 +00:00
roleEntry . BoundRegions = boundRegionRaw . ( [ ] string )
2017-02-24 19:19:10 +00:00
}
if boundVpcIDRaw , ok := data . GetOk ( "bound_vpc_id" ) ; ok {
2018-03-02 16:09:14 +00:00
roleEntry . BoundVpcIDs = boundVpcIDRaw . ( [ ] string )
2017-02-24 19:19:10 +00:00
}
if boundSubnetIDRaw , ok := data . GetOk ( "bound_subnet_id" ) ; ok {
2018-03-02 16:09:14 +00:00
roleEntry . BoundSubnetIDs = boundSubnetIDRaw . ( [ ] string )
2017-02-24 19:19:10 +00:00
}
2017-06-07 14:27:11 +00:00
if resolveAWSUniqueIDsRaw , ok := data . GetOk ( "resolve_aws_unique_ids" ) ; ok {
switch {
case req . Operation == logical . CreateOperation :
roleEntry . ResolveAWSUniqueIDs = resolveAWSUniqueIDsRaw . ( bool )
case roleEntry . ResolveAWSUniqueIDs && ! resolveAWSUniqueIDsRaw . ( bool ) :
return logical . ErrorResponse ( "changing resolve_aws_unique_ids from true to false is not allowed" ) , nil
default :
roleEntry . ResolveAWSUniqueIDs = resolveAWSUniqueIDsRaw . ( bool )
}
} else if req . Operation == logical . CreateOperation {
roleEntry . ResolveAWSUniqueIDs = data . Get ( "resolve_aws_unique_ids" ) . ( bool )
}
2016-09-23 16:47:35 +00:00
if boundIamRoleARNRaw , ok := data . GetOk ( "bound_iam_role_arn" ) ; ok {
2018-03-02 16:09:14 +00:00
roleEntry . BoundIamRoleARNs = boundIamRoleARNRaw . ( [ ] string )
2016-09-23 16:47:35 +00:00
}
2016-09-23 15:22:23 +00:00
if boundIamInstanceProfileARNRaw , ok := data . GetOk ( "bound_iam_instance_profile_arn" ) ; ok {
2018-03-02 16:09:14 +00:00
roleEntry . BoundIamInstanceProfileARNs = boundIamInstanceProfileARNRaw . ( [ ] string )
2016-06-14 18:46:08 +00:00
}
2018-03-15 16:19:28 +00:00
if boundEc2InstanceIDRaw , ok := data . GetOk ( "bound_ec2_instance_id" ) ; ok {
roleEntry . BoundEc2InstanceIDs = boundEc2InstanceIDRaw . ( [ ] string )
}
2017-04-24 19:15:50 +00:00
if boundIamPrincipalARNRaw , ok := data . GetOk ( "bound_iam_principal_arn" ) ; ok {
2018-03-02 16:09:14 +00:00
principalARNs := boundIamPrincipalARNRaw . ( [ ] string )
roleEntry . BoundIamPrincipalARNs = principalARNs
roleEntry . BoundIamPrincipalIDs = [ ] string { }
}
if roleEntry . ResolveAWSUniqueIDs && len ( roleEntry . BoundIamPrincipalIDs ) == 0 {
// we might be turning on resolution on this role, so ensure we update the IDs
for _ , principalARN := range roleEntry . BoundIamPrincipalARNs {
if ! strings . HasSuffix ( principalARN , "*" ) {
principalID , err := b . resolveArnToUniqueIDFunc ( ctx , req . Storage , principalARN )
if err != nil {
return logical . ErrorResponse ( fmt . Sprintf ( "unable to resolve ARN %#v to internal ID: %#v" , principalARN , err ) ) , nil
}
roleEntry . BoundIamPrincipalIDs = append ( roleEntry . BoundIamPrincipalIDs , principalID )
2017-06-07 14:27:11 +00:00
}
}
2017-04-24 19:15:50 +00:00
}
if inferRoleTypeRaw , ok := data . GetOk ( "inferred_entity_type" ) ; ok {
roleEntry . InferredEntityType = inferRoleTypeRaw . ( string )
}
if inferredAWSRegionRaw , ok := data . GetOk ( "inferred_aws_region" ) ; ok {
roleEntry . InferredAWSRegion = inferredAWSRegionRaw . ( string )
}
// auth_type is a special case as it's immutable and can't be changed once a role is created
if authTypeRaw , ok := data . GetOk ( "auth_type" ) ; ok {
// roleEntry.AuthType should only be "" when it's a new role; existing roles without an
// auth_type should have already been upgraded to have one before we get here
if roleEntry . AuthType == "" {
switch authTypeRaw . ( string ) {
case ec2AuthType , iamAuthType :
roleEntry . AuthType = authTypeRaw . ( string )
default :
return logical . ErrorResponse ( fmt . Sprintf ( "unrecognized auth_type: %v" , authTypeRaw . ( string ) ) ) , nil
}
} else if authTypeRaw . ( string ) != roleEntry . AuthType {
return logical . ErrorResponse ( "changing auth_type on a role is not allowed" ) , nil
}
} else if req . Operation == logical . CreateOperation {
switch req . MountType {
// maintain backwards compatibility for old aws-ec2 auth types
case "aws-ec2" :
roleEntry . AuthType = ec2AuthType
// but default to iamAuth for new mounts going forward
case "aws" :
roleEntry . AuthType = iamAuthType
default :
roleEntry . AuthType = iamAuthType
}
}
allowEc2Binds := roleEntry . AuthType == ec2AuthType
if roleEntry . InferredEntityType != "" {
switch {
case roleEntry . AuthType != iamAuthType :
return logical . ErrorResponse ( "specified inferred_entity_type but didn't allow iam auth_type" ) , nil
case roleEntry . InferredEntityType != ec2EntityType :
return logical . ErrorResponse ( fmt . Sprintf ( "specified invalid inferred_entity_type: %s" , roleEntry . InferredEntityType ) ) , nil
case roleEntry . InferredAWSRegion == "" :
return logical . ErrorResponse ( "specified inferred_entity_type but not inferred_aws_region" ) , nil
}
allowEc2Binds = true
} else if roleEntry . InferredAWSRegion != "" {
return logical . ErrorResponse ( "specified inferred_aws_region but not inferred_entity_type" ) , nil
}
numBinds := 0
2018-03-02 16:09:14 +00:00
if len ( roleEntry . BoundAccountIDs ) > 0 {
2017-04-24 19:15:50 +00:00
if ! allowEc2Binds {
2018-03-15 16:19:28 +00:00
return logical . ErrorResponse ( fmt . Sprintf ( "specified bound_account_id but not specifying ec2 auth_type or inferring %s" , ec2EntityType ) ) , nil
2017-04-24 19:15:50 +00:00
}
numBinds ++
}
2018-03-02 16:09:14 +00:00
if len ( roleEntry . BoundRegions ) > 0 {
2017-04-24 19:15:50 +00:00
if roleEntry . AuthType != ec2AuthType {
2018-03-15 16:19:28 +00:00
return logical . ErrorResponse ( "specified bound_region but not specifying ec2 auth_type" ) , nil
2017-04-24 19:15:50 +00:00
}
numBinds ++
}
2018-03-02 16:09:14 +00:00
if len ( roleEntry . BoundAmiIDs ) > 0 {
2017-04-24 19:15:50 +00:00
if ! allowEc2Binds {
2018-03-15 16:19:28 +00:00
return logical . ErrorResponse ( fmt . Sprintf ( "specified bound_ami_id but not specifying ec2 auth_type or inferring %s" , ec2EntityType ) ) , nil
2017-04-24 19:15:50 +00:00
}
numBinds ++
}
2018-03-02 16:09:14 +00:00
if len ( roleEntry . BoundIamInstanceProfileARNs ) > 0 {
2017-04-24 19:15:50 +00:00
if ! allowEc2Binds {
2018-03-15 16:19:28 +00:00
return logical . ErrorResponse ( fmt . Sprintf ( "specified bound_iam_instance_profile_arn but not specifying ec2 auth_type or inferring %s" , ec2EntityType ) ) , nil
}
numBinds ++
}
if len ( roleEntry . BoundEc2InstanceIDs ) > 0 {
if ! allowEc2Binds {
return logical . ErrorResponse ( fmt . Sprintf ( "specified bound_ec2_instance_id but not specifying ec2 auth_type or inferring %s" , ec2EntityType ) ) , nil
2017-04-24 19:15:50 +00:00
}
numBinds ++
}
2018-03-02 16:09:14 +00:00
if len ( roleEntry . BoundIamRoleARNs ) > 0 {
2017-04-24 19:15:50 +00:00
if ! allowEc2Binds {
2018-03-15 16:19:28 +00:00
return logical . ErrorResponse ( fmt . Sprintf ( "specified bound_iam_role_arn but not specifying ec2 auth_type or inferring %s" , ec2EntityType ) ) , nil
2017-04-24 19:15:50 +00:00
}
numBinds ++
}
2018-03-02 16:09:14 +00:00
if len ( roleEntry . BoundIamPrincipalARNs ) > 0 {
2017-04-24 19:15:50 +00:00
if roleEntry . AuthType != iamAuthType {
2018-03-15 16:19:28 +00:00
return logical . ErrorResponse ( "specified bound_iam_principal_arn but not specifying iam auth_type" ) , nil
2017-04-24 19:15:50 +00:00
}
numBinds ++
}
2018-03-02 16:09:14 +00:00
if len ( roleEntry . BoundVpcIDs ) > 0 {
2017-04-24 19:15:50 +00:00
if ! allowEc2Binds {
2018-03-15 16:19:28 +00:00
return logical . ErrorResponse ( fmt . Sprintf ( "specified bound_vpc_id but not specifying ec2 auth_type or inferring %s" , ec2EntityType ) ) , nil
2017-04-24 19:15:50 +00:00
}
numBinds ++
}
2018-03-02 16:09:14 +00:00
if len ( roleEntry . BoundSubnetIDs ) > 0 {
2017-04-24 19:15:50 +00:00
if ! allowEc2Binds {
2018-03-15 16:19:28 +00:00
return logical . ErrorResponse ( fmt . Sprintf ( "specified bound_subnet_id but not specifying ec2 auth_type or inferring %s" , ec2EntityType ) ) , nil
2017-04-24 19:15:50 +00:00
}
numBinds ++
}
if numBinds == 0 {
2016-06-14 15:58:19 +00:00
return logical . ErrorResponse ( "at least be one bound parameter should be specified on the role" ) , nil
2016-05-03 16:14:07 +00:00
}
2017-09-13 15:36:52 +00:00
policiesRaw , ok := data . GetOk ( "policies" )
2016-05-03 16:14:07 +00:00
if ok {
2017-09-13 15:36:52 +00:00
roleEntry . Policies = policyutil . ParsePolicies ( policiesRaw )
2016-05-03 16:14:07 +00:00
} else if req . Operation == logical . CreateOperation {
2017-09-13 15:36:52 +00:00
roleEntry . Policies = [ ] string { }
2016-05-03 16:14:07 +00:00
}
disallowReauthenticationBool , ok := data . GetOk ( "disallow_reauthentication" )
if ok {
2017-04-24 19:15:50 +00:00
if roleEntry . AuthType != ec2AuthType {
return logical . ErrorResponse ( "specified disallow_reauthentication when not using ec2 auth type" ) , nil
}
2016-05-03 16:14:07 +00:00
roleEntry . DisallowReauthentication = disallowReauthenticationBool . ( bool )
2017-04-24 19:15:50 +00:00
} else if req . Operation == logical . CreateOperation && roleEntry . AuthType == ec2AuthType {
2016-05-03 16:14:07 +00:00
roleEntry . DisallowReauthentication = data . Get ( "disallow_reauthentication" ) . ( bool )
}
allowInstanceMigrationBool , ok := data . GetOk ( "allow_instance_migration" )
if ok {
2017-04-24 19:15:50 +00:00
if roleEntry . AuthType != ec2AuthType {
return logical . ErrorResponse ( "specified allow_instance_migration when not using ec2 auth type" ) , nil
}
2016-05-03 16:14:07 +00:00
roleEntry . AllowInstanceMigration = allowInstanceMigrationBool . ( bool )
2017-04-24 19:15:50 +00:00
} else if req . Operation == logical . CreateOperation && roleEntry . AuthType == ec2AuthType {
2016-05-03 16:14:07 +00:00
roleEntry . AllowInstanceMigration = data . Get ( "allow_instance_migration" ) . ( bool )
}
2017-11-06 22:12:07 +00:00
if roleEntry . AllowInstanceMigration && roleEntry . DisallowReauthentication {
return logical . ErrorResponse ( "cannot specify both disallow_reauthentication=true and allow_instance_migration=true" ) , nil
}
2016-05-05 19:32:14 +00:00
var resp logical . Response
2016-08-09 21:29:45 +00:00
ttlRaw , ok := data . GetOk ( "ttl" )
if ok {
ttl := time . Duration ( ttlRaw . ( int ) ) * time . Second
defaultLeaseTTL := b . System ( ) . DefaultLeaseTTL ( )
if ttl > defaultLeaseTTL {
resp . AddWarning ( fmt . Sprintf ( "Given ttl of %d seconds greater than current mount/system default of %d seconds; ttl will be capped at login time" , ttl / time . Second , defaultLeaseTTL / time . Second ) )
}
roleEntry . TTL = ttl
} else if req . Operation == logical . CreateOperation {
roleEntry . TTL = time . Duration ( data . Get ( "ttl" ) . ( int ) ) * time . Second
}
2016-05-03 16:14:07 +00:00
maxTTLInt , ok := data . GetOk ( "max_ttl" )
if ok {
maxTTL := time . Duration ( maxTTLInt . ( int ) ) * time . Second
systemMaxTTL := b . System ( ) . MaxLeaseTTL ( )
if maxTTL > systemMaxTTL {
2016-08-09 21:29:45 +00:00
resp . AddWarning ( fmt . Sprintf ( "Given max_ttl of %d seconds greater than current mount/system default of %d seconds; max_ttl will be capped at login time" , maxTTL / time . Second , systemMaxTTL / time . Second ) )
2016-05-03 16:14:07 +00:00
}
if maxTTL < time . Duration ( 0 ) {
return logical . ErrorResponse ( "max_ttl cannot be negative" ) , nil
}
roleEntry . MaxTTL = maxTTL
} else if req . Operation == logical . CreateOperation {
roleEntry . MaxTTL = time . Duration ( data . Get ( "max_ttl" ) . ( int ) ) * time . Second
}
2016-08-09 21:45:42 +00:00
if roleEntry . MaxTTL != 0 && roleEntry . MaxTTL < roleEntry . TTL {
2016-08-09 21:29:45 +00:00
return logical . ErrorResponse ( "ttl should be shorter than max_ttl" ) , nil
}
2017-02-02 18:28:01 +00:00
periodRaw , ok := data . GetOk ( "period" )
if ok {
roleEntry . Period = time . Second * time . Duration ( periodRaw . ( int ) )
} else if req . Operation == logical . CreateOperation {
roleEntry . Period = time . Second * time . Duration ( data . Get ( "period" ) . ( int ) )
}
if roleEntry . Period > b . System ( ) . MaxLeaseTTL ( ) {
return logical . ErrorResponse ( fmt . Sprintf ( "'period' of '%s' is greater than the backend's maximum lease TTL of '%s'" , roleEntry . Period . String ( ) , b . System ( ) . MaxLeaseTTL ( ) . String ( ) ) ) , nil
}
2016-05-03 16:14:07 +00:00
roleTagStr , ok := data . GetOk ( "role_tag" )
if ok {
2017-04-24 19:15:50 +00:00
if roleEntry . AuthType != ec2AuthType {
return logical . ErrorResponse ( "tried to enable role_tag when not using ec2 auth method" ) , nil
}
2016-05-03 16:14:07 +00:00
roleEntry . RoleTag = roleTagStr . ( string )
// There is a limit of 127 characters on the tag key for AWS EC2 instances.
// Complying to that requirement, do not allow the value of 'key' to be more than that.
if len ( roleEntry . RoleTag ) > 127 {
2016-05-05 18:51:09 +00:00
return logical . ErrorResponse ( "length of role tag exceeds the EC2 key limit of 127 characters" ) , nil
2016-05-03 16:14:07 +00:00
}
2017-04-24 19:15:50 +00:00
} else if req . Operation == logical . CreateOperation && roleEntry . AuthType == ec2AuthType {
2016-05-03 16:14:07 +00:00
roleEntry . RoleTag = data . Get ( "role_tag" ) . ( string )
}
2016-05-05 18:51:09 +00:00
if roleEntry . HMACKey == "" {
roleEntry . HMACKey , err = uuid . GenerateUUID ( )
if err != nil {
2018-04-05 15:49:21 +00:00
return nil , errwrap . Wrapf ( "failed to generate role HMAC key: {{err}}" , err )
2016-05-05 18:51:09 +00:00
}
2016-05-03 16:14:07 +00:00
}
2018-01-19 06:44:44 +00:00
if err := b . nonLockedSetAWSRole ( ctx , req . Storage , roleName , roleEntry ) ; err != nil {
2016-05-03 16:14:07 +00:00
return nil , err
}
2017-06-05 14:52:43 +00:00
if len ( resp . Warnings ) == 0 {
2016-05-05 19:32:14 +00:00
return nil , nil
}
return & resp , nil
2016-05-03 16:14:07 +00:00
}
2018-03-02 16:09:14 +00:00
// Struct to hold the information associated with a Vault role
2016-05-03 16:14:07 +00:00
type awsRoleEntry struct {
2018-03-02 16:09:14 +00:00
AuthType string ` json:"auth_type" `
BoundAmiIDs [ ] string ` json:"bound_ami_id_list" `
BoundAccountIDs [ ] string ` json:"bound_account_id_list" `
2018-03-15 16:19:28 +00:00
BoundEc2InstanceIDs [ ] string ` json:"bound_ec2_instance_id_list" `
2018-03-02 16:09:14 +00:00
BoundIamPrincipalARNs [ ] string ` json:"bound_iam_principal_arn_list" `
BoundIamPrincipalIDs [ ] string ` json:"bound_iam_principal_id_list" `
BoundIamRoleARNs [ ] string ` json:"bound_iam_role_arn_list" `
BoundIamInstanceProfileARNs [ ] string ` json:"bound_iam_instance_profile_arn_list" `
BoundRegions [ ] string ` json:"bound_region_list" `
BoundSubnetIDs [ ] string ` json:"bound_subnet_id_list" `
BoundVpcIDs [ ] string ` json:"bound_vpc_id_list" `
InferredEntityType string ` json:"inferred_entity_type" `
InferredAWSRegion string ` json:"inferred_aws_region" `
ResolveAWSUniqueIDs bool ` json:"resolve_aws_unique_ids" `
RoleTag string ` json:"role_tag" `
AllowInstanceMigration bool ` json:"allow_instance_migration" `
TTL time . Duration ` json:"ttl" `
MaxTTL time . Duration ` json:"max_ttl" `
Policies [ ] string ` json:"policies" `
DisallowReauthentication bool ` json:"disallow_reauthentication" `
HMACKey string ` json:"hmac_key" `
Period time . Duration ` json:"period" `
Version int ` json:"version" `
// DEPRECATED -- these are the old fields before we supported lists and exist for backwards compatibility
BoundAmiID string ` json:"bound_ami_id,omitempty" `
BoundAccountID string ` json:"bound_account_id,omitempty" `
BoundIamPrincipalARN string ` json:"bound_iam_principal_arn,omitempty" `
BoundIamPrincipalID string ` json:"bound_iam_principal_id,omitempty" `
BoundIamRoleARN string ` json:"bound_iam_role_arn,omitempty" `
BoundIamInstanceProfileARN string ` json:"bound_iam_instance_profile_arn,omitempty" `
BoundRegion string ` json:"bound_region,omitempty" `
BoundSubnetID string ` json:"bound_subnet_id,omitempty" `
BoundVpcID string ` json:"bound_vpc_id,omitempty" `
}
func ( r * awsRoleEntry ) ToResponseData ( ) map [ string ] interface { } {
responseData := map [ string ] interface { } {
"auth_type" : r . AuthType ,
"bound_ami_id" : r . BoundAmiIDs ,
"bound_account_id" : r . BoundAccountIDs ,
2018-03-15 16:19:28 +00:00
"bound_ec2_instance_id" : r . BoundEc2InstanceIDs ,
2018-03-02 16:09:14 +00:00
"bound_iam_principal_arn" : r . BoundIamPrincipalARNs ,
"bound_iam_principal_id" : r . BoundIamPrincipalIDs ,
"bound_iam_role_arn" : r . BoundIamRoleARNs ,
"bound_iam_instance_profile_arn" : r . BoundIamInstanceProfileARNs ,
"bound_region" : r . BoundRegions ,
"bound_subnet_id" : r . BoundSubnetIDs ,
"bound_vpc_id" : r . BoundVpcIDs ,
"inferred_entity_type" : r . InferredEntityType ,
"inferred_aws_region" : r . InferredAWSRegion ,
"resolve_aws_unique_ids" : r . ResolveAWSUniqueIDs ,
"role_tag" : r . RoleTag ,
"allow_instance_migration" : r . AllowInstanceMigration ,
"ttl" : r . TTL / time . Second ,
"max_ttl" : r . MaxTTL / time . Second ,
"policies" : r . Policies ,
"disallow_reauthentication" : r . DisallowReauthentication ,
"period" : r . Period / time . Second ,
}
convertNilToEmptySlice := func ( data map [ string ] interface { } , field string ) {
if data [ field ] == nil || len ( data [ field ] . ( [ ] string ) ) == 0 {
data [ field ] = [ ] string { }
}
}
convertNilToEmptySlice ( responseData , "bound_ami_id" )
convertNilToEmptySlice ( responseData , "bound_account_id" )
convertNilToEmptySlice ( responseData , "bound_iam_principal_arn" )
convertNilToEmptySlice ( responseData , "bound_iam_principal_id" )
convertNilToEmptySlice ( responseData , "bound_iam_role_arn" )
convertNilToEmptySlice ( responseData , "bound_iam_instance_profile_arn" )
convertNilToEmptySlice ( responseData , "bound_region" )
convertNilToEmptySlice ( responseData , "bound_subnet_id" )
convertNilToEmptySlice ( responseData , "bound_vpc_id" )
return responseData
2016-05-03 16:14:07 +00:00
}
const pathRoleSyn = `
Create a role and associate policies to it .
`
const pathRoleDesc = `
A precondition for login is that a role should be created in the backend .
The login endpoint takes in the role name against which the instance
should be validated . After authenticating the instance , the authorization
for the instance to access Vault ' s resources is determined by the policies
that are associated to the role though this endpoint .
When the instances require only a subset of policies on the role , then
' role_tag ' option on the role can be enabled to create a role tag via the
2016-05-13 18:31:13 +00:00
endpoint ' role / < role > / tag ' . This tag then needs to be applied on the
2016-05-03 16:14:07 +00:00
instance before it attempts a login . The policies on the tag should be a
subset of policies that are associated to the role . In order to enable
login using tags , ' role_tag ' option should be set while creating a role .
2017-04-24 19:15:50 +00:00
This only applies when authenticating EC2 instances .
2016-05-03 16:14:07 +00:00
Also , a ' max_ttl ' can be configured in this endpoint that determines the maximum
2016-05-05 18:51:09 +00:00
duration for which a login can be renewed . Note that the ' max_ttl ' has an upper
2016-05-03 16:14:07 +00:00
limit of the ' max_ttl ' value on the backend ' s mount .
`
const pathListRolesHelpSyn = `
Lists all the roles that are registered with Vault .
`
const pathListRolesHelpDesc = `
Roles will be listed by their respective role names .
`