use a UI wrapper to auto-decode error messages
update docs to reflect optional config
This commit is contained in:
parent
191996628c
commit
09797df958
|
@ -19,6 +19,7 @@ import (
|
|||
type AccessConfig struct {
|
||||
AccessKey string `mapstructure:"access_key"`
|
||||
CustomEndpointEc2 string `mapstructure:"custom_endpoint_ec2"`
|
||||
DecodeAuthZMessages bool `mapstructure:"decode_authorization_messages"`
|
||||
MFACode string `mapstructure:"mfa_code"`
|
||||
ProfileName string `mapstructure:"profile"`
|
||||
RawRegion string `mapstructure:"region"`
|
||||
|
@ -91,6 +92,11 @@ func (c *AccessConfig) Session() (*session.Session, error) {
|
|||
}
|
||||
log.Printf("[INFO] AWS Auth provider used: %q", cp.ProviderName)
|
||||
}
|
||||
|
||||
if c.DecodeAuthZMessages {
|
||||
DecodeAuthZMessages(c.session)
|
||||
}
|
||||
|
||||
return c.session, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/sts"
|
||||
)
|
||||
|
||||
var encodedFailureMessagePattern = regexp.MustCompile(`(?i)(.*) Encoded authorization failure message: ([\w-]+) ?( .*)?`)
|
||||
|
||||
type stsDecoder interface {
|
||||
DecodeAuthorizationMessage(input *sts.DecodeAuthorizationMessageInput) (*sts.DecodeAuthorizationMessageOutput, error)
|
||||
}
|
||||
|
||||
// decodeError replaces encoded authorization messages with the
|
||||
// decoded results
|
||||
func decodeAWSError(decoder stsDecoder, err error) error {
|
||||
|
||||
groups := encodedFailureMessagePattern.FindStringSubmatch(err.Error())
|
||||
if groups != nil && len(groups) > 1 {
|
||||
result, decodeErr := decoder.DecodeAuthorizationMessage(&sts.DecodeAuthorizationMessageInput{
|
||||
EncodedMessage: aws.String(groups[2]),
|
||||
})
|
||||
if decodeErr == nil {
|
||||
msg := aws.StringValue(result.DecodedMessage)
|
||||
return fmt.Errorf("%s Authorization failure message: '%s'%s", groups[1], msg, groups[3])
|
||||
}
|
||||
log.Printf("[WARN] Attempted to decode authorization message, but received: %v", decodeErr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// DecodeAuthZMessages enables automatic decoding of any
|
||||
// encoded authorization messages
|
||||
func DecodeAuthZMessages(sess *session.Session) {
|
||||
azd := &authZMessageDecoder{
|
||||
Decoder: sts.New(sess),
|
||||
}
|
||||
sess.Handlers.UnmarshalError.AfterEachFn = azd.afterEachFn
|
||||
}
|
||||
|
||||
type authZMessageDecoder struct {
|
||||
Decoder stsDecoder
|
||||
}
|
||||
|
||||
func (a *authZMessageDecoder) afterEachFn(item request.HandlerListRunItem) bool {
|
||||
if err, ok := item.Request.Error.(awserr.Error); ok && err.Code() == "UnauthorizedOperation" {
|
||||
item.Request.Error = decodeAWSError(a.Decoder, err)
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/sts"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
)
|
||||
|
||||
type mockSTS struct {
|
||||
}
|
||||
|
||||
func (m *mockSTS) DecodeAuthorizationMessage(input *sts.DecodeAuthorizationMessageInput) (*sts.DecodeAuthorizationMessageOutput, error) {
|
||||
return &sts.DecodeAuthorizationMessageOutput{
|
||||
DecodedMessage: aws.String(`{
|
||||
"allowed": false,
|
||||
"explicitDeny": true,
|
||||
"matchedStatements": {}
|
||||
}`),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestErrorsParsing_RequestFailure(t *testing.T) {
|
||||
|
||||
ae := awserr.New("UnauthorizedOperation",
|
||||
`You are not authorized to perform this operation. Encoded authorization failure message: D9Q7oicjOMr9l2CC-NPP1FiZXK9Ijia1k-3l0siBFCcrK3oSuMFMkBIO5TNj0HdXE-WfwnAcdycFOohfKroNO6toPJEns8RFVfy_M_IjNGmrEFJ6E62pnmBW0OLrMsXxR9FQE4gB4gJzSM0AD6cV6S3FOfqYzWBRX-sQdOT4HryGkFNRoFBr9Xbp-tRwiadwkbdHdfnV9fbRkXmnwCdULml16NBSofC4ZPepLMKmIB5rKjwk-m179UUh2XA-J5no0si6XcRo5GbHQB5QfCIwSHL4vsro2wLZUd16-8OWKyr3tVlTbQe0ERZskqRqRQ5E28QuiBCVV6XstUyo-T4lBSr75Fgnyr3wCO-dS3b_5Ns3WzA2JD4E2AJOAStXIU8IH5YuKkAg7C-dJMuBMPpmKCBEXhNoHDwCyOo5PsV3xMlc0jSb0qYGpfst_TDDtejcZfn7NssUjxVq9qkdH-OXz2gPoQB-hX8ycmZCL5UZwKc3TCLUr7TGnudHjmnMrE9cUo-yTCWfyHPLprhiYhTCKW18EikJ0O1EKI3FJ_b4F19_jFBPARjSwQc7Ut6MNCVzrPdZGYSF6acj5gPaxdy9uSkVQwWXK7Pd5MFP7EBDE1_DgYbzodgwDO2PXeVFUbSLBHKWo_ebZS9ZX2nYPcGss_sYaly0ZVSIJXp7G58B5BoFVhvVH6jYnF9XiAOjMltuP_ycu1pQP1lki500RY3baLvfeYeAsB38XZHKEgWZzq7Fei-uh89q0cjJTmlVyrfRU3q6`,
|
||||
fmt.Errorf("You can't do it!!"))
|
||||
rf := awserr.NewRequestFailure(ae, 400, "abc-def-123-456")
|
||||
|
||||
result := decodeAWSError(&mockSTS{}, rf)
|
||||
if result == nil {
|
||||
t.Error("Expected resulting error")
|
||||
}
|
||||
if !strings.Contains(result.Error(), "Authorization failure message:") {
|
||||
t.Error("Expected authorization failure message")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorsParsing_NonAuthorizationFailure(t *testing.T) {
|
||||
|
||||
ae := awserr.New("BadRequest",
|
||||
`You did something wrong. Try again`,
|
||||
fmt.Errorf("Request was no good."))
|
||||
rf := awserr.NewRequestFailure(ae, 400, "abc-def-123-456")
|
||||
|
||||
result := decodeAWSError(&mockSTS{}, rf)
|
||||
if result == nil {
|
||||
t.Error("Expected resulting error")
|
||||
}
|
||||
if result != rf {
|
||||
t.Error("Expected original error to be returned unchanged")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorsParsing_NonAWSError(t *testing.T) {
|
||||
|
||||
err := fmt.Errorf("Random error occurred")
|
||||
|
||||
result := decodeAWSError(&mockSTS{}, err)
|
||||
if result == nil {
|
||||
t.Error("Expected resulting error")
|
||||
}
|
||||
if result != err {
|
||||
t.Error("Expected original error to be returned unchanged")
|
||||
}
|
||||
}
|
|
@ -121,6 +121,11 @@ each category, the available configuration keys are alphabetized.
|
|||
provider whose API is compatible with aws EC2. Specify another endpoint
|
||||
like this `https://ec2.custom.endpoint.com`.
|
||||
|
||||
- `decode_authorization_messages` (boolean) - Enable automatic decoding of any
|
||||
encoded authorization (error) messages using the `sts:DecodeAuthorizationMessage` API.
|
||||
Note: requires that the effective user/role have permissions to `sts:DecodeAuthorizationMessage`
|
||||
on resource `*`. Default `false`.
|
||||
|
||||
- `device_path` (string) - The path to the device where the root volume of the
|
||||
source AMI will be attached. This defaults to "" (empty string), which
|
||||
forces Packer to find an open device automatically.
|
||||
|
|
|
@ -151,6 +151,11 @@ builder.
|
|||
provider whose API is compatible with aws EC2. Specify another endpoint
|
||||
like this `https://ec2.custom.endpoint.com`.
|
||||
|
||||
- `decode_authorization_messages` (boolean) - Enable automatic decoding of any
|
||||
encoded authorization (error) messages using the `sts:DecodeAuthorizationMessage` API.
|
||||
Note: requires that the effective user/role have permissions to `sts:DecodeAuthorizationMessage`
|
||||
on resource `*`. Default `false`.
|
||||
|
||||
- `disable_stop_instance` (boolean) - Packer normally stops the build instance
|
||||
after all provisioners have run. For Windows instances, it is sometimes
|
||||
desirable to [run Sysprep](http://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ami-create-standard.html)
|
||||
|
|
|
@ -144,6 +144,11 @@ builder.
|
|||
provider whose API is compatible with aws EC2. Specify another endpoint
|
||||
like this `https://ec2.custom.endpoint.com`.
|
||||
|
||||
- `decode_authorization_messages` (boolean) - Enable automatic decoding of any
|
||||
encoded authorization (error) messages using the `sts:DecodeAuthorizationMessage` API.
|
||||
Note: requires that the effective user/role have permissions to `sts:DecodeAuthorizationMessage`
|
||||
on resource `*`. Default `false`.
|
||||
|
||||
- `disable_stop_instance` (boolean) - Packer normally stops the build instance
|
||||
after all provisioners have run. For Windows instances, it is sometimes
|
||||
desirable to [run Sysprep](http://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ami-create-standard.html)
|
||||
|
|
|
@ -137,6 +137,11 @@ builder.
|
|||
}
|
||||
```
|
||||
|
||||
- `decode_authorization_messages` (boolean) - Enable automatic decoding of any
|
||||
encoded authorization (error) messages using the `sts:DecodeAuthorizationMessage` API.
|
||||
Note: requires that the effective user/role have permissions to `sts:DecodeAuthorizationMessage`
|
||||
on resource `*`. Default `false`.
|
||||
|
||||
- `ebs_optimized` (boolean) - Mark instance as [EBS
|
||||
Optimized](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html).
|
||||
Default `false`.
|
||||
|
|
|
@ -189,6 +189,11 @@ builder.
|
|||
provider whose API is compatible with aws EC2. Specify another endpoint
|
||||
like this `https://ec2.custom.endpoint.com`.
|
||||
|
||||
- `decode_authorization_messages` (boolean) - Enable automatic decoding of any
|
||||
encoded authorization (error) messages using the `sts:DecodeAuthorizationMessage` API.
|
||||
Note: requires that the effective user/role have permissions to `sts:DecodeAuthorizationMessage`
|
||||
on resource `*`. Default `false`.
|
||||
|
||||
- `ebs_optimized` (boolean) - Mark instance as [EBS
|
||||
Optimized](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html).
|
||||
Default `false`.
|
||||
|
|
Loading…
Reference in New Issue