This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Installing Protegrity Provisioned Cluster

Steps to install PPC on AWS and Azure

The Protegrity Provisioned Cluster (PPC) is the core framework that forms Protegrity AI Team Edition, designed to deliver a modern, cloud-native experience for data security and governance. Built on Kubernetes, PPC uses a containerized architecture that simplifies deployment and scaling. Using OpenTofu scripts and Helm charts, administrators can stand up clusters with minimal manual intervention, ensuring consistency and reducing operational overhead.

PPC introduces a suite of Protegrity Common Services (PCS) that act as the backbone for AI Team Edition features. These include ingress control for secure traffic routing, certificate management for request validation, and robust authentication and authorization services. PPC also integrates Insight for audit logging and analytics, leveraging OpenSearch and OpenDashboards for visualization and compliance reporting. Beyond this foundation, AI Team Edition delivers advanced capabilities such as policy management, anonymization, data discovery, semantic guardrails, and synthetic data generation — all orchestrated within the PPC cluster. This modular approach ensures scalability, security, and flexibility, making PPC a strategic enabler for organizations adopting cloud-first and containerized environments.

Note: It is recommended to install and use AI Team Edition on AWS to test and use all the features. Install and use on Azure to use the fixed set of protectors supported on Azure.

The documentation in this section is for PPC v1.1.0. To refer to the earlier version of the documentation, refer to the PPC documentation.

1 - Installing PPC on Amazon Web Services (AWS)

Steps to install PPC on AWS

The Protegrity Provisioned Cluster PPC is the core framework that forms the AI Team Edition. It is designed to deliver a modern, cloud-native experience for data security and governance. Built on Kubernetes, PPC uses a containerized architecture that simplifies deployment and scaling. Using OpenTofu scripts and Helm charts, administrators can create clusters with minimal manual intervention, ensuring consistency and reducing operational overhead.

1.1 - Prerequisites

Ensure that the following prerequisites are met before deploying the PPC.

Updating the Roles and Permissions using JSON

The roles and permissions are updated using the JSONs.

From the AWS Console, navigate to IAM > Policies > Create policy > JSON, and create the following JSONs.

Note: Before using the provided JSON, replace the AWS_ACCOUNT_ID and REGION values with those of the account and region where the resources are being deployed.

  1. Creating KMS key and S3 bucket.
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "ReadOnlyAccess",
			"Effect": "Allow",
			"Action": [
				"eks:DescribeClusterVersions",
				"ec2:DescribeInstances",
				"ec2:DescribeVolumes",
				"s3:ListAllMyBuckets",
				"iam:ListUsers",
				"ec2:RunInstances",
				"ec2:DescribeInstances",
				"ec2:DescribeVolumes",
				"ec2:CreateKeyPair",
				"ec2:DescribeImages"
			],
			"Resource": "*"
		},
		{
			"Sid": "ScopedS3AndKMS",
			"Effect": "Allow",
			"Action": [
				"s3:ListBucket",
				"s3:PutEncryptionConfiguration",
				"s3:GetEncryptionConfiguration",
				"kms:CreateKey",
				"kms:PutKeyPolicy",
				"kms:GetKeyPolicy"
			],
			"Resource": [
				"arn:aws:s3:::*",
				"arn:aws:kms:*:<AWS_ACCOUNT_ID>:key/*"
			]
		},
		{
			"Sid": "SelfServiceIAM",
			"Effect": "Allow",
			"Action": [
				"iam:ListSSHPublicKeys",
				"iam:ListServiceSpecificCredentials",
				"iam:GetLoginProfile",
				"iam:ListAccessKeys",
				"iam:CreateAccessKey"
			],
			"Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:user/${aws:username}"
		},
        {
			"Sid": "EC2KeyPairPermission",
			"Effect": "Allow",
			"Action": [
				"ec2:CreateKeyPair",
				"ec2:DescribeKeyPairs"
			],
			"Resource": [
				"*"
			]
		}
	]
}
  1. Creating EC2 Service Policy.
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "DenyEC2Instances",
			"Effect": "Deny",
			"Action": "ec2:RunInstances",
			"Resource": "arn:aws:ec2:*:*:instance/*",
			"Condition": {
				"StringLike": {
					"ec2:InstanceType": [
						"p*",
						"g*",
						"inf*",
						"trn*",
						"x*",
						"u-*",
						"z*",
						"mac*"
					]
				}
			}
		},
		{
			"Sid": "ReadOnlyDescribeListEC2RegionRestricted",
			"Effect": "Allow",
			"Action": [
				"ec2:DescribeVpcs",
				"ec2:DescribeSubnets",
				"ec2:DescribeVpcAttribute",
				"ec2:DescribeTags",
				"ec2:DescribeSecurityGroups",
				"ec2:DescribeSecurityGroupRules",
				"ec2:DescribeLaunchTemplates",
				"ec2:DescribeLaunchTemplateVersions",
				"ec2:DescribeNetworkInterfaces",
				"ec2:DescribeAccountAttributes"
			],
			"Resource": "*",
			"Condition": {
				"StringEquals": {
					"aws:RequestedRegion": [
						"<REGION>"
					]
				}
			}
		},
		{
			"Sid": "EC2LifecycleAndSecurity",
			"Effect": "Allow",
			"Action": [
				"ec2:CreateSecurityGroup",
				"ec2:DeleteSecurityGroup",
				"ec2:AuthorizeSecurityGroupIngress",
				"ec2:AuthorizeSecurityGroupEgress",
				"ec2:RevokeSecurityGroupIngress",
				"ec2:RevokeSecurityGroupEgress",
				"ec2:CreateLaunchTemplate",
				"ec2:DeleteLaunchTemplate",
				"ec2:CreateTags",
				"ec2:DeleteTags"
			],
			"Resource": [
				"arn:aws:ec2:*:*:security-group/*",
				"arn:aws:ec2:*:*:launch-template/*",
				"arn:aws:ec2:*:*:instance/*",
				"arn:aws:ec2:*:*:network-interface/*",
				"arn:aws:ec2:*:*:subnet/*",
				"arn:aws:ec2:*:*:vpc/*",
				"arn:aws:ec2:*:*:image/*",
				"arn:aws:ec2:*:*:volume/*",
				"arn:aws:ec2:*:*:snapshot/*"
			]
		}
	]
}
  1. Creating EKS Service Policy.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ReadOnlyDescribeListEKSVersionsRegionRestricted",
            "Effect": "Allow",
            "Action": [
                "eks:DescribeAddonVersions"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:RequestedRegion": [
                        "<REGION>"
                    ]
                }
            }
        },
        {
            "Sid": "ReadOnlyDescribeListEKS",
            "Effect": "Allow",
            "Action": [
                "eks:DescribeCluster",
                "eks:DescribeAddon",
                "eks:DescribePodIdentityAssociation",
                "eks:DescribeNodegroup",
                "eks:ListAddons",
                "eks:ListPodIdentityAssociations"
            ],
            "Resource": [
                "arn:aws:eks:*:<AWS_ACCOUNT_ID>:cluster/*",
                "arn:aws:eks:*:<AWS_ACCOUNT_ID>:nodegroup/*",
                "arn:aws:eks:*:<AWS_ACCOUNT_ID>:addon/*",
                "arn:aws:eks:*:<AWS_ACCOUNT_ID>:podidentityassociation/*"
            ]
        },
        {
            "Sid": "EKSLifecycleAndTag",
            "Effect": "Allow",
            "Action": [
                "eks:CreateCluster",
                "eks:UpdateClusterVersion",
                "eks:UpdateClusterConfig",
                "eks:CreateNodegroup",
                "eks:UpdateNodegroupConfig",
                "eks:UpdateNodegroupVersion",
                "eks:DeleteNodegroup",
                "eks:CreateAddon",
                "eks:UpdateAddon",
                "eks:DeleteAddon",
                "eks:CreatePodIdentityAssociation",
                "eks:DeletePodIdentityAssociation",
                "eks:TagResource",
                "eks:ListClusters"
            ],
            "Resource": [
                "arn:aws:eks:*:<AWS_ACCOUNT_ID>:cluster/*",
                "arn:aws:eks:*:<AWS_ACCOUNT_ID>:nodegroup/*",
                "arn:aws:eks:*:<AWS_ACCOUNT_ID>:addon/*",
                "arn:aws:eks:*:<AWS_ACCOUNT_ID>:podidentityassociation/*"
            ]
        },
        {
            "Sid": "AllowEKSNodegroupSLR",
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "iam:CreateServiceLinkedRole"
            ],
            "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup"
        },
        {
            "Sid": "EKSDeleteClusterV6",
            "Effect": "Allow",
            "Action": "eks:DeleteCluster",
            "Resource": "arn:aws:eks:*:<AWS_ACCOUNT_ID>:cluster/*"
        }
    ]
}
  1. Creating IAM Service Policy.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyAdminPolicyAttachment",
            "Effect": "Deny",
            "Action": [
                "iam:AttachRolePolicy",
                "iam:PutRolePolicy"
            ],
            "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*",
            "Condition": {
                "ArnLike": {
                    "iam:PolicyARN": [
                        "arn:aws:iam::aws:policy/AdministratorAccess",
                        "arn:aws:iam::aws:policy/PowerUserAccess",
                        "arn:aws:iam::aws:policy/*FullAccess"
                    ]
                }
            }
        },
        {
            "Sid": "DenyInlinePolicyEscalation",
            "Effect": "Deny",
            "Action": [
                "iam:PutRolePolicy",
                "iam:PutUserPolicy",
                "iam:PutGroupPolicy"
            ],
            "Resource": "*"
        },
        {
            "Sid": "ReadOnlyDescribeListIAMScoped",
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "iam:ListRolePolicies",
                "iam:ListAttachedRolePolicies",
                "iam:ListInstanceProfilesForRole",
                "iam:GetInstanceProfile",
                "iam:GetPolicy",
                "iam:GetPolicyVersion",
                "iam:ListPolicyVersions",
                "iam:ListAccessKeys"
            ],
            "Resource": [
                "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*",
                "arn:aws:iam::<AWS_ACCOUNT_ID>:instance-profile/eks-*",
                "arn:aws:iam::<AWS_ACCOUNT_ID>:policy/eks-*"
            ]
        },
        {
            "Sid": "ReadOnlyDescribeListUnavoidableStar",
            "Effect": "Allow",
            "Action": "iam:ListRoles",
            "Resource": "*"
        },
        {
            "Sid": "IAMLifecycleRolesPoliciesInstanceProfiles",
            "Effect": "Allow",
            "Action": [
                "iam:CreateRole",
                "iam:TagRole",
                "iam:CreatePolicy",
                "iam:DeletePolicy",
                "iam:DeletePolicyVersion",
                "iam:TagPolicy",
                "iam:AttachRolePolicy",
                "iam:DetachRolePolicy",
                "iam:CreateInstanceProfile",
                "iam:TagInstanceProfile",
                "iam:AddRoleToInstanceProfile",
                "iam:RemoveRoleFromInstanceProfile",
                "iam:DeleteInstanceProfile"
            ],
            "Resource": [
                "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*",
                "arn:aws:iam::<AWS_ACCOUNT_ID>:policy/eks-*",
                "arn:aws:iam::<AWS_ACCOUNT_ID>:instance-profile/eks-*"
            ]
        },
        {
            "Sid": "EKSDeleteRoles",
            "Effect": "Allow",
            "Action": "iam:DeleteRole",
            "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks*"
        },
        {
            "Sid": "PassRoleOnlyToEKS",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*",
            "Condition": {
                "StringEquals": {
                    "iam:PassedToService": [
                        "eks.amazonaws.com",
                        "ec2.amazonaws.com",
                        "eks-pods.amazonaws.com",
                        "pods.eks.amazonaws.com"
                    ]
                }
            }
        },
        {
            "Sid": "PassRoleForEKSPodIdentityRoles",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": [
                "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*-karpenter-role",
                "arn:aws:iam::<AWS_ACCOUNT_ID>:role/eks-*-backup-recovery-utility-role"
            ]
        }
    ]
}
  1. Creating KMS Service Policy.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "KMSCreateAndList",
            "Effect": "Allow",
            "Action": [
                "kms:CreateKey",
                "kms:ListAliases"
            ],
            "Resource": "*"
        },
        {
            "Sid": "KMSKeyManagementScoped",
            "Effect": "Allow",
            "Action": [
                "kms:PutKeyPolicy",
                "kms:GetKeyPolicy",
                "kms:DescribeKey",
                "kms:GenerateDataKey",
                "kms:Decrypt",
                "kms:TagResource",
                "kms:UntagResource",
                "kms:EnableKeyRotation",
                "kms:GetKeyRotationStatus",
                "kms:ListResourceTags",
                "kms:ScheduleKeyDeletion",
                "kms:CreateAlias",
                "kms:DeleteAlias"
            ],
            "Resource": [
                "arn:aws:kms:*:<AWS_ACCOUNT_ID>:key/*",
                "arn:aws:kms:*:<AWS_ACCOUNT_ID>:alias/*"
            ]
        }
    ]
}
  1. Creating AWS S3 Service Policy.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3EncryptionConfigAndStateScoped",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetEncryptionConfiguration",
                "s3:PutEncryptionConfiguration",
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:CreateBucket",
                "s3:GetBucketTagging",
                "s3:GetBucketPolicy",
                "s3:GetBucketAcl",
                "s3:GetBucketCORS",
                "s3:PutBucketTagging",
                "s3:GetBucketWebsite",
                "s3:GetBucketVersioning",
                "s3:GetAccelerateConfiguration",
                "s3:GetBucketRequestPayment",
                "s3:GetBucketLogging",
                "s3:GetLifecycleConfiguration",
                "s3:GetReplicationConfiguration",
                "s3:GetBucketObjectLockConfiguration",
                "s3:DeleteBucket",
                "s3:PutBucketVersioning",
                "s3:ListBucketVersions",
                "s3:DeleteObjectVersion",
                "s3:GetObjectTagging"
            ],
            "Resource": "arn:aws:s3:::*",
            "Condition": {
                "StringEquals": {
                    "aws:RequestedRegion": [
                        "<REGION>"
                    ],
                    "aws:PrincipalAccount": "<AWS_ACCOUNT_ID>"
                }
            }
        }
    ]
}
 
 

Description for the JSON components

This section provides information for the permissions mentioned in the JSON file.

IAM Roles

Contact the IT team to create the necessary IAM roles with the following permissions to create and manage AWS EKS resources.

IAM RoleRequired Policies
Amazon EKS cluster IAM Role
Manages the Kubernetes cluster.
- AmazonEKSBlockStoragePolicy
- AmazonEKSClusterPolicy
- AmazonEKSComputePolicy
- AmazonEKSLoadBalancingPolicy
- AmazonEKSNetworkingPolicy
- AmazonEKSVPCResourceController
- AmazonEKSServicePolicy
- AmazonEBSCSIDriverPolicy
Amazon EKS node IAM Role
Communicates with the node.
- AmazonEBSCSIDriverPolicy
- AmazonEC2ContainerRegistryReadOnly
- AmazonEKS_CNI_Policy
- AmazonEKSWorkerNodePolicy
- AmazonSSMManagedInstanceCore

These policies are managed by AWS. For more information about AWS managed policies, refer to AWS managed policies for Amazon Elastic Kubernetes Service in the AWS documentation.

AWS IAM Permissions

The AWS IAM user or role to install PPC must have permissions to create and manage Amazon EKS clusters and the required supporting AWS resources.

EC2 Permissions

CategoryRequired Permissions
Networking & VPCec2:DescribeVpcs
ec2:DescribeSubnets
ec2:DescribeVpcAttribute
ec2:DescribeTags
ec2:DescribeNetworkInterfaces
Security Groupsec2:DescribeSecurityGroups
ec2:DescribeSecurityGroupRules
ec2:CreateSecurityGroup
ec2:DeleteSecurityGroup
ec2:AuthorizeSecurityGroupIngress
ec2:AuthorizeSecurityGroupEgress
ec2:RevokeSecurityGroupIngress
ec2:RevokeSecurityGroupEgress
Launch Templatesec2:DescribeLaunchTemplates
ec2:DescribeLaunchTemplateVersions
ec2:CreateLaunchTemplate
ec2:DeleteLaunchTemplate
Instancesec2:RunInstances
Taggingec2:CreateTags
ec2:DeleteTags

EKS Permissions

CategoryRequired Permissions
Cluster Managementeks:CreateCluster
eks:DescribeCluster
Node Groupseks:CreateNodegroup
eks:DescribeNodegroup
Add-onseks:CreateAddon
eks:DescribeAddon
eks:DescribeAddonVersions
eks:DeleteAddon
eks:ListAddons
Pod Identity Associationseks:CreatePodIdentityAssociation
eks:DescribePodIdentityAssociation
eks:DeletePodIdentityAssociation
eks:ListPodIdentityAssociations
Taggingeks:TagResource

IAM Permissions

CategoryRequired Permissions
Roles & Policiesiam:CreateRole
iam:DeleteRole
iam:TagRole
iam:GetRole
iam:ListRoles
iam:AttachRolePolicy
iam:DetachRolePolicy
iam:ListRolePolicies
iam:ListAttachedRolePolicies
Policiesiam:CreatePolicy
iam:DeletePolicy
iam:TagPolicy
iam:GetPolicy
iam:GetPolicyVersion
iam:ListPolicyVersions
Instance Profilesiam:CreateInstanceProfile
iam:DeleteInstanceProfile
iam:TagInstanceProfile
iam:GetInstanceProfile
iam:AddRoleToInstanceProfile
iam:RemoveRoleFromInstanceProfile
iam:ListInstanceProfilesForRole
Service-linked Roleiam:CreateServiceLinkedRole

AWS S3 Permissions

Required Permissions
s3:ListBucket
s3:PutEncryptionConfiguration
s3:GetEncryptionConfiguration

KMS Permissions

Required Permissions
kms:CreateKey
kms:PutKeyPolicy
kms:GetKeyPolicy

Jump box or local machine

  • A newly provisioned EC2 instance must be used as the jump box for PPC deployment.

  • The jump box must be provisioned in the same AWS region where the PPC cluster will be deployed to ensure proper connectivity and access to regional resources.

  • Supported operating systems: RHEL 10, Debian 13, or Debian 12.

Note: Ensure to retain the original jump box used for installation. The Terraform state files required for cleaning and upgrading the cluster are available on this jump box. A snapshot of the jump box must be maintained to prevent data loss.

AWS Account Details

  • A valid AWS account where Amazon EKS is deployed.

  • The AWS account ID and AWS region must be identified in advance, as all resources are provisioned in the selected region.

Service Quotas

Verify that the AWS account has sufficient service quotas to support the deployment. At a minimum, ensure adequate limits for the following:

  • EC2 instances based on node group size and instance types.
  • VPC and networking limits, including subnets, route tables, and security groups.
  • Elastic IP addresses and Load balancers.

If required, request quota increases through the AWS Service Quotas console before proceeding.

Service Control Policies (SCPs)

The AWS account must not have SCPs that restrict required permissions. In particular, SCPs must not block the following actions:

  • eks:*
  • ec2:*
  • iam:PassRole

Restrictive SCPs may prevent successful cluster creation and resource provisioning.

Virtual Private Cloud (VPC)

  • An existing VPC must be available in the target AWS region.
  • The VPC should be configured to support Amazon EKS workloads.

Subnet Requirements

  • At least two private subnets must be available.
  • Subnets must be distributed across two or more Availability Zones (AZs).

Creating AWS KMS Key and AWS S3 Bucket

Amazon S3 Bucket: An Amazon S3 bucket is required to store critical data such as backups, configuration artifacts, and restore metadata used during installation and recovery workflows. Using a dedicated AWS S3 bucket helps ensure data durability, isolation, and controlled access during cluster operations.

AWS KMS Key: An AWS KMS customer‑managed key is required to encrypt data stored in the AWS S3 bucket. This ensures that sensitive data is protected at rest and allows customers to manage encryption policies, key rotation, and access control in accordance with their security requirements.

Note: The KMS key must allow access to the IAM roles used by the EKS cluster and related services.

The following section explains how to create AWS KMS Key and AWS S3 Bucket. This can be done from the AWS Web UI or using the script.

  1. Create a KMS key for backup bucket.
    The KMS key created is referenced during installation and restore using its KMS ARN, and is validated by the installer.

Before you begin, ensure to have:

  • Access to the AWS account where the KMS key is created.

  • The KMS key can be in the same AWS account as the AWS S3 bucket, or in a different, cross‑account AWS account.

  • The user running the installer must have the permission kms:DescribeKey to describe the KMS key. If this permission is unavailable, then installation and restore fails.

The steps to create a KMS key are available at https://docs.aws.amazon.com/. Follow the KMS key creation steps, but ensure to select the following configurations.

  • On the Key configuration page:
    Select Key type as Symmetric.
    Select Key usage as Encrypt and decrypt.

    These settings are required for encrypting and decrypting AWS S3 objects used by backup and restore operations.

  • On the Key Administrative Permissions page, select the users or roles that can manage the key. The key administrators do not automatically get permission to encrypt or decrypt data, unless these permissions are explicitly granted.

  • On the Define key usage permissions page, grant permissions to the principals that will use the key.

    The user or role running the installation and restore must have the permission kms:DescribeKey to describe the key. This permission is mandatory because the installer validates the KMS key before proceeding. Without this, the installation or restore procedure fails, especially in cross‑account KMS scenarios.

  • On the Edit key policy - optional page, click Edit.

    The KMS key policy controls the access to the encryption key and must be applied before creating the AWS S3 bucket.

    If you are using AWS SSO IAM Identity Center, ensure that the IAM role ARN specified in the KMS key policy includes the full SSO path prefix: aws-reserved/sso.amazonaws.com/.
    For example: arn:aws:iam::<ACCOUNT_ID>:role/aws-reserved/sso.amazonaws.com/<SSO_ROLE_NAME>
    Omitting this path results in KMS key policy creation failures with an InvalidArnException.

