AWS Public Sector Blog

Creating AWS CloudFormation templates for AWS Ground Station DigIF workloads

AWS branded background with text overlay that says "Creating AWS CloudFormation templates for AWS Ground Station DigIF workloads"

Amazon Web Services (AWS) Ground Station has many different parameters and options to choose from when creating a contact and setting up data delivery. For this reason, it is advised that infrastructure as code (IaC) is used, such as AWS CloudFormation. Creating AWS CloudFormation templates for AWS Ground Station workloads requires many individual moving parts. This post is the first of a two-part tutorial that provides an overview of the resources required to create AWS CloudFormation templates for Digital Intermediate Frequency (DigIF) workloads, using AWS Ground Station to transmit data between the satellite and AWS Cloud environment.

This tutorial also gives brief explanations of the different parameter options for the three core components of AWS Ground Station: configs, dataflow endpoint groups, and mission profiles. This post explains how to customize AWS CloudFormation templates for AWS Ground Station workloads to suit your business needs and how to create your own if desired.

Digital Intermediate Frequency (DigIF)

In a DigIF workload, AWS Ground Station does not automatically demodulate (demod) or decode data that is downlinked from the satellite. Instead, this step is managed by the customer, allowing them to use a software defined radio (SDR) of their choosing for the demod/decode step. The following image shows an example architecture for an Amazon Elastic Compute Cloud (Amazon EC2) data delivery DigIF workload. The following steps are outlined in the image:

  • Step 1 – Downlink signals are acquired in any AWS Ground Station region, digitized, and stream live towards the customer’s secure domain in the AWS cloud.
  • Step 2 – Digitized downlink signals are delivered to the customer’s Amazon Virtual Private Cloud (Amazon VPC) within an AWS Region of choice. Signals are demodulated using software modems hosted in virtual machines managed by the customer, in either the same or separate VPCs.
  • Step 3- Demodulated/decoded data can be further processed, stored, and distributed using other services in the AWS Cloud. Customer operations and compute could also be implemented through containers, serverless services, and so on to reduce cost, complexity, overhead, and time to deployment. Amazon EC2 is depicted as an example compute resource.
  • Step 4 – Additional example services (such as Amazon Simple Storage Service (Amazon S3), Amazon Relational Database Service (Amazon RDS), and Managed Grafana) are depicted that would enable mission operations in the cloud.

Figure 1. Example architecture diagram for a DigIF workload. Data is transmitted from the satellite, through the AWS Ground Station service, and into an Amazon EC2 receiver instance.

Prerequisites

The following resources are required for this data delivery method, and explanations for the parameter options are available in an AWS CloudFormation template.

  • An Amazon Virtual Private Cloud (Amazon VPC) with at least one private subnet.
  • An SSH bastion host for connecting to the private instance. Using a bastion host allows you to lock down the receiver instance so that only the bastion host instance can connect to it. Learn more about bastion hosts at Linux Bastion Hosts on AWS.
  • An SSH key used to connect to the host once it is built.

Amazon EC2 data delivery

The following code snippet is an example of the resources to be included in an AWS CloudFormation template for Amazon EC2 data delivery.

Note: The EC2 instance used for data delivery must run in a Region that AWS Ground Station supports for data delivery.

Resources:
  DataDeliveryServiceRole:
  InstanceRole:
  ClusterPlacementGroup:
  GeneralInstanceProfile:
  InstanceSecurityGroup:
  DataflowEndpointSecurityGroup:
  ReceiverInstanceNetworkInterface:
  ReceiverInstanceInterfaceAttachment:
  ReceiverInstance:
  DataflowEndpointGroup:
  TrackingConfig:
  AntennaDownlinkConfig:
  DownlinkDigIfEndpointConfig:
  MissionProfile:

As you can see, this data delivery method requires more resources and planning. Still, it is the only data delivery method where customers can take advantage of streaming data from a satellite in real time.  

