Archive for the ‘Windows Server’ Category

Bamboo is a continuous integration (CI) server that can be used to automate the release management for a software application, creating a continuous delivery pipeline.

In this post we’ll enable users to authenticate to Bamboo using their Active Directory Credentials

Creating service account

We need account for searching AD (domain user account)

 

Capture.PNG

 

Create AD groups: one for Admin, second for user access

Edit 1.png

Edit configuration file (Bambo home\xml-data\configuration\atlassian-user-custom.xml

 

<atlassian-user>
<repositories>
<!– LDAP repository –>
<ldap key=”ldapRepository” name=”Active Directory LDAP Repository” cache=”true”>
<!–
[HOSTNAME], the hostname to your LDAP, (i.e.: 192.168.10.71)
[DISPLAY-NAME], i.e.: Sample User. A
[PASSWORD], password to authenticate “Sample User. A”
–>
<host>1.1.1.1</host>
<port>389</port>
<!–
in <security…> we are going to authenticate our LDAP configuration against a user in our Active Directory
whereas, in this example we will be using “Service Account BAMBOO LDAP. A” as user
–>
<securityPrincipal>CN=Service Account BAMBOO LDAP,OU=service,OU=accounts,DC=company,DC=com</securityPrincipal>
<securityCredential>pass</securityCredential>
<securityProtocol>plain</securityProtocol>
<securityAuthentication>simple</securityAuthentication>
<baseContext>DC=company,DC=com</baseContext>
<!–
in <baseUserNamespace> we are going to specify where our users have been created in the Active Directory
–>
<baseUserNamespace>OU=user,OU=accounts,DC=company,DC=com</baseUserNamespace>
<!–
in <baseGroupNamespace> we are going to specify where our groups have been created in the Active Directory
–>
<baseGroupNamespace>OU=security,OU=groups,DC=company,DC=com</baseGroupNamespace>
<userSearchAllDepths>true</userSearchAllDepths>
<groupSearchAllDepths>true</groupSearchAllDepths>
<usernameAttribute>sAMAccountName</usernameAttribute>
<!–
in <userSearchFilter> we are going to get all users that are members of “Bamboo.App.Admin” and “Bamboo.App.Users” groups
–>
<userSearchFilter>(&amp;(objectClass=person)(|(memberOf=CN=Bamboo.App.Admin,OU=security,OU=groups,DC=company,DC=com)(memberOf=CN=Bamboo.App.Users,OU=security,OU=groups,DC=company,DC=com)))</userSearchFilter>
<firstnameAttribute>givenName</firstnameAttribute>
<surnameAttribute>sn</surnameAttribute>
<emailAttribute>mail</emailAttribute>
<groupnameAttribute>cn</groupnameAttribute>
<!–
in <groupSearchFilter> we are going to get all the groups specified in <baseGroupNamespace>
–>
<groupSearchFilter>(&amp;(objectClass=group))</groupSearchFilter>
<membershipAttribute>member</membershipAttribute>
</ldap>
<!– Default bamboo user repository –>
<hibernate name=”Hibernate Repository” key=”hibernateRepository” description=”Hibernate Repository” cache=”true”/>
</repositories>
</atlassian-user>

 

Restart Bamboo service

4.PNG

 

Point Bamboo to LDAP repository:

Administration-User Management

5.png

Security-user repositories-Custom user repository-save, if config file has any error,it will be shown when you click Save, correct it and click Save again

 

2

 

You should be able to login with AD credentials

 

Setting permissions

Security-Global permissions-under Group access add group and chose permissions

 

6

 

 

Advertisements

In previous post we configured EC2 instance for System Manager Service and executed command manually against EC2 instance.That’s nice, but we can schedule command execution using Lambda.In this example we’ll schedule powershell command which will check if instance is in idle mode (no RDP connection) and, if yes, instance will be stopped.

In that way we’ll save some money ūüôā

First, install System Manager agent on your Windows instance, create IAM System Manager role and assign that role to your instances.Refer to my previous post for more info.

Then add 2 tags:Auto_Stop_Enabled-True and Instance_Used_As_Desktop (so we can filter instances this command will be run against)

2

You can skip these tags creations but also don’t remember to remove is references from Powershell script.

Creating Lambda Function

From AWS console click on Services-Lambda (or just type Lambda in search bar)

2

Click Create function:

2

Enter a name for function-from Role drop-down menu choose create custom role and click Create function

2.PNG

Type a name and click Edit

2

Delete current JSON code and put this one instead:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeTags",
"ec2:DescribeInstanceAttribute",
"ec2:DescribeInstanceStatus"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ssm:DescribeDocument",
"ssm:DescribeDocumentParameters",
"ssm:GetDocument",
"ssm:GetParameter"
],
"Resource": [
"arn:aws:ssm:*:*:document/*",
"arn:aws:ssm:*:*:parameter/*"
]
},
{
"Effect": "Allow",
"Action": [
"ssm:ListInventoryEntries",
"ssm:ListDocumentVersions",
"ssm:ListDocuments",
"ssm:SendCommand"
],
"Resource": "*"
}
]
}

