Skip to content

Commit

Permalink
Merge pull request #33415 from meetreks/f-aws_transfer_connector
Browse files Browse the repository at this point in the history
F aws transfer connector
  • Loading branch information
ewbankkit authored Sep 13, 2023
2 parents 1a1e777 + 4792cb5 commit d2b5118
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 35 deletions.
3 changes: 3 additions & 0 deletions .changelog/32741.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_transfer_connector: Add `sftp_config` argument and make `as2_config` optional
```
111 changes: 79 additions & 32 deletions internal/service/transfer/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
Expand Down Expand Up @@ -45,7 +46,7 @@ func ResourceConnector() *schema.Resource {
},
"as2_config": {
Type: schema.TypeList,
Required: true,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -97,6 +98,30 @@ func ResourceConnector() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"sftp_config": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"trusted_host_keys": {
Type: schema.TypeSet,
Optional: true,
MinItems: 1,
MaxItems: 10,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringLenBetween(1, 2028),
},
},
"user_secret_id": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(1, 2028),
},
},
},
},
names.AttrTags: tftags.TagsSchema(),
names.AttrTagsAll: tftags.TagsSchemaComputed(),
"url": {
Expand All @@ -115,15 +140,22 @@ func resourceConnectorCreate(ctx context.Context, d *schema.ResourceData, meta i

input := &transfer.CreateConnectorInput{
AccessRole: aws.String(d.Get("access_role").(string)),
As2Config: expandAs2Config(d.Get("as2_config").([]interface{})[0].(map[string]interface{})),
Tags: getTagsIn(ctx),
Url: aws.String(d.Get("url").(string)),
}

if v, ok := d.GetOk("as2_config"); ok {
input.As2Config = expandAs2Config(v.([]interface{}))
}

if v, ok := d.GetOk("logging_role"); ok {
input.LoggingRole = aws.String(v.(string))
}

if v, ok := d.GetOk("sftp_config"); ok {
input.SftpConfig = expandSftpConfig(v.([]interface{}))
}

output, err := conn.CreateConnectorWithContext(ctx, input)

if err != nil {
Expand Down Expand Up @@ -158,6 +190,9 @@ func resourceConnectorRead(ctx context.Context, d *schema.ResourceData, meta int
}
d.Set("connector_id", output.ConnectorId)
d.Set("logging_role", output.LoggingRole)
if err := d.Set("sftp_config", flattenSftpConfig(output.SftpConfig)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting sftp_config: %s", err)
}
d.Set("url", output.Url)
setTagsOut(ctx, output.Tags)

Expand All @@ -178,15 +213,17 @@ func resourceConnectorUpdate(ctx context.Context, d *schema.ResourceData, meta i
}

if d.HasChange("as2_config") {
if v, ok := d.GetOk("as2_config"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
input.As2Config = expandAs2Config(v.([]interface{})[0].(map[string]interface{}))
}
input.As2Config = expandAs2Config(d.Get("as2_config").([]interface{}))
}

if d.HasChange("logging_role") {
input.LoggingRole = aws.String(d.Get("logging_role").(string))
}

if d.HasChange("sftp_config") {
input.SftpConfig = expandSftpConfig(d.Get("sftp_config").([]interface{}))
}

if d.HasChange("url") {
input.Url = aws.String(d.Get("url").(string))
}
Expand Down Expand Up @@ -221,46 +258,43 @@ func resourceConnectorDelete(ctx context.Context, d *schema.ResourceData, meta i
return diags
}

func expandAs2Config(tfMap map[string]interface{}) *transfer.As2ConnectorConfig {
if tfMap == nil {
func expandAs2Config(pUser []interface{}) *transfer.As2ConnectorConfig {
if len(pUser) < 1 || pUser[0] == nil {
return nil
}

apiObject := &transfer.As2ConnectorConfig{}

if v, ok := tfMap["compression"].(string); ok && v != "" {
apiObject.Compression = aws.String(v)
m := pUser[0].(map[string]interface{})

as2Config := &transfer.As2ConnectorConfig{
Compression: aws.String(m["compression"].(string)),
EncryptionAlgorithm: aws.String(m["encryption_algorithm"].(string)),
LocalProfileId: aws.String(m["local_profile_id"].(string)),
MdnResponse: aws.String(m["mdn_response"].(string)),
MdnSigningAlgorithm: aws.String(m["mdn_signing_algorithm"].(string)),
MessageSubject: aws.String(m["message_subject"].(string)),
PartnerProfileId: aws.String(m["partner_profile_id"].(string)),
SigningAlgorithm: aws.String(m["signing_algorithm"].(string)),
}

if v, ok := tfMap["encryption_algorithm"].(string); ok && v != "" {
apiObject.EncryptionAlgorithm = aws.String(v)
}

if v, ok := tfMap["local_profile_id"].(string); ok && v != "" {
apiObject.LocalProfileId = aws.String(v)
}

if v, ok := tfMap["mdn_response"].(string); ok && v != "" {
apiObject.MdnResponse = aws.String(v)
}
return as2Config
}

if v, ok := tfMap["mdn_signing_algorithm"].(string); ok && v != "" {
apiObject.MdnSigningAlgorithm = aws.String(v)
func expandSftpConfig(pUser []interface{}) *transfer.SftpConnectorConfig {
if len(pUser) < 1 || pUser[0] == nil {
return nil
}

if v, ok := tfMap["message_subject"].(string); ok && v != "" {
apiObject.MessageSubject = aws.String(v)
}
m := pUser[0].(map[string]interface{})

if v, ok := tfMap["partner_profile_id"].(string); ok && v != "" {
apiObject.PartnerProfileId = aws.String(v)
sftpConfig := &transfer.SftpConnectorConfig{
UserSecretId: aws.String(m["user_secret_id"].(string)),
}

if v, ok := tfMap["signing_algorithm"].(string); ok && v != "" {
apiObject.SigningAlgorithm = aws.String(v)
if v, ok := m["trusted_host_keys"].(*schema.Set); ok && len(v.List()) > 0 {
sftpConfig.TrustedHostKeys = flex.ExpandStringSet(v)
}

return apiObject
return sftpConfig
}

func flattenAs2Config(apiObject *transfer.As2ConnectorConfig) []interface{} {
Expand Down Expand Up @@ -304,3 +338,16 @@ func flattenAs2Config(apiObject *transfer.As2ConnectorConfig) []interface{} {

return []interface{}{tfMap}
}

func flattenSftpConfig(posixUser *transfer.SftpConnectorConfig) []interface{} {
if posixUser == nil {
return []interface{}{}
}

m := map[string]interface{}{
"trusted_host_keys": aws.StringValueSlice(posixUser.TrustedHostKeys),
"user_secret_id": aws.StringValue(posixUser.UserSecretId),
}

return []interface{}{m}
}
54 changes: 54 additions & 0 deletions internal/service/transfer/connector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,41 @@ func TestAccTransferConnector_basic(t *testing.T) {
})
}

func TestAccTransferConnector_sftpConfig(t *testing.T) {
ctx := acctest.Context(t)
var conf transfer.DescribedConnector
resourceName := "aws_transfer_connector.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
publicKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNt3kA/dBkS6ZyU/sVDiGMuWJQaRPmLNbs/25K/e/fIl07ZWUgqqsFkcycLLMNFGD30Cmgp6XCXfNlIjzFWhNam+4cBb4DPpvieUw44VgsHK5JQy3JKlUfglmH5rs4G5pLiVfZpFU6jqvTsu4mE1CHCP0sXJlJhGxMG3QbsqYWNKiqGFEhuzGMs6fQlMkNiXsFoDmh33HAcXCbaFSC7V7xIqT1hlKu0iOL+GNjMj4R3xy0o3jafhO4MG2s3TwCQQCyaa5oyjL8iP8p3L9yp6cbIcXaS72SIgbCSGCyrcQPIKP2lJJHvE1oVWzLVBhR4eSzrlFDv7K4IErzaJmHqdiz" // nosemgrep:ci.ssh-key

resource.Test(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckPartitionHasService(t, transfer.EndpointsID)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, transfer.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckConnectorDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccConnectorConfig_sftpConfig(rName, "sftp://s-fakeserver.server.transfer.test.amazonaws.com", publicKey),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckConnectorExists(ctx, resourceName, &conf),
resource.TestCheckResourceAttrSet(resourceName, "arn"),
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
resource.TestCheckResourceAttr(resourceName, "url", "sftp://s-fakeserver.server.transfer.test.amazonaws.com"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccTransferConnector_disappears(t *testing.T) {
ctx := acctest.Context(t)
var conf transfer.DescribedConnector
Expand Down Expand Up @@ -261,6 +296,25 @@ resource "aws_transfer_connector" "test" {
`, rName, url))
}

