AD FS example
This commit is contained in:
parent
f42b0f06e4
commit
68e56058ab
|
@ -32,3 +32,5 @@ cloud_sql_proxy
|
||||||
examples/cloud-operations/binauthz/tenant-setup.yaml
|
examples/cloud-operations/binauthz/tenant-setup.yaml
|
||||||
examples/cloud-operations/binauthz/app/app.yaml
|
examples/cloud-operations/binauthz/app/app.yaml
|
||||||
env/
|
env/
|
||||||
|
examples/cloud-operations/adfs/ansible/vars/vars.yaml
|
||||||
|
examples/cloud-operations/adfs/ansible/gssh.sh
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
# AD FS
|
||||||
|
|
||||||
|
This example does the following:
|
||||||
|
|
||||||
|
Terraform:
|
||||||
|
|
||||||
|
- (Optional) Creates a project.
|
||||||
|
- (Optional) Creates a VPC.
|
||||||
|
- Sets up managed AD
|
||||||
|
- Creates a server where AD FS will be installed. This machine will also act as admin workstation for AD.
|
||||||
|
- Exposes AD FS using GLB.
|
||||||
|
|
||||||
|
Ansible:
|
||||||
|
|
||||||
|
- Installs the required Windows features and joins the computer to the AD domain.
|
||||||
|
- Provisions some tests users, groups and group memberships in AD. The data to provision is in the ifles directory of the ad-provisioning ansible role. There is script available in the scripts/ad-provisioning folder that you can use to generate an alternative users or memberships file.
|
||||||
|
- Installs AD FS
|
||||||
|
|
||||||
|
In addition to this, we also include a Powershell script that facilitates the configuration required for Anthos when authenticating users with AD FS as IdP.
|
||||||
|
|
||||||
|
The diagram below depicts the architecture of the example:
|
||||||
|
|
||||||
|
![Architecture](architecture.png)
|
||||||
|
|
||||||
|
## Running the example
|
||||||
|
|
||||||
|
Clone this repository or [open it in cloud shell](https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fcloud-foundation-fabric&cloudshell_print=cloud-shell-readme.txt&cloudshell_working_dir=examples%2Fcloud-operations%2Fadfs), then go through the following steps to create resources:
|
||||||
|
|
||||||
|
* `terraform init`
|
||||||
|
* `terraform apply -var project_id=my-project-id -var ad_dns_domain_name=my-domain.org -var adfs_dns_domain_name=adfs.my-domain.org`
|
||||||
|
|
||||||
|
Once the resources have been created, do the following:
|
||||||
|
|
||||||
|
1. Create an A record to point the AD FS DNS domain name to the public IP address returned after the terraform configuration was applied.
|
||||||
|
2. Run the ansible playbook
|
||||||
|
|
||||||
|
ansible-playbook playbook.yaml
|
||||||
|
|
||||||
|
# Testing the example
|
||||||
|
|
||||||
|
1. In your browser open the following URL:
|
||||||
|
|
||||||
|
https://adfs.my-domain.org/adfs/ls/IdpInitiatedSignOn.aspx
|
||||||
|
|
||||||
|
2. Enter the username and password of one of the users provisioned. The username has to be in the format: username@my-domain.org
|
||||||
|
3. Verify that you have successfuly signed in.
|
||||||
|
|
||||||
|
Once done testing, you can clean up resources by running `terraform destroy`.
|
||||||
|
<!-- BEGIN TFDOC -->
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
| name | description | type | required | default |
|
||||||
|
|---|---|:---:|:---:|:---:|
|
||||||
|
| [ad_dns_domain_name](variables.tf#L44) | AD DNS domain name. | <code>string</code> | ✓ | |
|
||||||
|
| [adfs_dns_domain_name](variables.tf#L49) | ADFS DNS domain name. | <code>string</code> | ✓ | |
|
||||||
|
| [project_id](variables.tf#L24) | Host project ID. | <code>string</code> | ✓ | |
|
||||||
|
| [ad_ip_cidr_block](variables.tf#L90) | Managed AD IP CIDR block. | <code>string</code> | | <code>"10.0.0.0/24"</code> |
|
||||||
|
| [disk_size](variables.tf#L54) | Disk size. | <code>number</code> | | <code>50</code> |
|
||||||
|
| [disk_type](variables.tf#L60) | Disk type. | <code>string</code> | | <code>"pd-ssd"</code> |
|
||||||
|
| [image](variables.tf#L66) | Image. | <code>string</code> | | <code>"projects/windows-cloud/global/images/family/windows-2022"</code> |
|
||||||
|
| [instance_type](variables.tf#L72) | Instance type. | <code>string</code> | | <code>"n1-standard-2"</code> |
|
||||||
|
| [network_config](variables.tf#L35) | Network configuration | <code title="object({ network = string subnet = string })">object({…})</code> | | <code>null</code> |
|
||||||
|
| [prefix](variables.tf#L29) | Prefix for the resources created. | <code>string</code> | | <code>null</code> |
|
||||||
|
| [project_create](variables.tf#L15) | Parameters for the creation of the new project. | <code title="object({ billing_account_id = string parent = string })">object({…})</code> | | <code>null</code> |
|
||||||
|
| [region](variables.tf#L78) | Region. | <code>string</code> | | <code>"europe-west1"</code> |
|
||||||
|
| [subnet_ip_cidr_block](variables.tf#L96) | Subnet IP CIDR block. | <code>string</code> | | <code>"10.0.1.0/28"</code> |
|
||||||
|
| [zone](variables.tf#L84) | Zone. | <code>string</code> | | <code>"europe-west1-c"</code> |
|
||||||
|
|
||||||
|
## Outputs
|
||||||
|
|
||||||
|
| name | description | sensitive |
|
||||||
|
|---|---|:---:|
|
||||||
|
| [ip_address](outputs.tf#L15) | IP address. | |
|
||||||
|
|
||||||
|
<!-- END TFDOC -->
|
|
@ -0,0 +1,8 @@
|
||||||
|
[defaults]
|
||||||
|
inventory = inventory/hosts.ini
|
||||||
|
|
||||||
|
[ssh_connection]
|
||||||
|
pipelining = True
|
||||||
|
ssh_executable = ./gssh.sh
|
||||||
|
transfer_method = piped
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
adfs ansible_connection=ssh ansible_shell_type=powershell
|
|
@ -0,0 +1,53 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
- name: Prepare
|
||||||
|
hosts: adfs
|
||||||
|
gather_facts: yes
|
||||||
|
vars_files:
|
||||||
|
- vars/vars.yaml
|
||||||
|
roles:
|
||||||
|
- role: server-setup
|
||||||
|
|
||||||
|
- name: Provision organizational units users, groups and memberships
|
||||||
|
hosts: adfs
|
||||||
|
gather_facts: no
|
||||||
|
vars_files:
|
||||||
|
- vars/vars.yaml
|
||||||
|
vars:
|
||||||
|
ansible_become: yes
|
||||||
|
ansible_become_method: runas
|
||||||
|
ansible_become_user: "SetupAdmin@{{ ad_dns_domain_name }}"
|
||||||
|
ansible_become_password: "{{ setupadmin_password }}"
|
||||||
|
roles:
|
||||||
|
- role: ad-provisioning
|
||||||
|
|
||||||
|
- name: Install AD FS
|
||||||
|
hosts: adfs
|
||||||
|
gather_facts: no
|
||||||
|
vars_files:
|
||||||
|
- vars/vars.yaml
|
||||||
|
vars:
|
||||||
|
ansible_become: yes
|
||||||
|
ansible_become_method: runas
|
||||||
|
adfssvc_password: "{{ lookup('ansible.builtin.password', '~/.adfssvc-password.txt chars=ascii_letters,digits') }}"
|
||||||
|
roles:
|
||||||
|
- role: adfs-prerequisites
|
||||||
|
vars:
|
||||||
|
ansible_become_user: "SetupAdmin@{{ ad_dns_domain_name }}"
|
||||||
|
ansible_become_password: "{{ setupadmin_password }}"
|
||||||
|
- role: adfs-installation
|
||||||
|
vars:
|
||||||
|
ansible_become_user: "adfssvc@{{ ad_dns_domain_name }}"
|
||||||
|
ansible_become_password: "{{ adfssvc_password }}"
|
|
@ -0,0 +1,8 @@
|
||||||
|
[
|
||||||
|
"gcp-billing-admins",
|
||||||
|
"gcp-devops",
|
||||||
|
"gcp-network-admins",
|
||||||
|
"gcp-organization-admins",
|
||||||
|
"gcp-security-admins",
|
||||||
|
"gcp-support"
|
||||||
|
]
|
|
@ -0,0 +1,82 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"group": "gcp-devops",
|
||||||
|
"member": "pamela.reed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-devops",
|
||||||
|
"member": "joshua.banks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-devops",
|
||||||
|
"member": "clayton.espinoza"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-devops",
|
||||||
|
"member": "maureen.morgan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-network-admins",
|
||||||
|
"member": "pamela.reed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-network-admins",
|
||||||
|
"member": "william.bowen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-network-admins",
|
||||||
|
"member": "clayton.espinoza"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-network-admins",
|
||||||
|
"member": "stacy.holland"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-network-admins",
|
||||||
|
"member": "joshua.banks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-network-admins",
|
||||||
|
"member": "charlene.mckenzie"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-network-admins",
|
||||||
|
"member": "lisa.harris"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-organization-admins",
|
||||||
|
"member": "maureen.morgan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-organization-admins",
|
||||||
|
"member": "pamela.reed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-support",
|
||||||
|
"member": "maureen.morgan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-support",
|
||||||
|
"member": "pamela.reed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-support",
|
||||||
|
"member": "lisa.harris"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-support",
|
||||||
|
"member": "tina.ferguson"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-support",
|
||||||
|
"member": "stacy.holland"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-support",
|
||||||
|
"member": "william.bowen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "gcp-support",
|
||||||
|
"member": "clayton.espinoza"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,56 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"first_name": "Pamela",
|
||||||
|
"last_name": "Reed",
|
||||||
|
"username": "pamela.reed",
|
||||||
|
"password": "Ig_17BbZVu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_name": "Charlene",
|
||||||
|
"last_name": "Mckenzie",
|
||||||
|
"username": "charlene.mckenzie",
|
||||||
|
"password": "$y0IsMLPy5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_name": "William",
|
||||||
|
"last_name": "Bowen",
|
||||||
|
"username": "william.bowen",
|
||||||
|
"password": "y882QxMHE@"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_name": "Joshua",
|
||||||
|
"last_name": "Banks",
|
||||||
|
"username": "joshua.banks",
|
||||||
|
"password": ")00+LN!r0$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_name": "Clayton",
|
||||||
|
"last_name": "Espinoza",
|
||||||
|
"username": "clayton.espinoza",
|
||||||
|
"password": "gIf@52FqUY"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_name": "Stacy",
|
||||||
|
"last_name": "Holland",
|
||||||
|
"username": "stacy.holland",
|
||||||
|
"password": "da4PLSQDb^"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_name": "Maureen",
|
||||||
|
"last_name": "Morgan",
|
||||||
|
"username": "maureen.morgan",
|
||||||
|
"password": "V)c2Vfc%i#"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_name": "Lisa",
|
||||||
|
"last_name": "Harris",
|
||||||
|
"username": "lisa.harris",
|
||||||
|
"password": "0@1Oid71co"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_name": "Tina",
|
||||||
|
"last_name": "Ferguson",
|
||||||
|
"username": "tina.ferguson",
|
||||||
|
"password": "+f#0C#_oi6"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
- name: Read files
|
||||||
|
set_fact:
|
||||||
|
ad_users: "{{ lookup('file','users.json') | from_json }}"
|
||||||
|
ad_groups: "{{ lookup('file','groups.json') | from_json }}"
|
||||||
|
ad_memberships: "{{ lookup('file','memberships.json') | from_json }}"
|
||||||
|
|
||||||
|
- name: Create organizational units
|
||||||
|
community.windows.win_domain_ou:
|
||||||
|
name: "{{ item }}"
|
||||||
|
path: "{{ cloud_path }}"
|
||||||
|
state: present
|
||||||
|
protected: true
|
||||||
|
with_items:
|
||||||
|
- "Users"
|
||||||
|
- "Groups"
|
||||||
|
|
||||||
|
- name: Create users
|
||||||
|
community.windows.win_domain_user:
|
||||||
|
name: "{{ item.username }}"
|
||||||
|
firstname: "{{ item.first_name }}"
|
||||||
|
surname: "{{ item.last_name }}"
|
||||||
|
email: "{{ item.username }}@{{ ad_dns_domain_name }}"
|
||||||
|
sam_account_name: "{{ item.username }}"
|
||||||
|
upn: "{{ item.username }}@{{ ad_dns_domain_name }}"
|
||||||
|
password: "{{ item.password }}"
|
||||||
|
path: "OU=Users,{{ cloud_path }}"
|
||||||
|
state: present
|
||||||
|
with_items: "{{ ad_users }}"
|
||||||
|
|
||||||
|
- name: Create groups
|
||||||
|
community.windows.win_domain_group:
|
||||||
|
name: "{{ item }}"
|
||||||
|
path: "OU=Groups,{{ cloud_path }}"
|
||||||
|
scope: global
|
||||||
|
state: present
|
||||||
|
with_items: "{{ ad_groups }}"
|
||||||
|
|
||||||
|
- name: Create memberships
|
||||||
|
community.windows.win_domain_group_membership:
|
||||||
|
name: "{{ item.group }}"
|
||||||
|
members:
|
||||||
|
- "{{ item.member }}"
|
||||||
|
state: present
|
||||||
|
with_items: "{{ ad_memberships }}"
|
|
@ -0,0 +1,104 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
- name: Create server certificate
|
||||||
|
ansible.windows.win_powershell:
|
||||||
|
script: |
|
||||||
|
$Certificate = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -eq "CN={{ adfs_dns_domain_name }}"}
|
||||||
|
if(-not $Certificate) {
|
||||||
|
$Certificate = New-SelfSignedCertificate `
|
||||||
|
-Subject {{ adfs_dns_domain_name }} `
|
||||||
|
-KeyAlgorithm RSA `
|
||||||
|
-KeyLength 2048 `
|
||||||
|
-KeyExportPolicy NonExportable `
|
||||||
|
-KeyUsage DigitalSignature, KeyEncipherment `
|
||||||
|
-Provider 'Microsoft Platform Crypto Provider' `
|
||||||
|
-NotAfter (Get-Date).AddDays(365) `
|
||||||
|
-Type SSLServerAuthentication `
|
||||||
|
-CertStoreLocation 'Cert:\LocalMachine\My' `
|
||||||
|
-DnsName {{ adfs_dns_domain_name }}
|
||||||
|
}
|
||||||
|
$Certificate.Thumbprint
|
||||||
|
register: server_cert
|
||||||
|
|
||||||
|
- name: Create token signing certificate
|
||||||
|
ansible.windows.win_powershell:
|
||||||
|
script: |
|
||||||
|
$Certificate = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -eq "CN=ADFS Signing"}
|
||||||
|
if(-not $Certificate) {
|
||||||
|
$Certificate = New-SelfSignedCertificate `
|
||||||
|
-Subject "ADFS Signing" `
|
||||||
|
-KeyAlgorithm RSA `
|
||||||
|
-KeyLength 2048 `
|
||||||
|
-KeyExportPolicy NonExportable `
|
||||||
|
-KeyUsage DigitalSignature, KeyEncipherment `
|
||||||
|
-Provider 'Microsoft RSA SChannel Cryptographic Provider' `
|
||||||
|
-NotAfter (Get-Date).AddDays(365) `
|
||||||
|
-DnsName {{ adfs_dns_domain_name }} `
|
||||||
|
-CertStoreLocation 'Cert:\LocalMachine\My'
|
||||||
|
}
|
||||||
|
$Certificate.Thumbprint
|
||||||
|
register: token_signing_cert
|
||||||
|
|
||||||
|
- name: Create AD FS DKM container
|
||||||
|
ansible.windows.win_powershell:
|
||||||
|
script: |
|
||||||
|
$DkmContainer = Get-ADObject -LDAPFilter "(Objectclass=container)" -SearchBase "CN=ADFS Data,{{ cloud_path }}" -SearchScope 1
|
||||||
|
if(-not $DkmContainer) {
|
||||||
|
$DkmContainer.DistinguishedName
|
||||||
|
$Name = (New-Guid).Guid
|
||||||
|
$DkmContainer = New-ADObject `
|
||||||
|
-Name $Name `
|
||||||
|
-Type Container `
|
||||||
|
-Path "CN=ADFS Data,{{ cloud_path }}" `
|
||||||
|
-PassThru
|
||||||
|
}
|
||||||
|
$DkmContainer.DistinguishedName
|
||||||
|
register: adfs_dkm_container
|
||||||
|
|
||||||
|
- name: Install ADFS
|
||||||
|
ansible.windows.win_powershell:
|
||||||
|
script: |
|
||||||
|
try {
|
||||||
|
$AdfsFarm = Get-AdfsFarmInformation
|
||||||
|
} catch [System.ServiceModel.EndpointNotFoundException] {
|
||||||
|
$AdfsCredential = New-Object `
|
||||||
|
-TypeName System.Management.Automation.PSCredential `
|
||||||
|
-ArgumentList "$env:userdomain\adfssvc", (ConvertTo-SecureString {{ adfssvc_password }} -AsPlainText -Force)
|
||||||
|
Install-ADFSFarm `
|
||||||
|
-CertificateThumbprint {{ server_cert.output[0] }} `
|
||||||
|
-SigningCertificateThumbprint {{ token_signing_cert.output[0] }} `
|
||||||
|
-DecryptionCertificateThumbprint {{ token_signing_cert.output[0] }}`
|
||||||
|
-FederationServiceName {{ adfs_dns_domain_name }} `
|
||||||
|
-ServiceAccountCredential $AdfsCredential `
|
||||||
|
-OverwriteConfiguration `
|
||||||
|
-AdminConfiguration @{"DKMContainerDn"="{{ adfs_dkm_container.output[0] }}"}
|
||||||
|
}
|
||||||
|
no_log: yes
|
||||||
|
|
||||||
|
- name: Configure TLS
|
||||||
|
ansible.windows.win_powershell:
|
||||||
|
script: |
|
||||||
|
netsh http show sslcert ipport=0.0.0.0:443
|
||||||
|
if($LastExitCode -gt 0) {
|
||||||
|
netsh http add sslcert ipport=0.0.0.0:443 certhash={{ server_cert.output[0] }} appid="{5d89a20c-beab-4389-9447-324788eb944a}" certstorename=MY
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Restart computer
|
||||||
|
ansible.windows.win_reboot:
|
||||||
|
|
||||||
|
- name: Enable the Idp-Initiated Sign on page
|
||||||
|
ansible.windows.win_powershell:
|
||||||
|
script: |
|
||||||
|
Set-AdfsProperties -EnableIdpInitiatedSignonPage $true
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
- name: Create AD FS service user
|
||||||
|
community.windows.win_domain_user:
|
||||||
|
name: "adfssvc"
|
||||||
|
password: "{{ adfssvc_password }}"
|
||||||
|
spn: "http/{{ adfs_dns_domain_name }}"
|
||||||
|
path: "OU=Users,{{ cloud_path }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Add AD FS service user to local Administrators group
|
||||||
|
ansible.windows.win_group_membership:
|
||||||
|
name: Administrators
|
||||||
|
members:
|
||||||
|
- "adfssvc@{{ ad_dns_domain_name }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create AD FS Data container
|
||||||
|
ansible.windows.win_powershell:
|
||||||
|
script: |
|
||||||
|
try {
|
||||||
|
Get-ADObject -Identity "CN=ADFS Data,{{ cloud_path }}"
|
||||||
|
} catch [Microsoft.ActiveDirectory.Management.ADIdentityResolutionException] {
|
||||||
|
New-ADObject `
|
||||||
|
-Name "ADFS Data" `
|
||||||
|
-Type Container `
|
||||||
|
-Path "{{ cloud_path }}"
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Grant the AD FS user full control on the container
|
||||||
|
ansible.windows.win_powershell:
|
||||||
|
script: |
|
||||||
|
dsacls.exe "CN=ADFS Data,{{ cloud_path }}" /G $env:userdomain\adfssvc:GA /I:T
|
|
@ -0,0 +1,67 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
$ApplicationGroup = Get-AdfsApplicationGroup -Name Anthos
|
||||||
|
|
||||||
|
$ApplicationGroupName = "Anthos"
|
||||||
|
$ApplicationGroupIdentifier = (New-Guid).Guid
|
||||||
|
New-AdfsApplicationGroup -Name $ApplicationGroupName `
|
||||||
|
-ApplicationGroupIdentifier $ApplicationGroupIdentifier
|
||||||
|
|
||||||
|
$ServerApplicationName = "$ApplicationGroupName Server App"
|
||||||
|
$ServerApplicationIdentifier = (New-Guid).Guid
|
||||||
|
$RelyingPartyTrustName = "Anthos"
|
||||||
|
$RelyingPartyTrustIdentifier = (New-Guid).Guid
|
||||||
|
$RedirectURI1 = "http://localhost:1025/callback"
|
||||||
|
$RedirectURI2 = "https://console.cloud.google.com/kubernetes/oidc"
|
||||||
|
|
||||||
|
$ADFSApp = Add-AdfsServerApplication -Name $ServerApplicationName `
|
||||||
|
-ApplicationGroupIdentifier $ApplicationGroupIdentifier `
|
||||||
|
-RedirectUri $RedirectURI1,$RedirectURI2 `
|
||||||
|
-Identifier $ServerApplicationIdentifier `
|
||||||
|
-GenerateClientSecret
|
||||||
|
|
||||||
|
$IssuanceTransformRules = @'
|
||||||
|
@RuleTemplate = "LdapClaims"
|
||||||
|
@RuleName = "groups"
|
||||||
|
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
|
||||||
|
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/claims/Group"), query = ";tokenGroups(domainQualifiedName);{0}", param = c.Value);
|
||||||
|
'@
|
||||||
|
|
||||||
|
Add-AdfsRelyingPartyTrust -Name $RelyingPartyTrustName `
|
||||||
|
-Identifier $RelyingPartyTrustIdentifier `
|
||||||
|
-AccessControlPolicyName "Permit everyone" `
|
||||||
|
-IssuanceTransformRules "$IssuanceTransformRules"
|
||||||
|
|
||||||
|
Grant-ADFSApplicationPermission -ClientRoleIdentifier $ServerApplicationIdentifier `
|
||||||
|
-ServerRoleIdentifier $RelyingPartyTrustIdentifier `
|
||||||
|
-ScopeName "allatclaims", "openid"
|
||||||
|
|
||||||
|
$ClientId = $ADFSApp.Identifier
|
||||||
|
$ClientSecret = $ADFSApp.ClientSecret
|
||||||
|
|
||||||
|
@"
|
||||||
|
authentication:
|
||||||
|
oidc:
|
||||||
|
clientID: $ADFSApp.Identifier
|
||||||
|
clientSecret: $ADFSApp.ClientSecret
|
||||||
|
extraParams: resource=$RelyingPartyTrustIdentifier
|
||||||
|
group: groups
|
||||||
|
groupPrefix: ""
|
||||||
|
issuerURI: https://{{ adfs_dns_domain_name }}/adfs
|
||||||
|
kubectlRedirectURL: $RedirectURI1
|
||||||
|
scopes: openid
|
||||||
|
username: upn
|
||||||
|
usernamePrefix: ""
|
||||||
|
"@
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
- name: Install Windows features
|
||||||
|
ansible.windows.win_feature:
|
||||||
|
name: "{{ item.feature }}"
|
||||||
|
include_mamangement_tools: "{{ item.include_management_tools }}"
|
||||||
|
state: present
|
||||||
|
with_items:
|
||||||
|
- { "feature": "RSAT-AD-Tools", "include_management_tools": false }
|
||||||
|
- { "feature": "GPMC", "include_management_tools": false }
|
||||||
|
- { "feature": "RSAT-DNS-Server", "include_management_tools": false }
|
||||||
|
- { "feature": "ADFS-Federation", "include_management_tools": true }
|
||||||
|
- { "feature": "RSAT-AD-PowerShell", "include_management_tools": false }
|
||||||
|
- { "feature": "RSAT-ADDS-Tools", "include_management_tools": false }
|
||||||
|
|
||||||
|
- name: Check if SetupAdmin password has already been reset
|
||||||
|
stat:
|
||||||
|
path: ~/.setupadmin-password.txt
|
||||||
|
register: setupadmin_password_file_check
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Set AD SetupAdmin password fact
|
||||||
|
set_fact:
|
||||||
|
setupadmin_password: "{{ lookup('file', '~/.setupadmin-password.txt') }}"
|
||||||
|
no_log: true
|
||||||
|
when: setupadmin_password_file_check.stat.exists
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Reset AD deletegated admin password
|
||||||
|
shell: >
|
||||||
|
gcloud active-directory domains reset-admin-password {{ ad_dns_domain_name }}
|
||||||
|
--project={{ project_id }}
|
||||||
|
--quiet
|
||||||
|
--format "value(password)"
|
||||||
|
register: setupadmin_password_reset
|
||||||
|
no_log: yes
|
||||||
|
when: not setupadmin_password_file_check.stat.exists
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Set AD SetupAdmin password fact
|
||||||
|
set_fact:
|
||||||
|
setupadmin_password: "{{ setupadmin_password_reset.stdout }}"
|
||||||
|
no_log: yes
|
||||||
|
when: not setupadmin_password_file_check.stat.exists
|
||||||
|
|
||||||
|
- name: Creating a file setupadmin password
|
||||||
|
copy:
|
||||||
|
dest: ~/.setupadmin-password.txt
|
||||||
|
content: "{{ setupadmin_password }}"
|
||||||
|
when: not setupadmin_password_file_check.stat.exists
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Add computer to domain
|
||||||
|
ansible.windows.win_domain_membership:
|
||||||
|
dns_domain_name: "{{ ad_dns_domain_name }}"
|
||||||
|
domain_admin_user: "SetupAdmin@{{ ad_dns_domain_name }}"
|
||||||
|
domain_admin_password: "{{ setupadmin_password }}"
|
||||||
|
state: domain
|
||||||
|
register: domain_state
|
||||||
|
|
||||||
|
- name: Restart computer
|
||||||
|
ansible.windows.win_reboot:
|
||||||
|
when: domain_state.reboot_required
|
||||||
|
|
||||||
|
- name: Get Domain info
|
||||||
|
community.windows.win_domain_object_info:
|
||||||
|
filter: ObjectClass -eq 'domain'
|
||||||
|
domain_username: "SetupAdmin@{{ ad_dns_domain_name }}"
|
||||||
|
domain_password: "{{ setupadmin_password }}"
|
||||||
|
register: ad_domain
|
||||||
|
|
||||||
|
- name: Set facts
|
||||||
|
set_fact:
|
||||||
|
cloud_path: "OU=Cloud,{{ ad_domain.objects[0].DistinguishedName }}"
|
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
|
@ -0,0 +1,191 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
locals {
|
||||||
|
prefix = (var.prefix == null || var.prefix == "") ? "" : "${var.prefix}-"
|
||||||
|
}
|
||||||
|
|
||||||
|
module "project" {
|
||||||
|
source = "../../../modules/project"
|
||||||
|
billing_account = (
|
||||||
|
var.project_create != null
|
||||||
|
? var.project_create.billing_account_id
|
||||||
|
: null
|
||||||
|
)
|
||||||
|
parent = (
|
||||||
|
var.project_create != null
|
||||||
|
? var.project_create.parent
|
||||||
|
: null
|
||||||
|
)
|
||||||
|
prefix = var.project_create == null ? null : var.prefix
|
||||||
|
name = var.project_id
|
||||||
|
services = [
|
||||||
|
"compute.googleapis.com",
|
||||||
|
"dns.googleapis.com",
|
||||||
|
"managedidentities.googleapis.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
module "vpc" {
|
||||||
|
count = var.network_config == null ? 1 : 0
|
||||||
|
source = "../../../modules/net-vpc"
|
||||||
|
project_id = module.project.project_id
|
||||||
|
name = "${local.prefix}vpc"
|
||||||
|
subnets = [
|
||||||
|
{
|
||||||
|
ip_cidr_range = var.subnet_ip_cidr_block
|
||||||
|
name = "subnet"
|
||||||
|
region = var.region
|
||||||
|
secondary_ip_range = null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_active_directory_domain" "ad_domain" {
|
||||||
|
project = module.project.project_id
|
||||||
|
domain_name = var.ad_dns_domain_name
|
||||||
|
locations = [var.region]
|
||||||
|
authorized_networks = [module.vpc[0].network.id]
|
||||||
|
reserved_ip_range = var.ad_ip_cidr_block
|
||||||
|
}
|
||||||
|
|
||||||
|
module "server" {
|
||||||
|
source = "../../../modules/compute-vm"
|
||||||
|
project_id = module.project.project_id
|
||||||
|
zone = var.zone
|
||||||
|
name = "adfs"
|
||||||
|
instance_type = var.instance_type
|
||||||
|
network_interfaces = [{
|
||||||
|
network = var.network_config == null ? module.vpc[0].self_link : var.network_config.network
|
||||||
|
subnetwork = var.network_config == null ? module.vpc[0].subnet_self_links["${var.region}/subnet"] : var.network_config.subnet
|
||||||
|
nat = false
|
||||||
|
addresses = null
|
||||||
|
}]
|
||||||
|
metadata = {
|
||||||
|
# Enables OpenSSH in the Windows instance
|
||||||
|
sysprep-specialize-script-cmd = "googet -noconfirm=true update && googet -noconfirm=true install google-compute-engine-ssh"
|
||||||
|
enable-windows-ssh = "TRUE"
|
||||||
|
# Set the default OpenSSH shell to Powershell
|
||||||
|
windows-startup-script-ps1 = <<EOT
|
||||||
|
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" `
|
||||||
|
-Name DefaultShell `
|
||||||
|
-Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" `
|
||||||
|
-PropertyType String `
|
||||||
|
-Force
|
||||||
|
EOT
|
||||||
|
}
|
||||||
|
service_account_create = true
|
||||||
|
boot_disk = {
|
||||||
|
image = var.image
|
||||||
|
type = var.disk_type
|
||||||
|
size = var.disk_size
|
||||||
|
}
|
||||||
|
group = {
|
||||||
|
named_ports = {
|
||||||
|
http = 443
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tags = ["https-server"]
|
||||||
|
}
|
||||||
|
|
||||||
|
module "glb" {
|
||||||
|
source = "../../../modules/net-glb"
|
||||||
|
name = "${local.prefix}glb"
|
||||||
|
project_id = module.project.project_id
|
||||||
|
|
||||||
|
https = true
|
||||||
|
reserve_ip_address = true
|
||||||
|
|
||||||
|
ssl_certificates_config = {
|
||||||
|
adfs-domain = {
|
||||||
|
domains = [
|
||||||
|
"${var.adfs_dns_domain_name}"
|
||||||
|
],
|
||||||
|
unmanaged_config = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target_proxy_https_config = {
|
||||||
|
ssl_certificates = [
|
||||||
|
"adfs-domain"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
backend_services_config = {
|
||||||
|
adfs-group-backend = {
|
||||||
|
bucket_config = null
|
||||||
|
enable_cdn = false
|
||||||
|
cdn_config = null
|
||||||
|
group_config = {
|
||||||
|
backends = [
|
||||||
|
{
|
||||||
|
group = module.server.group.id
|
||||||
|
options = null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
health_checks = ["hc"]
|
||||||
|
log_config = {
|
||||||
|
enable = true
|
||||||
|
sample_rate = 1
|
||||||
|
}
|
||||||
|
options = {
|
||||||
|
affinity_cookie_ttl_sec = null
|
||||||
|
custom_request_headers = null
|
||||||
|
custom_response_headers = null
|
||||||
|
connection_draining_timeout_sec = null
|
||||||
|
load_balancing_scheme = null
|
||||||
|
locality_lb_policy = null
|
||||||
|
port_name = null
|
||||||
|
security_policy = null
|
||||||
|
session_affinity = null
|
||||||
|
timeout_sec = null
|
||||||
|
circuits_breakers = null
|
||||||
|
consistent_hash = null
|
||||||
|
iap = null
|
||||||
|
protocol = "HTTPS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
health_checks_config = {
|
||||||
|
hc = {
|
||||||
|
type = "tcp"
|
||||||
|
logging = true
|
||||||
|
options = null
|
||||||
|
check = {
|
||||||
|
port_name = "http"
|
||||||
|
port_specification = "USE_NAMED_PORT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "local_file" "vars_file" {
|
||||||
|
content = templatefile("${path.module}/templates/vars.yaml.tpl", {
|
||||||
|
project_id = var.project_id
|
||||||
|
ad_dns_domain_name = var.ad_dns_domain_name
|
||||||
|
adfs_dns_domain_name = var.adfs_dns_domain_name
|
||||||
|
})
|
||||||
|
filename = "${path.module}/ansible/vars/vars.yaml"
|
||||||
|
file_permission = "0666"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "local_file" "gssh_file" {
|
||||||
|
content = templatefile("${path.module}/templates/gssh.sh.tpl", {
|
||||||
|
zone = var.zone
|
||||||
|
project_id = var.project_id
|
||||||
|
})
|
||||||
|
filename = "${path.module}/ansible/gssh.sh"
|
||||||
|
file_permission = "0777"
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
output "ip_address" {
|
||||||
|
description = "IP address."
|
||||||
|
value = module.glb.ip_address
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from textwrap import indent
|
||||||
|
import click
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
from faker import Faker
|
||||||
|
|
||||||
|
ENCODING = 'UTF8'
|
||||||
|
|
||||||
|
FIELD_USER_FIRST_NAME = 'first_name'
|
||||||
|
FIELD_USER_LAST_NAME = 'last_name'
|
||||||
|
FIELD_USER_USERNAME = 'username'
|
||||||
|
FIELD_USER_PASSWORD = 'password'
|
||||||
|
|
||||||
|
FIELD_MEMBERSHIP_GROUP = 'group'
|
||||||
|
FIELD_MEMBERSHIP_MEMBER = 'member'
|
||||||
|
|
||||||
|
fake = Faker()
|
||||||
|
|
||||||
|
@ click.group()
|
||||||
|
def cli():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@ cli.command()
|
||||||
|
@ click.option(
|
||||||
|
"--num-users",
|
||||||
|
help="Number of users to create",
|
||||||
|
default=10,
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--output-file",
|
||||||
|
help="Output file",
|
||||||
|
default="users.json",
|
||||||
|
)
|
||||||
|
def create_users(num_users, output_file):
|
||||||
|
rows = []
|
||||||
|
for i in range(1, num_users):
|
||||||
|
row = {}
|
||||||
|
row[FIELD_USER_FIRST_NAME] = fake.first_name()
|
||||||
|
row[FIELD_USER_LAST_NAME] = fake.last_name()
|
||||||
|
row[FIELD_USER_USERNAME] = row[FIELD_USER_FIRST_NAME].lower() + "." + \
|
||||||
|
row[FIELD_USER_LAST_NAME].lower()
|
||||||
|
row[FIELD_USER_PASSWORD] = fake.password()
|
||||||
|
rows.append(row)
|
||||||
|
write_json(output_file, rows)
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.option(
|
||||||
|
"--users-file",
|
||||||
|
help="Users file",
|
||||||
|
default="users.json",
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--groups-file",
|
||||||
|
help="Groups file",
|
||||||
|
default="groups.json",
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"--output-file",
|
||||||
|
help="Output file",
|
||||||
|
default="memberships.json",
|
||||||
|
)
|
||||||
|
def create_memberships(users_file, groups_file, output_file):
|
||||||
|
users = read_json(users_file)
|
||||||
|
groups = read_json(groups_file)
|
||||||
|
rows = []
|
||||||
|
for group in groups:
|
||||||
|
members = random.sample(users, random.randint(0, len(users) - 1))
|
||||||
|
for member in members:
|
||||||
|
row = {}
|
||||||
|
row[FIELD_MEMBERSHIP_GROUP] = group
|
||||||
|
row[FIELD_MEMBERSHIP_MEMBER] = member[FIELD_USER_USERNAME]
|
||||||
|
rows.append(row)
|
||||||
|
write_json(output_file, rows)
|
||||||
|
|
||||||
|
def write_json(file, rows):
|
||||||
|
with open(file, 'w') as f:
|
||||||
|
json.dump(rows, f, indent=2)
|
||||||
|
|
||||||
|
def read_json(file):
|
||||||
|
with open(file, 'r', encoding='UTF8') as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cli()
|
|
@ -0,0 +1,3 @@
|
||||||
|
argparse==1.4.0
|
||||||
|
Faker==13.3.2
|
||||||
|
click==8.0.4
|
|
@ -0,0 +1,66 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
param($DnsName)
|
||||||
|
|
||||||
|
$ApplicationGroup = Get-AdfsApplicationGroup -Name Anthos
|
||||||
|
|
||||||
|
$ApplicationGroupName = "Anthos"
|
||||||
|
$ApplicationGroupIdentifier = (New-Guid).Guid
|
||||||
|
New-AdfsApplicationGroup -Name $ApplicationGroupName `
|
||||||
|
-ApplicationGroupIdentifier $ApplicationGroupIdentifier
|
||||||
|
|
||||||
|
$ServerApplicationName = "$ApplicationGroupName Server App"
|
||||||
|
$ServerApplicationIdentifier = (New-Guid).Guid
|
||||||
|
$RelyingPartyTrustName = "Anthos"
|
||||||
|
$RelyingPartyTrustIdentifier = (New-Guid).Guid
|
||||||
|
$RedirectURI1 = "http://localhost:1025/callback"
|
||||||
|
$RedirectURI2 = "https://console.cloud.google.com/kubernetes/oidc"
|
||||||
|
|
||||||
|
$ADFSApp = Add-AdfsServerApplication -Name $ServerApplicationName `
|
||||||
|
-ApplicationGroupIdentifier $ApplicationGroupIdentifier `
|
||||||
|
-RedirectUri $RedirectURI1,$RedirectURI2 `
|
||||||
|
-Identifier $ServerApplicationIdentifier `
|
||||||
|
-GenerateClientSecret
|
||||||
|
|
||||||
|
$IssuanceTransformRules = @'
|
||||||
|
@RuleTemplate = "LdapClaims"
|
||||||
|
@RuleName = "groups"
|
||||||
|
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
|
||||||
|
=> issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/claims/Group"), query = ";tokenGroups(domainQualifiedName);{0}", param = c.Value);
|
||||||
|
'@
|
||||||
|
|
||||||
|
Add-AdfsRelyingPartyTrust -Name $RelyingPartyTrustName `
|
||||||
|
-Identifier $RelyingPartyTrustIdentifier `
|
||||||
|
-AccessControlPolicyName "Permit everyone" `
|
||||||
|
-IssuanceTransformRules "$IssuanceTransformRules"
|
||||||
|
|
||||||
|
Grant-ADFSApplicationPermission -ClientRoleIdentifier $ServerApplicationIdentifier `
|
||||||
|
-ServerRoleIdentifier $RelyingPartyTrustIdentifier `
|
||||||
|
-ScopeName "allatclaims", "openid"
|
||||||
|
|
||||||
|
@"
|
||||||
|
authentication:
|
||||||
|
oidc:
|
||||||
|
clientID: $($ADFSApp.Identifier)
|
||||||
|
clientSecret: $($ADFSApp.ClientSecret)
|
||||||
|
extraParams: resource=$RelyingPartyTrustIdentifier
|
||||||
|
group: groups
|
||||||
|
groupPrefix: ""
|
||||||
|
issuerURI: https://$DnsName/adfs
|
||||||
|
kubectlRedirectURL: $RedirectURI1
|
||||||
|
scopes: openid
|
||||||
|
username: upn
|
||||||
|
usernamePrefix: ""
|
||||||
|
"@
|
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
host="$${@: -2: 1}"
|
||||||
|
cmd="$${@: -1: 1}"
|
||||||
|
|
||||||
|
gcloud_args="
|
||||||
|
--tunnel-through-iap
|
||||||
|
--zone=${zone}
|
||||||
|
--project=${project_id}
|
||||||
|
--quiet
|
||||||
|
--no-user-output-enabled
|
||||||
|
--
|
||||||
|
-C
|
||||||
|
"
|
||||||
|
|
||||||
|
exec gcloud compute ssh "$host" $gcloud_args "$cmd"
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
project_id: ${project_id}
|
||||||
|
ad_dns_domain_name: ${ad_dns_domain_name}
|
||||||
|
adfs_dns_domain_name: ${adfs_dns_domain_name}
|
|
@ -0,0 +1,100 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
variable "project_create" {
|
||||||
|
description = "Parameters for the creation of the new project."
|
||||||
|
type = object({
|
||||||
|
billing_account_id = string
|
||||||
|
parent = string
|
||||||
|
})
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_id" {
|
||||||
|
description = "Host project ID."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "prefix" {
|
||||||
|
description = "Prefix for the resources created."
|
||||||
|
type = string
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "network_config" {
|
||||||
|
description = "Network configuration"
|
||||||
|
type = object({
|
||||||
|
network = string
|
||||||
|
subnet = string
|
||||||
|
})
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ad_dns_domain_name" {
|
||||||
|
description = "AD DNS domain name."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "adfs_dns_domain_name" {
|
||||||
|
description = "ADFS DNS domain name."
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "disk_size" {
|
||||||
|
description = "Disk size."
|
||||||
|
type = number
|
||||||
|
default = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "disk_type" {
|
||||||
|
description = "Disk type."
|
||||||
|
type = string
|
||||||
|
default = "pd-ssd"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "image" {
|
||||||
|
description = "Image."
|
||||||
|
type = string
|
||||||
|
default = "projects/windows-cloud/global/images/family/windows-2022"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "instance_type" {
|
||||||
|
description = "Instance type."
|
||||||
|
type = string
|
||||||
|
default = "n1-standard-2"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "region" {
|
||||||
|
description = "Region."
|
||||||
|
type = string
|
||||||
|
default = "europe-west1"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "zone" {
|
||||||
|
description = "Zone."
|
||||||
|
type = string
|
||||||
|
default = "europe-west1-c"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ad_ip_cidr_block" {
|
||||||
|
description = "Managed AD IP CIDR block."
|
||||||
|
type = string
|
||||||
|
default = "10.0.0.0/24"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "subnet_ip_cidr_block" {
|
||||||
|
description = "Subnet IP CIDR block."
|
||||||
|
type = string
|
||||||
|
default = "10.0.1.0/28"
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 1.1.0"
|
||||||
|
required_providers {
|
||||||
|
local = {
|
||||||
|
version = ">= 2.2.3"
|
||||||
|
}
|
||||||
|
google = {
|
||||||
|
source = "hashicorp/google"
|
||||||
|
version = ">= 4.17.0"
|
||||||
|
}
|
||||||
|
google-beta = {
|
||||||
|
source = "hashicorp/google-beta"
|
||||||
|
version = ">= 4.17.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2022 Google LLC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module "test" {
|
||||||
|
source = "../../../../../examples/cloud-operations/adfs"
|
||||||
|
project_create = var.project_create
|
||||||
|
project_id = var.project_id
|
||||||
|
ad_dns_domain_name = var.ad_dns_domain_name
|
||||||
|
adfs_dns_domain_name = var.adfs_dns_domain_name
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
variable "project_create" {
|
||||||
|
type = object({
|
||||||
|
billing_account_id = string
|
||||||
|
parent = string
|
||||||
|
})
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_id" {
|
||||||
|
type = string
|
||||||
|
default = "my-project"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "prefix" {
|
||||||
|
type = string
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "network_config" {
|
||||||
|
type = object({
|
||||||
|
network = string
|
||||||
|
subnet = string
|
||||||
|
})
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ad_dns_domain_name" {
|
||||||
|
type = string
|
||||||
|
default = "example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "adfs_dns_domain_name" {
|
||||||
|
type = string
|
||||||
|
default = "adfs.example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "disk_size" {
|
||||||
|
type = number
|
||||||
|
default = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "disk_type" {
|
||||||
|
type = string
|
||||||
|
default = "pd-ssd"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "image" {
|
||||||
|
type = string
|
||||||
|
default = "projects/windows-cloud/global/images/family/windows-2022"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "instance_type" {
|
||||||
|
type = string
|
||||||
|
default = "n1-standard-2"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "region" {
|
||||||
|
type = string
|
||||||
|
default = "europe-west1"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "zone" {
|
||||||
|
type = string
|
||||||
|
default = "europe-west1-c"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ad_ip_cidr_block" {
|
||||||
|
type = string
|
||||||
|
default = "10.0.0.0/24"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "subnet_ip_cidr_block" {
|
||||||
|
type = string
|
||||||
|
default = "10.0.1.0/28"
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Copyright 2022 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
def test_resources(e2e_plan_runner):
|
||||||
|
"Test that plan works and the numbers of resources is as expected."
|
||||||
|
modules, resources = e2e_plan_runner()
|
||||||
|
assert len(modules) == 4
|
||||||
|
assert len(resources) == 16
|
Loading…
Reference in New Issue