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 & Prerequisites
aws.lakeformation.DataLakeSettings to remove IAMAllowedPrincipals default permissions and configure admins. Without this setup, using this resource will not secure your data and will result in 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.Common Errors & Pitfalls
IAMAllowedPrincipals is a pseudo-entity group for backwards compatibility with AWS Glue that includes IAM users and roles allowed access by IAM policies. It conflicts with individual Lake Formation permissions and causes unexpected behavior, such as granting broader permissions than intended.permissions and permissionsWithGrantOption to overwrite implicit permissions before revoking.columnNames, which narrows their implicit permissions. Instead, set wildcard to true and remove columnNames.SELECT on a specific column may result in SELECT on all columns (wildcard) if IAMAllowedPrincipals permissions exist on the table.Principal Configuration
principal. Administrators have implicit permissions that cause errors when this resource tries to revoke them. Manage administrator permissions using aws.lakeformation.DataLakeSettings instead.IAM_ALLOWED_PRINCIPALS, IAM roles, users, groups, Federated Users, SAML groups and users, QuickSight groups, OUs, organizations, and AWS account IDs for cross-account permissions.Permissions & Grant Options
permissions are the permissions granted to the principal. permissionsWithGrantOption is a subset of permissions that the principal can pass to others (grant to other principals).ALL, ALTER, ASSOCIATE, CREATE_DATABASE, CREATE_TABLE, DATA_LOCATION_ACCESS, DELETE, DESCRIBE, DROP, INSERT, and SELECT.lfTagPolicy with resourceType and expressions containing key-value pairs. For example, you can grant permissions to resources tagged with Team: Sales and Environment: Dev or Production.Resource Types & Immutability
dataLocation, database, lfTag, lfTagPolicy, table, tableWithColumns, dataCellsFilter, or catalogResource. You must specify exactly one of these.principal, permissions, permissionsWithGrantOption, and all resource type properties are immutable. You must destroy and recreate the resource to change them.