2018-09-26 15:27:12 +00:00
package awsauth
import (
"context"
"fmt"
2019-04-13 07:44:06 +00:00
"github.com/hashicorp/vault/sdk/framework"
2020-04-27 17:06:07 +00:00
"github.com/hashicorp/vault/sdk/helper/authmetadata"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/hashicorp/vault/sdk/logical"
2018-09-26 15:27:12 +00:00
)
2020-04-27 17:06:07 +00:00
var (
// iamAuthMetadataFields is a list of the default auth metadata
// added to tokens during login. The default alias type used
// by this back-end is the role ID. Subsequently, the default
// fields included are expected to have a low rate of change
// when the role ID is in use.
iamAuthMetadataFields = & authmetadata . Fields {
FieldName : "iam_metadata" ,
Default : [ ] string {
"account_id" ,
"auth_type" ,
} ,
AvailableToAdd : [ ] string {
"canonical_arn" ,
"client_arn" ,
"client_user_id" ,
"inferred_aws_region" ,
"inferred_entity_id" ,
"inferred_entity_type" ,
} ,
}
// ec2AuthMetadataFields is a list of the default auth metadata
// added to tokens during login. The default alias type used
// by this back-end is the role ID. Subsequently, the default
// fields included are expected to have a low rate of change
// when the role ID is in use.
ec2AuthMetadataFields = & authmetadata . Fields {
FieldName : "ec2_metadata" ,
Default : [ ] string {
"account_id" ,
"auth_type" ,
} ,
AvailableToAdd : [ ] string {
"ami_id" ,
"instance_id" ,
"region" ,
} ,
}
)
2019-07-31 23:11:35 +00:00
func ( b * backend ) pathConfigIdentity ( ) * framework . Path {
2018-09-26 15:27:12 +00:00
return & framework . Path {
Pattern : "config/identity$" ,
Fields : map [ string ] * framework . FieldSchema {
2019-01-09 23:28:29 +00:00
"iam_alias" : {
2018-09-26 15:27:12 +00:00
Type : framework . TypeString ,
Default : identityAliasIAMUniqueID ,
2019-01-30 20:46:43 +00:00
Description : fmt . Sprintf ( "Configure how the AWS auth method generates entity aliases when using IAM auth. Valid values are %q, %q, and %q. Defaults to %q." , identityAliasRoleID , identityAliasIAMUniqueID , identityAliasIAMFullArn , identityAliasRoleID ) ,
2018-09-26 15:27:12 +00:00
} ,
2020-04-27 17:06:07 +00:00
iamAuthMetadataFields . FieldName : authmetadata . FieldSchema ( iamAuthMetadataFields ) ,
2019-01-09 23:28:29 +00:00
"ec2_alias" : {
Type : framework . TypeString ,
Default : identityAliasEC2InstanceID ,
2019-01-31 16:53:54 +00:00
Description : fmt . Sprintf ( "Configure how the AWS auth method generates entity alias when using EC2 auth. Valid values are %q, %q, and %q. Defaults to %q." , identityAliasRoleID , identityAliasEC2InstanceID , identityAliasEC2ImageID , identityAliasRoleID ) ,
2019-01-09 23:28:29 +00:00
} ,
2020-04-27 17:06:07 +00:00
ec2AuthMetadataFields . FieldName : authmetadata . FieldSchema ( ec2AuthMetadataFields ) ,
2018-09-26 15:27:12 +00:00
} ,
2019-07-31 23:11:35 +00:00
Operations : map [ logical . Operation ] framework . OperationHandler {
logical . ReadOperation : & framework . PathOperation {
Callback : pathConfigIdentityRead ,
} ,
logical . UpdateOperation : & framework . PathOperation {
Callback : pathConfigIdentityUpdate ,
} ,
2018-09-26 15:27:12 +00:00
} ,
HelpSynopsis : pathConfigIdentityHelpSyn ,
HelpDescription : pathConfigIdentityHelpDesc ,
}
}
2019-01-09 23:28:29 +00:00
func identityConfigEntry ( ctx context . Context , s logical . Storage ) ( * identityConfig , error ) {
entryRaw , err := s . Get ( ctx , "config/identity" )
2018-09-26 15:27:12 +00:00
if err != nil {
return nil , err
}
2019-01-09 23:28:29 +00:00
2020-04-27 17:06:07 +00:00
entry := & identityConfig {
IAMAuthMetadataHandler : authmetadata . NewHandler ( iamAuthMetadataFields ) ,
EC2AuthMetadataHandler : authmetadata . NewHandler ( ec2AuthMetadataFields ) ,
}
2019-01-30 20:46:43 +00:00
if entryRaw != nil {
2020-04-27 17:06:07 +00:00
if err := entryRaw . DecodeJSON ( entry ) ; err != nil {
2019-01-30 20:46:43 +00:00
return nil , err
}
2019-01-09 23:28:29 +00:00
}
if entry . IAMAlias == "" {
2019-01-30 20:46:43 +00:00
entry . IAMAlias = identityAliasRoleID
2019-01-09 23:28:29 +00:00
}
if entry . EC2Alias == "" {
2019-01-30 20:46:43 +00:00
entry . EC2Alias = identityAliasRoleID
2019-01-09 23:28:29 +00:00
}
2020-04-27 17:06:07 +00:00
return entry , nil
2019-01-09 23:28:29 +00:00
}
2019-07-31 23:11:35 +00:00
func pathConfigIdentityRead ( ctx context . Context , req * logical . Request , _ * framework . FieldData ) ( * logical . Response , error ) {
2019-01-09 23:28:29 +00:00
config , err := identityConfigEntry ( ctx , req . Storage )
if err != nil {
2018-09-26 15:27:12 +00:00
return nil , err
}
2019-01-09 23:28:29 +00:00
2018-09-26 15:27:12 +00:00
return & logical . Response {
Data : map [ string ] interface { } {
2020-04-27 17:06:07 +00:00
"iam_alias" : config . IAMAlias ,
iamAuthMetadataFields . FieldName : config . IAMAuthMetadataHandler . AuthMetadata ( ) ,
"ec2_alias" : config . EC2Alias ,
ec2AuthMetadataFields . FieldName : config . EC2AuthMetadataHandler . AuthMetadata ( ) ,
2018-09-26 15:27:12 +00:00
} ,
} , nil
}
func pathConfigIdentityUpdate ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2019-01-09 23:28:29 +00:00
config , err := identityConfigEntry ( ctx , req . Storage )
if err != nil {
return nil , err
}
2018-09-26 15:27:12 +00:00
iamAliasRaw , ok := data . GetOk ( "iam_alias" )
if ok {
iamAlias := iamAliasRaw . ( string )
2019-01-30 20:46:43 +00:00
allowedIAMAliasValues := [ ] string { identityAliasRoleID , identityAliasIAMUniqueID , identityAliasIAMFullArn }
2018-09-26 15:27:12 +00:00
if ! strutil . StrListContains ( allowedIAMAliasValues , iamAlias ) {
return logical . ErrorResponse ( fmt . Sprintf ( "iam_alias of %q not in set of allowed values: %v" , iamAlias , allowedIAMAliasValues ) ) , nil
}
2019-01-09 23:28:29 +00:00
config . IAMAlias = iamAlias
}
ec2AliasRaw , ok := data . GetOk ( "ec2_alias" )
if ok {
ec2Alias := ec2AliasRaw . ( string )
2019-01-30 20:46:43 +00:00
allowedEC2AliasValues := [ ] string { identityAliasRoleID , identityAliasEC2InstanceID , identityAliasEC2ImageID }
2019-01-09 23:28:29 +00:00
if ! strutil . StrListContains ( allowedEC2AliasValues , ec2Alias ) {
return logical . ErrorResponse ( fmt . Sprintf ( "ec2_alias of %q not in set of allowed values: %v" , ec2Alias , allowedEC2AliasValues ) ) , nil
2018-09-26 15:27:12 +00:00
}
2019-01-09 23:28:29 +00:00
config . EC2Alias = ec2Alias
2018-09-26 15:27:12 +00:00
}
2020-04-27 17:06:07 +00:00
if err := config . IAMAuthMetadataHandler . ParseAuthMetadata ( data ) ; err != nil {
return logical . ErrorResponse ( err . Error ( ) ) , logical . ErrInvalidRequest
}
if err := config . EC2AuthMetadataHandler . ParseAuthMetadata ( data ) ; err != nil {
return logical . ErrorResponse ( err . Error ( ) ) , logical . ErrInvalidRequest
}
2019-01-09 23:28:29 +00:00
entry , err := logical . StorageEntryJSON ( "config/identity" , config )
if err != nil {
return nil , err
}
err = req . Storage . Put ( ctx , entry )
if err != nil {
return nil , err
}
2018-09-26 15:27:12 +00:00
return nil , nil
}
type identityConfig struct {
2020-04-27 17:06:07 +00:00
IAMAlias string ` json:"iam_alias" `
IAMAuthMetadataHandler * authmetadata . Handler ` json:"iam_auth_metadata_handler" `
EC2Alias string ` json:"ec2_alias" `
EC2AuthMetadataHandler * authmetadata . Handler ` json:"ec2_auth_metadata_handler" `
2018-09-26 15:27:12 +00:00
}
const identityAliasIAMUniqueID = "unique_id"
const identityAliasIAMFullArn = "full_arn"
2019-01-09 23:28:29 +00:00
const identityAliasEC2InstanceID = "instance_id"
const identityAliasEC2ImageID = "image_id"
2019-01-30 20:46:43 +00:00
const identityAliasRoleID = "role_id"
2018-09-26 15:27:12 +00:00
const pathConfigIdentityHelpSyn = `
Configure the way the AWS auth method interacts with the identity store
`
const pathConfigIdentityHelpDesc = `
The AWS auth backend defaults to aliasing an IAM principal ' s unique ID to the
identity store . This path allows users to change how Vault configures the
mapping to Identity aliases for more flexibility .
You can set the iam_alias parameter to one of the following values :
* ' unique_id ' : This retains Vault ' s default behavior
* ' full_arn ' : This maps the full authenticated ARN to the identity alias , e . g . ,
" arn : aws : sts : : < account_id > : assumed - role / < role_name > / < role_session_name >
This is useful where you have an identity provder that sets role_session_name
to a known value of a person , such as a username or email address , and allows
you to map those roles back to entries in your identity store .
`