github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/builtin/providers/aws/resource_aws_iam_user_login_profile_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"testing"
     7  	"time"
     8  
     9  	"regexp"
    10  
    11  	"github.com/aws/aws-sdk-go/aws"
    12  	"github.com/aws/aws-sdk-go/aws/awserr"
    13  	"github.com/aws/aws-sdk-go/aws/credentials"
    14  	"github.com/aws/aws-sdk-go/aws/session"
    15  	"github.com/aws/aws-sdk-go/service/iam"
    16  	"github.com/hashicorp/terraform/helper/acctest"
    17  	"github.com/hashicorp/terraform/helper/resource"
    18  	"github.com/hashicorp/terraform/terraform"
    19  	"github.com/hashicorp/vault/helper/pgpkeys"
    20  )
    21  
    22  func TestAccAWSUserLoginProfile_basic(t *testing.T) {
    23  	var conf iam.GetLoginProfileOutput
    24  
    25  	username := fmt.Sprintf("test-user-%d", acctest.RandInt())
    26  
    27  	resource.Test(t, resource.TestCase{
    28  		PreCheck:     func() { testAccPreCheck(t) },
    29  		Providers:    testAccProviders,
    30  		CheckDestroy: testAccCheckAWSUserLoginProfileDestroy,
    31  		Steps: []resource.TestStep{
    32  			{
    33  				Config: testAccAWSUserLoginProfileConfig(username, "/", testPubKey1),
    34  				Check: resource.ComposeTestCheckFunc(
    35  					testAccCheckAWSUserLoginProfileExists("aws_iam_user_login_profile.user", &conf),
    36  					testDecryptPasswordAndTest("aws_iam_user_login_profile.user", "aws_iam_access_key.user", testPrivKey1),
    37  				),
    38  			},
    39  		},
    40  	})
    41  }
    42  
    43  func TestAccAWSUserLoginProfile_keybase(t *testing.T) {
    44  	var conf iam.GetLoginProfileOutput
    45  
    46  	username := fmt.Sprintf("test-user-%d", acctest.RandInt())
    47  
    48  	resource.Test(t, resource.TestCase{
    49  		PreCheck:     func() { testAccPreCheck(t) },
    50  		Providers:    testAccProviders,
    51  		CheckDestroy: testAccCheckAWSUserLoginProfileDestroy,
    52  		Steps: []resource.TestStep{
    53  			{
    54  				Config: testAccAWSUserLoginProfileConfig(username, "/", "keybase:terraformacctest"),
    55  				Check: resource.ComposeTestCheckFunc(
    56  					testAccCheckAWSUserLoginProfileExists("aws_iam_user_login_profile.user", &conf),
    57  					resource.TestCheckResourceAttrSet("aws_iam_user_login_profile.user", "encrypted_password"),
    58  					resource.TestCheckResourceAttrSet("aws_iam_user_login_profile.user", "key_fingerprint"),
    59  				),
    60  			},
    61  		},
    62  	})
    63  }
    64  
    65  func TestAccAWSUserLoginProfile_keybaseDoesntExist(t *testing.T) {
    66  	username := fmt.Sprintf("test-user-%d", acctest.RandInt())
    67  
    68  	resource.Test(t, resource.TestCase{
    69  		PreCheck:     func() { testAccPreCheck(t) },
    70  		Providers:    testAccProviders,
    71  		CheckDestroy: testAccCheckAWSUserLoginProfileDestroy,
    72  		Steps: []resource.TestStep{
    73  			{
    74  				// We own this account but it doesn't have any key associated with it
    75  				Config:      testAccAWSUserLoginProfileConfig(username, "/", "keybase:terraform_nope"),
    76  				ExpectError: regexp.MustCompile(`Error retrieving Public Key`),
    77  			},
    78  		},
    79  	})
    80  }
    81  
    82  func TestAccAWSUserLoginProfile_notAKey(t *testing.T) {
    83  	username := fmt.Sprintf("test-user-%d", acctest.RandInt())
    84  
    85  	resource.Test(t, resource.TestCase{
    86  		PreCheck:     func() { testAccPreCheck(t) },
    87  		Providers:    testAccProviders,
    88  		CheckDestroy: testAccCheckAWSUserLoginProfileDestroy,
    89  		Steps: []resource.TestStep{
    90  			{
    91  				// We own this account but it doesn't have any key associated with it
    92  				Config:      testAccAWSUserLoginProfileConfig(username, "/", "lolimnotakey"),
    93  				ExpectError: regexp.MustCompile(`Error encrypting Password`),
    94  			},
    95  		},
    96  	})
    97  }
    98  
    99  func testAccCheckAWSUserLoginProfileDestroy(s *terraform.State) error {
   100  	iamconn := testAccProvider.Meta().(*AWSClient).iamconn
   101  
   102  	for _, rs := range s.RootModule().Resources {
   103  		if rs.Type != "aws_iam_user_login_profile" {
   104  			continue
   105  		}
   106  
   107  		// Try to get user
   108  		_, err := iamconn.GetLoginProfile(&iam.GetLoginProfileInput{
   109  			UserName: aws.String(rs.Primary.ID),
   110  		})
   111  		if err == nil {
   112  			return fmt.Errorf("still exists.")
   113  		}
   114  
   115  		// Verify the error is what we want
   116  		ec2err, ok := err.(awserr.Error)
   117  		if !ok {
   118  			return err
   119  		}
   120  		if ec2err.Code() != "NoSuchEntity" {
   121  			return err
   122  		}
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  func testDecryptPasswordAndTest(nProfile, nAccessKey, key string) resource.TestCheckFunc {
   129  	return func(s *terraform.State) error {
   130  		profileResource, ok := s.RootModule().Resources[nProfile]
   131  		if !ok {
   132  			return fmt.Errorf("Not found: %s", nProfile)
   133  		}
   134  
   135  		password, ok := profileResource.Primary.Attributes["encrypted_password"]
   136  		if !ok {
   137  			return errors.New("No password in state")
   138  		}
   139  
   140  		accessKeyResource, ok := s.RootModule().Resources[nAccessKey]
   141  		if !ok {
   142  			return fmt.Errorf("Not found: %s", nAccessKey)
   143  		}
   144  
   145  		accessKeyId := accessKeyResource.Primary.ID
   146  		secretAccessKey, ok := accessKeyResource.Primary.Attributes["secret"]
   147  		if !ok {
   148  			return errors.New("No secret access key in state")
   149  		}
   150  
   151  		decryptedPassword, err := pgpkeys.DecryptBytes(password, key)
   152  		if err != nil {
   153  			return fmt.Errorf("Error decrypting password: %s", err)
   154  		}
   155  
   156  		iamAsCreatedUserSession := session.New(&aws.Config{
   157  			Region:      aws.String("us-west-2"),
   158  			Credentials: credentials.NewStaticCredentials(accessKeyId, secretAccessKey, ""),
   159  		})
   160  		_, err = iamAsCreatedUserSession.Config.Credentials.Get()
   161  		if err != nil {
   162  			return fmt.Errorf("Error getting session credentials: %s", err)
   163  		}
   164  
   165  		return resource.Retry(2*time.Minute, func() *resource.RetryError {
   166  			iamAsCreatedUser := iam.New(iamAsCreatedUserSession)
   167  			_, err = iamAsCreatedUser.ChangePassword(&iam.ChangePasswordInput{
   168  				OldPassword: aws.String(decryptedPassword.String()),
   169  				NewPassword: aws.String(generatePassword(20)),
   170  			})
   171  			if err != nil {
   172  				if awserr, ok := err.(awserr.Error); ok && awserr.Code() == "InvalidClientTokenId" {
   173  					return resource.RetryableError(err)
   174  				}
   175  
   176  				return resource.NonRetryableError(fmt.Errorf("Error changing decrypted password: %s", err))
   177  			}
   178  
   179  			return nil
   180  		})
   181  	}
   182  }
   183  
   184  func testAccCheckAWSUserLoginProfileExists(n string, res *iam.GetLoginProfileOutput) resource.TestCheckFunc {
   185  	return func(s *terraform.State) error {
   186  		rs, ok := s.RootModule().Resources[n]
   187  		if !ok {
   188  			return fmt.Errorf("Not found: %s", n)
   189  		}
   190  
   191  		if rs.Primary.ID == "" {
   192  			return errors.New("No UserName is set")
   193  		}
   194  
   195  		iamconn := testAccProvider.Meta().(*AWSClient).iamconn
   196  		resp, err := iamconn.GetLoginProfile(&iam.GetLoginProfileInput{
   197  			UserName: aws.String(rs.Primary.ID),
   198  		})
   199  		if err != nil {
   200  			return err
   201  		}
   202  
   203  		*res = *resp
   204  
   205  		return nil
   206  	}
   207  }
   208  
   209  func testAccAWSUserLoginProfileConfig(r, p, key string) string {
   210  	return fmt.Sprintf(`
   211  resource "aws_iam_user" "user" {
   212  	name = "%s"
   213  	path = "%s"
   214  	force_destroy = true
   215  }
   216  
   217  data "aws_caller_identity" "current" {}
   218  
   219  data "aws_iam_policy_document" "user" {
   220  	statement {
   221  		effect = "Allow"
   222  		actions = ["iam:GetAccountPasswordPolicy"]
   223  		resources = ["*"]
   224  	}
   225  	statement {
   226  		effect = "Allow"
   227  		actions = ["iam:ChangePassword"]
   228  		resources = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/&{aws:username}"]
   229  	}
   230  }
   231  
   232  resource "aws_iam_user_policy" "user" {
   233  	name = "AllowChangeOwnPassword"
   234  	user = "${aws_iam_user.user.name}"
   235  	policy = "${data.aws_iam_policy_document.user.json}"
   236  }
   237  
   238  resource "aws_iam_access_key" "user" {
   239  	user = "${aws_iam_user.user.name}"
   240  }
   241  
   242  resource "aws_iam_user_login_profile" "user" {
   243          user = "${aws_iam_user.user.name}"
   244          pgp_key = <<EOF
   245  %sEOF
   246  }
   247  `, r, p, key)
   248  }
   249  
   250  const testPubKey1 = `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
   275  OIu60YPNE4+h7u2CfYyFPu3AlUaGNMBlvy6PEpU=`
   276  
   277  const testPrivKey1 = `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
   325  7u2CfYyFPu3AlUaGNMBlvy6PEpU=`