DataDeliveryserviceRole

This is the AWS Identity and Access Management (IAM) role that the AWS Ground Station assumes to create and delete elastic network interfaces and describe network components such as subnets, VPCs, and security groups.

DataDeliveryServiceRole:
    Type: AWS::IAM::Role
    Properties:
      Policies:
        - PolicyDocument:
            Statement:
              - Action:
                  - ec2:CreateNetworkInterface
                  - ec2:DeleteNetworkInterface
                  - ec2:CreateNetworkInterfacePermission
                  - ec2:DeleteNetworkInterfacePermission
                  - ec2:DescribeSubnets
                  - ec2:DescribeVpcs
                  - ec2:DescribeSecurityGroups
                Effect: Allow
                Resource: 'ReceiverInstance'
            Version: '2012-10-17'
          PolicyName: DataDeliveryServicePolicy
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - groundstation.amazonaws.com
            Action:
            - sts:AssumeRole

InstanceRole

This is the IAM role that the Amazon EC2 instance ReceiverInstance assumes. The standout policies that are attached here are: CloudWatchAgentServerPolicy and AmazonSSMManagedInstanceCore. The first policy is for notification and automation purposes in this workflow, while the second policy enables AWS Systems Manager service core functionality on EC2 instances. The AmazonEC2ContainerServiceforEC2Role policy contains the permissions needed to use the full Amazon Elastic Container Service (ECS) feature set. (If you’re not going to use ECS, this can be omitted.)

The following code snippet shows how the ShouldCreateInstance condition is structured:

Conditions:
  ShouldCreateInstance:
    !Equals ["Yes", !Ref CreateReceiverInstance]

In this case, if the receiver instance is created, then the IAM role below is created for that instance.

For more on AWS CloudFormation conditions, refer to AWS CloudFormation Conditions.

The following policies are AWS managed policies. For more information on this type of policy, refer to AWS managed policies.

InstanceRole:
    Type: AWS::IAM::Role
    Condition: ShouldCreateInstance
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - "ec2.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
        - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
        - arn:aws:iam::aws:policy/service-role/AmazonSSMManagedInstanceCore

ClusterPlacementGroup

Here, the placement group for the ReceiverInstance is determined. Placement groups are used when there are multiple Amazon EC2 instances. If just one receiver instance is launched, this resource is not needed. The following example shows how this section would look if the cluster placement strategy is chosen. A cluster placement would reduce latency brought on by geographic distance between the data centers where the instances live.

ClusterPlacementGroup:
    Type: AWS::EC2::PlacementGroup
    Condition: ShouldCreateInstance
    Properties:
      Strategy: cluster

GeneralInstanceProfile

This resource is the instance profile for the ReceiverInstance, with a reference to the instance IAM role created above. Instance profiles pass an IAM role to an Amazon EC2 instance.

GeneralInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Condition: ShouldCreateInstance
    Properties:
      Roles:
        - !Ref InstanceRole

InstanceSecurityGroup

This is the security group that the ReceiverInstance will belong to. The prerequisite VPC is referenced here and the two rules in this example are allowing TCP traffic inbound from port 22 (for SSH) and AWS Ground Station UDP traffic inbound from port 55888.

The following code snippet shows a reference made to a parameter where the VPC ID is stored. You can use this method or input a VPC ID of your choosing.

InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: AWS Ground Station receiver instance security group.
      VpcId: !Ref VpcId 
      SecurityGroupIngress:
        # Allow SSH access from the CIDR block specified in the parameters.
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 10.0.0.0/16
        - IpProtocol: udp
          FromPort: 55888
          ToPort: 55888
          SourceSecurityGroupId: !Ref DataflowEndpointSecurityGroup
          Description: "AWS Ground Station Downlink Stream"

Elastic network interface

DataflowEndpointSecurityGroup

