Securing Remote Desktop Protocol (RDP) access in non-domain environments presents unique challenges for system administrators. When using Amazon AppStream 2.0, organizations often need to provide users with selective network access to specific resources while maintaining a strict security posture. Configuring network-level controls (Security Groups, NACLs) at the fleet level can possibly cast too wide of a net. This article demonstrates how to implement dynamic, user-specific RDP access controls using AppStream 2.0 session scripts, AWS Systems Manager Parameter Store, and Windows Defender Firewall.
The Challenge
In non-domain environments, traditional Group Policy and Active Directory-based controls aren't available. Organizations need to:
Allow access only to specific IP addresses based on user identity
Implement security controls that are dynamic per session
Maintain security without complex infrastructure
Solution Architecture
The solution combines several AWS services and features:
AppStream 2.0 session scripts for execution with SYSTEM privileges
AWS Systems Manager Parameter Store as a secure key value store
Note: We will be using standard string, but consider SecureString for highly sensitive information or for compliance purposes
Windows Defender Firewall for network access control
AppStream 2.0 fleet IAM roles to securely access AWS resources
User's submit access requests for a bastion host, that is accessible to various servers
Implementation
1. SSM Parameter Store Configuration
While AppStream 2.0 offers a 'Session Context' feature, this data cannot be used directly within Session Scripts. If you only need to pass data as environment variables after the session script executes, consider using Session Context instead of this solution.
In a real-world scenario, SSM Parameters would be created programmatically as part of a larger request pipeline. For this example, we can go ahead and create one manually.
Within AWS SSM Parameter store, create a new key value text pair following this structure:
Value format:
IP.adddr1-IP.addr2-IP.addr3 (hyphen-separated IP addresses)
2. IAM Role Configuration
AppStream fleets can (optionally) be configured to inherit a single IAM role. In our case, session scripts need to be able to retrieve values from SSM Parameter store.
Create a new IAM role with the following IAM Policy attached, and then assign it to your AppStream fleet (fleet must be in the stopped state):
Replace region and account-id
Modify the Trust relationship of the IAM role to allow the appstream service to assume the role:
3. Session Script Implementation
The session script performs these key functions:
Identifies the current user from registry
In this script, we assume the user-id value passed along the CreateStreamingURL API matches the key value of our SSM Parameter
Retrieves allowed IPs from SSM Parameter Store
This is seen as a delimited list of IPs. Our script is using the (-) delimiter to parse the list and add it to an array, which will be iterated through to add our firewall rules
Configures Windows Firewall rules
In order to restrict outbound network access in Windows Defender Firewall, we must first set the Default Behavior to "Block" instead of "Allow".
Since we only care about blocking RDP access, we will then immediately add additional rules to Allow TCP and UDP traffic on all ports besides 3389.
Only IP addresses contained within our SSM Parameter for the given user will be allowed as valid RDP destination hosts - regardless of what our security groups/NACLs are allowing.
Follow our public documentation for steps detailing how/where to configure the Session script. The contents of the script can be found below.
Testing the Solution
Create an SSM Parameter with a key name of your appstream user, and value of a list of IP addresses
Call the CreateStreamingURL API, and be sure to specify the same user-id value as your SSM Parameter user key. Paste the returned access URL into your browser.
Once connected to the fleet, open notepad or file explorer and navigate to the session script log location: C:\AppStream\SessionScripts\logs\SessionStart
Open the log file ending in -stdout to view the script output. You should see the verbose logging details from the script showing each step of the process
Lastly, open mstsc.exe and attempt to establish an RDP connection to one of the IP addresses you allow-listed, and compare that to an IP address of a host you did not allow-list. (The allow-list should immediately bring up the RDP username and password dialog box).
Security Considerations
Principle of Least Privilege
Firewall blocks all outbound RDP by default
Specific allow rules only for authorized IPs
Parameter Security
Sensitive SSM parameters should use SecureString type
IAM roles limited to specific parameter paths
Parameter naming convention enables granular access control
Execution Context
Script runs with SYSTEM privileges
User identification via registry values
Firewall rules specific to RDP application
Best Practices
Parameter Management
Use consistent naming conventions
Regular auditing of parameters
Clean up unused parameters
Error Handling
Validate IP addresses via Regex
Maintain default-deny state in case of script errors
Monitoring and Logging
Log script execution results
Monitor firewall rule changes
Use CloudTrail to track access requests to SSM and AppStream
Limitations and Considerations
60-second session script timeout
Non-persistent nature of AppStream instances
Consider integrating session scripts with storage connector for advanced use cases
AWS CLI performance advantages over PowerShell modules
Alternative Approaches
The solution detailed in this article isn't needed for every use case. Before considering this approach, identify whether your network security requirements can be met via any of the below:
Network-level controls (Security Groups, NACLs)
VPN or Direct Connect for network isolation
Third-party remote access solutions
Conclusion
This solution provides secure, manageable RDP access control for AppStream 2.0 environments without requiring Active Directory integration. By leveraging AWS services and Windows features, organizations can implement granular access controls while maintaining security and usability.
Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.