After clicking Apply you’ll be redirected back to Create function-Click Create function

2.PNG

Now scroll down until Function code section-right click auto_stop-New folder-name it modules.

2.PNG

Now right click on modules folder-new-folder-give it name controls

2.PNG

Now, under controls folder create a file named index.js

2

Put following code into index.js Hibernation is Log name,AutoStopScript source name, If you don’t want EC2 tags, then remove

{
Name: "tag:Instance_Used_As",
Values: ["Desktop"]
},
{
Name: "tag:Auto_Stop_Enabled",
Values: ["True","true", "Yes", "yes"]
}
]

auto_stop/modules/control/index.js code:

// Import Dependencies
let AWS = require(‘aws-sdk’);

module.exports.getInstanceIds = () => {
return new Promise(
(resolve, reject) => {
let ec2 = new AWS.EC2();
let params = {
Filters: [
{ Name: “instance-state-name”,
Values: [“running”]
},
{
Name: “tag:Instance_Used_As”,
Values: [“Desktop”]
},
{
Name: “tag:Auto_Stop_Enabled”,
Values: [“True”,”true”, “Yes”, “yes”]
}
]
};

ec2.describeInstances(params, (err, data) => {
if (err) reject(err);

let instanceIds = [];
let reservations = “”;

try {
reservations = data.Reservations;
}
catch(err) {
reject(err);
}
if(Array.isArray(reservations)) {
reservations.forEach((reservation) => {
reservation.Instances.forEach((instance) =>{
instanceIds.push(instance.InstanceId);
});
});
if(instanceIds.length >= 1) {
resolve(
{
“InstanceIds”: instanceIds
}
);
}
else {
reject(new Error(“[Error] getInstanceIds: No instances found.”));
}
}
else {
reject(new Error(“[Error] getInstanceIds: Reservations is not an array.”));
}
});
}
);
};

