Jim Rigsbee
2020-02-13 1e2288d704cc7b308efca749072d6f9df86fa986
Add ansible-skylight style classroom

Supports an Ansible for Windows classroom based off the skylight architecture.
Resolves issue #1024.
76 files added
4 files modified
4570 ■■■■■ changed files
ansible/configs/ansible-skylight/README.adoc 72 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/destroy_env.yml 18 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/env_vars.yml 398 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/files/cloud_providers/ec2_cloud_template.j2 325 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/files/hosts_template.j2 44 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/files/repos_template.j2 35 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/files/status.j2 5 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/files/tower_hosts_template.j2 39 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/lifecycle.yml 96 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/post_infra.yml 10 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/post_software.yml 72 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/pre_infra.yml 46 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/pre_software.yml 74 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/requirements.yml 10 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/software.yml 164 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/templates/report.j2 1 ●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/templates/win_ec2_userdata.j2 15 ●●●●● patch | view | raw | blame | history
ansible/roles/common/tasks/packages.yml 12 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/.ansible-lint 2 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/.gitignore 3 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/.travis.yml 32 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/LICENSE 20 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/README.md 149 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/defaults/main.yml 60 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/handlers/main.yml 5 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/meta/main.yml 28 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/molecule/default/molecule.yml 29 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/molecule/default/playbook-version.yml 31 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/molecule/default/playbook.yml 21 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/molecule/default/yaml-lint.yml 6 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/tasks/main.yml 77 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/templates/gitlab.rb.j2 74 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/vars/Debian.yml 3 ●●●●● patch | view | raw | blame | history
ansible/roles/geerlingguy.gitlab/vars/RedHat.yml 3 ●●●●● patch | view | raw | blame | history
ansible/roles/infra-ec2-template-generate/defaults/main.yml 79 ●●●●● patch | view | raw | blame | history
ansible/roles/set-repositories/tasks/epel-repo.yml 6 ●●●●● patch | view | raw | blame | history
ansible/roles/set-repositories/tasks/main.yml 4 ●●●● patch | view | raw | blame | history
ansible/roles/set-repositories/tasks/rhn-repos.yml 22 ●●●●● patch | view | raw | blame | history
ansible/roles/set-repositories/templates/epel_template.j2 8 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/defaults/main.yml 19 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/files/classroom_inventory.json 9 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/files/default_inventory.json 9 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/handlers/main.yml 8 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/tasks/create-resources.yml 239 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/tasks/main.yml 187 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/tasks/setup.yml 464 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/ansible-hosts.j2 7 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/ansible.cfg.j2 7 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/devops-creds.json.j2 10 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/gitlab-creds.json.j2 10 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/host_inventory.j2 44 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/inventory 23 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/krb5.conf.j2 25 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/ldap_conf.json.j2 39 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/sssd.conf.j2 45 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/tower-creds.json.j2 10 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/tower_config_adhoc.json.j2 3 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/tower_group.json.j2 6 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/tower_host.json.j2 8 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-ansible-tower/templates/win1_host.json.j2 8 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-do417-repos/tasks/main.yml 149 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-gitlab-env/defaults/main.yml 11 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-gitlab-env/tasks/api.yml 83 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-gitlab-env/tasks/main.yml 76 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-gitlab-env/templates/set_root_pw.sh.j2 11 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-linux-common/tasks/main.yml 38 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-ad/defaults/main.yml 13 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-ad/library/win_ad_dnsrecord.ps1 99 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-ad/library/win_ad_dnsrecord.py 66 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-ad/library/win_ad_reverse_dnszone.ps1 78 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-ad/library/win_dns_searchsuffix.ps1 48 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-ad/tasks/main.yml 138 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-common/defaults/main.yml 9 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-common/library/win_dns_searchsuffix.ps1 48 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-common/tasks/main.yml 69 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-workstation/files/settings.json 5 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-workstation/tasks/adv_lab.yml 13 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-workstation/tasks/git_lab.yml 13 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-workstation/tasks/main.yml 247 ●●●●● patch | view | raw | blame | history
ansible/roles/skylight-windows-workstation/tasks/myrtille.yml 78 ●●●●● patch | view | raw | blame | history
ansible/configs/ansible-skylight/README.adoc
New file
@@ -0,0 +1,72 @@
= ansible-skylight config
Author: Jim Rigsbee, jrigsbee@redhat.com
== Overview
Currently the ansible-skylight is used to deploy a classroom based on the
skylight classroom created by the SA Tiger team:
https://github.com/mgmt-sa-tiger-team/skylight.git
== NOTES
To be documented
== Review the Env_Type variable file
* This file link:./env_vars.yml[./env_vars.yml] contains all the variables you
 need to define to control, or customize, the deployment of your environment. In
