2015-03-20 16:59:48 +00:00
package aws
import (
2018-01-08 18:31:38 +00:00
"context"
2018-02-16 16:11:17 +00:00
"github.com/aws/aws-sdk-go/aws"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/framework"
2019-04-13 07:44:06 +00:00
"github.com/hashicorp/vault/sdk/logical"
2015-03-20 16:59:48 +00:00
)
2021-08-09 16:40:47 +00:00
// A single default template that supports both the different credential types (IAM/STS) that are capped at differing length limits (64 chars/32 chars respectively)
const defaultUserNameTemplate = ` {{ if ( eq .Type "STS" ) }} {{ printf "vault-%s-%s" ( unix_time ) ( random 20 ) | truncate 32 }} {{ else }} {{ printf "vault-%s-%s-%s" ( printf "%s-%s" ( .DisplayName ) ( .PolicyName ) | truncate 42 ) ( unix_time ) ( random 20 ) | truncate 64 }} {{ end }} `
2021-07-20 16:48:29 +00:00
2018-09-18 20:26:06 +00:00
func pathConfigRoot ( b * backend ) * framework . Path {
2015-03-20 16:59:48 +00:00
return & framework . Path {
2015-04-19 05:21:31 +00:00
Pattern : "config/root" ,
2015-03-20 16:59:48 +00:00
Fields : map [ string ] * framework . FieldSchema {
2021-04-08 16:43:39 +00:00
"access_key" : {
2015-03-20 16:59:48 +00:00
Type : framework . TypeString ,
Description : "Access key with permission to create new keys." ,
} ,
2021-04-08 16:43:39 +00:00
"secret_key" : {
2015-03-20 16:59:48 +00:00
Type : framework . TypeString ,
Description : "Secret key with permission to create new keys." ,
} ,
2021-04-08 16:43:39 +00:00
"region" : {
2015-03-20 16:59:48 +00:00
Type : framework . TypeString ,
Description : "Region for API calls." ,
} ,
2021-04-08 16:43:39 +00:00
"iam_endpoint" : {
2017-11-06 18:31:38 +00:00
Type : framework . TypeString ,
Description : "Endpoint to custom IAM server URL" ,
} ,
2021-04-08 16:43:39 +00:00
"sts_endpoint" : {
2017-11-06 18:31:38 +00:00
Type : framework . TypeString ,
Description : "Endpoint to custom STS server URL" ,
} ,
2021-04-08 16:43:39 +00:00
"max_retries" : {
2018-02-16 16:11:17 +00:00
Type : framework . TypeInt ,
Default : aws . UseServiceDefaultRetries ,
Description : "Maximum number of retries for recoverable exceptions of AWS APIs" ,
} ,
2021-07-20 16:48:29 +00:00
"username_template" : {
Type : framework . TypeString ,
Description : "Template to generate custom IAM usernames" ,
} ,
2015-03-20 16:59:48 +00:00
} ,
Callbacks : map [ logical . Operation ] framework . OperationFunc {
2019-09-13 17:07:04 +00:00
logical . ReadOperation : b . pathConfigRootRead ,
2018-09-18 20:26:06 +00:00
logical . UpdateOperation : b . pathConfigRootWrite ,
2015-03-20 16:59:48 +00:00
} ,
2015-04-04 04:10:54 +00:00
2015-04-19 05:22:35 +00:00
HelpSynopsis : pathConfigRootHelpSyn ,
HelpDescription : pathConfigRootHelpDesc ,
2015-03-20 16:59:48 +00:00
}
}
2019-09-13 17:07:04 +00:00
func ( b * backend ) pathConfigRootRead ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
b . clientMutex . RLock ( )
defer b . clientMutex . RUnlock ( )
entry , err := req . Storage . Get ( ctx , "config/root" )
if err != nil {
return nil , err
}
if entry == nil {
return nil , nil
}
var config rootConfig
if err := entry . DecodeJSON ( & config ) ; err != nil {
return nil , err
}
configData := map [ string ] interface { } {
2021-07-20 16:48:29 +00:00
"access_key" : config . AccessKey ,
"region" : config . Region ,
"iam_endpoint" : config . IAMEndpoint ,
"sts_endpoint" : config . STSEndpoint ,
"max_retries" : config . MaxRetries ,
"username_template" : config . UsernameTemplate ,
2019-09-13 17:07:04 +00:00
}
return & logical . Response {
Data : configData ,
} , nil
}
2018-09-18 20:26:06 +00:00
func ( b * backend ) pathConfigRootWrite ( ctx context . Context , req * logical . Request , data * framework . FieldData ) ( * logical . Response , error ) {
2015-04-19 05:21:31 +00:00
region := data . Get ( "region" ) . ( string )
2017-11-06 18:31:38 +00:00
iamendpoint := data . Get ( "iam_endpoint" ) . ( string )
stsendpoint := data . Get ( "sts_endpoint" ) . ( string )
2018-02-16 16:11:17 +00:00
maxretries := data . Get ( "max_retries" ) . ( int )
2021-07-20 16:48:29 +00:00
usernameTemplate := data . Get ( "username_template" ) . ( string )
if usernameTemplate == "" {
usernameTemplate = defaultUserNameTemplate
}
2015-04-19 05:21:31 +00:00
2018-09-26 14:10:00 +00:00
b . clientMutex . Lock ( )
defer b . clientMutex . Unlock ( )
2015-04-19 05:21:31 +00:00
entry , err := logical . StorageEntryJSON ( "config/root" , rootConfig {
2021-07-20 16:48:29 +00:00
AccessKey : data . Get ( "access_key" ) . ( string ) ,
SecretKey : data . Get ( "secret_key" ) . ( string ) ,
IAMEndpoint : iamendpoint ,
STSEndpoint : stsendpoint ,
Region : region ,
MaxRetries : maxretries ,
UsernameTemplate : usernameTemplate ,
2015-03-20 16:59:48 +00:00
} )
if err != nil {
return nil , err
}
2018-01-19 06:44:44 +00:00
if err := req . Storage . Put ( ctx , entry ) ; err != nil {
2015-03-20 16:59:48 +00:00
return nil , err
}
2018-09-18 20:26:06 +00:00
// clear possible cached IAM / STS clients after successfully updating
// config/root
b . iamClient = nil
b . stsClient = nil
2015-03-20 16:59:48 +00:00
return nil , nil
}
type rootConfig struct {
2021-07-20 16:48:29 +00:00
AccessKey string ` json:"access_key" `
SecretKey string ` json:"secret_key" `
IAMEndpoint string ` json:"iam_endpoint" `
STSEndpoint string ` json:"sts_endpoint" `
Region string ` json:"region" `
MaxRetries int ` json:"max_retries" `
UsernameTemplate string ` json:"username_template" `
2015-03-20 16:59:48 +00:00
}
2015-04-04 04:10:54 +00:00
2015-04-19 05:22:35 +00:00
const pathConfigRootHelpSyn = `
2015-04-04 04:10:54 +00:00
Configure the root credentials that are used to manage IAM .
`
2015-04-19 05:22:35 +00:00
const pathConfigRootHelpDesc = `
2015-04-04 04:10:54 +00:00
Before doing anything , the AWS backend needs credentials that are able
to manage IAM policies , users , access keys , etc . This endpoint is used
2018-03-20 18:54:10 +00:00
to configure those credentials . They don ' t necessarily need to be root
2015-04-04 04:10:54 +00:00
keys as long as they have permission to manage IAM .
`