diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a6ec52d..84ff9c27 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,8 +4,12 @@
 
 ### Modules
 
+* `iam-user-policy`: Module for IAM user and corresponding policy
+
 ### Examples
 
+* `vault-iam`: New example which creates a admin user for vault with policy suitable for it.
+* `vault-s3-private`: New example showing vault and IAM integration with restricted access.
 
 # v0.8.2
 
diff --git a/examples/vault-iam/Makefile b/examples/vault-iam/Makefile
new file mode 100644
index 00000000..6a60f4c8
--- /dev/null
+++ b/examples/vault-iam/Makefile
@@ -0,0 +1,43 @@
+.PHONY: init plan apply destroy clean
+
+.DEFAULT_GOAL = help
+
+# Hardcoding value of 3 minutes when we check if the plan file is stale
+STALE_PLAN_FILE := `find "tf.out" -mmin -3 | grep -q tf.out`
+
+## Check if tf.out is stale (Older than 2 minutes)
+check-plan-file:
+	@if ! ${STALE_PLAN_FILE} ; then \
+		echo "ERROR: Stale tf.out plan file (older than 3 minutes)!"; \
+		exit 1; \
+	fi
+
+## Runs terraform get and terraform init for env
+init:
+	@terraform get
+	@terraform init
+
+## use 'terraform plan' to map out updates to apply
+plan:
+	@terraform plan -out=tf.out
+
+## use 'terraform apply' to apply updates in a 'tf.out' plan file
+apply: check-plan-file
+	@terraform apply tf.out
+
+## use 'terraform destroy' to remove all resources from AWS
+destroy:
+	@terraform destroy
+
+## Show help screen.
+help:
+	@echo "Please use \`make <target>' where <target> is one of\n\n"
+	@awk '/^[a-zA-Z\-\_0-9]+:/ { \
+		helpMessage = match(lastLine, /^## (.*)/); \
+		if (helpMessage) { \
+			helpCommand = substr($$1, 0, index($$1, ":")-1); \
+			helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
+			printf "%-30s %s\n", helpCommand, helpMessage; \
+		} \
+	} \
+	{ lastLine = $$0 }' $(MAKEFILE_LIST)
diff --git a/examples/vault-iam/README.md b/examples/vault-iam/README.md
new file mode 100644
index 00000000..bcfdac27
--- /dev/null
+++ b/examples/vault-iam/README.md
@@ -0,0 +1,10 @@
+# Vault IAM user
+
+When setting up vault with AWS as it's secret engine, you need to have
+AWS secret and access keys for an IAM user with relevant
+permission. This example creates IAM user named "vault_user" and
+appropriate policy for it.
+
+In order for this example to create keys, you need to modify
+`variables.tf` appropriately.
+
diff --git a/examples/vault-iam/main.tf b/examples/vault-iam/main.tf
new file mode 100644
index 00000000..1ce19d76
--- /dev/null
+++ b/examples/vault-iam/main.tf
@@ -0,0 +1,43 @@
+resource "aws_iam_access_key" "vaultkey" {
+  user  = module.vault_iam_user_policy.user_name
+  count = var.key_count
+}
+
+data "aws_caller_identity" "current" {}
+
+module "vault_iam_user_policy" {
+  source          = "../../modules/iam-user-policy/"
+  user_name       = "vault_user"
+  environment     = "dev"
+  iam_policy_name = "vault_user_policy"
+  iam_user_policy = <<EOF
+{
+  "Version": "2012-10-17",
+  "Statement": [
+    {
+      "Effect": "Allow",
+      "Action": [
+        "iam:AttachUserPolicy",
+        "iam:CreateAccessKey",
+        "iam:CreateUser",
+        "iam:DeleteAccessKey",
+        "iam:DeleteUser",
+        "iam:DeleteUserPolicy",
+        "iam:DetachUserPolicy",
+        "iam:ListAccessKeys",
+        "iam:ListAttachedUserPolicies",
+        "iam:ListGroupsForUser",
+        "iam:ListUserPolicies",
+        "iam:PutUserPolicy",
+        "iam:RemoveUserFromGroup"
+      ],
+      "Resource": [
+        "arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/vtest-*"
+      ]
+    }
+  ]
+}
+EOF
+
+}
+
diff --git a/examples/vault-iam/outputs.tf b/examples/vault-iam/outputs.tf
new file mode 100644
index 00000000..66b66efd
--- /dev/null
+++ b/examples/vault-iam/outputs.tf
@@ -0,0 +1,8 @@
+output "secret_key" {
+  value = [aws_iam_access_key.vaultkey.*.secret]
+}
+
+output "access_id" {
+  value = [aws_iam_access_key.vaultkey.*.id]
+}
+
diff --git a/examples/vault-iam/variables.tf b/examples/vault-iam/variables.tf
new file mode 100644
index 00000000..b3eb7f44
--- /dev/null
+++ b/examples/vault-iam/variables.tf
@@ -0,0 +1,5 @@
+variable "key_count" {
+  description = "Set to 1 to optionally create access keys for the created IAM user"
+  default     = "0"
+}
+
diff --git a/examples/vault-s3-private/Makefile b/examples/vault-s3-private/Makefile
new file mode 100644
index 00000000..3694c5c4
--- /dev/null
+++ b/examples/vault-s3-private/Makefile
@@ -0,0 +1,49 @@
+.PHONY: init plan apply destroy clean
+
+.DEFAULT_GOAL = help
+
+# Hardcoding value of 3 minutes when we check if the plan file is stale
+STALE_PLAN_FILE := `find "tf.out" -mmin -3 | grep -q tf.out`
+
+## Check if tf.out is stale (Older than 2 minutes)
+check-plan-file:
+	@if ! ${STALE_PLAN_FILE} ; then \
+		echo "ERROR: Stale tf.out plan file (older than 3 minutes)!"; \
+		exit 1; \
+	fi
+
+## Runs terraform get and terraform init for env
+init:
+	@terraform get
+	@terraform init
+
+## use 'terraform plan' to map out updates to apply
+plan:
+	@terraform plan -out=tf.out
+
+## use 'terraform apply' to apply updates in a 'tf.out' plan file
+apply: check-plan-file
+	@terraform apply tf.out
+
+## use 'terraform destroy' to remove all resources from AWS
+destroy:
+	@terraform destroy
+
+## rm -rf all files and state
+clean:
+	@rm -f tf.out
+	@rm -f terraform.*.backup
+	@rm -f terraform.tfstate
+
+## Show help screen.
+help:
+	@echo "Please use \`make <target>' where <target> is one of\n\n"
+	@awk '/^[a-zA-Z\-\_0-9]+:/ { \
+		helpMessage = match(lastLine, /^## (.*)/); \
+		if (helpMessage) { \
+			helpCommand = substr($$1, 0, index($$1, ":")-1); \
+			helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
+			printf "%-30s %s\n", helpCommand, helpMessage; \
+		} \
+	} \
+	{ lastLine = $$0 }' $(MAKEFILE_LIST)
diff --git a/examples/vault-s3-private/README.md b/examples/vault-s3-private/README.md
new file mode 100644
index 00000000..52a40053
--- /dev/null
+++ b/examples/vault-s3-private/README.md
@@ -0,0 +1,128 @@
+# Example showing Vault and IAM Integration
+
+This example creates a private s3 bucket resources. It then uses vault
+to create keys which only has access to those s3 buckets. The example
+code will create an IAM role with access to that bucket and will also
+configure vault so that we can dynamically generate credentials for
+accessing that bucket.
+
+## Requirements
+
+These are the required things for this example:
+
+* A running vault server. If you just want to experiment with this,
+  run a development server using:
+
+``` shellsession
+vault server -dev
+```
+
+* The AWS access and secret keys for an IAM user which the AWS Secret
+  Backend for Vault will use for issuing new credentials. If you don't
+  have any, you can create one using [vault-iam
+  example](../vault-iam). You need to put the access keys in
+  [variables.tf](./variables.tf)
+
+
+## Environment creation and deployment
+
+``` shellsession
+$ make init
+$ make plan
+$ make apply
+module.vault_aws_backend.vault_aws_secret_backend.aws: Creating...
+module.vault_aws_backend.vault_aws_secret_backend.aws: Creation complete after 0s [id=fpco/aws/dev/vault]
+aws_iam_role.vault_bucket_role: Creating...
+aws_s3_bucket.vault-test-bucket: Creating...
+aws_iam_role.vault_bucket_role: Still creating... [10s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [10s elapsed]
+aws_iam_role.vault_bucket_role: Still creating... [20s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [20s elapsed]
+aws_iam_role.vault_bucket_role: Creation complete after 22s [id=bucket_access_role]
+module.vault_aws_backend.vault_aws_secret_backend_role.aws_role: Creating...
+module.vault_aws_backend.vault_aws_secret_backend_role.aws_role: Creation complete after 0s [id=fpco/aws/dev/vault/roles/s3_app_user]
+aws_s3_bucket.vault-test-bucket: Still creating... [30s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [40s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [50s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [1m0s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [1m10s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [1m20s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [1m30s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [1m40s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [1m50s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [2m0s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [2m10s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [2m20s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [2m30s elapsed]
+aws_s3_bucket.vault-test-bucket: Still creating... [2m40s elapsed]
+aws_s3_bucket.vault-test-bucket: Creation complete after 2m48s [id=vault-fpco-test-bucket]
+aws_iam_role_policy.vault_bucket_policy: Creating...
+aws_iam_role_policy.vault_bucket_policy: Still creating... [10s elapsed]
+aws_iam_role_policy.vault_bucket_policy: Still creating... [20s elapsed]
+aws_iam_role_policy.vault_bucket_policy: Creation complete after 24s [id=bucket_access_role:bucket-policy]
+
+Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
+
+The state of your infrastructure has been saved to the path
+below. This state is required to modify and destroy your
+infrastructure, so keep it safe. To inspect the complete state
+use the `terraform show` command.
+
+State path: terraform.tfstate
+```
+
+## Testing
+
+Make sure you are already authorized with the vault server. If not,
+use `vault login` to do it. And then, you can dynamically create AWS
+credentials for accessing the s3 bucket you created:
+
+``` shellsession
+$ vault read fpco/aws/dev/vault/creds/s3_app_user
+Key                Value
+---                -----
+lease_id           fpco/aws/prod/vault/creds/s3_app_user/eJcLUNbpTNRFpLoTL9mEW76p
+lease_duration     14m59s
+lease_renewable    false
+access_key         xxx
+secret_key         xxx
+security_token     xxx
+```
+
+Now let's try to see all the files in our bucket:
+
+``` shellsession
+$ env AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=xxx AWS_SESSION_TOKEN=xxx aws s3 ls s3://s3-vault-demo-dev-bucket
+```
+
+It gives you no output since there are no files. But the command
+works, which confirms us that the generated credentials are working as
+expected.
+
+Now let's try to do something for which you don't have access with the
+same credentials:
+
+``` shellsession
+$ env AWS_ACCESS_KEY_ID=xxxx AWS_SECRET_ACCESS_KEY=xxxx AWS_SESSION_TOKEN=xxx aws ec2 describe-instances --region="us-east-2"
+An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.
+```
+
+That doesn't work, which is expected. Let's try to see if we can
+access files of some other buckets which is present:
+
+``` shellsession
+$ env AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=xxx AWS_SESSION_TOKEN=xxx aws s3 ls s3://some-other-existing-bucket
+An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied
+```
+
+## Destruction
+
+``` shellsession
+$ make destroy
+$ make clean
+```
+
+## Notes
+
+- This example was last tested with `Terraform v0.12.3`
+- This example assumes AWS credentials setup with access to the **us-east-2** region.
diff --git a/examples/vault-s3-private/main.tf b/examples/vault-s3-private/main.tf
new file mode 100644
index 00000000..6330f01b
--- /dev/null
+++ b/examples/vault-s3-private/main.tf
@@ -0,0 +1,77 @@
+data "aws_region" "current" {}
+
+locals {
+  name_prefix = "${var.application}-${var.environment}"
+  region      = data.aws_region.current.name
+}
+
+resource "aws_s3_bucket" "vault-test-bucket" {
+  bucket = "${local.name_prefix}-bucket"
+  acl    = "private"
+  region = local.region
+
+  tags = {
+    Environment = var.environment
+  }
+}
+
+# Here we allow everyone to assume this role. In production systems
+# it's best to restrict it's scope so that only some IAM users are
+# able to assume this role.
+resource "aws_iam_role" "vault_bucket_role" {
+  name = "${local.name_prefix}-bucket-role"
+
+  assume_role_policy = <<EOF
+{
+  "Version": "2012-10-17",
+  "Statement": [
+    {
+      "Action": "sts:AssumeRole",
+      "Principal": {
+        "AWS": "*"
+      },
+      "Effect": "Allow",
+      "Sid": ""
+    }
+  ]
+}
+EOF
+
+
+  tags = {
+    Environment = var.environment
+  }
+}
+
+resource "aws_iam_role_policy" "vault_bucket_policy" {
+  name = "${local.name_prefix}-bucket-policy"
+  role = aws_iam_role.vault_bucket_role.id
+  policy = <<EOF
+{
+  "Version": "2012-10-17",
+  "Statement": [
+    {
+      "Effect": "Allow",
+      "Action": ["s3:*", "iam:CreateAccessKey"],
+      "Resource": ["${aws_s3_bucket.vault-test-bucket.arn}"]
+    }
+  ]
+}
+EOF
+
+}
+
+module "vault_aws_backend" {
+source                    = "../../modules/vault-aws-backend/"
+vault_address             = var.vault_address
+vault_token               = var.vault_token
+secret_backend_path       = var.secret_backend_path
+default_lease_ttl_seconds = var.default_lease_ttl_seconds
+max_lease_ttl_seconds     = var.max_lease_ttl_seconds
+credential_type           = var.credential_type
+role_name                 = var.role_name
+role_arn                  = aws_iam_role.vault_bucket_role.arn
+access_key                = var.access_key
+secret_key                = var.secret_key
+}
+
diff --git a/examples/vault-s3-private/variables.tf b/examples/vault-s3-private/variables.tf
new file mode 100644
index 00000000..ef11f1e5
--- /dev/null
+++ b/examples/vault-s3-private/variables.tf
@@ -0,0 +1,62 @@
+variable "application" {
+  description = "Application name"
+  default     = "s3-vault-demo"
+  type        = string
+}
+
+variable "environment" {
+  description = "Environment name: dev/qa/prod etc"
+  default     = "dev"
+  type        = string
+}
+
+variable "vault_address" {
+  description = "URL for the Vault server"
+  type        = string
+}
+
+variable "vault_token" {
+  description = "Vault token needed for authorization to the server"
+  type        = string
+}
+
+variable "secret_backend_path" {
+  description = "Unique AWS secret path for mouting"
+  type        = string
+  default     = "fpco/aws/dev/vault"
+}
+
+variable "default_lease_ttl_seconds" {
+  description = "The default TTL for credentials issued by this backend."
+  type        = string
+  default     = "900"
+}
+
+variable "max_lease_ttl_seconds" {
+  description = "The maximum TTL that can be requested for credentials issued by this backend."
+  type        = string
+  default     = "900"
+}
+
+variable "credential_type" {
+  description = "Specifies the type of credential to be used when retrieving credentials from the role."
+  type        = string
+  default     = "assumed_role"
+}
+
+variable "access_key" {
+  description = "The AWS Access Key ID this backend should use to issue new credentials."
+  type        = string
+}
+
+variable "secret_key" {
+  description = "The AWS Secret Key this backend should use to issue new credentials."
+  type        = string
+}
+
+variable "role_name" {
+  description = "The name to identify this role within the backend. Must be unique within the backend."
+  type        = string
+  default     = "s3_app_user"
+}
+
diff --git a/modules/iam-user-policy/README.md b/modules/iam-user-policy/README.md
new file mode 100644
index 00000000..21460867
--- /dev/null
+++ b/modules/iam-user-policy/README.md
@@ -0,0 +1,9 @@
+# IAM user and policy
+
+This module creates IAM user and policy and associates it with the
+created user.
+
+Further resources:
+
+* [AWS Policy elements reference](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html)
+* [AWS IAM Policy Documents with terraform](https://www.terraform.io/docs/providers/aws/guides/iam-policy-documents.html)
diff --git a/modules/iam-user-policy/main.tf b/modules/iam-user-policy/main.tf
new file mode 100644
index 00000000..d9e6e05e
--- /dev/null
+++ b/modules/iam-user-policy/main.tf
@@ -0,0 +1,18 @@
+resource "aws_iam_user" "iam_user" {
+  name = var.user_name
+  tags = {
+    "user"        = var.user_name
+    "Environment" = var.environment
+  }
+}
+
+resource "aws_iam_policy" "iam_policy" {
+  name   = var.iam_policy_name
+  policy = var.iam_user_policy
+}
+
+resource "aws_iam_user_policy_attachment" "iam_user_policy" {
+  user       = aws_iam_user.iam_user.name
+  policy_arn = aws_iam_policy.iam_policy.arn
+}
+
diff --git a/modules/iam-user-policy/outputs.tf b/modules/iam-user-policy/outputs.tf
new file mode 100644
index 00000000..c16228d3
--- /dev/null
+++ b/modules/iam-user-policy/outputs.tf
@@ -0,0 +1,4 @@
+output "user_name" {
+  value = aws_iam_user.iam_user.name
+}
+
diff --git a/modules/iam-user-policy/variables.tf b/modules/iam-user-policy/variables.tf
new file mode 100644
index 00000000..0ac4b1d6
--- /dev/null
+++ b/modules/iam-user-policy/variables.tf
@@ -0,0 +1,21 @@
+variable "user_name" {
+  description = "Name of the IAM user that needs to be created"
+  type        = string
+}
+
+variable "environment" {
+  description = "Environment name: dev/qa/prod etc"
+  default     = "dev"
+  type        = string
+}
+
+variable "iam_policy_name" {
+  description = "Policy name for the IAM user"
+  type        = string
+}
+
+variable "iam_user_policy" {
+  description = "The policy document. This is a JSON formatted string."
+  type        = string
+}
+
diff --git a/modules/vault-aws-backend/README.md b/modules/vault-aws-backend/README.md
new file mode 100644
index 00000000..23b7e165
--- /dev/null
+++ b/modules/vault-aws-backend/README.md
@@ -0,0 +1,6 @@
+# AWS Secret Backend for Vault
+
+This module creates an AWS secret backend and a role for the
+backend. Roles are used to map credentials to the policies that
+generated them. For an example of it's use, [see
+vault-s3-private](../../examples/vault-s3-private).
diff --git a/modules/vault-aws-backend/main.tf b/modules/vault-aws-backend/main.tf
new file mode 100644
index 00000000..02ba3d09
--- /dev/null
+++ b/modules/vault-aws-backend/main.tf
@@ -0,0 +1,25 @@
+provider "aws" {
+  region = "${var.region}"
+}
+
+provider "vault" {
+  address = "${var.vault_address}"
+  token   = "${var.vault_token}"
+}
+
+resource "vault_aws_secret_backend" "aws" {
+  region                    = "${var.region}"
+  access_key                = "${var.access_key}"
+  secret_key                = "${var.secret_key}"
+  path                      = "${var.secret_backend_path}"
+  default_lease_ttl_seconds = "${var.default_lease_ttl_seconds}"
+  max_lease_ttl_seconds     = "${var.max_lease_ttl_seconds}"
+}
+
+resource "vault_aws_secret_backend_role" "aws_role" {
+  backend         = "${vault_aws_secret_backend.aws.path}"
+  name            = "${var.role_name}"
+  credential_type = "${var.credential_type}"
+  role_arns       = ["${var.role_arn}"]
+}
+
diff --git a/modules/vault-aws-backend/variables.tf b/modules/vault-aws-backend/variables.tf
new file mode 100644
index 00000000..0012a7da
--- /dev/null
+++ b/modules/vault-aws-backend/variables.tf
@@ -0,0 +1,55 @@
+variable "vault_address" {
+  description = "URL for the Vault server"
+  type        = "string"
+}
+
+variable "vault_token" {
+  description = "Vault token needed for authorization to the server"
+  type        = "string"
+}
+
+variable "region" {
+  description = "AWS Region"
+  type        = "string"
+  default     = "us-east-2"
+}
+
+variable "secret_backend_path" {
+  description = "Unique AWS secret path for mouting"
+  type        = "string"
+}
+
+variable "default_lease_ttl_seconds" {
+  description = "The default TTL for credentials issued by this backend."
+  type = "string"
+}
+
+variable "max_lease_ttl_seconds" {
+  description = "The maximum TTL that can be requested for credentials issued by this backend."
+  type = "string"
+}
+
+variable "credential_type" {
+  description = "Specifies the type of credential to be used when retrieving credentials from the role."
+  type = "string"
+}
+
+variable "access_key" {
+  description = "The AWS Access Key ID this backend should use to issue new credentials."
+  type = "string"
+}
+
+variable "secret_key" {
+  description = "The AWS Secret Key this backend should use to issue new credentials."
+  type = "string"
+}
+
+variable "role_name" {
+  description = "The name to identify this role within the backend. Must be unique within the backend."
+  type = "string"
+}
+
+variable "role_arn" {
+  description = "Specifies the ARN of the AWS role this Vault role is allowed to assume"
+  type    = "string"
+}
diff --git a/tests/main.tf b/tests/main.tf
index e16f33e4..75834cd1 100644
--- a/tests/main.tf
+++ b/tests/main.tf
@@ -788,3 +788,11 @@ module "web-alb" {
   subnet_ids             = []
   vpc_id                 = ""
 }
+
+module "iam-user-policy" {
+  source          = "../modules/iam-user-policy/"
+  user_name       = ""
+  environment     = ""
+  iam_policy_name = ""
+  iam_user_policy = ""
+}