The following example shows a key policy that:

  • Allows the PPC bootstrap user to use the KMS key for cluster creation and backup operations.

  • Allows the IAM role to encrypt and decrypt EKS backups.

cat > kms-key-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Id": "key-resource-policy-0",
  "Statement": [
    {
      "Sid": "Allow KMS administrative actions only, no key usage permissions.",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<<ADMIN_AWS_ACCOUNT>>:root"
      },
      "Action": [
        "kms:Create*",
        "kms:Describe*",
        "kms:Enable*",
        "kms:List*",
        "kms:Put*",
        "kms:Update*",
        "kms:Revoke*",
        "kms:Disable*",
        "kms:Get*",
        "kms:Delete*",
        "kms:ScheduleKeyDeletion",
        "kms:CancelKeyDeletion"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Allow user running bootstrap.sh script of the PPC to use the KMS key.",
      "Effect": "Allow",
      "Principal": {
        "AWS": "<<SSO_OR_IAM_USER_ACCOUNT_ARN>>"
      },
      "Action": [
        "kms:DescribeKey",
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncryptFrom",
        "kms:ReEncryptTo",
        "kms:GenerateDataKey",
        "kms:GenerateDataKeyWithoutPlaintext"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Allow backup recovery utility and EKS Node roles KMS key usage permissions, Replace <<<<CLUSTER_NAME>>>> with the name of your EKS cluster.",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<<DEPLOYMENT_AWS_ACCOUNT>>:root"
      },
      "Action": [
        "kms:Decrypt",
        "kms:Encrypt",
        "kms:ReEncryptFrom",
        "kms:ReEncryptTo",
        "kms:GenerateDataKey",
        "kms:GenerateDataKeyWithoutPlaintext",
        "kms:GenerateDataKeyPair",
        "kms:GenerateDataKeyPairWithoutPlaintext",
        "kms:DescribeKey"
      ],
      "Resource": "*",
      "Condition": {
        "ArnLike": {
          "aws:PrincipalArn": [
            "arn:aws:iam::<<DEPLOYMENT_AWS_ACCOUNT>>:role/eks-<<CLUSTER_NAME>>-backup-recovery-utility-role",
            "arn:aws:iam::<<DEPLOYMENT_AWS_ACCOUNT>>:role/eks-<<CLUSTER_NAME>>-node-role"
          ]
        }
      }
    }
  ]
}
EOF

Update the values of the following based on the environment:

  • DEPLOYMENT_AWS_ACCOUNT - AWS account ID.

  • CLUSTER_NAME - EKS cluster name.

  • SSO_OR_IAM_USER_ACCOUNT_ARN - ARN of the IAM role used to run the bootstrap script. The ARN format depends on your authentication method:

    • IAM role – Use the ARN returned by aws sts get-caller-identity.

    • AWS SSO (IAM Identity Center) – Convert the session ARN returned by aws sts get-caller-identity to a full IAM role ARN before using it in the KMS key policy.

      If you are using AWS SSO (IAM Identity Center), the ARN returned by aws sts get-caller-identity is a session ARN and cannot be used directly in an AWS KMS key policy. AWS KMS requires the full IAM role ARN, including the aws-reserved/sso.amazonaws.com/ path. Without this, KMS key policy creation fails with InvalidArnException.

Retrieving the IAM role ARN for KMS key policy

To identify the role used to run the bootstrap script, run the following command:

aws sts get-caller-identity --query Arn --output text
  • IAM role: Use the returned ARN directly.

    arn:aws:iam::<DEPLOYMENT_AWS_ACCOUNT>:role/your-role-name
    
  • AWS SSO (IAM Identity Center): The command returns a session ARN, which must be converted.

    Do not use the session ARN:

    arn:aws:sts::<<DEPLOYMENT_AWS_ACCOUNT>>:assumed-role/AWSReservedSSO_PermissionSetName_abc123/john.doe@company.com
    

    Use this converted IAM role ARN in KMS policy:

    arn:aws:iam::<<DEPLOYMENT_AWS_ACCOUNT>>:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_PermissionSetName_abc123
    

    To convert:

    • Replace arn:aws:sts:: with arn:aws:iam::.
    • Replace assumed-role/ with role/aws-reserved/sso.amazonaws.com/.
    • Remove the session suffix (everything after the last /).

Important: Before initiating restore operation, review and update the KMS key policy to reflect the restore CLUSTER_NAME. Even if the policy was already configured for the source cluster, it must be updated for the new restore cluster. If the policy continues to reference the source cluster name, the IAM role created during restore cannot decrypt the backup data, causing the restore to fail.

After the KMS key is created, note the KMS key ARN. This KMS key ARN is required while creating the AWS S3 backup bucket.

  1. Create an AWS S3 Bucket encrypted with SSE‑KMS
    The AWS S3 bucket encrypted with SSE‑KMS is used as a backup bucket during installation and restore.

Before you begin, ensure to have:

  • Access to the AWS account where the AWS S3 bucket will be created.

  • Permission to create AWS S3 bucket.

  • The user running the installer must have permission to describe the KMS key. Without this permission, installation and restore fails.

The steps to create an AWS S3 bucket are available at https://docs.aws.amazon.com/. Follow the AWS S3 bucket creation steps, but ensure to set the following configurations as mentioned below.

In the Default Encryption section:

  • Select Encryption type as Server-side encryption with AWS Key Management Service keys (SSE-KMS).

  • Select the AWS KMS key ARN. If the KMS key is in a different AWS account than the AWS S3 bucket, then the key will not appear in the AWS console dropdown. In this case, enter the KMS key ARN manually.

  • Enable Bucket Key.

Automatic AWS KMS Key and S3 Bucket Provisioning

When deploying PPC using the bootstrap script, the AWS S3 bucket and KMS key can be provisioned automatically during the installation process, without any separate pre-installation steps.

During the bootstrap script execution, at step 5, you are prompted to choose how to provide the AWS S3 bucket for cluster backups:

Do you want to use an existing AWS S3 bucket, or provision a new one (with KMS key)?
  1) Use existing
  2) Provision new via Tofu (backup-infra)

Select Option 2 - Provision new via Tofu to have the bootstrap script automatically:

  • Create a new AWS KMS key.
  • Create a new AWS S3 bucket encrypted with SSE-KMS.
  • Associate the AWS S3 bucket with the KMS key.

At step 6, when prompted, provide a globally unique bucket name using the following naming rules:

  • Lowercase letters, digits, and hyphens only.
  • Between 3 and 63 characters.
  • Must not already exist.

Note: The AWS S3 bucket and KMS key are created in the same AWS account using this option. For cross-account KMS configurations, follow the steps in the Using AWS Web UI tab.

Use a dedicated AWS S3 bucket per cluster for backup and restore operations to ensure data and encryption isolation. Sharing a bucket across clusters increases the risk of cross-cluster data access or decryption due to IAM misconfiguration.

Blocking Public Access to the AWS S3 Bucket

The PPC bootstrap script does not configure AWS S3 Block Public Access at the per-bucket level. This is by design because many AWS Organizations enforce AWS S3 Block Public Access through Service Control Policies (SCPs) at the account or organization level. This causes per-bucket s3:PutBucketPublicAccessBlock calls to fail with AccessDenied. AWS enabled S3 Block Public Access by default for all new accounts created after April 2023. However, verify the settings manually before proceeding.

Warning: The AWS S3 backup bucket stores highly sensitive data. Ensure that AWS S3 Block Public Access is enforced at the AWS account or organization level to prevent accidental public exposure.

Verify that AWS S3 Block Public Access is enabled at the account level before deploying PPC:

  1. Navigate to the Amazon AWS S3 console.

  2. Click Account and organization settings from the left navigation.

  3. Ensure all four settings are enabled and set to On:

    • Block public access to buckets and objects granted through new access control lists (ACLs)
    • Block public access to buckets and objects granted through any access control lists (ACLs)
    • Block public access to buckets and objects granted through new public bucket or access point policies
    • Block public and cross-account access to buckets and objects through any public bucket or access point policies
  4. If it is set to Off, then click Edit, select the check boxes, and click Save changes.

  5. Verify that the Block Public Access settings for this account are enabled using the following command:

    aws s3control get-public-access-block --account-id $(aws sts get-caller-identity --query Account --output text)
    

    All four fields BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets should be set to true.

Note: To block the permissions at the bucket level, navigate to Buckets > General purpose buckets > select the bucket > Permissions > Block public access (bucket settings).

Zone Requirements

The cluster requires a minimum of two availability zones for high availability. It is required to have two zones available while deploying a PPC.

ZonesSupportedNotes
1NoInstallation fails.
2YesMinimum requirement for High Availability.

Zones are derived from the private subnets which are provided. Each subnet maps to exactly one availability zone. During the installation, the bootstrap script validates that the selected subnets are in different Availability Zones.

Note: Zones cannot be changed after cluster creation.

1.2 - Preparing for PPC deployment

Downloading and Extracting the Protegrity Cluster Template (PCT) for Deploying PPC

If the jump box is already set previously, run the ./bootstrap.sh --cloud aws destroy command in the directory where the cluster is installed. This ensures that the local repository on the jump box and the clusters are cleaned up before proceeding with a new installation.

Warning: Do not install or manage multiple clusters from the same working directory. Each cluster deployment maintains its own Terraform/OpenTofu state, and reusing a directory can overwrite state files, causing loss of cluster tracking and unintended cleanup behavior.
Use a dedicated directory, and jump box, where possible, per cluster, and always verify the active kubectl context before running cleanup commands such as ./bootstrap.sh --cloud aws destroy.

  1. Log in to the My.Protegrity portal.

  2. Navigate to Product Management > Explore Products > AI Team Edition > Platform & Features.

  3. Navigate to Platform Installation.

  4. From the Actions column for Protegrity Provisioned Cluster, click the Download Product icon to download the PPC 1.1 archive.

  5. Create a deployment directory on the jumpbox.

    mkdir deployment && cd deployment
    
  6. Copy the PCT to the deployment directory on the jump box.

  7. Extract the PCT.

    tar -xvf PPC-K8S-ALL_1.1.0.97.tar
    

1.3 - Deploying PPC

Steps to deploy the PPC cluster

By default, the PCT is configured to deploy a FIPS-enabled cluster using FIPS-compliant Bottlerocket AMIs.

Non-FIPS deployment: Before proceeding with the installation, complete the steps in Configuring PPC for Non-FIPS Deployment on AWS to modify the required Terraform configuration files. Then proceed with either the automated or component-based installation below.

FIPS deployment: No additional configuration is required. Proceed directly with either the automated or component-based installation below.

The PPC cluster can be deployed using one of the following methods:

Automated script-based installation: This method requires the bootstrap.sh script to deploy the PPC cluster. The script installs the required software and dependencies, prompts to provide the required information, and deploys the cluster automatically.

Manual component-based installation: This method requires to perform the deployment of each component to install the PPC cluster. The configuration files are edited to provide the required information and then deploy the cluster.

1.3.1 - Configuring PPC for Non-FIPS Deployment on AWS

Complete the steps provided in this section to configure the Protegrity Cluster Template (PCT) for a non-FIPS PPC deployment on AWS EKS.

Before you begin

By default, the PCT is configured to deploy a FIPS-enabled cluster using FIPS-compliant Bottlerocket AMIs. To deploy a standard, non-FIPS cluster, the following Terraform configuration files must be modified to use the standard (non-FIPS) Bottlerocket AMI types and SSM parameter paths before running the bootstrap script or the component-based installation.

Perform these steps after downloading and extracting the PCT and before proceeding with either the Script-based installation or the Component-based installation.

Configuring PPC for Non-FIPS Deployment on AWS

For a non-FIPS PPC deployment on AWS EKS, perform the following steps:

  1. Update the node group AMI type map in the /03_node_group/variables.tf file.

The node_group_ami_type_map variable defines the fallback EKS AMI type used per node architecture when node_group_ami_type is not explicitly set. The FIPS-enabled defaults must be replaced with the corresponding standard Bottlerocket AMI types.

a. Navigate to /03_node_group directory.

cd iac/aws/cluster/modules/03_node_group/

b. Edit the variables.tf file to make the following changes.

Change from (FIPS defaults):

variable "node_group_ami_type_map" {
  description = "Fallback EKS AMI type per architecture, used when node_group_ami_type is empty."
  type        = map(string)
  default = {
    amd64 = "BOTTLEROCKET_x86_64_FIPS"
    arm64 = "BOTTLEROCKET_ARM_64_FIPS"
  }
}

Change to (non-FIPS values):

variable "node_group_ami_type_map" {
  description = "Fallback EKS AMI type per architecture, used when node_group_ami_type is empty."
  type        = map(string)
  default = {
    amd64 = "BOTTLEROCKET_x86_64"
    arm64 = "BOTTLEROCKET_ARM_64"
  }
}
  1. Update the Karpenter AMI SSM parameter path in the /05_helm_releases/main.tf file.

The karpenter_fips_ami_ssm_parameter value specifies the AWS Systems Manager (SSM) parameter path that Karpenter uses to resolve the correct Bottlerocket AMI for worker nodes. The default path targets the FIPS AMI. For a non-FIPS cluster, remove the -fips segment from the EKS version portion of the path.

a. Navigate to /05_helm_releases directory.

cd iac/aws/cluster/modules/05_helm_releases/

b. Edit the main.tf file to make the following changes.

Change from (FIPS SSM path):

karpenter_fips_ami_ssm_parameter = "/aws/service/bottlerocket/aws-k8s-${data.aws_eks_cluster.this.version}-fips/${local.karpenter_ami_arch}/latest/image_id"

Change to (non-FIPS SSM path):

karpenter_fips_ami_ssm_parameter = "/aws/service/bottlerocket/aws-k8s-${data.aws_eks_cluster.this.version}/${local.karpenter_ami_arch}/latest/image_id"

After completing all these configuration changes, proceed with deploying the cluster using one of the following methods:

1.3.2 - Automated script-based installation

Complete the steps provided in this section to deploy PPC in AWS EKS.

Note for non-FIPS deployments: If you completed the steps in Configuring PPC for Non-FIPS Deployment on AWS, then the required Terraform configuration files have already been updated with non-FIPS values. The bootstrap script reads these files directly. Do not modify 03_node_group/variables.tf or 05_helm_releases/main.tf files back to FIPS defaults. Reverting those changes will result in a FIPS cluster being deployed instead of a non-FIPS cluster.

Before you begin

  • Before running the bootstrap or resiliency scripts as the root user on RHEL, ensure that /usr/local/bin, and the AWS CLI binary path, if applicable, is included in the $PATH. Alternatively, run the script using a non-root user, such as ec2-user, where /usr/local/bin is already part of the default PATH.

The repository provides a bootstrap script that automatically installs or updates the following software on the jump box:

  • AWS CLI - Required to communicate with the AWS account.
  • OpenTofu - Required to manage infrastructure as code.
  • kubectl - Required to communicate with the Kubernetes cluster.
  • Helm - Required to manage Kubernetes packages.
  • skopeo - Required to copy and inspect container images across registries without requiring a daemon.
  • jq - Required to parse JSON.

The bootstrap script also checks if you have the required permissions on AWS. It then sets up the EKS cluster and installs the microservices required for deploying the PPC.

Architecture Selection

The step [1b] Select Node Architecture in the bootstrap script prompts to select the node architecture interactively during deployment.

  • amd64 (x86-64-based environments such as standard Intel or AMD servers)

  • arm64 (ARM-based environments such as AWS Graviton)

Deploying the PPC

The bootstrap script prompts for variables to be set to complete your deployment. Follow the instructions on the screen:

./bootstrap.sh --cloud aws --arch amd64

The script prompts for the following variables.

  1. Enter Cluster Name

    The following characters are allowed:

    • Lowercase letters: a-z
    • Numbers: 0-9
    • Hyphens: -

    The following characters are not allowed:

    • Uppercase letters: A-Z
    • Underscores: _
    • Spaces
    • Any special characters such as: / ? * + % ! @ # $ ^ & ( ) = [ ] { } : ; , .
    • Leading or trailing hyphens
    • Names longer than 31 characters (the cluster name must be 31 characters or fewer)

    Note: Ensure that the cluster name does not exceed 31 characters. Cluster names longer than this limit can cause the bootstrap script to fail in subsequent installation steps. If the installation fails, specify a cluster name that is 31 characters or fewer and re-run the script. The script automatically applies the updated value and continues the bootstrap process.

    After the cluster name is accepted, the script prompts you to select the node architecture.

    [1b] Select Node Architecture

    [1b] Select Node Architecture
      1) amd64 (x86_64) — e.g. t3, m5, c5 instances
      2) arm64 (Graviton) — e.g. t4g, m7g, c7g instances
    

    Enter 1 to select amd64 or 2 to select arm64.

    Note: Select amd64 for standard Intel/AMD 64-bit environments. Select arm64 for ARM-based environments such as AWS Graviton instances.

  2. Enter a VPC ID from the table

    The script automatically retrieves the available VPCs. Enter the VPC ID where the cluster must be created.

  3. Querying for subnets in VPC…

    The script queries for the available VPC subnets and prompts to enter two private subnet IDs. Specify two private subnet IDs from different availability zones.
    The script automatically updates the VPC CIDR block based on the VPC details.

  4. Enter FQDN

    This is the Fully Qualified Domain Name (FQDN) for the ingress.

    Warning: Ensure that the FQDN does not exceed 50 characters and only the following characters are used:

    • Lowercase letters: a-z
    • Numbers: 0-9
    • Special characters: - .
  5. Select S3 Backup Bucket Option

    The script prompts to choose how to provide the AWS S3 bucket encrypted with SSE‑KMS used for storing cluster backups for disaster recovery.

    Do you want to use an existing S3 bucket, or provision a new one (with KMS key)?
      1) Use existing
      2) Provision new via Tofu (backup-infra)
    
  6. Enter S3 bucket name

    • Option 1 – Use existing: Enter the name of an existing S3 bucket in your AWS account. The bucket must already be encrypted with SSE‑KMS.
    • Option 2 – Provision new via Tofu: The script uses OpenTofu (backup-infra) to create the S3 bucket and the corresponding KMS key on your behalf. Provide a globally unique bucket name when prompted:
      • Lowercase letters, digits, and hyphens only
      • Between 3 and 63 characters
      • Must not already exist

    Use a dedicated S3 bucket per cluster for backup and restore operations to ensure data and encryption isolation. Sharing a bucket across clusters increases the risk of cross-cluster data access or decryption due to IAM misconfiguration. Dedicated buckets with unique IAM policies eliminate this risk.

    During disaster management, OpenSearch restores only those snapshots that are created using the daily-insight-snapshots policy. For more information, refer to Backing up and restoring indexes.

  7. Enter Image Registry Endpoint

    The image repository from where the container images are retrieved. Use registry.protegrity.com:9443 for using the Protegrity Container Registry (PCR), else use the local repository endpoint for the local repository.

    Expected format: <hostname>[:port].
    Do not include ‘https://’

    Note: The container registry endpoint must be a Fully Qualified Domain Name (FQDN). Sub-paths like, my-registry.com/v2/path, are not supported by the Open Container Initiative (OCI) distribution specification.

  8. Enter Registry Username

    Enter the username for the registry mentioned in the previous step. Leave this entry blank if the registry does not require authentication.

  9. Enter Registry Password or Access Token

    Enter Password or Access Token for the registry. Input is masked with * characters. Press Enter to keep the current value. Leave this entry blank if the registry does not require authentication.

  10. Enter Owner Email (for cluster tagging)

    Enter email address in the format name@domain.tld. This email is used for the cluster ‘Owner’ tag and the platform owner contact.

Note: The cluster creation process can take 10-15 minutes.

If the session is terminated during installation due to network issues, power outage, and so on, then the installation stops. To restart the installation, run the script again:

# Navigate to setup directory 
./bootstrap.sh --cloud aws

Important Information

  • Do not install or manage multiple clusters from the same working directory. Each cluster deployment maintains its own Terraform/OpenTofu state, and reusing a directory can overwrite state files, causing loss of cluster tracking and unintended cleanup behavior.

  • Use a dedicated directory, and jump box, where possible, per cluster, and always verify the active kubectl context before running cleanup commands such as ./bootstrap.sh --cloud aws destroy.
    To check the active kubectl context, run the following command:
    kubectl config current-context

  • Do not delete the original cluster deployment directory, as it contains the Terraform state files required for managing the deployment.

1.3.3 - Manual component-based installation

Complete the steps provided in this section to update the configuration files and deploy PPC in AWS EKS.

Before you begin

Ensure to have the following prerequisites before proceeding with the installation.

Jump box requirement

Ensure that the entire process is performed using the same jump box.

Parameter values

ValueExample
AWS credentialsAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
Cluster namemy-cluster
VPC IDvpc-0abc123
Two private subnet IDssubnet-aaa, subnet-bbb
Ingress FQDNmyapp.example.com
S3 backup bucket namemy-backup-bucket (existing) or provision one in Step 3
Image registry endpointregistry.example.com
Registry username and passwordProvided by organization

Deploying PPC using component-based installation

To deploy PPC using the component-based installation, perform the following steps

StepActionDescription
1Exporting AWS credentialsExports AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN as environment variables to authenticate Terraform and AWS CLI operations.
2Installing the toolsInstalls all required CLI tools (OpenTofu, AWS CLI, kubectl, Helm, and others) on the jump box, either automatically via bootstrap.sh install-tools or manually.
3Provisioning the S3 bucket(Skip if using an existing bucket) Provisions a new S3 bucket and KMS key for storing PPC backup data using the 00_backup_bucket Terraform module.
4Modifying and applying terraform.tfvars filesConfigures and applies five Terraform modules in sequence to provision all PPC infrastructure components.
4a01_iam_roles moduleCreates the EKS cluster IAM role, node group IAM role, and service account IAM roles required for the deployment.
4b02_eks_cluster moduleProvisions the EKS cluster, VPC security group, and networking add-ons (VPC CNI, kube-proxy).
4c03_node_group moduleCreates the EKS worker node group with the specified instance size, architecture, and subnet configuration.
4d04_eks_addons moduleInstalls EKS add-ons including CoreDNS, Metrics Server, EBS CSI driver, and snapshot controller.
4e05_helm_releases moduleDeploys all PPC platform Helm charts including Karpenter, Velero, Envoy Gateway, and Insight. This step may take 15–20 minutes.
5Verifying the installationConfirms all cluster nodes are in Ready state and all pods are in Running state.

1. Exporting AWS credentials

The installation process uses Terraform to provision and manage AWS resources, such as VPCs, EKS clusters, IAM roles, and S3 buckets. The AWS credentials must be exported as environment variables to authenticate these operations.

Note: While using temporary credentials, such as, using AWS STS, ensure the session token is included and that the credentials have not expired before proceeding.

If the components are installed by different users, ensure that each user must export their AWS credentials. This ensures that all the required access and permissions are available.

To export the AWS credentials, run the following commands.

export AWS_ACCESS_KEY_ID=<your-access-key-id>
export AWS_SECRET_ACCESS_KEY=<your-secret-access-key>
export AWS_SESSION_TOKEN=<your-session-token>

2. Installing the tools

The following tools and minimum versions are required for the component-based installation. Ensure they are installed on your jump box before proceeding, or use the bootstrap.sh install-tools command to install them automatically.

After downloading and extracting the PPC-K8S-ALL_1.1.0.97.tar, run the following command to install the required tools.

./bootstrap.sh install-tools --cloud aws

Alternatively, the following tools must be installed and available on the jump box before starting.

Tools NameDescriptionUpdated Version
OpenTofuRequired to manage infrastructure as code (IaC) and provision cloud resources.1.11.5
AWS CLIRequired to communicate with AWS and manage AWS resources.2.36.7
kubectlRequired to communicate with and manage Kubernetes clusters.1.36.1
HelmRequired to deploy and manage Kubernetes packages and applications.3.21.0
skopeoRequired to inspect, copy, and transfer container images between registries.1.18.0
jqRequired to parse, filter, and process JSON data.1.7
bcRequired for version comparisons and resource calculations.1.07.1
ssh-keygenRequired to generate and manage SSH keys for secure access to deployment environments.OpenSSH_10.0p2 Debian-7+deb13u4
orasRequired to pull OCI artifacts, including non-container deployment packages, from registries.1.3.3
cmctlRequired to validate, manage, and troubleshoot cert-manager TLS certificates.2.5.0

3. Provisioning the S3 bucket

This step is required if a new S3 bucket is to be provisioned for storing the backup data. If an existing S3 bucket is to be used, note the bucket name and KMS key ARN required for the installation process and skip to the next step.

a. To navigate to 00_backup_bucket directory, run the following command.

cd iac/aws/cluster/modules/00_backup_bucket

b. Edit the terraform.tfvars file to provide the following information.

cluster_name                = "<cluster-name>" 
s3_bucket_name              = "<globally-unique-bucket-name>" 
kms_key_alias_name          = "alias/pty-backup-<cluster-name>-key" 
aws_region                  = "<region>" 

c. To apply the terraform configuration, run the following command.

tofu init 
tofu plan          # review the role assignments that will be created
tofu apply         # type "yes" when prompted

After the S3 bucket is provisioned successfully, note the bucket name and KMS key ARN. These values are required during the installation process.

d. To sync the Terraform state file to the S3 bucket, run the following command.

# Navigate to the bootstrap-scripts directory
cd <package-root>/bootstrap-scripts

# Run the script to sync the backup data to the S3 bucket
./sync-backup-bucket-state-to-s3.sh

4. Modifying and applying terraform.tfvars files

The iac/aws/cluster/modules/ directory contains the Terraform modules for the PPC installation. To enter details in the terraform.tfvars file, navigate to the appropriate module directory and edit the file accordingly.

After modifying the terraform.tfvars file, apply the changes

01_iam_roles module

a. To navigate to 01_iam_roles directory, run the following command.

cd iac/aws/cluster/modules/01_iam_roles

b. Edit the terraform.tfvars file to provide the following information.

aws_region            = "<region>"          
eks_cluster_name      = "<cluster-name>"
backup_bucket         = "<s3-bucket-name>"
backup_bucket_kms_arn = "<kms-key-arn>"    

c. To apply the terraform configuration, run the following command.

tofu init 
tofu plan          # review the role assignments that will be created
tofu apply         # type "yes" when prompted

d. After the configurations are successfully applied, verify the required resources are created.
To verify if the resources are created successfully, run the following command.

aws iam list-roles --query "Roles[?contains(RoleName, 'doc-test')].[RoleName, Arn]" --output table

The EKS cluster IAM role, Node group IAM role, and Service account IAM roles must be created.

Additionally, note the role ARNs from the Terraform output. These values are required in subsequent modules.

02_eks_cluster module

a. To navigate to 02_eks_cluster directory, run the following command.

cd iac/aws/cluster/modules/02_eks_cluster

b. Edit the terraform.tfvars file to provide the following information.

Ensure that the security group name must not start with sg.

aws_region          = "<region>"
eks_cluster_name    = "<cluster-name>"
backup_bucket       = "<s3-bucket-name>" 

# --- Networking ---
vpc_id              = "<vpc-id>" 
security_group_name = "<security-group-name>" 
private_subnet_ids  = [
  "<subnet-a>",
  "<subnet-b>"
]

# --- Tagging ---
owner_email = "<owner_email>"

# --- Access Entries (optional) ---
# Add IAM users/roles that need kubectl / tofu access beyond the original installer.
additional_access_entries = [
  # {
  #   principal_arn = "<principal-arn>"
  # },
]

c. To apply the terraform configuration, run the following command.

tofu init 
tofu plan          # review the role assignments that will be created
tofu apply         # type "yes" when prompted

d. After the configurations are successfully applied, verify the required resources are created.
To verify if the resources are created successfully, run the following command.

# Confirm the cluster is ACTIVE
aws eks describe-cluster --name <cluster-name> --region <region> \
  --query "cluster.{Name:name, Status:status, Version:version, Endpoint:endpoint}" \
  --output table
 
# Verify kubectl can reach the API server
kubectl get nodes          # expected: no nodes yet (node group is Stage 03)
 
# Verify the worker security group exists
aws ec2 describe-security-groups \
  --filters "Name=group-name,Values=<security-group-name>*" \
  --region <region> \
  --query "SecurityGroups[].{Name:GroupName, ID:GroupId}" \
  --output table
 
# Verify VPC CNI and kube-proxy add-ons are ACTIVE
aws eks list-addons --cluster-name <cluster-name> --region <region> --output table

03_node_group module

a. To navigate to 03_node_group directory, run the following command.

cd iac/aws/cluster/modules/03_node_group

b. Edit the terraform.tfvars file to provide the following information.

Note: Use the private subnet IDs from the VPC where the EKS cluster is provisioned while installing the 02_eks_cluster module.

aws_region       = "<region>" 
eks_cluster_name = "<cluster-name>" 
backup_bucket    = "<s3-bucket-name>" 

# --- System Node Group ---
node_group_name    = "<node-group-name>" 
private_subnet_ids = [
  "<subnet-a>",
  "<subnet-b>"
]
architecture            = "<amd64/arm64>"
node_group_desired_size = 2      
node_group_max_size     = 2
node_group_min_size     = 1

Note for non-FIPS deployments: If you completed the steps in Configuring PPC for Non-FIPS Deployment on AWS, the node_group_ami_type_map default values in variables.tf file have already been changed to BOTTLEROCKET_x86_64 (amd64) or BOTTLEROCKET_ARM_64 (arm64). Do not add or override node_group_ami_type with a FIPS value in terraform.tfvars, as this will reintroduce FIPS AMIs.

c. To apply the terraform configuration, run the following command.

tofu init 
tofu plan          # review the role assignments that will be created
tofu apply         # type "yes" when prompted

d. After the configurations are successfully applied, verify the required resources are created.
To verify if the resources are created successfully, run the following command.

aws eks describe-nodegroup --cluster-name <cluster-name> --nodegroup-name <node-group-name> --query "nodegroup.status"
kubectl get nodes

Ensure that the Node group status is ACTIVE and the desired number of nodes are in Ready state.

04_eks_addons module

a. To navigate to 04_eks_addons directory, run the following command.

cd iac/aws/cluster/modules/04_eks_addons

b. Edit the terraform.tfvars file to provide the following information.

aws_region       = "<region>"
eks_cluster_name = "<cluster-name>"
backup_bucket    = "<s3-bucket-name>" # 

# --- Upgrade mode only ---
# Set to "~/.kube/config" when upgrading an existing cluster;
# leave empty ("") for a fresh install.
kubeconfig_path  = ""

c. To apply the terraform configuration, run the following command.

tofu init 
tofu plan          # review the role assignments that will be created
tofu apply         # type "yes" when prompted

Note: This stage waits for all nodes from Stage 03 to reach Ready status before installing add-ons.

d. After the configurations are successfully applied, verify the required resources are created.
To verify if the resources are created successfully, run the following command.

# List all EKS add-ons and confirm they are ACTIVE
aws eks list-addons --cluster-name <cluster-name> --region <region> --output table
 
# Check add-on health details
for addon in coredns metrics-server aws-ebs-csi-driver snapshot-controller eks-pod-identity-agent; do
  echo "--- $addon ---"
  aws eks describe-addon --cluster-name <cluster-name> --addon-name $addon --region <region> \
    --query "addon.{Name:addonName, Status:status, Version:addonVersion}" --output table
done
 
# Verify the default storage class exists
kubectl get storageclass
 
# Confirm CoreDNS and Metrics Server pods are running
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl get pods -n kube-system -l k8s-app=metrics-server

05_helm_releases module

a. To navigate to 05_helm_releases directory, run the following command.

cd iac/aws/cluster/modules/05_helm_releases

b. Edit the terraform.tfvars file to provide the following information.

The default node OS is BOTTLEROCKET_x86_64_FIPS. While providing the node_os value, ensure that the value must be the same as nnode_group_ami_type value obtained from the 03_node_group module.

For obtaining the value of node_os, run the following command.

kubectl get nodes -o jsonpath='{.items[0].status.nodeInfo.osImage}'; echo

Provide the node_os value in the terraform.tfvars file.

aws_region            = "<region>"
eks_cluster_name      = "<cluster-name>"
backup_bucket         = "<s3-bucket-name>" 
backup_bucket_kms_arn = "<kms-key-arn>"
architecture          = "<amd64/arm64>"
node_os               = "<node-os>"

# --- Registry ---
global_image_reg = "<registry-endpoint>"
harbor_secret    = "harbor-secret" 

# --- Ingress ---
ingress_fqdn = "<fqdn>" 

# --- Owner ---
owner_email = "<owner-email>" 

# --- Networking (used to derive internal proxy CIDRs) ---
vpc_cidr_block = "<cidr>" 

# --- Envoy Gateway (LoadBalancer subnet discovery) ---
# Populated automatically by bootstrap.sh from stage 02 state.
private_subnet_ids = []

# --- Restore ---
restore              = false                               
backup_name          = "authnz-postgresql-schedule-backup" 
insight_backup_name  = ""                                  

# --- Upgrade mode only ---
# Set to "~/.kube/config" when upgrading an existing cluster;
# leave empty ("") for a fresh install.
kubeconfig_path = ""
is_upgrade      = false
skip_validations = false

c. To enter registry credentials using the environment variables, run the following commands.

export TF_VAR_username="<registry-username>"
export TF_VAR_password="<registry-password>"

d. To apply the terraform configuration, run the following command.

tofu init 
tofu plan          # review the role assignments that will be created
tofu apply         # type "yes" when prompted

Note: This process may take 15–20 minutes to get completed. Karpenter nodes are provisioned on demand after the NodePool is created.

e. After the configurations are successfully applied, verify the required resources are created.
To verify if the resources are created successfully, run the following command.

# Confirm all Helm releases are deployed
helm list -A
 
# Verify Karpenter controller is running
kubectl get pods -n karpenter
 
# Verify Karpenter NodePool and EC2NodeClass exist
kubectl get nodepools
kubectl get ec2nodeclasses
 
# Verify Velero is running
kubectl get pods -n pty-backup-recovery
 
# Verify PPC platform pods
kubectl get pods -A 
 
# Verify Insight pods
kubectl get pods -n pty-insight
 
# Verify Envoy Gateway
kubectl get pods -n api-gateway
 
# Check all pods across the cluster are healthy
kubectl get pods -A --field-selector=status.phase!=Running,status.phase!=Succeeded

5. Verifying the installation

To verify the installation, run the following command.

kubectl get nodes
kubectl get pods -A

All the nodes should be in the Ready state and all the pods should be in the Running state.

1.4 - Installing Features and Protectors

Installing the features and protectors

Before you begin

Ensure that PPC is successfully installed before installing the features or protectors.

Installing Features

The following table lists the available features.

FeatureDescription
Data DiscoveryInstalling Data Discovery
Semantic GuardrailsInstalling Semantic Guardrails
Protegrity AgentInstalling Protegrity Agent
AnonymizationInstalling Anonymization
Synthetic DataInstalling Synthetic Data

Installing Protectors

The following table lists the available protectors.

ProtectorDescription
Application ProtectorInstalling Application Protector
Repository ProtectorInstalling Repository Protector
Application Protector Java ContainerInstalling Application Protector Java Container
Rest ContainerInstalling Rest Container
Cloud ProtectorInstalling Cloud Protector

1.5 - Accessing the PPC CLI

The Protegrity Provisioned Cluster (PPC) CLI provides a command-line interface for managing policies, users, and log forwarding. Access is established over SSH using the private key generated during the PPC installation.

1.5.1 - Prerequisites

The deployment includes a CLI container that provides command-line access to the Protegrity Management CLI using SSH, on both Linux and Windows.

To access the PPC CLI, ensure that the following prerequisites are met.

  • SSH Keys: The SSH private key that corresponds to the public key configured in the pty-cli pod is required.

  • Network Access: Ensure to have network connectivity to the cluster.

  • Resolve FQDN: Use Route 53 configuration on AWS to resolve the PPC FQDN specified during the installation to the internal load balancer. For more information, refer to Prerequisites.

The private key to access the CLI pod will be in the .ssh directory.

From the .ssh/ directory:

ssh -i /home/admin/.ssh/<cluster_name>_user_svc ptyitusr@<user-provided-fqdn>

The private key to access the CLI pod will be in the .ssh directory. Copy the key file to a directory on the local Windows machine.

  • Using Windows SSH Client (Windows 10/11 with OpenSSH):

    ssh -i C:\path\to\copied\file\.ssh -p 22 ptyitusr@<user-provided-fqdn>
    
  • Using PuTTY:

    • Host Name: <user-provided-fqdn>
    • Port: 22
    • Connection Type: SSH
    • Under Connection > SSH > Auth, browse and select your private key file (.ppk format)
    • Username: ptyitusr

1.5.2 - Accessing the PPC CLI

Once connected, the Protegrity CLI welcome banner is displayed. Enter the following parameters when prompted:

  • Username: Application username
  • Password: Application password

For more information about the default credentials, refer to the Release Notes.

The CLI supports three main command categories:

  • pim: Policy Information Management commands for data protection policies.
  • admin: User, Role, Permission, and Group management commands.
  • insight: Log forwarding to external SIEM and syslog servers.

Note: Ensure that at least one additional backup administrator user is configured with the same administrative privileges as the primary admin user.
If the primary admin account is locked or its credentials are lost, restoring the system from a backup is the only recovery option.

1.6 - Login to PPC

The PPC provides a web-based user interface for managing data protection policies, users, and roles. Access the UI through a browser using the cluster’s FQDN. This section covers the prerequisites for resolving the FQDN and the steps to log in.

1.6.1 - Prerequisites

Before accessing the Web UI, configure AWS Route 53 to resolve the PPC Fully Qualified Domain Name (FQDN) to the internal load balancer. This section lists the network and DNS requirements you need to verify, and the steps to map the FQDN to the load balancer.

Use Route 53 configuration on AWS to resolve the PPC FQDN specified during the installation to the internal load balancer.

  • Ensure that the instance is using the AWS-provided DNS server, such as, VPC CIDR + 2.
  • Verify that enableDnsHostnames and enableDnsSupport are set to true in the VPC settings.
  • Verify the Security Group of the load balancer. Ensure that Inbound traffic is allowed on the required ports, such as, 80 and 443, from the client instance’s IP or Security Group.
  • Keep the following information ready:
    • VPC ID: The ID of the VPC for the client instances and the Load Balancer. For example, vpc-0123456789.
    • Internal ELB DNS Name: The DNS name of the load balancer. For example, internal-abcdefghi123456-123456789.us-east-1.amazonaws.com.
    • Target FQDN: The FQDN for PPC. For example, mysite.aws.com.
  1. Find the AWS Load Balancer address.
    kubectl get gateway -A

The output appears similar to the following:

    NAMESPACE     NAME       CLASS   ADDRESS                                                                         PROGRAMMED   AGE
    api-gateway   pty-main   envoy   a814fae40464d462da9ca685921699c0-1ccfcf98919adf90.elb.us-east-1.amazonaws.com   True         34m
  1. Verify that the gateway address resolves to an internal IP, using the following command.
    ping <gateway_address>

Where <gateway_address> is the ADDRESS value from the previous step.

The output confirms that the hostname resolves to a private VPC IP address (10.x.x.x range), indicating the load balancer is internal and accessible only within the AWS VPC.

The output appears similar to the following:

    PING a814fae40464d462da9ca685921699c0-1ccfcf98919adf90.elb.us-east-1.amazonaws.com (10.31.4.172) 56(84) bytes of data.
  1. Map the PPC FQDN to the load balancer using Route 53.

For more information about configuring Route 53, refer to the AWS documentation.

1.6.2 - Log in to PPC

After completing the prerequisites, log in to the web-based user interface for managing data protection policies, users, and roles. This page describes the steps to access the Web UI using the Fully Qualified Domain Name (FQDN) provided during the installation process.

Access the PPC using the FQDN provided during the installation process.

Enter the following parameters to log in and view the Insight Dashboard.

  • Username: Application username
  • Password: Application password

For more information about the default credentials, refer to the Release Notes.

If Protegrity Agent is installed, then the Protegrity Agent dashboard appears. Click Insight to open the Insight Dashboard. For more information about Protegrity Agent, refer to Using Protegrity Agent.

1.7 - Upgrading the PPC

Complete the steps provided in this section to upgrade a PPC to v1.1.0.

Before you begin

Before starting an upgrade, ensure the following conditions are met:

  • Access to the jump box associated with the PPC v1.0.0 cluster is required. This must be the same jump box used during the PPC v1.0.0 installation.

  • Maintain both, previous and current installation directories. Do not delete the original cluster deployment directory, as it contains the Terraform state files required for managing the deployment.

  • Create a Velero backup and an OpenSearch snapshot to ensure data recovery is possible, in case of an upgrade failure.

  • Maintain a backup of the state file in the AWS S3 backup bucket.

  • If logs are forwarded to an external SIEM, then from the PPC CLI, run the insight delete syslog or the insight delete fluentd as per your configuration. After the upgrade is complete, re-configure the SIEM. For more information about SIEM configuration, refer to Sending logs to a SIEM.

  • The context is set to the cluster where the upgrade operation is to be performed. Run the following command.

    kubectl config current-context
    

    The cluster name in the output must match the cluster installed with PPC v1.0.0.

Note: Before running the bootstrap or resiliency scripts as the root user on RHEL, ensure that /usr/local/bin, and the AWS CLI binary path, if applicable, is included in the $PATH. Alternatively, run the script using a non-root user, such as ec2-user where /usr/local/bin is already part of the default $PATH.

Upgrading PPC

