Skip to content

Commit

Permalink
Merge pull request #28621 from bennylu2/f-aws_transfer_server-protoco…
Browse files Browse the repository at this point in the history
…l_details-27695

aws_transfer_server - add protocol_details
  • Loading branch information
ewbankkit authored Mar 7, 2023
2 parents 8b8b745 + c0c6a7e commit 6eb475b
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .changelog/28621.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_transfer_server: Add `protocol_details` argument
```
102 changes: 102 additions & 0 deletions internal/service/transfer/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,43 @@ func ResourceServer() *schema.Resource {
Sensitive: true,
ValidateFunc: validation.StringLenBetween(0, 512),
},
"protocol_details": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"as2_transports": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringInSlice(transfer.As2Transport_Values(), false),
},
},
"passive_ip": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringLenBetween(0, 15),
},
"set_stat_option": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice(transfer.SetStatOption_Values(), false),
},
"tls_session_resumption_mode": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice(transfer.TlsSessionResumptionMode_Values(), false),
},
},
},
},
"protocols": {
Type: schema.TypeSet,
MinItems: 1,
Expand Down Expand Up @@ -317,6 +354,10 @@ func resourceServerCreate(ctx context.Context, d *schema.ResourceData, meta inte
input.PreAuthenticationLoginBanner = aws.String(v.(string))
}

if v, ok := d.GetOk("protocol_details"); ok && len(v.([]interface{})) > 0 {
input.ProtocolDetails = expandProtocolDetails(v.([]interface{}))
}

if v, ok := d.GetOk("protocols"); ok && v.(*schema.Set).Len() > 0 {
input.Protocols = flex.ExpandStringSet(v.(*schema.Set))
}
Expand Down Expand Up @@ -444,6 +485,9 @@ func resourceServerRead(ctx context.Context, d *schema.ResourceData, meta interf
d.Set("logging_role", output.LoggingRole)
d.Set("post_authentication_login_banner", output.PostAuthenticationLoginBanner)
d.Set("pre_authentication_login_banner", output.PreAuthenticationLoginBanner)
if err := d.Set("protocol_details", flattenProtocolDetails(output.ProtocolDetails)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting protocol_details: %s", err)
}
d.Set("protocols", aws.StringValueSlice(output.Protocols))
d.Set("security_policy_name", output.SecurityPolicyName)
if output.IdentityProviderDetails != nil {
Expand Down Expand Up @@ -620,6 +664,10 @@ func resourceServerUpdate(ctx context.Context, d *schema.ResourceData, meta inte
input.PreAuthenticationLoginBanner = aws.String(d.Get("pre_authentication_login_banner").(string))
}

if d.HasChange("protocol_details") {
input.ProtocolDetails = expandProtocolDetails(d.Get("protocol_details").([]interface{}))
}

if d.HasChange("protocols") {
input.Protocols = flex.ExpandStringSet(d.Get("protocols").(*schema.Set))
}
Expand Down Expand Up @@ -811,6 +859,60 @@ func flattenEndpointDetails(apiObject *transfer.EndpointDetails, securityGroupID
return tfMap
}

func expandProtocolDetails(m []interface{}) *transfer.ProtocolDetails {
if len(m) < 1 || m[0] == nil {
return nil
}

tfMap := m[0].(map[string]interface{})

apiObject := &transfer.ProtocolDetails{}

if v, ok := tfMap["as2_transports"].(*schema.Set); ok && v.Len() > 0 {
apiObject.As2Transports = flex.ExpandStringSet(v)
}

if v, ok := tfMap["passive_ip"].(string); ok && len(v) > 0 {
apiObject.PassiveIp = aws.String(v)
}

if v, ok := tfMap["set_stat_option"].(string); ok && len(v) > 0 {
apiObject.SetStatOption = aws.String(v)
}

if v, ok := tfMap["tls_session_resumption_mode"].(string); ok && len(v) > 0 {
apiObject.TlsSessionResumptionMode = aws.String(v)
}

return apiObject
}

func flattenProtocolDetails(apiObject *transfer.ProtocolDetails) []interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{}

if v := apiObject.As2Transports; v != nil {
tfMap["as2_transport"] = aws.StringValueSlice(v)
}

if v := apiObject.PassiveIp; v != nil {
tfMap["passive_ip"] = aws.StringValue(v)
}

if v := apiObject.SetStatOption; v != nil {
tfMap["set_stat_option"] = aws.StringValue(v)
}

if v := apiObject.TlsSessionResumptionMode; v != nil {
tfMap["tls_session_resumption_mode"] = aws.StringValue(v)
}

return []interface{}{tfMap}
}

func expandWorkflowDetails(tfMap []interface{}) *transfer.WorkflowDetails {
apiObject := &transfer.WorkflowDetails{
OnPartialUpload: []*transfer.WorkflowDetail{},
Expand Down
60 changes: 60 additions & 0 deletions internal/service/transfer/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ func testAccServer_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "logging_role", ""),
resource.TestCheckResourceAttr(resourceName, "post_authentication_login_banner", ""),
resource.TestCheckResourceAttr(resourceName, "pre_authentication_login_banner", ""),
resource.TestCheckResourceAttr(resourceName, "protocol_details.#", "1"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.as2_transports.#", "0"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.passive_ip", "AUTO"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.set_stat_option", "DEFAULT"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.tls_session_resumption_mode", "ENFORCED"),
resource.TestCheckResourceAttr(resourceName, "protocols.#", "1"),
resource.TestCheckTypeSetElemAttr(resourceName, "protocols.*", "SFTP"),
resource.TestCheckResourceAttr(resourceName, "security_policy_name", "TransferSecurityPolicy-2018-11"),
Expand Down Expand Up @@ -791,6 +796,49 @@ func testAccServer_protocols(t *testing.T) {
})
}

func testAccServer_protocolDetails(t *testing.T) {
ctx := acctest.Context(t)
var s transfer.DescribedServer
resourceName := "aws_transfer_server.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); testAccPreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, transfer.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckServerDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccServerConfig_protocolDetails("AUTO", "DEFAULT", "ENFORCED"),
Check: resource.ComposeTestCheckFunc(
testAccCheckServerExists(ctx, resourceName, &s),
resource.TestCheckResourceAttr(resourceName, "protocol_details.#", "1"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.as2_transports.#", "0"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.passive_ip", "AUTO"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.set_stat_option", "DEFAULT"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.tls_session_resumption_mode", "ENFORCED"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"force_destroy"},
},
{
Config: testAccServerConfig_protocolDetails("8.8.8.8", "ENABLE_NO_OP", "DISABLED"),
Check: resource.ComposeTestCheckFunc(
testAccCheckServerExists(ctx, resourceName, &s),
resource.TestCheckResourceAttr(resourceName, "protocol_details.#", "1"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.as2_transports.#", "0"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.passive_ip", "8.8.8.8"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.set_stat_option", "ENABLE_NO_OP"),
resource.TestCheckResourceAttr(resourceName, "protocol_details.0.tls_session_resumption_mode", "DISABLED"),
),
},
},
})
}

func testAccServer_apiGateway(t *testing.T) {
ctx := acctest.Context(t)
var conf transfer.DescribedServer
Expand Down Expand Up @@ -1752,6 +1800,18 @@ resource "aws_transfer_server" "test" {
`, rName))
}

