Skip to content

Use IAM Roles In Resource Access Policy

Description

Assigning permissions to roles, as opposed to users, allows better management of permissions. In the case of Amazon EC2, IAM dynamically provides temporary credentials to the EC2 instance, and these credentials are automatically rotated for you.

IAM roles are meant to be assumed by authorized entities, applications, AWS services and IAM users, to enable managed privilege escalation. E.g. an employee can assume a role to obtain extra permissions on AWS services that are associated with the role.

For information about IAM roles, please refer to the IAM documentation.

Rationale

Allow IAM roles instead of IAM users in your Amazon Elasticsearch Resource Policies.

In order to authenticate as a user, static credentials must be used. Unauthorized access to these credentials might allow attackers to escalate their privileges. Therefore, by switching to IAM Roles you can ensure short-term credentials are used and eliminate the need to store credentials, whose compromise can enable an external attack.

Applies To

  • Databases

Tags

This rule is applied when the following tags are present:

Tag With Value
secureclouddb/provider aws
secureclouddb/service elasticsearch

Default Rule

const { isAwsElasticsearch } = aws

/**
 * @param {Object} databaseSettings - database settings object
 * @returns {boolean} true if iam roles are present in access policies config and domain is not public
 */
function validate(databaseSettings) {

    const accessPolicies =
        isAwsElasticsearch(databaseSettings) &&
        databaseSettings.awsDatabaseInstance.elasticsearchDomain.accessPolicies;

    if (!accessPolicies) {
        return {
            success: false
        }
    }

    const policiesJson = JSON.parse(accessPolicies)
    const regex = /^arn:aws:iam::[0-9]*:user\//
    const hasUser = policiesJson.Statement &&
        policiesJson.Statement[0].Principal &&
        policiesJson.Statement[0].Principal.AWS &&
        regex.test(policiesJson.Statement[0].Principal.AWS)

    // elasticsearchDomainPubliclyAccessible
    const domainIsPublic =
        isAwsElasticsearch(databaseSettings) &&
        !databaseSettings.awsDatabaseInstance.elasticsearchDomain.vpcOptions ||
        !databaseSettings.awsDatabaseInstance.elasticsearchDomain.vpcOptions.vpcId

    const success = !hasUser && !domainIsPublic

    return {
        success,
    }
}

// invoke
validate(databaseSettings);