To upgrade the PPC from v1.0.0 to v1.1.0, perform the following steps:

  1. Create a deployment_110 directory on the jump box and navigate to it.

    mkdir deployment_110 && cd deployment_110
    
  2. Log in to the My.Protegrity portal.

  3. Navigate to Product Management > Explore Products > AI Team Edition > Platform & Features.

  4. Navigate to Platform Installation.

  5. From the Actions column for Protegrity Provisioned Cluster, click the Download Product icon and download the PPC 1.1 archive to the deployment_110 directory.

  6. Extract the archive contents.

    tar -xvf PPC-K8S-ALL_1.1.0.97.tar
    
  7. Copy the Terraform state file from the v1.0.0 cluster installation to the deployment_110 directory created for upgrade.

    cp /<v1.0.0-cluster-dir>/deployment/iac_setup/scripts/iac/terraform.tfstate /<v1.1.0-cluster-dir>/deployment_110/terraform.tfstate
    

    where <v1.0-cluster-dir> is the path to the original PPC v1.0.0 cluster installation directory on the jump box, and <v1.1.0-cluster-dir> is the path to the new directory created for upgrade.

  1. Verify the active context points to the correct cluster using the following command.

     kubectl config current-context
    
  2. Initiate the upgrade from the deployment_110 directory using the following command.

    bash upgrade.sh --cloud aws --v1.0-state-file /<v1.1.0-cluster-dir>/deployment_110/terraform.tfstate
    

    where /<v1.1.0-cluster-dir>/deployment/terraform.tfstate is the path to the Terraform state file copied in Step 6.

    After the upgrade is successful, a PPC upgrade completed successfully. message is displayed.

The cluster upgrade process can take 10–15 minutes approximately and may differ accordingly.

Post Upgrade Steps

Verify all nodes are Ready

To verify if all nodes are in the ready state, run the following command.

kubectl get nodes -o wide

Verify all pods are Running

To verify if all pods are in the running state, run the following command.

kubectl get pods -A

Verify Helm releases

To verify if the helm releases are in the deployed state, run the following command.

helm list -A

Password Policy After Upgrade

PPC v1.1.0 upgrade enforces the following behavior.

  • If the minimum password length was set to a value less than 14 characters, or was not configured, the upgrade sets it to 14 characters.

  • If the minimum password length was already set to 14 characters or greater, that value is preserved and remains unchanged after the upgrade.

For more information about the password policy, refer to Password Policy APIs or CLI reference for get password_policy.

Configuring SIEM

If logs were forwarded to an external SIEM before the upgrade, then SIEM log forwarding was disabled as part of the pre-upgrade prerequisites. After completing the upgrade, update the settings to resume sending logs to the external SIEM.

For more information about configuring SIEM, refer to Sending logs to an external security information and event management (SIEM).

Directory Maintenance after Upgrade

During upgrade, both the previous and the new PPC installation directories must be retained.

  • The original directory contains Terraform state and deployment metadata.
  • The new directory contains the updated configuration and binaries.

Both directories are required for proper management of the deployment.

Recovering from a Failed Upgrade

If the session is terminated during upgrade due to network issues, power outage, or any such issues, then the upgrade process stops. The ./upgrade.sh script resumes the upgrade.

To restart the process, run the following command:

   bash upgrade.sh --cloud aws --v1.0-state-file /<v1.1.0-cluster-dir>/deployment_110/terraform.tfstate

Warning: Do not install or manage multiple clusters from the same working directory. Each cluster deployment maintains its own Terraform or OpenTofu state, and reusing a directory can overwrite state files, causing loss of cluster tracking and unintended cleanup behavior.
Use a dedicated directory, and jump box, where possible, per cluster, and always verify the active kubectl context before running cleanup commands such as ./bootstrap.sh --cloud aws destroy.
To check the active kubectl context, run the following command:
kubectl config current-context

Reverting to a previous version of PPC

To revert to a previous version of PPC, restore the cluster using the steps in Restoring the PPC.

1.8 - Backing up the PPC

Complete the steps provided in this section to backup a PPC deployment.

Protegrity Provisioned Cluster (PPC) supports backup of Insight indexes and cluster configurations. Use the procedures below to update the scheduled backups of your PPC deployment.

Backing up Velero backup schedule

To take a backup at an interval of 10 minutes, the cron job must be executed before the schedule. This ensures that the latest configurations are included and are available in the Storage Account.
By default, the cron job is executed after every 3 hours and schedule is executed after every 3.5 hours.

For taking the backups, the frequency of schedule and cron job can be changed, as required.

Perform the following steps to update the frequency.

  1. To update the frequency of the cron job, run the following command.

    $ kubectl patch cronjob authnz-postgresql-backup-recovery-cron-job \
    -n api-gateway \'
    --type=merge -p '{"spec":{"schedule":"<required frequency>"}}'
    
  2. To update the frequency of the schedule, run the following command.

    $ kubectl patch schedule authnz-postgresql-schedule-backup \   
    -n pty-backup-recovery \
    --type=merge -p '{"spec":{"schedule":"<required frequency>"}}' 
    

For instance, to update the frequency of the backup schedule to 10 minutes, perform the following steps.

  1. To update the cron job to every 8 minutes, run the following command.

    $ kubectl patch cronjob authnz-postgresql-backup-recovery-cron-job \
     -n api-gateway \
     --type=merge -p '{"spec":{"schedule":"8-58/10 * * * *"}}'
    
  2. To update the schedule to every 10 minutes, run the following command.

    $ kubectl patch schedule authnz-postgresql-schedule-backup \
     -n pty-backup-recovery \
     --type=merge -p '{"spec":{"schedule":"*/10 * * * *"}}'
    

Backing up indexes

Insight indexes are backed up automatically using a scheduled job. To manually back up the indexes, perform the following steps:

  1. Log in to the Insight Dashboard.
  2. Select the main menu.
  3. Navigate to Management > Snapshot Management > Snapshot policies.
  4. Click the daily-insight-snapshots policy.
  5. Click Edit.
  6. Update the following parameters:
    • Snapshot schedule
      • Frequency: Custom (Cron expression)
      • Cron expression: */15 * * * *
  7. Click Update.
  8. Wait for the next scheduled snapshot to complete. Verify that the snapshot is created from the snapshot status.

Note: The snapshot schedule is set to run every 15 minutes for creating the manual backup. Restore the default settings after the manual backup is complete. Before upgrading, disable the scheduler job after the backup is created. Ensure that the default parameters are restored and the job is re-enabled after the upgrade.

1.9 - Restoring the PPC

Complete the steps provided in this section to restore a PPC deployment using an existing backup.

Before you begin

Before starting a restore, ensure the following conditions are met:

  • An existing backup is available. Backups are taken automatically as part of the default installation using scheduled backup mechanisms. These backups are stored in an AWS S3 bucket configured during the original installation.

  • Access to the original backup AWS S3 bucket. During restore, the same S3 bucket that was used during the original installation must be specified.

  • Before initiating the restore, review and update the KMS key policy to reflect the restore cluster name. Even if the policy was already configured for the source cluster, it must be updated for the new restore cluster. If the policy continues to reference the source cluster name, the IAM role created during restore cannot decrypt the backup data, causing the restore to fail.

  • Permissions to read from the S3 bucket. The user performing the restore must have sufficient permissions to access the backup data stored in the bucket.

  • A Kubernetes cluster is created. Restore is performed as part of creating a cluster, not on an existing one. Restore is only supported during a fresh installation flow.

  • While the backup is taken from the source cluster, do not perform Create, Read, Update, or Delete (CRUD) operations on the source cluster. This ensures backup consistency and prevents data corruption during restore.

  • Before restoring to a new cluster, if the source cluster is accessible, disable the backup operations on the source cluster by setting the backup storage location to read‑only. This ensures that no additional backup data is written during the restore process.

    To disable the backup operation on the source cluster, run the following command:

    kubectl patch backupstoragelocation default -n pty-backup-recovery --type merge -p '{"spec":{"accessMode":"ReadOnly"}}'
    

    If the source cluster is not accessible, this step can be skipped.

During Disaster management, the backup data is used to restore the cluster and the OpenSearch indexes using snapshots. However, Insight restores OpenSearch data only from the most recent snapshot created by the daily-insight-snapshots policy.
For more information, refer to Backing up and restoring indexes.

Warning: Do not install or manage multiple clusters from the same working directory. Each cluster deployment maintains its own Terraform or OpenTofu state, and reusing a directory can overwrite state files, causing loss of cluster tracking and unintended cleanup behavior.
Use a dedicated directory, and jump box, where possible, per cluster, and always verify the active kubectl context before running cleanup commands such as ./bootstrap.sh --cloud aws destroy.

The repository provides a bootstrap script that automatically installs or updates the following software on the jump box:

  • AWS CLI - Required to communicate with your AWS account.
  • bc - Required for version comparisons and resource calculations.
  • cmctl - Required to validate and manage TLS certificates.
  • Helm - Required to manage Kubernetes packages.
  • jq - Required to parse JSON.
  • kubectl - Required to communicate with the Kubernetes cluster.
  • OpenTofu - Required to manage infrastructure as code.
  • ORAS - Required to pull OCI artifacts such as deployment packages.
  • skopeo - Required to copy container images between registries.
  • ssh-keygen - Required to secure SSH access to deployment environments.

The bootstrap script also checks if you have the required permissions on AWS. It then sets up the EKS cluster and installs the microservices required for deploying the PCS on a PPC.

Note: Before running the bootstrap or resiliency scripts as the root user on RHEL, ensure that /usr/local/bin (and the AWS CLI binary path, if applicable) is included in the $PATH. Alternatively, run the script using a non-root user (such as ec2-user) where /usr/local/bin is already part of the default PATH.

Architecture Selection

  • amd64 (x86-64-based environments such as standard Intel or AMD servers)
  • arm64 (ARM-based environments such as AWS Graviton)

The bootstrap script prompts you to select the node architecture interactively during deployment (step 1b).

Restoring the PPC

Ensure that the PCT is downloaded and extracted on the jump box. For more information, refer to Preparing for PPC deployment.

Run the following command to initiate restore using an existing backup:

./bootstrap.sh --cloud aws --restore

To deploy PPC on ARM-based infrastructure, specify the architecture explicitly:

The bootstrap script asks for variables to be set to complete the deployment. Follow the instructions on the screen.

The --restore command enables the restore mode for the installation. It initiates restoration of data from the configured AWS S3 backup bucket. This process must be followed on a fresh jump box.

The script prompts for the following variables.

  1. Enter Cluster Name

    • Ensure that the cluster name does not match the name of the source cluster. Reusing an existing cluster name during restore can lead to discrepancies during cluster installation.
    • This same cluster name must already be updated in the KMS key policy. If this update is not performed, the restore process fails because the new cluster cannot decrypt the backup data.
    • Ensure that the cluster name does not exceed 31 characters. Cluster names longer than this limit can cause the bootstrap script to fail in subsequent installation steps.
      If the installation fails because the cluster name exceeds the 31-character limit, correct the name and re-run the script.
      • Correction: Choose a cluster name with 31 characters or fewer.
      • Retry: Execute the installation command again with the updated name. The script will automatically handle the update and proceed with the bootstrap process.

    The following characters are allowed:

    • Lowercase letters: a-z
    • Numbers: 0-9
    • Hyphens: -

    The following characters are not allowed:

    • Uppercase letters: A-Z
    • Underscores: _
    • Spaces
    • Any special characters such as: / ? * + % ! @ # $ ^ & ( ) = [ ] { } : ; , .
    • Leading or trailing hyphens
    • More than 31 characters

    After the cluster name is accepted, the script prompts you to select the node architecture.

    [1b/10] Select Node Architecture

    [1b/10] Select Node Architecture
      1) amd64 (x86_64) — e.g. t3, m5, c5 instances
      2) arm64 (Graviton) — e.g. t4g, m7g, c7g instances
    

    Enter 1 to select amd64 or 2 to select arm64.

    Note: Select amd64 for standard Intel/AMD 64-bit environments. Select arm64 for ARM-based environments such as AWS Graviton instances.

  2. Enter a VPC ID from the table

    The script automatically retrieves the available VPCs. Enter the VPC ID where the cluster must be created.

  3. Querying for subnets in VPC…

    The script queries for the available VPC subnets and prompts to enter two private subnet IDs. Specify two private subnet IDs from different availability zones.
    The script then automatically updates the VPC CIDR block based on the VPC details.

  4. Enter FQDN

    This is the Fully Qualified Domain Name (FQDN) for the ingress.

    While entering the FQDN, ensure that:

    • contains at least two labels separated by a dot, such as, app.example.com
    • does not start or end with a dot or hyphen
    • does not contain consecutive dot character
    • label length must be between 1–63 characters
    • each label must start and end with a letter or digit
    • the last label must start only with a letter

    Warning: Ensure that the FQDN does not exceed 50 characters and only the following characters are used:

    • Lowercase letters: a-z
    • Numbers: 0-9
    • Special characters: - .
  5. Restore mode requires an existing S3 bucket. Proceeding to existing bucket validation in Step 6.

  6. Select S3 Backup Bucket Option

    An AWS S3 bucket encrypted with SSE‑KMS containing backup artifacts used during the restore process.

    Use a dedicated S3 bucket per cluster for backup and restore operations to ensure data and encryption isolation. Sharing a bucket across clusters increases the risk of cross-cluster data access or decryption due to IAM misconfiguration. Dedicated buckets with unique IAM policies eliminate this risk.

    Select backup

    During restore, the script prompts to manually select a backup from the available backups stored in the S3 bucket. User input is required to either restore from the latest backup or choose a specific backup from the list.

    [restore] Backup selection — schedule: authnz-postgresql-schedule-backup
    Restore from latest backup? [Y/n]
    
    • Enter Y to restore from the most recent backup.
    • Enter n to manually select a backup.

    If n is selected, then the script displays a list of available backups (latest first) and prompts to select one by number:

    Available backups (latest first):
    [1] <timestamp> authnz-postgresql-schedule-backup-xxxxxxx
    [2] <timestamp> authnz-postgresql-schedule-backup-xxxxxxx
    
    Select a backup number (1-2):
    

    After entering the backup number, the chosen backup is used for the restore, and the installation continues.

    Enter Insight backup

    During restore, the script prompts to manually select the required insight backup from the available backups stored in the S3 bucket. User input is required to either restore from the latest backup or choose a specific backup from the list.

    [restore] Insight backup selection — schedule: insight-configmaps-secrets
    Restore from latest backup? [Y/n]
    
    • Enter Y to restore from the most recent backup.
    • Enter n to manually select a backup.

    If n is selected, then the script displays a list of available backups (latest first) and prompts to select one by number:

    Available backups (latest first):
    [1] <timestamp>  insight-configmaps-secrets-xxxxxxxxx
    [2] <timestamp>  insight-configmaps-secrets-xxxxxxxxx
    
    Select a backup number (1-2):
    

    After entering the backup number, the chosen backup is used for the restore, and the installation continues.

  7. Enter Image Registry Endpoint

    The image repository from where the container images are retrieved.

    Expected format: <hostname>[:port].
    Do not include ‘https://’

    Note: The container registry endpoint must be a FQDN (Fully Qualified Domain Name). Sub-paths like, my-registry.com/v2/path, are not supported by the OCI distribution specification.

  8. Enter Registry Username

    Enter the username for the registry mentioned in the previous step. Leave this entry blank if the registry does not require authentication.

  9. Enter Registry Password or Access Token

    Enter Password or Access Token for the registry. Input is masked with * characters. Press Enter to keep the current value.

    Leave this entry blank if the registry does not require authentication.

  10. Enter Owner Email (for cluster tagging)

    Enter email address in the format name@domain.tld. This email is used for the cluster ‘Owner’ tag and the platform owner contact.

Note: The cluster creation process can take approximately 15-20 minutes.

If the session is terminated during restore due to network issues, power outage, and so on, then the restore stops. To restart the process, run the following commands:

# Navigate to deployment directory and run the following command
./bootstrap.sh --cloud aws destroy

# Restore the cluster
./bootstrap.sh --cloud aws --restore

Warning: Do not install or manage multiple clusters from the same working directory. Each cluster deployment maintains its own Terraform or OpenTofu state, and reusing a directory can overwrite state files, causing loss of cluster tracking and unintended cleanup behavior.
Use a dedicated directory, and jump box, where possible, per cluster, and always verify the active kubectl context before running cleanup commands such as ./bootstrap.sh --cloud aws destroy.
To check the active kubectl context, run the following command:
kubectl config current-context

After the restore to the new cluster is completed successfully and all required validation and migration activities are finished, the source cluster can be deleted.

1.10 - Deleting PPC

Steps to delete the cluster

Prerequisites

Authentication

The deletion process uses OpenTofu to destroy AWS resources, such as EKS clusters, IAM roles, S3 buckets, and KMS keys. The AWS credentials must be exported as environment variables to authenticate these operations.

Note: While using temporary credentials, such as, using AWS STS, ensure the session token is included and that the credentials have not expired before proceeding.

To export the AWS credentials, run the following commands.

export AWS_ACCESS_KEY_ID=<your-access-key-id>
export AWS_SECRET_ACCESS_KEY=<your-secret-access-key>
export AWS_SESSION_TOKEN=<your-session-token>

To verify that the credentials are valid and the correct AWS identity is being used, run the following command.

aws sts get-caller-identity

Required Permissions

The same IAM principal (or one with equivalent permissions) that installed the cluster, can delete the cluster. The principal must have cluster-creator admin access to the EKS Kubernetes API.

The required IAM Permissions are listed in the following table:

CategoryPermissionsUsed by
S3 (state backend)s3:ListBucket,
s3:GetObject,
s3:PutObject,
s3:DeleteObject
All modules (backend state read/write)
KMSkms:Decrypt,
kms:Encrypt,
kms:GenerateDataKey,
kms:DescribeKey,
kms:ScheduleKeyDeletion
S3 backend (SSE-KMS), module 00 destroy
EKSeks:DescribeCluster,
eks:DeleteCluster,
eks:DeleteNodegroup,
eks:DeleteAddon,
eks:DeleteAccessEntry,
eks:DeletePodIdentityAssociation
Modules 02–05
IAMiam:DeleteRole,
iam:DetachRolePolicy,
iam:DeletePolicy,
iam:DeleteInstanceProfile,
iam:RemoveRoleFromInstanceProfile
Module 01
EC2ec2:DeleteSecurityGroup,
ec2:RevokeSecurityGroupIngress,
ec2:RevokeSecurityGroupEgress,
ec2:DeleteLaunchTemplate,
ec2:DeleteTags,
ec2:TerminateInstances
Modules 02, 03, Karpenter cleanup
EKS Kubernetes APICluster admin (AmazonEKSClusterAdminPolicy or equivalent)Modules 04, 05 (Helm releases, storage classes, namespaces)

Required tools

The following tools must be installed and available on the machine before proceeding with deletion:

  • tofu (OpenTofu)
  • kubectl (configured with cluster context)
  • aws CLI
  • helm

Cleaning up the EKS Resources

There are two ways to destroy all created resources, including the EKS cluster and related components.

Method 1: Bootstrap scriptMethod 2: OpenTofu modules
ApproachAutomated, single commandManual, module-by-module
ControlFully automated; no per-stage visibilityFull control and visibility over each stage
Best forStandard teardowns where speed is preferredTroubleshooting, partial cleanup, or auditing each deletion step
EffortMinimalHigher; requires navigating each module directory

Method 1: Using the bootstrap script

From the folder where bootstrap script is present, run the following command:

./bootstrap.sh --cloud aws destroy

Method 2: Using OpenTofu to delete all modules

This method displays how to delete a PPC cluster on AWS by destroying the OpenTofu modules in reverse order. Destroying modules one at a time gives full control and visibility over each stage.

Warning: This process is irreversible. All cluster resources, data, and backups stored in the S3 bucket will be permanently deleted.

The modules are located at:

~/iac/aws/cluster/modules/
├── 00_backup_bucket
├── 01_iam_roles
├── 02_eks_cluster
├── 03_node_group
├── 04_eks_addons
└── 05_helm_releases

These modules must be destroyed in reverse order: 05 → 04 → 03 → 02 → 01 → 00.

To delete the modules, perform the following steps:

  1. To delete the helm releases resource, perform the following steps:
# Navigate to 05_helm_releases directory
cd /iac/aws/cluster/modules/05_helm_releases

# Initialize providers
tofu init  

# Delete the helm release
tofu destroy        # type "yes" when prompted
  1. To delete the EKS Addons resource, run the following command.
# Navigate to 04_eks_addons directory
cd /iac/aws/cluster/modules/04_eks_addons

# Initialize providers
tofu init  

# Delete the eks addons
tofu destroy        # type "yes" when prompted
  1. To delete the Node Group resource, run the following command.
# Navigate to 03_node_group directory
cd /iac/aws/cluster/modules/03_node_group

# Initialize providers
tofu init 

# Delete the node group
tofu destroy        # type "yes" when prompted
  1. To delete the EKS Cluster resource, run the following command.
# Navigate to 02_eks_cluster directory
cd /iac/aws/cluster/modules/02_eks_cluster

# Initialize providers
tofu init 

# Delete the eks cluster
tofu destroy        # type "yes" when prompted
  1. To delete the IAM Roles resource, run the following command.
# Navigate to 01_iam_roles directory
cd /iac/aws/cluster/modules/01_iam_roles

# Initialize providers
tofu init 

# Delete the iam roles
tofu destroy        # type "yes" when prompted
  1. To delete the Backup Bucket (S3 + KMS) resource, perform the following steps.
# 1.Navigate to 00_backup_bucket directory
cd /iac/aws/cluster/modules/00_backup_bucket
# 2. Download the state file from S3 (synced there during install)
aws s3 cp \
  s3://<bucket-name>/infrastructure-manifest/<cluster-name>/states/00_backup_bucket.tfstate \
  ./terraform.tfstate
# 3. Initialize providers
tofu init
# 4. Enable force_destroy on the bucket (updates only the flag)
tofu apply -var="force_destroy_bucket=true"
# 5. Destroy all resources
tofu destroy -var="force_destroy_bucket=true"        # type "yes" when prompted

