How to download aws cli and use in the same powershell script - amazon-web-services

I have the following powershell script that runs via packer utility while creating aws ami image.
This script downloads and installs aws cli and then immediately try to use it. The installation process will update windows PATH environment variable but I think it will not be available immediately in the same script. So I set the location to where cli is installed before using it.
$SETUP_DIR = "C:\Setup"
New-Item -Path $SETUP_DIR -ItemType Directory -Force -ErrorAction SilentlyContinue
Clear-Host
Set-Location -Path $SETUP_DIR -PassThru
# install AWS CLI
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi /quiet
Write-Host "AWS CLI installation completed."
# Set location to AWS CLI
Set-Location -Path "C:\Program Files\Amazon\AWSCLIV2" -PassThru
# Download utility from AWS S3
aws s3 cp s3://tools/utility.exe
Write-Host "Utility download completed."
# switch the location back to c:\setup
Set-Location -Path $SETUP_DIR -PassThru
However when the script executed, it throws error as The term 'aws' is not recognized
aws s3 cp s3://tools/utility.exe ...
==> amazon-ebs.windows_server: + ~~~
==> amazon-ebs.windows_server: + CategoryInfo : ObjectNotFound: (aws:String) [], CommandNotFoundException
==> amazon-ebs.windows_server: + FullyQualifiedErrorId : CommandNotFoundException
==> amazon-ebs.windows_server:
amazon-ebs.windows_server:
==> amazon-ebs.windows_server: aws : The term 'aws' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the
==> amazon-ebs.windows_server: spelling of the name, or if a path was included, verify that the path is correct and try again.

When you run aws s3 ... system is trying to locate aws in the system path it knows about. The fact that you change directory to the location of the aws binary does not do anything for you.
As you probably know, even when you are in the same directory as a binary, if you simply try to use it, it won't work if it is not in the path, and that's why you would use .\binary_name.exe That's a safety feature in PowerShell.
You could try updating the path as suggested in the commends by adding that location:
$env:path="$env:path;C:\Program Files\Amazon\AWSCLIV2"
or point to the binary directly. You could also create an alias like:
set-alias -name aws -value "c:\program files\Amazon\awscliv2\aws.cmd"
Then use aws and it should run the aws.cmd (check that folder to make sure you are calling the correct binary. It used to be aws.cmd for aws cli v1 but may have changed)

Related

How to create IAM group and user in AWS using powershell?

