Skip to content

Commit

Permalink
Merge pull request #6727 from AMeng/cleanup-iam-ssh
Browse files Browse the repository at this point in the history
Add ability to import aws_iam_user_ssh_key
  • Loading branch information
bflad authored Dec 7, 2018
2 parents e1bead7 + fd9164f commit d64d95f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 4 deletions.
49 changes: 48 additions & 1 deletion aws/resource_aws_iam_user_ssh_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aws
import (
"fmt"
"log"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
Expand All @@ -18,6 +19,9 @@ func resourceAwsIamUserSshKey() *schema.Resource {
Read: resourceAwsIamUserSshKeyRead,
Update: resourceAwsIamUserSshKeyUpdate,
Delete: resourceAwsIamUserSshKeyDelete,
Importer: &schema.ResourceImporter{
State: resourceAwsIamUserSshKeyImport,
},

Schema: map[string]*schema.Schema{
"ssh_public_key_id": {
Expand All @@ -37,6 +41,13 @@ func resourceAwsIamUserSshKey() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if d.Get("encoding").(string) == "SSH" {
old = cleanSshKey(old)
new = cleanSshKey(new)
}
return strings.Trim(old, "\n") == strings.Trim(new, "\n")
},
},

"encoding": {
Expand Down Expand Up @@ -82,10 +93,11 @@ func resourceAwsIamUserSshKeyCreate(d *schema.ResourceData, meta interface{}) er
func resourceAwsIamUserSshKeyRead(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
username := d.Get("username").(string)
encoding := d.Get("encoding").(string)
request := &iam.GetSSHPublicKeyInput{
UserName: aws.String(username),
SSHPublicKeyId: aws.String(d.Id()),
Encoding: aws.String(d.Get("encoding").(string)),
Encoding: aws.String(encoding),
}

getResp, err := iamconn.GetSSHPublicKey(request)
Expand All @@ -98,9 +110,15 @@ func resourceAwsIamUserSshKeyRead(d *schema.ResourceData, meta interface{}) erro
return fmt.Errorf("Error reading IAM User SSH Key %s: %s", d.Id(), err)
}

publicKey := *getResp.SSHPublicKey.SSHPublicKeyBody
if encoding == "SSH" {
publicKey = cleanSshKey(publicKey)
}

d.Set("fingerprint", getResp.SSHPublicKey.Fingerprint)
d.Set("status", getResp.SSHPublicKey.Status)
d.Set("ssh_public_key_id", getResp.SSHPublicKey.SSHPublicKeyId)
d.Set("public_key", publicKey)
return nil
}

Expand Down Expand Up @@ -142,3 +160,32 @@ func resourceAwsIamUserSshKeyDelete(d *schema.ResourceData, meta interface{}) er
}
return nil
}

func resourceAwsIamUserSshKeyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
idParts := strings.SplitN(d.Id(), ":", 3)

if len(idParts) != 3 || idParts[0] == "" || idParts[1] == "" || idParts[2] == "" {
return nil, fmt.Errorf("unexpected format of ID (%q), UserName:SSHPublicKeyId:Encoding", d.Id())
}

username := idParts[0]
sshPublicKeyId := idParts[1]
encoding := idParts[2]

d.Set("username", username)
d.Set("ssh_public_key_id", sshPublicKeyId)
d.Set("encoding", encoding)
d.SetId(sshPublicKeyId)

return []*schema.ResourceData{d}, nil
}