Note: After destroying all the modules, delete the CloudWatch Logs group created by EKS control plane logging using the following command.

aws logs delete-log-group \
 --log-group-name "/aws/eks/<cluster-name>/cluster" \
 --region <region>

1.11 - Accessing PPC using a Linux machine

Steps to access PPC using a separate Linux machine

Access to the PPC cluster from a separate Linux machine may be required in the following situations:

  • The original jump box used during installation is no longer available or has been decommissioned.
  • A different team member or administrator needs cluster access without setting up a new jump box.
  • Operational tasks, such as troubleshooting or monitoring, are being performed from a dedicated management machine.
  • The organization requires cluster access to be restricted to specific machines for security or compliance reasons.

Before you begin

Ensure that the following prerequisites are met.

  • A Linux machine is available and running.
  • AWS CLI is installed and configured.
  • Kubernetes command-line tool is installed.

Perform the following steps to access PPC using a separate Linux machine.

  1. Log in to Linux machine with root credentials.

  2. Configure AWS credentials, using the following command.

    aws configure
    
  3. Verify that AWS credentials are working, using the following command.

    aws sts get-caller-identity
    
  4. If the Kubernetes command-line tool is not available, then install the Kubernetes command-line tool, using the following command.

    kubectl version --client 2>/dev/null || {
     echo "Installing kubectl..."
     curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
     chmod +x kubectl
     sudo mv kubectl /usr/local/bin/
     kubectl version --client
    }
    
  5. Set up the Kubernetes command-line tool and access the cluster, using the following command.

    aws eks update-kubeconfig --region <region_name> --name <cluster_name>
    
  6. Verify the access to the cluster, using the following command.

    kubectl get nodes
    

1.12 - Restoring the SSH keys and PCT from backed up Terraform state file

Complete the steps provided in this section to restore the SSH keys and PCT from a backed up Terraform state file of a deleted v1.1.0 jump box.

This section describes the procedure to rebuild a usable PPC v1.1.0 deployment workspace on a jump box from an existing cluster and a backed up Terraform state file.

Before you Begin

Ensure the following requirements are met.

  • The state file from all the following modules must be available on the AWS S3 backup bucket.

    • 00_backup_bucket
    • 01_iam_roles
    • 02_eks_cluster
    • 03_node_group
    • 04_eks_addons
    • 05_helm_releases
  • Access to the same AWS account and target EKS cluster.

  • AWS CLI credentials with required permissions.

Perform the following steps to recover PPC

  1. Create a workspace.

    To create a working directory for PCT, run the following command.

    mkdir -p deployment
    cd deployment
    
  2. Download and extract the PCT

    Download the PCT package into the deployment directory and extract it.
    For more information about downloading and extracting the PCT, refer to Preparing for PPC deployment.

    After successfully extracting the template, this directory behaves as recovered installation workspace.

  3. Install required dev tools

    Run the following script.

    cd bootstrap-scripts/
    ./setup-devtools-aws.sh
    
  4. Set kubectl to the target EKS cluster

    To set kubectl to the target EKS cluster, run the following command.

    aws eks update-kubeconfig --region <aws-region> --name <cluster-name>
    

    Example:

    aws eks update-kubeconfig --region us-east-1 --name <cluster-name>
    

    Verify the current cluster

    Before proceeding, verify the context and cluster connectivity. Run the following command.

    kubectl config current-context
    
  5. Initialize OpenTofu

    To initialize OpenTofu for the cluster module, run the following command,

    cd deployment/iac/aws/cluster/modules/05_helm_releases
    tofu init
    
  6. Generate the SSH key for CLI access

    To generate the SSH key for CLI access

    tofu output -raw user_svc_private_key > ~/.ssh/user_svc.pem
    chmod 600 ~/.ssh/user_svc.pem
    

2 - Installing PPC on Microsoft Azure

Steps to install PPC on Microsoft Azure

2.1 - Prerequisites

Ensure that the following prerequisites are met before deploying the Protegrity Provisioned Cluster (PPC).

Microsoft Azure Resource Providers

The following Microsoft Azure resource providers are registered.

  • Microsoft.ContainerService
  • Microsoft.Network
  • Microsoft.Compute
  • Microsoft.Storage
  • Microsoft.KeyVault
  • Microsoft.ManagedIdentity

Permissions to deploy AKS

Update the following custom role permissions.

Before you begin

  • Identify the resource group where the AKS cluster will be created.
  • Ensure that a custom role is already created in the subscription or resource group.
  • Complete this configuration before starting the AKS installation process.

To update the permission for the custom role, perform the following steps:

  1. Navigate to the required resource group in the Azure portal.

  2. Open Access control (IAM) for the selected resource group.

  3. Locate the existing custom role.

  4. Select the custom role and click Edit.

  5. Select JSON and click Edit.

    Update the role by adding the following permissions:

  {
    "id": "/subscriptions/<SUBSCRIPTION-ID>/providers/Microsoft.Authorization/roleDefinitions/<ROLE-DEFINITION-ID>",
    "properties": {
        "roleName": "<ROLE-NAME>",
        "description": "",
        "assignableScopes": [
            "/subscriptions/<SUBSCRIPTION-ID>/resourceGroups/<RG-Name>"
        ],
        "permissions": [
            {
                "Actions": [
                    "Microsoft.Authorization/roleAssignments/read",
                    "Microsoft.Authorization/roleAssignments/write",
                    "Microsoft.Authorization/roleDefinitions/read",
                    "Microsoft.Authorization/roleDefinitions/write",
                    "Microsoft.ContainerService/managedClusters/read",
                    "Microsoft.ContainerService/managedClusters/write",
                    "Microsoft.KeyVault/vaults/read",
                    "Microsoft.KeyVault/vaults/write",
                    "Microsoft.ManagedIdentity/userAssignedIdentities/assign/action",
                    "Microsoft.ManagedIdentity/userAssignedIdentities/read",
                    "Microsoft.Network/virtualNetworks/read",
                    "Microsoft.Network/virtualNetworks/subnets/join/action",
                    "Microsoft.Network/virtualNetworks/subnets/read",
                    "Microsoft.Resources/subscriptions/resourceGroups/read",
                    "Microsoft.Storage/locations/checknameavailability/read",
                    "Microsoft.Storage/storageAccounts/blobServices/containers/read",
                    "Microsoft.Storage/storageAccounts/blobServices/containers/write",
                    "Microsoft.Storage/storageAccounts/blobServices/read",
                    "Microsoft.Storage/storageAccounts/blobServices/write",
                    "Microsoft.Storage/storageAccounts/fileServices/read",
                    "Microsoft.Storage/storageAccounts/fileServices/write",
                    "Microsoft.Storage/storageAccounts/listKeys/action",
                    "Microsoft.Storage/storageAccounts/read",
                    "Microsoft.Storage/storageAccounts/write",
                    "Microsoft.Network/privateDnsZones/read",
                    "Microsoft.Network/privateDnsZones/A/read",
                    "Microsoft.Network/privateDnsZones/A/write",
                    "Microsoft.Network/privateDnsZones/write",
                    "Microsoft.Network/privateDnsZones/join/action",
                    "Microsoft.Network/privateDnsZones/virtualNetworkLinks/read",
                    "Microsoft.Network/privateDnsZones/virtualNetworkLinks/write",
                    "Microsoft.ContainerService/managedClusters/listClusterUserCredential/action",
                    "Microsoft.ContainerService/managedClusters/agentPools/read",
                    "Microsoft.ContainerService/managedClusters/agentPools/write",
                    "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write",
                    "Microsoft.KeyVault/vaults/read"
                ],
                "notActions": [],
                "dataActions": [],
                "notDataActions": []
            }
        ]
    }
}
  1. Click Save after updating the permissions.
  2. Click Review + update to finalise the changes.

Jump Box or Local Machine

A jump box serves as a secure, controlled access point for executing installation commands and managing cluster resources. It ensures that all operations originate from a trusted environment with direct network access to the PPC cluster, avoiding connectivity issues that may arise from local machines with restricted network paths or inconsistent tooling.

  • Use a dedicated Debian or Red Hat jump box created in Microsoft Azure. Do not use a jump box hosted on any other cloud.

  • The jump box must be provisioned in the same Azure region where the PPC cluster will be deployed to ensure proper connectivity and access to regional resources.

    For example, if the PPC cluster is deployed in eastus, the jump box must also be created in eastus. Placing the jump box in a different region, such as westeurope, may result in network access failures or latency issues when connecting to cluster endpoints.

Microsoft Azure Region

For automated installation

Identify the Azure region where the cluster is to be deployed.

The deployment region is automatically detected from the resource group’s location during the bootstrap process. Ensure that the resource group is created in the intended deployment region before running the installer.

All resources must be in the same region.
For more information about Microsoft Azure resources, refer to Microsoft Azure Resource IDs from Infrastructure Team.

For component-based installation

Identify the Azure region where the cluster is to be deployed.

Region must be specified as azure_location in the terraform.tfvars file during the 00_backup_storage and 02_aks_cluster stages.

All resources must be in the same region.
For more information about Microsoft Azure resources, refer to Microsoft Azure Resource IDs from Infrastructure Team.

Microsoft Azure Resource IDs from Infrastructure Team

Deployment Resource Group

Before proceeding with the installation, identify the Azure Resource Group where the cluster is to be deployed.

  • For automated deployment, the value of this resource group name must be specified during the input prompt while running the ./bootstrap.sh script.
  • For component-based deployment, the value of this resource group name must be specified in the resource_group_name field in the terraform.tfvars files, wherever required.

The following resources are provisioned within the resource group specified during deployment.

StageResources Created
00_Backup StorageStorage Account, Key Vault, Key Vault Key, Blob Container
01_IdentityRBAC Role Assignments (references existing UAMIs; no new resources created)
02_AKS ClusterAKS Cluster, Federated Credentials
03_Node PoolAKS User Node Pool
04_AKS AddonsStorage Classes, Cluster Add-ons
05_Helm ReleasesKubernetes Namespaces, Secrets, Helm Charts

Pre-existing Resources

The following resources must be provisioned by the IT team before installation.

They can reside in any resource group in the same region. The installer references each resource by its entire Azure resource ID.

Ensure the deploying identity, such as, service principal or managed identity, has the appropriate permissions on these resources.

ResourceDescriptionVariable in terraform.tfvarsExample Resource ID
AKS User-Assigned Managed IdentityIdentity used by the AKS cluster to interact with Azure resources such as Private DNS Zones and Virtual Networks.uami_id/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-applianceframework
Must have Private DNS Zone and VNet custom role permissions. For more information, refer to AKS User-Assigned Managed Identity Permissions.
Velero User-Assigned Managed IdentityIdentity used by Velero to access Azure Blob Storage for cluster backup and restore operations.velero_uami_id/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-velero
OpenSearch User-Assigned Managed IdentityIdentity used by OpenSearch to access required Azure resources for log storage and indexing.opensearch_uami_id/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-opensearch
Virtual Network / SubnetThe subnet within an existing Virtual Network where all AKS cluster nodes are placed.subnet_id/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<subnet>
Private DNS ZoneThe pre-existing private DNS zone used for resolving internal AKS API server endpoints within the Virtual Network.private_dns_zone_id/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/privateDnsZones/privatelink.eastus.azmk8s.io

AKS User-Assigned Managed Identity Permissions

The AKS User-Assigned Managed Identity (id-aks-applianceframework) must be granted a custom role with the following permissions on the resource group containing the Private DNS Zone and Virtual Network. These permissions enable AKS to manage private DNS records and join virtual networks during cluster operations.

To configure User-Assigned Managed Identity with a custom Azure role containing the permissions required for AKS deployment and management operations within the specified resource group, perform the following steps:

1. Creating a Custom Role

  1. In the Azure portal, navigate to Resource Groups.
  2. Select the resource group that contains the AKS resources.
  3. Open Access Control (IAM).
  4. Select Add > Add custom role.
  5. Provide a name and description for the custom role.
  6. Select JSON and add the following permissions.
{
  "Name": "<ROLE-NAME>",
  "Description": "",
  "AssignableScopes": [
    "/subscriptions/<SUBSCRIPTION-ID>/resourceGroups/<RESOURCE-GROUP>"
  ],
  "Actions": [
    "Microsoft.Network/privateDnsZones/read",
    "Microsoft.Network/privateDnsZones/A/read",
    "Microsoft.Network/privateDnsZones/A/write",
    "Microsoft.Network/privateDnsZones/A/delete",
    "Microsoft.Network/privateDnsZones/virtualNetworkLinks/read",
    "Microsoft.Network/privateDnsZones/virtualNetworkLinks/write",
    "Microsoft.Network/privateDnsZones/virtualNetworkLinks/delete",
    "Microsoft.Network/virtualNetworks/subnets/read",
    "Microsoft.Network/virtualNetworks/subnets/join/action",
    "Microsoft.Network/privateDnsZones/write",
    "Microsoft.Network/virtualNetworks/join/action"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": []
}
  1. Review the permissions and create the custom role.

Note: These permissions are required when using a private AKS cluster with a pre-existing Private DNS Zone (private_dns_zone_id). Without them, cluster provisioning and DNS resolution will fail.

2. Assigning the custom role to the Managed Identity

  1. On the Azure portal, navigate to Managed Identities.

  2. Select Create.

  3. Specify the following:

    • Subscription
    • Resource group
    • Managed identity name
    • Region
  4. Select Review + Create and then Create.

    Wait for the User-Assigned Managed Identity (UAMI) to be provisioned.

  5. Open the newly created User-Assigned Managed Identity.

  6. Select Azure role assignments.

  7. Select Add role assignment.

  8. Set the scope to the target resource group.

  9. Select the custom role created in the previous section.

  10. Assign the role to the User-Assigned Managed Identity.

  11. Verify that the role assignment appears under the managed identity’s role assignments.

Zone Requirements

The cluster requires a minimum of two availability zones for high availability. Three-zone cluster deployments are supported and recommended for production.

No. of ZonesSupportedNotes
1NoInstallation fails.
2YesMinimum requirement for High Availability.
3YesRecommended for production environments.

Ensure the following requirements are met before deploying:

RequirementDetail
Region supportThe target Azure region must support availability zones.
VM SKU availabilityThe chosen VM size must be available in all the specified zones.

Modules: 02_aks_cluster, 03_node_pool

Note: The bootstrap script does not prompt for zone selection, it uses the default three zone configuration.

The default zone configuration is ["1", "2", "3"]. Not all Azure regions support three availability zones, and not all VM SKUs are available in every zone. Using a zone that does not support your VM SKU causes cluster creation to fail.

Important: system_node_pool_zones (module 02) and node_pool_zones (module 03) must use the same set of zones. If the zones differ, disks provisioned in one zone cannot be attached to nodes rescheduled into another zone.

Before deploying, verify zone and VM SKU availability:

# List availability zones for your region
az account list-locations \
  --query "[?name=='<region>'].{Region:name, Zones:availabilityZoneMappings}" \
  -o table

# Check which zones support your VM SKU
az vm list-skus \
  --location <region> \
  --size Standard_D4ds_v4 \
  --query "[].{Name:name, Zones:locationInfo[0].zones}" \
  -o table

Replace <region> with your Azure region, for example eastus.

If zone adjustment is required, navigate to iac/azure/cluster/modules and set matching values in both terraform.tfvars files:

# 02_aks_cluster/terraform.tfvars
system_node_pool_zones = ["1", "2"]    # adjust to the zones your region supports

# 03_node_pool/terraform.tfvars
node_pool_zones = ["1", "2"]           # must match system_node_pool_zones exactly

For more information on editing the 02_aks_cluster, and 03_node_pool modules, refer to Manual component-based installation.

System node pool sizing

The step [1b] Select Node Architecture in the bootstrap script prompts to select the node architecture interactively during deployment.

The default system node pool VM size (Standard_D2ds_v4, 2 vCPU / 8 GiB RAM) can become resource-constrained under production load when Karpenter, CoreDNS, and CSI drivers run concurrently on the same node. Use the following or larger for production system node pools.

amd64 (x86-64)

Node PoolVM SizevCPUsMemory
SystemStandard_D2as_v528 GB
UserStandard_D8as_v5832 GB

arm64

Node PoolVM SizevCPUsMemory
SystemStandard_D2ps_v528 GB
UserStandard_D8ps_v5832 GB

In 02_aks_cluster/terraform.tfvars, edit the following value:

system_node_pool_vm_size = "Standard_D4ds_v5"   # or Standard_D8ds_v4 for heavier loads

For more information on editing the 02_aks_cluster module, refer to Manual component-based installation.

AKS cluster tier

The sku_tier setting controls the AKS API server uptime SLA, available node capacity, and supported features.

TierUptime SLANotes
FreeNo SLASuitable for development and testing only
Standard99.9% (99.95% with Availability Zones)Recommended for production
Premium99.9% (99.95% with Availability Zones) + LTSRequired if long-term support is needed

Set sku_tier = "Standard" for all production deployments. Use "Premium" if your organization requires long-term support (LTS) guarantees.

In 02_aks_cluster/terraform.tfvars, edit the following value:

sku_tier = "Standard"

For more information on editing the 02_aks_cluster module, refer to Manual component-based installation.

2.2 - Preparing for PPC deployment

Downloading and extracting the Protegrity Cluster Template (PCT) for deploying PPC

The Protegrity Cluster Template (PCT) is a pre-packaged deployment archive that contains the infrastructure-as-code scripts, Helm charts, and bootstrap tooling required to provision a PPC on your target cloud platform. It automates the creation of the Kubernetes cluster, networking, identity configuration, and installation of Protegrity microservices. Download and extract the PCT on your jump box before starting the deployment process.

Note: If there is an existing cluster from a previous install, clean up your local repository on the jump box and any existing clusters by running ./bootstrap.sh --cloud azure destroy from /deployment before proceeding.

During installation, the system may prompt for the system password and require sign-in to Microsoft Azure. If the Azure CLI is not already logged in, the bootstrap script automatically runs az login --use-device-code. A device-code prompt similar to the following appears.

[YYYY-MM-DD HH:MM:SS] Azure CLI not logged in. Triggering az login...
To sign in, use a web browser to open the page https://login.microsoft.com/device and enter the code XXXXXXXX to authenticate.

To sign-in to Microsoft Azure, perform the following steps:

  1. Open the displayed URL in a browser, and enter the code shown in the terminal.
  2. Complete the SSO sign-in and follow the on-screen instructions.
  3. After successful authentication, the script continues automatically.

To download and extract PCT, perform the following steps:

  1. Log in to the My.Protegrity portal.

  2. Navigate to Product Management > Explore Products > AI Team Edition > Platform & Features.

  3. Navigate to Platform Installation.

  4. From the Actions column for Protegrity Provisioned Cluster, click the Download Product icon to download the PPC 1.1 archive.

  5. Create a deployment_110 directory on the jumpbox.

    mkdir deployment_110 && cd deployment_110
    
  6. Copy the PCT to the deployment_110 directory on the jump box.

  7. Extract the PCT.

    tar -xvf PPC-K8S-ALL_1.1.0.97.tar
    

2.3 - Deploying PPC

Steps to deploy the PPC cluster

By default, the PCT is configured to deploy a FIPS-enabled cluster using FIPS-compliant node OS images.

Non-FIPS deployment: Before proceeding with the installation, complete the steps in Configuring PPC for Non-FIPS Deployment on Microsoft Azure to modify the required Terraform configuration files. Then proceed with either the automated or component-based installation below.

FIPS deployment: No additional configuration is required. Proceed directly with either the automated or component-based installation below.

The PPC cluster can be deployed using one of the following methods:

Automated script-based installation: This method requires the bootstrap.sh script to deploy the PPC cluster. The script installs the required software and dependencies, prompts to provide the required information, and deploys the cluster automatically.

Manual component-based installation: This method requires to perform the deployment of each component to install the PPC cluster. The configuration files are edited to provide the required information and then deploy the cluster.

Note: A PPC can be deployed in regions where minimum two zones are present.

2.3.1 - Production configuration

Review and override these settings before deploying to production for high availability, data safety, and security compliance.

The default terraform.tfvars values are optimized for development and staging environments. Before deploying to production, override the settings below to ensure high availability, data safety, and security compliance.

Applying the changes

  • Script-based installation: After the bootstrap script generates the terraform.tfvars files, edit them before the script runs tofu apply, or modify and re-apply individually using OpenTofu after installation.

  • Component-based installation: Edit the relevant terraform.tfvars for each module before running tofu apply.

Storage redundancy

Modules: 00_backup_storage, 04_aks_addons

By default, the backup storage account uses Locally Redundant Storage (LRS), which stores data only within a single datacenter. When AKS nodes span multiple availability zones, an LRS-backed disk cannot be reattached to a node in a different zone during failover, causing pod scheduling to fail.

Recommendations:

  • Use ZRS (Zone-Redundant Storage) when nodes are spread across availability zones in the same region.
  • Use GRS (Geo-Redundant Storage) if cross-region disaster recovery is required.
  • Use Premium_ZRS as the storage class for Kubernetes persistent volumes.

In 00_backup_storage/terraform.tfvars:

storage_account_replication_type = "ZRS"   # use "GRS" for cross-region redundancy

System node pool sizing

Module: 02_aks_cluster

The default system node pool VM size (Standard_D2ds_v4, 2 vCPU / 8 GiB RAM) can become resource-constrained under production load when Karpenter, CoreDNS, and CSI drivers run concurrently on the same node.

Recommendation: Use Standard_D4ds_v4 (4 vCPU / 16 GiB) or larger for production system node pools.

In 02_aks_cluster/terraform.tfvars, edit the following value:

system_node_pool_vm_size = "Standard_D4ds_v4"   # or Standard_D8ds_v4 for heavier loads

Key Vault SKU

Module: 00_backup_storage

The default Key Vault SKU is standard, which uses software-protected keys. For organizations with compliance requirements (such as FIPS 140-2 Level 2 or Level 3), the premium SKU provides HSM-backed encryption keys.

Recommendation: Use premium when your security or compliance policy requires HSM-backed key protection.

In 00_backup_storage/terraform.tfvars:

key_vault_sku = "premium"

Note: Confirm with your compliance team whether HSM-backed keys are required before changing this setting. The premium SKU incurs additional Azure costs.

Availability zones

Modules: 02_aks_cluster, 03_node_pool

The default zone configuration is ["1", "2", "3"]. Not all Azure regions support three availability zones, and not all VM SKUs are available in every zone. Using a zone that does not support your VM SKU causes cluster creation to fail.

Important: system_node_pool_zones (module 02) and node_pool_zones (module 03) must use the same set of zones. If the zones differ, disks provisioned in one zone cannot be attached to nodes rescheduled into another zone.

Before deploying, verify zone and VM SKU availability:

# List availability zones for your region
az account list-locations \
  --query "[?name=='<region>'].{Region:name, Zones:availabilityZoneMappings}" \
  -o table

# Check which zones support your VM SKU
az vm list-skus \
  --location <region> \
  --size Standard_D4ds_v4 \
  --query "[].{Name:name, Zones:locationInfo[0].zones}" \
  -o table

Replace <region> with your Azure region, for example eastus.

In both 02_aks_cluster/terraform.tfvars and 03_node_pool/terraform.tfvars, set matching values:

# 02_aks_cluster/terraform.tfvars
system_node_pool_zones = ["1", "2"]    # adjust to the zones your region supports

# 03_node_pool/terraform.tfvars
node_pool_zones = ["1", "2"]           # must match system_node_pool_zones exactly

AKS cluster tier (sku_tier)

Module: 02_aks_cluster

The sku_tier setting controls the AKS API server uptime SLA, available node capacity, and supported features.

TierUptime SLANotes
FreeNo SLASuitable for development and testing only
Standard99.9% (99.95% with Availability Zones)Recommended for production
Premium99.9% (99.95% with Availability Zones) + LTSRequired if long-term support is needed

Recommendation: Set sku_tier = "Standard" for all production deployments. Use "Premium" if your organization requires long-term support (LTS) guarantees.

In 02_aks_cluster/terraform.tfvars:

sku_tier = "Standard"

Note: Standard and Premium tiers incur an additional hourly cost per cluster. See the AKS pricing page for current rates.

Storage account network access

Module: 00_backup_storage

The backup storage account is created with public network access enabled by default. In production, restrict access using your organization’s existing network controls.

Azure provides three options:

MethodIsolation levelTypical use
Private EndpointsAssigns the storage account a private IP inside your VNet. Removes it from public internet.Recommended for most enterprise deployments.
VNet service endpointsRoutes traffic through the VNet without a private IP.Lower cost alternative to Private Endpoints.
Azure Firewall / NSGNetwork-layer traffic filtering.Supplement to either option above.

Apply the appropriate controls after deployment. The example below uses the service endpoint approach:

# Allow access from a specific VNet subnet
az storage account network-rule add \
  --account-name <storage-account-name> \
  --resource-group <resource-group> \
  --vnet-name <vnet-name> \
  --subnet <subnet-name>

# Deny all other public access
az storage account update \
  --name <storage-account-name> \
  --resource-group <resource-group> \
  --default-action Deny

Note: Consult your organization’s security team to select the appropriate access control method before deploying to production.

SettingDefaultProduction recommendationModule
storage_account_replication_typeLRSZRS or GRS00_backup_storage
system_node_pool_vm_sizeStandard_D2ds_v4Standard_D4ds_v4 or larger02_aks_cluster
key_vault_skustandardpremium (if HSM required)00_backup_storage
system_node_pool_zones["1","2","3"]Verify per region/SKU; match node_pool_zones02_aks_cluster
node_pool_zones["1","2","3"]Must match system_node_pool_zones03_node_pool
sku_tierFreeStandard or Premium02_aks_cluster
Storage account network accessPublic (default)Private Endpoints, VNet service endpoints, or FirewallPost-deploy

2.3.2 - Configuring PPC for Non-FIPS Deployment on Microsoft Azure

Complete the steps provided in this section to configure the Protegrity Cluster Template (PCT) for a non-FIPS PPC deployment on Azure AKS.

Before you begin

The following files require changes:

FileSettingValue
deployment/iac/azure/cluster/modules/02_aks_cluster/terraform.tfvarsfips_enabledfalse
deployment/iac/azure/cluster/modules/03_node_pool/terraform.tfvarsfips_enabledfalse

Configuring PPC for Non-FIPS Deployment on Azure

For a non-FIPS PPC deployment on Azure AKS, perform the following steps:

  1. Disable FIPS in the AKS Cluster Module.

a. Navigate to the 02_aks_cluster module.

cd iac/azure/cluster/modules/02_aks_cluster/

b. Edit the terraform.tfvars file. Locate the fips_enabled parameter and set it to false.

fips_enabled                  = false

c. Save the file and exit the editor.

  1. Disable FIPS in the Node Pool Module.

a. Navigate to the 03_node_pool module.

cd iac/azure/cluster/modules/03_node_pool/

b. Edit the terraform.tfvars file. Locate the fips_enabled parameter and set it to false.

fips_enabled                  = false

c. Save the file and exit the editor.

After saving all these configuration changes, proceed with deploying the cluster using one of the following methods:

Note: The Script-based and Component-based installation instructions reference default FIPS-enabled settings. When following either installation method, do not revert or overwrite the values configured on this page. Keep fips_enabled set to false in 02_aks_cluster and 03_node_pool.

2.3.3 - Automated script-based installation

Complete the steps provided in this section to deploy PPC in Microsoft Azure AKS.

Before you begin

  • Ensure that all the required resources are in the same resource-group. If the resources are in different resource groups, then ensure to move the resources to the same group before proceeding for PPC deployment.

  • The repository provides a bootstrap script that automatically installs or updates the following tools on the jump box:

    • Azure CLI - Required to communicate with your Microsoft Azure account.
    • Helm - Required to manage Kubernetes packages.
    • jq - Required to parse JSON.
    • kubectl - Required to communicate with the Kubernetes cluster.
    • OpenTofu - Required to manage infrastructure as code.
    • oras: Required to pull non‑container, generic OCI artifacts from the registry that are not handled by standard container tooling.

Note: If you are performing a non-FIPS deployment, ensure that you have already completed the steps in the section Configuring PPC for Non-FIPS Deployment on Microsoft Azure before proceeding. Do not revert fips_enabled to true or change node_os back to a FIPS-compliant image during the steps below.

Architecture Selection

The step [1b] Select Node Architecture in the bootstrap script prompts to select the node architecture interactively during deployment.

  • amd64 (x86-64)
Node PoolVM SizevCPUsMemory
SystemStandard_D2as_v528 GB
UserStandard_D8as_v5832 GB
  • arm64
Node PoolVM SizevCPUsMemory
SystemStandard_D2ps_v528 GB
UserStandard_D8ps_v5832 GB

The bootstrap script prompts you to select the node architecture interactively during deployment (step 1b).

Deploying the PPC

The bootstrap script prompts for variables to be set to complete the deployment. Run the following command and follow the instructions on the screen.

./bootstrap.sh --cloud azure

The script prompts for the following variables.

  1. Enter AKS Cluster Name

    The following characters are allowed:

    • Lowercase letters: a-z
    • Numbers: 0-9
    • Hyphens: -

    The following characters are not allowed:

    • Uppercase letters: A-Z
    • Underscores: _
    • Spaces
    • Any special characters such as: / ? * + % ! @ # $ ^ & ( ) = [ ] { } : ; , .
    • Leading or trailing hyphens
    • Names longer than 10 characters (the cluster name must be 10 characters or fewer)

    Note: Ensure that the cluster name does not exceed 10 characters. Cluster names longer than this limit can cause the bootstrap script to fail in subsequent installation steps. If the installation fails because the cluster name exceeds the 10-character limit, correct the name and re-run the script.

    • Correction: Choose a cluster name with 31 characters or fewer.
    • Retry: Execute the installation command again with the updated name. The script will automatically handle the update and proceed with the bootstrap process.

    After the cluster name is accepted, the script prompts you to select the node architecture.

    [1b] Select Node Architecture

    [1b] Select Node Architecture
      1) amd64 (x86_64) — e.g. Standard_D8as_v5
      2) arm64 (ARM/Ampere) — e.g. Standard_D8ps_v5
    

    Enter 1 to select amd64 or 2 to select arm64.

    Note: Select amd64 for standard Intel/AMD 64-bit environments. Select arm64 for ARM-based environments such as AWS Graviton instances.

  2. Querying for available Resource Groups

    The script queries for the available Resource Groups.

    Enter the Resource Group name from the table []

    The script then automatically detects the location and subscription ID of the resource group.

  3. Enter UAMI Resource ID

    Provide the complete Azure resource ID for the UAMI used by AKS in the following format:

    /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<identity-name>
    

    The UAMI client ID is detected automatically.

  4. Enter AKS Subnet Resource ID

    Provide the complete resource ID of the pre-existing subnet used for AKS nodes in the following format:

    /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Network/virtualNetworks/<vnet-name>/subnets/<subnet-name>
    
  5. Enter Private DNS Zone Resource ID

    Provide the Private DNS zone ID used by the AKS private cluster in the following format:

    /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Network/privateDnsZones/privatelink.<region>.azmk8s.io
    

    The script attempts to automatically detect network settings:

    • Virtual network address space
    • Service CIDR
    • DNS service IP

    If the detection fails, then default values configured in the terraform.tfvars file are used.

  1. Enter FQDN [name.domain.com]

    This is the Fully Qualified Domain Name for the ingress.

    Warning: Ensure that the FQDN does not exceed 50 characters and only the following characters are used:

    • Lowercase letters: a-z
    • Numbers: 0-9
    • Special characters: - .
  2. Storage Account and Key Vault provisioning

    Choose whether to use existing resources or create new resources:

    1) Use existing
    2) Provision new via Tofu
    
    • Enter 1 if an encrypted Storage Account and Key Vault are already provisioned for this cluster. The installer prompts for the Storage Account name, Key Vault name, backup container, Key Vault key name, and the Velero UAMI Resource ID.

    • Enter 2 to allow the installer to create a new Storage Account and Key Vault with the velero container, the pty-backup-key encryption key, and a Velero UAMI automatically. Only the new resource names are required.

  3. Enter Velero UAMI Resource ID (required)

    Enter the resource ID of the dedicated Velero User-Assigned Managed Identity (UAMI) in the format:

    /subscriptions/<subscription-id>/resourceGroups/<velero-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name>
    

    The script automatically validates the UAMI and detects the UAMI Client ID.

  4. Enter OpenSearch UAMI Resource ID (required)

    Enter the resource ID of the OpenSearch Velero User-Assigned Managed Identity (UAMI) in the format:

    /subscriptions/<subscription-id>/resourceGroups/<opensearch-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name>
    

    The script automatically validates the UAMI and detects the UAMI Client ID.

  5. Enter Image Registry Endpoint

The image repository from where the container images are retrieved.

Expected format: <hostname>[:port].

Do not include ‘https://’

  1. Enter Registry Username

Enter the username for the registry mentioned in the previous step. Leave this entry blank if the registry does not require authentication.

  1. Enter Registry Password or Access Token

Enter Password or Access Token for the registry.

Input is masked with * characters. Press Enter to keep the current value.

Leave this entry blank if the registry does not require authentication.

  1. Enter Owner Email (for cluster tagging)

Enter email address in the format name@domain.tld. This email is used for the cluster ‘Owner’ tag and the platform owner contact.

Note: The cluster creation process can take 10-15 minutes.

If the session is terminated during installation due to network issues, power outage, and so on, then the installation stops. To restart the installation, run the script again:

# Navigate to setup directory 
./bootstrap.sh --cloud azure

After the bootstrap script is completed, verify the cluster and workloads using the following commands:

# Confirm nodes are Ready
kubectl get nodes

# Confirm NFA workloads are Running
kubectl get pods -A

2.3.4 - Manual component-based installation

Complete the steps provided in this section to update the configuration files and deploy PPC in Microsoft Azure AKS.

This section is intended for enterprise customers who need full control over each stage of the AKS cluster deployment. Use this path when individual infrastructure stages must be reviewed or approved separately, when integration with an existing CI/CD pipeline is required, or when corporate change-management controls prevent running an all-in-one automated script. Each stage is self-contained and can be executed by different teams on the same jump box.

Before deploying to production: The default values are optimized for development and staging. Review the Production configuration section to override settings for high availability, data safety, and security compliance before running tofu apply.

Note: If you are performing a non-FIPS deployment, ensure you have already completed Configuring PPC for Non-FIPS Deployment on Microsoft Azure before proceeding. Do not revert fips_enabled to true when performing the following steps.

Deploying PPC using component-based installation

To install PPC, complete the following steps in order. Each step is described in detail in the sections below.

StepActionDescription
1Installing the toolsInstalls all required CLI tools (OpenTofu, Azure CLI, kubectl, Helm, and others) on the jump box, either automatically via bootstrap.sh install-tools --cloud azure or manually.
2Authenticating with Azure CLIAuthenticates with Azure using az login and verifies access to the target subscription, resource group, managed identities, subnet, and private DNS zone.
3Downloading and extracting the release PCTDownloads and extracts the PPC release archive on the jump box.
4Provisioning backup storage and key vault(Skip if using existing resources) Provisions a new Azure Storage Account, Blob container, Key Vault, and encryption key for storing PPC backup data using the 00_backup_storage Terraform module.
5Filling in each module’s terraform.tfvarsConfigures and applies five Terraform modules in sequence to provision all PPC infrastructure components.
5a01_identity moduleCreates RBAC role assignments for the pre-existing User-Assigned Managed Identities (UAMIs) required by AKS, Velero, and OpenSearch.
5b02_aks_cluster moduleProvisions the private AKS cluster with a system node pool, configures networking (Azure CNI Overlay and Cilium), enables Workload Identity, and creates federated identity credentials for Velero and OpenSearch.
5c03_node_pool moduleCreates a user node pool for application workloads with the specified VM size, architecture, and availability zone configuration.
5d04_aks_addons moduleCreates default and backup Kubernetes storage classes using Azure Managed Disks (Premium LRS) and removes the built-in default storage class annotation.
5e05_helm_releases moduleDeploys all PPC platform Helm charts including Velero, NFA/Eclipse, Insight, Reloader, and Envoy Gateway. This step may take 15–20 minutes.
6Verifying the installationConfirms all cluster nodes are in Ready state and all pods are in Running state.

Before you begin

Ensure to have the following prerequisites before proceeding with the installation.

Access and permissions

RequirementDetails
Azure RBACContributor and User Access Administrator on the target subscription or resource group.
Jump boxDebian or Red Hat VM in Azure with internet access to pull the release archive.

Required Roles

The Azure principal must have AKS cluster admin access.

The required Azure RBAC Roles are listed in the following table:

RoleScopeUsed by
ContributorResource groupCreate AKS cluster, node pool, storage account, Key Vault
User Access AdministratorResource groupCreate role assignments (module 01)
Storage Blob Data ContributorBackup storage accountAccess state files in backend, upload module 00 state
Key Vault AdministratorKey VaultCreate Key Vault and keys (module 00)
AKS Cluster AdminAKS clusterKubernetes API access for Helm, kubectl operations (modules 04, 05)

Deployment Resource Group

All resources created by the installer are provisioned in a single Azure resource group specified using resource_group_name in each terraform.tfvars file. This resource group must exist before running the installer.

The following resources are created inside this resource group.

StageResources Created
00_Backup StorageStorage Account, Key Vault, Key Vault Key, Blob Container
01_IdentityRBAC Role Assignments (references existing UAMIs; no new resources created)
02_AKS ClusterAKS Cluster, Federated Credentials
03_Node PoolAKS User Node Pool
04_AKS AddonsStorage Classes, Cluster Add-ons
05_Helm ReleasesKubernetes Namespaces, Secrets, Helm Charts

Installing the tools

After downloading and extracting the PPC-K8S-ALL_1.1.0.97.tar, run the following command to install the required tools.

./bootstrap.sh install-tools --cloud azure

Alternatively, the following tools must be installed and available on the jumpbox before starting:

Tool NameDescriptionVersion
OpenTofuOpen-source Terraform fork used to provision and manage infrastructureOpenTofu v1.11.5
Azure CLICommand-line tool for managing Azure resources2.88.0
kubectlKubernetes command-line tool for interacting with the clusterv1.36.3
HelmKubernetes package manager for deploying Helm chartsv3.21.3+g1ad6e68
skopeoTool for inspecting and copying container images between registriesskopeo version 1.18.0
jqLightweight command-line JSON processorjq-1.7
bcArbitrary-precision calculator used in shell scriptsbc 1.07.1
ssh-keygenTool for generating SSH key pairs used for secure accessOpenSSH_10.0p2 Debian-7+deb13u4, OpenSSL 3.5.6 7 Apr 2026
orasOCI Registry As Storage client for pushing and pulling artifacts1.3.3
cmctlCommand-line tool for managing cert-manager resourcesv2.5.0

Values to collect before starting

Gather the following values before populating each stage terraform.tfvars in Step 4.

ValueDescriptionExample
Cluster nameName of the AKS cluster to create or manage.my-aks-cluster
Resource groupAzure resource group containing the AKS cluster and related resources.rg-aks-prod
Azure subscription IDUnique identifier of the Azure subscription used for deployment.<subscription-id>
Azure regionAzure region where the cluster and resources are deployed.eastus
AKS UAMI resource IDFull resource ID of the user-assigned managed identity for AKS appliance framework workloads./subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-applianceframework
AKS subnet resource IDFull resource ID of the virtual network subnet where AKS nodes are deployed./subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<subnet>
Private DNS zone resource IDFull resource ID of the private DNS zone used for AKS private cluster name resolution./subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/privateDnsZones/privatelink.eastus.azmk8s.io
Storage account nameAzure Storage Account used for Velero backups and Terraform remote state.existing name or provisioned in Step 3
Backup container nameBlob container within the storage account used by Velero for cluster backups.velero
Key Vault nameAzure Key Vault that holds the backup encryption key.existing name or provisioned in Step 3
Key Vault key nameName of the encryption key inside the Key Vault used by Velero.pty-backup-key
Velero UAMI resource IDFull resource ID of the user-assigned managed identity for Velero backup and restore operations./subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-velero
OpenSearch UAMI resource IDFull resource ID of the user-assigned managed identity for OpenSearch workload identity./subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-opensearch
Ingress FQDNFully qualified domain name used by the ingress controller to expose cluster services externally.myapp.example.com
Image registry endpointEndpoint of the container image registry from which cluster images are pulled.registry.example.com
Registry username & passwordCredentials for authenticating with the container image registry.provided by the team

Deploying the PPC

To deploy the PPC using component-based installation, perform the following steps:

1. Authenticating with Azure CLI

To authenticate with the Azure CLI on the jump box, run the following command.

az login
az account show

Ensure the target subscription, resource group, managed identities, subnet, and private DNS zone are accessible before continuing.

2. Downloading and extracting the release PCT

To download and extract the PCT, refer to Preparing for PPC deployment.

3. Provisioning backup storage and key vault

This is an optional step.

Note: Skip this step if an Azure Storage Account, backup container, Key Vault, and key already exist for this cluster. Note these values. They will be needed in next steps.

  1. Navigate to the 00_backup_storage directory.
cd iac/azure/cluster/modules/00_backup_storage
  1. Open terraform.tfvars and fill in the required values.
    resource_group_name    = "<resource-group>"
    aks_cluster_name       = "<cluster-name>"
    storage_account_name   = "<storage-account-name>"
    storage_container_name = "velero"
    key_vault_name         = "<key-vault-name>"
    key_name               = "pty-backup-key"

    azure_subscription_id = "<subscription-id>"
    azure_location        = "<region>"        # e.g. eastus
  1. Save the file and exit the editor.

  2. To apply the terraform configuration, run the following command.

    tofu init
    tofu plan          # review the role assignments that will be created
    tofu apply         # type "yes" when prompted
  1. Note the Storage Account, container, Key Vault, and key values for future steps.

4. Filling in each module’s terraform.tfvars

Each module under iac/azure/cluster/modules/ contains its own terraform.tfvars file. There is no single shared configuration file, so the terraform.tfvars file in every module must be updated before running the deployment.

Verify that the following values are the same across all modules:

  • resource_group_name
  • aks_cluster_name
  • azure_subscription_id
  • storage_account_name
  • storage_container_name
  1. 01_identity module

This stage creates RBAC role assignments for the pre-existing User-Assigned Managed Identities (UAMIs) required by AKS, Velero, and OpenSearch.