The security group that the elastic network interface created by AWS Ground Station belongs to. By default, this security group allows AWS Ground Station to stream traffic to any IP address in your VPC (hence why three private CIDR ranges are shown). You can modify this in a way that limits traffic to a specific set of IP addresses.

DataflowEndpointSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security Group for AWS Ground Station registration of Dataflow Endpoint Groups
      VpcId: !Ref VpcId
      SecurityGroupEgress:
        - IpProtocol: udp
          FromPort: 55888
          ToPort: 55888
          CidrIp: 10.0.0.0/8
          Description: "AWS Ground Station Downlink Stream To 10/8"
        - IpProtocol: udp
          FromPort: 55888
          ToPort: 55888
          CidrIp: 172.16.0.0/12
          Description: "AWS Ground Station Downlink Stream To 172.16/12"
        - IpProtocol: udp
          FromPort: 55888
          ToPort: 55888
          CidrIp: 192.168.0.0/16
          Description: "AWS Ground Station Downlink Stream To 192.168/16"

ReceiverInstanceNetworkInterface and network interface attachment

The first resource shown (ReceiverInstanceNetworkInterface) is an elastic network interface that provides a fixed IP address for AWS Ground Station to connect to. A fixed IP address is used in this case so that data transfer is not interrupted by a dynamic IP address change.

The second resource (ReceiverInstanceInterfaceAttachment) attaches the network interface to the ReceiverInstance.

ReceiverInstanceNetworkInterface:
    Type: AWS::EC2::NetworkInterface
    Properties:
      Description: Floating network interface providing a fixed IP address for AWS Ground Station to connect to.
      GroupSet:
        - !Ref InstanceSecurityGroup
      SubnetId: !Ref SubnetId
ReceiverInstanceInterfaceAttachment:
    Type: AWS::EC2::NetworkInterfaceAttachment
    Condition: ShouldCreateInstance
    Properties:
      DeleteOnTermination: false
      DeviceIndex: "1"
      InstanceId: !Ref ReceiverInstance
      NetworkInterfaceId: !Ref ReceiverInstanceNetworkInterface

ReceiverInstance

The receiver instance is an EC2 instance that the satellite will send data to. Note that in the UserData section of the code, the Ground Station Agent is installed on this instance. More information on this agent can be found in the links below.

It’s worth noting here that in the following example, the ImageID property is set to ami-06ed42feca6a948c7, which at the time of writing this post, is the most up-to-date Amazon Machine Image (AMI) containing the AWS Ground Station agent. This AWS Ground Station AMI comes preloaded with the software needed to enable data delivery to an Amazon EC2 instance. A custom AMI of your choosing can be used, but Data Defender and other specialized software will need to be installed manually. Data Defender monitors the incoming packets to increase packet integrity.

The EC2 instance defined in this section does not have a Front End (FE) processor or SDR installed by default. You need to install an FE processor or SDR in order to process the VITA-49 packets streamed to and from the AWS Ground Station antenna system.

The following links contain more information on creating Amazon EC2 instances for AWS Ground Station, AWS Ground Station AMIs, and SDRs available on the AWS Marketplace.

