Skip to content
This repository was archived by the owner on Jul 11, 2023. It is now read-only.

Commit e873485

Browse files
psibiketzacoatl
authored andcommitted
AWS Managed Microsoft AD directory and Windows EC2 join
1 parent f516155 commit e873485

10 files changed

+504
-0
lines changed

examples/ad-ec2/Makefile

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
.PHONY: init ssh-key plan-vpc plan-subnets plan-gateway plan apply destroy clean
2+
3+
.DEFAULT_GOAL = help
4+
5+
# Hardcoding value of 3 minutes when we check if the plan file is stale
6+
STALE_PLAN_FILE := `find "tf.out" -mmin -3 | grep -q tf.out`
7+
8+
## Check if tf.out is stale (Older than 2 minutes)
9+
check-plan-file:
10+
@if ! ${STALE_PLAN_FILE} ; then \
11+
echo "ERROR: Stale tf.out plan file (older than 3 minutes)!"; \
12+
exit 1; \
13+
fi
14+
15+
## Runs terraform get and terraform init for env
16+
init:
17+
@terraform get
18+
@terraform init
19+
20+
## Create ssh key
21+
ssh-key:
22+
@ssh-keygen -q -N "" -b 4096 -C "SSH key for vpc-scenario-1 example" -f ./id_rsa
23+
24+
## use 'terraform plan' to 'target' the vpc in the vpc module
25+
plan-vpc:
26+
@terraform plan \
27+
-target="module.vpc.module.vpc" \
28+
-out=tf.out
29+
30+
## use 'terraform plan' to 'target' the public subnets in the vpc module
31+
plan-subnets:
32+
@terraform plan \
33+
-target="module.vpc.module.public-subnets" \
34+
-out=tf.out
35+
36+
## use 'terraform plan' to 'target' the public gateway in the vpc module
37+
plan-gateway:
38+
@terraform plan \
39+
-target="module.vpc.module.public-gateway" \
40+
-out=tf.out
41+
42+
## use 'terraform plan' to map out updates to apply
43+
plan:
44+
@terraform plan -out=tf.out
45+
46+
## use 'terraform apply' to apply updates in a 'tf.out' plan file
47+
apply: check-plan-file
48+
@terraform apply tf.out
49+
50+
## use 'terraform destroy' to remove all resources from AWS
51+
destroy:
52+
@terraform destroy
53+
54+
## rm -rf all files and state
55+
clean:
56+
@rm -f tf.out
57+
@rm -f id_rsa
58+
@rm -f id_rsa.pub
59+
@rm -f terraform.tfvars
60+
@rm -f terraform.*.backup
61+
@rm -f terraform.tfstate
62+
63+
## Show help screen.
64+
help:
65+
@echo "Please use \`make <target>' where <target> is one of\n\n"
66+
@awk '/^[a-zA-Z\-\_0-9]+:/ { \
67+
helpMessage = match(lastLine, /^## (.*)/); \
68+
if (helpMessage) { \
69+
helpCommand = substr($$1, 0, index($$1, ":")); \
70+
helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
71+
printf "%-30s %s\n", helpCommand, helpMessage; \
72+
} \
73+
} \
74+
{ lastLine = $$0 }' $(MAKEFILE_LIST)

