Users

Users

IAM users represent a human user or programmatic workload and provides access to AWS resources or services. Users belong to a single parent account and consists of the following properties and credentials:

  • Access Credentials: Programmatic long-lived credentials consisting of an access key ID and secret key.
  • Path: The IAM namespace which contains the user.
  • Login Profile: AWS web console credentials.
  • MFA Device: MFA devices required for accessing AWS resources, whether through the web console or programmatically.
  • SSL Certificates: May be used to authenticate with certain AWS services.
  • SSH Keys: SSH public keys to be used with AWS Codecommit, a git repository service, during application development.

Command

aws iam get-user --user-name $USERNAME

Output

{
    "User": {
        "Path": "/",
        "UserName": "username",
        "UserId": "ADSAYFF72444NEI6MNIOP",
        "Arn": "arn:aws:iam::012345678910:user/username",
        "CreateDate": "2019-07-10T23:13:11+00:00",
        "Tags": [
            {
                "Key": "TagName",
                "Value": "TagValue"
            }
        ]
    }
}

Upon creating a new AWS account, a root user is automatically created, which has complete access to all cloud resources with limited exceptions. For this reason, it is recommended that you create an administrator user for everyday use and restrict access to root user credentials.

Console Login Process

There are two possible login flows depending on the type of user attempting to sign in.1

Root User

To sign in as a root user, simply navigate to the sign-in page, select “Root User”, and enter the root user credentials and optional MFA code.

IAM User

To sign in to the AWS console as a non-root user, you can either use standard sign-in webpage and provide the target AWS account number or specify the account alias in the URL as such: https://<account_id_or_alias>.signin.aws.amazon.com/console/.

Subsections of Users

Provision Users

To provision an IAM user, the only required property is the username, which is unique within the AWS account.

pulumi up -y
pulumi destroy -y
// iam/identities/users/create_user/ts/index.ts

import * as aws from "@pulumi/aws";

// Create IAM user with long-lived access credentials
const user = new aws.iam.User("techsquawks-user", {
    name: "techsquawks-user"
});

// Export user information
export const userArn = user.arn;
export const userName = user.name;
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
// iam/identities/users/create_user/js/index.js

"use strict";
const aws = require("@pulumi/aws");

// Create IAM user with long-lived access credentials
const user = new aws.iam.User("techsquawks-user", {
    name: "techsquawks-user"
});

// Export user information
exports.userArn = user.arn;
exports.userName = user.name;
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
# iam/identities/users/create_user/py/__main__.py

import pulumi
from pulumi_aws import iam

# Create IAM user with long-lived access credentials
user = iam.User("techsquawks-user", name="techsquawks-user")

# Export user information
pulumi.export('userArn', user.arn)
pulumi.export('userName', user.name)
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
// iam/identities/users/create_user/go/main.go

package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Create IAM user with long-lived access credentials
		user, err := iam.NewUser(ctx, "techsquawks-user", &iam.UserArgs{
			Name: pulumi.String("techsquawks-user"),
		})
		if err != nil {
			return err
		}

		// Export user information
		ctx.Export("userArn", user.Arn)
		ctx.Export("userName", user.Name)
		return nil
	})
}
Deploy Repository Report Issue

Stack Outputs

Outputs:
    userArn : "arn:aws:iam::012345678910:user/techsquawks-user"
    userName: "techsquawks-user"

To further verify that the user was provisioned correctly, the identity can be fetched via the get-user IAM API call.

Command

aws iam get-user --user-name techsquawks-user

Output

{
    "User": {
        "Path": "/",
        "UserName": "techsquawks-user",
        "UserId": "DBSAYFF32444NEI6MNIOP",
        "Arn": "arn:aws:iam::012345678910:user/techsquawks-user",
        "CreateDate": "2023-07-10T23:13:11+00:00",
    }
}

Paths

Paths are analogous to namespaces and help in organizing IAM users both for reporting and associating permissions.

pulumi up -y
pulumi destroy -y
// iam/identities/users/paths/ts/index.ts

import * as aws from "@pulumi/aws";

// Create IAM user with long-lived access credentials
const user1 = new aws.iam.User("techsquawks-user-1", {
    name: "techsquawks-user",
    path: "/example/path/1/"
});
const user2 = new aws.iam.User("techsquawks-user-2", {
    name: "techsquawks-user-2",
    path: "/example/path/2/"
});
const user2a = new aws.iam.User("techsquawks-user-2a", {
    name: "techsquawks-user-2a",
    path: "/example/path/2/"
});
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
// iam/identities/users/paths/js/index.js