ReceiverInstance:
    Type: AWS::EC2::Instance
    Condition: ShouldCreateInstance
    Properties:
      DisableApiTermination: false
      IamInstanceProfile: !Ref GeneralInstanceProfile
      ImageId: ami-06ed42feca6a948c7  
      InstanceType: m5.4xlarge
      KeyName: string
      Monitoring: true
      PlacementGroupName: !Ref ClusterPlacementGroup
      SecurityGroupIds:
        - Ref: InstanceSecurityGroup
      SubnetId: string
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeType: gp2
            VolumeSize: 40
      Tags:
        - Key: Name
          Value: !Join [ "-" , [ "Receiver" , !Ref "AWS::StackName" ] ]
      UserData:
        Fn::Base64: 
          |
          #!/bin/bash
          exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
          echo `date +'%F %R:%S'` "INFO: Logging Setup" >&2

          GROUND_STATION_DIR="/opt/aws/groundstation"
          GROUND_STATION_BIN_DIR="${GROUND_STATION_DIR}/bin"
          STREAM_CONFIG_PATH="${GROUND_STATION_DIR}/customer_stream_config.json"

          echo "Creating ${STREAM_CONFIG_PATH}"
          cat << STREAM_CONFIG > "${STREAM_CONFIG_PATH}"
          {
            "ddx_streams": [
              {
                "streamName": "Downlink",
                "maximumWanRate": 4000000000,
                "lanConfigDevice": "lo",
                "lanConfigPort": 50000,
                "wanConfigDevice": "eth1",
                "wanConfigPort": 55888,
                "isUplink": false
              }
            ]
          }
          STREAM_CONFIG

          echo "Waiting for Data Defender to start"
          while netstat -lnt | awk '$4 ~ /:80$/ {exit 1}'; do sleep 10; done

          echo "Configuring Data Defender streams"
          python "${GROUND_STATION_BIN_DIR}/configure_streams.py" --configFileName "${STREAM_CONFIG_PATH}"
          sleep 2
          python "${GROUND_STATION_BIN_DIR}/save_default_config.py"

          exit 0

Configs

DataflowEndpointGroup

Dataflow endpoint groups are one of the core components of AWS Ground Station. A dataflow endpoint group is composed of individual dataflow endpoints that are used for sending and receiving data to or from your satellite.

DataflowEndpointGroup:
    Type: AWS::GroundStation::DataflowEndpointGroup
    Properties:
      EndpointDetails:
        - Endpoint:
            Name: !Join [ "-" , [ !Ref "AWS::StackName" , "Downlink" ] ]
            Address:
              Name: !GetAtt ReceiverInstanceNetworkInterface.PrimaryPrivateIpAddress
              Port: 55888
          SecurityDetails:
            SecurityGroupIds:
              - Ref: InstanceSecurityGroup
            SubnetIds:
              - Ref: string
            RoleArn: !GetAtt DataDeliveryServiceRole.Arn

TrackingConfig

The TrackingConfig performs the same duty with Amazon EC2 data delivery as it does with Amazon Simple Storage Service (Amazon S3) data delivery. It allows you to specify how you want the position of the satellite tracked during contacts. The options for this parameter are:

  • REMOVED specifies that program track should only be used during the contact.
  • PREFERRED specifies that autotracking is preferred during the contact but falls back to program track if the signal is lost.
  • REQUIRED specifies that automatic tracking is required during the contact and not to use program track if the signal is lost.
TrackingConfig:
    Type: AWS::GroundStation::Config
    Properties:
      Name: "Tracking Config"
      ConfigData:
        TrackingConfig:
          Autotrack: "PREFERRED"

AntennaDownlinkConfig

The AntennaDownlinkConfig performs the same duty with Amazon EC2 data delivery that it does with Amazon S3 data delivery. This type of config specifies certain parameters that will be used to configure the satellite antennae when your data is downlinked from the satellite. Give the config a name and set the desired spectrum bandwidth, center frequency, and polarization units and values.

AntennaDownlinkConfig:
    Type: AWS::GroundStation::Config
    Properties:
      Name: "EC2 Antenna Config"
      ConfigData:
        AntennaDownlinkConfig:
          SpectrumConfig:
            Bandwidth:
              Units: "MHz"
              Value: 0
            CenterFrequency:
              Units: "MHz"
              Value: 0
            Polarization: "RIGHT_HAND"

DataflowEndpointConfig

Dataflow endpoint configs are used to specify which dataflow endpoint in a dataflow endpoint group from which or to which you want data to flow during a contact. The two parameters of a dataflow endpoint config specify the name and Region of the dataflow endpoint. When reserving a contact, AWS Ground Station analyzes the mission profile you specified and attempts to find a dataflow endpoint group that contains all of the dataflow endpoints specified by the dataflow endpoint configs contained in your mission profile.

