From cb54ff2f0d06e123dda1ac56b69708fca59259f4 Mon Sep 17 00:00:00 2001 From: Berndt Jung Date: Fri, 19 Oct 2018 22:00:40 -0700 Subject: [PATCH] Add basic chat-ops UI Also return JSON rather than string from aws.py (this probably breaks things) * added region to aws.py * changed secret keys Signed-off-by: Berndt Jung --- boto.txt | 2 + chat-ops-ui/.gitignore | 1 + chat-ops-ui/Dockerfile | 8 ++ chat-ops-ui/build.sh | 4 + chat-ops-ui/chat-ops.nginx.conf | 51 ++++++++ chat-ops-ui/src/app/vm/vm.component.ts | 8 +- chat-ops-ui/src/app/vm/vm.service.ts | 9 +- chat-ops-ui/src/app/vmware/vmware.service.ts | 2 +- .../src/environments/environment.prod.ts | 3 +- chat-ops-ui/src/environments/environment.ts | 3 +- chat-ops-ui/src/index.html | 6 +- functions/aws.py | 20 ++- hardenvm.ps1 | 123 ++++++++++++++++++ ui-apis.yaml | 67 ++++++++++ 14 files changed, 280 insertions(+), 27 deletions(-) create mode 100644 boto.txt create mode 100644 chat-ops-ui/Dockerfile create mode 100755 chat-ops-ui/build.sh create mode 100644 chat-ops-ui/chat-ops.nginx.conf create mode 100644 hardenvm.ps1 create mode 100644 ui-apis.yaml diff --git a/boto.txt b/boto.txt new file mode 100644 index 0000000..515eeb3 --- /dev/null +++ b/boto.txt @@ -0,0 +1,2 @@ +boto3==1.9.28 +requests==2.18.4 \ No newline at end of file diff --git a/chat-ops-ui/.gitignore b/chat-ops-ui/.gitignore index ee5c9d8..821f02b 100644 --- a/chat-ops-ui/.gitignore +++ b/chat-ops-ui/.gitignore @@ -33,6 +33,7 @@ npm-debug.log yarn-error.log testem.log /typings +.htpasswd # System Files .DS_Store diff --git a/chat-ops-ui/Dockerfile b/chat-ops-ui/Dockerfile new file mode 100644 index 0000000..8aef3bf --- /dev/null +++ b/chat-ops-ui/Dockerfile @@ -0,0 +1,8 @@ +FROM nginx:latest + +RUN mkdir /etc/nginx/ssl +ADD /chat-ops.key /etc/nginx/ssl/chat-ops.key +ADD /chat-ops.crt /etc/nginx/ssl/chat-ops.crt +ADD /chat-ops.nginx.conf /etc/nginx/conf.d/default.conf +ADD /.htpasswd /etc/nginx/.htpasswd +ADD /dist/chat-ops-ui /usr/share/nginx/html \ No newline at end of file diff --git a/chat-ops-ui/build.sh b/chat-ops-ui/build.sh new file mode 100755 index 0000000..6391c15 --- /dev/null +++ b/chat-ops-ui/build.sh @@ -0,0 +1,4 @@ +#! /bin/bash + +ng build --prod +docker build -t ${1} . diff --git a/chat-ops-ui/chat-ops.nginx.conf b/chat-ops-ui/chat-ops.nginx.conf new file mode 100644 index 0000000..62e94d3 --- /dev/null +++ b/chat-ops-ui/chat-ops.nginx.conf @@ -0,0 +1,51 @@ +server { + listen 443 ssl; + server_name chat-ops-ato.dispatchframework.io; + + ssl_certificate /etc/nginx/ssl/chat-ops.crt; + ssl_certificate_key /etc/nginx/ssl/chat-ops.key; + + + #charset koi8-r; + #access_log /var/log/nginx/log/host.access.log main; + + location / { + auth_basic "Restricted Content"; + auth_basic_user_file /etc/nginx/.htpasswd; + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} +} diff --git a/chat-ops-ui/src/app/vm/vm.component.ts b/chat-ops-ui/src/app/vm/vm.component.ts index a7581ed..23af317 100644 --- a/chat-ops-ui/src/app/vm/vm.component.ts +++ b/chat-ops-ui/src/app/vm/vm.component.ts @@ -1,13 +1,7 @@ -import { Component, OnInit } from '@angular/core'; +import { OnInit } from '@angular/core'; import { VMService } from "./vm.service"; import { VM } from "./vm"; - -@Component({ - selector: 'app-aws', - templateUrl: './../vm/vm.component.html', - styleUrls: ['./../vm/vm.component.css'] -}) export abstract class VMComponent implements OnInit { vmService !: VMService; diff --git a/chat-ops-ui/src/app/vm/vm.service.ts b/chat-ops-ui/src/app/vm/vm.service.ts index b24715e..3cfacaa 100644 --- a/chat-ops-ui/src/app/vm/vm.service.ts +++ b/chat-ops-ui/src/app/vm/vm.service.ts @@ -2,12 +2,11 @@ import { Injectable } from '@angular/core'; import { Http, Response, RequestOptions, Headers } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import { environment } from '../../environments/environment'; -import { interval } from 'rxjs'; +import { interval, throwError } from 'rxjs'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/switchMap'; -import 'rxjs/add/observable/throw'; import { VM } from '../vm/vm'; @@ -50,14 +49,14 @@ export abstract class VMService { .catch(this.handleError); } - private extractVMs(cloud: string, res: Response) { + extractVMs(cloud: string, res: Response) { let data = res.json(); if (data) { data.forEach(element => { element.cloud = cloud element.name = element.name element.id = element.id - element.state = element.state + element.state = element.status }); console.log(data); return data; @@ -76,6 +75,6 @@ export abstract class VMService { errMsg = error.message ? error.message : error.toString(); } console.error(errMsg); - return Observable.throw(errMsg); + return throwError(errMsg); } } diff --git a/chat-ops-ui/src/app/vmware/vmware.service.ts b/chat-ops-ui/src/app/vmware/vmware.service.ts index 5f28cf4..8324d22 100644 --- a/chat-ops-ui/src/app/vmware/vmware.service.ts +++ b/chat-ops-ui/src/app/vmware/vmware.service.ts @@ -6,5 +6,5 @@ import { VMService } from '../vm/vm.service'; providedIn: 'root' }) export class VMwareService extends VMService { - cloud = "vmware"; + cloud = "vsphere"; } diff --git a/chat-ops-ui/src/environments/environment.prod.ts b/chat-ops-ui/src/environments/environment.prod.ts index 54a6623..7b54642 100644 --- a/chat-ops-ui/src/environments/environment.prod.ts +++ b/chat-ops-ui/src/environments/environment.prod.ts @@ -1,5 +1,4 @@ export const environment = { production: true, - apiURL: "http://localhost:8081/dispatch-server/", - apiPathAWS: "aws" + apiURL: "https://ato-api.dispatchframework.io/" }; diff --git a/chat-ops-ui/src/environments/environment.ts b/chat-ops-ui/src/environments/environment.ts index 320f4c8..5bf43b0 100644 --- a/chat-ops-ui/src/environments/environment.ts +++ b/chat-ops-ui/src/environments/environment.ts @@ -4,8 +4,7 @@ export const environment = { production: false, - apiURL: "http://localhost:8081/dispatch-server/", - apiPathAWS: "aws" + apiURL: "https://ato-api.dispatchframework.io/" }; /* diff --git a/chat-ops-ui/src/index.html b/chat-ops-ui/src/index.html index f4dcd7f..fbab54a 100644 --- a/chat-ops-ui/src/index.html +++ b/chat-ops-ui/src/index.html @@ -8,11 +8,11 @@ - + - + - + diff --git a/functions/aws.py b/functions/aws.py index 7702486..6eb1808 100644 --- a/functions/aws.py +++ b/functions/aws.py @@ -115,14 +115,20 @@ def handle(ctx, payload): entry point for AWS commands """ - access_key = ctx['secrets']['access_key'] - secret_key = ctx['secrets']['secret_key'] region = ctx['secrets']['region'] - - ec2_resource = boto3.resource("ec2", aws_access_key_id=access_key, - aws_secret_access_key=secret_key, region_name=region) - ec2_client = boto3.client("ec2", aws_access_key_id=access_key, - aws_secret_access_key=secret_key, region_name=region) + access_key = ctx['secrets']['aws_access_key'] + secret_key = ctx['secrets']['aws_secret_key'] + + ec2_resource = boto3.resource( + "ec2", + aws_access_key_id=access_key, + aws_secret_access_key=secret_key, + region_name=region) + ec2_client = boto3.client( + "ec2", + aws_access_key_id=access_key, + aws_secret_access_key=secret_key, + region_name=region) if 'command' not in payload: return _error('command is required') diff --git a/hardenvm.ps1 b/hardenvm.ps1 new file mode 100644 index 0000000..dc387f7 --- /dev/null +++ b/hardenvm.ps1 @@ -0,0 +1,123 @@ +Import-Module PowerCLI.ViCore + +function Apply-Hardening { + <# + .NOTES + =========================================================================== + Created by: Markus Kraus + Twitter: @VMarkus_K + Private Blog: mycloudrevolution.com + =========================================================================== + Changelog: + 2016.11 ver 2.0 Base Release + =========================================================================== + External Code Sources: + + =========================================================================== + Tested Against Environment: + vSphere Version: 5.5 U2 + PowerCLI Version: PowerCLI 6.3 R1, PowerCLI 6.5 R1 + PowerShell Version: 4.0, 5.0 + OS Version: Windows 8.1, Server 2012 R2 + Keyword: VM, Hardening, Security + =========================================================================== + .DESCRIPTION + Applys a set of Hardening options to your VMs + .Example + Get-VM TST* | Apply-Hardening + .Example + $SampleVMs = Get-VM "TST*" + Apply-Hardening -VMs $SampleVMs + .PARAMETER VMs + Specify the VMs + #Requires PS -Version 4.0 + #Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="6.3.0.0"} + #> + + [CmdletBinding()] + param( + [Parameter(Mandatory=$true, + ValueFromPipeline=$True, + Position=0)] + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]] + $VMs + ) + + Process { + #region: Create Options + $ExtraOptions = @{ + "isolation.tools.diskShrink.disable"="true"; + "isolation.tools.diskWiper.disable"="true"; + "isolation.tools.copy.disable"="true"; + "isolation.tools.paste.disable"="true"; + "isolation.tools.dnd.disable"="true"; + "isolation.tools.setGUIOptions.enable"="false"; + "log.keepOld"="10"; + "log.rotateSize"="100000" + "RemoteDisplay.maxConnections"="2"; + "RemoteDisplay.vnc.enabled"="false"; + + } + if ($DebugPreference -eq "Inquire") { + Write-Output "VM Hardening Options:" + $ExtraOptions | Format-Table -AutoSize + } + + $VMConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec + + Foreach ($Option in $ExtraOptions.GetEnumerator()) { + $OptionValue = New-Object VMware.Vim.optionvalue + $OptionValue.Key = $Option.Key + $OptionValue.Value = $Option.Value + $VMConfigSpec.extraconfig += $OptionValue + } + #endregion + + #region: Apply Options + ForEach ($VM in $VMs){ + $VMv = Get-VM $VM | Get-View + $state = $VMv.Summary.Runtime.PowerState + Write-Output "...Starting Reconfiguring VM: $VM " + $TaskConf = ($VMv).ReconfigVM_Task($VMConfigSpec) + if ($state -eq "poweredOn") { + Write-Output "...Migrating VM: $VM " + $TaskMig = $VMv.MigrateVM_Task($null, $_.Runtime.Host, 'highPriority', $null) + } + } + } + #endregion + } + + function handle($context, $payload) { + [void](Set-PowerCLIConfiguration -InvalidCertificateAction ignore -Confirm:$false) + + $username = $context.secrets.username + $password = $context.secrets.password + $hostname = $context.secrets.host + $statusurl = $context.secrets.statusUrl + $vmName = $payload.metadata.vm_name + + # Connect to vSphere + Write-Host "Checking VC Connection is active" + if (-not $global:defaultviservers) { + Write-Host "Connecting to $hostname" + $server = connect-viserver -server $hostname -User $username -Password $password + } else { + Write-Host "Already connected to $hostname" + } + + Write-Host "Get Virtual Machine By name" + $vm = Get-VM -Name $vmName + + Write-Host "Security Harden our VM" + $vm | Apply-Hardening + + Write-Host "Sending Slack Message" + SendToSlack $statusurl "$vmName has been security hardened!" +} + +function SendToSlack ([uri]$URL , $message){ + $body = '{ "text": "'+ $message+ '" }' + $body + Invoke-WebRequest -Uri $URL -Headers $headers -Method "POST" -ContentType "application/json" -Body $body +} \ No newline at end of file diff --git a/ui-apis.yaml b/ui-apis.yaml new file mode 100644 index 0000000..b347ffd --- /dev/null +++ b/ui-apis.yaml @@ -0,0 +1,67 @@ +kind: API +name: get-aws +enabled: true +function: aws +cors: true +methods: + - GET +protocols: + - https +hosts: + - ato-api.dispatchframework.io +uris: + - /aws +tags: + - key: role + value : ato +--- +kind: API +name: get-gcp +enabled: true +function: gcp +cors: true +methods: + - GET +protocols: + - https +hosts: + - ato-api.dispatchframework.io +uris: + - /gcp +tags: + - key: role + value : ato +--- +kind: API +name: get-azure +enabled: true +function: azure +cors: true +methods: + - GET +protocols: + - https +hosts: + - ato-api.dispatchframework.io +uris: + - /azure +tags: + - key: role + value : ato +--- +kind: API +name: get-vsphere +enabled: true +function: vsphere +cors: true +methods: + - GET +protocols: + - https +hosts: + - ato-api.dispatchframework.io +uris: + - /vsphere +tags: + - key: role + value : ato