Google App Script, Powershell e inventário de equipamentos
Este artigo explora possibilidades de projetos usando soluções GSuite, que se tornaram ainda mais forte durante o período de pandemia do COVID-19, e sua integração com outras tecnologias.
O GSuite possui poderosas funcionalidades, além do ambiente para gestão e edição de documentos, e-mail, planilhas, apresentações, formulários, arquivos.
A criação de macros torna o ambiente ainda mais poderoso.
Macros, Simples como o bom e velho VBA, utilizado para macros no Excel. Não explorei a fundo o Office 365 para falar sobre como estão hoje estes recursos.
Desafio
Criar um sistema para gestão de inventário de hardware e software de máquinas windows utilizando as ferramentas:
Projeto
O projeto visa a criação de uma planilha no google drive onde serão registrados todos os dados das máquinas windows a serem inventariadas.
Como interface de acesso à planilha será criado um weebhook usando Google App Script para escrever nas linhas e colunas da planilha.
O cliente será um script PowerShell porque irá coletar as informações da máquina cliente e fazer o post das informações que serão publicadas na planilha.
A Planilha/Google App Script - (server side)
Vamos começar nosso projeto criando uma planilha simples no Google Spreadsheet.
Nomeie a planilha com um nome a sua escolha.
Ferramentas > Editor de script
Abra a tela do editor de scripts:
Copie o código abaixo:
Trata-se do nosso código escrito em Google App Script.
let configuration = {
has: function () {
if (this.sheet == null) {
this.sheet = SpreadsheetApp.getActive().getSheetByName('settings');
this.tokenlist = {};this.sheet.getRange("A:B").getValues()
.filter(obj => { return (obj[0] != "" && obj[0] != "User") })
.forEach(obj => {
this.tokenlist[obj[1]] = obj[0];
});
}
return (this.sheet != null);
},
get: function (token) {
return this.tokenlist[token.trim()];
}
};let Data = {
setUser: function(user) {
this.user = user;
},
setServiceTag: function(serviceTag) {
this.serviceTag = serviceTag;
},
setHeader: function(header) {
this.header = header;
},
set: function(data) {
this.data = data;
},
get: function() {
let values = [];
this.data._user = this.user;
this.data._date = new Date();
if(this.serviceTag) {
this.data.service_tag = this.serviceTag;
}
this.header.forEach((key,idx) => {
if (this.data[key]) {
values[idx] = this.data[key];
}
});
return values;
}
};//this is a function that fires when the webapp receives a GET request
function doGet(e) {
return HtmlService.createHtmlOutput("request received");
}//this is a function that fires when the webapp receives a POST request
function doPost(e) {
if(e.postData && e.postData.contents) {
let params = JSON.stringify(e.postData.contents);
params = JSON.parse(params);
let data = JSON.parse(e.postData.contents);let responseMsg = "discarded post";
if (configuration.has()) {
let user = configuration.get(data.token);if (user) {
var sheet = SpreadsheetApp.getActive().getSheetByName(data.sheet_name);
if (sheet) {
let header = sheet.getRange("A1:ZZ1").getValues();
Data.setUser(user);
Data.setHeader(header[0]);
Data.setServiceTag(data.service_tag);
if (Array.isArray(data.data)) {
data.data.forEach(_data => {
Data.set(_data);
sheet.appendRow(Data.get());
});
} else {
Data.set(data.data);
sheet.appendRow(Data.get());
}responseMsg = "post accepted";
SpreadsheetApp.flush();
}
}
}return HtmlService.createHtmlOutput(responseMsg);
}
}function uuid() {
return Utilities.getUuid();
}
Selecione o código que aparece no editor:
cole o novo código:
salve e nomeie seu projeto:
publique seu script como aplicativo da web:
click em [Deploy]
clicar [Analisar permissões]
copie a url apresentada, este é o endpoint do seu webhook:
https://script.google.com/macros/s/<id>/exec
Após copiar a url click em [OK].
concluimos aqui o lado server side.
PowerShell — (client side)
Ultimamente, a necessidade em automatizar pequenos processos em ambiente MS Windows me levou de volta ao bom e velho .bat Dos. Como usuário de bash com nível avançado imaginem a irritação devido a forma que algumas coisas são feitas.
Fui encorajado então pelo Ricardo a dar uma olhada em scripts powershell, cara feia, torcida no nariz e voilà!
Comecei a gostar da coisa!
Umas pesquisas na net me levaram à um script que pegava as informações que eu precisava.
Get Server Inventory: CPU, Memory, and OS information. Export to CSV.
Achei o código um pouco bagunçado à primeira vista da linguagem, mas bastante promissor. Então erá só estudar e adaptar para o que eu queria.
O resultado foi o script a seguir, que pode ser executado via powershell em nossas máquinas windows a fim de coletar as informações e enviar à nosso webhook para alimentar a planilha.
<#
.SYNOPSIS
Get Windows Host information
.DESCRIPTION
This script will get the CPU specifications, memory usage statistics, and OS configuration of any Server or Computer listed in $servers variable and post data to $webhook url.
.NOTES
The script will execute the commands on multiple machines sequentially using non-concurrent sessions. This will process all servers from $servers variable listed order.
The info will be exported to a csv format.
Requires:
File Name : MyInventory.ps1
Author: Pedro Robson Leao <pedro.leao@gmail.com>
http://github.com/pedrorobsonleao
References:
https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Script-Get-beced710
https://github.com/ian8667/powershell/blob/master/Get-ServerInfo.ps1
#>
# server or server list to execute this script
$servers = @("localhost")
# webhook endpoint and access token to write in this sheet
$webhook = "https://script.google.com/macros/s/<id>/exec"
$token = "xxxxxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxx"
# config class to get information and sheet to write this information
$configs = '[
{ "class": "Win32_SystemEnclosure", "sheet": "manufacture" },
{ "class": "Win32_Processor", "sheet": "cpu" },
{ "class": "Win32_OperatingSystem", "sheet": "operacional_system" },
{ "class": "CIM_PhysicalMemory", "sheet": "memory" },
{ "class": "Win32_UserAccount", "sheet": "users" },
{ "class": "Win32_Product", "sheet": "softwares" },
{ "class": "Win32_Volume", "sheet": "volumes"},
{ "class": "Service", "sheet": "services" }
]' | ConvertFrom-Json
# start data object to post with the token
$data = @{
"token" = $token
}
# server list iterator
ForEach ($server in $servers) {
# config lines iterator
ForEach ($config in $configs) {
# set sheet name to write
$data.sheet_name = $config.sheet
Try {
if ($config.class -eq "Service") {
# to Service need consult Get-Service information
$data.data = Get-Service -ComputerName $server -ErrorAction Stop
} else {
# to another information use Get-WmiObject with the class
$data.data = Get-WmiObject -ComputerName $server -Class $config.class -ErrorAction Stop
}
if($config.sheet -eq "manufacture") {
# the service tag only is read in manufacture session. I save this information to use in another posts data
$data.service_tag = $data.data.SerialNumber
}
# convert data powershell to json to post
$dt = $data | ConvertTo-Json
# post data to endpoint
$response = Invoke-WebRequest -UseBasicParsing -Uri $webhook -Method Post -ContentType "application/json;charset=UTF-8" -Body $dt
# show status, description and posted data
Write-Host $config.sheet $response.StatusCode $response.StatusDescription
$dt
} Catch {
# when error - show error information
Write-Host $config.sheet $_.Exception
}
}
}
Integrando server e client
Agora que toda a codificação necessária foi feita, vamos comecar a integrar as coisas.
O primeiro passo necessário é criar na planilha a página settings.
Inclua na página settings as colunas User e Token.
Você pode usar a função uuid() na planilha para gerar um novo token, porém lembre-se de copiar o resultado da função e usar a opção colar especial para salvar o número na coluna. Usar a função direto na coluna token irá fazer a planilha mudar o token sempre que for aberta.
Edite o script MyInventory.ps1 e inclua o endpoint e o token no trecho de código que segue:
# webhook endpoint and access token to write in this sheet
$webhook = "https://script.google.com/macros/s/<id>/exec"
$token = "xxxxxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxx"
Após editar o arquivo com as informações, abra um terminal powershell e execute o script:
PS C:\Users\User\Desktop> .\MyInventory2.ps1 >.\object.json
manufacture 200 OK
cpu 200 OK
operacional_system 200 OK
memory 200 OK
users 200 OK
softwares 200 OK
volumes 200 OK
services 200 OK
O arquivo object.json gerado terá todos os objetos coletados no host e postados à planilha. Você pode usar este arquivo para identificar informações que poderão ser incluidas em sua planilha de informações.
Basta criar o nome do campo na primeira linha da planilha.
Os campos _user e _date são incluidos automáticamente pelo servidor ao objeto. O campo serialNumber do objeto manufacture é copiado a todos os outros objetos como service_tag.
Para nosso exemplo vou criar as páginas informadas na execução do script:
- manufacture
- cpu
- operacional_system
- memory
- users
- softwares
- volumes
Após a devida configuração das páginas da planilha, aí é só executar o script em suas máquinas:
Conclusão
Existem no mercado várias ferramentas conceituadas para inventariar hardware e software. Existem opções pagas e open-source e todas de grande qualidade.
A idéia aqui é usar o problema, inventariar máquinas, como case para demonstrar e explorar todo o potencial do ambiente GSuite/Google Drive.