Can somene help me how to give the specific service principal name for azure custom policy in terraform code - azure-devops

The Scenario is:We need to create resources in azure portal through terraform cloud only by using service principals and azure portal shouldn't allow creation of resources by other means.
(No manual creation in azure portal,and also by SVM's tools like vs code)
The following code which i tried:
resource "azurerm_policy_definition" "policych" {
name = "PolicyTestSP"
policy_type = "Custom"
mode = "Indexed"
display_name = "Allow thru SP"
metadata = <<METADATA
{
"category": "General"
}
METADATA
policy_rule = <<POLICY_RULE
{
"if": {
"not": {
"field": "type",
"equals": "https://app.terraform.io/"
}
},
"then": {
"effect": "deny"
}
}
POLICY_RULE
}
resource "azurerm_policy_assignment" "policych" {
name = "Required servive-principles"
display_name = "Allow thru SP"
description = " Require SP Authentication'"
policy_definition_id = "${azurerm_policy_definition.policych.id}"
scope = "/subscriptions/xxxx-xxxx-xxxx-xxxx"
}

Related

CannotPullContainerError: failed to extract layer

I'm trying to run a task on a windows container in fargate mode on aws
The container is a .net console application (Fullframework 4.5)
This is the task definition generated programmatically by SDK
var taskResponse = await ecsClient.RegisterTaskDefinitionAsync(new Amazon.ECS.Model.RegisterTaskDefinitionRequest()
{
RequiresCompatibilities = new List<string>() { "FARGATE" },
TaskRoleArn = TASK_ROLE_ARN,
ExecutionRoleArn = EXECUTION_ROLE_ARN,
Cpu = CONTAINER_CPU.ToString(),
Memory = CONTAINER_MEMORY.ToString(),
NetworkMode = NetworkMode.Awsvpc,
Family = "netfullframework45consoleapp-task-definition",
EphemeralStorage = new EphemeralStorage() { SizeInGiB = EPHEMERAL_STORAGE_SIZE_GIB },
ContainerDefinitions = new List<Amazon.ECS.Model.ContainerDefinition>()
{
new Amazon.ECS.Model.ContainerDefinition()
{
Name = "netfullframework45consoleapp-task-definition",
Image = "XXXXXXXXXX.dkr.ecr.eu-west-1.amazonaws.com/netfullframework45consoleapp:latest",
Cpu = CONTAINER_CPU,
Memory = CONTAINER_MEMORY,
Essential = true
//I REMOVED THE LOG DEFINITION TO SIMPLIFY THE PROBLEM
//,
//LogConfiguration = new Amazon.ECS.Model.LogConfiguration()
//{
// LogDriver = LogDriver.Awslogs,
// Options = new Dictionary<string, string>()
// {
// { "awslogs-create-group", "true"},
// { "awslogs-group", $"/ecs/{TASK_DEFINITION_NAME}" },
// { "awslogs-region", AWS_REGION },
// { "awslogs-stream-prefix", $"{TASK_DEFINITION_NAME}" }
// }
//}
}
}
});
these are the role policies contained used by the task AmazonECSTaskExecutionRolePolicy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
i got this error when lunch the task
CannotPullContainerError: ref pull has been retried 1 time(s): failed to extract layer sha256:fe48cee89971abac42eedb9110b61867659df00fc5b0b90dd91d6e19f704d935: link /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/212/fs/Files/ProgramData/Microsoft/Event Viewer/Views/ServerRoles/RemoteDesktop.Events.xml /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/212/fs/Files/Windows/Microsoft.NET/assembly/GAC_64/Microsoft.Windows.ServerManager.RDSPlugin/v4.0_10.0.0.0__31bf3856ad364e35/RemoteDesktop.Events.xml: no such file or directory: unknown
some search drived me here:
https://aws.amazon.com/it/premiumsupport/knowledge-center/ecs-pull-container-api-error-ecr/
the point 1 says that if i run the task on the private subnet (like i'm doing) i need a NAT with related route to garantee the communication towards the ECR, but
note that in my infrastructure i've a VPC Endpoint to the ECR....
so the first question is: is a VPC Endpoint sufficent to garantee the comunication from the container to the container images registry(ECR)? or i need necessarily to implement what the point 1 say (NAT and route on the route table) or eventually run the task on a public subnet?
Can be the error related to the missing communication towards the ECR, or could be a missing policy problem?
Make sure your VPC endpoint is configured correctly. Note that
"Amazon ECS tasks hosted on Fargate using platform version 1.4.0 or later require both the com.amazonaws.region.ecr.dkr and com.amazonaws.region.ecr.api Amazon ECR VPC endpoints as well as the Amazon S3 gateway endpoint to take advantage of this feature."
See https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html for more information
In the first paragraph of the page I linked: "You don't need an internet gateway, a NAT device, or a virtual private gateway."

Terraform Error creating Topic: googleapi: Error 403: User not authorized to perform this action

Googleapi: Error 403: User not authorized to perform this action
provider "google" {
project = "xxxxxx"
region = "us-central1"
}
resource "google_pubsub_topic" "gke_cluster_upgrade_notifications" {
name = "cluster-notifications"
labels = {
foo = "bar"
}
message_storage_policy {
allowed_persistence_regions = [
"region",
]
}
}
# create the storage bucket for our scripts
resource "google_storage_bucket" "source_code" {
name = "xxxxxx-bucket-lh05111992"
location = "us-central1"
force_destroy = true
}
# zip up function source code
data "archive_file" "function_script_zip" {
type = "zip"
source_dir = "./function/"
output_path = "./function/main.py.zip"
}
# add function source code to storage
resource "google_storage_bucket_object" "function_script_zip" {
name = "main.py.zip"
bucket = google_storage_bucket.source_code.name
source = "./function/main.py.zip"
}
resource "google_cloudfunctions_function" "gke_cluster_upgrade_notifications" {---
-------
}
The service account has the owner role attached
Also tried using
1.export GOOGLE_APPLICATION_CREDENTIALS={{path}}
2.credentials = "${file("credentials.json")}" by place json file in terraform root folder.
It seems that the used account is missing some permissions (e.g. pubsub.topics.create) to create the Cloud Pub/Sub topic. The owner role should be sufficient to create the topic, as it contains the necessary permissions (you can check this here). Therefore, a wrong service account might be set in Terraform.
To address these IAM issues I would suggest:
Use the Policy Troubleshooter.
Impersonate service account and do the API call using CLI with --verbosity=debug flag, which will provide helpful information about the missing permissions.

How to provision RDS postgres db users with AWS IAM auth using terraform?

By checking this AWS blog: https://aws.amazon.com/premiumsupport/knowledge-center/users-connect-rds-iam/ I noticed that I need to create a DB user after login with the master username and password:
CREATE USER {dbusername} IDENTIFIED WITH AWSAuthenticationPlugin as 'RDS';
I can see terraform has mysql_user to provision mysql db users: https://www.terraform.io/docs/providers/mysql/r/user.html
However, I couldn't find postgres_user. Is there a way to provision postgres user with IAM auth?
In Postgres, a user is called a "role". The Postgres docs say:
a role can be considered a "user", a "group", or both depending on how it is used
So, the TF resource to create is a postgresql_role
resource "postgresql_role" "my_replication_role" {
name = "replication_role"
replication = true
login = true
connection_limit = 5
password = "md5c98cbfeb6a347a47eb8e96cfb4c4b890"
}
To enable IAM user to assume the role, follow the steps in the AWS docs.
From those instructions, you would end up with TF code looking something like:
module "db" {
source = "terraform-aws-modules/rds/aws"
// ...
}
provider "postgresql" {
// ...
}
resource "postgresql_role" "pguser" {
login = true
name = var.pg_username
password = var.pg_password
roles = ["rds_iam"]
}
resource "aws_iam_user" "pguser" {
name = var.pg_username
}
resource "aws_iam_user_policy" "pguser" {
name = var.pg_username
user = aws_iam_user.pguser.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds-db:connect"
],
"Resource": [
"arn:aws:rds-db:${var.region}:${data.aws_caller_identity.current.account_id}:dbuser:${module.db.this_db_instance_resource_id}/${var.pg_username}"
]
}
]
}
EOF
}