ResourcePurpose
Managed Identity Operator roleAllows AKS to assign the UAMI to nodes
Virtual Machine Contributor roleAllows AKS to manage VMs in the node resource group
Disk Snapshot Contributor roleAllows Velero to create and manage disk snapshots
Storage Blob Data Contributor (Velero)Allows Velero to read/write backup blobs
Key Vault Crypto User roleAllows Velero to encrypt/decrypt backups with the Key Vault key
Storage Blob Data Contributor (OpenSearch)Allows OpenSearch to store snapshot data in blob storage

To update the 01_identity module, perform the following steps.

a. Navigate to the iac/azure/cluster/modules/01_identity/ directory.

    cd iac/azure/cluster/modules/01_identity/

b. Edit the terraform.tfvars file to provide the required values.

    resource_group_name    = "<resource-group>" # e.g. "aks-rg-prod"
    aks_cluster_name       = "<cluster-name>" # e.g. "prod-aks-cluster"
    azure_subscription_id  = "<subscription-id>" # e.g. "1e9ef7b6-cdc4-4a6b-98f7-a408ac1e19e0"
    storage_account_name   = "<storage-account-name>" # e.g. "myclusterstateaccount"
    storage_container_name = "velero"

    # -------------------------------------------------
    # Pre-existing managed identities (provided by IT)
    # -------------------------------------------------
    uami_id = "</subscriptions/<subscription-id>/resourceGroups/<it-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-applianceframework>"

    velero_uami_id = "</subscriptions/<subscription-id>/resourceGroups/<velero-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-velero>" # required

    opensearch_uami_id = "</subscriptions/<subscription-id>/resourceGroups/<opensearch-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/aks-opensearch-identity>" # required

    # -------------------------------------------------
    # Key Vault (leave empty to skip KV role assignment)
    # -------------------------------------------------
    key_vault_name = "<key-vault-name>" # e.g. "my-key-vault"

c. Save the file and exit the editor.

d. To initialise, plan, and apply the changes, run the following commands.

    tofu init
    tofu plan          # review the role assignments that will be created
    tofu apply         # type "yes" when prompted

e. To verify the resources created in this stage, run the following commands

For AKS UAMI:

# Retrieve the Principal ID of the AKS User-Assigned Managed Identity (UAMI)
az identity show \
  --ids "<uami-resource-id>" \
  --query principalId \
  --output tsv
#Use the returned Principal ID to verify the role assignments:
az role assignment list \
  --assignee "<aks-uami-principal-id>" \
  --output table

For Velero UAMI

# Retrieve the Principal ID of the Velero UAMI
az identity show \
  --ids "<velero-uami-principal-id>" \
  --query principalId \
  --output tsv
#Use the returned Principal ID to verify the role assignments:
az role assignment list \
  --assignee "<velero-uami-principal-id>" \
  --output table

For OpenSearch UAMI

# Retrieve the Principal ID of the OpenSearch UAMI
az identity show \
  --ids "<opensearch-uami-principal-id>" \
  --query principalId \
  --output tsv
#Use the returned Principal ID to verify the role assignments:
az role assignment list \
  --assignee "<opensearch-uami-principal-id>" \
  --output table
  1. 02_aks_cluster module

This stage provisions the private AKS cluster with a system node pool, configures networking (Azure CNI Overlay and Cilium), enables Workload Identity, and creates federated identity credentials for Velero and OpenSearch.

ResourcePurpose
AKS clusterPrivate Kubernetes control plane with OIDC issuer and Workload Identity enabled
System node pool2-node pool for core Kubernetes components (CoreDNS, metrics-server, etc.)
Federated credential (Velero)Allows the Velero service account to authenticate as the Velero UAMI
Federated credential (OpenSearch)Allows the OpenSearch service account to authenticate as the OpenSearch UAMI
Kubeconfig contextAuto-configures kubectl access to the new cluster

To update the 02_aks_cluster module, perform the following steps.

a. Navigate to the iac/azure/cluster/modules/02_aks_cluster/ directory.

    cd iac/azure/cluster/modules/02_aks_cluster/

Note (Non-FIPS deployment): If you are deploying a non-FIPS cluster, ensure fips_enabled remains false as configured in the section Configuring PPC for Non-FIPS Deployment on Microsoft Azure. Do not change this value to true.

b. Edit the terraform.tfvars file to provide the required values.

    resource_group_name    = "<resource-group>" # e.g. "aks-rg-prod"
    aks_cluster_name       = "<cluster-name>" # e.g. "prod-aks-cluster"
    azure_subscription_id  = "<subscription-id>" # e.g. "1e9ef7b6-cdc4-4a6b-98f7-a408ac1e19e0"
    storage_account_name   = "<storage-account-name>" # e.g. "myclusterstateaccount"
    storage_container_name = "velero"

    # -------------------------------------------------
    # Identity (UAMI for kubelet and federated credentials)
    # -------------------------------------------------
    uami_id            = "</subscriptions/<subscription-id>/resourceGroups/<it-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-applianceframework>" # full UAMI resource ID (same as Stage 01)
    velero_uami_id     = "</subscriptions/<subscription-id>/resourceGroups/<velero-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/id-aks-velero>" # full Velero UAMI resource ID (for federated credential)
    opensearch_uami_id = "</subscriptions/<subscription-id>/resourceGroups/<opensearch-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/aks-opensearch-identity>" # full OpenSearch UAMI resource ID (for federated credential)

    # -------------------------------------------------
    # Cluster
    # -------------------------------------------------
    azure_location      = "<region>" # e.g. "eastus"  (auto-detected from resource group)
    subnet_id           = "</subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<subnet>>" # e.g. "/subscriptions/.../subnets/snet-aks-applianceframework"
    private_dns_zone_id = "</subscriptions/<subscription-id>/resourceGroups/<dns-resource-group>/providers/Microsoft.Network/privateDnsZones/privatelink.eastus.azmk8s.io>" # e.g. "/subscriptions/.../privateDnsZones/privatelink.eastus.azmk8s.io"

    # -------------------------------------------------
    # Networking (service CIDR + DNS IP)
    # -------------------------------------------------
    service_cidr   = "<10.0.0.0/16>" # auto-derived by updatevartf.sh (non-overlapping with the VNet)
    dns_service_ip = "<10.220.0.10>" # auto-derived: the .10 host of the chosen service_cidr
    pod_cidr       = "<10.0.0.0/16>" # auto-derived: non-overlapping with the VNet and service_cidr

    # -------------------------------------------------
    # System node pool
    # -------------------------------------------------
    architecture                  = "amd64" # amd64 or arm64
    system_node_pool_vm_size      = ""      # leave empty to auto-select based on architecture
    system_node_pool_node_count   = 2
    system_node_pool_disk_size_gb = 50
    system_node_pool_os_sku       = "AzureLinux"
    system_node_pool_zones        = ["1", "2", "3"]
    fips_enabled                  = true # set false for a non-FIPS node OS image (immutable)

    # -------------------------------------------------
    # Ownership / tagging
    # -------------------------------------------------
    owner_email                   = "<name@domain.tld>" # optional; blank = auto-detect from the Azure CLI identity

c. Save the file and exit the editor.

d. To initialise, plan, and apply the changes, run the following commands.

    tofu init
    tofu plan          # review the role assignments that will be created
    tofu apply         # type "yes" when prompted

e. To verify the resources created in this stage, run the following commands.

# Confirm the AKS cluster is in Succeeded state
az aks show --name <cluster-name> --resource-group <resource-group> \
  --query "{Name:name, State:provisioningState, Version:kubernetesVersion, Fqdn:privateFqdn}" \
  --output table

A sample output is displayed below:

Name              State      Version    Fqdn
----------------  ---------  ---------  -----------------------------------------------
<cluster-name>    Succeeded  1.35       <cluster-name>.privatelink.<region>.azmk8s.io
# Verify kubectl can reach the cluster
kubectl get nodes    # expect 2 system nodes in Ready state
# Verify federated credentials exist
az identity federated-credential list \
  --identity-name <velero-uami-name> \
  --resource-group <velero-uami-resource-group> --output table
az identity federated-credential list \
  --identity-name <opensearch-uami-name> \
  --resource-group <opensearch-uami-resource-group> --output table
  1. 03_node_pool module

This stage creates a user-managed node pool for application workloads. Node Auto Provisioning (NAP) handles autoscaling; no cluster autoscaler is configured on this pool.

ResourcePurpose
User node pool (userpool)Worker nodes for NFA platform, Insight, and other application pods

To update the 03_node_pool module, perform the following steps.

a. Navigate to the iac/azure/cluster/modules/03_node_pool/ directory.

    cd iac/azure/cluster/modules/03_node_pool/

Note (Non-FIPS deployment): If you are deploying a non-FIPS cluster, ensure fips_enabled remains false as configured in Configuring PPC for Non-FIPS Deployment on Microsoft Azure. Do not change this value to true.

b. Edit the terraform.tfvars file to provide the required values.

    resource_group_name    = "<resource-group>" # e.g. "aks-rg-prod"
    aks_cluster_name       = "<cluster-name>" # e.g. "prod-aks-cluster"
    azure_subscription_id  = "<subscription-id>" # e.g. "1e9ef7b6-cdc4-4a6b-98f7-a408ac1e19e0"
    storage_account_name   = "<storage-account-name>" # e.g. "myclusterstateaccount"
    storage_container_name = "velero"

    # -------------------------------------------------
    # Node pool
    # -------------------------------------------------
    subnet_id              = "</subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<subnet>>"      # same subnet as AKS nodes (Stage 02)
    architecture           = "amd64" # amd64 or arm64
    vm_size                = ""      # leave empty for architecture default
    node_pool_disk_size_gb = 120
    node_pool_desired_size = 3
    node_pool_zones        = ["1", "2", "3"]
    fips_enabled           = true # set false for a non-FIPS node OS image (immutable)

c. Save the file and exit the editor.

d. To initialise, plan, and apply the changes, run the following commands.

    tofu init
    tofu plan          # review the role assignments that will be created
    tofu apply         # type "yes" when prompted

Expected time for this stage is approximately 5 to 10 minutes for node pool provisioning.

e. To verify the resources created in this stage, run the following commands.

# Confirm the user node pool exists and is Succeeded
az aks nodepool show --cluster-name <cluster-name> \
  --resource-group <resource-group> --name userpool \
  --query "{Name:name, State:provisioningState, Count:count, VmSize:vmSize, OsSku:osSku}" \
  --output table

A sample output is displayed below:

Name      State      Count    VmSize      OsSku
--------  ---------  -------  ----------  ----------
userpool  Succeeded  <count>  <vm-size>   AzureLinux
# Verify all nodes are Ready (system + user nodes)
kubectl get nodes -o wide
# Confirm user pool nodes have the expected label
kubectl get nodes -l agentpool=userpool
  1. 04_aks_addons module

This stage creates the default and backup Kubernetes storage classes using Azure Managed Disks (Premium LRS) and removes the built-in default storage class annotation.

ResourcePurpose
ebs-sc storage classDefault storage class (Premium LRS, WaitForFirstConsumer, expandable)
ebs-bkp storage classBackup storage class used by Velero for PVC snapshots
Remove built-in default SCEnsures only ebs-sc is marked as the cluster default

To update the 04_aks_addons module, perform the following steps.

a. Navigate to the iac/azure/cluster/modules/04_aks_addons/ directory.

    cd iac/azure/cluster/modules/04_aks_addons/

b. Edit the terraform.tfvars file to provide the required values.

    resource_group_name    = "<resource-group>" # e.g. "aks-rg-prod"
    aks_cluster_name       = "<cluster-name>" # e.g. "prod-aks-cluster"
    azure_subscription_id  = "<subscription-id>" # e.g. "1e9ef7b6-cdc4-4a6b-98f7-a408ac1e19e0"
    storage_account_name   = "<storage-account-name>" # e.g. "myclusterstateaccount"
    storage_container_name = "velero"

c. Save the file and exit the editor.

d. To initialise, plan, and apply the changes, run the following commands.

    tofu init
    tofu plan          # review the role assignments that will be created
    tofu apply         # type "yes" when prompted

e. To verify the resources created in this stage, run the following commands.

# List storage classes and confirm ebs-sc is the default
kubectl get storageclass
# Verify ebs-sc details
kubectl describe storageclass ebs-sc
# Confirm the built-in 'default' storage class is no longer the default
kubectl get storageclass default -o jsonpath='{.metadata.annotations.storageclass\.kubernetes\.io/is-default-class}'
# expected output: empty or "false"

A sample output is displayed below:

storage_class_names = {
  "backup" = "ebs-bkp"
  "default" = "ebs-sc"
}
  1. 05_helm_releases module

This stage deploys all application Helm charts, configures Velero backup with the Azure plugin, and bootstraps the NFA platform and Insight analytics stack.

ResourcePurpose
Velero Helm releaseBackup and disaster recovery with Azure Blob Storage and disk snapshots
NFA / Eclipse Helm releaseMain platform stack (cert-manager, Keycloak, API Gateway, services)
Insight Helm releaseLog aggregation and analytics (OpenSearch, Dashboards, Fluentd)
Reloader Helm releaseAuto-restarts workloads on ConfigMap or Secret changes
Envoy Gateway Helm releaseAPI gateway and ingress proxy
VolumeSnapshotClassCSI snapshot class (csi-azure-vsc) for Azure Disk snapshots
Namespaces & registry secretsCreates namespaces with image-pull secrets for the private registry

To update the 05_helm_releases module, perform the following steps.

a. Navigate to the iac/azure/cluster/modules/05_helm_releases/ directory.

    cd iac/azure/cluster/modules/05_helm_releases/

b. Run the following commands and note the values.

# Get the Velero Client ID
az identity show \
  --name id-aks-velero \
  --resource-group aks-ppc \
  --query clientId \
  -o tsv
# Get the OpenSearch Client ID
az identity show \
  --name aks-ppc01-opensearch-identity \
  --resource-group aks-ppc \
  --query clientId \
  -o tsv

c. Edit the terraform.tfvars file to provide the required values.

    resource_group_name    = "<resource-group>" # e.g. "aks-rg-prod"
    aks_cluster_name       = "<cluster-name>" # e.g. "prod-aks-cluster"
    azure_subscription_id  = "<subscription-id>" # e.g. "1e9ef7b6-cdc4-4a6b-98f7-a408ac1e19e0"
    storage_account_name   = "<storage-account-name>" # e.g. "myclusterstateaccount"
    storage_container_name = "velero"
    
    # -------------------------------------------------
    # Networking
    # -------------------------------------------------
    subnet_id    = "</subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<subnet>>" # same subnet as Stages 02/03 (for VNet address space lookup)
    pod_cidr     = ""  # optional override; empty = auto-detected from the live AKS network profile
    architecture = "amd64" # amd64 or arm64
    node_os      = "AzureLinux_FIPS" # should mirror stage-03 user node pool os_sku + fips_enabled

    # -------------------------------------------------
    # Registry
    # -------------------------------------------------
    global_image_reg = "<registry endpoint>" # e.g. "harbor.example.com"
    harbor_secret    = "<harbour secret>" # e.g. "harbor-pull-secret"
    ingress_fqdn     = "<FQDN>" # e.g. "apps.example.com"

    # -------------------------------------------------
    # Ownership / tagging
    # -------------------------------------------------
    owner_email = "<name@domain.tld>" # optional; blank = auto-detect from the Azure CLI identity

    # -------------------------------------------------
    # Restore / backup
    # -------------------------------------------------
    restore             = false                               # set to true to restore from a previous backup
    backup_name         = "authnz-postgresql-schedule-backup" # Velero backup name used when restore = true
    insight_backup_name = ""                                  # Insight Velero backup name (K8s resources only); leave empty to auto-resolve latest

    # -------------------------------------------------
    # Workload Identity
    # -------------------------------------------------
    velero_uami_client_id     = "<velero_uami_client_id>" # client ID of the Velero UAMI 
    opensearch_uami_client_id = "<opensearch_uami_client_id>" # client ID of the OpenSearch UAMI    

c. Save the file and exit the editor.

d. Export registry credentials using environment variables. Do not put them in the tfvars file.

    export TF_VAR_username="<registry-username>"
    export TF_VAR_password="<registry-password>"

e. To initialise, plan, and apply the changes, run the following commands.

    tofu init
    tofu plan          # review the role assignments that will be created
    tofu apply         # type "yes" when prompted

Expected time for this stage is approximately 15 to 20 minutes.

f. To verify the resources created in this stage, run the following commands.

# Confirm all Helm releases are deployed
helm list -A
# Verify Velero is running
kubectl get pods -n pty-backup-recovery
# Verify NFA platform pods
kubectl get pods -A
# Verify Insight pods
kubectl get pods -n pty-insight
# Verify Envoy Gateway
kubectl get pods -n api-gateway
# Verify VolumeSnapshotClass exists
kubectl get volumesnapshotclass
# Check all pods across the cluster are healthy
kubectl get pods -A --field-selector=status.phase!=Running,status.phase!=Succeeded
# Confirm the ingress gateway has an IP
kubectl get gateway -A

A sample output is displayed below:

nfa_release_status = "deployed"
user_svc_private_key = <sensitive>
velero_release_status = "deployed"

All the nodes must be in the Ready state and all the pods must be in the Running or Completed state.

Verifying the installation

To verify the installation, run the following command.

kubectl get nodes
kubectl get pods -A

2.4 - Installing Features and Protectors

Installing the features and protectors

Before you begin

Ensure that PPC is successfully installed before installing the features or protectors.

Installing Features

The following table lists the available features.

FeatureDescription
Data DiscoveryInstalling Data Discovery
Semantic GuardrailsInstalling Semantic Guardrails
Protegrity AgentInstalling Protegrity Agent
AnonymizationInstalling Anonymization
Synthetic DataInstalling Synthetic Data

Installing Protectors

The following table lists the available protectors.

ProtectorDescription
Application ProtectorInstalling Application Protector
Repository ProtectorInstalling Repository Protector
Application Protector Java ContainerInstalling Application Protector Java Container
Rest ContainerInstalling Rest Container
Cloud ProtectorInstalling Cloud Protector

2.5 - Login to PPC

The PPC provides a web-based user interface for managing data protection policies, users, and roles. Access the UI through a browser using the cluster’s FQDN. This section covers the prerequisites for resolving the FQDN and the steps to log in.

To access the Web UI, map the gateway hostname to the Microsoft Azure Load Balancer IP address in the local hosts file.

  1. Get gateway details: Find the hostname and the Microsoft Azure Load Balancer address.

    kubectl get gateway -A
    

    The output will look similar to:

    NAMESPACE     NAME       CLASS   ADDRESS       PROGRAMMED   AGE
    api-gateway   pty-main   envoy   10.221.8.33   True         5h7m
    
  2. Update the hosts file: Add an entry mapping the ingress FQDN to the IP.

    • Linux: /etc/hosts
    • Windows: C:\Windows\System32\drivers\etc\hosts

    Example entry:

    10.221.8.33    <FQDN given during cluster installation>
    

    Use the same FQDN provided during the installation process..

  3. Access the UI in the browser.

    URL: https://<user-provided-fqdn>

    Enter the following parameters to log in and view the Insight Dashboard.

    • Username: Application username
    • Password: Application password

    For more information about the default credentials, refer to the Release Notes.

2.6 - Accessing the PPC CLI

The Protegrity Provisioned Cluster (PPC) CLI provides a command-line interface for managing policies, users, and log forwarding. Access is established over SSH using the private key generated during the PPC installation.

The deployment includes a CLI container that provides command-line access to the Protegrity Management CLI using SSH, on both Linux and Windows.

Prerequisites

  • SSH key: The private key generated during bootstrap at ~/.ssh/<cluster_name>_user_svc, matches the public key configured in the pty-cli pod.

  • Network access: Ensure you have connectivity to the AKS cluster’s ingress Load Balancer.

  • Hosts file: Same as Web UI access. Map the ingress FQDN to the Load Balancer IP.

The private key is placed under ~/.ssh/<cluster_name>_user_svc after bootstrap completes, where <cluster_name> is the AKS cluster name provided during installation.

From the project root directory, run the following command:

ssh -i ~/.ssh/<cluster_name>_user_svc -p 22 ptyitusr@<your-fqdn>

To skip host-key checking on first connect, run the following command:

ssh -i ~/.ssh/<cluster_name>_user_svc \
    -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null \
    -p 22 ptyitusr@<your-fqdn>
  • OpenSSH (Windows 10/11): Copy the private key from the jump box (~/.ssh/<cluster_name>_user_svc) to Windows machine, then run the following command:
ssh -i C:\path\to\<cluster_name>_user_svc -p 22 ptyitusr@<your-fqdn>
  • PuTTY:
    • Host Name: <user-provided-fqdn>
    • Port: 22
    • Connection Type: SSH
    • Connection > SSH > Auth: Browse to your private key (.ppk format)
    • Username: ptyitusr

CLI usage

Once connected, the Protegrity CLI welcome banner is displayed. Enter the following parameters when prompted:

  • Username: Application username
  • Password: Application password

For more information about the default credentials, refer to the Release Notes.

The CLI supports three command categories:

  • pim: Policy Information Management commands for data protection policies.
  • admin: User, role, permission, group, and email management commands.
  • insight: Log forwarding to external SIEM and syslog servers.

Note: Ensure that at least one additional backup administrator user is configured with the same administrative privileges as the primary admin user.
If the primary admin account is locked or its credentials are lost, restoring the system from a backup is the only recovery option.

2.7 - Deleting PPC

Steps to delete the cluster

Prerequisites

Authentication

The deletion process uses OpenTofu to destroy Azure resources, such as AKS clusters, managed identities, storage accounts, and Key Vaults. The Azure CLI must be authenticated to perform these operations.