In the following example, !Join is used to create a dataflow endpoint name using a combination of the AWS CloudFormation stack and Downlink.

DataflowEndpointConfig:
    Type: AWS::GroundStation::Config
    Properties:
      Name: "DF Endpoint Config"
      ConfigData:
        DataflowEndpointConfig:
          DataflowEndpointName: !Join [ "-" , [ !Ref "AWS::StackName" , "Downlink" ] ]
          DataflowEndpointRegion: !Ref AWS::Region

MissionProfile

Mission profiles contain configs and parameters for how contacts are executed. When you reserve a contact or search for available contacts, you supply the mission profile that you intend to use. Mission profiles bring all of your configs together and define how the antenna will be configured and where data will go during your contact.

Properties you will need to specify are:

  • ContactPrePassDurationSeconds – Amount of time prior to contact start you’d like to receive an Amazon CloudWatch event indicating an upcoming pass.
  • ContactPostPassDurationSeconds – Amount of time after a contact ends that you’d like to receive an Amazon CloudWatch event indicating the pass has finished.
  • TrackingConfigArn – The ARN of the desired TrackingConfig.
  • DataflowEdges – This property specifies a source config and destination config for your data during the satellite contact. In this example, the source and destination are the AntennaDownlinkConfig and DataflowEndpointConfig that were explained in the previous section.
MissionProfile:
    Type: AWS::GroundStation::MissionProfile
    Properties:
      Name: "99999 example satellite"
      ContactPrePassDurationSeconds: 120
      ContactPostPassDurationSeconds: 60
      MinimumViableContactDurationSeconds: 180
      TrackingConfigArn: !Ref TrackingConfig
      DataflowEdges:
        - Source: !Ref AntennaDownlinkConfig
          Destination: !Ref DataflowEndpointConfig

Wideband support

Wideband support for DigIF is available in these Regions.

Automation

Amazon EventBridge enables you to automate your AWS services and respond automatically to system events such as application availability issues or resource changes.

Examples of scenarios where this can be used with AWS Ground Station are:

  • Starting the EC2 receiver instance before a satellite contact and stopping the instance after it has processed the data. This will make it so that the instance is only running while it is processing data.
  • Verifying that the receiver instance exists and hasn’t been accidentally deleted.

For more information on the different automation workflows that can be created for AWS Ground Station, refer to Automating AWS Ground Station with Events

Parameters

Throughout this tutorial, I’ve discussed the use of AWS CloudFormation parameters. The following snippet shows what the parameters for VpcId and SubnetId would look like:

Parameters:

  SubnetId:
    Description: Subnet to launch the EC2 receiver instance in. Choose any subnet if you are not creating an EC2 receiver instance.
    Type: AWS::EC2::Subnet::Id

  VpcId:
    Description: VPC to launch the EC2 receiver instance in. Choose any VPC if you are not creating an EC2 receiver instance.
    Type: AWS::EC2::VPC::Id

Terraform

At the time of writing this tutorial, Terraform doesn’t support AWS Ground Station configurations. If you want to use Terraform to deploy AWS Ground Station workloads, there is a way to embed the AWS CloudFormation template into Terraform scripts. Details for this can be found at the Terraform Registry.

Conclusion

Over the course of this blog tutorial, the Amazon CloudFormation syntax for AWS Ground Station was explained, and the three major components of the AWS Ground Station service were reviewed. If you’d like to start using AWS Ground Station in your own AWS account, look through our AWS Ground Station documentation for Amazon EC2 data delivery.

The data delivery mechanism discussed in this blog was Amazon EC2, which is the only data delivery method of the two available that supports real-time streaming of data from satellites. If your data delivery needs do not require real-time streaming, another data delivery method supported is Amazon S3. Stay tuned for part two of this tutorial, which will go into detail about using Amazon S3 data delivery.