normal usage this should not need to be touched or ammended and one-off changes
can be tested by passing vars or var files with `-e` or `-e @my_version_vars.yml`.
== Secrets
To be documented
== Running Ansible Playbook
You can run the playbook with the following arguments to overwrite the default variable values:
From the `ansible_agnostic_deployer/ansible` directory run
`
[source,bash]
----
ENVTYPE=ansible-skylight
GUID=test02
CLOUDPROVIDER=ec2
REGION=us-east-1
HOSTZONEID='Z3IHLWJZOU9SRT'
KEYNAME=awskey
ansible-playbook main.yml  \
      -e "guid=${GUID}" \
      -e "env_type=${ENVTYPE}" \
      -e "key_name=${KEYNAME}" \
      -e "subdomain_base_suffix=${BASESUFFIX}" \
      -e "cloud_provider=${CLOUDPROVIDER}" \
      -e "aws_region=${REGION}" \
      -e "HostedZoneId=${HOSTZONEID}" \
      -e "email=name@example.com" \
      -e "output_dir=/tmp/workdir" \
      -e @~/secret.yml \
      -e @~/my_env_vars.yml
----
=== To Delete an environment
[source,bash]
----
REGION=us-east-1
KEYNAME=awskey
GUID=test02
ENVTYPE=ansible-skylight
CLOUDPROVIDER=ec2
ansible-playbook configs/${ENVTYPE}/destroy_env.yml \
        -e "guid=${GUID}" -e "env_type=${ENVTYPE}" \
        -e "cloud_provider=${CLOUDPROVIDER}" \
        -e "aws_region=${REGION}"  -e "key_name=${KEYNAME}"  \
        -e @~/secret.yml \
        -e @~/my_env_vars.yml
----
ansible/configs/ansible-skylight/destroy_env.yml
New file
@@ -0,0 +1,18 @@
---
- import_playbook: ../../include_vars.yml
- name: Delete Infrastructure
  hosts: localhost
  connection: local
  gather_facts: False
  become: no
  tasks:
    - name: Run infra-ec2-template-destroy
      include_role:
        name: "infra-{{cloud_provider}}-template-destroy"
      when: cloud_provider == 'ec2'
    - name: Run infra-azure-template-destroy
      include_role:
        name: "infra-{{cloud_provider}}-template-destroy"
      when: cloud_provider == 'azure'
ansible/configs/ansible-skylight/env_vars.yml
New file
@@ -0,0 +1,398 @@
---
###### VARIABLES YOU SHOULD CONFIGURE FOR YOUR DEPLOYEMNT
###### OR PASS as "-e" args to ansible-playbook command
### Common Host settings
repo_method: file # Other Options are: file, satellite and rhn
#If using repo_method: satellite, you must set these values as well.
# satellite_url: satellite.example.com
# satellite_org: Sat_org_name
# satellite_activationkey: "rhel7basic"
# Do you want to run a full yum update
update_packages: false
install_bastion: false
install_common: true
install_courseware: true
# Indicate whether status will be reported to status API service on Bastion
# Also, indicates whether the status API will be installed on Bastion
report_status: true
# Defines the version of the Ansible Tower installer.
# The version should match a file available here:
# https://releases.ansible.com/ansible-tower/setup/
towerversion: "3.5.2-1"
tower_admin_password: changeme
## guid is the deployment unique identifier, it will be appended to all tags,
## files and anything that identifies this environment from another "just like it"
guid: defaultguid
course_name: default
platform: opentlc
project_tag: "{{ env_type }}-{{ guid }}"
### If you want a Key Pair name created and injected into the hosts,
# set `set_env_authorized_key` to true and set the keyname in `env_authorized_key`
# you can use the key used to create the environment or use your own self generated key
# if you set "use_own_key" to false your PRIVATE key will be copied to the bastion. (This is {{key_name}})
use_own_key: true
env_authorized_key: "{{guid}}key"
ansible_ssh_private_key_file: ~/.ssh/{{key_name}}
set_env_authorized_key: true
win_connect_method: psrp
### AWS EC2 Environment settings
### Route 53 Zone ID (AWS)
# This is the Route53 HostedZoneId where you will create your Public DNS entries
# This only needs to be defined if your CF template uses route53
HostedZoneId: Z3IHLWJZOU9SRT
# The region to be used, if not specified by -e in the command line
aws_region: us-east-1
# The key that is used to
key_name: "default_key_name"
## Networking (AWS)
subdomain_base_short: "{{ guid }}"
subdomain_base_suffix: ".{{ course_name }}.opentlc.com"
subdomain_base: "{{ subdomain_base_short }}{{ subdomain_base_suffix }}"
zone_internal_dns: "{{guid}}.{{course_name}}.internal."
chomped_zone_internal_dns: "{{guid}}.{{course_name}}.internal"
vpcid_cidr_block: "172.25.0.0/16"
vpcid_name_tag: "{{subdomain_base}}"
aws_availability_zone: "{{ aws_region }}a"
aws_private_subnet_cidr: "172.25.250.0/24"
aws_public_subnet_cidr: "172.25.251.0/24"
aws_vpc_name: "{{course_name}}-{{guid}}-vpc"
cf_template_description: "{{ env_type }}-{{ guid }} Ansible Agnostic Deployer "
## Environment Sizing
bastion_instance_type: "t2.medium"
tower_instance_type: "t2.medium"
gitlab_instance_type: "t2.medium"
windows_instance_count: 2
windows_instance_type: "t3.medium"
windows_workstation_instance_type: "t3.large"
activedirectory_instance_count: 1
activedirectory_instance_type: "t3.medium"
# Windows Domain Settings
dns_domain_name: "example.com"
dns_domain_name_short: "example"
ldap_basedn: "DC=example,DC=com"
ldap_search_base: "{{ ldap_basedn }}"
ldap_access_filter: "(&(objectClass=user)(memberOf=CN=Ansible Users,CN=Users,{{ ldap_search_base }}))"
tower_ldap_search_dn: "CN=Users,{{ ldap_search_base }}"
security_groups:
  - name: BastionSG
    rules:
      - name: SSHBastion
        description: "SSH public"
        from_port: 22
        to_port: 22
        protocol: tcp
        cidr: "0.0.0.0/0"
        rule_type: Ingress
      - name: HttpBastion
        description: "Http public"
        from_port: 80
        to_port: 80
        protocol: tcp
        cidr: "0.0.0.0/0"
        rule_type: Ingress
      - name: NginxBastion
        description: "Http public"
        from_port: 30904
        to_port: 30904
        protocol: tcp
        cidr: "0.0.0.0/0"
        rule_type: Ingress
  - name: TowerSG
    rules:
      - name: InternalNetworkTowerTcp
        description: "All internal TCP traffic"
        from_port: 0
        to_port: 65535
        protocol: tcp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
      - name: InternalNetworkTowerUdp
        description: "All internal UDP traffic"
        from_port: 0
        to_port: 65535
        protocol: udp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
  - name: GitlabSG
    rules:
      - name: InternalNetworkGitlabTcp
        description: "All internal TCP traffic"
        from_port: 0
        to_port: 65535
        protocol: tcp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
      - name: InternalNetworkGitlabUdp
        description: "All internal UDP traffic"
        from_port: 0
        to_port: 65535
        protocol: udp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
  - name: WinDCSG
    rules:
      - name: InternalNetworkWinTcp
        description: "All internal TCP traffic"
        from_port: 0
        to_port: 65535
        protocol: tcp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
      - name: InternalNetworkWinUdp
        description: "All internal UDP traffic"
        from_port: 0
        to_port: 65535
        protocol: udp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
  - name: WinSG
    rules:
      - name: InternalNetworkWinTcp
        description: "All internal TCP traffic"
        from_port: 0
        to_port: 65535
        protocol: tcp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
      - name: InternalNetworkWinUdp
        description: "All internal UDP traffic"
        from_port: 0
        to_port: 65535
        protocol: udp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
  - name: WorkstationSG
    rules:
      - name: HTTPWin
        description: "HTTP public"
        from_port: 80
        to_port: 80
        protocol: tcp
        cidr: "0.0.0.0/0"
        rule_type: Ingress
      - name: HTTPSWin
        description: "HTTPS public"
        from_port: 443
        to_port: 443
        protocol: tcp
        cidr: "0.0.0.0/0"
        rule_type: Ingress
      - name: WinRDP
        description: "Win RDP public"
        from_port: 3389
        to_port: 3389
        protocol: tcp
        cidr: "0.0.0.0/0"
        rule_type: Ingress
      - name: InternalNetworkWinTcp
        description: "All internal TCP traffic"
        from_port: 0
        to_port: 65535
        protocol: tcp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
      - name: InternalNetworkWinUdp
        description: "All internal UDP traffic"
        from_port: 0
        to_port: 65535
        protocol: udp
        cidr: "{{ vpcid_cidr_block }}"
        rule_type: Ingress
instances:
  - name: "bastion"
    count: 1
    unique: true
    security_group: "BastionSG"
    public_dns: true
    flavor:
      "ec2": "{{bastion_instance_type}}"
    image_id: RHEL76GOLD
    tags:
      - key: "AnsibleGroup"
        value: "bastions"
      - key: "ostype"
        value: "linux"
  - name: "tower"
    count: 1
    unique: true
    security_group: "TowerSG"
    public_dns: false
    flavor:
      "ec2": "{{tower_instance_type}}"
    image_id: RHEL76GOLD
    tags:
      - key: "AnsibleGroup"
        value: "towers"
      - key: "ostype"
        value: "linux"
    #TODO is this needed? it doesn't work like this
    # UserData: |
    #      UserData:
    #             hostname: tower
    #             fqdn: "tower.{{dns_domain_name}}"
    #             manage_etc_hosts: true
    #             chpasswd: { expire: False }
    #             ssh_pwauth: True
  - name: "gitlab"
    count: 1
    unique: true
    security_group: "GitlabSG"
    public_dns: false
    flavor:
      "ec2": "{{gitlab_instance_type}}"
    image_id: RHEL76GOLD
    tags:
      - key: "AnsibleGroup"
        value: "gitlab"
      - key: "ostype"
        value: "linux"
  - name: "windc"
    count: "{{activedirectory_instance_count}}"
    public_dns: false
    unique: "{{ true if activedirectory_instance_count | int <= 1 else false }}"
    security_group: "WinDCSG"
    flavor:
      "ec2": "{{activedirectory_instance_type}}"
    image_id: WIN2019FULL
    UserData: "{{ lookup('template', '../configs/{{ env_type }}/templates/win_ec2_userdata.j2') }}"
    tags:
      - key: "AnsibleGroup"
        value: "activedirectories"
      - key: "ostype"
        value: "windows"
  - name: "win"
    count: "{{windows_instance_count}}"
    unique: "{{ true if windows_instance_count | int <= 1 else false }}"
    public_dns: false
    security_group: "WinSG"
    flavor:
      "ec2": "{{windows_instance_type}}"
    image_id: WIN2019FULL
    UserData: "{{ lookup('template', '../configs/{{ env_type }}/templates/win_ec2_userdata.j2') }}"
    tags:
      - key: "AnsibleGroup"
        value: "windows_servers"
      - key: "ostype"
        value: "windows"
    volumes:
      - device_name: "/dev/xvdf"
        size: 5
  - name: "workstation"
    count: 1
    unique: true
    public_dns: true
    security_group: "WorkstationSG"
    flavor:
      "ec2": "{{windows_workstation_instance_type}}"
    image_id: WIN2016FULL
    UserData: "{{ lookup('template', '../configs/{{ env_type }}/templates/win_ec2_userdata.j2') }}"
    tags:
      - key: "AnsibleGroup"
        value: "workstations"
      - key: "ostype"
        value: "windows"
install_win_ssh: false
###### VARIABLES YOU SHOULD ***NOT*** CONFIGURE FOR YOUR DEPLOYMENT
###### You can, but you usually wouldn't need to.
# The following interfere with Windows servers which use Administrator
#ansible_user: ec2-user
#remote_user: ec2-user
common_packages:
  - python
  - unzip
  - bash-completion
  - tmux
  - bind-utils
  - wget
  - git
  - vim-enhanced
  - at
  - python2-pip
  - gcc
rhel_repos:
  - rhel-7-server-rpms
  - rhel-7-server-extras-rpms
disable_default_repos: true
enable_epel: true
# Needed for reverse lookup DNS setup
ptr_zone_name: "250.25.172.in-addr.arpa"
ptr_zone_cidr: "172.25.250.0/24"
# Windows Default account
user_prefix: student
workstation_user: training
###################### GITLAB INFO #######################
# Gitlab variables
gitlab_external_url: "https://gitlab.{{ dns_domain_name }}/"
gitlab_git_data_dir: "/var/opt/gitlab/git-data"
gitlab_backup_path: "/var/opt/gitlab/backups"
gitlab_edition: "gitlab-ce"
# SSL Config
gitlab_redirect_http_to_https: "true"
gitlab_ssl_certificate: "/etc/gitlab/ssl/gitlab.crt"
gitlab_ssl_certificate_key: "/etc/gitlab/ssl/gitlab.key"
# SSL Self-signed Certificate Configuration
gitlab_create_self_signed_cert: "true"
gitlab_self_signed_cert_subj: "/C=US/ST=North Carolina/L=Raleigh/O=Ansible/CN=gitlab.{{ dns_domain_name }}"
# LDAP Configuration
gitlab_ldap_enabled: "true"
gitlab_ldap_host: "windc.{{ dns_domain_name }}"
gitlab_ldap_port: "389"
gitlab_ldap_uid: "sAMAccountName"
gitlab_ldap_method: "plain"
gitlab_ldap_bind_dn: "CN=Admin,CN=Users,{{ ldap_basedn }}"
gitlab_ldap_password: "{{ windows_password }}"
gitlab_ldap_base: "{{ ldap_basedn }}"
# General Config
gitlab_time_zone: "UTC"
gitlab_backup_keep_time: "604800"
gitlab_download_validate_certs: yes
gitlab_version: "10.0.6-ce.0.el7"
# Email configuration.
gitlab_email_enabled: "false"
gitlab_smtp_enable: "false"
git_lab: false
advanced_lab: false
ansible/configs/ansible-skylight/files/cloud_providers/ec2_cloud_template.j2
New file
@@ -0,0 +1,325 @@
AWSTemplateFormatVersion: "2010-09-09"
Mappings:
  RegionMapping: {{ aws_ami_region_mapping | to_json }}
Resources:
   Vpc:
    Type: "AWS::EC2::VPC"
    Properties:
     CidrBlock: "{{vpcid_cidr_block}}"
     EnableDnsSupport: true
     EnableDnsHostnames: true
     Tags:
      - Key: Name
        Value: "{{vpcid_name_tag}}"
      - Key: Hostlication
        Value:
          Ref: "AWS::StackId"
   VpcInternetGateway:
    Type: "AWS::EC2::InternetGateway"
    Properties:
     Tags:
      - Key: Name
        Value: "{{vpcid_name_tag}}"
   VpcGA:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
     InternetGatewayId:
      Ref: VpcInternetGateway
     VpcId:
      Ref: Vpc
   VpcRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
     VpcId:
      Ref: Vpc
     Tags:
      - Key: Name
        Value: "{{vpcid_name_tag}}"
   VPCRouteInternetGateway:
    DependsOn: VpcGA
    Type: "AWS::EC2::Route"
    Properties:
     GatewayId:
      Ref: VpcInternetGateway
     DestinationCidrBlock: "0.0.0.0/0"
     RouteTableId:
      Ref: VpcRouteTable
   PublicSubnet:
    Type: "AWS::EC2::Subnet"
    DependsOn:
      - Vpc
    Properties:
{% if aws_availability_zone is defined %}
      AvailabilityZone: "{{ aws_availability_zone }}"
{% endif %}
      CidrBlock: "{{ aws_public_subnet_cidr }}"
      Tags:
        - Key: Name
          Value: "{{vpcid_name_tag}}-public"
        - Key: Hostlication
          Value:
            Ref: "AWS::StackId"
      MapPublicIpOnLaunch: false
      VpcId:
        Ref: Vpc
   PublicSubnetRTA:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
     RouteTableId:
      Ref: VpcRouteTable
     SubnetId:
      Ref: PublicSubnet
   PrivateRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
     VpcId:
      Ref: Vpc
     Tags:
      - Key: Name
        Value: "{{vpcid_name_tag}}-private"
   PrivateRouteNatGateway:
    DependsOn:
     - NatGateway
    Type: "AWS::EC2::Route"
    Properties:
     NatGatewayId:
      Ref: NatGateway
     DestinationCidrBlock: "0.0.0.0/0"
     RouteTableId:
      Ref: PrivateRouteTable
   PrivateSubnet:
    Type: "AWS::EC2::Subnet"
    DependsOn:
     - Vpc
    Properties:
{% if aws_availability_zone is defined %}
     AvailabilityZone: "{{ aws_availability_zone }}"
{% endif %}
     CidrBlock: "{{ aws_private_subnet_cidr }}"
     Tags:
      - Key: Name
        Value: "{{ vpcid_name_tag }}-private"
      - Key: Hostlication
        Value:
         Ref: "AWS::StackId"
     MapPublicIpOnLaunch: false
     VpcId:
      Ref: Vpc
   PrivateSubnetRTA:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
     RouteTableId:
      Ref: PrivateRouteTable
     SubnetId:
      Ref: PrivateSubnet
   NatGatewayEIP:
    Type: "AWS::EC2::EIP"
    DependsOn:
     - VpcGA
    Properties:
     Domain: vpc
   NatGateway:
    Type: "AWS::EC2::NatGateway"
    DependsOn:
     - NatGatewayEIP
     - PublicSubnet
    Properties:
     AllocationId:
      Fn::GetAtt:
       - NatGatewayEIP
       - AllocationId
     SubnetId:
      Ref: PublicSubnet
     Tags:
      - Key: Name
        Value: "{{vpcid_name_tag}}"
{% for security_group in security_groups %}
   {{security_group['name']}}:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: Host
      VpcId:
        Ref: Vpc
      Tags:
        - Key: Name
          Value: "{{course_name}}-{{guid}}-{{security_group['name']}}"
{% endfor %}
{% for security_group in security_groups %}
{% for rule in security_group['rules'] %}
   {{security_group['name']}}{{rule['name']}}:
    Type: "AWS::EC2::SecurityGroup{{rule['rule_type']}}"
    Properties:
     GroupId:
       Fn::GetAtt:
         - "{{security_group['name']}}"
         - GroupId
     IpProtocol: {{rule['protocol']}}
     FromPort: {{rule['from_port']}}
     ToPort: {{rule['to_port']}}
{% if rule['cidr'] is defined %}
     CidrIp: "{{rule['cidr']}}"
{% endif  %}
{% if rule['group'] is defined %}
     SourceSecurityGroupId:
       Fn::GetAtt:
        - "{{rule['group']}}"
        - GroupId
{% endif  %}
{% endfor %}
{% endfor %}
   zoneinternalidns:
    Type: "AWS::Route53::HostedZone"
    Properties:
     Name: "{{ zone_internal_dns }}"
     VPCs:
      - VPCId:
          Ref: Vpc
        VPCRegion:
          Ref: "AWS::Region"
     HostedZoneConfig:
      Comment: "Created By ansible agnostic deployer"
{% for instance in instances %}
{% for c in range(1,(instance['count'] |int)+1) %}
{% set instancecount = loop %}
#this is host {{instance['name']}}{{loop.index}}
   {{instance['name']}}{{loop.index}}:
    Type: "AWS::EC2::Instance"
    DependsOn:
     - PrivateRouteNatGateway
    Properties:
     ImageId:
      "Fn::FindInMap":
       - RegionMapping
       - Ref: "AWS::Region"
       - {{ instance['image_id'] | default(aws_default_image) }}
     InstanceType: "{{instance['flavor'][cloud_provider]}}"
     KeyName: "{{instance['key_name'] | default(key_name)}}"
{% if instance['UserData'] is defined %}
     {{instance['UserData']}}
{% endif %}
     SecurityGroupIds:
        - "Fn::GetAtt":
          - {{instance['security_group']}}
          - GroupId
     SubnetId:
{% if instance['public_dns'] %}
      Ref: PublicSubnet
{% else %}
      Ref: PrivateSubnet
{% endif %}
     Tags:
{% if instance['unique'] | default(false) %}
      - Key: Name
        Value: {{course_name}}-{{guid}}-{{instance['name']}}
      - Key: internaldns
        Value: {{instance['name']}}.{{chomped_zone_internal_dns}}
{% else %}
      - Key: Name
        Value: {{course_name}}-{{guid}}-{{instance['name']}}{{instancecount.index}}
      - Key: internaldns
        Value: {{instance['name']}}{{loop.index}}.{{chomped_zone_internal_dns}}
{% endif %}
      - Key: "owner"
        Value: "{{ email | default('unknownuser') }}"
      - Key: "Project"
        Value: "{{project_tag}}"
      - Key: "{{project_tag}}"
        Value: "{{ instance['name'] }}"
{% if instance['unique'] | default(false) %}
      - Key: "instance_name"
        Value: "{{ instance['name'] }}"
{% else %}
      - Key: "instance_name"
        Value: "{{ instance['name'] }}{{instancecount.index}}"
{% endif %}
      - Key: "env_type"
        Value: "{{ env_type }}"
      - Key: "guid"
        Value: "{{ guid }}"
{% for tag in instance['tags'] %}
      - Key: {{tag['key']}}
        Value: {{tag['value']}}
{% endfor %}
     BlockDeviceMappings:
        - DeviceName: "/dev/sda1"
          Ebs:
            VolumeSize: 30
{% for vol in instance.volumes|default([]) if vol.enable|d(true) %}
        - DeviceName: "{{ vol.name | default(vol.device_name) }}"
          Ebs:
{% if cloud_provider in vol and 'type' in vol.ec2 %}
            VolumeType: "{{ vol[cloud_provider].type }}"
{% else %}
            VolumeType: "{{ aws_default_volume_type }}"
{% endif %}
            VolumeSize: "{{ vol.size }}"
            DeleteOnTermination: true
{% endfor %}
   {{instance['name']}}{{loop.index}}InternalDNS:
    Type: "AWS::Route53::RecordSetGroup"
    Properties:
     HostedZoneId:
      Ref: zoneinternalidns
     RecordSets:
{% if instance['unique'] | default(false) %}
      - Name: "{{instance['name']}}.{{zone_internal_dns}}"
{% else %}
      - Name: "{{instance['name']}}{{loop.index}}.{{zone_internal_dns}}"
{% endif %}
        Type: A
        TTL: 10
        ResourceRecords:
          - "Fn::GetAtt":
            - {{instance['name']}}{{loop.index}}
            - PrivateIp
{% if instance['public_dns'] %}
   {{instance['name']}}{{loop.index}}EIP:
     Type: "AWS::EC2::EIP"
     DependsOn:
      - VpcGA
     Properties:
      InstanceId:
       Ref: {{instance['name']}}{{loop.index}}
   {{instance['name']}}{{loop.index}}PublicDNS:
     Type: "AWS::Route53::RecordSetGroup"
     DependsOn:
        - {{instance['name']}}{{loop.index}}EIP
     Properties:
      HostedZoneId: {{HostedZoneId}}
      RecordSets:
{% if instance['unique'] | default(false) %}
         - Name: "{{instance['name']}}.{{subdomain_base}}."
{% else %}
         - Name: "{{instance['name']}}{{loop.index}}.{{subdomain_base}}."
{% endif %}
           Type: A
           TTL: 10
           ResourceRecords:
           - "Fn::GetAtt":
             - {{instance['name']}}{{loop.index}}
             - PublicIp
{% endif %}
{% endfor %}
{% endfor %}
ansible/configs/ansible-skylight/files/hosts_template.j2
New file
@@ -0,0 +1,44 @@
[windows_hosts]
{% for host in hostvars %}
{%   if "win1" in host %}
{{ hostvars[host].instance_name }}.{{ dns_domain_name }} ansible_host={{ hostvars[host].private_ip_address }} ansible_user={{ hostvars[host].ansible_user }} ansible_password="{{ windows_password }}" private_ip={{ hostvars[host].private_ip_address }}
{%   elif "win2" in host %}
{{ hostvars[host].instance_name }}.{{ dns_domain_name }} ansible_host={{ hostvars[host].private_ip_address }} ansible_user={{ hostvars[host].ansible_user }} ansible_password="{{ windows_password }}" private_ip={{ hostvars[host].private_ip_address }}
{%   elif "workstation" in host %}
{{ hostvars[host].instance_name }}.{{ dns_domain_name }} ansible_host={{ hostvars[host].private_ip_address }} ansible_user={{ hostvars[host].ansible_user }} ansible_password="{{ workstation_password }}" private_ip={{ hostvars[host].private_ip_address }}
{%   endif %}
{% endfor %}
{% for group in groups %}
{% if 'tag' not in group and 'unknowns' not in group and 'ungrouped' not in group and 'linux' not in group and 'towers' not in group and 'gitlab' not in group and 'bastions' not in group %}
[{{group}}]
{%   for entry in groups[group] %}
{%     for host in hostvars %}
{%       if entry == host and 'bastion' not in entry %}
{{ hostvars[host].instance_name }}.{{ dns_domain_name }} ansible_host={{ hostvars[host].private_ip_address }}
{%       endif %}
{%     endfor %}
{%   endfor %}
{% endif %}
{% endfor %}
[windows_hosts:vars]
ansible_connection=winrm
ansible_winrm_transport=credssp
ansible_winrm_server_cert_validation=ignore
ansible_port=5986
[workstations:vars]
ansible_connection=winrm
ansible_winrm_transport=credssp
ansible_winrm_server_cert_validation=ignore
ansible_port=5986
[activedirectories:vars]
ansible_connection=winrm
ansible_winrm_transport=credssp
ansible_winrm_server_cert_validation=ignore
ansible_port=5986
ansible_user=Administrator
ansible_password="{{ windows_password }}"
ansible/configs/ansible-skylight/files/repos_template.j2
New file
@@ -0,0 +1,35 @@
[rhel-7-server-rpms]
name=Red Hat Enterprise Linux 7
baseurl={{ own_repo_path }}/ocp/common/rhel-7-server-rpms
enabled=1
gpgcheck=0
[rhel-7-server-rh-common-rpms]
name=Red Hat Enterprise Linux 7 Common
baseurl={{ own_repo_path }}/ocp/common/rhel-7-server-rh-common-rpms
enabled=1
gpgcheck=0
[rhel-7-server-extras-rpms]
name=Red Hat Enterprise Linux 7 Extras
baseurl={{ own_repo_path }}/ocp/common/rhel-7-server-extras-rpms
enabled=1
gpgcheck=0
[rhel-7-server-optional-rpms]
name=Red Hat Enterprise Linux 7 Optional
baseurl={{ own_repo_path }}/ocp/common/rhel-7-server-optional-rpms
enabled=1
gpgcheck=0
[rhel-server-rhscl-7-rpms]
name=Red Hat Enterprise Linux 7 Software Collections
baseurl={{ own_repo_path}}/ocp/common/rhel-server-rhscl-7-rpms
enabled=1
gpgcheck=0
[pinned-epel-rpms]
name=EPEL Pinned (RPMs)
baseurl={{own_repo_path}}/epel
enabled=1
gpgcheck=0
ansible/configs/ansible-skylight/files/status.j2
New file
@@ -0,0 +1,5 @@
{{ "%-60s" | format('Instance') }} State      Type
----------------------------------------------------------------
{% for instance in r_instances.instances %}
{{ "%-60s" | format(instance.tags.Name) }} {{ "%-10s" | format(instance.state.name) }} {{ instance.instance_type }}
{% endfor %}
ansible/configs/ansible-skylight/files/tower_hosts_template.j2
New file
@@ -0,0 +1,39 @@
[GenericExample:vars]
###########################################################################
### Ansible Vars
###########################################################################
[all:vars]
ansible_become=true
admin_password="{{tower_admin_password}}"
pg_host='support1.{{chomped_zone_internal_dns}}'
pg_port='5432'
pg_database='awx'
pg_username='awx'
pg_password="{{tower_admin_password}}"
rabbitmq_port=5672
rabbitmq_vhost=tower
rabbitmq_username=tower
rabbitmq_password="{{tower_admin_password}}"
rabbitmq_cookie=cookiemonster
rabbitmq_use_long_name=true
[GenericExample:children]
# These
tower
database
[tower]
## These are the towers
{% for host in groups['towers'] %}
tower{{loop.index}}.{{chomped_zone_internal_dns}} public_host_name=tower{{loop.index}}.{{ guid }}{{subdomain_base_suffix}} ssh_host={{host}}
{% endfor %}
## These are the supporthosts
[database]
support1.{{chomped_zone_internal_dns}}
ansible/configs/ansible-skylight/lifecycle.yml
New file
@@ -0,0 +1,96 @@
---
# Start / Stop Logic for OCP 4 Clusters
- import_playbook: ../../setup_runtime.yml
- name: Build inventory
  hosts: localhost
  connection: local
  gather_facts: false
  become: false
  tasks:
    - when: cloud_provider == 'ec2'
      block:
      - name: Run infra-ec2-create-inventory Role
        include_role:
          name: infra-ec2-create-inventory
      - name: Run Common SSH Config Generator Role
        include_role:
          name: infra-common-ssh-config-generate
        when: "'bastions' in groups"
- name: Set ansible_ssh_extra_args
  hosts:
    - all:!windows:!network
  gather_facts: false
  any_errors_fatal: true
  ignore_errors: false
  tasks:
    - name: Set facts for remote access
      set_fact:
        ansible_ssh_extra_args: >-
          {{ ansible_ssh_extra_args|d() }}
          -F {{hostvars.localhost.output_dir}}/{{ env_type }}_{{ guid }}_ssh_conf
- name: Run stop/start/status/... actions
  hosts: localhost
  connection: local
  gather_facts: False
  become: no
  tasks:
  - name: Check for project_tag
    when: project_tag is not defined or project_tag == ''
    fail:
      msg: "project_tag is not defined"
  - name: Check for ACTION
    when: ACTION is not defined
    fail:
      msg: "ACTION is not defined"
  - name: Start / Stop VMs on AWS
    when:
      - cloud_provider == 'ec2'
      - guid is defined
      - guid != ''
      - guid != '*'
    environment:
      AWS_ACCESS_KEY_ID: "{{aws_access_key_id}}"
      AWS_SECRET_ACCESS_KEY: "{{aws_secret_access_key}}"
      AWS_DEFAULT_REGION: "{{aws_region_final|d(aws_region)}}"
    block:
    - name: Stop instances by (guid,env_type) tags
      when: ACTION == 'stop'
      ec2_instance:
        state: stopped
        wait: no
        filters:
          "tag:guid": "{{ guid }}"
          "tag:env_type": "{{ env_type }}"
          instance-state-name: running
    - name: Start instances by (guid, env_type) tags
      when: ACTION == 'start'
      ec2_instance:
        state: started
        wait: true
        filters:
          "tag:guid": "{{ guid }}"
          "tag:env_type": "{{ env_type }}"
          instance-state-name: stopped
      ignore_errors: true
    - when: ACTION == 'status'
      block:
        - name: Get EC2 facts using (guid, env_type) tag
          ec2_instance_facts:
            filters:
              "tag:guid": "{{ guid }}"
              "tag:env_type": "{{ env_type }}"
          register: r_instances
        - name: Print status information to a file
          template:
            dest: "{{ output_dir }}/status.txt"
            src: files/status.j2
ansible/configs/ansible-skylight/post_infra.yml
New file
@@ -0,0 +1,10 @@
- name: Step 002 Post Infrastructure
  hosts: localhost
  connection: local
  become: false
  tags:
    - step002
    - post_infrastructure
  tasks:
    - debug:
        msg: Post Infrastructure Completed
ansible/configs/ansible-skylight/post_software.yml
New file
@@ -0,0 +1,72 @@
- name: Step 00xxxxx post software
  hosts: localhost
  connection: local
  gather_facts: False
  become: no
  tasks:
    - debug:
        msg: "Post-Software tasks Started"
- name: Copy files to workstation
  hosts: workstations
  tasks:
    - name: Copy Ansible Inventory for this environment
      win_copy:
        src: "{{output_dir}}/hosts-{{ env_type }}-{{ guid }}"
        dest: "C:\\inventory.ini"
- name: PostSoftware flight-check
  hosts: towers
  gather_facts: false
  become: yes
  tags:
    - post_flight_check
  tasks:
    - name: See if virtualenv is installed
      stat:
        path: venv
      register: virtualenv
    - name: Setup python virtualenv
      shell: |
        virtualenv venv
        source venv/bin/activate
        pip install ansible requests-credssp pywinrm
        deactivate
        exit 0
      when: not virtualenv.stat.exists
    - name: Test Ansible connectivity to Windows servers
      shell: |
        source venv/bin/activate
        ansible windows -m win_ping
      register: ansible_check
      ignore_errors: true
    - debug:
        var: ansible_check
    - fail:
        msg: "Ansible test of tower environment failed"
      when: ansible_check is failed
    - debug:
        msg: "Post-Software checks completed successfully"
- name: Provisioning final tasks
  hosts: localhost
  connection: local
  gather_facts: false
  become: no
  tasks:
    - name: Report provisioning status
      include_role:
        name: status-report
      vars:
        classroom_status: "Classroom ready"
        status_json: "{{ lookup('template', 'report.j2') }}"
      when: report_status
    - name: Stop SSH/Socks proxy for Windows proxying through bastion
      shell: |
        ssh -i {{ ssh_key | default(infra_ssh_key) | default(ansible_ssh_private_key_file) | default(default_key_name)}} -o "ControlPath=~/.ssh/cp/ssh-%r@%h:%p" -O exit -p 22 {{hostvars[bastion_hostname].ansible_user}}@{{hostvars[bastion_hostname].public_ip_address}}
      when: win_connect_method | d('winrm') == 'psrp'
ansible/configs/ansible-skylight/pre_infra.yml
New file
@@ -0,0 +1,46 @@
- name: Step 000 Pre Infrastructure
  hosts: localhost
  connection: local
  become: false
  tags:
    - step001
    - pre_infrastructure
  tasks:
    - name: if windows_password is not defined, generate one
      when: windows_password is not defined
      block:
      - name: Stat workdir/[...]_windows_password.txt file
        stat:
          path: "{{output_dir}}/{{ env_type }}_{{guid}}_windows_password.txt"
        register: passwordfile
# This task needs to be "ansibled", we cannot assume tr exists
# This also doesn't work on MAC, that does have tr.
      - name: Generate windows Administrator password if not already defined
        command: openssl rand -base64 25
        register: password_gen_r
        when: not passwordfile.stat.exists
      # TODO: use slurp
      - name: Read windows password from workdir/[...]_windows_password.txt file
        command: "cat '{{output_dir}}/{{ env_type }}_{{guid}}_windows_password.txt'"
        register: password_get_r
        changed_when: false
        when: passwordfile.stat.exists
      - name: set_fact windows_password (just generated)
        set_fact:
          generated_windows_password: "{{ password_gen_r.stdout }}"
          windows_password: "{{ password_gen_r.stdout }}"
        when: not passwordfile.stat.exists
      - name: set_fact windows_password (previously generated)
        set_fact:
          generated_windows_password: "{{ password_get_r.stdout }}"
        when: passwordfile.stat.exists
    - name: Save windows_password or generated_windows_password into workdir/
      copy:
        content: "{{ windows_password | default(generated_windows_password) }}"
        dest: "{{output_dir}}/{{ env_type }}_{{guid}}_windows_password.txt"
        mode: 0600
ansible/configs/ansible-skylight/pre_software.yml
New file
@@ -0,0 +1,74 @@
---
- name: Step 003 - Create env key
  hosts: localhost
  connection: local
  gather_facts: false
  become: false
  tags:
    - step003
    - generate_env_keys
  tasks:
    - name: Generate SSH keys
      shell: ssh-keygen -b 2048 -t rsa -f "{{output_dir}}/{{env_authorized_key}}" -q -N ""
      args:
        creates: "{{output_dir}}/{{env_authorized_key}}"
      when: set_env_authorized_key | bool
# Cloudformation template or equivalent should tag all hosts with Project:{{ env_type }}-{{ guid }}
- name: Configure all hosts with Repositories, Common Files and Set environment key
  hosts:
    - all:!windows
  become: true
  gather_facts: False
  tags:
    - step004
    - common_tasks
  roles:
    - { role: "set-repositories", when: 'repo_method is defined' }
    - { role: "common", when: 'install_common' }
    - { role: "set_env_authorized_key", when: 'set_env_authorized_key' }
- name: Configuring Bastion Hosts
  hosts: bastions
  become: true
  roles:
    - { role: "bastion", when: 'install_bastion' }
    - { role: "status-report-install", when: 'report_status | d(false)' }
  tags:
    - step004
    - bastion_tasks
# - name: Inject and configure FTL on bastion as grader host
#   hosts: bastions
#   become: true
#   tasks:
#     - name: Setup FTL
#       include_role:
#         name: ftl-injector
#   tags:
#     - step004
#     - ftl-injector
- name: Configure windows machines
  hosts:
    - windows
  gather_facts: False
  tags:
    - step004
    - common_tasks
    - windows_tasks
  roles:
    - role: windows-common
      when: hostvars.localhost.install_win_ssh
- name: PreSoftware flight-check
  hosts: localhost
  connection: local
  gather_facts: false
  become: false
  tags:
    - flight_check
  tasks:
    - debug:
        msg: "Pre-Software checks completed successfully"
ansible/configs/ansible-skylight/requirements.yml
New file
@@ -0,0 +1,10 @@
---
# External role to setup grader host virtualenv and FTL grading infra
- src: https://github.com/redhat-gpte-devopsautomation/ftl-injector
  name: ftl-injector
  version: v0.7
# From 'Stouts.wsgi'
- src: https://github.com/Stouts/Stouts.wsgi
  version: 2.1.4
ansible/configs/ansible-skylight/software.yml
New file
@@ -0,0 +1,164 @@
---
- name: Step 00xxxxx software
  hosts: localhost
  gather_facts: False
  become: false
  tasks:
    - debug:
        msg: "Software tasks Started"
- name: Report Provisioning Status
  hosts: localhost
  connection: local
  gather_facts: false
  become: no
  tasks:
    - name: Report provisioning status
      include_role:
        name: status-report
      vars:
        classroom_status: "Servers provisioned 1 of 6"
        status_json: "{{ lookup('template', 'report.j2') }}"
      when: report_status
- name: Step 001 software - Configure Active Directory DC
  hosts: activedirectories
  gather_facts: true
  tags:
    - windows-ad-controller
  roles:
    - skylight-windows-ad
- name: Report Provisioning Status
  hosts: localhost
  connection: local
  gather_facts: false
  become: no
  tasks:
    - name: Report provisioning status
      include_role:
        name: status-report
      vars:
        classroom_status: "Active Directory configured 2 of 6"
        status_json: "{{ lookup('template', 'report.j2') }}"
      when: report_status
- name: Step 002 software - Configure Windows Servers
  hosts:
    - windows_servers
    - workstations
  gather_facts: true
  tags:
    - windows-servers
  roles:
    - skylight-windows-common
- name: Report Provisioning Status
  hosts: localhost
  connection: local
  gather_facts: false
  become: no
  tasks:
    - name: Report provisioning status
      include_role:
        name: status-report
      vars:
        classroom_status: "Windows servers configured 3 of 6"
        status_json: "{{ lookup('template', 'report.j2') }}"
      when: report_status
- name: Step 003.1 software - Configure GitLab Host
  hosts: gitlab
  become: true
  gather_facts: true
  tags:
    - gitlab
  roles:
    - skylight-linux-common
    - geerlingguy.gitlab
- name: Step 003.2 software - Configure Gitlab Environment
  hosts: gitlab
  become: true
  gather_facts: true
  tags:
    - gitlab
  roles:
    - skylight-gitlab-env
- name: Step 003.3 software - Configure DO417 repos
  hosts: gitlab
  become: False
  gather_facts: False
  tags:
    - gitlab
  roles:
    - skylight-do417-repos
- name: Report Provisioning Status
  hosts: localhost
  connection: local
  gather_facts: false
  become: no
  tasks:
    - name: Report provisioning status
      include_role:
        name: status-report
      vars:
        classroom_status: "Gitlab configured 4 of 6"
        status_json: "{{ lookup('template', 'report.j2') }}"
      when: report_status
- name: Step 004 software - Configure Ansible Tower
  hosts: towers
  become: true
  gather_facts: true
  tags:
    - ansible-tower
  roles:
    - skylight-linux-common
    - skylight-ansible-tower
- name: Report Provisioning Status
  hosts: localhost
  connection: local
  gather_facts: false
  become: no
  tasks:
    - name: Report provisioning status
      include_role:
        name: status-report
      vars:
        classroom_status: "Ansible Tower configured 5 of 6"
        status_json: "{{ lookup('template', 'report.j2') }}"
      when: report_status
- name: Step 005 software - Configure Windows Workstation
  hosts: workstations
  gather_facts: true
  tags:
    - windows-workstation
  roles:
    - skylight-windows-workstation
- name: Report Provisioning Status
  hosts: localhost
  connection: local
  gather_facts: false
  become: no
  tasks:
    - name: Report provisioning status
      include_role:
        name: status-report
      vars:
        classroom_status: "Windows Workstation configured 6 of 6"
        status_json: "{{ lookup('template', 'report.j2') }}"
      when: report_status
- name: Step 00xxxxx software
  hosts: localhost
  gather_facts: False
  become: false
  tasks:
    - debug:
        msg: "Software tasks Ended"
ansible/configs/ansible-skylight/templates/report.j2
New file
@@ -0,0 +1 @@
{ "workstation_username": "{{ workstation_user }}", "workstation_password": "{{ workstation_password }}", "workstation_hostname": "workstation.{{ guid }}{{subdomain_base_suffix}}", "classroom_identifier": "{{ guid }}", "classroom_type": "{{ env_type }}", "classroom_region": "{{ aws_region }}", "status": "{{ classroom_status | d('unknown') }}" }
ansible/configs/ansible-skylight/templates/win_ec2_userdata.j2
New file
@@ -0,0 +1,15 @@
UserData:
      "Fn::Base64":
        "Fn::Join":
          - ""
          - - "<powershell>\n"
            - "Get-ScheduledTask *ngen* | Disable-ScheduledTask\n"
            - "reg add 'HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update' /v AUOptions /t REG_DWORD /d 1 /f\n"
            - "net stop wuauserv\n"
            - "net start wuauserv\n"
            - "Set-MpPreference -DisableRealtimeMonitoring $true\n"
            - "$admin = [adsi]('WinNT://./administrator, user')\n"
            - "$admin.PSBase.Invoke('SetPassword', '{{windows_password}}')\n"
            - "Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile C:\\ConfigureRemotingForAnsible.ps1\n"
            - "C:\\ConfigureRemotingForAnsible.ps1 -ForceNewSSLCert -EnableCredSSP -GlobalHttpFirewallAccess\n"
            - "</powershell>"
ansible/roles/common/tasks/packages.yml
@@ -1,10 +1,22 @@
#vim: set ft=ansible:
---
######################### Install Basic Packages
- name: Install DNF backend for Yum
  yum:
    state: present
    name: python2-dnf
  register: dnf
  until: dnf is succeeded
  retries: 10
  delay: 10
  tags:
    - install_common_packages
- name: install basic packages
  yum:
    state: present
    name: "{{common_packages}}"
    use_backend: dnf
  register: yumr
  until: yumr is succeeded
  retries: "{{ common_install_basic_packages_retries }}"
ansible/roles/geerlingguy.gitlab/.ansible-lint
New file
@@ -0,0 +1,2 @@
skip_list:
  - '602'
ansible/roles/geerlingguy.gitlab/.gitignore
New file
@@ -0,0 +1,3 @@
*.retry
*/__pycache__
*.pyc
ansible/roles/geerlingguy.gitlab/.travis.yml
New file
@@ -0,0 +1,32 @@
---
language: python
services: docker
env:
  global:
    - ROLE_NAME: gitlab
  matrix:
    - MOLECULE_DISTRO: centos7
    - MOLECULE_DISTRO: ubuntu1804
    - MOLECULE_DISTRO: debian9
    - MOLECULE_DISTRO: centos7
      MOLECULE_PLAYBOOK: playbook-version.yml
    - MOLECULE_DISTRO: ubuntu1804
      MOLECULE_PLAYBOOK: playbook-version.yml
install:
  # Install test dependencies.
  - pip install molecule docker
before_script:
  # Use actual Ansible Galaxy role name for the project directory.
  - cd ../
  - mv ansible-role-$ROLE_NAME geerlingguy.$ROLE_NAME
  - cd geerlingguy.$ROLE_NAME
script:
  # Run tests.
  - molecule test
notifications:
  webhooks: https://galaxy.ansible.com/api/v1/notifications/
ansible/roles/geerlingguy.gitlab/LICENSE
New file
@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2017 Jeff Geerling
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ansible/roles/geerlingguy.gitlab/README.md
New file
@@ -0,0 +1,149 @@
# Ansible Role: GitLab
[![Build Status](https://travis-ci.org/geerlingguy/ansible-role-gitlab.svg?branch=master)](https://travis-ci.org/geerlingguy/ansible-role-gitlab)
Installs GitLab, a Ruby-based front-end to Git, on any RedHat/CentOS or Debian/Ubuntu linux system.
GitLab's default administrator account details are below; be sure to login immediately after installation and change these credentials!
    root
    5iveL!fe
## Requirements
None.
## Role Variables
Available variables are listed below, along with default values (see `defaults/main.yml`):
    gitlab_external_url: "https://gitlab/"
The URL at which the GitLab instance will be accessible. This is set as the `external_url` configuration setting in `gitlab.rb`, and if you want to run GitLab on a different port (besides 80/443), you can specify the port here (e.g. `https://gitlab:8443/` for port 8443).
    gitlab_git_data_dir: "/var/opt/gitlab/git-data"
