The aws:lakeformation/permissions:Permissions resource, part of the Pulumi AWS provider, grants Lake Formation permissions to principals for accessing Data Catalog metadata and underlying S3 data. This guide focuses on three capabilities: S3 data location access, database-level permissions, and tag-based access control.
Lake Formation permissions reference existing IAM roles, Glue databases, registered S3 resources, and LF-tags. The examples are intentionally small. Combine them with your own IAM roles, Data Catalog resources, and Lake Formation configuration.
Grant access to S3 data locations
Data lake workflows often begin by granting principals access to S3 locations registered with Lake Formation, enabling them to read or write data through Lake Formation’s permission model.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.lakeformation.Permissions("example", {
principal: workflowRole.arn,
permissions: ["DATA_LOCATION_ACCESS"],
dataLocation: {
arn: exampleAwsLakeformationResource.arn,
},
});
import pulumi
import pulumi_aws as aws
example = aws.lakeformation.Permissions("example",
principal=workflow_role["arn"],
permissions=["DATA_LOCATION_ACCESS"],
data_location={
"arn": example_aws_lakeformation_resource["arn"],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lakeformation"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := lakeformation.NewPermissions(ctx, "example", &lakeformation.PermissionsArgs{
Principal: pulumi.Any(workflowRole.Arn),
Permissions: pulumi.StringArray{
pulumi.String("DATA_LOCATION_ACCESS"),
},
DataLocation: &lakeformation.PermissionsDataLocationArgs{
Arn: pulumi.Any(exampleAwsLakeformationResource.Arn),
},
})
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.LakeFormation.Permissions("example", new()
{
Principal = workflowRole.Arn,
PermissionDetails = new[]
{
"DATA_LOCATION_ACCESS",
},
DataLocation = new Aws.LakeFormation.Inputs.PermissionsDataLocationArgs
{
Arn = exampleAwsLakeformationResource.Arn,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lakeformation.Permissions;
import com.pulumi.aws.lakeformation.PermissionsArgs;
import com.pulumi.aws.lakeformation.inputs.PermissionsDataLocationArgs;
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 Permissions("example", PermissionsArgs.builder()
.principal(workflowRole.arn())
.permissions("DATA_LOCATION_ACCESS")
.dataLocation(PermissionsDataLocationArgs.builder()
.arn(exampleAwsLakeformationResource.arn())
.build())
.build());
}
}
resources:
example:
type: aws:lakeformation:Permissions
properties:
principal: ${workflowRole.arn}
permissions:
- DATA_LOCATION_ACCESS
dataLocation:
arn: ${exampleAwsLakeformationResource.arn}
The dataLocation block references an S3 resource registered with Lake Formation. The DATA_LOCATION_ACCESS permission allows the principal to access data at that location. The principal property specifies the IAM role ARN that receives the permission.
Grant database-level permissions
Teams building data pipelines grant database permissions to roles that create tables, modify schemas, or manage database objects within the Glue Data Catalog.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.lakeformation.Permissions("example", {
principal: workflowRole.arn,
permissions: [
"CREATE_TABLE",
"ALTER",
"DROP",
],
database: {
name: exampleAwsGlueCatalogDatabase.name,
catalogId: "110376042874",
},
});
import pulumi
import pulumi_aws as aws
example = aws.lakeformation.Permissions("example",
principal=workflow_role["arn"],
permissions=[
"CREATE_TABLE",
"ALTER",
"DROP",
],
database={
"name": example_aws_glue_catalog_database["name"],
"catalog_id": "110376042874",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lakeformation"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := lakeformation.NewPermissions(ctx, "example", &lakeformation.PermissionsArgs{
Principal: pulumi.Any(workflowRole.Arn),
Permissions: pulumi.StringArray{
pulumi.String("CREATE_TABLE"),
pulumi.String("ALTER"),
pulumi.String("DROP"),
},
Database: &lakeformation.PermissionsDatabaseArgs{
Name: pulumi.Any(exampleAwsGlueCatalogDatabase.Name),
CatalogId: pulumi.String("110376042874"),
},
})
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.LakeFormation.Permissions("example", new()
{
Principal = workflowRole.Arn,
PermissionDetails = new[]
{
"CREATE_TABLE",
"ALTER",
"DROP",
},
Database = new Aws.LakeFormation.Inputs.PermissionsDatabaseArgs
{
Name = exampleAwsGlueCatalogDatabase.Name,
CatalogId = "110376042874",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lakeformation.Permissions;
import com.pulumi.aws.lakeformation.PermissionsArgs;
import com.pulumi.aws.lakeformation.inputs.PermissionsDatabaseArgs;
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 Permissions("example", PermissionsArgs.builder()
.principal(workflowRole.arn())
.permissions(
"CREATE_TABLE",
"ALTER",
"DROP")
.database(PermissionsDatabaseArgs.builder()
.name(exampleAwsGlueCatalogDatabase.name())
.catalogId("110376042874")
.build())
.build());
}
}
resources:
example:
type: aws:lakeformation:Permissions
properties:
principal: ${workflowRole.arn}
permissions:
- CREATE_TABLE
- ALTER
- DROP
database:
name: ${exampleAwsGlueCatalogDatabase.name}
catalogId: '110376042874'
The database block identifies the Glue Catalog database by name and catalog ID. The permissions array specifies what operations the principal can perform: CREATE_TABLE for adding tables, ALTER for modifying schemas, and DROP for removing objects. These permissions apply to the database and its contents.
Grant permissions using LF-tag policies
Organizations managing many databases and tables use LF-tag policies to grant permissions based on metadata tags rather than individual resource ARNs, simplifying access control at scale.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = new aws.lakeformation.Permissions("test", {
principal: salesRole.arn,
permissions: [
"CREATE_TABLE",
"ALTER",
"DROP",
],
lfTagPolicy: {
resourceType: "DATABASE",
expressions: [
{
key: "Team",
values: ["Sales"],
},
{
key: "Environment",
values: [
"Dev",
"Production",
],
},
],
},
});
import pulumi
import pulumi_aws as aws
test = aws.lakeformation.Permissions("test",
principal=sales_role["arn"],
permissions=[
"CREATE_TABLE",
"ALTER",
"DROP",
],
lf_tag_policy={
"resource_type": "DATABASE",
"expressions": [
{
"key": "Team",
"values": ["Sales"],
},
{
"key": "Environment",
"values": [
"Dev",
"Production",
],
},
],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lakeformation"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := lakeformation.NewPermissions(ctx, "test", &lakeformation.PermissionsArgs{
Principal: pulumi.Any(salesRole.Arn),
Permissions: pulumi.StringArray{
pulumi.String("CREATE_TABLE"),
pulumi.String("ALTER"),
pulumi.String("DROP"),
},
LfTagPolicy: &lakeformation.PermissionsLfTagPolicyArgs{
ResourceType: pulumi.String("DATABASE"),
Expressions: lakeformation.PermissionsLfTagPolicyExpressionArray{
&lakeformation.PermissionsLfTagPolicyExpressionArgs{
Key: pulumi.String("Team"),
Values: pulumi.StringArray{
pulumi.String("Sales"),
},
},
&lakeformation.PermissionsLfTagPolicyExpressionArgs{
Key: pulumi.String("Environment"),
Values: pulumi.StringArray{
pulumi.String("Dev"),
pulumi.String("Production"),
},
},
},
},
})
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 test = new Aws.LakeFormation.Permissions("test", new()
{
Principal = salesRole.Arn,
PermissionDetails = new[]
{
"CREATE_TABLE",
"ALTER",
"DROP",
},
LfTagPolicy = new Aws.LakeFormation.Inputs.PermissionsLfTagPolicyArgs
{
ResourceType = "DATABASE",
Expressions = new[]
{
new Aws.LakeFormation.Inputs.PermissionsLfTagPolicyExpressionArgs
{
Key = "Team",
Values = new[]
{
"Sales",
},
},
new Aws.LakeFormation.Inputs.PermissionsLfTagPolicyExpressionArgs
{
Key = "Environment",
Values = new[]
{
"Dev",
"Production",
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lakeformation.Permissions;
import com.pulumi.aws.lakeformation.PermissionsArgs;
import com.pulumi.aws.lakeformation.inputs.PermissionsLfTagPolicyArgs;
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 test = new Permissions("test", PermissionsArgs.builder()
.principal(salesRole.arn())
.permissions(
"CREATE_TABLE",
"ALTER",
"DROP")
.lfTagPolicy(PermissionsLfTagPolicyArgs.builder()
.resourceType("DATABASE")
.expressions(
PermissionsLfTagPolicyExpressionArgs.builder()
.key("Team")
.values("Sales")
.build(),
PermissionsLfTagPolicyExpressionArgs.builder()
.key("Environment")
.values(
"Dev",
"Production")
.build())
.build())
.build());
}
}
resources:
test:
type: aws:lakeformation:Permissions
properties:
principal: ${salesRole.arn}
permissions:
- CREATE_TABLE
- ALTER
- DROP
lfTagPolicy:
resourceType: DATABASE
expressions:
- key: Team
values:
- Sales
- key: Environment
values:
- Dev
- Production
The lfTagPolicy block grants permissions to all resources matching the specified tag expressions. The resourceType property sets whether the policy applies to databases, tables, or other resource types. The expressions array defines tag key-value pairs that resources must match. This configuration grants permissions to all databases tagged with Team=Sales and Environment matching either Dev or Production.
Beyond these examples
These snippets focus on specific Lake Formation permission features: S3 data location access, database-level permissions, and tag-based access control. They’re intentionally minimal rather than full data lake access control configurations.
The examples reference pre-existing infrastructure such as IAM roles for principals, Glue Catalog databases, S3 resources registered with Lake Formation, and LF-tags attached to resources. They focus on granting permissions rather than provisioning the underlying resources.
To keep things focused, common permission patterns are omitted, including:
- Grant options (permissionsWithGrantOption)
- Table and column-level permissions
- Data cells filter permissions
- Catalog-wide permissions (catalogResource)
- IAMAllowedPrincipals configuration and removal
These omissions are intentional: the goal is to illustrate how each permission type is wired, not provide drop-in access control modules. See the Lake Formation Permissions resource reference for all available configuration options.
Let's configure AWS Lake Formation Permissions
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Setup & Default Behavior
aws.lakeformation.DataLakeSettings and remove existing IAMAllowedPrincipals permissions, or your data will not be secured and you’ll encounter errors.aws.lakeformation.Permissions with aws.lakeformation.DataLakeSettings to remove IAMAllowedPrincipals, OR (2) Use IAMAllowedPrincipals without aws.lakeformation.Permissions. Combining them causes unexpected behavior and errors.IAMAllowedPrincipals permissions. Then configure aws.lakeformation.DataLakeSettings to clear createDatabaseDefaultPermissions and createTableDefaultPermissions.Principal & Administrator Permissions
principal will cause errors when the resource is destroyed because you cannot revoke implicit permissions. Manage administrator rights using aws.lakeformation.DataLakeSettings instead.principal receiving permissions in this resource, since it already has implicit permissions.IAMAllowedPrincipals & Pseudo-Groups
IAMAllowedPrincipals is a pseudo-entity group for backwards compatibility with AWS Glue. It includes any IAM users and roles allowed access to your Data Catalog resources by your IAM policies. It conflicts with individual Lake Formation permissions.SELECT on a specific column will grant SELECT on all columns (wildcard) if the table has IAMAllowedPrincipals permissions, instead of just the specified column.AllIAMPrincipals is a pseudo-entity group that includes all IAMs in the account. Use the format 123456789012:IAMPrincipals as the principal value to grant permissions to all IAM entities in account 123456789012.Common Errors
permissions and permissionsWithGrantOption to overwrite the implicit ones.columnNames to a principal who is also an administrator. This narrows their implicit permissions, which is not allowed. Instead, set wildcard to true and remove columnNames.Configuration & Resource Types
ALL, ALTER, ASSOCIATE, CREATE_DATABASE, CREATE_TABLE, DATA_LOCATION_ACCESS, DELETE, DESCRIBE, DROP, INSERT, and SELECT. Use permissionsWithGrantOption to specify which permissions the principal can pass to others.dataLocation, database, lfTag, lfTagPolicy, table, tableWithColumns) are immutable after creation. You must destroy and recreate the resource to change the resource type.