"use strict";
const aws = require("@pulumi/aws");

// Create IAM user with long-lived access credentials
const user1 = new aws.iam.User("techsquawks-user-1", {
    name: "techsquawks-user1",
    path: "/example/path/1/"
});
const user2 = new aws.iam.User("techsquawks-user-2", {
    name: "techsquawks-user-2",
    path: "/example/path/2/"
});
const user2a = new aws.iam.User("techsquawks-user-2a", {
    name: "techsquawks-user-2a",
    path: "/example/path/2/"
});
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
# iam/identities/users/paths/py/__main__.py

import pulumi
from pulumi_aws import iam

# Create IAM user with long-lived access credentials
user1 = iam.User("techsquawks-user-1", name="techsquawks-user1", path="/example/path/1/")
user2 = iam.User("techsquawks-user-2a", name="techsquawks-user2", path="/example/path/2/")
user2a = iam.User("techsquawks-user-2b", name="techsquawks-user2a", path="/example/path/2/")
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
// iam/identities/users/paths/go/main.go

package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Create IAM user with long-lived access credentials
		_, err := iam.NewUser(ctx, "techsquawks-user1", &iam.UserArgs{
			Name: pulumi.String("techsquawks-user1"),
			Path: pulumi.String("/example/path/1/"),
		})
		if err != nil {
			return err
		}
		_, err = iam.NewUser(ctx, "techsquawks-user2", &iam.UserArgs{
			Name: pulumi.String("techsquawks-user2"),
			Path: pulumi.String("/example/path/2/"),
		})
		if err != nil {
			return err
		}
		_, err = iam.NewUser(ctx, "techsquawks-user2a", &iam.UserArgs{
			Name: pulumi.String("techsquawks-user2a"),
			Path: pulumi.String("/example/path/2/"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
Deploy Repository Report Issue

Users who belong to the same path can be targeted in certain IAM operations, such as listing users:

Command

aws iam list-users --path "/example/path/2/"

Output

{
    "Users": [
        {
            "Path": "/example/path/2/",
            "UserName": "techsquawks-user-2",
            "UserId": "AFCAYGH7AQ44FXTSPCX55",
            "Arn": "arn:aws:iam::012345678910:user/example/path/2/techsquawks-user-2",
            "CreateDate": "2023-07-24T22:39:32+00:00"
        },
		{
            "Path": "/example/path/2/",
            "UserName": "techsquawks-user-2a",
            "UserId": "BEAAYHI7AQ45GXTQPCX44",
            "Arn": "arn:aws:iam::012345678910:user/example/path/2/techsquawks-user-2a",
            "CreateDate": "2023-07-24T22:39:32+00:00"
        }
    ]
}

Access Credentials

To access cloud resources through the API, users may be associated with a set of long-lived access credential key pair, consisting of an access key ID and secret key for signing requests.

pulumi up -y
pulumi destroy -y
// iam/identities/users/access_credentials/ts/index.ts

import * as aws from "@pulumi/aws";

// Create IAM user with long-lived access credentials
const user = new aws.iam.User("techsquawks-user", {
    name: "techsquawks-user"
});
const credentials = new aws.iam.AccessKey("techsquawks-user-credentials", {user: user.name});

// Export user information
export const userArn = user.arn;
export const userName = user.name;
export const userAccessKeyId = credentials.id;
export const userAccessSecret = credentials.secret;
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
// iam/identities/users/access_credentials/js/index.js

"use strict";
const aws = require("@pulumi/aws");

// Create IAM user with long-lived access credentials
const user = new aws.iam.User("techsquawks-user", {
    name: "techsquawks-user"
});
const credentials = new aws.iam.AccessKey("techsquawks-user-credentials", {user: user.name});

// Export user information
exports.userArn = user.arn;
exports.userName = user.name;
exports.userAccessKeyId = credentials.id;
exports.userAccessSecret = credentials.secret;
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
# iam/identities/users/access_credentials/py/__main__.py

import pulumi
from pulumi_aws import iam

# Create IAM user with long-lived access credentials
user = iam.User("techsquawks-user", name="techsquawks-user")
credentials = iam.AccessKey("techsquawks-user-credentials", user=user.name)

# Export user information
pulumi.export('userArn', user.arn)
pulumi.export('userName', user.name)
pulumi.export('userAccessKeyId', credentials.id)
pulumi.export('userSecretKey', credentials.secret)
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
// iam/identities/users/access_credentials/go/main.go

package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Create IAM user with long-lived access credentials
		user, err := iam.NewUser(ctx, "techsquawks-user", &iam.UserArgs{
			Name: pulumi.String("techsquawks-user"),
		})
		if err != nil {
			return err
		}
		credentials, err := iam.NewAccessKey(ctx, "techsquawks-user-credentials", &iam.AccessKeyArgs{
			User: user.Name,
		})
		if err != nil {
			return err
		}

		// Export user information
		ctx.Export("userArn", user.Arn)
		ctx.Export("userName", user.Name)
		ctx.Export("userAccessKeyId", credentials.ID())
		ctx.Export("userSecretKey", credentials.Secret)
		return nil
	})
}
Deploy Repository Report Issue

