Back to blog
AWSBest PracticesCloud SecurityMonitoring & LoggingOperations & Compliance

Transfer Server Has No Logging: Closing the AWS Transfer Family Blind Spot

Learn why an AWS Transfer Family server without a CloudWatch logging role is a security blind spot, and how to fix and prevent it with CLI, Terraform, and policy as code.

TL;DR

Your AWS Transfer Family server is moving files over SFTP, FTPS, or FTP without a CloudWatch Logs role, so there is no record of who connected or what they uploaded. Attach a logging role to the server so authentication attempts and file operations are captured.

AWS Transfer Family gives you a managed SFTP, FTPS, or FTP endpoint backed by S3 or EFS. It is a common way to let partners, vendors, and legacy systems push and pull files without you running your own file transfer infrastructure. The convenience is real, but a Transfer server with no logging role configured is a blind spot. If something goes wrong, you have nothing to look at.

This check, transfer_nologging, flags any AWS Transfer Family server that has no CloudWatch logging role attached. It is a simple configuration gap with outsized consequences during an incident.


What this check detects

Every AWS Transfer Family server has an optional LoggingRole property. This is an IAM role that grants the service permission to push structured logs to CloudWatch Logs. When it is set, Transfer Family records connection events, authentication results, and file-level operations such as OPEN, CLOSE, RENAME, and DELETE.

When the LoggingRole is empty, none of that happens. The check looks at the server configuration and fails if the role is missing.

Note: AWS Transfer Family supports two logging styles. The older approach uses a CloudWatch logging role for service-managed logs. Newer servers can use structured JSON logging delivered to a CloudWatch Logs group you specify. Either way, a server with no logging configuration at all is the problem this check catches.


Why it matters

File transfer endpoints sit at a sensitive boundary. They often handle PII, financial records, healthcare data, or batch files that feed downstream systems. External parties authenticate to them, sometimes with credentials that have not been rotated in years. Without logs, you lose visibility into all of it.

You cannot investigate what you cannot see

Picture a partner account that gets compromised. The attacker authenticates to your SFTP endpoint with valid stolen credentials and starts pulling down every file in the bucket. With logging enabled, you would see the connection source IP, the authentication success, and the list of files accessed. With no logging, your first clue might be a customer complaint or a data exposure notice weeks later.

Failed authentication patterns go unnoticed

Logging captures failed authentication attempts. A spike in failures from an unfamiliar IP range is a clear signal of credential stuffing or a brute force attempt against your usernames. No logs means no signal, no alert, and no chance to block the source before it succeeds.

Compliance and audit gaps

Frameworks like SOC 2, PCI DSS, and HIPAA expect you to log access to systems that handle regulated data. PCI DSS Requirement 10, for example, calls for audit trails that link access to individual users. An auditor asking "show me who downloaded this file on this date" has no good answer if the Transfer server was never logging.

Warning: CloudWatch Logs ingestion and storage are billable. A busy Transfer server can generate a meaningful volume of log data. This is rarely expensive relative to the value of the visibility, but set a retention policy on the log group so old data ages out instead of accumulating forever.


How to fix it

Remediation is to create an IAM role that lets Transfer Family write to CloudWatch Logs, then attach it to the server. No downtime is involved, and existing connections are not interrupted.

Step 1: Create the logging IAM role

First, define a trust policy so the Transfer Family service can assume the role. Save this as trust-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "transfer.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Create the role and attach the AWS managed logging policy:

aws iam create-role \
  --role-name TransferLoggingRole \
  --assume-role-policy-document file://trust-policy.json

aws iam attach-role-policy \
  --role-name TransferLoggingRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSTransferLoggingAccess

The managed policy AWSTransferLoggingAccess grants the minimum CloudWatch Logs permissions Transfer Family needs: creating log groups and streams and putting log events.

Step 2: Attach the role to your server

Grab your server ID first if you do not have it:

aws transfer list-servers \
  --query "Servers[].ServerId" --output table

Then update the server with the logging role ARN:

aws transfer update-server \
  --server-id s-0123456789abcdef0 \
  --logging-role arn:aws:iam::111122223333:role/TransferLoggingRole

Note: If you prefer structured JSON logging to a specific log group, use --structured-log-destinations with the ARN of a CloudWatch Logs group instead. The logging role is still required for the service to write there.

Console steps

  1. Open the AWS Transfer Family console and select your server.
  2. Choose Edit next to the Additional details section.
  3. Under CloudWatch logging, select Create a new role or pick an existing logging role.
  4. Save the changes.

Verify it worked

aws transfer describe-server \
  --server-id s-0123456789abcdef0 \
  --query "Server.LoggingRole" --output text

You should see the role ARN returned instead of an empty value. Make a test connection and confirm log streams appear under the /aws/transfer/<server-id> log group.


How to prevent it from happening again

Fixing one server by hand is fine. Stopping the next one from launching without logging is what keeps this off your dashboard for good. Define your Transfer servers in infrastructure as code with the logging role baked in.

Terraform

resource "aws_iam_role" "transfer_logging" {
  name = "TransferLoggingRole"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "transfer.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })
}

resource "aws_iam_role_policy_attachment" "transfer_logging" {
  role       = aws_iam_role.transfer_logging.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSTransferLoggingAccess"
}

resource "aws_transfer_server" "sftp" {
  identity_provider_type = "SERVICE_MANAGED"
  protocols              = ["SFTP"]
  logging_role           = aws_iam_role.transfer_logging.arn
}

Tip: Wrap your Transfer server in a reusable Terraform module that requires the logging_role as a non-optional input. If a teammate cannot create a server without supplying one, the gap closes itself.

Catch it in CI with policy as code

Add a Checkov or OPA gate to your pipeline so a Transfer server missing its logging role fails the build before it reaches AWS. A minimal Rego policy looks like this:

package transfer.logging

deny[msg] {
  resource := input.resource.aws_transfer_server[name]
  not resource.logging_role
  msg := sprintf("Transfer server '%s' has no logging_role configured", [name])
}

Catch existing drift continuously

IaC gates only cover resources created through your pipeline. Servers spun up by hand or by a forgotten script still slip through. Continuous scanning with Lensix catches those by checking the live account state, so the transfer_nologging finding surfaces no matter how the server was created.


Best practices

  • Set log retention. Apply a retention policy to the /aws/transfer/* log groups so data ages out predictably. Thirty to ninety days is common, longer if compliance demands it.
  • Alert on failed authentications. Build a CloudWatch metric filter on authentication failures and wire it to an SNS alarm. Repeated failures from one source deserve an alert.
  • Prefer structured JSON logging. Newer Transfer servers support structured logs that are far easier to query in CloudWatch Logs Insights than the legacy free text format.
  • Centralize logs. Ship Transfer logs to your SIEM or a central logging account so file access events live alongside the rest of your security telemetry.
  • Rotate partner credentials. Logging tells you about access, but short-lived keys and regular rotation reduce the blast radius if credentials leak.
  • Restrict source IPs. Pair logging with a VPC endpoint and security group rules so only known partner ranges can even reach the server.

Tip: Combine the logging role with a CloudWatch Logs Insights saved query that lists the top source IPs and accessed file paths. When an incident lands, you want that query one click away rather than written from scratch under pressure.

Logging on a Transfer Family server is one of those low-effort, high-payoff controls. It costs a single IAM role and a server update, and it turns a silent file gateway into an auditable, observable one. Get it attached, codify it, and keep scanning so it stays that way.