func cleanSshKey(key string) string {
// Remove comments from SSH Keys
// Comments are anything after "ssh-rsa XXXX" where XXXX is the key.
parts := strings.Split(key, " ")
if len(parts) > 2 {
parts = parts[0:2]
}
return strings.Join(parts, " ")
}
45 changes: 42 additions & 3 deletions aws/resource_aws_iam_user_ssh_key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func TestAccAWSUserSSHKey_basic(t *testing.T) {

ri := acctest.RandInt()
config := fmt.Sprintf(testAccAWSSSHKeyConfig_sshEncoding, ri)
resourceName := "aws_iam_user_ssh_key.user"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Expand All @@ -26,9 +27,15 @@ func TestAccAWSUserSSHKey_basic(t *testing.T) {
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSUserSSHKeyExists("aws_iam_user_ssh_key.user", "Inactive", &conf),
testAccCheckAWSUserSSHKeyExists(resourceName, "Inactive", &conf),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateIdFunc: testAccAWSUserSSHKeyImportStateIdFunc(resourceName),
ImportStateVerify: true,
},
},
})
}
Expand All @@ -38,6 +45,7 @@ func TestAccAWSUserSSHKey_pemEncoding(t *testing.T) {

ri := acctest.RandInt()
config := fmt.Sprintf(testAccAWSSSHKeyConfig_pemEncoding, ri)
resourceName := "aws_iam_user_ssh_key.user"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Expand All @@ -47,9 +55,15 @@ func TestAccAWSUserSSHKey_pemEncoding(t *testing.T) {
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSUserSSHKeyExists("aws_iam_user_ssh_key.user", "Active", &conf),
testAccCheckAWSUserSSHKeyExists(resourceName, "Active", &conf),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateIdFunc: testAccAWSUserSSHKeyImportStateIdFunc(resourceName),
ImportStateVerify: true,
},
},
})
}
Expand Down Expand Up @@ -122,6 +136,21 @@ func testAccCheckAWSUserSSHKeyExists(n, status string, res *iam.GetSSHPublicKeyO
}
}

func testAccAWSUserSSHKeyImportStateIdFunc(resourceName string) resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return "", fmt.Errorf("not found: %s", resourceName)
}

username := rs.Primary.Attributes["username"]
sshPublicKeyId := rs.Primary.Attributes["ssh_public_key_id"]
encoding := rs.Primary.Attributes["encoding"]

return fmt.Sprintf("%s:%s:%s", username, sshPublicKeyId, encoding), nil
}
}

const testAccAWSSSHKeyConfig_sshEncoding = `
resource "aws_iam_user" "user" {
name = "test-user-%d"
Expand All @@ -145,6 +174,16 @@ resource "aws_iam_user" "user" {
resource "aws_iam_user_ssh_key" "user" {
username = "${aws_iam_user.user.name}"
encoding = "PEM"
public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8giupGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKVHO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwWdhXmXSrbX8ZbabVohBK41 phodgson@thoughtworks.com"
public_key = <<EOF
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9xercjxBRM1dC191/AbF
3TLEM9cdnBIpCgxGNGiI+NaoMTAj/4rXp3ql0iBWQaeb4sz72qCEd1JvcSuzxqFv
IIrqRp/hD7sSAOHAzOL8zqjpIjD4c+VytMIRI5Fc06OPktKbrw2bsCLHYlvZsYSX
O7YATS9HGJVkmFZM+Bv37JTX0T1uZmADOPX+H4bcT2+aJOENi4PXTylRzvwYHruc
KDHO0WNKdXo+g+AihROpcpkgyaVtGB1/8KhPfnHxGroe8WXBtKvbdrWuhen5l9Go
L6RcmaPGhW13lAa+6LEgiTYL2r1mzP9Op4lqzr2F9scFnYV5l0q21/GW2m1aIQSu
NQIDAQAB
-----END PUBLIC KEY-----
EOF
}
`
7 changes: 7 additions & 0 deletions website/docs/r/iam_user_ssh_key.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,10 @@ In addition to all arguments above, the following attributes are exported:
* `ssh_public_key_id` - The unique identifier for the SSH public key.
* `fingerprint` - The MD5 message digest of the SSH public key.

## Import

SSH public keys can be imported using the `username`, `ssh_public_key_id`, and `encoding` e.g.

```
$ terraform import aws_iam_user_ssh_key.user user:APKAJNCNNJICVN7CFKCA:SSH
```

0 comments on commit d64d95f

Please sign in to comment.