Note: While using temporary credentials, such as service principal tokens or managed identity tokens, ensure that the credentials have not expired before proceeding.

To authenticate and set the correct subscription, run the following commands.

az login
az account set --subscription <subscription-id>

To verify that the credentials are valid and the correct Azure subscription is being used, run the following command.

az account show

Required Resource Providers

The following Azure resource providers must be registered in the subscription before deletion can proceed. If any provider is missing, the destroy operation may fail when attempting to manage the associated resources.

  • Microsoft.ContainerService
  • Microsoft.Storage
  • Microsoft.KeyVault
  • Microsoft.ManagedIdentity
  • Microsoft.Network
  • Microsoft.Compute

Required permissions

The following permissions are required to delete the PPC cluster. Create a custom role with these permissions and assign it to the managed identity used for deletion.

{
  "Name": "<ROLE-NAME>",
  "Description": "",
  "AssignableScopes": [
    "/subscriptions/<SUBSCRIPTION-ID>/resourceGroups/<RESOURCE-GROUP>"
  ],
  "Actions": [
    "Microsoft.Storage/storageAccounts/listKeys/action",
    "Microsoft.Resources/subscriptions/resourceGroups/read",
    "Microsoft.ContainerService/managedClusters/read",
    "Microsoft.ContainerService/managedClusters/listClusterUserCredential/action",
    "Microsoft.Storage/storageAccounts/read",
    "Microsoft.ContainerService/managedClusters/agentPools/read",
    "Microsoft.ManagedIdentity/userAssignedIdentities/read",
    "Microsoft.ContainerService/managedClusters/agentPools/delete",
    "Microsoft.ContainerService/managedClusters/delete",
    "Microsoft.Storage/storageAccounts/blobServices/read",
    "Microsoft.Storage/storageAccounts/fileServices/read",
    "Microsoft.Storage/storageAccounts/blobServices/containers/read",
    "Microsoft.Storage/storageAccounts/write",
    "Microsoft.Authorization/roleAssignments/delete",
    "Microsoft.Storage/storageAccounts/blobServices/containers/delete",
    "Microsoft.KeyVault/vaults/delete",
    "Microsoft.KeyVault/vaults/read",
    "Microsoft.Storage/storageAccounts/delete"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": []
}

To create the custom role and assign it to the managed identity, follow the steps in AKS User-Assigned Managed Identity Permissions.

Required tools

The following tools must be installed and available on the machine before proceeding with deletion:

  • tofu (OpenTofu)
  • kubectl (configured with cluster context)
  • az CLI (authenticated)
  • helm

Cleaning up the AKS Resources

There are two ways to destroy all created resources, including the AKS cluster and related components.

Method 1: Using the bootstrap script

From the folder where bootstrap script is present, run the following command:

./bootstrap.sh --cloud azure destroy

Method 2: Using OpenTofu to delete all modules

This method displays how to delete a PPC cluster on Azure by destroying the OpenTofu modules in reverse order. Destroying modules one at a time gives full control and visibility over each stage.

Warning: This process is irreversible. All cluster resources, data, and backups stored in the backup storage will be permanently deleted.

The modules are located at:

~/iac/azure/cluster/modules/
├── 00_backup_storage
├── 01_identity
├── 02_aks_cluster
├── 03_node_pool
├── 04_aks_addons
└── 05_helm_releases

These modules must be destroyed in reverse order: 05 → 04 → 03 → 02 → 01 → 00.

To delete the modules, perform the following steps:

  1. To delete the helm releases resource, run the following command.
# Navigate to 05_helm_releases directory
cd /iac/azure/cluster/modules/05_helm_releases

# Initialize providers
tofu init  

# Delete the helm release
tofu destroy        # type "yes" when prompted
  1. To delete the AKS Addons resource, run the following command.
# Navigate to 04_aks_addons directory
cd /iac/azure/cluster/modules/04_aks_addons

# Initialize providers
tofu init 

# Delete the aks addons
tofu destroy        # type "yes" when prompted
  1. To delete the Node Pool resource, run the following command.
# Navigate to 03_node_pool directory
cd /iac/azure/cluster/modules/03_node_pool

# Initialize providers
tofu init 

# Delete the node pool
tofu destroy        # type "yes" when prompted
  1. To delete the AKS Cluster resource, run the following command.
# Navigate to 02_aks_cluster directory
cd /iac/azure/cluster/modules/02_aks_cluster

# Initialize providers
tofu init 

# Delete the aks cluster
tofu destroy        # type "yes" when prompted
  1. To delete the Identity resource, run the following command.
# Navigate to 01_identity directory
cd /iac/azure/cluster/modules/01_identity

# Initialize providers
tofu init 

# Delete the identity
tofu destroy        # type "yes" when prompted
  1. To delete the Backup Storage (Backup storage account + container) resource, run the following command.
# Navigate to 00_backup_storage directory
cd /iac/azure/cluster/modules/00_backup_storage

# Initialize providers
tofu init 

# Destroy all resources (Storage Account, Key Vault, container, encryption key)
tofu destroy        # type "yes" when prompted

2.8 - Backing up the PPC

Complete the steps provided in this section to backup a PPC deployment.

Protegrity Provisioned Cluster (PPC) supports backup of Insight indexes and cluster configurations. Use the procedures below to update the scheduled backups of your PPC deployment.

Backing up Velero backup schedule

To take a backup at an interval of 10 minutes, the cron job must be executed before the schedule. This ensures that the latest configurations are included and are available in the Storage Account.
By default, the cron job is executed after every 3 hours and schedule is executed after every 3.5 hours.

For taking the backups, the frequency of schedule and cron job can be changed, as required.

Perform the following steps to update the frequency.

  1. To update the frequency of the cron job, run the following command.

    $ kubectl patch cronjob authnz-postgresql-backup-recovery-cron-job \
    -n api-gateway \'
    --type=merge -p '{"spec":{"schedule":"<required frequency>"}}'
    
  2. To update the frequency of the schedule, run the following command.

    $ kubectl patch schedule authnz-postgresql-schedule-backup \   
    -n pty-backup-recovery \
    --type=merge -p '{"spec":{"schedule":"<required frequency>"}}' 
    

For instance, to update the frequency of the backup schedule to 10 minutes, perform the following steps.

  1. To update the cron job to every 8 minutes, run the following command.

    $ kubectl patch cronjob authnz-postgresql-backup-recovery-cron-job \
     -n api-gateway \
     --type=merge -p '{"spec":{"schedule":"8-58/10 * * * *"}}'
    
  2. To update the schedule to every 10 minutes, run the following command.

    $ kubectl patch schedule authnz-postgresql-schedule-backup \
     -n pty-backup-recovery \
     --type=merge -p '{"spec":{"schedule":"*/10 * * * *"}}'
    

Backing up indexes

Insight indexes are backed up automatically using a scheduled job. To manually back up the indexes, complete the following steps:

  1. Log in to the Insight Dashboard.
  2. Select the main menu.
  3. Navigate to Management > Snapshot Management > Snapshot policies.
  4. Click the daily-insight-snapshots policy.
  5. Click Edit.
  6. Update the following parameters:
    • Snapshot schedule
      • Frequency: Custom (Cron expression)
      • Cron expression: */15 * * * *
  7. Click Update.
  8. Wait for the next scheduled snapshot to complete. Verify that the snapshot is created from the snapshot status.

Note: The snapshot schedule is set to run every 15 minutes for creating the manual backup. Restore the default settings after the manual backup is complete. Before upgrading, disable the scheduler job after the backup is created. Ensure that the default parameters are restored and the job is re-enabled after the upgrade.

2.9 - Restoring the PPC

Complete the steps provided in this section to restore a PPC deployment using an existing backup.

Before you begin

Before starting a restore, ensure the following conditions are met:

  • An existing backup is available. Backups are taken automatically as part of the default installation using scheduled backup mechanisms. These backups are stored in a Storage Account configured during the original installation.

  • Access to the original backup Storage Account. During restore, the same Storage Account that was used during the original installation must be specified.

  • Permissions to read from the Storage Account. The user performing the restore must have sufficient permissions to access the backup data stored in the account.

  • A new Kubernetes cluster is created. Restore is performed as part of creating a new cluster, not on an existing one. Restore is only supported during a fresh installation flow.

  • While the backup is taken from the source cluster, do not perform Create, Read, Update, or Delete (CRUD) operations on the source cluster. This ensures backup consistency and prevents data corruption during restore.

  • Before restoring to a new cluster, if the source cluster is accessible, disable the backup operations on the source cluster by setting the backup storage location to read‑only. This ensures that no additional backup data is written during the restore process.

    To disable the backup operation on the source cluster, run the following command:

    kubectl patch backupstoragelocation default -n pty-backup-recovery --type merge -p '{"spec":{"accessMode":"ReadOnly"}}'
    

    If the source cluster is not accessible, this step can be skipped.

During Disaster management, the backup data is used to restore the cluster and the OpenSearch indexes using snapshots. However, Insight restores OpenSearch data only from the most recent snapshot created by the daily-insight-snapshots policy.
For more information, refer to Backing up and restoring indexes.

Warning: Do not install or manage multiple clusters from the same working directory. Each cluster deployment maintains its own Terraform/OpenTofu state, and reusing a directory can overwrite state files, causing loss of cluster tracking and unintended cleanup behavior.
Use a dedicated directory, and jump box, where possible, per cluster, and always verify the active kubectl context before running cleanup commands such as ./bootstrap.sh --cloud azure destroy.

The repository provides a bootstrap script that automatically installs or updates the following software on the jump box:

  • Azure CLI - Required to communicate with your Microsoft Azure account.
  • OpenTofu - Required to manage infrastructure as code.
  • kubectl - Required to communicate with the Kubernetes cluster.
  • Helm - Required to manage Kubernetes packages.
  • jq - Required to parse JSON.
  • skopeo - Required to copy container images between registries.
  • bc - Required for version comparisons and resource calculations.
  • ORAS - Required to pull OCI artifacts such as deployment packages.
  • ssh-keygen - Required to secure SSH access to deployment environments.
  • cmctl - Required to validate and manage TLS certificates.

The bootstrap script also checks if you have the required permissions on Azure. It then sets up the AKS cluster and installs the microservices required for deploying the PCS on a PPC.

Note: Before running the bootstrap or resiliency scripts as the root user on RHEL, ensure that /usr/local/bin (and the Azure CLI binary path, if applicable) is included in the $PATH. Alternatively, run the script using a non-root user where /usr/local/bin is already part of the default PATH.

Architecture Selection

  • amd64 (x86-64-based environments such as Standard_D8as_v5)
  • arm64 (ARM-based environments such as Standard_D8ps_v5)

The bootstrap script prompts you to select the node architecture interactively during deployment (step 1b).

Restoring the PPC

Ensure that the PCT is downloaded and extracted on the jump box. For more information, refer to Preparing for PPC deployment.

Run the following command to initiate restore using an existing backup:

./bootstrap.sh --cloud azure --restore

The script prompts for the following variables.

  1. Enter AKS Cluster Name [opencluster-v1]

    The following characters are allowed:

    • Lowercase letters: a-z
    • Numbers: 0-9
    • Hyphens: -

    The following characters are not allowed:

    • Uppercase letters: A-Z
    • Underscores: _
    • Spaces
    • Any special characters such as: / ? * + % ! @ # $ ^ & ( ) = [ ] { } : ; , .
    • Leading or trailing hyphens
    • Names must only contain up to 10 characters

    While creating a cluster, the cluster name must:

    • Start with a lowercase letter.
    • End with a letter or number.
    • Not contain consecutive hyphens.

    Note: Ensure that the cluster name does not exceed 10 characters. Cluster names longer than this limit can cause the bootstrap script to fail in subsequent installation steps.

    After the cluster name is accepted, the script prompts you to select the node architecture.

    [1b] Select Node Architecture

    Select the required architecture.

    [1b] Select Node Architecture
      1) amd64 (x86_64) — e.g. Standard_D8as_v5
      2) arm64 (ARM/Ampere) — e.g. Standard_D8ps_v5
    

    Enter 1 to select amd64 or 2 to select arm64.

    Note: Select amd64 for Standard_D8as_v5 environments. Select arm64 for ARM-based environments such as Standard_D8ps_v5.

  2. Querying for available Resource Groups

    The script queries for the available Resource Groups.

    Enter the Resource Group name from the table []

    The script then automatically detects the location and subscription ID of the resource group.

  3. Enter UAMI Resource ID

    Provide the complete Azure resource ID for the UAMI used by AKS in the following format:

    /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<identity-name>
    

    The UAMI client ID is detected automatically.

  4. Enter AKS Subnet Resource ID

    Provide the complete resource ID of the pre-existing subnet used for AKS nodes in the following format:

    /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Network/virtualNetworks/<vnet-name>/subnets/<subnet-name>
    
  5. Enter Private DNS Zone Resource ID

    Provide the Private DNS zone ID used by the AKS private cluster in the following format:

    /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.Network/privateDnsZones/privatelink.<region>.azmk8s.io
    

    The script attempts to automatically detect network settings:

    • Virtual network address space
    • Service CIDR
    • Pod CIDR
    • DNS service IP
  1. Enter FQDN [name.domain.com]

    This is the Fully Qualified Domain Name for the ingress.

    While entering the FQDN, ensure that:

    • contains at least two labels separated by a dot, such as, app.example.com
    • does not start or end with a dot or hyphen
    • does not contain consecutive dot character
    • label length must be between 1–63 characters
    • each label must start and end with a letter or digit
    • the last label must start only with a letter

    Warning: Ensure that the FQDN does not exceed 253 characters and only the following characters are used:

    • Lowercase letters: a-z
    • Numbers: 0-9
    • Special characters: - .
  2. Storage Account and Key Vault provisioning

    During restore, the script prompts for existing Storage Account and Key Vault configuration. Provide the existing values in this step.

    Storage Account & Key Vault provisioning
    
    Restore mode requires existing Storage Account and Key Vault configuration.
    Skipping provisioning choice; provide existing values in this step.
    
    Enter existing Storage Account Name:
    <bucket-name>
    Storage account '<bucket-name>' found in resource group '<resource-group>'.
    Using container: velero
    
    Enter existing Key Vault Name:
    <key-vault-name>
    

    During restore, the script prompts to manually select a backup from the available backups stored in the Storage Account. User input is required to either restore from the latest backup or choose a specific backup from the list.

    [restore] Backup selection — schedule: authnz-postgresql-schedule-backup
    Restore from latest backup? [Y/n]
    
    • Enter Y to restore from the most recent backup.
    • Enter n to manually select a backup.

    If n is selected, then the script displays a list of available backups (latest first) and prompts to select one by number:

    Available backups (latest first):
    [1] <timestamp> authnz-postgresql-schedule-backup-xxxxxxx
    [2] <timestamp> authnz-postgresql-schedule-backup-xxxxxxx
    Select a backup number (1-2):
    

    After entering the backup number, the chosen backup is used for the restore, and the installation continues.

    Enter Insight backup

    During restore, the script prompts to manually select the required insight backup from the available backups stored in the Storage Account. User input is required to either restore from the latest backup or choose a specific backup from the list.

    [restore] Insight backup selection — schedule: insight-configmaps-secrets
    Restore from latest backup? [Y/n]
    
    • Enter Y to restore from the most recent backup.
    • Enter n to manually select a backup.

    If n is selected, then the script displays a list of available backups (latest first) and prompts to select one by number:

    Available backups (latest first):
    [1] <timestamp>  insight-configmaps-secrets-xxxxxxxxx
    [2] <timestamp>  insight-configmaps-secrets-xxxxxxxxx
    Select a backup number (1-2):
    

    After entering the backup number, the chosen backup is used for the restore, and the installation continues.

  3. Enter Velero UAMI Resource ID

    Enter the resource ID of the dedicated Velero User-Assigned Managed Identity (UAMI) in the format:

    /subscriptions/<subscription-id>/resourceGroups/<velero-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name>
    

    The script automatically validates the UAMI and detects the UAMI Client ID.

  4. Enter OpenSearch UAMI Resource ID

    Enter the resource ID of the OpenSearch Velero User-Assigned Managed Identity (UAMI) in the format:

    /subscriptions/<subscription-id>/resourceGroups/<opensearch-resource-group>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name>
    

    The script automatically validates the UAMI and detects the UAMI Client ID.

  5. Enter Image Registry Endpoint

The image repository from where the container images are retrieved.

Expected format: <hostname>[:port].

Do not include ‘https://’

  1. Enter Registry Username

Enter the username for the registry mentioned in the previous step. Leave this entry blank if the registry does not require authentication.

  1. Enter Registry Password or Access Token

Enter Password or Access Token for the registry.

Input is masked with * characters.

Leave this entry blank if the registry does not require authentication.

  1. Enter Owner Email (for cluster tagging)

Enter email address in the format name@domain.tld. This email is used for the cluster ‘Owner’ tag and the platform owner contact.

Note: The cluster creation process can take approximately 15-20 minutes.

If the session is terminated during installation due to network issues, power outage, and so on, then the installation stops. To restart the installation, run the script again:

# Navigate to deployment directory and run the following command
./bootstrap.sh --cloud azure destroy

# Restore the cluster
./bootstrap.sh --cloud azure --restore

After the bootstrap script is completed, verify the cluster and workloads using the following commands:

# Confirm nodes are Ready
kubectl get nodes

# Confirm NFA workloads are Running
kubectl get pods -A

2.10 - Troubleshooting

Accessing the PPC CLI

  • Permission denied for publickey: Ensure the correct private key ~/.ssh/<cluster_name>_user_svc is used and matches the authorized_keys in the pod.

  • Connection refused: Verify the load balancer IP and hosts file configuration.

  • Key format issues: Ensure the private key is in the correct format . For example, OpenSSH format for Linux or macOS, .ppk for PuTTY.

Component installation issues

  • Helm chart not found: Run helm repo update to refresh the repository cache.

  • Namespace already exists: Drop the --create-namespace flag if the namespace is already created.

  • CRD conflicts: If cert-manager CRDs already exist, skip the CRD installation step.

  • Pod not starting: Inspect logs with kubectl logs <pod> -n <namespace> and kubectl describe pod <pod> -n <namespace>.

State lock error after interrupted installation

Issue: When an installation is interrupted mid-apply (Ctrl+C, network drop, SSH disconnect, or jump box crash), subsequent installation attempts fail with the following error:

Error: Error acquiring the state lock
Error message: state blob is already locked
Lock Info:
  ID:        9377a903-94d1-4b19-3e57-1ee92b18bed5
  Path:      https://<storage>.blob.core.windows.net/velero/infrastructure-manifest%2F<cluster>%2Fstates%2F01_identity.tfstate
  Operation: OperationTypeApply

Description: OpenTofu acquires a lease on the state blob in Azure Blob Storage before applying changes. If the process is terminated without a graceful shutdown, the lease is not released automatically. This can occur due to Ctrl+C, network disconnection, SSH session timeout, or a jump box reboot.

Resolution: Force-unlock the state using the lock ID from the error message, then re-run the installation.

cd iac/azure/cluster/modules/<failed-stage>
tofu init
tofu force-unlock <lock-id>

Replace <failed-stage> with the module directory that failed (for example, 01_identity) and <lock-id> with the ID shown in the error output.

2.11 - Restoring the SSH keys and PCT from backed up Terraform state file

Complete the steps provided in this section to restore the SSH keys and PCT from a backed up Terraform state file of a deleted v1.1.0 jump box.

This section describes the procedure to rebuild a usable PPC v1.1.0 deployment workspace on a jump box from an existing cluster and a backed up Terraform state file.

Before you Begin

Ensure the following requirements are met.

  • The state file from all the following modules must be available on the Storage Account.

    • 00_backup_bucket
    • 01_iam_roles
    • 02_eks_cluster
    • 03_node_group
    • 04_eks_addons
    • 05_helm_releases
  • Access to the same Microsoft Azure account and target AKS cluster.

  • Azure CLI credentials with required permissions.

Perform the following steps to recover PPC

  1. Create a workspace.

    To create a working directory for PCT, run the following command.

    mkdir -p deployment
    cd deployment
    
  2. Download and extract the PCT

    Download the PCT package into the deployment directory and extract it.
    For more information about downloading and extracting the PCT, refer to Preparing for PPC deployment.

    After successfully extracting the template, this directory behaves as recovered installation workspace.

  3. Login to Microsoft Azure as a Service Principal

    To login to Microsoft Azure as a Service Principal, run the following command

    az login -u <username> -p <password> -t <tenant-id>
    
  4. Install required dev tools

    Run the following script.

    cd deployment/bootstrap-scripts
    ./setup-devtools-azure.sh
    
  5. Initialize OpenTofu

    To initialize OpenTofu for the cluster module, run the following command,

    cd deployment/iac/azure/cluster/modules/05_helm_releases
    tofu init
    
  6. Generate the SSH key for CLI access

    To generate the SSH key for CLI access

    tofu output -raw user_svc_private_key > ~/.ssh/user_svc.pem
    chmod 600 ~/.ssh/user_svc.pem
    
  7. Configure kubectl to communicate with the AKS cluster

    To configure kubectl to communicate with the AKS cluster, run the following command.

    az aks get-credentials \
    --resource-group aks-ppc \
    --name           base-test
    
  8. Verify the nodes and pods status

    To verify the nodes and pods status, run the following command.

    kubectl get nodes
    kubectl get pods -A