Configure AWS account roles using Terraform

This topic describes how to use Terraform to create a role in your AWS account that allows users to work with Secrets Hub.

In addition, this topic describes how to use Terraform to add policy to existing user roles to deny them from performing actions that may interfere with Secrets Hub functionality.

Prerequisites and assumptions

  • You must have an active session via the AWS CLI

  • You must have permissions in AWS to apply new Terraform files

Define "allow" role for Secrets Hub

This section describes how to configure a role in AWS that allows Secrets Hub to sync secrets from Privilege Cloud to AWS Secrets Manager.

Create this role on the root path of the AWS account that has your AWS Secrets Manager.

  1. Log in to the AWS CLI.

  2. Copy the following Terraform file (.tf) template to a text editor:

    #############
    # VARIABLES #
    #############
      
    variable Policy {
      description = "A meaningful name for the policy. Do not use spaces in the policy name"
      type = string
    }
      
    variable CyberArkSecretsHubRoleARN {
      description = "The Secrets Hub Role ARN created for your CyberArk tenant. You can access this value from the Settings page in UI or via /api/info API"
      type = string
    }
      
    variable SecretsManagerAccount {
      description = "The AWS Secrets Manager's account ID"
      type = string
    }
      
    variable SecretsManagerRegion {
      description = "The AWS Secrets Manager's region"
      type = string
    }
      
      
    #############
    # RESOURCES #
    #############
      
    resource "aws_iam_role" "allow_secrets_access_role" {
        
      name = "AllowSecretsAccessRole"
      force_detach_policies = true
      
      assume_role_policy = jsonencode({
        Statement = [
          {
            Effect = "Allow"
            Principal = {
              AWS = "${var.CyberArkSecretsHubRoleARN}"
            }
            Action = [
              "sts:AssumeRole"
            ]
          }
        ]
      })
      
      inline_policy {
        name = "${var.Policy}"
      
        policy = jsonencode({
          Statement = [
            {
              Action   = ["secretsmanager:CreateSecret"]
              Effect   = "Allow"
              Resource = join(":", ["arn", "aws", "secretsmanager", "${var.SecretsManagerRegion}", "${var.SecretsManagerAccount}", "secret", "*"])
              Condition = {
                StringEquals = {
                  "aws:RequestTag/Sourced by CyberArk" = [
                    ""
                  ]
                }
              }
            },
            {
              Action   = ["secretsmanager:ListSecrets"]
              Effect   = "Allow"
              Resource = "*"
              Condition = {
                StringEquals = {
                  "aws:RequestedRegion" = "${var.SecretsManagerRegion}"
                }
              }
            },
            {
              Action   = [
                    "secretsmanager:UpdateSecret",
                    "secretsmanager:PutSecretValue",
                    "secretsmanager:DeleteSecret",
                    "secretsmanager:DescribeSecret",
                    "secretsmanager:TagResource",
                    "secretsmanager:UntagResource"
              ]
              Effect   = "Allow"
              Resource = join(":", ["arn", "aws", "secretsmanager", "${var.SecretsManagerRegion}", "${var.SecretsManagerAccount}", "secret", "*"])
              Condition = {
                StringEqualsIgnoreCase = {
                  "aws:ResourceTag/Sourced by CyberArk" = ""
                }
              }
            },    
          ]
        })
      }
    }
      
      
    ###########
    # OUTPUTS #
    ###########
      
    output allow_secrets_access_role_arn {
      description = "The ARN of the role that allows CyberArk Secrets Hub to manage secrets in the provided AWS Secrets Manager"
      value       = resource.aws_iam_role.allow_secrets_access_role.arn
    }
     
    output allow_secrets_access_role_name {
      description = "The name of the role that allows CyberArk Secrets Hub to manage secrets in the provided AWS Secrets Manager"
      value       = resource.aws_iam_role.allow_secrets_access_role.name
    }

    Save the file as resources_allowSecretsHubRole.tf in a directory where you are working, or download the file and unzip it.

    Use a different directory for the "allow" role and the "deny" role. Using the same directory can result in a misconfiguration that will fail your sync process.

  3. Optional: Create a variables file to inject values into resources_allowSecretsHubRole.tf.

    If you skip this step, you will be prompted for these values when you apply resources_allowSecretsHubRole.tf later.

    Copy the following to a text editor:

    Policy                    = "<POLICY NAME>"
    CyberArkSecretsHubRoleARN = "<The Secrets Hub tenant role ARN taken from the Settings page in UI or via /api/info API>"
    SecretsManagerAccount     = "<AWS SECRETS MANAGER ACCOUNT ID>"
    SecretsManagerRegion      = "<AWS SECRETS MANAGER REGION>"

    Save the file as variables_allowSecretsHubRole.tfvars in the working directory.

  4. In the working directory:

    1. Initialize Terraform:

      terraform init
    2. If you defined a variables file earlier, in the AWS CLI, run the following to inject the variable values in variables_allowSecretsHubRole.tfvars into resources_allowSecretsHubRole.tf:

      terraform plan -var-file=variables_allowSecretsHubRole.tfvars -out=tfplan
    3. Apply the Terraform execution file:

      terraform apply tfplan

      If you didn't prepare the variables file earlier, provide the information when prompted.

      The file is applied and outputs a new IAM ARN.