The `gitlab_git_data_dir` is the location where all the Git repositories will be stored. You can use a shared drive or any path on the system.
    gitlab_backup_path: "/var/opt/gitlab/backups"
The `gitlab_backup_path` is the location where Gitlab backups will be stored.
    gitlab_edition: "gitlab-ce"
The edition of GitLab to install. Usually either `gitlab-ce` (Community Edition) or `gitlab-ee` (Enterprise Edition).
    gitlab_version: ''
If you'd like to install a specific version, set the version here (e.g. `11.4.0-ce.0` for Debian/Ubuntu, or `11.4.0-ce.0.el7` for RedHat/CentOS).
    gitlab_config_template: "gitlab.rb.j2"
The `gitlab.rb.j2` template packaged with this role is meant to be very generic and serve a variety of use cases. However, many people would like to have a much more customized version, and so you can override this role's default template with your own, adding any additional customizations you need. To do this:
  - Create a `templates` directory at the same level as your playbook.
  - Create a `templates\mygitlab.rb.j2` file (just choose a different name from the default template).
  - Set the variable like: `gitlab_config_template: mygitlab.rb.j2` (with the name of your custom template).
### SSL Configuration.
    gitlab_redirect_http_to_https: "true"
    gitlab_ssl_certificate: "/etc/gitlab/ssl/gitlab.crt"
    gitlab_ssl_certificate_key: "/etc/gitlab/ssl/gitlab.key"
GitLab SSL configuration; tells GitLab to redirect normal http requests to https, and the path to the certificate and key (the default values will work for automatic self-signed certificate creation, if set to `true` in the variable below).
    # SSL Self-signed Certificate Configuration.
    gitlab_create_self_signed_cert: "true"
    gitlab_self_signed_cert_subj: "/C=US/ST=Missouri/L=Saint Louis/O=IT/CN=gitlab"
Whether to create a self-signed certificate for serving GitLab over a secure connection. Set `gitlab_self_signed_cert_subj` according to your locality and organization.
    # LDAP Configuration.
    gitlab_ldap_enabled: "false"
    gitlab_ldap_host: "example.com"
    gitlab_ldap_port: "389"
    gitlab_ldap_uid: "sAMAccountName"
    gitlab_ldap_method: "plain"
    gitlab_ldap_bind_dn: "CN=Username,CN=Users,DC=example,DC=com"
    gitlab_ldap_password: "password"
    gitlab_ldap_base: "DC=example,DC=com"
GitLab LDAP configuration; if `gitlab_ldap_enabled` is `true`, the rest of the configuration will tell GitLab how to connect to an LDAP server for centralized authentication.
    gitlab_time_zone: "UTC"
Gitlab timezone.
    gitlab_backup_keep_time: "604800"
