AWSTemplateFormatVersion: '2010-09-09'
Description: This sample template will create an Amazon EFS file system, Amazon EFS Mount Target, IAM Roles Anywhere Trust Anchor, IAM Roles Anywhere Profile, IAM policy and role for EFS client authentications, and EC2 Security Group.
Parameters:
  MountTargetVPC:
    Type: AWS::EC2::VPC::Id
    Description: Select the VPC to use for the Amazon EFS file System
    AllowedPattern: .+
    ConstraintDescription: You must select the VPC for the Amazon EFS file System
  MountTargetSubnet:
    Type: AWS::EC2::Subnet::Id
    Description: Select the Subnet within your VPC to use for your EFS file System
    AllowedPattern: .+
    ConstraintDescription: You must select the Subnet within your VPC for your EFS file System
  UseAcm:
    Type: String
    Description: Must select Yes or No
    AllowedValues:
      - 'Yes'
      - 'No'
    AllowedPattern: .+
    ConstraintDescription: You must select Yes or No to indicate if you are using AWS Private Certificate Authority 
  AcmCaId:
    Type: String
    Description: 'If selected Yes to using AWS Private CA, enter the AWS Private CA ID, for example: 26t253b7-b17a-4837-b848-87c6ec2cbc7a'
  X509CaPem:
    Type: String
    Description: 'If selected No to using AWS Private CA, enter the SSM parameter for the PEM-encoded CA, for example: /demo/efsanywheredemo/cabundlepem'
  ClientCidr:
    Type: String
    Description: 'Enter the IP address of your Linux server in CIDR notation, for example: 192.168.1.0/24 or 192.168.1.5/32'
    AllowedPattern: '((\d{1,3})\.){3}\d{1,3}/\d{1,2}'
    ConstraintDescription: You must enter the NFS client IP address in CIDR notation, for example 192.168.1.0/24 or 192.168.1.5/32
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: IAM Roles Anywhere Trust Anchor
        Parameters:
          - UseAcm
          - AcmCaId
          - X509CaPem
      - Label:
          default: EFS File System
        Parameters:
          - MountTargetVPC
          - MountTargetSubnet
      - Label:
          default: Linux Server NFS Client
        Parameters:
          - ClientCidr
    ParameterLabels:
      UseAcm:
        default: Using AWS Private Certificate Authority?
      AcmCaId:
        default: AWS Private Certificate Authority ID
      X509CaPem:
        default: Systems Manager Parameter for PEM-encoded CA
      MountTargetVPC:
        default: EFS File System Mount Target VPC
      MountTargetSubnet:
        default: EFS File System Mount Target Subnet
      ClientCidr:
        default: Linux server NFS client IP address
Conditions:
  UseAcmCaId: !Equals
    - !Ref 'UseAcm'
    - 'Yes'
Resources:
  EFSanywhereDemoIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - rolesanywhere.amazonaws.com
            Action:
              - sts:AssumeRole
              - sts:TagSession
              - sts:SetSourceIdentity
      Path: /
  EFSanywhereDemoIAMPolicies:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - elasticfilesystem:ClientRootAccess
              - elasticfilesystem:ClientWrite
              - elasticfilesystem:ClientMount
            Resource: !GetAtt 'EFSanywhereDemoFileSystem.Arn'
            Condition:
              Bool:
                elasticfilesystem:AccessedViaMountTarget: 'true'
      Roles:
        - !Ref 'EFSanywhereDemoIAMRole'
  EFSanywhereDemoTrustAnchor:
    Type: AWS::RolesAnywhere::TrustAnchor
    Properties:
      Enabled: 'True'
      Name: EFSanywhereDemoTrustAnchor
      Source: !If
        - UseAcmCaId
        - SourceData:
            AcmPcaArn: !Sub 'arn:${AWS::Partition}:acm-pca:${AWS::Region}:${AWS::AccountId}:certificate-authority/${AcmCaId}'
          SourceType: AWS_ACM_PCA
        - SourceData:
            X509CertificateData: !Sub '{{resolve:ssm:${X509CaPem}}}'
          SourceType: CERTIFICATE_BUNDLE
  EFSanywhereDemoProfile:
    Type: AWS::RolesAnywhere::Profile
    Properties:
      DurationSeconds: 3600
      Enabled: 'True'
      Name: EFSanywhereDemoProfile
      RoleArns:
        - !GetAtt 'EFSanywhereDemoIAMRole.Arn'
  EFSanywhereDemoMountTargetSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow NFS access to Mount Target
      VpcId: !Ref 'MountTargetVPC'
      SecurityGroupIngress:
        - Description: Allow NFS Clients access to Mount Target
          IpProtocol: tcp
          FromPort: 2049
          ToPort: 2049
          CidrIp: !Ref 'ClientCidr'
  EFSanywhereDemoMountTargetSGEgress:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:    
          Description: Allow NFS Clients access to Mount Target
          GroupId: !Ref 'EFSanywhereDemoMountTargetSG'
          IpProtocol: '-1'
          DestinationSecurityGroupId: !Ref 'EFSanywhereDemoMountTargetSG'
  EFSanywhereDemoFileSystem:
    Type: AWS::EFS::FileSystem
    Properties:
      Encrypted: true
      FileSystemTags:
        - Key: Name
          Value: EFS_Roles_Anywhere
      FileSystemPolicy:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action:
              - elasticfilesystem:ClientMount
            Principal:
              AWS: !GetAtt 'EFSanywhereDemoIAMRole.Arn'
      BackupPolicy:
        Status: DISABLED
  EFSanywhereMountTarget:
    Type: AWS::EFS::MountTarget
    Properties:
      FileSystemId: !Ref 'EFSanywhereDemoFileSystem'
      SubnetId: !Ref 'MountTargetSubnet'
      SecurityGroups:
        - !Ref 'EFSanywhereDemoMountTargetSG'
Outputs:
  HostsCommand:
    Description: Run this command on your Linux server to append the EFS file system hostname to /etc/hosts
    Value: !Sub 'echo ''${EFSanywhereMountTarget.IpAddress} ${EFSanywhereDemoFileSystem.FileSystemId}.efs.${AWS::Region}.${AWS::URLSuffix} ${EFSanywhereDemoFileSystem.FileSystemId}'' | sudo tee -a /etc/hosts'
  MountCommand:
    Description: Run this command on your Linux server to manually mount the EFS file system
    Value: !Sub 'sudo mount -t efs -o tls,iam,awsprofile=efs ${EFSanywhereDemoFileSystem.FileSystemId}:/ /mnt/efsdemo/'
  FstabCommand:
    Description: Run this command on your Linux server to automatically mount the EFS file system
    Value: !Sub 'echo ''${EFSanywhereDemoFileSystem.FileSystemId}.efs.${AWS::Region}.${AWS::URLSuffix}:/ /mnt/efsdemo efs _netdev,tls,iam,awsprofile=efs 0 0'' | sudo tee -a /etc/fstab '
  ProfileCredentials:
    Description: Update the file paths and append to the [profile efs] section of your /root/.aws/config file
    Value: !Sub 'credential_process = /UPDATEME/aws_signing_helper credential-process --certificate /UPDATEME/certificate.pem --private-key /UPDATEME/private-key.pem --trust-anchor-arn ${EFSanywhereDemoTrustAnchor.TrustAnchorArn}
      --profile-arn ${EFSanywhereDemoProfile.ProfileArn} --role-arn ${EFSanywhereDemoIAMRole.Arn}'