examples/ad-ec2/README.md

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Active Directory with seamless Windows EC2 join
2+
3+
The terraform code is built on top of
4+
[vpc-scenario1](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Scenario1.html)
5+
with two additional private subnets and a NAT gateway on a public
6+
subnet.
7+
8+
## Environment creation and deployment
9+
10+
To use this example set up AWS credentials and then run the commands in the
11+
following order:
12+
13+
```
14+
make ssh-key
15+
make init
16+
make plan-vpc
17+
make apply
18+
make plan-subnets
19+
make apply
20+
make plan-gateway
21+
make apply
22+
make plan
23+
make apply
24+
```
25+
26+
## Execution
27+
28+
Once you run the above commands, you will get an output like this:
29+
30+
``` shellsession
31+
...
32+
module.nat-gateway.aws_route_table_association.private-rta[0]: Refreshing state... [id=rtbassoc-0be4f2c71ef12e768]
33+
module.nat-gateway.aws_route_table_association.private-rta[1]: Refreshing state... [id=rtbassoc-08a1f878abab73841]
34+
aws_ssm_association.associate_ssm: Refreshing state... [id=996ff9a8-0931-4000-85aa-d01ef536f5a7]
35+
36+
Outputs:
37+
38+
microsoft-ad_dns_ip_addresses = [
39+
"10.23.21.173",
40+
"10.23.22.20",
41+
]
42+
microsoft-ad_dns_name = dev.fpcomplete.local
43+
windows_ec2_public_dns = ec2-3-15-223-193.us-east-2.compute.amazonaws.com
44+
```
45+
46+
## Testing
47+
48+
You need to test that the Windows EC2 instance actually joined the
49+
Active directory. There are two ways to test it:
50+
51+
* RDP to your instance and verify
52+
* RDP using Active Directory authentication
53+
54+
### Method 1
55+
56+
On a Linux client machine, something like
57+
[remmina](https://remmina.org) can be used to RDP into your Windows
58+
EC2 instance. You need to fill three information in the Remmina client
59+
to successfully RDP:
60+
61+
* Server: This will be the output from `windows_ec2_public_dns`
62+
* User name: Administrator
63+
* User password: The password you used with the variable named
64+
`admin_password` in `variables.tf`.
65+
66+
![Remmina settings](./assets/remmina-settings1.png)
67+
68+
Note that if you try to take the password from the AWS Console using
69+
your SSH private key, that won't work as it has been overridden using
70+
[bootstrap.win.txt](./bootstrap.win.txt).
71+
72+
Once you connect into the instance, you need to check the properties
73+
of your machine there:
74+
75+
![System Properties](./assets/system-properties.png)
76+
77+
If you have a `Domain:` entry there, then that means the instance has
78+
successfully joined the Active directory. Instead, if you have an
79+
entry that starts with `Workgroup:` then your device is not joined to an
80+
Active Directory.
81+
82+
### Method 2
83+
84+
In this method, you again try to RDP via the Active directory
85+
credentials. When you create a directory with AWS Managed Microsoft
86+
AD, it will create a directory administrator account with the user
87+
name `Admin` and the specified password (which you supplied through
88+
terraform). Let's again use Remmina to fill the following four
89+
information:
90+
91+
* Server: This will be the output from `windows_ec2_public_dns`
92+
* User name: Admin
93+
* User password: The password you used with the variable named
94+
`active_directory_password` in `variables.tf`.
95+
* Domain: The domain name which you passed in the `locals.tf`. For
96+
this example, it is `dev.fpcomplete.local`.
97+
98+
![Remmina settings](./assets/remmina-settings2.png)
99+
100+
If it's able to successfully connect to the instance, you can confirm
101+
that the EC2 instance has actually joined the AD. You can further verify that you have actually logged in via Active directory through the following steps:
102+
103+
* Start the "CMD" program.
104+
* Type "set user".
105+
* You will recieve a output from the above command. Look at the line
106+
start with `USERDOMAIN:` entry. If it contains your computer's name,
107+
then you're logged in to the computer. If it contains the Active
108+
Directory's name, you're logged in to the Active Directory. In our
109+
case this is the output we receive which confirms that we are logged
110+
in via AD:
111+
112+
``` shellsession
113+
C:\Users\Admin>set user
114+
USERDNSDOMAIN=DEV.FPCOMPLETE.LOCAL
115+
USERDOMAIN=dev
116+
USERDOMAIN_ROAMINGPROFILE=dev
117+
USERNAME=Admin
118+
USERPROFILE=C:\Users\Admin
119+
```
120+
121+
## Destruction
122+
123+
To destroy the test environment run the following commands:
124+
125+
```
126+
$ make destroy
127+
$ make clean
128+
```
129+
130+
## Reference
131+
132+
* [AWS docs on AWS Managed Microsoft AD](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/ms_ad_getting_started.html)
133+
* [AWS docs on Joining an EC2 instance](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/ms_ad_join_instance.html)
134+
* [AWS docss on Systems manager and AD](https://aws.amazon.com/premiumsupport/knowledge-center/ec2-systems-manager-dx-domain/)
53.5 KB
Loading
54.7 KB
Loading
65 KB
Loading

examples/ad-ec2/bootstrap.win.txt

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<powershell>
2+
# Set administrator password
3+
net user Administrator "${admin_password}"
4+
wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE
5+
6+
# First, make sure WinRM can't be connected to
7+
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block
8+
9+
# Delete any existing WinRM listeners
10+
winrm delete winrm/config/listener?Address=*+Transport=HTTP 2>$Null
11+
winrm delete winrm/config/listener?Address=*+Transport=HTTPS 2>$Null
12+
13+
# Create a new WinRM listener and configure
14+
winrm create winrm/config/listener?Address=*+Transport=HTTP
15+
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="0"}'
16+
winrm set winrm/config '@{MaxTimeoutms="7200000"}'
17+
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
18+
winrm set winrm/config/service '@{MaxConcurrentOperationsPerUser="12000"}'
19+
winrm set winrm/config/service/auth '@{Basic="true"}'
20+
winrm set winrm/config/client/auth '@{Basic="true"}'
21+
22+
# Configure UAC to allow privilege elevation in remote shells
23+
$Key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
24+
$Setting = 'LocalAccountTokenFilterPolicy'
25+
Set-ItemProperty -Path $Key -Name $Setting -Value 1 -Force
26+
27+
# Configure and restart the WinRM Service; Enable the required firewall exception
28+
Stop-Service -Name WinRM
29+
Set-Service -Name WinRM -StartupType Automatic
30+
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new action=allow localip=any remoteip=any
31+
Start-Service -Name WinRM
32+
</powershell>

examples/ad-ec2/locals.tf

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
locals {
2+
stage = "dev"
3+
base_domain = "fpcomplete.local"
4+
domain = "${local.stage}.${local.base_domain}"
5+
}

0 commit comments

Comments
 (0)