module.exports.hibernateInstances = (controlObj) => {
return new Promise(
(resolve, reject) => {
let ec2 = new AWS.EC2();
let ssm = new AWS.SSM();

let instanceIds = controlObj.InstanceIds;

let params = {
InstanceIds: instanceIds
};

let ssmParams = {
InstanceIds: instanceIds,
DocumentName: “AWS-RunPowerShellScript”,
Parameters: {
“workingDirectory”:[“”],
“executionTimeout”:[“1200”],
“commands”:[
“########################”,
“#### VARIABLES #########”,
“########################”,
“$eventLogName = \”Hibernation\””,
“$eventSourceName = \”AutoStopScript\””,
“$eventLogIds = @{“,
” 1001 = \”Event log initialised.\”;”,
” 1002 = \”No active RDP sessions were found. Proceed to hibernate the instance.\”;”,
” 1003 = \”Active RDP session detected. Abort the hibernation attempt.\”;”,
” 1004 = \”Hibernation is enabled. Preparing for shutdown.\”;”,
” 3001 = \”CPU Usage is higher than the threshold. The hibernation is cancelled.\””,
” 4001 = \”Trouble accessing ‘qwinsta’ executable. Make sure ‘qwinsta’ is in the PATH.\”;”,
” 4002 = \”Trouble accessing ‘powercfg’. Make sure it is in PATH.\”;”,
” 4003 = \”Hibernation was not enabled successfully. Check C:\\ for enough drive space.\”;”,
” 4004 = \”Hibernation attempt failed. Please check if ‘shutdown’ is in PATH.\”;”,
“”,”}”,””,
“$mailMessages = @{“,
” hibernationEnableError = \”Error: Failed to enable hibernation.\”;”,
” hibernationStartError = \”Error: Failed to hibernate an instance.\”;”,”}”,”$minAverageCPU = 20 #If an instance has less than 20% average CPU usage in the period of 5 minutes, it will get shut down.”,””,”########################”,”#### INITIALIZATION ####”,”########################”,
“#### EVENT LOG INIT”,”Try {“,” $null = Get-EventLog -LogName $eventLogName -ErrorAction Stop”,”}”,”Catch {“,” Try {“,” New-EventLog -LogName $eventLogName -Source $eventSourceName -ErrorAction Stop”,” } “,” Catch {“,” #Noop”,” }”,” “,” Write-EventLog -LogName $eventLogName -Source $eventSourceName -EntryType Information -EventId 1001 -Category 1 -Message $eventLogIds.1001″,”}”,””,
“########################”,”#### FUNCTIONS #########”,”########################”,”# # Used to send notifications to the uses.”,”# Function Send-RESTMailMessage {“,”# Param (“,”# $Subject,”,”# $Message,”,”# $Recipient”,”# )”,”# $_headers = New-Object \”System.Collections.Generic.Dictionary[[String],[String]]\””,”# $_headers.Add(\”Content-Type\”, ‘application/json’)”,”# $_headers.Add(\”Cache-Control\”, ‘no-cache’)”,
“# $_headers.Add(\”x-api-key\”, ‘flREiNZkVK2lgGHWHUmxr1VPP8GIfLTz7uVH6eKz’)”,””,”# $body = @{“,”# subject=$Subject”,”# message=$Message”,”# auth_key=’sDfFXAk421412DSAkxKLaksdKASdFG'”,”# recipients=@($Recipient)”,”# }”,””,”# $body = $body | ConvertTo-JSON”,””,”# $response = Invoke-RestMethod -Uri \”https://ekiss3x6gl.execute-api.us-east-1.amazonaws.com/v1/notifications/system\” -Method Post -Headers $headers -Body $body”,”# return $response”,”# }”,
“”,”Function Get-ActiveRDPSessions {“,” # Check for any active RDP sessions.”,” # This function relies on \”qwinsta\” tool which comes bundled with Windows.p”,” # The function returns \”true\” if there are active RDP sessions or \”false\” if there aren’t any.”,” Param (“,” $EventLogName,”,” $EventSourceName,”,” $EventIds”,” )”,” Try {“,” $_allSessions = qwinsta”,” }”,” Catch {“,” Write-EventLog -LogName $EventLogName -Source $EventSourceName -EntryType Error -EventId 4001 -Category 4 -Message $EventIds.4001″,” return 1″,” }”,” “,” ForEach($_s in $_allSessions) {“,” If($_s -match \”rdp\” -and $_s -match \”Active\”) {“,” Write-EventLog -LogName $EventLogName -Source $eventSourceName -EntryType Information -EventId 1003 -Category 1 -Message $EventIds.1003″,” return \”ActiveSessionFound\””,” }”,” }”,” “,” Write-EventLog -LogName $EventLogName -Source $eventSourceName -EntryType Information -EventId 1002 -Category 1 -Message $EventIds.1002″,” return \”NoActiveSessionFound\””,”}”,””,”Function Enable-Hibernation {“,” Param (“,” $EventLogName,”,” $EventSourceName,”,” $EventIds”,” )”,””,” Try {“,” $_process = Start-Process powercfg -ArgumentList \”/h\”, \”on\” -PassThru -ErrorAction Stop”,” Start-Sleep -Seconds 3″,” }”,” Catch {“,” Write-EventLog -LogName $EventLogName -Source $EventSourceName -EntryType Error -EventId 4002 -Category 4 -Message $EventIds.4002″,” return 1″,” }”,””,” If ($_process.ExitCode -eq 0) {“,” Write-EventLog -LogName $EventLogName -Source $EventSourceName -EntryType Information -EventId 1004 -Category 1 -Message $EventIds.1004″,” return \”Enabled\””,””,” } “,” Else {“,” Write-EventLog -LogName $EventLogName -Source $EventSourceName -EntryType Error -EventId 4003 -Category 4 -Message $EventIds.4003″,” return 1″,” }”,”}”,””,”Function Start-Hibernation {“,” Param (“,” $EventLogName,”,” $EventSourceName,”,” $EventIds”,” )”,””,” Try {“,” $_process = Start-Process shutdown -ArgumentList \”/h\” -PassThru -ErrorAction Stop”,” }”,” Catch {“,” Write-EventLog -LogName $EventLogName -Source $EventSourceName -EntryType Error -EventId 4004 -Category 4 -Message $EventIds.4004″,” return 1″,” }”,”}”,””,”Function Check-CPUUsage {“,” $_samples = 5″,” $_intervalSeconds = 60″,” $_cpuLoadAverage = 0″,” For($i = 0; $i -ne $_samples; $i++) {“,” $_cpuLoadAverage += (Get-WmiObject win32_processor).LoadPercentage”,” Start-Sleep -Seconds $_intervalSeconds”,” }”,””,” return $_cpuLoadAverage / $_samples “,”}”,””,””,”########################”,”#### MAIN ##############”,”########################”,”$rdpSessionStatus = Get-ActiveRDPSessions -EventLogName $eventLogName -EventSourceName $eventSourceName -EventIds $eventLogIds”,””,”If ($rdpSessionStatus -eq \”NoActiveSessionFound\”) {“,” #Enable Hibernation”,” Enable-Hibernation -EventLogName $eventLogName -EventSourceName $eventSourceName -EventIds $eventLogIds”,” “,” If(Check-CPUUsage -lt $minAverageCPU) {“,””,””,” # TODO Notify User”,” # TODO Wait 10 minutes”,” # TODO Check for active RDP sessions again”,””,” #Hibernate”,” Start-Hibernation -EventLogName $eventLogName -EventSourceName $eventSourceName -EventIds $eventLogIds”,” }”,” Else {“,” Write-EventLog -LogName $EventLogName -Source $EventSourceName -EntryType Warning -EventId 3001 -Category 3 -Message $EventIds.3001″,” return 0″,” }”,”} “,”Else {“,” return 0″,”}”
]
},
MaxErrors: “0”,
TimeoutSeconds: 120
}

// Hibernate instances
ssm.sendCommand(ssmParams, function(err, data) {
if (err) reject(err);
resolve(data);
});
resolve(instanceIds);
console.log(instanceIds);
}
);
};

 

Now click on “parent” index.js (under auto_stop only)

 

2.PNG

paste following code (change AWS zone to fit your needs):

 

// Global Module Imports
let AWS = require(‘aws-sdk’);
AWS.config.region = “eu-west-1”;
let controls = require(“./modules/controls”);

// This is the function AWS Lambda will execute.
exports.handler = (event, context, callback) => {

// Execute the power control
controls.getInstanceIds()
.then(controls.hibernateInstances)
.catch((err) => {
callback(err);
});
};

At the end it should be like this:

 

2.PNG

 

Now, we need to schedule our function:

in Add trigger section click CloudWatch Events

 

2.PNG

Give it name and set schedule

 

You can use the following sample cron strings when creating a rule with schedule.

Minutes Hours Day of month Month Day of week Year Meaning
0 10 * * ? * Run at 10:00 am (UTC) every day
15 12 * * ? * Run at 12:15 pm (UTC) every day
0 18 ? * MON-FRI * Run at 6:00 pm (UTC) every Monday through Friday
0 8 1 * ? * Run at 8:00 am (UTC) every 1st day of the month
0/15 * * * ? * Run every 15 minutes
0/10 * ? * MON-FRI * Run every 10 minutes Monday through Friday
0/5 8-17 ? * MON-FRI * Run every 5 minutes Monday through Friday between 8:00 am and 5:55 pm (UTC)

 

In this example i set it to run every 20 minutes.

 

2.PNG

 

It should be something like this:

 

2

When you click on run_auto_stop_script you’ll get following picture:

 

2

 

If your instance is idle, it should be stopped. You can check it from AWS console-EC2-SYSTEM-MANAGER SHARED RESOURCES-Run Command

3.PNG

 

AWS Systems Manager is a management service that helps automatically collect software inventory, apply OS patches, create system images, and configure Windows and Linux operating systems (running scripts).

Creating System Manager role

In AWS console click on IAM

6

Roles-create role, choose EC2 and click next

Untitled.png

Then select EC2 Role for Simple Systems Manager and click Next

Untitled.png

in Attached permission policy select AmazonEC2RoleforSSM

Untitled

Click next, give role a name and click Create role

Assigning role to EC2 instance

In this example i used Windows Server 2016 EC2 instance.Select EC2 in list of services, select instance-Action-Instance Setting-Attach/Replace IAM Role

Untitled

Select System Manager Role and click Apply

Untitled

Installing  SSM agent

Login to EC2 instance,download and install SSM agent.Start service:

Start-Service AmazonSSMAgent

 

Running command

In AWS console-EC2 service-Scroll until SYSTEM MANAGER SHARED RESOURCES-Managed instances

 

Untitled.png

 

Select instance and click Run a command

Untitled.png

 

Select one of the commands

Untitled

 

Type command and click Run

Untitled.png

Click on Command ID

 

Untitled.png

 

Then click output-View Output

Untitled

 

Untitled.png

 

 

In previous post we added linux node to Rundeck server.Now, we’ll add a Windows Server

Creating AD user

I’ll be adding Domain Controller to Rundeck, so i created Domain user and put it in Built-in Administrator group,username:rundeck@test.com

Capture.PNG

Installing OpenSSH server on Windows Server

In order to run inline scripts against Windows server we need password-less connection to Windows server (private/public key authentication), because Rundeck first copies script to remote node before executing it

Download OpenSSH server,unzip it and copy it to desired destination (i put it in C:\Program Files)

Capture.PNG

With powershell browse to unzipped folder and run ./install-sshd.ps1

Two services should be installed:sshd and ssh-agent,make sure both are running-set Startup type to Automatic

Capture.PNG

Open sshd_config_default file

Capture.PNG

edit is as following:

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

#HostKey __PROGRAMDATA__/ssh/ssh_host_rsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_dsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ecdsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:
RSAAuthentication yes
#LoginGraceTime 2m
#PermitRootLogin prohibit-password
PermitRootLogin yes
StrictModes no
#MaxAuthTries 6
#MaxSessions 10
RhostsRSAAuthentication yes
PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile	.ssh/authorized_keys

#AuthorizedPrincipalsFile none

# For this to work you will also need host keys in %programData%/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication yes
#PermitEmptyPasswords no

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#PermitUserEnvironment no
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# override default of no subsystems
Subsystem	sftp	sftp-server.exe

# Example of overriding settings on a per-user basis
#Match User anoncvs
#	AllowTcpForwarding no
#	PermitTTY no
#	ForceCommand cvs server

In Rundeck user profile folder create folder .ssh

cd C:\Users\rundeck
mkdir .ssh

Create keypair on Rundeck server (if not created)

ssh-keygen

Copy  Rundeck public key (cat /root/.ssh/id_rsa.pub) to Windows machine to .ssh folder of rundeck user-authorized_keys file, if folder is not visible enable showing hidden folders and files

Capture.PNG

On Windows,make sure port 22 is opened, restart sshd,Restart-Service sshd

Try ssh connection to Windows server from Rundeck

ssh rundeck@192.168.0.13

You shouldn’t be asked for password

Capture.PNG

Creating project

Capture.PNG

Capture.PNG

Add node (resources.xml)

Linuxtopic/server.1key was created in previous post.

 

<node name=”dc” description=”My windows” tags=”node2″ hostname=”192.168.0.13″ osArch=”x86_64″ osFamily=”Windows” osName=”Windows Server 2016″ username=”rundeck” ssh-key-storage-path=”keys/Linuxtopic/server.1key” />

 

Password authentiation

If, for some reason Public key authentication doesn’t work (it happened to me with AWS EC2 Windows instance-Write Failed: broken pipe ) , we can try password authentication

 

0-1

 

Key Type: Password

 

0

Specify Password storage created in step above and password as SSH authentication

 

Capture

 

 

Untitled

 

resources.xml:

 

<node name=”windows” description=”My windows” tags=”node2″ hostname=”1.1.1.2″ osArch=”x86_64″ osFamily=”Windows” osName=”Windows Server 2016″ username=”rundeck” ssh-authentication=”password” ssh-password-storage-path=”keys/Windows” />

 

 

Creating Job

I added Powershell script to get AD user and to create OU

Capture.PNG

Capture.PNG

Capture.PNG

Chocolatey AU module is great for automatically updating multiple package files, but all files are downloaded to temp folder, as result, user needs to have internet connection so he can download newest packages.This Powershell script will copy setup files to respective tools folder

#delete old setup files downloaded by AU module (downloaded to temp folder)

Get-ChildItem -Path "Z:\*\tools\*" -filter *.exe | Remove-Item -Force -Recurse

 

#Delete content of TEMP folder (where chocolatey module stores packages)

Set-Location $env:TEMP
Remove-Item * -recurse -force

 

#Update all packages

 

Z:

updateall

#Copy new exe/MSI to respective directory and create packages

 

#ccleaner

$file=Get-ChildItem -Path $env:TMP -recurse -Filter cc*.exe
$filename=$file.FullName
copy-item $filename Z:\Ccleaner\tools\ccleaner.exe
cd Z:\ccleaner
choco pack


#VLC Player

$file=Get-ChildItem -Path $env:TMP -recurse -Filter vlc*.exe
$filename=$file.FullName
copy-item $filename Z:\VideoLAN\tools\vlcplayer.exe

cd Z:\VideLAN

choco pack

#WINRAR

$file=Get-ChildItem -Path $env:TMP -recurse -Filter winrar*.exe
$filename=$file.FullName
copy-item $filename Z:\WinRAR\tools\winrar.exe
cd Z:\WinRar
choco pack

#Same for all packages......

In previous article we set package to always download newest version, now we’ll see how to update multiple packages. In this example i created 3 packages (VideoLAN,CCleaner and WinRAR) and put it in Z: drive

We can easily update all packages by running updateall | ft  powershell command (to see all packages created by AU module  type lsau

Capture

If we want to get some report and to get more flexibility we need to use update-all.ps1.(Available on github).

Capture

First, we need to change path to reflect package path

2.png

We can also run update or to specific packages or to packages wich starts with specific name

.\update_all.ps1 -name ccleaner
.\update_all.ps1 -name c*

We also can also send reports by email (2 reports are created:update_info.xml and AUPackages.md)

3

Besides, we can set timeout for package URL checks, should we push packages to github…

Reading xml file

Import-Clixml .\update_info.xml | set info

info variable has some properties: $results, to get summary of updates

PS Z:\> $info.result
 
all : {AUPackage, AUPackage, AUPackage}
ignored :
errors :
ok : {AUPackage, AUPackage, AUPackage}
pushed :
updated : {AUPackage, AUPackage, AUPackage}

$info.packages (to list packages)

PS Z:\> $info.packages
Directory: Z:\

Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/2/2018 12:33 PM ccleaner
d----- 3/2/2018 12:37 PM VideoLAN
d----- 3/2/2018 12:31 PM winrar

$info.updated (count of updated packages)

$info.result.ok (see updated packages)
$info.result.errors (to see errors)

$info.result. yields more outputs

 

Chocolatey is package manager for Windows.AU is module which help us to update/install packages to newest version,directly from web site

Prerequisites:

powershell 5.1

set-executionpolicy -bypass

-Disable Enhanced IE settings:

1

-Allow cookies

1

Installation:

choco install au

Download au-template from github, find and copy update.ps1 to your package folder

1

Edit update.ps1

import-module au

$releases = 'https://www.ccleaner.com/ccleaner/download/standard'

function global:au_SearchReplace {

@{

"tools\chocolateyInstall.ps1" = @{

"(?i)(^\s*url\s*=\s*)('.*')"      = "`$1'$($Latest.URL32)'"           #1

"(?i)(^\s*checksum\s*=\s*)('.*')" = "`$1'$($Latest.Checksum32)'"      #2

}

}

}
function global:au_GetLatest {
    $download_page = Invoke-WebRequest -Uri $releases
    $url = $download_page.links | ? href -match '\.exe$' | % href | select -First 1
    $ver=$url.Substring(36,3)
    $version=$ver.Insert(1,".")
    @{URL32=$url;Version=$version}
     
}

update -ChecksumFor 32 -force

Function au_SearchReplace:

Searches for¬† url and checksum fields in nuspec file and in chocolateyinstall.ps1 and put there values from “`$1’$($Latest.URL32)'” and “`$1’$($Latest.Checksum32)'” respectively

Function au_GetLatest:

Lists paths to execustable files and extract version (540) then adding ‚Äú.‚ÄĚ (5.40) and calculates hash.

Nuspec and chocolateyinnstall.ps1 files:

 

Nuspec:

<?xml version=”1.0″ encoding=”utf-8″?>

<package xmlns=”http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd”&gt;

<metadata>

<id></id>

<version></version>

<title></title>

<authors>__REPLACE_AUTHORS_OF_SOFTWARE_COMMA_SEPARATED__</authors>

<projectUrl>https://_Software_Location_REMOVE_OR_FILL_OUT_</projectUrl&gt;

<tags></tags>

<summary></summary>

<description></description>

</metadata>

<files>

<!– this section controls what actually gets packaged into the Chocolatey package –>

<file src=”tools\**” target=”tools” />

<!–Building from Linux? You may need this instead: <file src=”tools/**” target=”tools” />–>

</files>

</package>

<!–Building from Linux? You may need this instead: –>

 

Chocolateyinstall.ps1: (located in tools folder)

 

1.PNG

 

 

$ErrorActionPreference = 'Stop'; # stop on all errors

$toolsDir   = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"

$packageArgs = @{

packageName   = 'ccleaner'

fileType      = 'EXE' #only one of these: exe, msi, msu

url           = ''

checksum      = ''

checksumType  = 'sha256' #default is md5, can also be sha1, sha256 or sha512

silentArgs    = "/S"

validExitCodes= @(0, 3010, 1641)

}

Install-ChocolateyPackage @packageArgs

 

Test au_GetLatest-you should get download link and version

 

1.PNG

 

Now try executing .\update.ps1, you can ignore error ūüėä

As we can see from output, version, id, url and checksum will be placed in nuspec and chocolateyinstall files

1.PNG

 

Check nuspec and chocolateyinstall files again:url,version and checksum values should be populated:

 

1

 

1.PNG

 

Testing package

In powershell run test-package install/test-package-uninstall

1.PNG

 

nupkg file is created

 

1