How long to keep local backups (useful if you don't want backups to fill up your drive!).
    gitlab_download_validate_certs: true
Controls whether to validate certificates when downloading the GitLab installation repository install script.
    # Email configuration.
    gitlab_email_enabled: "false"
    gitlab_email_from: "gitlab@example.com"
    gitlab_email_display_name: "Gitlab"
    gitlab_email_reply_to: "gitlab@example.com"
Gitlab system mail configuration. Disabled by default; set `gitlab_email_enabled` to `true` to enable, and make sure you enter valid from/reply-to values.
    # SMTP Configuration
    gitlab_smtp_enable: "false"
    gitlab_smtp_address: "smtp.server"
    gitlab_smtp_port: "465"
    gitlab_smtp_user_name: "smtp user"
    gitlab_smtp_password: "smtp password"
    gitlab_smtp_domain: "example.com"
    gitlab_smtp_authentication: "login"
    gitlab_smtp_enable_starttls_auto: "true"
    gitlab_smtp_tls: "false"
    gitlab_smtp_openssl_verify_mode: "none"
    gitlab_smtp_ca_path: "/etc/ssl/certs"
    gitlab_smtp_ca_file: "/etc/ssl/certs/ca-certificates.crt"
Gitlab SMTP configuration; of `gitlab_smtp_enable` is `true`, the rest of the configuration will tell GitLab how to send mails using an smtp server.
    gitlab_nginx_listen_port: 8080
If you are running GitLab behind a reverse proxy, you may want to override the listen port to something else.
    gitlab_nginx_listen_https: "false"
If you are running GitLab behind a reverse proxy, you may wish to terminate SSL at another proxy server or load balancer
    gitlab_nginx_ssl_verify_client: ""
    gitlab_nginx_ssl_client_certificate: ""
If you want to enable [2-way SSL Client Authentication](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-2-way-ssl-client-authentication), set `gitlab_nginx_ssl_verify_client` and add a path to the client certificate in `gitlab_nginx_ssl_client_certificate`.
    gitlab_default_theme: 2
GitLab includes a number of themes, and you can set the default for all users with this variable. See [the included GitLab themes to choose a default](https://github.com/gitlabhq/gitlabhq/blob/master/config/gitlab.yml.example#L79-L85).
## Dependencies
None.
## Example Playbook
    - hosts: servers
      vars_files:
        - vars/main.yml
      roles:
        - { role: geerlingguy.gitlab }
*Inside `vars/main.yml`*:
    gitlab_external_url: "https://gitlab.example.com/"
## License
MIT / BSD
## Author Information
This role was created in 2014 by [Jeff Geerling](http://jeffgeerling.com/), author of [Ansible for DevOps](http://ansiblefordevops.com/).
ansible/roles/geerlingguy.gitlab/defaults/main.yml
New file
@@ -0,0 +1,60 @@
---
# General config.
gitlab_external_url: "https://gitlab/"
gitlab_git_data_dir: "/var/opt/gitlab/git-data"
gitlab_edition: "gitlab-ce"
gitlab_version: ''
gitlab_backup_path: "/var/opt/gitlab/backups"
gitlab_config_template: "gitlab.rb.j2"
# SSL Configuration.
gitlab_redirect_http_to_https: "true"
gitlab_ssl_certificate: "/etc/gitlab/ssl/gitlab.crt"
gitlab_ssl_certificate_key: "/etc/gitlab/ssl/gitlab.key"
# SSL Self-signed Certificate Configuration.
gitlab_create_self_signed_cert: "true"
gitlab_self_signed_cert_subj: "/C=US/ST=Missouri/L=Saint Louis/O=IT/CN=gitlab"
# LDAP Configuration.
gitlab_ldap_enabled: "false"
gitlab_ldap_host: "example.com"
gitlab_ldap_port: "389"
gitlab_ldap_uid: "sAMAccountName"
gitlab_ldap_method: "plain"
gitlab_ldap_bind_dn: "CN=Username,CN=Users,DC=example,DC=com"
gitlab_ldap_password: "password"
gitlab_ldap_base: "DC=example,DC=com"
# SMTP Configuration
gitlab_smtp_enable: "false"
gitlab_smtp_address: "smtp.server"
gitlab_smtp_port: "465"
gitlab_smtp_user_name: "smtp user"
gitlab_smtp_password: "smtp password"
gitlab_smtp_domain: "example.com"
gitlab_smtp_authentication: "login"
gitlab_smtp_enable_starttls_auto: "true"
gitlab_smtp_tls: "false"
gitlab_smtp_openssl_verify_mode: "none"
gitlab_smtp_ca_path: "/etc/ssl/certs"
gitlab_smtp_ca_file: "/etc/ssl/certs/ca-certificates.crt"
# 2-way SSL Client Authentication support.
gitlab_nginx_ssl_verify_client: ""
gitlab_nginx_ssl_client_certificate: ""
# Probably best to leave this as the default, unless doing testing.
gitlab_restart_handler_failed_when: 'gitlab_restart.rc != 0'
# Optional settings.
gitlab_time_zone: "UTC"
gitlab_backup_keep_time: "604800"
gitlab_download_validate_certs: true
gitlab_default_theme: '2'
# Email configuration.
gitlab_email_enabled: "false"
gitlab_email_from: "gitlab@example.com"
gitlab_email_display_name: "Gitlab"
gitlab_email_reply_to: "gitlab@example.com"
ansible/roles/geerlingguy.gitlab/handlers/main.yml
New file
@@ -0,0 +1,5 @@
---
- name: restart gitlab
  command: gitlab-ctl reconfigure
  register: gitlab_restart
  failed_when: gitlab_restart_handler_failed_when | bool
ansible/roles/geerlingguy.gitlab/meta/main.yml
New file
@@ -0,0 +1,28 @@
---
dependencies: []
galaxy_info:
  author: geerlingguy
  description: GitLab Git web interface
  company: "Midwestern Mac, LLC"
  license: "license (BSD, MIT)"
  min_ansible_version: 2.0
  platforms:
    - name: EL
      versions:
        - 6
        - 7
    - name: Debian
      versions:
        - all
    - name: Ubuntu
      versions:
        - all
  galaxy_tags:
    - development
    - web
    - gitlab
    - git
    - repository
    - ci
    - integration
ansible/roles/geerlingguy.gitlab/molecule/default/molecule.yml
New file
@@ -0,0 +1,29 @@
---
dependency:
  name: galaxy
driver:
  name: docker
lint:
  name: yamllint
  options:
    config-file: molecule/default/yaml-lint.yml
platforms:
  - name: instance
    image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos7}-ansible:latest"
    command: ${MOLECULE_DOCKER_COMMAND:-""}
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
    privileged: true
    pre_build_image: true
provisioner:
  name: ansible
  lint:
    name: ansible-lint
  playbooks:
    converge: ${MOLECULE_PLAYBOOK:-playbook.yml}
scenario:
  name: default
verifier:
  name: testinfra
  lint:
    name: flake8
ansible/roles/geerlingguy.gitlab/molecule/default/playbook-version.yml
New file
@@ -0,0 +1,31 @@
---
- name: Converge
  hosts: all
  become: true
  vars:
    gitlab_restart_handler_failed_when: false
  pre_tasks:
    - name: Update apt cache.
      apt: update_cache=true cache_valid_time=600
      when: ansible_os_family == 'Debian'
      changed_when: false
    - name: Remove the .dockerenv file so GitLab Omnibus doesn't get confused.
      file:
        path: /.dockerenv
        state: absent
    - name: Set the test GitLab version number for Debian.
      set_fact:
        gitlab_version: '11.4.0-ce.0'
      when: ansible_os_family == 'Debian'
    - name: Set the test GitLab version number for RedHat.
      set_fact:
        gitlab_version: '11.4.0-ce.0.el7'
      when: ansible_os_family == 'RedHat'
  roles:
    - role: geerlingguy.gitlab
ansible/roles/geerlingguy.gitlab/molecule/default/playbook.yml
New file
@@ -0,0 +1,21 @@
---
- name: Converge
  hosts: all
  become: true
  vars:
    gitlab_restart_handler_failed_when: false
  pre_tasks:
    - name: Update apt cache.
      apt: update_cache=true cache_valid_time=600
      when: ansible_os_family == 'Debian'
      changed_when: false
    - name: Remove the .dockerenv file so GitLab Omnibus doesn't get confused.
      file:
        path: /.dockerenv
        state: absent
  roles:
    - role: geerlingguy.gitlab
ansible/roles/geerlingguy.gitlab/molecule/default/yaml-lint.yml
New file
@@ -0,0 +1,6 @@
---
extends: default
rules:
  line-length:
    max: 140
    level: warning
ansible/roles/geerlingguy.gitlab/tasks/main.yml
New file
@@ -0,0 +1,77 @@
---
- name: Include OS-specific variables.
  include_vars: "{{ ansible_os_family }}.yml"
- name: Check if GitLab configuration file already exists.
  stat: path=/etc/gitlab/gitlab.rb
  register: gitlab_config_file
- name: Check if GitLab is already installed.
  stat: path=/usr/bin/gitlab-ctl
  register: gitlab_file
# Install GitLab and its dependencies.
- name: Install GitLab dependencies.
  package:
    name:
      - openssh-server
      - postfix
      - curl
      - openssl
      - tzdata
    state: present
- name: Download GitLab repository installation script.
  get_url:
    url: "{{ gitlab_repository_installation_script_url }}"
    dest: /tmp/gitlab_install_repository.sh
    validate_certs: "{{ gitlab_download_validate_certs }}"
  when: not gitlab_file.stat.exists
- name: Install GitLab repository.
  command: bash /tmp/gitlab_install_repository.sh
  when: not gitlab_file.stat.exists
- name: Define the Gitlab package name.
  set_fact:
    gitlab_package_name: "{{ gitlab_edition }}{{ gitlab_package_version_separator }}{{ gitlab_version }}"
  when: gitlab_version != ''
- name: Install GitLab
  package:
    name: "{{ gitlab_package_name | default(gitlab_edition) }}"
    state: present
  when: not gitlab_file.stat.exists
# Start and configure GitLab. Sometimes the first run fails, but after that,
# restarts fix problems, so ignore failures on this run.
- name: Reconfigure GitLab (first run).
  command: >
    gitlab-ctl reconfigure
    creates=/var/opt/gitlab/bootstrapped
  failed_when: false
- name: Create GitLab SSL configuration folder.
  file:
    path: /etc/gitlab/ssl
    state: directory
    owner: root
    group: root
    mode: 0700
  when: gitlab_create_self_signed_cert | bool
- name: Create self-signed certificate.
  command: >
    openssl req -new -nodes -x509 -subj "{{ gitlab_self_signed_cert_subj }}"
    -days 3650 -keyout {{ gitlab_ssl_certificate_key }} -out {{ gitlab_ssl_certificate }} -extensions v3_ca
    creates={{ gitlab_ssl_certificate }}
  when: gitlab_create_self_signed_cert | bool
- name: Copy GitLab configuration file.
  template:
    src: "{{ gitlab_config_template }}"
    dest: /etc/gitlab/gitlab.rb
    owner: root
    group: root
    mode: 0600
  notify: restart gitlab
ansible/roles/geerlingguy.gitlab/templates/gitlab.rb.j2
New file
@@ -0,0 +1,74 @@
# The URL through which GitLab will be accessed.
external_url "{{ gitlab_external_url }}"
# gitlab.yml configuration
gitlab_rails['time_zone'] = "{{ gitlab_time_zone }}"
gitlab_rails['backup_keep_time'] = {{ gitlab_backup_keep_time }}
gitlab_rails['gitlab_email_enabled'] = {{ gitlab_email_enabled }}
{% if gitlab_email_enabled == "true" %}
gitlab_rails['gitlab_email_from'] = "{{ gitlab_email_from }}"
gitlab_rails['gitlab_email_display_name'] = "{{ gitlab_email_display_name }}"
gitlab_rails['gitlab_email_reply_to'] = "{{ gitlab_email_reply_to }}"
{% endif %}
# Default Theme
gitlab_rails['gitlab_default_theme'] = "{{ gitlab_default_theme }}"
# Whether to redirect http to https.
nginx['redirect_http_to_https'] = {{ gitlab_redirect_http_to_https }}
nginx['ssl_certificate'] = "{{ gitlab_ssl_certificate }}"
nginx['ssl_certificate_key'] = "{{ gitlab_ssl_certificate_key }}"
# The directory where Git repositories will be stored.
git_data_dirs({"default" => {"path" => "{{ gitlab_git_data_dir }}"} })
# The directory where Gitlab backups will be stored
gitlab_rails['backup_path'] = "{{ gitlab_backup_path }}"
# These settings are documented in more detail at
# https://gitlab.com/gitlab-org/gitlab-ce/blob/master/config/gitlab.yml.example#L118
gitlab_rails['ldap_enabled'] = {{ gitlab_ldap_enabled }}
gitlab_rails['ldap_host'] = '{{ gitlab_ldap_host }}'
gitlab_rails['ldap_port'] = {{ gitlab_ldap_port }}
gitlab_rails['ldap_uid'] = '{{ gitlab_ldap_uid }}'
gitlab_rails['ldap_method'] = '{{ gitlab_ldap_method}}' # 'ssl' or 'plain'
gitlab_rails['ldap_bind_dn'] = '{{ gitlab_ldap_bind_dn }}'
gitlab_rails['ldap_password'] = '{{ gitlab_ldap_password }}'
gitlab_rails['ldap_allow_username_or_email_login'] = true
gitlab_rails['ldap_base'] = '{{ gitlab_ldap_base }}'
# GitLab Nginx
## See https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md
{% if gitlab_nginx_listen_port is defined %}
nginx['listen_port'] = "{{ gitlab_nginx_listen_port }}"
{% endif %}
{% if gitlab_nginx_listen_https is defined %}
nginx['listen_https'] = {{ gitlab_nginx_listen_https }}
{% endif %}
# Use smtp instead of sendmail/postfix
# More details and example configuration at
# https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/smtp.md
gitlab_rails['smtp_enable'] = {{ gitlab_smtp_enable }}
gitlab_rails['smtp_address'] = '{{ gitlab_smtp_address }}'
gitlab_rails['smtp_port'] = {{ gitlab_smtp_port }}
gitlab_rails['smtp_user_name'] = '{{ gitlab_smtp_user_name }}'
gitlab_rails['smtp_password'] = '{{ gitlab_smtp_password }}'
gitlab_rails['smtp_domain'] = '{{ gitlab_smtp_domain }}'
gitlab_rails['smtp_authentication'] = '{{ gitlab_smtp_authentication }}'
gitlab_rails['smtp_enable_starttls_auto'] = {{ gitlab_smtp_enable_starttls_auto }}
gitlab_rails['smtp_tls'] = {{ gitlab_smtp_tls }}
gitlab_rails['smtp_openssl_verify_mode'] = '{{ gitlab_smtp_openssl_verify_mode }}'
gitlab_rails['smtp_ca_path'] = '{{ gitlab_smtp_ca_path }}'
gitlab_rails['smtp_ca_file'] = '{{ gitlab_smtp_ca_file }}'
# 2-way SSL Client Authentication.
{% if gitlab_nginx_ssl_verify_client %}
nginx['ssl_verify_client'] = "{{ gitlab_nginx_ssl_verify_client }}"
{% endif %}
{% if gitlab_nginx_ssl_client_certificate %}
nginx['ssl_client_certificate'] = "{{ gitlab_nginx_ssl_client_certificate }}"
{% endif %}
# To change other settings, see:
# https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#changing-gitlab-yml-settings
ansible/roles/geerlingguy.gitlab/vars/Debian.yml
New file
@@ -0,0 +1,3 @@
---
gitlab_package_version_separator: '='
gitlab_repository_installation_script_url: "https://packages.gitlab.com/install/repositories/gitlab/{{ gitlab_edition }}/script.deb.sh"
ansible/roles/geerlingguy.gitlab/vars/RedHat.yml
New file
@@ -0,0 +1,3 @@
---
gitlab_package_version_separator: '-'
gitlab_repository_installation_script_url: "https://packages.gitlab.com/install/repositories/gitlab/{{ gitlab_edition }}/script.rpm.sh"
ansible/roles/infra-ec2-template-generate/defaults/main.yml
@@ -95,107 +95,186 @@
aws_ami_region_mapping:
  ap-south-1:
    RHEL76GOLD: ami-0656c5f7881490f7a # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-0c6ec6988a8df3acc # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-952879fa # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0aa4317636e016115 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-5c2f7e33 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-03087b28576b37511 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-0dfd6c47961875b86 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-069b8cf30ef60e8aa # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-0d08c1bf7e46a5840 # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-01d03db4f15785967 # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-0f081411c04e148ab # Windows_Server-2019-English-Full-Base-2019.11.13
  eu-west-3:
    RHEL76GOLD: ami-0a74212566be8f9e2 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-0a0167e3e2a1d1d9b # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-69d06614 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-039346fed23fb53ad # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-66d0661b # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-080d3d8def91e4f44 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-0b9d191a8259d92e2 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-08075bd104313685c # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-072e7e4e02eeb267d # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-013d8e43691bee8e8 # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-01ce756cc8a299d0a # Windows_Server-2019-English-Full-Base-2019.11.13
  eu-west-2:
    RHEL76GOLD: ami-051fb39c3a16c8a85 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-01f010afd559615b9 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-55bca731 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0ac5fae255ddac6f6 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-b4b3a8d0 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0699aabf510a3f2f8 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-0964d8bb6ca66d551 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-055831cb3e2a3fb18 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-0d3900ac08ee9aa1c # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-0f7dea7db52f4eddb # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-01ce80a64fb8cb5e9 # Windows_Server-2019-English-Full-Base-2019.11.13
  eu-west-1:
    RHEL76GOLD: ami-02a1dcbcc4f50bdb9 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-0c51cd02617947143 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-b7b6d3ce # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-092acf20fad7f7795 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-ccb7d2b5 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0370c806916d2a17f # Windows_Server-2012-R2_RTM-English-64Bit-HyperV-2018.09.15
    RHEL81: ami-0534d3148e3ce93d7 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-09eb28f10d99d7ef7 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-0737ec3d03742d38c # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-0e4373deed7b23043 # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-00f8336af4b6b40bf # Windows_Server-2019-English-Full-Base-2019.11.13
  ap-northeast-2:
    RHEL76GOLD: ami-0983c35dbbdd0f69e # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-031161cd3182e012a # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-9fa201f1 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0d226f15e3e46903a # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-90a201fe # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-02ee840e33e7c2244 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-0dbadd8c47cf535fd # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-0e0539efa8c604e98 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-00ca4e793a7f026d7 # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-0dff19cc751766905 # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-07b58618e45d4362d # Windows_Server-2019-English-Full-Base-2019.11.13
  ap-northeast-1:
    RHEL76GOLD: ami-0b1fa7354371d3331 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-0bf9ecb88f5719e17 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-ccf695aa # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0b517025bb2f0ad4a # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-36f09350 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-08e310c576c077de1 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-0302fadfb901ae198 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-003d54e8a61bf0615 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-0f8870c207dc4af69 # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-0109f4d579a89a0b6 # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-0c63fb8188f151fb7 # Windows_Server-2019-English-Full-Base-2019.11.13
  sa-east-1:
    RHEL76GOLD: ami-06addb952810f166b # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-93b693ff # RHEL-7.5_HVM_GA-JBEAP-7.1.2-20180629-x86_64-1-Access2-GP2
    RHEL74GOLD: ami-dc014db0 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-01c56172f9db84834 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-1a064a76 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-079f7c686ba77c199 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-0bac1917c46ed1418 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-008a45dbdbd743c04 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-0f06dcfea3d436659 # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-0cf0e7fb5d2493b57 # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-0b27170c41289fc50 # Windows_Server-2019-English-Full-Base-2019.11.13
  ca-central-1:
    RHEL76GOLD: ami-0ed2e023e005c9178 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-e320ad87 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-2a00854e # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-fc20ad98 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-71018415 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-020be7519c99e8064 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-0eec8704b9b12656a # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-0a633699f800842b7 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-07cf57bc6e0b66c11 # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-08673d963f6845dad # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-07d23537f44fe67c1 # Windows_Server-2019-English-Full-Base-2019.11.13
  ap-southeast-1:
    RHEL76GOLD: ami-070467cd1ef12f289 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-0f44e46fa59e902b6 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-8193eafd # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-09fc728e15fbfb535 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-8d90e9f1 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0906117a55c70d5e7 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-00d042f59a75c06e7 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-07de3a63467109bd0 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-09082d40574490760 # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-04666e19c9439a2e3 # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-007e1dbff2381b636 # Windows_Server-2019-English-Full-Base-2019.11.13
  ap-southeast-2:
    RHEL76GOLD: ami-0499d01ff89fea5e6 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-0066ef2f9c72fad96 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-dd9668bf # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0a61d60bde3940420 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-e1996783 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-09fb195e1d6625aab # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-0e3696cc3d156dd22 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-02ed9c9708d50eb1a # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-0202f51d204a8428f # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-0416c5cd08406d47d # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-0fb8890c7a7ca1457 # Windows_Server-2019-English-Full-Base-2019.11.13
  eu-central-1:
    RHEL76GOLD: ami-012838bc227c83b03 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-07d3f0705bebac978 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-b3d841dc # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-05ba90b00a46d83fa # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-8a21bfe5 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-07b8613a03480d559 # Windows_Server-2012-R2_RTM-English-64Bit-HyperV-2018.09.15
    RHEL81: ami-067e4f6fa56351e07 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-0d3fa57abf075dc09 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-02a6791b44938cfcd # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-02008f43af65efe69 # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-09fe2745618d2af42 # Windows_Server-2019-English-Full-Base-2019.11.13
  us-east-1:
    RHEL76GOLD: ami-0f83261cb7d041a1b #RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-0456c465f72bd0c95 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-c5a094bf # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0394fe9914b475c53 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-76a3970c # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-003027603b9c132b3 # Windows_Server-2012-R2_RTM-Japanese-64Bit-SQL_2016_SP1_Express-2018.09.15
    RHEL81: ami-09b947b170ccd0dbc # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    # WIN2016CORE: ami-0e7c21400e27171b2 # Windows_Server-2016-English-Core-Base Custom (2019.11)
    # WIN2016FULL: ami-09bdbb4e91a102190 # Windows_Server-2016-English-Full-Base Custom (2019.11)
    # WIN2019CORE: ami-08086d73e6b1b76d8 # Windows_Server-2019-English-Core-Base Custom (2019.11)
    # WIN2019FULL: ami-0cb644506ed6091c9 # Windows_Server-2019-English-Full-Base Custom (2019.11)
    WIN2016CORE: ami-020cff55b06f0b7c0 # Windows_Server-2016-English-Core-Base  (2019.11)
    WIN2016FULL: ami-08c7081300f7d9abb # Windows_Server-2016-English-Full-Base  (2019.11)
    WIN2019CORE: ami-0cce25b71e3c7c00f # Windows_Server-2019-English-Core-Base  (2019.11)
    WIN2019FULL: ami-08b11fc5bd2026dee # Windows_Server-2019-English-Full-Base  (2019.11)
  us-east-2:
    RHEL76GOLD: ami-0bdf2c4eae6c71d2b # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-04268981d7c33264d # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-9db09af8 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0376bbf9be9eac670 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-cebe94ab # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-02fa46b8e1a36044b # Windows_Server-2012-R2_RTM-English-P3-2018.09.15
    RHEL81: ami-0fdea47967124a409 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-0cad7ba8362fdf600 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-02dca99d899d09cb3 # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-06ed2e6548512523c # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-01b9e78fb84ac8b2f # Windows_Server-2019-English-Full-Base-2019.11.13
  us-west-1:
    RHEL76GOLD: ami-00ef21b27071fe235 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-02574210e91c38419 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-6f030e0f # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0bdc0ff10fb093057 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-c8020fa8 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0f9c4789993c313f7 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
    RHEL81: ami-008d471ffd812f4b8 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-0a571fc3ce06e3517 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-0255ad7855945d5ef # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-0f93e82396e11a3ef # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-0052629573c8e3eda # Windows_Server-2019-English-Full-Base-2019.11.13
  us-west-2:
    RHEL76GOLD: ami-0fae471393c00f216 # RHEL-7.6_HVM-20190618-x86_64-0-Access2-GP2
    RHEL75GOLD: ami-0e6bab6682ec471c0 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-c405b8bc # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-096510cab1b6b2c6d # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-1607ba6e # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0d786d5cc800b2456 # Windows_Server-2012-R2_RTM-English-64Bit-HyperV-2018.09.15
    RHEL81: ami-0ae93796700af07d3 # RHEL-8.1.0_HVM-20191029-x86_64-0-Hourly2-GP2
    WIN2016CORE: ami-01128dbe7ee60f431 # Windows_Server-2016-English-Core-Base-2019.11.13
    WIN2016FULL: ami-000bf92d1a21bf9ac # Windows_Server-2016-English-Full-Base-2019.11.13
    WIN2019CORE: ami-0a9cf554fc5042df7 # Windows_Server-2019-English-Core-Base-2019.11.13
    WIN2019FULL: ami-0d5ab31b93c643ca8 # Windows_Server-2019-English-Full-Base-2019.11.13
ansible/roles/set-repositories/tasks/epel-repo.yml
New file
@@ -0,0 +1,6 @@
---
- name: Drop EPEL repo file
  template:
    src: epel_template.j2
    dest: /etc/yum.repos.d/epel.repo
ansible/roles/set-repositories/tasks/main.yml
@@ -18,3 +18,7 @@
    - name: Configure Repository File
      import_tasks: ./file-repos.yml
      when: repo_method == "file"
    - name: Configure EPEL
      import_tasks: ./epel-repo.yml
      when: enable_epel | d(false) | bool
ansible/roles/set-repositories/tasks/rhn-repos.yml
@@ -18,7 +18,27 @@
    pool_ids: "{{ rhsm_pool_ids }}"
    auto_attach: false
- name: "Run 'subscription-manager to disable/enable repos"
# TODO: should take pool ids from a var
- name: get product pool id
  shell: /usr/bin/subscription-manager list --all --available --matches="*{{rhn_pool_id_string}}*" | awk '/Pool ID/ {print $3}' | head -1
  # command: subscription-manager list --all --available --matches="OpenShift Container Platform" | awk '/Pool ID/ {print $3}' | head -1
  register: pool_id
  until: pool_id is succeeded
  retries: 10
  delay: 5
- name: attach host to subscription pool
  shell: /usr/bin/subscription-manager attach --pool={{ pool_id.stdout }}
  register: task_result
  until: task_result.rc == 0
  retries: 10
  delay: 5
- name: "Run subscription-manager to disable all repos"
  command: subscription-manager repos --disable "*"
  when: disable_default_repos | d(false)
- name: "Run subscription-manager to enable repos"
  command: >-
    subscription-manager repos {% for repo in rhel_repos %}
    --enable={{ repo }}
ansible/roles/set-repositories/templates/epel_template.j2
New file
@@ -0,0 +1,8 @@
[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch
mirrorlist=http://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=0
#gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
ansible/roles/skylight-ansible-tower/defaults/main.yml
New file
@@ -0,0 +1,19 @@
---
# defaults file for ansible-tower
ansible_devel: false
dns_domain_name: "example.com"
# AD login info
authconfig_options:
  - "--enablesssd"
  - "--enablesssdauth"
  - "--enablemkhomedir"
  - "--enablelocauthorize"
  - "--update"
  - "--nostart"
ldap_search_base: "DC=example,DC=com"
ldap_access_filter: "(&(objectClass=user)(memberOf=CN=LinuxServers,CN=Users,DC=example,DC=com))"
#ldap_access_filter: "(&(objectClass=user)(|(memberOf=CN=OSunix,OU=UnixServers,DC=example,DC=com)(memberOf=CN=DBAunix,OU=UnixServers,DC=example,DC=com)))"
#ldap_access_filter: "(&(objectClass=user)(|(sAMAccountName=john)(sAMAccountName=merry)))"
towerchk: undefined
ansible/roles/skylight-ansible-tower/files/classroom_inventory.json
New file
@@ -0,0 +1,9 @@
{
  "name": "Classroom inventory",
  "description": "This is the classroom inventory",
  "organization": 1,
  "kind": "",
  "host_filter": null,
  "variables": "ansible_connection: local\n",
  "insights_credential": null
}
ansible/roles/skylight-ansible-tower/files/default_inventory.json
New file
@@ -0,0 +1,9 @@
{
  "name": "Default inventory",
  "description": "This is the default inventory",
  "organization": 1,
  "kind": "",
  "host_filter": null,
  "variables": "ansible_port: 5986\nansible_connection: winrm\nansible_winrm_server_cert_validation: ignore\nansible_winrm_transport: credssp",
  "insights_credential": null
}
ansible/roles/skylight-ansible-tower/handlers/main.yml
New file
@@ -0,0 +1,8 @@
---
- name: restart sssd
  service:
    name: sssd
    state: restarted
- name: restart tower
  command: ansible-tower-service restart
ansible/roles/skylight-ansible-tower/tasks/create-resources.yml
New file
@@ -0,0 +1,239 @@
---
- name: Remove repo directory
  file:
    path: /tmp/do417
    state: absent
- name: Get ssh key for Github
  copy:
    src: "{{ github_ssh_key }}"
    dest: /tmp/github_ssh_key
    mode: 0400
    owner: "{{ ansible_user }}"
- name: Get lab source code
  git:
    clone: yes
    force: yes
    dest: "/tmp/do417"
    repo: "git@github.com:RedHatTraining/do417.git"
    key_file: /tmp/github_ssh_key
    accept_hostkey: true
- name: Remove ssh key for Github
  file:
    path: /tmp/github_ssh_key
    state: absent
- name: Remove .git directory
  file:
    path: /tmp/do417/.git
    state: absent
- name: Determining material directories
  command: find /tmp/do417/classroom/infrastructure/playbooks/files/src -maxdepth 1 -mindepth 1 -type d -printf '%f\n'
  register: repos_name
- name: Wait for Tower to be reachable
  wait_for:
    port: 443
    delay: 5
- name: Retrieve default organization ID
  uri:
    url:  "https://localhost/api/v2/organizations/?name=Default"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: organization_id
- name: Retrieve default inventory ID
  uri:
    url: "https://localhost/api/v2/inventories/?name=Default+inventory"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: inventory_id
- name: Create GitLab credentials
  uri:
    url:  "https://localhost/api/v2/credentials/"
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ lookup('template','gitlab-creds.json.j2') }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
- name: Retrieve credentials ID
  uri:
    url:  "https://localhost/api/v2/credentials/?name=GitLab"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: gitlab_credentials_id
- name: Create DevOps credentials
  uri:
    url:  "https://localhost/api/v2/credentials/"
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ lookup('template','devops-creds.json.j2') }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
- name: Retrieve credentials ID
  uri:
    url:  "https://localhost/api/v2/credentials/?name=DevOps"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: devops_credentials_id
- name: Create Tower credentials
  uri:
    url:  "https://localhost/api/v2/credentials/"
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ lookup('template','tower-creds.json.j2') }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
- name: Create Git projects
  uri:
    url:  "https://localhost/api/v2/projects/"
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body:
      name: "{{ item }} repository"
      description: "{{ item }} project"
      local_path: ""
      scm_type: "git"
      scm_url: "https://gitlab.{{ dns_domain_name }}/student/{{ item }}.git"
      scm_branch: "master"
      scm_clean: false
      scm_delete_on_update: false
      credential: "{{ gitlab_credentials_id.json.results[0].id }}"
      timeout: 0
      organization: "{{ organization_id.json.results[0].id }}"
      scm_update_on_launch: true
      scm_update_cache_timeout: 0
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
  with_items: "{{ repos_name.stdout_lines }}"