Stack Outputs

Outputs:
    userAccessKeyId: "BKINYAJ78Q44D3CT4NER"
    userArn :        "arn:aws:iam::012345678910:user/techsquawks-user"
    userName:        "techsquawks-user"
    userSecretKey:   [secret]
Info

Sensitive values are hidden by default in the Pulumi stack output. To get the secret key value, execute pulumi stack output userSecretKey --show-secrets --stack dev

To validate that the access credentials work as expected, invoke the caller identity API using the newly provisioned credentials:

Command

AWS_ACCESS_KEY_ID=$(pulumi stack output userAccessKeyId --stack dev)
AWS_SECRET_ACCESS_KEY=$(pulumi stack output userSecretKey --stack dev --show-secrets)
aws sts get-caller-identity

Output

{
    "UserId": "BKXNYAA78Q56W3CT4NTJ",
    "Account": "012345678910,
    "Arn": "arn:aws:iam::012345678910:user/techsquawks-user"
}

Console Passwords

While API access requires user access keys, password credentials are required for accessing the AWS account resources via the web console. IAM provides various API methods and resources for managing user passwords. For instance, login profiles define the password constraints for a given user.

pulumi up -y
pulumi destroy -y
// iam/identities/users/user_login_profile/ts/index.ts

import * as aws from "@pulumi/aws";

// Create IAM user with password/console credentials
const user = new aws.iam.User("techsquawks-user", {
    name: "techsquawks-user",
    forceDestroy: true
});
const loginProfile = new aws.iam.UserLoginProfile("techsquawks-user-login-profile", {
    user: user.name,
    passwordLength: 15,
    passwordResetRequired: true
});
export const password = loginProfile.password;
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
// iam/identities/users/user_login_profile/js/index.js

"use strict";
const aws = require("@pulumi/aws");

// Create IAM user with password/console credentials
const user = new aws.iam.User("techsquawks-user", {
    name: "techsquawks-user",
    forceDestroy: true
});
const loginProfile = new aws.iam.UserLoginProfile("techsquawks-user-login-profile", {
    user: user.name,
    passwordLength: 15,
    passwordResetRequired: true
});
exports.password = loginProfile.password;
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
# iam/identities/users/user_login_profile/py/__main__.py

import pulumi
from pulumi_aws import iam

# Create IAM user with long-lived access credentials
user = iam.User("techsquawks-user", name="techsquawks-user")
login_profile = iam.UserLoginProfile("techsquawks-user-login-profile",
    user=user.name,
    password_length=15,
    password_reset_required=True
);

pulumi.export('password', login_profile.password)
Deploy Repository Report Issue
pulumi up -y
pulumi destroy -y
// iam/identities/users/user_login_profile/go/main.go

package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Create IAM user with password/console credentials
		user, err := iam.NewUser(ctx, "techsquawks-user", &iam.UserArgs{
			Name: pulumi.String("techsquawks-user"),
		})
		if err != nil {
			return err
		}
		loginProfile, err := iam.NewUserLoginProfile(ctx, "loginProfile", &iam.UserLoginProfileArgs{
			User:                  user.Name,
			PasswordLength:        pulumi.Int(15),
			PasswordResetRequired: pulumi.Bool(true),
		})
		if err != nil {
			return err
		}
		ctx.Export("password", loginProfile.Password)
		return nil
	})
}
Deploy Repository Report Issue