Merge pull request #8247 from b-b3rn4rd/master

New Feature: allow to specify  IAM policy for a temporary instance profile
This commit is contained in:
Megan Marsh 2019-10-22 09:33:23 -07:00 committed by GitHub
commit cdc3fdf926
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 34021 additions and 14 deletions

View File

@ -45,6 +45,15 @@ type VpcFilterOptions struct {
Filters map[*string]*string
}
type PolicyDocument struct {
Version string
Statement []struct {
Effect string
Action []string
Resource string
}
}
func (d *VpcFilterOptions) Empty() bool {
return len(d.Filters) == 0
}
@ -124,6 +133,25 @@ type RunConfig struct {
// profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
// to launch the EC2 instance with.
IamInstanceProfile string `mapstructure:"iam_instance_profile" required:"false"`
// Temporary IAM instance profile policy document
// If IamInstanceProfile is specified it will be used instead. Example:
//
// ```json
//{
// "Version": "2012-10-17",
// "Statement": [
// {
// "Action": [
// "logs:*"
// ],
// "Effect": "Allow",
// "Resource": "*"
// }
// ]
//}
// ```
//
TemporaryIamInstanceProfilePolicyDocument *PolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false"`
// Automatically terminate instances on
// shutdown in case Packer exits ungracefully. Possible values are stop and
// terminate. Defaults to stop.

View File

@ -0,0 +1,194 @@
package common
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"log"
"time"
"encoding/json"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
type StepIamInstanceProfile struct {
IamInstanceProfile string
TemporaryIamInstanceProfilePolicyDocument *PolicyDocument
createdInstanceProfileName string
createdRoleName string
createdPolicyName string
roleIsAttached bool
}
func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
iamsvc := state.Get("iam").(*iam.IAM)
ui := state.Get("ui").(packer.Ui)
state.Put("iamInstanceProfile", "")
if len(s.IamInstanceProfile) > 0 {
_, err := iamsvc.GetInstanceProfile(
&iam.GetInstanceProfileInput{
InstanceProfileName: aws.String(s.IamInstanceProfile),
},
)
if err != nil {
err := fmt.Errorf("Couldn't find specified instance profile: %s", err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
log.Printf("Using specified instance profile: %v", s.IamInstanceProfile)
state.Put("iamInstanceProfile", s.IamInstanceProfile)
return multistep.ActionContinue
}
if s.TemporaryIamInstanceProfilePolicyDocument != nil {
// Create the profile
profileName := fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
policy, err := json.Marshal(s.TemporaryIamInstanceProfilePolicyDocument)
if err != nil {
ui.Error(err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
ui.Say(fmt.Sprintf("Creating temporary instance profile for this instance: %s", profileName))
profileResp, err := iamsvc.CreateInstanceProfile(&iam.CreateInstanceProfileInput{
InstanceProfileName: aws.String(profileName),
})
if err != nil {
ui.Error(err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
s.createdInstanceProfileName = aws.StringValue(profileResp.InstanceProfile.InstanceProfileName)
log.Printf("[DEBUG] Waiting for temporary instance profile: %s", s.createdInstanceProfileName)
err = iamsvc.WaitUntilInstanceProfileExists(&iam.GetInstanceProfileInput{
InstanceProfileName: aws.String(s.createdInstanceProfileName),
})
if err == nil {
log.Printf("[DEBUG] Found instance profile %s", s.createdInstanceProfileName)
} else {
err := fmt.Errorf("Timed out waiting for instance profile %s: %s", s.createdInstanceProfileName, err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
ui.Say(fmt.Sprintf("Creating temporary role for this instance: %s", profileName))
roleResp, err := iamsvc.CreateRole(&iam.CreateRoleInput{
RoleName: aws.String(profileName),
Description: aws.String("Temporary role for Packer"),
AssumeRolePolicyDocument: aws.String("{\"Version\": \"2012-10-17\",\"Statement\": [{\"Effect\": \"Allow\",\"Principal\": {\"Service\": \"ec2.amazonaws.com\"},\"Action\": \"sts:AssumeRole\"}]}"),
})
if err != nil {
ui.Error(err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
s.createdRoleName = aws.StringValue(roleResp.Role.RoleName)
log.Printf("[DEBUG] Waiting for temporary role: %s", s.createdInstanceProfileName)
err = iamsvc.WaitUntilRoleExists(&iam.GetRoleInput{
RoleName: aws.String(s.createdRoleName),
})
if err == nil {
log.Printf("[DEBUG] Found temporary role %s", s.createdRoleName)
} else {
err := fmt.Errorf("Timed out waiting for temporary role %s: %s", s.createdRoleName, err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
ui.Say(fmt.Sprintf("Attaching policy to the temporary role: %s", profileName))
_, err = iamsvc.PutRolePolicy(&iam.PutRolePolicyInput{
RoleName: roleResp.Role.RoleName,
PolicyName: aws.String(profileName),
PolicyDocument: aws.String(string(policy)),
})
if err != nil {
ui.Error(err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
s.createdPolicyName = aws.StringValue(roleResp.Role.RoleName)
_, err = iamsvc.AddRoleToInstanceProfile(&iam.AddRoleToInstanceProfileInput{
RoleName: roleResp.Role.RoleName,
InstanceProfileName: profileResp.InstanceProfile.InstanceProfileName,
})
if err != nil {
ui.Error(err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
s.roleIsAttached = true
state.Put("iamInstanceProfile", aws.StringValue(profileResp.InstanceProfile.InstanceProfileName))
time.Sleep(5 * time.Second)
}
return multistep.ActionContinue
}
func (s *StepIamInstanceProfile) Cleanup(state multistep.StateBag) {
iamsvc := state.Get("iam").(*iam.IAM)
ui := state.Get("ui").(packer.Ui)
var err error
if s.roleIsAttached == true {
ui.Say("Detaching temporary role from instance profile...")
_, err := iamsvc.RemoveRoleFromInstanceProfile(&iam.RemoveRoleFromInstanceProfileInput{
InstanceProfileName: aws.String(s.createdInstanceProfileName),
RoleName: aws.String(s.createdRoleName),
})
if err != nil {
ui.Error(fmt.Sprintf(
"Error %s. Please delete the role manually: %s", err.Error(), s.createdRoleName))
}
}
if s.createdPolicyName != "" {
ui.Say("Removing policy from temporary role...")
iamsvc.DeleteRolePolicy(&iam.DeleteRolePolicyInput{
PolicyName: aws.String(s.createdPolicyName),
RoleName: aws.String(s.createdRoleName),
})
}
if s.createdRoleName != "" {
ui.Say("Deleting temporary role...")
_, err = iamsvc.DeleteRole(&iam.DeleteRoleInput{RoleName: &s.createdRoleName})
if err != nil {
ui.Error(fmt.Sprintf(
"Error %s. Please delete the role manually: %s", err.Error(), s.createdRoleName))
}
}
if s.createdInstanceProfileName != "" {
ui.Say("Deleting temporary instance profile...")
_, err = iamsvc.DeleteInstanceProfile(&iam.DeleteInstanceProfileInput{
InstanceProfileName: &s.createdInstanceProfileName})
if err != nil {
ui.Error(fmt.Sprintf(
"Error %s. Please delete the instance profile manually: %s", err.Error(), s.createdInstanceProfileName))
}
}
}

View File

@ -28,7 +28,6 @@ type StepRunSourceInstance struct {
EbsOptimized bool
EnableT2Unlimited bool
ExpectedRootDevice string
IamInstanceProfile string
InstanceInitiatedShutdownBehavior string
InstanceType string
IsRestricted bool
@ -45,6 +44,8 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
ec2conn := state.Get("ec2").(*ec2.EC2)
securityGroupIds := aws.StringSlice(state.Get("securityGroupIds").([]string))
iamInstanceProfile := aws.String(state.Get("iamInstanceProfile").(string))
ui := state.Get("ui").(packer.Ui)
userData := s.UserData
@ -110,7 +111,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
UserData: &userData,
MaxCount: aws.Int64(1),
MinCount: aws.Int64(1),
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile},
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: iamInstanceProfile},
BlockDeviceMappings: s.LaunchMappings.BuildEC2BlockDeviceMappings(),
Placement: &ec2.Placement{AvailabilityZone: &az},
EbsOptimized: &s.EbsOptimized,

View File

@ -31,7 +31,6 @@ type StepRunSpotInstance struct {
Comm *communicator.Config
EbsOptimized bool
ExpectedRootDevice string
IamInstanceProfile string
InstanceInitiatedShutdownBehavior string
InstanceType string
SourceAMI string
@ -69,12 +68,14 @@ func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string,
launchMappingRequests = append(launchMappingRequests, launchRequest)
}
iamInstanceProfile := aws.String(state.Get("iamInstanceProfile").(string))
// Create a launch template.
templateData := ec2.RequestLaunchTemplateData{
BlockDeviceMappings: launchMappingRequests,
DisableApiTermination: aws.Bool(false),
EbsOptimized: &s.EbsOptimized,
IamInstanceProfile: &ec2.LaunchTemplateIamInstanceProfileSpecificationRequest{Name: &s.IamInstanceProfile},
IamInstanceProfile: &ec2.LaunchTemplateIamInstanceProfileSpecificationRequest{Name: iamInstanceProfile},
ImageId: &s.SourceAMI,
InstanceMarketOptions: marketOptions,
Placement: &ec2.LaunchTemplatePlacementRequest{

View File

@ -2,6 +2,7 @@ package common
import (
"bytes"
"fmt"
"testing"
"time"
@ -73,6 +74,7 @@ func tStateSpot() multistep.StateBag {
})
state.Put("availability_zone", "us-east-1c")
state.Put("securityGroupIds", []string{"sg-0b8984db72f213dc3"})
state.Put("iamInstanceProfile", "packer-123")
state.Put("subnet_id", "subnet-077fde4e")
state.Put("source_image", "")
return state
@ -91,7 +93,6 @@ func getBasicStep() *StepRunSpotInstance {
},
EbsOptimized: false,
ExpectedRootDevice: "ebs",
IamInstanceProfile: "",
InstanceInitiatedShutdownBehavior: "stop",
InstanceType: "t2.micro",
SourceAMI: "",
@ -125,6 +126,10 @@ func TestCreateTemplateData(t *testing.T) {
t.Fatalf("Template should have contained a networkInterface object: recieved %#v", template.NetworkInterfaces)
}
if *template.IamInstanceProfile.Name != state.Get("iamInstanceProfile") {
t.Fatalf("Template should have contained a InstanceProfile name: recieved %#v", template.IamInstanceProfile.Name)
}
// Rerun, this time testing that we set security group IDs
state.Put("subnet_id", "")
template = stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state,
@ -132,4 +137,13 @@ func TestCreateTemplateData(t *testing.T) {
if template.NetworkInterfaces != nil {
t.Fatalf("Template shouldn't contain network interfaces object if subnet_id is unset.")
}
// Rerun, this time testing that instance doesn't have instance profile is iamInstanceProfile is unset
state.Put("iamInstanceProfile", "")
template = stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state,
&ec2.LaunchTemplateInstanceMarketOptionsRequest{})
fmt.Println(template.IamInstanceProfile)
if *template.IamInstanceProfile.Name != "" {
t.Fatalf("Template shouldn't contain instance profile if iamInstanceProfile is unset.")
}
}

View File

@ -12,6 +12,7 @@ import (
"fmt"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
@ -126,13 +127,14 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
ec2conn := ec2.New(session)
iam := iam.New(session)
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)
state.Put("config", &b.config)
state.Put("access_config", &b.config.AccessConfig)
state.Put("ami_config", &b.config.AMIConfig)
state.Put("ec2", ec2conn)
state.Put("iam", iam)
state.Put("awsSession", session)
state.Put("hook", hook)
state.Put("ui", ui)
@ -149,7 +151,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Debug: b.config.PackerDebug,
EbsOptimized: b.config.EbsOptimized,
ExpectedRootDevice: "ebs",
IamInstanceProfile: b.config.IamInstanceProfile,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
SourceAMI: b.config.SourceAmi,
@ -171,7 +172,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
EbsOptimized: b.config.EbsOptimized,
EnableT2Unlimited: b.config.EnableT2Unlimited,
ExpectedRootDevice: "ebs",
IamInstanceProfile: b.config.IamInstanceProfile,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
@ -217,6 +217,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
CommConfig: &b.config.RunConfig.Comm,
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
},
&awscommon.StepIamInstanceProfile{
IamInstanceProfile: b.config.IamInstanceProfile,
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
},
&awscommon.StepCleanupVolumes{
LaunchMappings: b.config.LaunchMappings,
},

View File

@ -8,6 +8,7 @@ import (
"context"
"errors"
"fmt"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/ec2"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
@ -164,7 +165,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
if err != nil {
return nil, err
}
ec2conn := ec2.New(session)
iam := iam.New(session)
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)
@ -172,6 +175,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state.Put("access_config", &b.config.AccessConfig)
state.Put("ami_config", &b.config.AMIConfig)
state.Put("ec2", ec2conn)
state.Put("iam", iam)
state.Put("awsSession", session)
state.Put("hook", hook)
state.Put("ui", ui)
@ -188,7 +192,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Debug: b.config.PackerDebug,
EbsOptimized: b.config.EbsOptimized,
ExpectedRootDevice: "ebs",
IamInstanceProfile: b.config.IamInstanceProfile,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
SourceAMI: b.config.SourceAmi,
@ -210,7 +213,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
EbsOptimized: b.config.EbsOptimized,
EnableT2Unlimited: b.config.EnableT2Unlimited,
ExpectedRootDevice: "ebs",
IamInstanceProfile: b.config.IamInstanceProfile,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
@ -258,6 +260,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
CommConfig: &b.config.RunConfig.Comm,
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
},
&awscommon.StepIamInstanceProfile{
IamInstanceProfile: b.config.IamInstanceProfile,
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
},
&awscommon.StepCleanupVolumes{
LaunchMappings: b.config.LaunchMappings.Common(),
},

View File

@ -9,6 +9,7 @@ import (
"fmt"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
@ -141,12 +142,14 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
return nil, err
}
ec2conn := ec2.New(session)
iam := iam.New(session)
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)
state.Put("config", &b.config)
state.Put("access_config", &b.config.AccessConfig)
state.Put("ec2", ec2conn)
state.Put("iam", iam)
state.Put("hook", hook)
state.Put("ui", ui)
@ -162,7 +165,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Debug: b.config.PackerDebug,
EbsOptimized: b.config.EbsOptimized,
ExpectedRootDevice: "ebs",
IamInstanceProfile: b.config.IamInstanceProfile,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
SourceAMI: b.config.SourceAmi,
@ -184,7 +186,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
EbsOptimized: b.config.EbsOptimized,
EnableT2Unlimited: b.config.EnableT2Unlimited,
ExpectedRootDevice: "ebs",
IamInstanceProfile: b.config.IamInstanceProfile,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
@ -224,6 +225,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
CommConfig: &b.config.RunConfig.Comm,
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
},
&awscommon.StepIamInstanceProfile{
IamInstanceProfile: b.config.IamInstanceProfile,
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
},
instanceStep,
&stepTagEBSVolumes{
VolumeMapping: b.config.VolumeMappings,

View File

@ -8,6 +8,7 @@ import (
"context"
"errors"
"fmt"
"github.com/aws/aws-sdk-go/service/iam"
"os"
"strings"
@ -229,6 +230,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
return nil, err
}
ec2conn := ec2.New(session)
iam := iam.New(session)
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)
@ -236,6 +238,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state.Put("access_config", &b.config.AccessConfig)
state.Put("ami_config", &b.config.AMIConfig)
state.Put("ec2", ec2conn)
state.Put("iam", iam)
state.Put("awsSession", session)
state.Put("hook", hook)
state.Put("ui", ui)
@ -251,7 +254,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Comm: &b.config.RunConfig.Comm,
Debug: b.config.PackerDebug,
EbsOptimized: b.config.EbsOptimized,
IamInstanceProfile: b.config.IamInstanceProfile,
InstanceType: b.config.InstanceType,
SourceAMI: b.config.SourceAmi,
SpotPrice: b.config.SpotPrice,
@ -270,7 +272,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Debug: b.config.PackerDebug,
EbsOptimized: b.config.EbsOptimized,
EnableT2Unlimited: b.config.EnableT2Unlimited,
IamInstanceProfile: b.config.IamInstanceProfile,
InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
SourceAMI: b.config.SourceAmi,
@ -313,6 +314,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
SecurityGroupIds: b.config.SecurityGroupIds,
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
},
&awscommon.StepIamInstanceProfile{
IamInstanceProfile: b.config.IamInstanceProfile,
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
},
instanceStep,
&awscommon.StepGetPassword{
Debug: b.config.PackerDebug,

33117
vendor/github.com/aws/aws-sdk-go/service/iam/api.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

80
vendor/github.com/aws/aws-sdk-go/service/iam/doc.go generated vendored Normal file
View File

@ -0,0 +1,80 @@
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
// Package iam provides the client and types for making API
// requests to AWS Identity and Access Management.
//
// AWS Identity and Access Management (IAM) is a web service that you can use
// to manage users and user permissions under your AWS account. This guide provides
// descriptions of IAM actions that you can call programmatically. For general
// information about IAM, see AWS Identity and Access Management (IAM) (http://aws.amazon.com/iam/).
// For the user guide for IAM, see Using IAM (https://docs.aws.amazon.com/IAM/latest/UserGuide/).
//
// AWS provides SDKs that consist of libraries and sample code for various programming
// languages and platforms (Java, Ruby, .NET, iOS, Android, etc.). The SDKs
// provide a convenient way to create programmatic access to IAM and AWS. For
// example, the SDKs take care of tasks such as cryptographically signing requests
// (see below), managing errors, and retrying requests automatically. For information
// about the AWS SDKs, including how to download and install them, see the Tools
// for Amazon Web Services (http://aws.amazon.com/tools/) page.
//
// We recommend that you use the AWS SDKs to make programmatic API calls to
// IAM. However, you can also use the IAM Query API to make direct calls to
// the IAM web service. To learn more about the IAM Query API, see Making Query
// Requests (https://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_UsingQueryAPI.html)
// in the Using IAM guide. IAM supports GET and POST requests for all actions.
// That is, the API does not require you to use GET for some actions and POST
// for others. However, GET requests are subject to the limitation size of a
// URL. Therefore, for operations that require larger sizes, use a POST request.
//
// Signing Requests
//
// Requests must be signed using an access key ID and a secret access key. We
// strongly recommend that you do not use your AWS account access key ID and
// secret access key for everyday work with IAM. You can use the access key
// ID and secret access key for an IAM user or you can use the AWS Security
// Token Service to generate temporary security credentials and use those to
// sign requests.
//
// To sign requests, we recommend that you use Signature Version 4 (https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html).
// If you have an existing application that uses Signature Version 2, you do
// not have to update it to use Signature Version 4. However, some operations
// now require Signature Version 4. The documentation for operations that require
// version 4 indicate this requirement.
//
// Additional Resources
//
// For more information, see the following:
//
// * AWS Security Credentials (https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html).
// This topic provides general information about the types of credentials
// used for accessing AWS.
//
// * IAM Best Practices (https://docs.aws.amazon.com/IAM/latest/UserGuide/IAMBestPractices.html).
// This topic presents a list of suggestions for using the IAM service to
// help secure your AWS resources.
//
// * Signing AWS API Requests (https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html).
// This set of topics walk you through the process of signing a request using
// an access key ID and secret access key.
//
// See https://docs.aws.amazon.com/goto/WebAPI/iam-2010-05-08 for more information on this service.
//
// See iam package documentation for more information.
// https://docs.aws.amazon.com/sdk-for-go/api/service/iam/
//
// Using the Client
//
// To contact AWS Identity and Access Management with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//
// See the SDK's documentation for more information on how to use the SDK.
// https://docs.aws.amazon.com/sdk-for-go/api/
//
// See aws.Config documentation for more information on configuring SDK clients.
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
//
// See the AWS Identity and Access Management client IAM for more
// information on creating client for this service.
// https://docs.aws.amazon.com/sdk-for-go/api/service/iam/#New
package iam

200
vendor/github.com/aws/aws-sdk-go/service/iam/errors.go generated vendored Normal file
View File

@ -0,0 +1,200 @@
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package iam
const (
// ErrCodeConcurrentModificationException for service response error code
// "ConcurrentModification".
//
// The request was rejected because multiple requests to change this object
// were submitted simultaneously. Wait a few minutes and submit your request
// again.
ErrCodeConcurrentModificationException = "ConcurrentModification"
// ErrCodeCredentialReportExpiredException for service response error code
// "ReportExpired".
//
// The request was rejected because the most recent credential report has expired.
// To generate a new credential report, use GenerateCredentialReport. For more
// information about credential report expiration, see Getting Credential Reports
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/credential-reports.html)
// in the IAM User Guide.
ErrCodeCredentialReportExpiredException = "ReportExpired"
// ErrCodeCredentialReportNotPresentException for service response error code
// "ReportNotPresent".
//
// The request was rejected because the credential report does not exist. To
// generate a credential report, use GenerateCredentialReport.
ErrCodeCredentialReportNotPresentException = "ReportNotPresent"
// ErrCodeCredentialReportNotReadyException for service response error code
// "ReportInProgress".
//
// The request was rejected because the credential report is still being generated.
ErrCodeCredentialReportNotReadyException = "ReportInProgress"
// ErrCodeDeleteConflictException for service response error code
// "DeleteConflict".
//
// The request was rejected because it attempted to delete a resource that has
// attached subordinate entities. The error message describes these entities.
ErrCodeDeleteConflictException = "DeleteConflict"
// ErrCodeDuplicateCertificateException for service response error code
// "DuplicateCertificate".
//
// The request was rejected because the same certificate is associated with
// an IAM user in the account.
ErrCodeDuplicateCertificateException = "DuplicateCertificate"
// ErrCodeDuplicateSSHPublicKeyException for service response error code
// "DuplicateSSHPublicKey".
//
// The request was rejected because the SSH public key is already associated
// with the specified IAM user.
ErrCodeDuplicateSSHPublicKeyException = "DuplicateSSHPublicKey"
// ErrCodeEntityAlreadyExistsException for service response error code
// "EntityAlreadyExists".
//
// The request was rejected because it attempted to create a resource that already
// exists.
ErrCodeEntityAlreadyExistsException = "EntityAlreadyExists"
// ErrCodeEntityTemporarilyUnmodifiableException for service response error code
// "EntityTemporarilyUnmodifiable".
//
// The request was rejected because it referenced an entity that is temporarily
// unmodifiable, such as a user name that was deleted and then recreated. The
// error indicates that the request is likely to succeed if you try again after
// waiting several minutes. The error message describes the entity.
ErrCodeEntityTemporarilyUnmodifiableException = "EntityTemporarilyUnmodifiable"
// ErrCodeInvalidAuthenticationCodeException for service response error code
// "InvalidAuthenticationCode".
//
// The request was rejected because the authentication code was not recognized.
// The error message describes the specific error.
ErrCodeInvalidAuthenticationCodeException = "InvalidAuthenticationCode"
// ErrCodeInvalidCertificateException for service response error code
// "InvalidCertificate".
//
// The request was rejected because the certificate is invalid.
ErrCodeInvalidCertificateException = "InvalidCertificate"
// ErrCodeInvalidInputException for service response error code
// "InvalidInput".
//
// The request was rejected because an invalid or out-of-range value was supplied
// for an input parameter.
ErrCodeInvalidInputException = "InvalidInput"
// ErrCodeInvalidPublicKeyException for service response error code
// "InvalidPublicKey".
//
// The request was rejected because the public key is malformed or otherwise
// invalid.
ErrCodeInvalidPublicKeyException = "InvalidPublicKey"
// ErrCodeInvalidUserTypeException for service response error code
// "InvalidUserType".
//
// The request was rejected because the type of user for the transaction was
// incorrect.
ErrCodeInvalidUserTypeException = "InvalidUserType"
// ErrCodeKeyPairMismatchException for service response error code
// "KeyPairMismatch".
//
// The request was rejected because the public key certificate and the private
// key do not match.
ErrCodeKeyPairMismatchException = "KeyPairMismatch"
// ErrCodeLimitExceededException for service response error code
// "LimitExceeded".
//
// The request was rejected because it attempted to create resources beyond
// the current AWS account limits. The error message describes the limit exceeded.
ErrCodeLimitExceededException = "LimitExceeded"
// ErrCodeMalformedCertificateException for service response error code
// "MalformedCertificate".
//
// The request was rejected because the certificate was malformed or expired.
// The error message describes the specific error.
ErrCodeMalformedCertificateException = "MalformedCertificate"
// ErrCodeMalformedPolicyDocumentException for service response error code
// "MalformedPolicyDocument".
//
// The request was rejected because the policy document was malformed. The error
// message describes the specific error.
ErrCodeMalformedPolicyDocumentException = "MalformedPolicyDocument"
// ErrCodeNoSuchEntityException for service response error code
// "NoSuchEntity".
//
// The request was rejected because it referenced a resource entity that does
// not exist. The error message describes the resource.
ErrCodeNoSuchEntityException = "NoSuchEntity"
// ErrCodePasswordPolicyViolationException for service response error code
// "PasswordPolicyViolation".
//
// The request was rejected because the provided password did not meet the requirements
// imposed by the account password policy.
ErrCodePasswordPolicyViolationException = "PasswordPolicyViolation"
// ErrCodePolicyEvaluationException for service response error code
// "PolicyEvaluation".
//
// The request failed because a provided policy could not be successfully evaluated.
// An additional detailed message indicates the source of the failure.
ErrCodePolicyEvaluationException = "PolicyEvaluation"
// ErrCodePolicyNotAttachableException for service response error code
// "PolicyNotAttachable".
//
// The request failed because AWS service role policies can only be attached
// to the service-linked role for that service.
ErrCodePolicyNotAttachableException = "PolicyNotAttachable"
// ErrCodeReportGenerationLimitExceededException for service response error code
// "ReportGenerationLimitExceeded".
//
// The request failed because the maximum number of concurrent requests for
// this account are already running.
ErrCodeReportGenerationLimitExceededException = "ReportGenerationLimitExceeded"
// ErrCodeServiceFailureException for service response error code
// "ServiceFailure".
//
// The request processing has failed because of an unknown error, exception
// or failure.
ErrCodeServiceFailureException = "ServiceFailure"
// ErrCodeServiceNotSupportedException for service response error code
// "NotSupportedService".
//
// The specified service does not support service-specific credentials.
ErrCodeServiceNotSupportedException = "NotSupportedService"
// ErrCodeUnmodifiableEntityException for service response error code
// "UnmodifiableEntity".
//
// The request was rejected because only the service that depends on the service-linked
// role can modify or delete the role on your behalf. The error message includes
// the name of the service that depends on this service-linked role. You must
// request the change through that service.
ErrCodeUnmodifiableEntityException = "UnmodifiableEntity"
// ErrCodeUnrecognizedPublicKeyEncodingException for service response error code
// "UnrecognizedPublicKeyEncoding".
//
// The request was rejected because the public key encoding format is unsupported
// or unrecognized.
ErrCodeUnrecognizedPublicKeyEncodingException = "UnrecognizedPublicKeyEncoding"
)

View File

@ -0,0 +1,95 @@
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package iam
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/aws/aws-sdk-go/private/protocol/query"
)
// IAM provides the API operation methods for making requests to
// AWS Identity and Access Management. See this package's package overview docs
// for details on the service.
//
// IAM methods are safe to use concurrently. It is not safe to
// modify mutate any of the struct's properties though.
type IAM struct {
*client.Client
}
// Used for custom client initialization logic
var initClient func(*client.Client)
// Used for custom request initialization logic
var initRequest func(*request.Request)
// Service information constants
const (
ServiceName = "iam" // Name of service.
EndpointsID = ServiceName // ID to lookup a service endpoint with.
ServiceID = "IAM" // ServiceID is a unique identifer of a specific service.
)
// New creates a new instance of the IAM client with a session.
// If additional configuration is needed for the client instance use the optional
// aws.Config parameter to add your extra config.
//
// Example:
// // Create a IAM client from just a session.
// svc := iam.New(mySession)
//
// // Create a IAM client with additional configuration
// svc := iam.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
func New(p client.ConfigProvider, cfgs ...*aws.Config) *IAM {
c := p.ClientConfig(EndpointsID, cfgs...)
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
}
// newClient creates, initializes and returns a new service client instance.
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *IAM {
svc := &IAM{
Client: client.New(
cfg,
metadata.ClientInfo{
ServiceName: ServiceName,
ServiceID: ServiceID,
SigningName: signingName,
SigningRegion: signingRegion,
Endpoint: endpoint,
APIVersion: "2010-05-08",
},
handlers,
),
}
// Handlers
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
svc.Handlers.Build.PushBackNamed(query.BuildHandler)
svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler)
svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler)
svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler)
// Run custom client initialization if present
if initClient != nil {
initClient(svc.Client)
}
return svc
}
// newRequest creates a new request for a IAM operation and runs any
// custom request initialization.
func (c *IAM) newRequest(op *request.Operation, params, data interface{}) *request.Request {
req := c.NewRequest(op, params, data)
// Run custom request initialization if present
if initRequest != nil {
initRequest(req)
}
return req
}

214
vendor/github.com/aws/aws-sdk-go/service/iam/waiters.go generated vendored Normal file
View File

@ -0,0 +1,214 @@
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package iam
import (
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
)
// WaitUntilInstanceProfileExists uses the IAM API operation
// GetInstanceProfile to wait for a condition to be met before returning.
// If the condition is not met within the max attempt window, an error will
// be returned.
func (c *IAM) WaitUntilInstanceProfileExists(input *GetInstanceProfileInput) error {
return c.WaitUntilInstanceProfileExistsWithContext(aws.BackgroundContext(), input)
}
// WaitUntilInstanceProfileExistsWithContext is an extended version of WaitUntilInstanceProfileExists.
// With the support for passing in a context and options to configure the
// Waiter and the underlying request options.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *IAM) WaitUntilInstanceProfileExistsWithContext(ctx aws.Context, input *GetInstanceProfileInput, opts ...request.WaiterOption) error {
w := request.Waiter{
Name: "WaitUntilInstanceProfileExists",
MaxAttempts: 40,
Delay: request.ConstantWaiterDelay(1 * time.Second),
Acceptors: []request.WaiterAcceptor{
{
State: request.SuccessWaiterState,
Matcher: request.StatusWaiterMatch,
Expected: 200,
},
{
State: request.RetryWaiterState,
Matcher: request.StatusWaiterMatch,
Expected: 404,
},
},
Logger: c.Config.Logger,
NewRequest: func(opts []request.Option) (*request.Request, error) {
var inCpy *GetInstanceProfileInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.GetInstanceProfileRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
w.ApplyOptions(opts...)
return w.WaitWithContext(ctx)
}
// WaitUntilPolicyExists uses the IAM API operation
// GetPolicy to wait for a condition to be met before returning.
// If the condition is not met within the max attempt window, an error will
// be returned.
func (c *IAM) WaitUntilPolicyExists(input *GetPolicyInput) error {
return c.WaitUntilPolicyExistsWithContext(aws.BackgroundContext(), input)
}
// WaitUntilPolicyExistsWithContext is an extended version of WaitUntilPolicyExists.
// With the support for passing in a context and options to configure the
// Waiter and the underlying request options.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *IAM) WaitUntilPolicyExistsWithContext(ctx aws.Context, input *GetPolicyInput, opts ...request.WaiterOption) error {
w := request.Waiter{
Name: "WaitUntilPolicyExists",
MaxAttempts: 20,
Delay: request.ConstantWaiterDelay(1 * time.Second),
Acceptors: []request.WaiterAcceptor{
{
State: request.SuccessWaiterState,
Matcher: request.StatusWaiterMatch,
Expected: 200,
},
{
State: request.RetryWaiterState,
Matcher: request.ErrorWaiterMatch,
Expected: "NoSuchEntity",
},
},
Logger: c.Config.Logger,
NewRequest: func(opts []request.Option) (*request.Request, error) {
var inCpy *GetPolicyInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.GetPolicyRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
w.ApplyOptions(opts...)
return w.WaitWithContext(ctx)
}
// WaitUntilRoleExists uses the IAM API operation
// GetRole to wait for a condition to be met before returning.
// If the condition is not met within the max attempt window, an error will
// be returned.
func (c *IAM) WaitUntilRoleExists(input *GetRoleInput) error {
return c.WaitUntilRoleExistsWithContext(aws.BackgroundContext(), input)
}
// WaitUntilRoleExistsWithContext is an extended version of WaitUntilRoleExists.
// With the support for passing in a context and options to configure the
// Waiter and the underlying request options.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *IAM) WaitUntilRoleExistsWithContext(ctx aws.Context, input *GetRoleInput, opts ...request.WaiterOption) error {
w := request.Waiter{
Name: "WaitUntilRoleExists",
MaxAttempts: 20,
Delay: request.ConstantWaiterDelay(1 * time.Second),
Acceptors: []request.WaiterAcceptor{
{
State: request.SuccessWaiterState,
Matcher: request.StatusWaiterMatch,
Expected: 200,
},
{
State: request.RetryWaiterState,
Matcher: request.ErrorWaiterMatch,
Expected: "NoSuchEntity",
},
},
Logger: c.Config.Logger,
NewRequest: func(opts []request.Option) (*request.Request, error) {
var inCpy *GetRoleInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.GetRoleRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
w.ApplyOptions(opts...)
return w.WaitWithContext(ctx)
}
// WaitUntilUserExists uses the IAM API operation
// GetUser to wait for a condition to be met before returning.
// If the condition is not met within the max attempt window, an error will
// be returned.
func (c *IAM) WaitUntilUserExists(input *GetUserInput) error {
return c.WaitUntilUserExistsWithContext(aws.BackgroundContext(), input)
}
// WaitUntilUserExistsWithContext is an extended version of WaitUntilUserExists.
// With the support for passing in a context and options to configure the
// Waiter and the underlying request options.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *IAM) WaitUntilUserExistsWithContext(ctx aws.Context, input *GetUserInput, opts ...request.WaiterOption) error {
w := request.Waiter{
Name: "WaitUntilUserExists",
MaxAttempts: 20,
Delay: request.ConstantWaiterDelay(1 * time.Second),
Acceptors: []request.WaiterAcceptor{
{
State: request.SuccessWaiterState,
Matcher: request.StatusWaiterMatch,
Expected: 200,
},
{
State: request.RetryWaiterState,
Matcher: request.ErrorWaiterMatch,
Expected: "NoSuchEntity",
},
},
Logger: c.Config.Logger,
NewRequest: func(opts []request.Option) (*request.Request, error) {
var inCpy *GetUserInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.GetUserRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
w.ApplyOptions(opts...)
return w.WaitWithContext(ctx)
}

1
vendor/modules.txt vendored
View File

@ -136,6 +136,7 @@ github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil
github.com/aws/aws-sdk-go/service/ec2
github.com/aws/aws-sdk-go/service/ec2/ec2iface
github.com/aws/aws-sdk-go/service/ecr
github.com/aws/aws-sdk-go/service/iam
github.com/aws/aws-sdk-go/service/s3
github.com/aws/aws-sdk-go/service/s3/s3iface
github.com/aws/aws-sdk-go/service/s3/s3manager

View File

@ -209,6 +209,30 @@ work, but specifics will depend on your use-case.
}
```
In case when you're creating a temporary instance profile you will require to have following
IAM policies.
``` json
{
"Sid": "PackerIAMCreateRole",
"Effect": "Allow",
"Action": [
"iam:PassRole",
"iam:CreateInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:GetRole",
"iam:GetInstanceProfile",
"iam:DeleteRolePolicy",
"iam:RemoveRoleFromInstanceProfile",
"iam:CreateRole",
"iam:DeleteRole",
"iam:PutRolePolicy",
"iam:AddRoleToInstanceProfile"
],
"Resource": "*"
}
```
### Checking that system time is current
Amazon uses the current time as part of the [request signing

View File

@ -64,6 +64,24 @@
profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
to launch the EC2 instance with.
- `temporary_iam_instance_profile_policy_document` (\*PolicyDocument) - Temporary IAM instance profile policy document
If IamInstanceProfile is specified it will be used instead. Example:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
```
- `shutdown_behavior` (string) - Automatically terminate instances on
shutdown in case Packer exits ungracefully. Possible values are stop and
terminate. Defaults to stop.