How to set aws cloudwatch retention via Terraform

Using Terraform to deploy API Gateway/Lambda and already have the appropriate logs in Cloudwatch. However I can't seem to find a way to set the retention on the logs via Terraform, using my currently deployed resources (below). It looks like the log group resource is where I'd do it, but not sure how to point log stream from api gateway at the new log group. I must be missing something obvious ... any advice is very much appreciated!
resource "aws_api_gateway_account" "name" {
cloudwatch_role_arn = "${aws_iam_role.cloudwatch.arn}"
}
resource "aws_iam_role" "cloudwatch" {
name = "#{name}_APIGatewayCloudWatchLogs"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_policy_attachment" "api_gateway_logs" {
name = "#{name}_api_gateway_logs_policy_attach"
roles = ["${aws_iam_role.cloudwatch.id}"]
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs"
}
resource "aws_api_gateway_method_settings" "name" {
rest_api_id = "${aws_api_gateway_rest_api.name.id}"
stage_name = "${aws_api_gateway_stage.name.stage_name}"
method_path = "${aws_api_gateway_resource.name.path_part}/${aws_api_gateway_method.name.http_method}"
settings {
metrics_enabled = true
logging_level = "INFO"
data_trace_enabled = true
}
}
yes, you can use the Lambda log name to create log resource before you create the Lambda function. Or you can import the existing log groups.
resource "aws_cloudwatch_log_group" "lambda" {
name = "/aws/lambda/${var.env}-${join("", split("_",title(var.lambda_name)))}-Lambda"
retention_in_days = 7
lifecycle {
create_before_destroy = true
prevent_destroy = false
}
}