func testAccServerConfig_protocolDetails(passive_ip, set_stat_option, tls_session_resumption_mode string) string {
return fmt.Sprintf(`
resource "aws_transfer_server" "test" {
protocol_details {
passive_ip = %[1]q
set_stat_option = %[2]q
tls_session_resumption_mode = %[3]q
}
}
`, passive_ip, set_stat_option, tls_session_resumption_mode)
}

func testAccServerConfig_rootCA(domain string) string {
return fmt.Sprintf(`
resource "aws_acmpca_certificate_authority" "test" {
Expand Down
1 change: 1 addition & 0 deletions internal/service/transfer/transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func TestAccTransfer_serial(t *testing.T) {
"HostKey": testAccServer_hostKey,
"LambdaFunction": testAccServer_lambdaFunction,
"Protocols": testAccServer_protocols,
"ProtocolDetails": testAccServer_protocolDetails,
"SecurityPolicy": testAccServer_securityPolicy,
"UpdateEndpointTypePublicToVPC": testAccServer_updateEndpointType_publicToVPC,
"UpdateEndpointTypePublicToVPCAddressAllocationIDs": testAccServer_updateEndpointType_publicToVPC_addressAllocationIDs,
Expand Down
10 changes: 9 additions & 1 deletion website/docs/r/transfer_server.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ The following arguments are supported:
* `endpoint_details` - (Optional) The virtual private cloud (VPC) endpoint settings that you want to configure for your SFTP server. Fields documented below.
* `endpoint_type` - (Optional) The type of endpoint that you want your SFTP server connect to. If you connect to a `VPC` (or `VPC_ENDPOINT`), your SFTP server isn't accessible over the public internet. If you want to connect your SFTP server via public internet, set `PUBLIC`. Defaults to `PUBLIC`.
* `invocation_role` - (Optional) Amazon Resource Name (ARN) of the IAM role used to authenticate the user account with an `identity_provider_type` of `API_GATEWAY`.
* `host_key` - (Optional) RSA private key (e.g., as generated by the `ssh-keygen -N "" -m PEM -f my-new-server-key` command).
* `host_key` - (Optional) RSA, ECDSA, or ED25519 private key (e.g., as generated by the `ssh-keygen -t rsa -b 2048 -N "" -m PEM -f my-new-server-key`, `ssh-keygen -t ecdsa -b 256 -N "" -m PEM -f my-new-server-key` or `ssh-keygen -t ed25519 -N "" -f my-new-server-key` commands).
* `url` - (Optional) - URL of the service endpoint used to authenticate users with an `identity_provider_type` of `API_GATEWAY`.
* `identity_provider_type` - (Optional) The mode of authentication enabled for this service. The default value is `SERVICE_MANAGED`, which allows you to store and access SFTP user credentials within the service. `API_GATEWAY` indicates that user authentication requires a call to an API Gateway endpoint URL provided by you to integrate an identity provider of your choice. Using `AWS_DIRECTORY_SERVICE` will allow for authentication against AWS Managed Active Directory or Microsoft Active Directory in your on-premises environment, or in AWS using AD Connectors. Use the `AWS_LAMBDA` value to directly use a Lambda function as your identity provider. If you choose this value, you must specify the ARN for the lambda function in the `function` argument.
* `directory_id` - (Optional) The directory service ID of the directory service you want to connect to with an `identity_provider_type` of `AWS_DIRECTORY_SERVICE`.
Expand All @@ -108,6 +108,7 @@ The following arguments are supported:
* `force_destroy` - (Optional) A boolean that indicates all users associated with the server should be deleted so that the Server can be destroyed without error. The default value is `false`. This option only applies to servers configured with a `SERVICE_MANAGED` `identity_provider_type`.
* `post_authentication_login_banner`- (Optional) Specify a string to display when users connect to a server. This string is displayed after the user authenticates. The SFTP protocol does not support post-authentication display banners.
* `pre_authentication_login_banner`- (Optional) Specify a string to display when users connect to a server. This string is displayed before the user authenticates.
* `protocol_details`- (Optional) The protocol settings that are configured for your server.
* `security_policy_name` - (Optional) Specifies the name of the security policy that is attached to the server. Possible values are `TransferSecurityPolicy-2018-11`, `TransferSecurityPolicy-2020-06`, `TransferSecurityPolicy-FIPS-2020-06` and `TransferSecurityPolicy-2022-03`. Default value is: `TransferSecurityPolicy-2018-11`.
* `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.
* `workflow_details` - (Optional) Specifies the workflow details. See Workflow Details below.
Expand All @@ -120,6 +121,13 @@ The following arguments are supported:
* `vpc_endpoint_id` - (Optional) The ID of the VPC endpoint. This property can only be used when `endpoint_type` is set to `VPC_ENDPOINT`
* `vpc_id` - (Optional) The VPC ID of the virtual private cloud in which the SFTP server's endpoint will be hosted. This property can only be used when `endpoint_type` is set to `VPC`.

### Protocol Details

* `as2_transports` - (Optional) Indicates the transport method for the AS2 messages. Currently, only `HTTP` is supported.
* `passive_ip` - (Optional) Indicates passive mode, for FTP and FTPS protocols. Enter a single IPv4 address, such as the public IP address of a firewall, router, or load balancer.
* `set_stat_option` - (Optional) Use to ignore the error that is generated when the client attempts to use `SETSTAT` on a file you are uploading to an S3 bucket. Valid values: `DEFAULT`, `ENABLE_NO_OP`.
* `tls_session_resumption_mode` - (Optional) A property used with Transfer Family servers that use the FTPS protocol. Provides a mechanism to resume or share a negotiated secret key between the control and data connection for an FTPS session. Valid values: `DISABLED`, `ENABLED`, `ENFORCED`.

### Workflow Details

* `on_upload` - (Optional) A trigger that starts a workflow: the workflow begins to execute after a file is uploaded. See Workflow Detail below.
Expand Down

0 comments on commit 6eb475b

Please sign in to comment.