AWS Public Sector Blog
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.
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.