- name: Retrieve projects ID
  uri:
    url:  "https://localhost/api/v2/projects/?name={{ item }}+repository"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  with_items: "{{ repos_name.stdout_lines }}"
  register: projects_id
- name: Create job templates
  uri:
    url:  "https://localhost/api/v2/job_templates/"
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body:
      name: "Run {{ item.json.results[0].description }}"
      description: Use this job template to run your playbooks
      job_type: run
      inventory: "{{ inventory_id.json.results[0].id }}"
      project:  "{{ item.json.results[0].id }}"
      playbook: dummy.yml
      forks: 0
      verbosity: 0
      force_handlers: false
      timeout: 0
      use_fact_cache: false
      ask_diff_mode_on_launch: false
      ask_variables_on_launch: false
      ask_limit_on_launch: false
      ask_tags_on_launch: false
      ask_skip_tags_on_launch: false
      ask_job_type_on_launch: false
      ask_verbosity_on_launch: false
      ask_inventory_on_launch: false
      ask_credential_on_launch: false
      survey_enabled: true
      become_enabled: false
      diff_mode: false
      allow_simultaneous: false
      custom_virtualenv:
      job_slice_count: 1
      credential: "{{ devops_credentials_id.json.results[0].id }}"
      vault_credential:
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
  with_items: "{{ projects_id.results }}"
ansible/roles/skylight-ansible-tower/tasks/main.yml
New file
@@ -0,0 +1,187 @@
---
- name: Add Ansible repo - transition to engine...
  yum_repository:
    name: ansible
    description: Ansible for Enterprise Linux 7
    baseurl: http://releases.ansible.com/ansible/rpm/release/epel-7-x86_64/
    enabled: yes
    gpgcheck: no
- name: Install packages
  yum:
    name:
      - vim
      - git
      - sshpass
      - ansible
      - nano
      - bind-utils
      - python-pip
      - python-ldap3
    state: present
    use_backend: dnf
#- name: Install devel branch
#  pip:
#    name: git+https://github.com/ansible/ansible.git@devel#egg=ansible
#  when: ansible_devel | bool
- name: Create /etc/ansible directory
  file:
    path: /etc/ansible
    state: directory
    mode: 0755
- name: Create /etc/ansible/ansible.cfg
  template:
    src: ansible.cfg.j2
    dest: /etc/ansible/ansible.cfg
    owner: root
    group: root
    mode: 0644
- name: install the last version of OpenSSL
  pip:
    name: pyOpenSSL
    state: latest
- name: Install dependencies for Kerberos auth
  yum:
    name:
      - python-devel
      - krb5-devel
      - krb5-libs
      - krb5-workstation
      - python-kerberos
      - gcc
    state: present
    use_backend: dnf
- name: Install pywinrm for connecting to windows hosts
  pip:
    name:
      - pywinrm>=0.2.2
      - pywinrm[kerberos]
      - pywinrm[credssp]
#- name: Install requests-credssp for Tower 3.2
#  pip:
#    name: requests-credssp
#  when: towerversion < 3.3
- name: Configure KRB5.conf file
  template:
    src: krb5.conf.j2
    dest: /etc/krb5.conf
    owner: root
    group: root
    mode: 0604
#- name: Install dependencies for domain join
#  package:
#    name:
#      - oddjob
#      - oddjob-mkhomedir
#      - openldap-clients
#      - realmd
#      - sssd
#      - samba-common-tools
#      - authconfig
#    state: present
### Add something to check if it is already in a domain?
#- name: Install pexpect using pip
#  pip:
#    name: pexpect
#- name: Check if machine is bound
#  shell: "realm list | grep sssd"
#  register: realmd_bound
#  changed_when: false
#  ignore_errors: true
#- name: Join the Domain
#  expect:
#    command: "realm join -U Admin@{{ dns_domain_name }} {{ dns_domain_name | upper }}"
#    responses:
#      Password for *: "{{ windows_password }}"
#  register: realm_join_cmd_result
#  #no_log: true         # Uncomment this when in prod... (clear text)
#  #changed_when: realm_join_cmd_result.rc != 100
#  #failed_when: realm_join_cmd_result.rc not in [0, 100]
#  when: realmd_bound is failed
#- name: Add ad group to sudoers
#  lineinfile:
#    dest: /etc/sudoers
#    line: "%Ansible\\ Users    ALL=(ALL)    NOPASSWD: ALL"
#    insertafter: "^%wheel"
#  when: realmd_bound is failed
#- name: Get Kerberos Ticket
#  command: echo -n "{{ domain_admin_password }}" | kinit Admin@{{ dns_domain_name | upper }}
#  #command: kinit -k -t /etc/krb5.keytab {{ ansible_hostname | upper }}$\@{{ adauth_realm }}
#  args:
#    creates: /tmp/krb5cc_0
#- name: Check if authconfig ran before
#  command: "/bin/egrep '^auth.*sufficient.*pam_sss.so' /etc/pam.d/system-auth"
#  register: authconfig_run
#  failed_when: False
#  changed_when: False
#- name: Configure Server to use SSSD for auth
#  command: /usr/sbin/authconfig {{ authconfig_options | join(" ") }}
#  when: authconfig_run.rc != 0
#- name: Configure SSSD to use AD for authentication
#  template:
#    src: sssd.conf.j2
#    dest: /etc/sssd/sssd.conf
#    owner: root
#    group: root
#    mode: 0600
#  notify: restart sssd
#- name: Ensure SSSD is started and enabled on boot
#  service:
#    name: sssd
#    state: started
#    enabled: yes
#- name: Ensure oddjobd for mkhomedir is started and enabled on boot
#  service:
#    name: oddjobd
#    state: started
#    enabled: yes
- name: Copy student inventory to host
  template:
    src: host_inventory.j2
    dest: /etc/ansible/hosts
    owner: root
    group: root
    mode: 0644
    backup: yes
- name: Allow insecure git repos for self signed certificates
  command: git config --global http.sslVerify "false"
- name: Set git user
  command: git config --global user.name "{{ user_prefix }}{{ inventory_hostname | regex_replace('\\D') }}"
- name: Set git user email
  command: git config --global user.email "{{ user_prefix }}{{ inventory_hostname | regex_replace('\\D') }}@{{ dns_domain_name }}"
- name: Set git to cache credentials
  command: git config --global credential.helper cache
- name: Update git to credential timeout after 1 day
  command: git config --global credential.helper 'cache --timeout=86400'
