215 lines
9.3 KiB
PowerShell
215 lines
9.3 KiB
PowerShell
function New-ServerlessServiceAccountPair {
|
|
<#
|
|
.SYNOPSIS
|
|
Top-level function to create serverless service accounts.
|
|
|
|
.DESCRIPTION
|
|
Top-level function to create serverless service accounts. Initializes data structures and invokes
|
|
individual handling functions to create an Active Directory user account pair and an AWS Secrets
|
|
Manager secret containing the authentication parameters for the users.
|
|
|
|
.PARAMETER Cred
|
|
[PSCredential] A credential object for the FH user that has permissions to create new accounts
|
|
on the domain.
|
|
|
|
.PARAMETER ServiceName
|
|
[string] The truncated identifier for the service name. Must be nine characters or less.
|
|
|
|
.PARAMETER Environment
|
|
[string] The target environment for the user accounts.
|
|
|
|
.PARAMETER ProfileName
|
|
[string] The AWS profile to use during user creation.
|
|
|
|
.PARAMETER TicketNumber
|
|
[string] The Jira ticket identifier requesting the new accounts.
|
|
|
|
.PARAMETER ServiceAccountIamRoleArn
|
|
[string] The AWS IAM role ARN that should be granted access to the AWS Secrets Manager secret.
|
|
|
|
.PARAMETER Region
|
|
[string] The AWS region to use during user creation. If not provided, defaults to 'us-east-1'
|
|
|
|
.PARAMETER ReplicationRegion
|
|
[string] The target AWS region for replicated AWS Secrets Manager secrets.
|
|
To disable replication, set this value to null or empty. If not provided, defaults to 'us-west-2'.
|
|
|
|
.PARAMETER SecretAccessExtraArns
|
|
[string[]] An array of AWS ARNs allowed to access the created secret in addition to the defaults.
|
|
|
|
.PARAMETER RotationSchedule
|
|
[string] A scheduling expression for password rotation. Refer to https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_schedule.html.
|
|
To disable rotation, set this value to null or empty.
|
|
If not provided, the default scheduling expression will rotate passwords at 1400 UTC on the first Tuesday of the month.
|
|
|
|
.PARAMETER RotationWindow
|
|
[string] A window duration for password rotation. Refer to https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotate-secrets_schedule.html.
|
|
If not provided, the default rotation window is two hours.
|
|
|
|
.INPUTS
|
|
None. You cannot pipe objects to New-ServerlessServiceAccountPair.
|
|
|
|
.OUTPUTS
|
|
[PSObject] New-ServerlessServiceAccountPair returns an object with the following top-level members:
|
|
[PSCredential[]] Credentials : Contains the usernames and passwords created by this function.
|
|
[string[]] SecretArns : Contains the ARN(s) of the AWS Secrets Manager secret(s) created by this function.
|
|
|
|
.EXAMPLE
|
|
New-ServerlessServiceAccountPair -Cred (Get-AlkamiCredential) `
|
|
-ServiceName 'Example' `
|
|
-Environment 'Prod' `
|
|
-ProfileName 'temp-prod' `
|
|
-TicketNumber 'SYSENG-1234' `
|
|
-ServiceAccountIamRoleArn 'arn:aws:iam::000000000000:role/example-services-accounts-role' `
|
|
-Region 'us-east-1' `
|
|
-ReplicationRegion 'us-west-2' `
|
|
-SecretAccessExtraArns @( 'ExampleArn1' )
|
|
|
|
SecretArns Credentials
|
|
---------- -----------
|
|
{ExampleSecretArn1, ExampleSecretArn2} {System.Management.Automation.PSCredential, System.Management.Automation.PSCredential}
|
|
#>
|
|
[OutputType([PSObject])]
|
|
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory = $true)]
|
|
[PSCredential] $Cred,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateLength(1, 8)]
|
|
[string] $ServiceName,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateSet('Dev', 'Qa', 'LoadTest', 'Staging', 'Prod', IgnoreCase = $false)]
|
|
[string] $Environment,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string] $ProfileName,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidatePattern("^[a-z]+-\d+$")]
|
|
[string]$TicketNumber,
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string] $ServiceAccountIamRoleArn,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[ValidateScript({$_ -in (Get-AWSRegion).region})]
|
|
[string] $Region = 'us-east-1',
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[ValidateScript({([String]::IsNullOrEmpty($_) -or ($_ -in (Get-AWSRegion).region))})]
|
|
[string] $ReplicationRegion = 'us-west-2',
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string[]] $SecretAccessExtraArns = $null,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string] $RotationSchedule = 'cron(0 14 ? * 3#1 *)',
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[string] $RotationWindow = '2h'
|
|
)
|
|
|
|
$logLead = Get-LogLeadName
|
|
$usernamePrefix = "${Environment}${ServiceName}Svc"
|
|
$environmentTagValue = ( "{0}shared" -f $Environment.ToLower() )
|
|
$userOuPathCommon = "/ServiceAccounts/${Environment}"
|
|
$secretName = "${userOuPathCommon}/${usernamePrefix}"
|
|
$secretDescription = "Serverless service account secret for $usernamePrefix"
|
|
$accessArns = @($ServiceAccountIamRoleArn)
|
|
$result = New-Object PSObject -Property @{
|
|
Credentials = @()
|
|
SecretArns = @()
|
|
}
|
|
|
|
# Dump out a list of the decisions we made if the user wants to see them.
|
|
Write-Verbose "$logLead : Username prefix evaluated to be '$usernamePrefix'."
|
|
Write-Verbose "$logLead : Environment tag evaluated to be '$environmentTagValue'."
|
|
Write-Verbose "$logLead : User OU Path that will be used by Active Directory and AWS Secrets code evaluated to be '$userOuPathCommon'."
|
|
Write-Verbose "$logLead : Secret name evaluated to be '$secretName'."
|
|
Write-Verbose "$logLead : Secret description evaluated to be '$secretDescription'."
|
|
|
|
# Generate two usernames and passwords for multi-user rotation strategy.
|
|
for ($i = 0; $i -lt 2; $i++) {
|
|
|
|
$result.Credentials += ( Get-AlkamiCredential -UserName ( "{0}{1}" -f $usernamePrefix, [char]([byte][char]'A' + $i)) `
|
|
-Password (New-SecurePassword -PasswordLength 20 -ProfileName $ProfileName -Region $Region ))
|
|
}
|
|
|
|
try {
|
|
|
|
# Create users in AD.
|
|
New-ServerlessServiceAccountActiveDirectoryUserPair -Cred $Cred `
|
|
-UserDataList $result.Credentials `
|
|
-UserOuPathCommon $userOuPathCommon `
|
|
-Environment $Environment `
|
|
-TicketNumber $TicketNumber
|
|
|
|
} catch {
|
|
|
|
Write-Error "$logLead : Creation of Active Directory users failed. Error encountered was: [$PSItem]"
|
|
return $result
|
|
}
|
|
|
|
try {
|
|
# Create secret
|
|
$result.SecretArns = New-ServerlessServiceAccountSecret -SecretName $secretName `
|
|
-UserDataList $result.Credentials `
|
|
-EnvironmentTag $environmentTagValue `
|
|
-ProfileName $ProfileName `
|
|
-Region $Region `
|
|
-ReplicationRegion $ReplicationRegion `
|
|
-Description $secretDescription
|
|
|
|
} catch {
|
|
|
|
Write-Error "$logLead : Creation of AWS secret failed. Error encountered was: [$PSItem]"
|
|
return $result
|
|
}
|
|
|
|
try {
|
|
|
|
New-ServerlessServiceAccountIamPolicy -RoleArn $ServiceAccountIamRoleArn `
|
|
-ProfileName $ProfileName `
|
|
-Region $Region `
|
|
-SecretArns $result.SecretArns
|
|
|
|
} catch {
|
|
|
|
Write-Warning "$logLead : Creation of IAM policy failed. Error encountered was: [$PSItem]"
|
|
}
|
|
|
|
try {
|
|
$accessArns += $SecretAccessExtraArns
|
|
$accessArns += ( Get-YeatsLambdaIamRoleArn -EnvironmentTag $environmentTagValue -ProfileName $ProfileName )
|
|
$accessArns = $accessArns | Where-Object { $false -eq [string]::IsNullOrWhitespace($_) }
|
|
|
|
# Create the resource policy on the secret in AWS.
|
|
Write-AlkamiSecretResourcePolicy -SecretName $secretName -ProfileName $ProfileName -Region $Region -SecretAccessExtraArns $accessArns
|
|
|
|
# Enable rotation on the secret (if the operator didn't turn off that feature).
|
|
if ( $false -eq [string]::IsNullOrWhitespace( $RotationSchedule )) {
|
|
|
|
$rotationLambdaArn = Get-YeatsRotationLambdaArn -EnvironmentTag $environmentTagValue -ProfileName $ProfileName -Region $Region
|
|
if ( $null -ne $rotationLambdaArn ) {
|
|
|
|
# Note that we disable immediate rotation of the secret because we just created the accounts -- the passwords
|
|
# do not require rotation at this time.
|
|
Invoke-SECSecretRotation -SecretId $result.SecretArns[0] -RotateImmediately $false -RotationLambdaArn $rotationLambdaArn `
|
|
-RotationRules_ScheduleExpression $RotationSchedule -RotationRules_Duration $RotationWindow `
|
|
-ProfileName $ProfileName -Region $Region
|
|
}
|
|
}
|
|
|
|
} catch {
|
|
|
|
Write-Warning "$logLead : Configuration of AWS secret failed. Error encountered was: [$PSItem]"
|
|
}
|
|
|
|
return $result
|
|
}
|