How to configure the APNS.Certificate in the arm template

I am using the following azuredeploy.json file for setting up the notification hub on the Azure cloud.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"Gcm.GoogleApiKey": {
"type": "string",
"metadata": {
"description": "Google Cloud Messaging API Key"
},
"defaultValue": "AIzaSyAyp9MernKgMS3wFNM3yNWByiP-TaGrqEg"
},
"APNS.Certificate": {
"type": "string",
"metadata": {
"description": "A certificate (in base 64 format) provided by Apple on the iOS Provisioning Portal"
},
"defaultValue": ""
},
"APNS.certificateKey": {
"type": "string",
"metadata": {
"description": "The Certificate Key provided by the iOS Provisioning Portal when registering the application"
},
"defaultValue": "ce469bf21dfa7b9d595d4999bfaca8a94ea47e46"
},
"APNS.endpoint": {
"type": "string",
"metadata": {
"description": "The APNS endpoint to which our service connects. This is one of two values: gateway.sandbox.push.apple.com for the sandbox endpoint or gateway.push.apple.com, for the production endpoint. Any other value is invalid."
},
"allowedValues": [
"gateway.sandbox.push.apple.com",
"gateway.push.apple.com"
],
"defaultValue": "gateway.push.apple.com"
}
},
"variables": {
"hubVersion": "[providers('Microsoft.NotificationHubs', 'namespaces').apiVersions[0]]",
"notificationHubNamespace": "[concat('hubv2', uniqueString(resourceGroup().id))]",
"notificationHubName": "notificationhub"
},
"resources": [
{
"name": "[variables('NotificationHubNamespace')]",
"location": "[resourceGroup().location]",
"type": "Microsoft.NotificationHubs/namespaces",
"apiVersion": "[variables('hubVersion')]",
"comments": "Notification hub namespace",
"properties": {
"namespaceType": "NotificationHub"
},
"resources": [
{
"name": "[concat(variables('NotificationHubNamespace'),'/',variables('NotificationHubName'))]",
"location": "[resourceGroup().location]",
"type": "Microsoft.NotificationHubs/namespaces/notificationHubs",
"apiVersion": "[variables('hubVersion')]",
"properties": {
"GcmCredential": {
"properties": {
"googleApiKey": "[parameters('Gcm.GoogleApiKey')]",
"gcmEndpoint": "https://android.googleapis.com/gcm/send"
}
}
},
"dependsOn": [
"[variables('NotificationHubNamespace')]"
]
}
]
}
],
"outputs": {
}
}
Now I tried to set up the apple push notification service also using the following snippet:
"apnsCredential": {
"properties": {
"apnsCertificate": "[parameters('APNS.Certificate')]",
"certificateKey": "[parameters('APNS.certificateKey')]",
"endpoint": " gateway.sandbox.push.apple.com or gateway.push.apple.com",
}
}
With the above changes, I executed the Deploy-AzureResourceGroup.ps1 using powershell command prompt and on executing it I am getting an error with message 'Bad Request'
Can anyone help me to fix this issue.
Add the proper APNS.Certificate and APNS.certificateKey.
It is failing on trying to verify your details, hence the bad request.
You need a base 64 formatted APNS.Certificate.
APNS.Certificate:
This is the Apple Push Notification certificate in base 64 string-format.
You can use PowerShell to convert the certificate like this (then copie the key from the output file ‘MyPushCert.txt’ and use it.):
$fileContentBytes = get-content ‘Apple_Certificate.p12’ -Encoding Byte
[System.Convert]::ToBase64String($fileContentBytes) | Out-File ‘MyPushCert.txt’
APNS.certificateKey:
This is the password you specified when you exported the certificate.(The password you created on Apple at the time of creating the cert.)
It's impossible to know exactly what caused this without knowing more about your environment/setup. According to this post, one possible issue could be how strong your password is:
After a few hours of pulling my hair out and not getting anything
beyond “Bad Request”, I finally thought to use a password stronger
than “pass#word1”. I’ll be darned, it worked. Not only that, but
provisioning with Azure Resource Manager is asynchronous, so your
scripts finish a heck of a lot sooner than they used to because VMs
provision in parallel.
The post recommends going through Troubleshooting common Azure deployment errors with Azure Resource Manager.
I'm not sure you should be dynamically setting the apiVersion for your templates. They vary depending on what you are deploying.
See Best Practices:
Avoid using a parameter or variable for the API version for a resource type. Resource properties and values can vary by version number. IntelliSense in a code editor cannot determine the correct schema when the API version is set to a parameter or variable. Instead, hard-code the API version in the template.
The correct apiVersion for notification hubs appears to be 2015-04-01: https://github.com/Azure/azure-resource-manager-schemas/blob/master/schemas/2015-04-01/Microsoft.NotificationHubs.json
I had to use PowerShell to resolve this problem.
Partially the idea was taken from here: https://learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-deploy-and-manage-powershell
Below is the script, which tested locally and is working.
Microsoft.Azure.NotificationHubs -Version 1.0.9 used.
We adopted it for VSTS Release as one of the PowerShell tasks/steps after Notification Hub has been created with ARM template.
Login-AzureRmAccount
Select-AzureRmSubscription -SubscriptionName my-subscription-here
Write-Host "Begin process..."
try
{
# Make sure to reference the latest version of Microsoft.Azure.NotificationHubs.dll
Write-Host "Adding the [Microsoft.Azure.NotificationHubs.dll] assembly to the script...";
$scriptPath = Split-Path (Get-Variable MyInvocation -Scope 0).Value.MyCommand.Path;
$packagesFolder = $scriptPath + "\packs";
Write-Host $packagesFolder;
$assembly = Get-ChildItem $packagesFolder -Include "Microsoft.Azure.NotificationHubs.dll" -Recurse;
write-Host $assembly.FullName;
Add-Type -Path $assembly.FullName;
Write-Host "The [Microsoft.Azure.NotificationHubs.dll] assembly has been successfully added to the script.";
# Create requered variables
$HubNamespace = "hub-namespace";
$HubName = "hub-name";
$ResourceGroup = "resource-group";
$GcmApiKey = "api key here";
# Possible values: gateway.push.apple.com, gateway.sandbox.push.apple.com
$ApnsEndpoint = "gateway.push.apple.com";
# A certificate (in base 64 format) provided by Apple on the iOS Provisioning Portal
$ApnsCertificate = "base 64 certificate here";
$ApnsCertificateKey = "certificate key/password here";
$GcmCredential = New-Object -TypeName Microsoft.Azure.NotificationHubs.GcmCredential -ArgumentList $GcmApiKey;
$ApnsCredential = New-Object -TypeName Microsoft.Azure.NotificationHubs.ApnsCredential;
$ApnsCredential.Endpoint = $ApnsEndpoint;
$ApnsCredential.ApnsCertificate = $ApnsCertificate;
$ApnsCredential.CertificateKey = $ApnsCertificateKey;
# Query the namespace
$FoundNamespaces = Get-AzureRmNotificationHubsNamespace -Namespace $HubNamespace -ResourceGroup $ResourceGroup
# Check if the namespace already exists
if ($FoundNamespaces -and $FoundNamespaces.Length -eq 1)
{
$CurrentNamespace = $FoundNamespaces[0];
Write-Host "The namespace [$HubNamespace] in the [$($CurrentNamespace.Location)] region was found.";
$HubListKeys = Get-AzureRmNotificationHubListKeys -Namespace $HubNamespace -ResourceGroup $ResourceGroup -NotificationHub $HubName -AuthorizationRule DefaultFullSharedAccessSignature;
# Check to see if the Notification Hub exists
if ($HubListKeys)
{
# Create the NamespaceManager object used to update the notification hub
Write-Host "Creating a NamespaceManager object for the [$HubNamespace] namespace...";
$NamespaceManager = [Microsoft.Azure.NotificationHubs.NamespaceManager]::CreateFromConnectionString($HubListKeys.PrimaryConnectionString);
Write-Host "NamespaceManager object for the [$HubNamespace] namespace has been successfully created.";
# Update notification hub with new details
Write-Host "The [$Path] notification hub already exists in the [$HubNamespace] namespace." ;
$NHDescription = $NamespaceManager.GetNotificationHub($HubName);
$NHDescription.GcmCredential = $GcmCredential;
$NHDescription.ApnsCredential = $ApnsCredential;
$NHDescription = $NamespaceManager.UpdateNotificationHub($NHDescription);
Write-Host "The [$HubName] notification hub was updated";
}
else
{
Write-Host "The [$HubName] notification hub does not exist."
}
}
else
{
Write-Host "The [$HubNamespace] namespace does not exist."
}
}
catch [System.Exception]
{
Write-Error($_.Exception.Message)
}
Hope that helps someone.