1 I am using PowerShell and want to run following command New-IAMGroup -Path "/ps-created-groups/" -GroupName "powerUsers", but getting below error
New-IAMGroup : The term 'New-IAMGroup' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At line:1 char:1
New-IAMGroup -Path "/ps-created-groups/" -GroupName "powerUsers"
+ CategoryInfo : ObjectNotFound: (New-IAMGroup:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
How can this be resolved? I am new to Powershell.Your help much appreciated
The powershell cli for AWS does not install service specific cmdlets. You need to install them yourself.
See AWS documentation for this - https://docs.aws.amazon.com/powershell/latest/userguide/pstools-getting-set-up-windows.html
For IAM this will help you install the right cmdlets.
Install-AWSToolsModule AWS.Tools.IdentityManagement -Scope AllUsers
And then try to run your commands.
P.S. change the scope from AllUsers to CurrentUser as needed.

aws command not getting recognized after MSI install

I am new to powershell here. I can't figure out why after successfully installing AWS CLI, I intermittently get back aws command not recognized error. I put in sleep thinking some environment variables might be getting set in background. Need help figuring out what do I need to do here to able to to successfully execute $putItem command.
I followed the instructions here https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-windows.html
PLEASE NOTE: The whole thing has to be automated, so I can't manually login to a host and fix something as this same script has to be run on 100+ hosts
Write-Output "Checking if AWS CLI support exists..."
cmd.exe /c "aws --version"
if ($LASTEXITCODE -eq 0){
Write-Output "AWS CLI installed already"
} else {
Write-Output "Installing AWS CLI V2"
cmd.exe /c "msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi /qn"
if ($LASTEXITCODE -eq 0){
Write-Output "AWS CLI installed successfully"
Start-Sleep -s 5
} else {
Write-Output "Could not install AWS CLI"
exit 1
}
}
$putItem = 'aws dynamodb put-item --table-name ' + $instanceStatusDDBTable + ' --item "{\"HostName\" : {\"S\" : \"' + $instanceName + '\"}, \"Modules\" : {\"M\" : {}}, \"DAGName\" : {\"S\" : \"' + $dagName +'\"}}"'
Write-Output "Executing DB put item query $putItem"
cmd.exe /c $putItem
if ($LASTEXITCODE -eq 0){
Write-Output "Created entry for $instanceName in $instanceStatusDDBTable DDB table"
} else {
Write-Output "Could not complete put Item operation for $instanceName"
exit 1
}
Here is the output
Checking if AWS CLI support exists...
Installing AWS CLI V2
AWS CLI installed successfully
Executing DB put item query aws dynamodb put-item --table-name Ex2019-HostStatusTable --item "{\"HostName\" : {\"S\" : \"Host1\"}, \"Modules\" : {\"M\" : {}}, \"DAGName\" : {\"S\" : \"USW-D01\"}}"
Could not complete put Item operation for Host1
Error output -
'aws' is not recognized as an internal or external command,
operable program or batch file.
Try adding the below code to refresh your environment variables after you check your $LASTEXITCODE variable. The shell session has to regather the updated environment variables your installer just added. See this response for more info.
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
You may also want to consider using the Start-Process with the -wait and -passthru params to invoke your installer as the cmd may not wait long enough for the app to finish installing. You can read up on here. I do agree with David, you could just check to see if it's installed by running aws --version and then reading in the version number or catching the error in a try catch block.

How to properly use AWS Secrets Manager in a Elastic Beanstalk Deployment on Windows Server

Im trying to pass my applications connectionstring from Secrets Manager into Elastic Beanstalk during deployment. If i remote desktop onto the server i am deploying to, i can run the following command -
aws secretsmanager get-secret-value --secret-id XXX-MY-SECRET-ID --version-stage AWSCURRENT --query=SecretString --output text
And it outputs correctly. All good.
However when i try and automate this through the .ebextensions folder, it always returns an empty string.
So ive tried lots of things, firstly using a container command to point to a Powershell file that i placed in the .ebextensions folder, like so -
container_commands:
00-myscript:
command : powershell.exe -ExecutionPolicy Bypass -Command ".\\.ebextensions\\BuildConnectionStrings.ps1"
Then the Powershell command would be
$response = aws secretsmanager get-secret-value --secret-id XXX-MY-SECRET-ID --version-stage AWSCURRENT --query=SecretString --output text
$FileName = "ConnectionStrings.config"
New-Item $FileName -ItemType File
Set-Content $FileName $response
If i run this directly in powershell, it all works as expected. But when i deploy the site, it just creates an empty file.
Ive tried various combinations of putting the Powershell commands directly in the .ebextensions config files, always with the same result.
I just cant figure out why the same commands work when i run them directly on the server, but not when deployed through EB.
Ive been stuck for days on this, can anyone help?
So for anyone else that has this problem...
Simply installing the aws cli on the server is not enough. The error i was getting was caused by PowerShell not recognising the aws command (even tho it had been installed).
The solution was to run the following code at the beginning of my script -
$command = "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12"
Invoke-Expression $command
Invoke-WebRequest -Uri "https://awscli.amazonaws.com/AWSCLIV2.msi" -Outfile C:\AWSCLIV2.msi
$arguments = "/i `"C:\AWSCLIV2.msi`" /quiet"
Start-Process msiexec.exe -ArgumentList $arguments -Wait
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")
aws --version
This ensured that the aws cli would be installed (again).
I dont know why this is necessary, but its the only solution ive found

Powershell can't remove file i just wrote

I wanted to install git on an AWS EC2 Windows Server. So i used an Invoke-WebRequest to download the portable git exe
Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.23.0.windows.1/PortableGit-2.23.0-64-bit.7z.exe -UseBasicParsing -OutFile git.exe
But the Download got stuck and i terminated the session. Now i want to remove git.exe but for some reason i'm not allowed to.
I tried removing the file with:
Remove-Item .\git.exe
But i got an error message telling me i'm not allowd to
Remove-Item : Cannot remove item C:\git.exe: Access to the path 'C:\git.exe' is denied.
At line:1 char:1
+ Remove-Item .\git.exe
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\git.exe:FileInfo) [Remove-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : RemoveFileSystemItemUnAuthorizedAccess,Microsoft.PowerShell.Commands.RemoveItemCommand
I just found out that the Invoke-WebRequest was not properly terminated and the stuck process still kept the file on lock. after restarting the server i was able to delete the file. Thanks for the suggestions and comments.

Debugging a PowerShell script in .ebextensions

I'm trying to follow the instructions on https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/SSLNET.SingleInstance.html to install a self-signed certificate on an Elastic Beanstalk dev instance. That is, I have (in addition to other prerequisites listed there), a .ebextensions/https-instance-dotnet.config file of the form:
files:
"C:\\certs\\install-cert.ps1":
content:
Echo "I want some SSL"
import-module webadministration
## Settings - replace the following values with your own
$bucket = "my-bucket"
$certkey = "example.com.pfx"
$pwdkey = "password.txt"
[...]
commands:
00_install_ssl:
command: powershell -NoProfile -ExecutionPolicy Bypass -file C:\\certs\\install-cert.ps1 > c:\\certs\\log.txt
I'm publishing from Visual Studio to AWS EB using AWS Toolkit and not seeing errors. The file seems to be formatted correctly according to a YAML validator. But I can't tell if the script is working or not, or even being run, or if C:\certs\install-cert.ps1 and log.txt are being created in my environment.
My question is: How do I debug or trace this so I can see (for example) the results of the Echo commands?