Lustre ファイルシステムは S3 にどの IAM でアクセスしているのか調べてみた
こんにちは!AWS 事業本部コンサルティング部のたかくに(@takakuni_)です。
最近、FSx for Lustre を触る機会がありまして、 Lustre は S3 にどの IAM でアクセスしているのか気になったので調べてみました。
Terraform で定義する部分がない
ことの発端はインフラの構築を HashiCorp Terraform で作成していたことから始まります。
Lustre ファイルシステムは aws_fsx_lustre_file_system
と aws_fsx_data_repository_association
で作成します。
IAM を定義する部分がないですね。
###################################################
# Lustre File System
###################################################
resource "aws_fsx_lustre_file_system" "this" {
storage_type = "SSD"
file_system_type_version = "2.15"
storage_capacity = 1200
security_group_ids = [aws_security_group.lustre.id]
subnet_ids = [module.vpc.private_subnets[0]]
data_compression_type = "LZ4"
deployment_type = "PERSISTENT_2"
per_unit_storage_throughput = 250
metadata_configuration {
mode = "AUTOMATIC"
}
}
resource "aws_fsx_data_repository_association" "this" {
file_system_id = aws_fsx_lustre_file_system.this.id
data_repository_path = "s3://${aws_s3_bucket.data_repository.bucket}"
file_system_path = "/data-repository"
s3 {
auto_export_policy {
events = ["NEW", "CHANGED", "DELETED"]
}
auto_import_policy {
events = ["NEW", "CHANGED", "DELETED"]
}
}
}
バケットポリシー側も確認してみましたが、とくに更新されていないですね。
一体、どこで操作権限を管理しているのでしょうか。
結論
結論、 Lustre クラスターを作成した際に AWS 側で 2 つのサービスリンクロールを作成します。
- AWSServiceRoleForAmazonFSx
- AWSServiceRoleForFSxS3Access_fs-01234567890
このうちの AWSServiceRoleForFSxS3Access_fs-01234567890 の方で S3 とのやりとりを行います。
Amazon FSx uses two service-linked roles named AWSServiceRoleForAmazonFSx and AWSServiceRoleForFSxS3Access_fs-01234567890 that perform certain actions in your account. Examples of these actions are creating elastic network interfaces for your file systems in your VPC and accessing your data repository in an Amazon S3 bucket. For AWSServiceRoleForFSxS3Access_fs-01234567890, this service-linked role is created for each Amazon FSx for Lustre file system you create that is linked to an S3 bucket.
AWSServiceRoleForAmazonFSx
AWSServiceRoleForAmazonFSx の方は何をしているのだろう。となりますよね。
AWSServiceRoleForAmazonFSx は ENI の作成や CloudWatch Logs へのメトリクス発行を行うようです。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CreateFileSystem",
"Effect": "Allow",
"Action": [
"ds:AuthorizeApplication",
"ds:GetAuthorizedApplicationDetails",
"ds:UnauthorizeApplication",
"ec2:CreateNetworkInterface",
"ec2:CreateNetworkInterfacePermission",
"ec2:DeleteNetworkInterface",
"ec2:DescribeAddresses",
"ec2:DescribeDhcpOptions",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeRouteTables",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVPCs",
"ec2:DisassociateAddress",
"ec2:GetSecurityGroupsForVpc",
"route53:AssociateVPCWithHostedZone"
],
"Resource": "*"
},
{
"Sid": "PutMetrics",
"Effect": "Allow",
"Action": ["cloudwatch:PutMetricData"],
"Resource": ["*"],
"Condition": {
"StringEquals": {
"cloudwatch:namespace": "AWS/FSx"
}
}
},
{
"Sid": "TagResourceNetworkInterface",
"Effect": "Allow",
"Action": ["ec2:CreateTags"],
"Resource": ["arn:aws:ec2:*:*:network-interface/*"],
"Condition": {
"StringEquals": {
"ec2:CreateAction": "CreateNetworkInterface"
},
"ForAllValues:StringEquals": {
"aws:TagKeys": "AmazonFSx.FileSystemId"
}
}
},
{
"Sid": "ManageNetworkInterface",
"Effect": "Allow",
"Action": [
"ec2:AssignPrivateIpAddresses",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:UnassignPrivateIpAddresses"
],
"Resource": ["arn:aws:ec2:*:*:network-interface/*"],
"Condition": {
"Null": {
"aws:ResourceTag/AmazonFSx.FileSystemId": "false"
}
}
},
{
"Sid": "ManageRouteTable",
"Effect": "Allow",
"Action": ["ec2:CreateRoute", "ec2:ReplaceRoute", "ec2:DeleteRoute"],
"Resource": ["arn:aws:ec2:*:*:route-table/*"],
"Condition": {
"StringEquals": {
"aws:ResourceTag/AmazonFSx": "ManagedByAmazonFSx"
}
}
},
{
"Sid": "PutCloudWatchLogs",
"Effect": "Allow",
"Action": [
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:log-group:/aws/fsx/*"
},
{
"Sid": "ManageAuditLogs",
"Effect": "Allow",
"Action": [
"firehose:DescribeDeliveryStream",
"firehose:PutRecord",
"firehose:PutRecordBatch"
],
"Resource": "arn:aws:firehose:*:*:deliverystream/aws-fsx-*"
}
]
}
また、 AWSServiceRoleForAmazonFSx は FSx for Lustre ファイルシステム全体で利用されます。
The AWSServiceRoleForAmazonFSx is used by all Amazon FSx file system types; some of the listed permissions are not applicable to FSx for Lustre.
やってみる
Lustre ファイルシステムの作成
それでは、 Lustre ファイルシステムを作成して、 IAM ロールの挙動を確認してみましょう。
Terraform で諸々作成します。
###################################################
# Provider
###################################################
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.81.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
data "aws_caller_identity" "self" {}
data "aws_region" "current" {}
locals {
prefix = "dev"
region = data.aws_region.current.name
}
###################################################
# Network
###################################################
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = local.prefix
cidr = "10.0.0.0/16"
azs = ["${local.region}a"]
private_subnets = ["10.0.1.0/24"]
}
###################################################
# Security Group for Lustre File System
###################################################
resource "aws_security_group" "lustre" {
name = "${local.prefix}-lustre-sg"
vpc_id = module.vpc.vpc_id
description = "${local.prefix}-hyperpod-sg"
tags = {
Name = "${local.prefix}-lustre-sg"
}
}
# Ingress
resource "aws_vpc_security_group_ingress_rule" "lustre_all_traffic_self" {
security_group_id = aws_security_group.lustre.id
referenced_security_group_id = aws_security_group.lustre.id
ip_protocol = "-1"
}
# Egress
resource "aws_vpc_security_group_egress_rule" "lustre_all_traffic_self" {
security_group_id = aws_security_group.lustre.id
referenced_security_group_id = aws_security_group.lustre.id
ip_protocol = "-1"
}
###################################################
# Data Repository for Lustre File System
###################################################
resource "aws_s3_bucket" "data_repository" {
bucket = "${local.prefix}-data-${local.account_id}"
force_destroy = true
}
resource "aws_s3_bucket_public_access_block" "data_repository" {
bucket = aws_s3_bucket.data_repository.bucket
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_ownership_controls" "data_repository" {
bucket = aws_s3_bucket.data_repository.bucket
rule {
object_ownership = "BucketOwnerPreferred"
}
}
###################################################
# Lustre File System
###################################################
resource "aws_fsx_lustre_file_system" "this" {
storage_type = "SSD"
file_system_type_version = "2.15"
storage_capacity = 1200
security_group_ids = [aws_security_group.lustre.id]
subnet_ids = [module.vpc.private_subnets[0]]
data_compression_type = "LZ4"
deployment_type = "PERSISTENT_2"
per_unit_storage_throughput = 250
metadata_configuration {
mode = "AUTOMATIC"
}
}
resource "aws_fsx_data_repository_association" "this" {
file_system_id = aws_fsx_lustre_file_system.this.id
data_repository_path = "s3://${aws_s3_bucket.data_repository.bucket}"
file_system_path = "/data-repository"
s3 {
auto_export_policy {
events = ["NEW", "CHANGED", "DELETED"]
}
auto_import_policy {
events = ["NEW", "CHANGED", "DELETED"]
}
}
}
IAM コンソールを見てみます。AWSServiceRoleForFSxS3Access_fs-01234567890
が作成されていますね。
信頼されたエンティティには s3.data-source.lustre.fsx.amazonaws.com
が許可されています。非常に興味深いです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "s3.data-source.lustre.fsx.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
ポリシーの中身を見てみる
AWSServiceRoleForFSxS3Access_fs-01234567890
の IAM ポリシーを見てみましょう。許可ポリシーが 2 つ付与されています。
FSxDeleteServiceLinkedRoleAccess
FSxDeleteServiceLinkedRoleAccess は Lustre と S3 の関連付け削除時に IAM 自体を削除するためのポリシーのようです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:DeleteServiceLinkedRole",
"iam:GetServiceLinkedRoleDeletionStatus",
"iam:GetRole"
],
"Resource": "arn:*:iam::*:role/aws-service-role/s3.data-source.lustre.fsx.amazonaws.com/AWSServiceRoleForFSxS3Access_*"
}
]
}
FSxS3Access
カスタマーインラインで定義された FSxS3Access
ポリシーも見てみます。特定の S3 バケットに対して S3 API の許可が行われていますね。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:PutObject",
"s3:Get*",
"s3:List*",
"s3:PutBucketNotification"
],
"Resource": [
"arn:aws:s3:::dev-data-123456789012/*",
"arn:aws:s3:::dev-data-123456789012"
]
}
]
}
アタッチを増やしてみる
それでは、S3 との関連性を増やしてみましょう。
###################################################
# Provider
###################################################
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.81.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
data "aws_caller_identity" "self" {}
data "aws_region" "current" {}
locals {
prefix = "dev"
region = data.aws_region.current.name
}
###################################################
# Network
###################################################
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = local.prefix
cidr = "10.0.0.0/16"
azs = ["${local.region}a"]
private_subnets = ["10.0.1.0/24"]
}
###################################################
# Security Group for Lustre File System
###################################################
resource "aws_security_group" "lustre" {
name = "${local.prefix}-lustre-sg"
vpc_id = module.vpc.vpc_id
description = "${local.prefix}-hyperpod-sg"
tags = {
Name = "${local.prefix}-lustre-sg"
}
}
# Ingress
resource "aws_vpc_security_group_ingress_rule" "lustre_all_traffic_self" {
security_group_id = aws_security_group.lustre.id
referenced_security_group_id = aws_security_group.lustre.id
ip_protocol = "-1"
}
# Egress
resource "aws_vpc_security_group_egress_rule" "lustre_all_traffic_self" {
security_group_id = aws_security_group.lustre.id
referenced_security_group_id = aws_security_group.lustre.id
ip_protocol = "-1"
}
###################################################
# Data Repository for Lustre File System
###################################################
resource "aws_s3_bucket" "data_repository" {
bucket = "${local.prefix}-data-${local.account_id}"
force_destroy = true
}
resource "aws_s3_bucket_public_access_block" "data_repository" {
bucket = aws_s3_bucket.data_repository.bucket
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_ownership_controls" "data_repository" {
bucket = aws_s3_bucket.data_repository.bucket
rule {
object_ownership = "BucketOwnerPreferred"
}
}
+ resource "aws_s3_bucket" "data_repository_2" {
+ bucket = "${local.prefix}-data2-${local.account_id}"
+ force_destroy = true
+ }
+
+ resource "aws_s3_bucket_public_access_block" "data_repository_2" {
+ bucket = aws_s3_bucket.data_repository_2.bucket
+ block_public_acls = true
+ block_public_policy = true
+ ignore_public_acls = true
+ restrict_public_buckets = true
+ }
+
+ resource "aws_s3_bucket_ownership_controls" "data_repository_2" {
+ bucket = aws_s3_bucket.data_repository_2.bucket
+ rule {
+ object_ownership = "BucketOwnerPreferred"
+ }
+ }
###################################################
# Lustre File System
###################################################
resource "aws_fsx_lustre_file_system" "this" {
storage_type = "SSD"
file_system_type_version = "2.15"
storage_capacity = 1200
security_group_ids = [aws_security_group.lustre.id]
subnet_ids = [module.vpc.private_subnets[0]]
data_compression_type = "LZ4"
deployment_type = "PERSISTENT_2"
per_unit_storage_throughput = 250
metadata_configuration {
mode = "AUTOMATIC"
}
}
resource "aws_fsx_data_repository_association" "this" {
file_system_id = aws_fsx_lustre_file_system.this.id
data_repository_path = "s3://${aws_s3_bucket.data_repository.bucket}"
file_system_path = "/data-repository"
s3 {
auto_export_policy {
events = ["NEW", "CHANGED", "DELETED"]
}
auto_import_policy {
events = ["NEW", "CHANGED", "DELETED"]
}
}
}
+ resource "aws_fsx_data_repository_association" "this_2" {
+ file_system_id = aws_fsx_lustre_file_system.this.id
+ data_repository_path = "s3://${aws_s3_bucket.data_repository_2.bucket}"
+ file_system_path = "/data-repository2"
+
+ s3 {
+ auto_export_policy {
+ events = ["NEW", "CHANGED", "DELETED"]
+ }
+
+ auto_import_policy {
+ events = ["NEW", "CHANGED", "DELETED"]
+ }
+ }
+ }
IAM ポリシーが増える形ではなく FSxS3Access のリソース句がアップデートされました。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:PutObject",
"s3:Get*",
"s3:List*",
"s3:PutBucketNotification"
],
"Resource": [
"arn:aws:s3:::dev-data2-123456789012/*",
"arn:aws:s3:::dev-data-123456789012/*",
"arn:aws:s3:::dev-data2-123456789012",
"arn:aws:s3:::dev-data-123456789012"
]
}
]
}
何を気にしていたかというと IAM ロールにアタッチ可能な IAM ポリシーの数は固定値で 20 までなので、どういった形で抜けているのか気になった次第でした。
Lustre と S3 の関連性に関してはとくに言及されていないようでした。
変更して良いのか
編集ができないと記載されていますね。
Amazon FSx does not allow you to edit these service-linked roles. After you create a service-linked role, you cannot change the name of the role because various entities might reference the role. However, you can edit the description of the role using IAM. For more information, see Editing a service-linked role in the IAM User Guide.
確かにサービスリンクロールのため、説明以外変更するボタンがなかったです。
まとめ
以上、「Lustre ファイルシステムは S3 にどの IAM でアクセスしているのか調べてみた」でした。
「そういえば、 Terraform で IAM を定義していないな」と思ったので調べてみました。このブログがどなたかの参考になれば幸いです。
AWS 事業本部コンサルティング部のたかくに(@takakuni_)でした!