func testAccConnectorConfig_sftpConfig(rName, url, publickey string) string {
return acctest.ConfigCompose(testAccConnectorConfig_base(rName), fmt.Sprintf(`
resource "aws_transfer_connector" "test" {
access_role = aws_iam_role.test.arn
sftp_config {
trusted_host_keys = [%[3]q]
user_secret_id = aws_secretsmanager_secret.test.id
}
url = %[2]q
}
resource "aws_secretsmanager_secret" "test" {
name = %[1]q
}
`, rName, url, publickey))
}

func testAccConnectorConfig_tags1(rName, url, tagKey1, tagValue1 string) string {
return acctest.ConfigCompose(testAccConnectorConfig_base(rName), fmt.Sprintf(`
resource "aws_transfer_connector" "test" {
Expand Down
25 changes: 22 additions & 3 deletions website/docs/r/transfer_connector.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,28 @@ resource "aws_transfer_connector" "example" {
}
```

### SFTP Connector

```terraform
resource "aws_transfer_connector" "example" {
access_role = aws_iam_role.test.arn
sftp_config {
trusted_host_keys = ["ssh-rsa AAAAB3NYourKeysHere"]
user_secret_id = aws_secretsmanager_secret.example.id
}
url = "sftp://test.com"
}
```

## Argument Reference

This resource supports the following arguments:

* `access_role` - (Required) The IAM Role which provides read and write access to the parent directory of the file location mentioned in the StartFileTransfer request.
* `as2_config` - (Required) The parameters to configure for the connector object. Fields documented below.
* `as2_config` - (Optional) Either SFTP or AS2 is configured.The parameters to configure for the connector object. Fields documented below.
* `logging_role` - (Optional) The IAM Role which is required for allowing the connector to turn on CloudWatch logging for Amazon S3 events.
* `url` - (Required) The URL of the partners AS2 endpoint.
* `sftp_config` - (Optional) Either SFTP or AS2 is configured.The parameters to configure for the connector object. Fields documented below.
* `url` - (Required) The URL of the partners AS2 endpoint or SFTP endpoint.
* `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.

### As2Config Details
Expand All @@ -52,12 +66,17 @@ This resource supports the following arguments:
* `partner_profile_id` - (Required) The unique identifier for the AS2 partner profile.
* `signing_algorithm` - (Required) The algorithm that is used to sign AS2 messages sent with the connector. The valid values are SHA256 | SHA384 | SHA512 | SHA1 | NONE .

### SftpConfig Details

* `trusted_host_keys` - (Required) A list of public portion of the host key, or keys, that are used to authenticate the user to the external server to which you are connecting.(https://docs.aws.amazon.com/transfer/latest/userguide/API_SftpConnectorConfig.html)
* `user_secret_id` - (Required) The identifier for the secret (in AWS Secrets Manager) that contains the SFTP user's private key, password, or both. The identifier can be either the Amazon Resource Name (ARN) or the name of the secret.

## Attribute Reference

This resource exports the following attributes in addition to the arguments above:

* `arn` - The ARN of the connector.
* `connector_id` - The unique identifier for the AS2 profile.
* `connector_id` - The unique identifier for the AS2 profile or SFTP Profile.

## Import

Expand Down

0 comments on commit d2b5118

Please sign in to comment.