- include_tasks: setup.yml
# Creation of custom DO417 resources
# TODO: where to get these from?
- include_tasks: create-resources.yml
ansible/roles/skylight-ansible-tower/tasks/setup.yml
New file
@@ -0,0 +1,464 @@
---
- name: Check if we need to do installer things
  uri:
    url: https://localhost/api/v1/ping/
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    validate_certs: False
  register: checkout
  ignore_errors: True
- name: Set condtional if the above didn't error
  set_fact:
    towerchk: "{{ checkout.json.version }}"
  when: checkout.json is defined
- name: Download tower installer
  get_url:
    url: https://releases.ansible.com/ansible-tower/setup/ansible-tower-setup-{{ towerversion }}.tar.gz
    dest: /tmp/ansible-tower-setup-{{ towerversion }}.tar.gz
    mode: 0640
  when: towerchk not in towerversion
- name: Extract installer
  unarchive:
    src: /tmp/ansible-tower-setup-{{ towerversion }}.tar.gz
    dest: /tmp/
    remote_src: True
  when: towerchk not in towerversion
- name: Template inventory file
  template:
    src: inventory
    dest: /tmp/ansible-tower-setup-{{ towerversion }}/inventory
  when: towerchk != towerversion
- name: Create the environment file (fixes the incorrect repository lookup)
  copy:
   dest: /tmp/ansible-tower-setup-{{ towerversion }}/install_vars.yml
   content: |
     redhat_aws_rhui_repos:
       - rhel-server-rhui-rhscl-7-rpms
       - rhel-7-server-rhui-extras-rpms
- name: Run the tower installer
  shell: ./setup.sh -e "@install_vars.yml"
  args:
    chdir: /tmp/ansible-tower-setup-{{ towerversion }}
  when: towerchk not in towerversion
- name: Wait for tower to be up
  uri:
    url: https://localhost/api/v1/ping/
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    validate_certs: False
    force_basic_auth: yes
  register: check2
  until: check2.json is defined and check2.json.version in towerversion
  retries: 10
  delay: 30
  when: towerchk not in towerversion
- name: Post license key
  uri:
    url: https://localhost/api/v1/config/
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ tower_license }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
  ignore_errors: True
- name: Add LDAP Config
  uri:
    url: https://localhost/api/v2/settings/ldap/
    method: PATCH
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ lookup('template','ldap_conf.json.j2') }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
- set_fact:
    userid: "{{ inventory_hostname | regex_replace('[^0-9]', '') }}"
- name: Delete demo inventory
  uri:
    url:  https://localhost/api/v2/inventories/1/
    method: DELETE
    user: admin
    password: "{{ tower_admin_password }}"
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 202
      - 204
      - 400
      - 404
  register: response
  changed_when: response.status == 204
- name: Delete demo project
  uri:
    url:  https://localhost/api/v2/projects/4/
    method: DELETE
    user: admin
    password: "{{ tower_admin_password }}"
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 202
      - 204
      - 400
      - 404
  register: response
  changed_when: response.status == 204
- name: Delete demo template
  uri:
    url:  https://localhost/api/v2/job_templates/5/
    method: DELETE
    user: admin
    password: "{{ tower_admin_password }}"
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 202
      - 204
      - 400
      - 404
  register: response
  changed_when: response.status == 204
- name: Delete demo credential
  uri:
    url:  https://localhost/api/v2/credentials/1/
    method: DELETE
    user: admin
    password: "{{ tower_admin_password }}"
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 202
      - 204
      - 400
      - 404
  register: response
  changed_when: response.status == 204
- name: Create default inventory
  uri:
    url:  https://localhost/api/v2/inventories/
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ lookup('file','default_inventory.json') }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
- name: Retrieve default inventory ID
  uri:
    url:  "https://localhost/api/v2/inventories/?name=Default+inventory"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: default_inventory_id
- name: Create group in default inventory
  uri:
    url:  "https://localhost/api/v2/groups/"
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body:
      name: "Windows"
      description: ""
      inventory: "{{ default_inventory_id.json.results[0].id }}"
      variables: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
- name: Retrieve default group ID
  uri:
    url:  "https://localhost/api/v2/groups/?name=Windows"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: group_id
- name: Create host in default group
  uri:
    url:  https://localhost/api/v2/hosts/
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ lookup('template','win1_host.json.j2') }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
- name: Retrieve host ID
  uri:
    url:  "https://localhost/api/v2/hosts/?name=win1.{{ dns_domain_name }}"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: host_id
- name: Associate host to group
  uri:
    url:  "https://localhost/api/v2/groups/{{ group_id.json.results[0].id }}/hosts/"
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body:
      '{ "id": {{ host_id.json.results[0].id | int }} }'
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 204
      - 400
  register: response
  changed_when: response.status == 204
- name: Create classroom inventory
  uri:
    url:  https://localhost/api/v2/inventories/
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ lookup('file','classroom_inventory.json') }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
- name: Retrieve classroom inventory ID
  uri:
    url:  "https://localhost/api/v2/inventories/?name=Classroom+inventory"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: classroom_inventory_id
- name: Create group in classroom inventory
  uri:
    url:  "https://localhost/api/v2/groups/"
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body:
      name: "Tower"
      description: ""
      inventory: "{{ classroom_inventory_id.json.results[0].id }}"
      variables: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
- name: Retrieve classroom group ID
  uri:
    url:  "https://localhost/api/v2/groups/?name=Tower"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: group_id
- name: Create host in tower group
  uri:
    url:  https://localhost/api/v2/hosts/
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ lookup('template','tower_host.json.j2') }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 201
      - 400
  register: response
  changed_when: response.status == 201
- name: Retrieve tower host ID
  uri:
    url:  "https://localhost/api/v2/hosts/?name=tower"
    method: GET
    user: admin
    password: "{{ tower_admin_password }}"
    body: ""
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
  register: host_id
- name: Associate host to group
  uri:
    url:  "https://localhost/api/v2/groups/{{ group_id.json.results[0].id }}/hosts/"
    method: POST
    user: admin
    password: "{{ tower_admin_password }}"
    body:
      '{ "id": {{ host_id.json.results[0].id | int }} }'
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 204
      - 400
  register: response
  changed_when: response.status == 204
- name: Add win_shell/win_feature/win_reboot to allowed adhoc modules
  uri:
    url:  https://localhost/api/v2/settings/all/
    method: PATCH
    user: admin
    password: "{{ tower_admin_password }}"
    body: "{{ lookup('template','tower_config_adhoc.json.j2') }}"
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 204
      - 400
  register: response
  changed_when: response.status == 200
- name: Set Base URL of Tower to resolve issues with websocket
  uri:
    url:  https://localhost/api/v2/settings/system/
    method: PATCH
    user: admin
    password: "{{ tower_admin_password }}"
    body: '{ "TOWER_URL_BASE": "https://tower.{{ dns_domain_name }}" }'
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 204
      - 400
  register: response
  changed_when: response.status == 200
- name: Change timeout default value
  uri:
    url:  "https://localhost/api/v2/settings/authentication/"
    method: PATCH
    user: admin
    password: "{{ tower_admin_password }}"
    body: '{ "SESSION_COOKIE_AGE": 14400 }'
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 204
      - 400
  register: response
  changed_when: response.status == 200
- name: Change Tower settings for Git and Galaxy SSL validation
  uri:
    url:  "https://localhost/api/v2/settings/jobs/"
    method: PATCH
    user: admin
    password: "{{ tower_admin_password }}"
    body: '{"AWX_TASK_ENV": {"GALAXY_IGNORE_CERTS": "TRUE","GIT_SSL_NO_VERIFY": "TRUE"}}'
    body_format: json
    validate_certs: False
    force_basic_auth: yes
    status_code:
      - 200
      - 204
      - 400
  register: response
  changed_when: response.status == 200
  # RM: Manual restart since we need the next playbook to
  # to be able to clone the repos
- name: restart tower
  command: ansible-tower-service restart