Deny user roles access to secrets (recommended)

After granting Secrets Hub permission to sync your secrets, as described in Define "allow" role for Secrets Hub, we recommend that you apply a deny policy to all the other AWS roles that exist in your account.

Applying deny policies on roles other than the Secrets Hub role enforces least-privilege and ensures that AWS users don't perform actions that may interfere with Secrets Hub functionality and the integrity of the sync process.

  1. Log in to the AWS CLI.

  2. Copy the following Terraform file (.tf) template to a text editor:

    #############
    # VARIABLES #
    #############
      
    variable Policy {
      description = "A meaningful name for the policy, for example, DenyPermissionsToUser. Do not use spaces in the policy name."
      type = string
    }
      
    variable UserRole {
      description = "The name of the role this policy will be added to, thereby denying users that are assigned to this role from updating secret managed by Secrets Hub."
      type = string
    }
      
    variable SecretsManagerAccount {
      description = "The AWS Secrets Manager's account ID."
      type = string
    }
      
    variable SecretsManagerRegion {
      description = "The AWS Secrets Manager's region."
      type = string
    }
      
      
    #############
    # RESOURCES #
    #############
      
    resource "aws_iam_policy" "deny_asm_policy" {
      name        = var.Policy
      description = "A policy to deny users from updating secrets from a specifics AWS Secrets Manager that are managed by Secrets Hub"
      policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
            {
                Effect =  "Deny",
                Action = [  
                          "secretsmanager:UpdateSecret",
                          "secretsmanager:PutSecretValue",
                          "secretsmanager:DeleteSecret"
                ],
                Resource = join(":", ["arn", "aws", "secretsmanager", var.SecretsManagerRegion, var.SecretsManagerAccount, "secret", "*"]),
                Condition = {
                    StringEquals = {
                        "aws:ResourceTag/Sourced by CyberArk": ""
                    }
                }
            },
            {
                Effect = "Deny",
                Action = "secretsmanager:TagResource",
                Resource = join(":", ["arn", "aws", "secretsmanager", var.SecretsManagerRegion, var.SecretsManagerAccount, "secret", "*"]),
                Condition = {
                    "ForAllValues:StringLike" = {
                        "aws:TagKeys" = [
                                        "CyberArk*",
                                        "cyberark*",
                                        "Cyberark*",
                                        "cyberArk*",
                                        "CYBERARK*"
                        ]
                    }
                }
            },
            {
                Effect = "Deny",
                Action = "secretsmanager:UntagResource",
                Resource = join(":", ["arn", "aws", "secretsmanager", var.SecretsManagerRegion, var.SecretsManagerAccount, "secret", "*"]),
                Condition = {
                    "ForAllValues:StringLike" = {
                        "aws:TagKeys" = [
                                        "CyberArk*",
                                        "cyberark*",
                                        "Cyberark*",
                                        "cyberArk*",
                                        "CYBERARK*",
                                        "Sourced by CyberArk"
                        ]
                    }
                }
            },    
          ]
      })
    }
      
      
    resource "aws_iam_role_policy_attachment" "attach_deny_policy_to_role" {
      role       = var.UserRole
      policy_arn = resource.aws_iam_policy.deny_asm_policy.arn
    }
      
      
    ##########
    # OUTPUT #
    ##########  
     
    output role_name_to_deny {
      description = "The name of the AWS role to assign the deny policy to"
      value       = var.UserRole
    }  
     
    output deny_policy_arn {
      description = "The ARN of the policy that denies access to the provided AWS Secrets Manager"
      value       = resource.aws_iam_policy.deny_asm_policy.arn
    }

    Save the file as resource_denyPolicy.tf in a directory where you are working.

    Use a different directory for the "allow" role and the "deny" role. Using the same directory can result in a misconfiguration that will fail your sync process.

  3. Optional: Create a variables file to inject values into resource_denyPolicy.tf

    If you skip this step, you will be prompted for these values when you apply resource_denyPolicy.tf later.

    Copy the following to a text editor:

    Policy                = "<Policy>"
    UserRole               = "<USERROLES THAT SHOULD BE DENIED ACCESS>"
    SecretsManagerAccount  = "<AWS SECRETS MANANGER ACCOUNT ID>"
    SecretsManagerRegion   = "<AWS SECRETS MANAGER REGION>

    Save the file as variables_denyPolicy.tfvars in your working directory.

  4. From the working directory:

    1. Initialize Terraform:

      terraform init
    2. If you defined a variables file earlier, in the AWS CLI, run the following to inject the variables in variables_denyPolicy.tfvars into resource_denyPolicy.tf:

      terraform plan -var-file=variables_denyPolicy.tfvars -out=tfplan

      The Terraform execution file is created.

    3. Apply the Terraform execution file:

      terraform apply tfplan

      If you didn't prepare the variables file earlier, provide the information when prompted.

      The file is applied and the user roles defined in the Terraform file are denied access to the specified AWS Secrets Manager.

The policy is added to the specified user role. You can see the updated user role in the AWS Management Console > IAM console (Roles > <UserRole>).