The aws:amp/resourcePolicy:ResourcePolicy resource, part of the Pulumi AWS provider, attaches resource-based policies to Amazon Managed Service for Prometheus workspaces, controlling which AWS accounts and services can write or query metrics. This guide focuses on three capabilities: same-account access, cross-account sharing, and service principal permissions.
Resource policies reference existing AMP workspaces and use IAM policy documents to define permissions. The examples are intentionally small. Combine them with your own workspace configuration and KMS key grants if using customer-managed encryption.
Grant workspace access to your own account
Most deployments start by granting their own AWS account permissions to write and query metrics, establishing baseline access before adding external principals.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const exampleWorkspace = new aws.amp.Workspace("example", {alias: "example-workspace"});
const current = aws.getCallerIdentity({});
const example = pulumi.all([current, exampleWorkspace.arn]).apply(([current, arn]) => aws.iam.getPolicyDocumentOutput({
statements: [{
effect: "Allow",
principals: [{
type: "AWS",
identifiers: [current.accountId],
}],
actions: [
"aps:RemoteWrite",
"aps:QueryMetrics",
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata",
],
resources: [arn],
}],
}));
const exampleResourcePolicy = new aws.amp.ResourcePolicy("example", {
workspaceId: exampleWorkspace.id,
policyDocument: example.apply(example => example.json),
});
import pulumi
import pulumi_aws as aws
example_workspace = aws.amp.Workspace("example", alias="example-workspace")
current = aws.get_caller_identity()
example = example_workspace.arn.apply(lambda arn: aws.iam.get_policy_document(statements=[{
"effect": "Allow",
"principals": [{
"type": "AWS",
"identifiers": [current.account_id],
}],
"actions": [
"aps:RemoteWrite",
"aps:QueryMetrics",
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata",
],
"resources": [arn],
}]))
example_resource_policy = aws.amp.ResourcePolicy("example",
workspace_id=example_workspace.id,
policy_document=example.json)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amp"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
exampleWorkspace, err := amp.NewWorkspace(ctx, "example", &.WorkspaceArgs{
Alias: pulumi.String("example-workspace"),
})
if err != nil {
return err
}
current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{
}, nil);
if err != nil {
return err
}
example := exampleWorkspace.Arn.ApplyT(func(arn string) (iam.GetPolicyDocumentResult, error) {
return iam.GetPolicyDocumentResult(interface{}(iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
Statements: []iam.GetPolicyDocumentStatement([]iam.GetPolicyDocumentStatement{
{
Effect: pulumi.StringRef(pulumi.String(pulumi.StringRef("Allow"))),
Principals: []iam.GetPolicyDocumentStatementPrincipal{
{
Type: "AWS",
Identifiers: interface{}{
current.AccountId,
},
},
},
Actions: []string{
"aps:RemoteWrite",
"aps:QueryMetrics",
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata",
},
Resources: []string{
arn,
},
},
}),
}, nil))), nil
}).(iam.GetPolicyDocumentResultOutput)
_, err = amp.NewResourcePolicy(ctx, "example", &.ResourcePolicyArgs{
WorkspaceId: exampleWorkspace.ID(),
PolicyDocument: pulumi.String(example.ApplyT(func(example iam.GetPolicyDocumentResult) (*string, error) {
return &example.Json, nil
}).(pulumi.StringPtrOutput)),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var exampleWorkspace = new Aws.Amp.Workspace("example", new()
{
Alias = "example-workspace",
});
var current = Aws.GetCallerIdentity.Invoke();
var example = Aws.Iam.GetPolicyDocument.Invoke(new()
{
Statements = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementArgs
{
Effect = "Allow",
Principals = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalArgs
{
Type = "AWS",
Identifiers = new[]
{
current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId),
},
},
},
Actions = new[]
{
"aps:RemoteWrite",
"aps:QueryMetrics",
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata",
},
Resources = new[]
{
exampleWorkspace.Arn,
},
},
},
});
var exampleResourcePolicy = new Aws.Amp.ResourcePolicy("example", new()
{
WorkspaceId = exampleWorkspace.Id,
PolicyDocument = example.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amp.Workspace;
import com.pulumi.aws.amp.WorkspaceArgs;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.amp.ResourcePolicy;
import com.pulumi.aws.amp.ResourcePolicyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var exampleWorkspace = new Workspace("exampleWorkspace", WorkspaceArgs.builder()
.alias("example-workspace")
.build());
final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
.build());
final var example = exampleWorkspace.arn().applyValue(_arn -> IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
.statements(GetPolicyDocumentStatementArgs.builder()
.effect("Allow")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("AWS")
.identifiers(current.accountId())
.build())
.actions(
"aps:RemoteWrite",
"aps:QueryMetrics",
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata")
.resources(_arn)
.build())
.build()));
var exampleResourcePolicy = new ResourcePolicy("exampleResourcePolicy", ResourcePolicyArgs.builder()
.workspaceId(exampleWorkspace.id())
.policyDocument(example.json())
.build());
}
}
resources:
exampleWorkspace:
type: aws:amp:Workspace
name: example
properties:
alias: example-workspace
exampleResourcePolicy:
type: aws:amp:ResourcePolicy
name: example
properties:
workspaceId: ${exampleWorkspace.id}
policyDocument: ${example.json}
variables:
current:
fn::invoke:
function: aws:getCallerIdentity
arguments: {}
example:
fn::invoke:
function: aws:iam:getPolicyDocument
arguments:
statements:
- effect: Allow
principals:
- type: AWS
identifiers:
- ${current.accountId}
actions:
- aps:RemoteWrite
- aps:QueryMetrics
- aps:GetSeries
- aps:GetLabels
- aps:GetMetricMetadata
resources:
- ${exampleWorkspace.arn}
The policyDocument property contains a JSON IAM policy that defines who can access the workspace and what actions they can perform. The principals block specifies the AWS account ID, while actions lists AMP-specific operations like RemoteWrite for ingestion and QueryMetrics for querying. The resources array must match the workspace ARN that the policy attaches to via workspaceId.
Share workspace access with another AWS account
Organizations with multiple AWS accounts often centralize metrics collection while allowing other accounts to write and query data.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.amp.Workspace("example", {alias: "example-workspace"});
const crossAccount = aws.iam.getPolicyDocumentOutput({
statements: [{
effect: "Allow",
principals: [{
type: "AWS",
identifiers: ["arn:aws:iam::123456789012:root"],
}],
actions: [
"aps:RemoteWrite",
"aps:QueryMetrics",
],
resources: [example.arn],
}],
});
const crossAccountResourcePolicy = new aws.amp.ResourcePolicy("cross_account", {
workspaceId: example.id,
policyDocument: crossAccount.apply(crossAccount => crossAccount.json),
});
import pulumi
import pulumi_aws as aws
example = aws.amp.Workspace("example", alias="example-workspace")
cross_account = aws.iam.get_policy_document_output(statements=[{
"effect": "Allow",
"principals": [{
"type": "AWS",
"identifiers": ["arn:aws:iam::123456789012:root"],
}],
"actions": [
"aps:RemoteWrite",
"aps:QueryMetrics",
],
"resources": [example.arn],
}])
cross_account_resource_policy = aws.amp.ResourcePolicy("cross_account",
workspace_id=example.id,
policy_document=cross_account.json)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amp"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := amp.NewWorkspace(ctx, "example", &.WorkspaceArgs{
Alias: pulumi.String("example-workspace"),
})
if err != nil {
return err
}
crossAccount := iam.GetPolicyDocumentOutput(ctx, iam.GetPolicyDocumentOutputArgs{
Statements: iam.GetPolicyDocumentStatementArray{
&iam.GetPolicyDocumentStatementArgs{
Effect: pulumi.String("Allow"),
Principals: iam.GetPolicyDocumentStatementPrincipalArray{
&iam.GetPolicyDocumentStatementPrincipalArgs{
Type: pulumi.String("AWS"),
Identifiers: pulumi.StringArray{
pulumi.String("arn:aws:iam::123456789012:root"),
},
},
},
Actions: pulumi.StringArray{
pulumi.String("aps:RemoteWrite"),
pulumi.String("aps:QueryMetrics"),
},
Resources: pulumi.StringArray{
example.Arn,
},
},
},
}, nil)
_, err = amp.NewResourcePolicy(ctx, "cross_account", &.ResourcePolicyArgs{
WorkspaceId: example.ID(),
PolicyDocument: pulumi.String(crossAccount.ApplyT(func(crossAccount iam.GetPolicyDocumentResult) (*string, error) {
return &crossAccount.Json, nil
}).(pulumi.StringPtrOutput)),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Amp.Workspace("example", new()
{
Alias = "example-workspace",
});
var crossAccount = Aws.Iam.GetPolicyDocument.Invoke(new()
{
Statements = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
{
Effect = "Allow",
Principals = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
{
Type = "AWS",
Identifiers = new[]
{
"arn:aws:iam::123456789012:root",
},
},
},
Actions = new[]
{
"aps:RemoteWrite",
"aps:QueryMetrics",
},
Resources = new[]
{
example.Arn,
},
},
},
});
var crossAccountResourcePolicy = new Aws.Amp.ResourcePolicy("cross_account", new()
{
WorkspaceId = example.Id,
PolicyDocument = crossAccount.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amp.Workspace;
import com.pulumi.aws.amp.WorkspaceArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.amp.ResourcePolicy;
import com.pulumi.aws.amp.ResourcePolicyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Workspace("example", WorkspaceArgs.builder()
.alias("example-workspace")
.build());
final var crossAccount = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
.statements(GetPolicyDocumentStatementArgs.builder()
.effect("Allow")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("AWS")
.identifiers("arn:aws:iam::123456789012:root")
.build())
.actions(
"aps:RemoteWrite",
"aps:QueryMetrics")
.resources(example.arn())
.build())
.build());
var crossAccountResourcePolicy = new ResourcePolicy("crossAccountResourcePolicy", ResourcePolicyArgs.builder()
.workspaceId(example.id())
.policyDocument(crossAccount.applyValue(_crossAccount -> _crossAccount.json()))
.build());
}
}
resources:
example:
type: aws:amp:Workspace
properties:
alias: example-workspace
crossAccountResourcePolicy:
type: aws:amp:ResourcePolicy
name: cross_account
properties:
workspaceId: ${example.id}
policyDocument: ${crossAccount.json}
variables:
crossAccount:
fn::invoke:
function: aws:iam:getPolicyDocument
arguments:
statements:
- effect: Allow
principals:
- type: AWS
identifiers:
- arn:aws:iam::123456789012:root
actions:
- aps:RemoteWrite
- aps:QueryMetrics
resources:
- ${example.arn}
Cross-account access uses an IAM principal ARN that identifies the target account’s root user. The example grants RemoteWrite and QueryMetrics permissions, enabling the external account to both ingest and query metrics. If your workspace uses customer-managed KMS keys for encryption, you must also grant the external account access to those keys through KMS grants.
Allow AWS services to query workspace metrics
Visualization tools like Amazon Managed Grafana need read-only access to query metrics without write permissions.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.amp.Workspace("example", {alias: "example-workspace"});
const serviceAccess = aws.iam.getPolicyDocumentOutput({
statements: [{
effect: "Allow",
principals: [{
type: "Service",
identifiers: ["grafana.amazonaws.com"],
}],
actions: [
"aps:QueryMetrics",
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata",
],
resources: [example.arn],
}],
});
const serviceAccessResourcePolicy = new aws.amp.ResourcePolicy("service_access", {
workspaceId: example.id,
policyDocument: serviceAccess.apply(serviceAccess => serviceAccess.json),
});
import pulumi
import pulumi_aws as aws
example = aws.amp.Workspace("example", alias="example-workspace")
service_access = aws.iam.get_policy_document_output(statements=[{
"effect": "Allow",
"principals": [{
"type": "Service",
"identifiers": ["grafana.amazonaws.com"],
}],
"actions": [
"aps:QueryMetrics",
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata",
],
"resources": [example.arn],
}])
service_access_resource_policy = aws.amp.ResourcePolicy("service_access",
workspace_id=example.id,
policy_document=service_access.json)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amp"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := amp.NewWorkspace(ctx, "example", &.WorkspaceArgs{
Alias: pulumi.String("example-workspace"),
})
if err != nil {
return err
}
serviceAccess := iam.GetPolicyDocumentOutput(ctx, iam.GetPolicyDocumentOutputArgs{
Statements: iam.GetPolicyDocumentStatementArray{
&iam.GetPolicyDocumentStatementArgs{
Effect: pulumi.String("Allow"),
Principals: iam.GetPolicyDocumentStatementPrincipalArray{
&iam.GetPolicyDocumentStatementPrincipalArgs{
Type: pulumi.String("Service"),
Identifiers: pulumi.StringArray{
pulumi.String("grafana.amazonaws.com"),
},
},
},
Actions: pulumi.StringArray{
pulumi.String("aps:QueryMetrics"),
pulumi.String("aps:GetSeries"),
pulumi.String("aps:GetLabels"),
pulumi.String("aps:GetMetricMetadata"),
},
Resources: pulumi.StringArray{
example.Arn,
},
},
},
}, nil)
_, err = amp.NewResourcePolicy(ctx, "service_access", &.ResourcePolicyArgs{
WorkspaceId: example.ID(),
PolicyDocument: pulumi.String(serviceAccess.ApplyT(func(serviceAccess iam.GetPolicyDocumentResult) (*string, error) {
return &serviceAccess.Json, nil
}).(pulumi.StringPtrOutput)),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Amp.Workspace("example", new()
{
Alias = "example-workspace",
});
var serviceAccess = Aws.Iam.GetPolicyDocument.Invoke(new()
{
Statements = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
{
Effect = "Allow",
Principals = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
{
Type = "Service",
Identifiers = new[]
{
"grafana.amazonaws.com",
},
},
},
Actions = new[]
{
"aps:QueryMetrics",
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata",
},
Resources = new[]
{
example.Arn,
},
},
},
});
var serviceAccessResourcePolicy = new Aws.Amp.ResourcePolicy("service_access", new()
{
WorkspaceId = example.Id,
PolicyDocument = serviceAccess.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amp.Workspace;
import com.pulumi.aws.amp.WorkspaceArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.amp.ResourcePolicy;
import com.pulumi.aws.amp.ResourcePolicyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Workspace("example", WorkspaceArgs.builder()
.alias("example-workspace")
.build());
final var serviceAccess = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
.statements(GetPolicyDocumentStatementArgs.builder()
.effect("Allow")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("Service")
.identifiers("grafana.amazonaws.com")
.build())
.actions(
"aps:QueryMetrics",
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata")
.resources(example.arn())
.build())
.build());
var serviceAccessResourcePolicy = new ResourcePolicy("serviceAccessResourcePolicy", ResourcePolicyArgs.builder()
.workspaceId(example.id())
.policyDocument(serviceAccess.applyValue(_serviceAccess -> _serviceAccess.json()))
.build());
}
}
resources:
example:
type: aws:amp:Workspace
properties:
alias: example-workspace
serviceAccessResourcePolicy:
type: aws:amp:ResourcePolicy
name: service_access
properties:
workspaceId: ${example.id}
policyDocument: ${serviceAccess.json}
variables:
serviceAccess:
fn::invoke:
function: aws:iam:getPolicyDocument
arguments:
statements:
- effect: Allow
principals:
- type: Service
identifiers:
- grafana.amazonaws.com
actions:
- aps:QueryMetrics
- aps:GetSeries
- aps:GetLabels
- aps:GetMetricMetadata
resources:
- ${example.arn}
Service principals use type “Service” with the service’s domain name as the identifier. This example grants Grafana read-only actions (QueryMetrics, GetSeries, GetLabels, GetMetricMetadata) without RemoteWrite, preventing the service from modifying workspace data. Service principals don’t require KMS grants because they operate within AWS’s internal trust boundaries.
Beyond these examples
These snippets focus on specific resource policy features: same-account and cross-account access, service principal permissions, and action-level permission control. They’re intentionally minimal rather than full workspace configurations.
The examples reference pre-existing infrastructure such as AMP workspaces and IAM permissions to create policy documents. They focus on attaching policies rather than provisioning the workspace itself.
To keep things focused, common policy patterns are omitted, including:
- KMS key grants for encrypted workspaces
- Policy revision management (revisionId)
- Condition-based access controls
- Multiple principal types in one policy
These omissions are intentional: the goal is to illustrate how each policy configuration is wired, not provide drop-in access control modules. See the AMP ResourcePolicy resource reference for all available configuration options.
Let's configure AWS Managed Prometheus Resource Policies
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Permissions & Actions
aps:RemoteWrite (write metrics), aps:QueryMetrics (query metrics), aps:GetSeries (retrieve time series), aps:GetLabels (retrieve labels), and aps:GetMetricMetadata (retrieve metadata).aps:RemoteWrite is the only write action. The read-only actions are aps:QueryMetrics, aps:GetSeries, aps:GetLabels, and aps:GetMetricMetadata.Access Patterns
type: "AWS" and specify the account root ARN as the identifier (e.g., arn:aws:iam::123456789012:root), as shown in the Cross-Account Access example.type: "Service" and the service identifier (e.g., grafana.amazonaws.com), as shown in the Service-Specific Access example.Common Issues & Limitations
arn property in your policy document.Using a different cloud?
Explore monitoring guides for other cloud providers: