Enhance EFS file system protection with TLS and IAM

Andreas Wittig – 07 Sep 2022

Two significant aspects of data security are access restriction as well as confidentiality. In the following, you will learn two techniques to increase the security of data stored on an EFS file system (Amazon Elastic File System): enabling encryption of data in transit (TLS) and adding an authentication and authorization layer with IAM.

Enhance EFS file system protection with TLS and IAM

Prefer watching a video instead of reading this blog post? Here you go.

But let’s start with the initial situation.

Security Groups restrict traffic from EC2 to EFS

When EFS launched, the only way to restrict access to the network file system was to use security groups to control traffic tightly. As illustrated in the following figure, using a security group sg-ec2 for the EC2 instance and another security group sg-efs for the mount targets of the EFS file system allows restricting access to the EFS file system on the network layer.

Controlling access to EFS by using security groups

The following code snippet shows how to create an EFS file system, a mount target, as well as two security groups with the help of CloudFormation.

All the following code examples are from our book Amazon Web Services in Action (3rd edition).

FileSystem:
Type: 'AWS::EFS::FileSystem'
Properties:
Encrypted: true
ThroughputMode: bursting
PerformanceMode: generalPurpose
EFSClientSecurityGroup: # Attach to EC2 instance
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: 'EFS Mount target client'
VpcId: !Ref VPC
MountTargetSecurityGroup: # Attach to EFS mount target
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: 'EFS Mount target'
SecurityGroupIngress: # Allows traffic from EC2 instance with EFSClientSecurityGroup only
- IpProtocol: tcp
FromPort: 2049
ToPort: 2049
SourceSecurityGroupId: !Ref EFSClientSecurityGroup
VpcId: !Ref VPC
MountTargetA:
Type: 'AWS::EFS::MountTarget'
Properties:
FileSystemId: !Ref FileSystem
SecurityGroups:
- !Ref MountTargetSecurityGroup # Attaches the MountTargetSecurityGroup
SubnetId: !Ref SubnetA

By default, the data in transit between an EC2 instance and the EFS file system is not encrypted. But, even though the data does not leave your VPC in most scenarios, AWS recommends encrypting all data in transit.

Encryption in Transit (TLS) for EFS

It is pretty simple to enable encryption of the data in transit as EFS file systems support TLS out of the box. For this to work, you must establish a TLS tunnel to EFS before mounting on the EC2 instance. Doing so is quite simple. Install amazon-efs-utils and use the tool to mount EFS file systems, as illustrated in the following figure.

Encrypting data in transit for EFS

The following excerpt of a CloudFormation template explains the details. Direct your attention to the shell script executed via user data when the EC2 instance is first started.

EC2InstanceB:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI]
InstanceType: 't2.micro'
IamInstanceProfile: !Ref IamInstanceProfile
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeleteOnTermination: true
DeviceIndex: 0
GroupSet:
- !Ref EFSClientSecurityGroup
SubnetId: !Ref SubnetB
UserData:
'Fn::Base64': !Sub |
#!/bin/bash -ex
trap '/opt/aws/bin/cfn-signal -e 1 --stack ${AWS::StackName} --resource EC2InstanceB --region ${AWS::Region}' ERR

# install dependencies
yum install -y nc amazon-efs-utils

# mount EFS file system
echo "${FileSystem}:/ /home efs _netdev,noresvport,tls 0 0" >> /etc/fstab
mount -a

/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource EC2InstanceB --region ${AWS::Region}
Tags:
- Key: Name
Value: 'efs-b'
CreationPolicy:
ResourceSignal:
Timeout: PT10M

The user data script adds an entry to the /etc/fstab configuration file. The critical option is named tls which tells the efs-utils installed before establishing a TLS tunnel before mounting the network file system.

On top of that, use a file system policy to deny insecure access to the file system.

FileSystem:
Type: 'AWS::EFS::FileSystem'
Properties:
Encrypted: true
ThroughputMode: bursting
PerformanceMode: generalPurpose
FileSystemPolicy: # resource-based policy
Version: '2012-10-17'
Statement: # deny access when data in transit is not encrypted
- Effect: 'Deny'
Action: '*'
Principal:
AWS: '*'
Condition:
Bool:
'aws:SecureTransport': 'false'

The resource-based policy leads us to use IAM to authenticate and authorize requests to an EFS file system.

IAM authentication and authorization for EFS

By default, mounting an EFS file system does not require any authentication. Typically, only the security groups control access to a file system on the network level. But EFS supports IAM authentication for mounting network file systems as well.

Requiring IAM authentication and authorization for accessing EFS file systems

IAM for EFS requires two things:

  • Configuring a file system policy.
  • Attaching an IAM role to the EC2 instance.

An EFS file system without a file system policy does not require any authentication. But after defining such a resource-based policy, accessing the file system requires authentication and authorization via IAM. So when we added the file system policy to deny unencrypted traffic in the previous section, we also activated IAM authentication and authorization.

Luckily, the amazon-efs-utils do support not only TLS but also IAM. All you have to do is to add another mount parameter called iam to the /etc/fstab configuration file.

EC2InstanceB:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI]
InstanceType: 't2.micro'
IamInstanceProfile: !Ref IamInstanceProfile
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeleteOnTermination: true
DeviceIndex: 0
GroupSet:
- !Ref EFSClientSecurityGroup
SubnetId: !Ref SubnetB
UserData:
'Fn::Base64': !Sub |
#!/bin/bash -ex
trap '/opt/aws/bin/cfn-signal -e 1 --stack ${AWS::StackName} --resource EC2InstanceB --region ${AWS::Region}' ERR

# install dependencies
yum install -y nc amazon-efs-utils

# mount EFS file system
echo "${FileSystem}:/ /home efs _netdev,noresvport,tls,iam 0 0" >> /etc/fstab
mount -a

/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource EC2InstanceB --region ${AWS::Region}
Tags:
- Key: Name
Value: 'efs-b'
CreationPolicy:
ResourceSignal:
Timeout: PT10M

Of course, you need to assign an IAM role to the EC2 instance to grant access to the EFS file system. The following code snippet shows how to do so with CloudFormation.

IamRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- 'ec2.amazonaws.com'
Action: 'sts:AssumeRole'
Policies:
- PolicyName: efs
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'elasticfilesystem:ClientRootAccess'
- 'elasticfilesystem:ClientWrite'
- 'elasticfilesystem:ClientMount'
Resource: !GetAtt 'FileSystem.Arn'

That’s it. With IAM, you added authentication and authorization at the application layer. So you are not only relying on security groups to control access to EFS file systems anymore.

Summary

To protect your data stored on EFS (Amazon Elastic File System), I recommend enabling and enforcing encryption in transit (TLS) as well as IAM authentication and authorization. The amazon-efs-utils support TLS and IAM out of the box.

Andreas Wittig

Andreas Wittig

I’ve been building on AWS since 2012 together with my brother Michael. We are sharing our insights into all things AWS on cloudonaut and have written the book AWS in Action. Besides that, we’re currently working on bucketAV,HyperEnv for GitHub Actions, and marbot.

Here are the contact options for feedback and questions.