ansible/roles/skylight-ansible-tower/templates/ansible-hosts.j2
New file
@@ -0,0 +1,7 @@
{% for item in groups %}
[{{item}}]
{%   for entry in groups[item] %}
{{ entry }} ansible_ssh_host={{hostvars[entry]["ansible_ssh_host"]}} ansible_ssh_port={{hostvars[entry]["ansible_ssh_port"]|default("22")}} ansible_ssh_user={{hostvars[entry]["ansible_ssh_user"]}} ansible_ssh_pass={{hostvars[entry]["ansible_ssh_pass"]}} ansible_ssh_connection={{hostvars[entry]["ansible_ssh_connection"]}}
{%   endfor %}
{% endfor %}
ansible/roles/skylight-ansible-tower/templates/ansible.cfg.j2
New file
@@ -0,0 +1,7 @@
[defaults]
connection = smart
timeout = 60
forks = 10
inventory = /etc/ansible/hosts
host_key_checking = False
ansible/roles/skylight-ansible-tower/templates/devops-creds.json.j2
New file
@@ -0,0 +1,10 @@
{
  "name": "DevOps",
  "description": "DevOps Credentials",
  "organization": 1,
  "credential_type": 1,
  "inputs": {
    "username": "devops",
    "password": "{{ windows_password }}"
  }
}
ansible/roles/skylight-ansible-tower/templates/gitlab-creds.json.j2
New file
@@ -0,0 +1,10 @@
{
  "name": "GitLab",
  "description": "GitLab Credentials",
  "organization": 1,
  "credential_type": 2,
  "inputs": {
    "username": "{{ user_prefix }}",
    "password": "{{ windows_password }}"
  }
}
ansible/roles/skylight-ansible-tower/templates/host_inventory.j2
New file
@@ -0,0 +1,44 @@
[windows_hosts]
{% for host in hostvars %}
{%   if "win1" in host %}
{{ hostvars[host].instance_name }}.{{ dns_domain_name }} ansible_host={{ hostvars[host].private_ip_address }} ansible_user={{ hostvars[host].ansible_user }} ansible_password="{{ windows_password }}" private_ip={{ hostvars[host].private_ip_address }}
{%   elif "win2" in host %}
{{ hostvars[host].instance_name }}.{{ dns_domain_name }} ansible_host={{ hostvars[host].private_ip_address }} ansible_user={{ hostvars[host].ansible_user }} ansible_password="{{ windows_password }}" private_ip={{ hostvars[host].private_ip_address }}
{%   elif "workstation" in host %}
{{ hostvars[host].instance_name }}.{{ dns_domain_name }} ansible_host={{ hostvars[host].private_ip_address }} ansible_user={{ hostvars[host].ansible_user }} ansible_password="{{ workstation_password }}" private_ip={{ hostvars[host].private_ip_address }}
{%   endif %}
{% endfor %}
{% for group in groups %}
{% if 'tag' not in group and 'unknowns' not in group and 'ungrouped' not in group and 'linux' not in group and 'towers' not in group and 'gitlab' not in group and 'bastions' not in group %}
[{{group}}]
{%   for entry in groups[group] %}
{%     for host in hostvars %}
{%       if entry == host and 'bastion' not in entry %}
{{ hostvars[host].instance_name }}.{{ dns_domain_name }} ansible_host={{ hostvars[host].private_ip_address }}
{%       endif %}
{%     endfor %}
{%   endfor %}
{% endif %}
{% endfor %}
[windows_hosts:vars]
ansible_connection=winrm
ansible_winrm_transport=credssp
ansible_winrm_server_cert_validation=ignore
ansible_port=5986
[workstations:vars]
ansible_connection=winrm
ansible_winrm_transport=credssp
ansible_winrm_server_cert_validation=ignore
ansible_port=5986
[activedirectories:vars]
ansible_connection=winrm
ansible_winrm_transport=credssp
ansible_winrm_server_cert_validation=ignore
ansible_port=5986
ansible_user=Administrator
ansible_password="{{ windows_password }}"
ansible/roles/skylight-ansible-tower/templates/inventory
New file
@@ -0,0 +1,23 @@
[tower]
localhost ansible_connection=local
[database]
[all:vars]
admin_password='{{tower_admin_password}}'
pg_host=''
pg_port=''
pg_database='awx'
pg_username='awx'
pg_password='{{ pgpass }}'
rabbitmq_port=5672
rabbitmq_vhost=tower
rabbitmq_username=tower
rabbitmq_password='{{ rabbitpass }}'
rabbitmq_cookie=cookiemonster
# Needs to be true for fqdns and ip addresses
rabbitmq_use_long_name=false
ansible/roles/skylight-ansible-tower/templates/krb5.conf.j2
New file
@@ -0,0 +1,25 @@
# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log
[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
 default_realm = {{ dns_domain_name | upper }}
 default_ccache_name = KEYRING:persistent:%{uid}
[realms]
{{ dns_domain_name | upper }} = {
 kdc = windc.{{ dns_domain_name }}:88
}
[domain_realm]
{{ dns_domain_name }} = {{ dns_domain_name | upper }}
ansible/roles/skylight-ansible-tower/templates/ldap_conf.json.j2
New file
@@ -0,0 +1,39 @@
{
    "AUTH_LDAP_SERVER_URI": "ldap://windc.{{ dns_domain_name }}:389",
    "AUTH_LDAP_BIND_DN": "Admin@{{ dns_domain_name }}",
    "AUTH_LDAP_BIND_PASSWORD": "{{ windows_password }}",
    "AUTH_LDAP_START_TLS": false,
    "AUTH_LDAP_CONNECTION_OPTIONS": {
        "OPT_NETWORK_TIMEOUT": 30,
        "OPT_REFERRALS": 0
    },
    "AUTH_LDAP_USER_SEARCH": [
        "{{ tower_ldap_search_dn }}",
        "SCOPE_SUBTREE",
        "(sAMAccountName=%(user)s)"
    ],
    "AUTH_LDAP_USER_DN_TEMPLATE": null,
    "AUTH_LDAP_USER_ATTR_MAP": {
        "first_name": "givenName",
        "last_name": "sn",
        "email": "mail"
    },
    "AUTH_LDAP_GROUP_SEARCH": [
        "{{ tower_ldap_search_dn }}",
        "SCOPE_SUBTREE",
        "(objectClass=group)"
    ],
    "AUTH_LDAP_GROUP_TYPE": "MemberDNGroupType",
    "AUTH_LDAP_REQUIRE_GROUP": "",
    "AUTH_LDAP_DENY_GROUP": null,
    "AUTH_LDAP_USER_FLAGS_BY_GROUP": {
    },
    "AUTH_LDAP_ORGANIZATION_MAP": {
        "Default": {
            "admins": "CN=Ansible Users,CN=Users,{{ ldap_basedn }}",
            "remove_admins": true
        }
    },
    "AUTH_LDAP_TEAM_MAP": {
    }
}
ansible/roles/skylight-ansible-tower/templates/sssd.conf.j2
New file
@@ -0,0 +1,45 @@
[domain/{{ dns_domain_name }}]
debug_level = 2
auth_provider = ad
chpass_provider = ad
id_provider = ad
cache_credentials = true
krb5_canonicalize = false
krb5_kpasswd = windc.{{ dns_domain_name }}
krb5_realm = {{ dns_domain_name | upper }}
krb5_server = windc.{{ dns_domain_name }}
#ldap_disable_referrals = true
ldap_force_upper_case_realm = true
ldap_id_mapping = True
ldap_sasl_authid = {{ ansible_hostname | upper }}$@{{ dns_domain_name | upper }}
ldap_sasl_mech = GSSAPI
ldap_schema = ad
ldap_search_base = {{ ldap_search_base }}
ad_server = windc.{{ dns_domain_name }}
#ad_backup_server =
access_provider = ldap
ldap_access_order = filter, expire
ldap_account_expire_policy = ad
ldap_access_filter = {{ ldap_access_filter }}
min_id = 2000
[sssd]
services = nss, pam
config_file_version = 2
debug_level = 2
domains = {{ dns_domain_name }}
[nss]
debug_level = 2
fallback_homedir = /home/%d/%u
default_shell = /bin/bash
filter_users = root
filter_groups = root
[pam]
ansible/roles/skylight-ansible-tower/templates/tower-creds.json.j2
New file
@@ -0,0 +1,10 @@
{
  "name": "Tower",
  "description": "Tower Credentials",
  "organization": 1,
  "credential_type": 1,
  "inputs": {
    "username": "root",
    "password": "redhat"
  }
}
ansible/roles/skylight-ansible-tower/templates/tower_config_adhoc.json.j2
New file
@@ -0,0 +1,3 @@
{
  "AD_HOC_COMMANDS":["command","shell","yum","apt","apt_key","apt_repository","apt_rpm","service","group","user","mount","ping","selinux","setup","win_ping","win_service","win_updates","win_group","win_user","win_shell","win_feature","win_reboot"]
}
ansible/roles/skylight-ansible-tower/templates/tower_group.json.j2
New file
@@ -0,0 +1,6 @@
{
    "name": "Windows",
    "description": "",
    "inventory": 2,
    "variables": ""
}
ansible/roles/skylight-ansible-tower/templates/tower_host.json.j2
New file
@@ -0,0 +1,8 @@
{
    "name": "tower",
    "description": "",
    "inventory": "{{ classroom_inventory_id.json.results[0].id }}",
    "enabled": true,
    "instance_id": "",
    "variables": ""
}
ansible/roles/skylight-ansible-tower/templates/win1_host.json.j2
New file
@@ -0,0 +1,8 @@
{
    "name": "win1.{{ dns_domain_name }}",
    "description": "",
    "inventory": "{{ default_inventory_id.json.results[0].id }}",
    "enabled": true,
    "instance_id": "",
    "variables": ""
}
ansible/roles/skylight-do417-repos/tasks/main.yml
New file
@@ -0,0 +1,149 @@
---
- name: Remove repo directory
  file:
    path: /tmp/do417
    state: absent
- name: Install acl
  yum:
    name: acl
    state: present
    use_backend: dnf
  become: true
- name: Get ssh key for Github
  copy:
    src: "{{ github_ssh_key }}"
    dest: /tmp/github_ssh_key
    mode: 0400
    owner: "{{ ansible_user }}"
- name: Get lab source code
  git:
    clone: yes
    force: yes
    dest: "/tmp/do417"
    repo: "git@github.com:RedHatTraining/do417.git"
    key_file: /tmp/github_ssh_key
    accept_hostkey: true
- name: Remove ssh key for Github
  file:
    path: /tmp/github_ssh_key
    state: absent
- name: Remove .git directory
  file:
    path: /tmp/do417/.git
    state: absent
- name: Determining material directories
  command: find /tmp/do417/classroom/infrastructure/playbooks/files/src -maxdepth 1 -mindepth 1 -type d -printf '%f\n'
  register: repos_name
- name: Retrieve access token
  uri:
    url: "https://localhost/oauth/token"
    method: POST
    validate_certs: no
    status_code: 200
    body_format: json
    headers:
      Content-Type: application/json
    body: >
      {
        "grant_type": "password",
        "username": "root",
        "password": "{{ windows_password }}"
      }
  register: gitlab_access_token
- name: Retrieve local user information via API
  uri:
    url: https://localhost/api/v4/users?username={{ user_prefix }}
    method: GET
    validate_certs: no
    status_code:
      - 200
      - 201
    headers:
      Content-Type: application/json
      Authorization: Bearer {{ gitlab_access_token.json.access_token }}
  register: gitlab_local_users
- name: Create projects via API
  uri:
    url: https://localhost/api/v4/projects/user/{{ gitlab_local_users.json[0].id }}
    method: POST
    validate_certs: no
    status_code:
      - 200
      - 201
      - 409
      - 400
    body_format: json
    headers:
      Content-Type: application/json
      Authorization: Bearer {{ gitlab_access_token.json.access_token }}
    body: >
      {
        "name": "{{ item }}",
        "group": "{{ gitlab_local_users.json[0].name }}",
        "issues_enabled": false,
        "wiki_enabled": true,
        "snippets_enabled": true
      }
  with_items: "{{ repos_name.stdout_lines }}"
  when: gitlab_local_users.json[0].id is defined
- name: Configure local account
  shell: |
    git config --global http.sslVerify false
    git config --global user.email student@example.com
    git config --global user.name student
- name: Delete previous directories if present
  file:
    path: "/tmp/{{ item }}"
    state: absent
  with_items: "{{ repos_name.stdout_lines }}"
- name: Clone repositories
  git:
    repo: https://{{ user_prefix | urlencode }}:{{ windows_password | urlencode }}@localhost/student/{{ item }}.git
    dest: "/tmp/{{ item }}/"
    clone: yes
  with_items: "{{ repos_name.stdout_lines }}"
  ignore_errors: true
- name: Copying files for repositories
  copy:
    src: "/tmp/do417/classroom/infrastructure/playbooks/files/src/{{ item }}/"
    dest: "/tmp/{{ item }}/"
    remote_src: true
  with_items: "{{ repos_name.stdout_lines }}"
- name: ({{ repo_name }}) - Creating dummy file
  copy:
    dest: "/tmp/{{ item }}/dummy.yml"
    content: |
      ---
      - name: Dummy playbook
        hosts: all
        tasks:
          - name: Print Hello World
            debug:
              msg: 'Hello World'
  with_items: "{{ repos_name.stdout_lines }}"
- name: Load files into repositories
  shell: |
    git init
    git remote add origin https://{{ user_prefix | urlencode }}:{{ windows_password | urlencode }}@localhost/student/{{ item }}.git
    git add .
    git commit -m 'Establish initial {{ item }} repository'
    git push -u origin HEAD:master
    exit 0
  args:
    chdir: "/tmp/{{ item }}"
  with_items: "{{ repos_name.stdout_lines }}"
ansible/roles/skylight-gitlab-env/defaults/main.yml
New file
@@ -0,0 +1,11 @@
---
# defaults file for gitlab-postconfig
# defaults file for windows-ad-controller
dns_domain_name: "example.com"
# Users and Password to Create
windows_password: "MySecureP@ssword1"        # MUST FOLLOW WINDOWS AD PASSWORD RULES
users:
  - user1
  - user2
ansible/roles/skylight-gitlab-env/tasks/api.yml
New file
@@ -0,0 +1,83 @@
---
- name: GitLab Post | Obtain Access Token
  uri:
    url: https://gitlab.{{ dns_domain_name }}/oauth/token
    method: POST
    validate_certs: no
    status_code: 200
    body_format: json
    headers:
      Content-Type: application/json
    body: >
      {
        "grant_type": "password",
        "username": "root",
        "password": "{{ windows_password }}"
      }
  register: gitlab_access_token
- name: GitLab Post | Create local users via API
  uri:
    url: https://gitlab.{{ dns_domain_name }}/api/v4/users
    method: POST
    validate_certs: no
    status_code:
      - 200
      - 201
      - 409
    body_format: json
    headers:
      Content-Type: application/json
      Authorization: Bearer {{ gitlab_access_token.json.access_token }}
    body: >
      {
        "username": "{{ user_prefix }}",
        "password": "{{ windows_password }}",
        "name": "{{ user_prefix }}",
        "email": "{{ user_prefix }}@{{ dns_domain_name }}",
        "skip_confirmation": true
      }
# - name: GitLab Post | Get local user information via API
#   uri:
#     url: https://gitlab.{{ dns_domain_name }}/api/v4/users?username={{ user_prefix }}
#     method: GET
#     validate_certs: no
#     status_code:
#       - 200
#       - 201
#     headers:
#       Content-Type: application/json
#       Authorization: Bearer {{ gitlab_access_token.json.access_token }}
#   register: gitlab_local_users
#
# - name: debug
#   debug:
#     var: gitlab_local_users
#
# - name: GitLab Post | Create Projects via API
#   uri:
#     url: https://gitlab.{{ dns_domain_name }}/api/v4/projects/user/{{ item.id }}
#     method: POST
#     validate_certs: no
#     status_code:
#       - 200
#       - 201
#       - 409
#       - 400
#     body_format: json
#     headers:
#       Content-Type: application/json
#       Authorization: Bearer {{ gitlab_access_token.json.access_token }}
#     body: >
#       {
#         "name": "{{ item.name }}",
#         "group": "{{ item.name }}",
#         "issues_enabled": false,
#         "wiki_enabled": false,
#         "snippets_enabled": false
#       }
#   with_items:
#     - "{{ gitlab_local_users.json }}"
#   when: item.id is defined
ansible/roles/skylight-gitlab-env/tasks/main.yml
New file
@@ -0,0 +1,76 @@
---
- name: GitLab Post | Install pip
  yum:
    name: python-pip
    state: present
- name: GitLab Post | Install pyapi-gitlab
  pip:
    name: pyapi-gitlab
- name: GitLab Post | Repos to create
  debug:
    msg: "https://gitlab.{{ dns_domain_name }}/{{ user_prefix }}/ansible-playbooks"
- name: GitLab Post | copy root password script to host
  template:
    src: set_root_pw.sh.j2
    dest: /root/set_root_pw.sh
    owner: root
    group: root
    mode: 0700
- name: GitLab Post | Execute set root password
  command: ./set_root_pw.sh
  args:
    chdir: /root
- name: GitLab Post | Remove set root password script
  file:
    path: /root/set_root_pw.sh
    state: absent
#TODO try new way from RM
- name: sleep 2 minute to allow root to initialize after password set
  pause:
    minutes: 2
### Gitlab workaround
### Users are not populated from AD until login from Web UI
### I haven't found an automated workaround...
- block:
    - name: GitLab Post | Create local users
      gitlab_user:
        server_url: https://gitlab.{{ dns_domain_name }}
        validate_certs: False
        login_user: root
        login_password: "{{ windows_password }}"
        name: "{{ user_prefix }}"
        username: "{{ user_prefix }}"
        password: "{{ windows_password }}"
        email: "{{ user_prefix }}@{{ dns_domain_name }}"
        confirm: False
        state: present
    # - name: GitLab Post | Create Projects in GitLab
    #   gitlab_project:
    #     server_url: https://gitlab.{{ dns_domain_name }}
    #     validate_certs: False
    #     login_user: root
    #     login_password: "{{ windows_password }}"
    #     name: "{{ user_prefix }}"
    #     group: "{{ user_prefix }}"
    #     issues_enabled: False
    #     wiki_enabled: False
    #     snippets_enabled: False
    #     state: present
    #   ignore_errors: true
  when: ansible_version.full is version_compare('2.8', '<')
# There seems to be an issue with using basic auth when using ansible 2.8
# Create users and projects with uri module using API endpoint
- include_tasks: api.yml
  when: ansible_version.full is version_compare('2.8', '>=')
ansible/roles/skylight-gitlab-env/templates/set_root_pw.sh.j2
New file
@@ -0,0 +1,11 @@
#!/bin/bash
echo "user = User.where(id: 1).first
user.password = '{{ windows_password }}'
user.password_confirmation = '{{ windows_password }}'
user.password_automatically_set = false
user.reset_password_token = nil
user.reset_password_sent_at = nil
user.save!
user.unlock_access!
quit
" | gitlab-rails console production
ansible/roles/skylight-linux-common/tasks/main.yml
New file
@@ -0,0 +1,38 @@
---
- name: Install packages
  yum:
    name:
      - NetworkManager
    state: present
    use_backend: dnf
- name: Set hostname
  hostname:
    name: "{{ hostvars[inventory_hostname].instance_name}}.{{ dns_domain_name }}"
- name: Create dhclient.conf
  file:
    path: /etc/dhcp/dhclient.conf
    state: touch
    owner: root
    group: root
    mode: 0644
- name: Discover domain controller host
  set_fact:
    dc_host: "{{groups['activedirectories'][0]}}"
- name: Set custom DNS server
  blockinfile:
    dest: /etc/dhcp/dhclient.conf
    block: |
      prepend domain-name-servers {{ hostvars[dc_host].private_ip_address }};
      prepend domain-search "{{ dns_domain_name }}", "ec2.internal";
    state: present
  register: dnschange
- name: Restart NetworkManager
  service:
    name: NetworkManager
    state: restarted
  when: dnschange.changed
ansible/roles/skylight-windows-ad/defaults/main.yml
New file
@@ -0,0 +1,13 @@
---
# defaults file for windows-ad-controller
dns_domain_name: "example.com"
domain_admin_password: "Micr0soft!"
# Users and Password to Create
users:
  - user1
  - user2
# Details for reverse DNS lookup
ptr_zone_name: "0.168.192.in-addr.arpa"
ptr_zone_cidr: "192.168.0.0/24"
ansible/roles/skylight-windows-ad/library/win_ad_dnsrecord.ps1
New file
@@ -0,0 +1,99 @@
#!powershell
# This file is part of Ansible
#
# Copyright 2018, Jimmy Conner <jconner@redhat.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
# WANT_JSON
# POWERSHELL_COMMON
$params = Parse-Args $args -supports_check_mode $true
$hostname = Get-AnsibleParam -obj $params -name "hostname" -type "str" -failifempty $true
$zone = Get-AnsibleParam -obj $params -name "zone" -type "str" -failifempty $true
$ipaddr = Get-AnsibleParam -obj $params -name "ipaddr" -type "str" -default ""
$timetolive = Get-AnsibleParam -obj $params -name "timetolive" -type "str" -default "01:00:00"
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -validateset "present","absent" -default "present"
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
$result = @{
    changed = $false
    msg = ""
}
# Determine if AD Domain is setup
try {
    $domain = get-addomain
} catch {
    $errormsg = $_.Exception.Message
    Fail-Json $result "AD Domain not setup: $errormsg"
}
if ($state -eq 'present' -and $ipaddr -eq "") {
    Fail-Json $result "ipaddr can not be blank if state = present"
}
try {
    $exists = Get-DnsServerResourceRecord -ZoneName $zone -Name $hostname -ErrorAction SilentlyContinue
    if ($state -eq 'present') {
        if ($exists) {
            $ip = $exists.RecordData.IPv4Address.IPAddressToString
            # Check if we need to update the Entry
            if ($ip -ne $ipaddr) {
                if (-not $check_mode) {
                    Remove-DnsServerResourceRecord -ZoneName $zone -RRType "A" -Name $hostname -Force
                    Add-DnsServerResourceRecordA -Name "$hostname"    `
                            -ZoneName "$zone" `
                            -IPv4Address "$ipaddr" `
                            -AllowUpdateAny `
                            -AgeRecord `
                            -TimeToLive $timetolive
                }
                $result.changed = $true
                $result.msg = "DNS A Record: Updated: ($ip) >> ($ipaddr)"
            } else {
                # Record exists and doesn't need to be updated
                $result.msg = "DNS A Record: Present: $hostname ($ipaddr)"
            }
        } else {
            if (-not $check_mode) {
                Add-DnsServerResourceRecordA -Name "$hostname"    `
                        -ZoneName "$zone" `
                        -IPv4Address "$ipaddr" `
                        -AllowUpdateAny `
                        -AgeRecord `
                        -TimeToLive $timetolive
            }
            $result.changed = $true
            $result.msg = "DNS A Record: Added: $hostname ($ipaddr)"
        }
    } else {
        if ($exists) {
            if (-not $check_mode) {
                Remove-DnsServerResourceRecord -ZoneName $zone -RRType "A" -Name $hostname -Force
            }
            $result.changed = $true
            $result.msg = "DNS A Record: Removed: $hostname ($ipaddr)"
        } else {
            $result.msg = "DNS A Record: Absent: $hostname ($ipaddr)"
        }
    }
}
catch {
    Fail-Json $result $_.Exception.Message
}
Exit-Json $result
ansible/roles/skylight-windows-ad/library/win_ad_dnsrecord.py
New file
@@ -0,0 +1,66 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# This file is part of Ansible
#
# Copyright 2018, Jimmy Conner <jconner@redhat.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
# this is a windows documentation stub.  actual code lives in the .ps1
# file of the same name
DOCUMENTATION = '''
---
module: win_ad_dnsrecord
version_added: "2.6"
short_description: Manages DNS A Record on Windows DNS Server
description:
     - Manages DNS A Record on Windows DNS Server
options:
  hostname:
    description: Specifies a host name
    required: yes
  zone:
    description: Specifies the name of a DNS zone
    required: yes
  ipaddr:
    description: Specifies an IPv4 address (required if state = present)
    required: no
  timetolive:
    description: Specifies the Time to Live (TTL) value, in seconds, for a resource record. Specified in Time Format ex: 01:00:00
    required: no
    default: 01:00:00
  state:
    description: If present then a DNS record is created. If absent the DNS record is deleted
    choices: ['present', 'absent']
    default: 'present'
author: Jimmy Conner (jconner@redhat.com)
'''
EXAMPLES = r'''
- name: Create / Update DNS A Record
  win_ad_dnsrecord:
    hostname: myserver1
    zone: mydomain.pvt
    ipaddr: 192.168.0.2
    timetolive: 01:00:00
    state: present
- name: Remove DNS A Record
  win_ad_dnsrecord:
    hostname: myserver1
    zone: mydomain.pvt
    state: absent
'''
ansible/roles/skylight-windows-ad/library/win_ad_reverse_dnszone.ps1
New file
@@ -0,0 +1,78 @@
#!powershell
# This file is part of Ansible
#
# Copyright 2018, Jimmy Conner <jconner@redhat.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
# WANT_JSON
# POWERSHELL_COMMON
$params = Parse-Args $args -supports_check_mode $true
$subnet = Get-AnsibleParam -obj $params -name "subnet" -type "str" -failifempty $true
$zonename = Get-AnsibleParam -obj $params -name "zonename" -type "str" -failifempty $true
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -validateset "present","absent" -default "present"
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
$result = @{
    changed = $false
    msg = ""
}
# Determine if AD Domain is setup
try {
    $domain = get-addomain
} catch {
    $errormsg = $_.Exception.Message
    Fail-Json $result "AD Domain not setup: $errormsg"
}
try {
    $exists = $false
    $zones = Get-DnsServerZone
    foreach ($zone in $zones) {
        if ($zone.ZoneName -eq $zonename) {
            $exists = $true
        }
    }
    if ($state -eq "present") {
        if ($exists) {
            # Record exists and doesn't need to be updated
            $result.msg = "DNS Zone: Present: $zonename"
        } else {
            if (-not $check_mode) {
                Add-DnsServerPrimaryZone -NetworkId "$subnet" -DynamicUpdate Secure -ReplicationScope Domain
            }
            $result.changed = $true
            $result.msg = "DNS Zone: Added: $zonename ($subnet)"
        }
    } else {
        if ($exists) {
            if (-not $check_mode) {
                Remove-DnsServerZone -Name "$zonename" -Force
            }
            $result.changed = $true
            $result.msg = "DNS Zone: Removed: $zonename"
        } else {
            $result.msg = "DNS Zone: Absent: $zonename"
        }
    }
} catch {
    Fail-Json $result $_.Exception.Message
}
Exit-Json $result
ansible/roles/skylight-windows-ad/library/win_dns_searchsuffix.ps1
New file
@@ -0,0 +1,48 @@
#!powershell
# This file is part of Ansible
#
# Copyright 2018, Jimmy Conner <jconner@redhat.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
# WANT_JSON
# POWERSHELL_COMMON
$params = Parse-Args $args -supports_check_mode $true
$suffixes = (Get-AnsibleParam -obj $params -name "suffixes" -type "list" -failifempty $true) -join ","
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
$result = @{
    changed = $false
    msg = ""
}
try {
    $current = ((Get-DnsClientGlobalSetting | Select SuffixSearchList).SuffixSearchList) -join ","
    if ($suffixes -eq $current) {
        $result.msg = "Suffixes are present"
    } else {
        if (-not $check_mode) {
            Set-DnsClientGlobalSetting -SuffixSearchList $suffixes
        }
        $result.changed = $true
        $result.msg = "Updated Suffixes: Original: ($current) -- New: ($suffixes)"
    }
}
catch {
    Fail-Json $result $_.Exception.Message
}
Exit-Json $result
ansible/roles/skylight-windows-ad/tasks/main.yml
New file
@@ -0,0 +1,138 @@
---
- name: Disable firewall for Domain, Public, and Private profiles
  win_firewall:
    state: disabled
    profiles:
    - Domain
    - Private
    - Public
- name: Set hostname
  win_hostname:
    name: "{{ hostvars[inventory_hostname].instance_name }}"
  register: win_hostname
- name: Reboot if required
  win_reboot:
  when: win_hostname.reboot_required
- name: Install AD-Domain-Services
  win_feature:
    name: AD-Domain-Services
    state: present
    include_management_tools: True
    include_sub_features: True
  register: winfeature
- name: Reboot if needed
  win_reboot:
  when: winfeature.changed
- name: Create DNS Domain
  win_domain:
    dns_domain_name: "{{ dns_domain_name }}"
    safe_mode_password: "{{ windows_password }}"
  register: windomain
- name: Reboot if needed
  win_reboot:
  when:
    - windomain.reboot_required
- name: Wait for Active Directory Web Services port
  win_wait_for:
    host: localhost
    port: 9389
    timeout: 600
- name: Ensure AD Services are started
  win_service:
    name: "{{ item }}"
    state: started
    start_mode: auto
  with_items:
    - dns
    - adws
- name: Set Reverse Lookup Zone
  win_ad_reverse_dnszone:
    subnet: "{{ ptr_zone_cidr }}"
    zonename: "{{ ptr_zone_name }}"
    state: present
  register: reverse
  until: reverse is not failed
  retries: 100
- name: Create DNS A records
  win_ad_dnsrecord:
    hostname: "{{ hostvars[item]['instance_name'] }}"
    zone: "{{ dns_domain_name }}"
    ipaddr: "{{ hostvars[item]['private_ip_address'] }}"
    state: present
  with_items:
    - "gitlab.{{ chomped_zone_internal_dns }}"
    - "tower.{{ chomped_zone_internal_dns }}"
    - "win1.{{ chomped_zone_internal_dns }}"
    - "win2.{{ chomped_zone_internal_dns }}"
- name: Add windows group
  win_domain_group:
    name: Ansible Users
    scope: global
- name: Add windows domain admin
  win_domain_user:
    name: "Admin"
    upn: "Admin@{{ dns_domain_name }}"
    state: present
    enabled: yes
    account_locked: no
    groups:
      - Domain Admins
    password: "{{ windows_password }}"
    update_password: on_create
    password_expired: false
    firstname: admin
    surname: user
    company: Training
    email: "Admin@{{ dns_domain_name }}"
- name: Add windows AD users
  win_domain_user:
    name: "{{ user_prefix }}"
    upn: "{{ user_prefix }}@{{ dns_domain_name }}"
    state: present
    enabled: yes
    account_locked: no
    groups:
      - Ansible Users
    password: "{{ windows_password }}"
    update_password: on_create
    password_expired: false
    firstname: "{{ user_prefix }}"
    surname: "student"
    company: Training
    email: "{{ user_prefix }}@{{ dns_domain_name }}"
- name: Set DNS search string
  win_dns_searchsuffix:
    suffixes:
      - "{{ dns_domain_name }}"
- name: Install RSAT feature
  win_feature:
    name: RSAT-AD-PowerShell
    state: present
    include_management_tools: yes
- name: Extend password expiry
  win_shell: |
    import-module ActiveDirectory
    $admin_passwd = ConvertTo-SecureString "{{ windows_password }}" -AsPlainText -Force
    $admin_creds = New-Object System.Management.Automation.PSCredential ("EXAMPLE\Administrator", $admin_passwd)
    Set-ADDefaultDomainPasswordPolicy -Identity example.com -Credential $admin_creds -MaxPasswordAge 90.00:00:00
# - name: Remove RSAT feature
#   win_feature:
#     name: RSAT-AD-PowerShell
#     state: absent
ansible/roles/skylight-windows-common/defaults/main.yml
New file
@@ -0,0 +1,9 @@
---
# defaults file for windows-common
dns_domain_name: "example.com"
domain_admin_password: "Micr0soft!"
# Grab the private IP of your windows DNS for your lab dns server
dns_servers:
  - "{{ hostvars['windc'].ansible_host }}"
  - 8.8.8.8
ansible/roles/skylight-windows-common/library/win_dns_searchsuffix.ps1
New file
@@ -0,0 +1,48 @@
#!powershell
# This file is part of Ansible
#
# Copyright 2018, Jimmy Conner <jconner@redhat.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
# WANT_JSON
# POWERSHELL_COMMON
$params = Parse-Args $args -supports_check_mode $true
$suffixes = (Get-AnsibleParam -obj $params -name "suffixes" -type "list" -failifempty $true) -join ","
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
$result = @{
    changed = $false
    msg = ""
}
try {
    $current = ((Get-DnsClientGlobalSetting | Select SuffixSearchList).SuffixSearchList) -join ","
    if ($suffixes -eq $current) {
        $result.msg = "Suffixes are present"
    } else {
        if (-not $check_mode) {
            Set-DnsClientGlobalSetting -SuffixSearchList $suffixes
        }
        $result.changed = $true
        $result.msg = "Updated Suffixes: Original: ($current) -- New: ($suffixes)"
    }
}
catch {
    Fail-Json $result $_.Exception.Message
}
Exit-Json $result
ansible/roles/skylight-windows-common/tasks/main.yml
New file
@@ -0,0 +1,69 @@
---
- name: Discover domain controller host
  set_fact:
    dc_host: "{{groups['activedirectories'][0]}}"
- name: Add domain controller private IP as DNS server
  win_dns_client:
    adapter_names: "*"
    ipv4_addresses: "{{ hostvars[dc_host]['private_ip_address'] }}"
- name: Set hostname
  win_hostname:
    name: "{{ hostvars[inventory_hostname].instance_name }}"
  register: win_hostname
- name: Reboot if required
  win_reboot:
  when: win_hostname.reboot_required
- name: Set DNS search suffix to {{ dns_domain }}
  win_dns_searchsuffix:
    suffixes:
      - "{{ dns_domain_name }}"
- name: Add devops user in Administrators group
  win_user:
    account_locked: no
    description: "{{ item }} user"
    fullname: "{{ item }}"
    groups:
      - Administrators
      - "Remote Management Users"
    name: "{{ item }}"
    password: "{{ windows_password }}"
    state: present
    user_cannot_change_password: yes
  with_items:
    - 'devops'
- name: Join Domain
  block:
    - name: Join Domain
      win_domain_membership:
        dns_domain_name: "{{ dns_domain_name }}"
        domain_admin_user: "admin@{{ dns_domain_name }}"
        domain_admin_password: "{{ windows_password }}"
        state: domain
      register: windomain
    - name: Reboot if needed
      win_reboot:
      when: windomain.reboot_required
    - name: Add Ansible group to a local Administrators
      win_group_membership:
        name: Administrators
        members:
        - "{{ dns_domain_name_short }}\\Ansible Users"
        state: present
    - name: Add Ansible group to a local Remote Management Users
      win_group_membership:
        name: Remote Management Users
        members:
          - "{{ dns_domain_name_short }}\\Ansible Users"
        state: present
  # We don't want win2 to join the main domain.
  when: "'win2' not in inventory_hostname"
ansible/roles/skylight-windows-workstation/files/settings.json
New file
@@ -0,0 +1,5 @@
{
    "git.enableSmartCommit": true,
    "git.confirmSync": false,
    "http.proxyStrictSSL": false
}
ansible/roles/skylight-windows-workstation/tasks/adv_lab.yml
New file
@@ -0,0 +1,13 @@
- block:
  - name: Create an shortcut to Advanced Docs site
    win_shortcut:
      src: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe'
      dest: '%UserProfile%\Desktop\Advanced Workshop Docs.lnk'
      args: --new-window http://docs.{{ dns_domain_name }}/advanced/
      directory: '%ProgramFiles(x86)%\Google\Chrome\Application'
      icon: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe,0'
  become: yes
  become_user: "{{ dns_domain_name_short }}\\{{ user_prefix }}"
  become_method: runas
ansible/roles/skylight-windows-workstation/tasks/git_lab.yml
New file
@@ -0,0 +1,13 @@
- block:
  - name: Create an shortcut to GIT Docs site
    win_shortcut:
      src: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe'
      dest: '%UserProfile%\Desktop\GIT Workshop Docs.lnk'
      args: --new-window http://docs.{{ dns_domain_name }}/git/
      directory: '%ProgramFiles(x86)%\Google\Chrome\Application'
      icon: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe,0'
  become: yes
  become_user: "{{ dns_domain_name_short }}\\{{ user_prefix }}"
  become_method: runas
ansible/roles/skylight-windows-workstation/tasks/main.yml
New file
@@ -0,0 +1,247 @@
---
- name: Change workstation administrator password
  win_user:
    account_locked: no
    name: Administrator
    password: "{{ workstation_password }}"
    password_expired: no
    update_password: always
    password_never_expires: yes
    state: present
- name: Change ansible password for this server
  set_fact:
    ansible_password: "{{ workstation_password }}"
- name: Remove domain student account from Remote Desktop Users
  win_group_membership:
    name: "Remote Desktop Users"
    members:
    - "{{ dns_domain_name_short }}\\{{ user_prefix }}"
    state: absent
- name: Remove specific users from Remote Management
  win_group_membership:
    name: "Remote Management Users"
    members:
    - "{{ dns_domain_name_short }}\\Ansible Users"
    - "devops"
    state: absent
- name: Remove specific users from Administrators
  win_group_membership:
    name: "Administrators"
    members:
    - "{{ dns_domain_name_short }}\\Ansible Users"
    - "devops"
    state: absent
- name: Add local student user to workstation
  win_user:
    account_locked: no
    description: "Workstation Training account"
    fullname: "Training User"
    groups:
      - Administrators
    name: "{{ workstation_user }}"
    password: "{{ workstation_password }}"
    state: present
    user_cannot_change_password: yes
# TODO figure out why this doesn't work
# JR: Ansible just ignores this and runs as Administrator but when I set
#     "become" vars via set_fact it uses them - go figure????
# - become: yes
#   become_user: "{{ workstation_user }}"
#   become_method: runas
#   become_flags: logon_type=new_credentials logon_flags=netcredentials_only
#   vars:
#     ansible_become_password: "{{ windows_password }}"
- block:
  - name: Become student the hackish way
    set_fact:
      ansible_become_user: "{{ workstation_user }}"
      ansible_become: yes
      ansible_become_password: "{{  workstation_password }}"
      ansible_become_method: runas
  - name: install Chocolatey
    win_chocolatey:
      name: chocolatey
      state: present
  - name: disable enhanced exit codes
    win_chocolatey_feature:
      name: useEnhancedExitCodes
      state: disabled
    when: ansible_version.full is version_compare('2.8', '<')
  - name: Install Visual Studio Code, Git, and Chrome
    win_chocolatey:
      name:
        - visualstudiocode
        - git
        - googlechrome
      ignore_checksums: true
  - name: Create a shortcut to Tower site
    win_shortcut:
      src: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe'
      dest: '%UserProfile%\Desktop\Ansible Tower.lnk'
      args: --new-window http://tower.{{ dns_domain_name }}/
      directory: '%ProgramFiles(x86)%\Google\Chrome\Application'
      icon: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe,0'
  - name: Create a shortcut to the user's Gitlab ansible-playbooks repository
    win_shortcut:
      src: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe'
      dest: '%UserProfile%\Desktop\GitLab.lnk'
      args: --new-window https://gitlab.{{ dns_domain_name }}/{{ user_prefix }}
      directory: '%ProgramFiles(x86)%\Google\Chrome\Application'
      icon: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe,0'
  - name: Create a shortcut to Ansible Docs site
    win_shortcut:
      src: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe'
      dest: '%UserProfile%\Desktop\Ansible Docs.lnk'
      args: --new-window http://docs.ansible.com/
      directory: '%ProgramFiles(x86)%\Google\Chrome\Application'
      icon: '%ProgramFiles(x86)%\Google\Chrome\Application\chrome.exe,0'
  - name: Set git to cache credentials
    win_command: git config --global credential.helper manager
  - name: Allow insecure git repos for self signed certificates
    win_command: git config --global http.sslVerify "false"
  - name: Set git user
    win_command: git config --global user.name "{{ user_prefix }}"
  - name: Set git user email
    win_command: git config --global user.email "{{ user_prefix }}@{{ dns_domain_name }}"
  - name: Set git password
    win_shell: cmdkey /generic:LegacyGeneric:target=git:https://gitlab.{{ dns_domain_name }} /user:{{ user_prefix }} /pass:"{{ windows_password }}"
  - name: Set git password
    win_shell: cmdkey /generic:LegacyGeneric:target=git:https://{{ user_prefix }}@gitlab.{{ dns_domain_name }} /user:{{ user_prefix }} /pass:"{{ windows_password }}"
  - name: Copy .gitconfig to user directory
    win_copy:
      src: C:\Windows\.gitconfig
      dest: C:\Users\{{ workstation_user }}\.gitconfig
      remote_src: True
  # - name: Clone student git repo
  #   win_command: git clone https://gitlab.{{ dns_domain_name }}/{{ user_prefix }}/{{ user_prefix }}.git
  #   args:
  #     chdir: C:\Users\{{ workstation_user }}\Documents
  #     creates: C:\Users\{{ workstation_user }}\Documents\{{ user_prefix }}
  #
  # - name: Create Readme file to intialize the repo
  #   win_copy:
  #     dest: C:\Users\{{ workstation_user }}\Documents\{{ user_prefix }}\README.md
  #     content: ""
  #   register: initialize
  #
  # - name: Add initial file
  #   win_command: git add C:\Users\{{ workstation_user }}\Documents\{{ user_prefix }}\README.md
  #   args:
  #     chdir: C:\Users\{{ workstation_user }}\Documents\{{ user_prefix }}
  #   when: initialize.changed
  #
  # - name: Commit initial file
  #   win_command: git commit -m "Initialize"
  #   args:
  #     chdir: C:\Users\{{ workstation_user }}\Documents\{{ user_prefix }}
  #   when: initialize.changed
  #
  # - name: Push initial commit
  #   win_command: git push
  #   args:
  #     chdir: C:\Users\{{ workstation_user }}\Documents\{{ user_prefix }}
  #   when: initialize.changed
  - name: Create VS Code Settings Directory
    win_file:
      path: C:\Users\{{ workstation_user }}\AppData\Roaming\Code\User\
      state: directory
  - name: Create VS Code Settings Directory
    win_file:
      path: C:\Users\{{ workstation_user }}\AppData\Roaming\Code\User\
      state: directory
  - name: Configure VS Code Settings File
    win_copy:
      src: files/settings.json
      dest: C:\Users\{{ workstation_user }}\AppData\Roaming\Code\User\settings.json
  - name: Set Chrome to default Browser
    win_regedit:
      path: HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\{{ item }}\UserChoice
      name: ProgId
      data: ChromeHTML
    with_items:
      - http
      - https
  - name: Set Chrome to not ask about default browser
    win_regedit:
      path: HKLM:\Software\Policies\Google\Chrome
      name: DefaultBrowserSettingEnabled
      data: 0
      type: dword
  - name: Disable Chrome Welcome Screen
    win_regedit:
      path: HKLM:\Software\Policies\Google\Chrome
      name: "{{ item }}"
      data: 0
      type: dword
    with_items:
      - PromotionalTabsEnabled
      - WelcomePageOnOSUpgradeEnabled
  - name: Disable Chrome Syncing
    win_regedit:
      path: HKLM:\Software\Policies\Google\Chrome
      name: SyncDisabled
      data: 1
      type: dword
  - name: Disable Server Management at Startup
    win_regedit:
      path: HKCU:\Software\Microsoft\ServerManager\
      name: DoNotOpenServerManagerAtLogon
      data: 1
      type: dword
  - name: Remove EC2 Feedback Icon
    win_file:
      path: C:\Users\{{ workstation_user }}\Desktop\EC2 Feedback.website
      state: absent
  - name: Remove EC2 Website Icon
    win_file:
      path: C:\Users\{{ workstation_user }}\Desktop\EC2 Microsoft Windows Guide.website
      state: absent
  always:
  - name: Restore ansible user info
    set_fact:
      ansible_become: no
  # become: yes
  # become_user: "{{ workstation_user }}"
  # become_method: runas
  # become_flags: logon_type=new_credentials logon_flags=netcredentials_only
  # vars:
  #   ansible_become_password: "{{ windows_password }}"
- include_tasks: myrtille.yml
- include_tasks: git_lab.yml
  when: git_lab | d(false) | bool
- include_tasks: adv_lab.yml
  when: advanced_lab | d(false) | bool
ansible/roles/skylight-windows-workstation/tasks/myrtille.yml
New file
@@ -0,0 +1,78 @@
# https://github.com/cedrozor/myrtille
- name: Install IIS and .Net 4.5 on Server
  win_feature:
    name:
      - Web-Server
      - NET-Framework-Core
#      - Application-Server
      - Web-Asp-Net45
    include_management_tools: True
    state: present
  when: "'Windows 10' not in ansible_distribution"
- name: Install IIS and .Net 4.5 on Non-Server
  win_dsc:
    resource_name: WindowsOptionalFeature
    Name: "{{ item }}"
    Ensure: Enable
  when: "'Windows 10' in ansible_distribution"
  loop:
    - IIS-WebServerRole
    - IIS-WebServer
    - NetFx4Extended-ASPNET45
    - IIS-NetFxExtensibility45
    - IIS-ISAPIExtensions
    - IIS-ISAPIFilter
    - IIS-ASPNET45
- name: Create temp directory
  win_file:
    path: C:\Temp\
    state: directory
- name: Check if Myrtille is downloaded
  win_stat:
    path: C:\Temp\Myrtille_2.3.1_x86_x64_Setup.exe
  register: myrtille
# The following fails because windows defaults to TLS 1.0 and Github now requires 1.2
# - name: Download Myrtille to specified path only if modified
#   win_get_url:
#     url: https://github.com/cedrozor/myrtille/releases/download/v2.3.1/Myrtille_2.3.1_x86_x64_Setup.exe
#     dest: C:\Temp\Myrtille_2.3.1_x86_x64_Setup.exe
#   when: not myrtille.stat.exists
- name: Download Myrtille to specified path only if modified
  win_shell: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri 'https://github.com/cedrozor/myrtille/releases/download/v2.3.1/Myrtille_2.3.1_x86_x64_Setup.exe' -OutFile 'C:\\Temp\\Myrtille_2.3.1_x86_x64_Setup.exe'"
  when: not myrtille.stat.exists
- name: Extract the binary
  win_command: Myrtille_2.3.1_x86_x64_Setup.exe -o "C:\Temp" -y
  args:
    chdir: C:\Temp\
    creates: C:\Temp\setup.exe
- name: Install Myrtille
  win_package:
    path: C:\Temp\setup.exe
    arguments: /q
    creates_path: C:\Program Files (x86)\Myrtille
- name: Disable NTLM RDP Authetication requirement
  win_regedit:
    path: HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
    name: "{{ item }}"
    data: 0
    type: dword
  with_items:
    - SecurityLayer
    - UserAuthentication
- name: Create RDP Application
  win_iis_webapplication:
    name: rdp
    site: Default Web Site
    application_pool: MyrtilleAppPool
    physical_path: C:\Program Files (x86)\Myrtille\
    state: present