You can use tags to control access from FlexStack services to other AWS resources in your account that support tagging. "Resources" include everything from EC2 instances, SNS topic, and S3 buckets to IAM roles.
How it works
Each request you make to AWS specifies a resource, action, and principal (role). When you try to access a particular resource, AWS checks that your service (the principal) is authorized to perform an action on that resource before continuing with the request.
Tags can be used to conditionally allow a role to access resources in a policy statement, for example if a tag matches a particular pattern. FlexStack adds tags to your resources that describe the project, environment, and component they belong to e.g. FlexStack:ComponentID
and these tags can be added to roles as filters using the "Conditions" property in policy statements.
Every FlexStack service is assigned an IAM role that allows it to access resources when certain magic tags are added to those resources. When you add these magic tags to your AWS resources, the role stipulates that the FlexStack service may access that resource. This simple, powerful pattern is called resource RBAC.
Allow full access to resources
Add one of the tags below to an AWS resource to allow full access to it from a project, environment, or component.
From every service in a project
Replace PROJECT_ID with the ID of your project.
Key | Value |
---|---|
FlexStack:ProjectID:PROJECT_ID:Role | FullAccess |
From every service in an environment
Replace ENVIRONMENT_ID with the ID of your project.
Key | Value |
---|---|
FlexStack:EnvironmentID:ENVIRONMENT_ID:Role | FullAccess |
From a specific service in an environment
Replace COMPONENT_ID with the ID of your project.
Key | Value |
---|---|
FlexStack:ComponentID:COMPONENT_ID:Role | FullAccess |
Example
Here is an example of an SNS topic that grants full access to an environment with the ID "1CAzN3J6NQQt93NgJqUse4"
Allow read-only access to resources
Add one of the tags below to an AWS resource to allow read-only access to it from a project, environment, or component.
From every service in a project
Replace PROJECT_ID with the ID of your project.
Key | Value |
---|---|
FlexStack:ProjectID:PROJECT_ID:Role | ReadOnlyAccess |
From every service in an environment
Replace ENVIRONMENT_ID with the ID of your project.
Key | Value |
---|---|
FlexStack:EnvironmentID:ENVIRONMENT_ID:Role | ReadOnlyAccess |
From a specific service in an environment
Replace COMPONENT_ID with the ID of your project.
Key | Value |
---|---|
FlexStack:ComponentID:COMPONENT_ID:Role | ReadOnlyAccess |
Example
Here is an example of an SNS topic that grants read-only access to an environment with the ID "1CAzN3J6NQQt93NgJqUse4"
What is read-only access?
Read-only access means something different for each resource in AWS. In selecting our list, we used the AWS ReadOnlyAccess policy as a reference guide.
Our comprehensive list of allowed actions can be found below:
var readOnlyActions = []string{
"a4b:Get*",
"a4b:List*",
"a4b:Search*",
"acm-pca:Describe*",
"acm-pca:Get*",
"acm-pca:List*",
"acm:Describe*",
"acm:Get*",
"acm:List*",
"airflow:ListEnvironments",
"airflow:ListTagsForResource",
"amplify:Get*",
"amplify:List*",
"aoss:BatchGet*",
"aoss:Get*",
"aoss:ListA*",
"apigateway:GET",
"appconfig:Get*",
"appconfig:List*",
"appfabric:Get*",
"appfabric:List*",
"application-autoscaling:Describe*",
"application-autoscaling:ListTagsForResource",
"appmesh:Describe*",
"appmesh:List*",
"appstream:Describe*",
"appstream:List*",
"appsync:Get*",
"appsync:List*",
"aps:Describe*",
"aps:Get*",
"aps:List*",
"aps:Query*",
"arc-zonal-shift:Get*",
"arc-zonal-shift:List*",
"athena:Batch*",
"athena:Get*",
"athena:List*",
"autoscaling:Describe*",
"autoscaling:GetPredictiveScalingForecast",
"aws-portal:View*",
"backup-gateway:Get*",
"backup-gateway:List*",
"backup:Describe*",
"backup:Get*",
"backup:List*",
"batch:Describe*",
"batch:List*",
"bedrock:Get*",
"bedrock:List*",
"braket:Get*",
"braket:Search*",
"cassandra:Select",
"chatbot:Describe*",
"chatbot:Get*",
"chatbot:ListMicrosoft*",
"chime:Get*",
"chime:List*",
"chime:Retrieve*",
"chime:Search*",
"chime:Validate*",
"cloud9:Describe*",
"cloud9:List*",
"clouddirectory:BatchRead",
"clouddirectory:Get*",
"clouddirectory:List*",
"clouddirectory:LookupPolicy",
"cloudformation:Describe*",
"cloudformation:Detect*",
"cloudformation:Estimate*",
"cloudformation:Get*",
"cloudformation:List*",
"cloudformation:ValidateTemplate",
"cloudfront-keyvaluestore:Describe*",
"cloudfront-keyvaluestore:Get*",
"cloudfront-keyvaluestore:List*",
"cloudfront:Describe*",
"cloudfront:Get*",
"cloudfront:List*",
"cloudhsm:Describe*",
"cloudhsm:List*",
"cloudsearch:Describe*",
"cloudsearch:List*",
"cloudwatch:Describe*",
"cloudwatch:GenerateQuery",
"cloudwatch:Get*",
"cloudwatch:List*",
"codeartifact:Describe*",
"codeartifact:Get*",
"codeartifact:List*",
"codeartifact:Read*",
"codebuild:BatchGet*",
"codebuild:Describe*",
"codebuild:List*",
"codecommit:BatchGet*",
"codecommit:Describe*",
"codecommit:Get*",
"codecommit:GitPull",
"codecommit:List*",
"codedeploy:BatchGet*",
"codedeploy:Get*",
"codedeploy:List*",
"codeguru-profiler:Describe*",
"codeguru-profiler:Get*",
"codeguru-profiler:List*",
"codeguru-reviewer:Describe*",
"codeguru-reviewer:Get*",
"codeguru-reviewer:List*",
"codepipeline:Get*",
"codepipeline:List*",
"comprehend:BatchDetect*",
"comprehend:Classify*",
"comprehend:Contains*",
"comprehend:Describe*",
"comprehend:Detect*",
"comprehend:List*",
"config:BatchGetAggregateResourceConfig",
"config:BatchGetResourceConfig",
"config:Deliver*",
"config:Describe*",
"config:Get*",
"config:List*",
"config:SelectAggregateResourceConfig",
"config:SelectResourceConfig",
"connect:Describe*",
"connect:Get*",
"connect:List*",
"databrew:Describe*",
"databrew:List*",
"dataexchange:Get*",
"dataexchange:List*",
"datapipeline:Describe*",
"datapipeline:EvaluateExpression",
"datapipeline:Get*",
"datapipeline:List*",
"datapipeline:QueryObjects",
"datapipeline:Validate*",
"datasync:Describe*",
"datasync:List*",
"dax:BatchGetItem",
"dax:Describe*",
"dax:GetItem",
"dax:ListTags",
"dax:Query",
"dax:Scan",
"deepcomposer:Get*",
"deepcomposer:List*",
"detective:BatchGet*",
"detective:Get*",
"detective:List*",
"detective:SearchGraph",
"devicefarm:Get*",
"devicefarm:List*",
"directconnect:Describe*",
"discovery:Describe*",
"discovery:Get*",
"discovery:List*",
"dlm:Get*",
"dms:Describe*",
"dms:List*",
"dms:Test*",
"drs:Describe*",
"drs:Get*",
"drs:List*",
"ds:Check*",
"ds:Describe*",
"ds:Get*",
"ds:List*",
"ds:Verify*",
"dynamodb:BatchGet*",
"dynamodb:Describe*",
"dynamodb:Get*",
"dynamodb:List*",
"dynamodb:PartiQLSelect",
"dynamodb:Query",
"dynamodb:Scan",
"ec2:Describe*",
"ec2:Get*",
"ec2:ListImagesInRecycleBin",
"ec2:ListSnapshotsInRecycleBin",
"ec2:SearchLocalGatewayRoutes",
"ec2:SearchTransitGatewayRoutes",
"ec2messages:Get*",
"ecr-public:BatchCheckLayerAvailability",
"ecr-public:Describe*",
"ecr-public:Get*",
"ecr-public:List*",
"ecr:BatchCheck*",
"ecr:BatchGet*",
"ecr:Describe*",
"ecr:Get*",
"ecr:List*",
"ecs:Describe*",
"ecs:List*",
"eks:Describe*",
"eks:List*",
"elastic-inference:Describe*",
"elastic-inference:List*",
"elasticache:Describe*",
"elasticache:List*",
"elasticbeanstalk:Check*",
"elasticbeanstalk:Describe*",
"elasticbeanstalk:List*",
"elasticbeanstalk:Request*",
"elasticbeanstalk:Retrieve*",
"elasticbeanstalk:Validate*",
"elasticfilesystem:Describe*",
"elasticfilesystem:ListTagsForResource",
"elasticloadbalancing:Describe*",
"elasticmapreduce:Describe*",
"elasticmapreduce:GetBlockPublicAccessConfiguration",
"elasticmapreduce:List*",
"elasticmapreduce:View*",
"elastictranscoder:List*",
"elastictranscoder:Read*",
"emr-containers:Describe*",
"emr-containers:List*",
"emr-serverless:Get*",
"emr-serverless:List*",
"es:Describe*",
"es:ESHttpGet",
"es:ESHttpHead",
"es:Get*",
"es:List*",
"events:Describe*",
"events:List*",
"events:Test*",
"evidently:Get*",
"evidently:List*",
"evidently:TestSegmentPattern",
"firehose:Describe*",
"firehose:List*",
"forecast:Describe*",
"forecast:Get*",
"forecast:List*",
"forecast:Query*",
"frauddetector:BatchGet*",
"frauddetector:Describe*",
"frauddetector:Get*",
"frauddetector:List*",
"freertos:Describe*",
"freertos:List*",
"fsx:Describe*",
"fsx:List*",
"gamelift:Describe*",
"gamelift:Get*",
"gamelift:List*",
"gamelift:ResolveAlias",
"gamelift:Search*",
"glacier:Describe*",
"glacier:Get*",
"glacier:List*",
"globalaccelerator:Describe*",
"globalaccelerator:List*",
"glue:Batch*",
"glue:CheckSchemaVersionValidity",
"glue:Get*",
"glue:List*",
"glue:QuerySchemaVersionMetadata",
"glue:Search*",
"grafana:Describe*",
"grafana:List*",
"greengrass:DescribeComponent",
"greengrass:Get*",
"greengrass:List*",
"groundstation:DescribeContact",
"groundstation:Get*",
"groundstation:List*",
"guardduty:Describe*",
"guardduty:Get*",
"guardduty:List*",
"health:Describe*",
"iam:Generate*",
"iam:Get*",
"iam:List*",
"iam:Simulate*",
"imagebuilder:Get*",
"imagebuilder:List*",
"importexport:Get*",
"importexport:List*",
"iot:Describe*",
"iot:Get*",
"iot:List*",
"iot1click:Describe*",
"iot1click:Get*",
"iot1click:List*",
"iotanalytics:Describe*",
"iotanalytics:Get*",
"iotanalytics:List*",
"iotanalytics:SampleChannelData",
"iotevents:Describe*",
"iotevents:List*",
"iotfleethub:DescribeApplication",
"iotfleethub:ListApplications",
"iotfleetwise:Get*",
"iotfleetwise:List*",
"iotroborunner:Get*",
"iotroborunner:List*",
"iotsitewise:Describe*",
"iotsitewise:Get*",
"iotsitewise:List*",
"iotwireless:Get*",
"iotwireless:List*",
"ivs:BatchGet*",
"ivs:Get*",
"ivs:List*",
"ivschat:Get*",
"ivschat:ListLoggingConfigurations",
"ivschat:ListRooms",
"ivschat:ListTagsForResource",
"kafka:Describe*",
"kafka:Get*",
"kafka:List*",
"kafkaconnect:Describe*",
"kafkaconnect:List*",
"kendra:BatchGetDocumentStatus",
"kendra:Describe*",
"kendra:Get*",
"kendra:List*",
"kendra:Query",
"kinesis:Describe*",
"kinesis:Get*",
"kinesis:List*",
"kinesisanalytics:Describe*",
"kinesisanalytics:Discover*",
"kinesisanalytics:Get*",
"kinesisanalytics:List*",
"kinesisvideo:Describe*",
"kinesisvideo:Get*",
"kinesisvideo:List*",
"kms:Describe*",
"kms:Get*",
"kms:List*",
"lakeformation:Describe*",
"lakeformation:Get*",
"lakeformation:List*",
"lakeformation:Search*",
"lambda:Get*",
"lambda:List*",
"lex:Describe*",
"lex:Get*",
"lex:List*",
"license-manager:Get*",
"license-manager:List*",
"logs:Describe*",
"logs:FilterLogEvents",
"logs:Get*",
"logs:ListAnomalies",
"logs:ListLogAnomalyDetectors",
"logs:ListLogDeliveries",
"logs:ListTags*",
"logs:StartLiveTail",
"logs:StartQuery",
"logs:StopLiveTail",
"logs:StopQuery",
"logs:TestMetricFilter",
"lookoutmetrics:Get*",
"lookoutmetrics:List*",
"lookoutvision:Describe*",
"lookoutvision:List*",
"machinelearning:Describe*",
"machinelearning:Get*",
"managedblockchain:Get*",
"managedblockchain:List*",
"mediaconnect:Describe*",
"mediaconnect:List*",
"mediaconvert:Describe*",
"mediaconvert:Get*",
"mediaconvert:List*",
"medialive:Describe*",
"medialive:List*",
"mediapackage-vod:Describe*",
"mediapackage-vod:List*",
"mediapackage:Describe*",
"mediapackage:List*",
"mediapackagev2:Get*",
"mediapackagev2:List*",
"mediastore:Describe*",
"mediastore:Get*",
"mediastore:List*",
"memorydb:Describe*",
"memorydb:ListTags",
"mgh:Describe*",
"mgh:GetHomeRegion",
"mgh:List*",
"mgn:Describe*",
"mgn:Get*",
"mgn:List*",
"mobileanalytics:Get*",
"mobiletargeting:Get*",
"mobiletargeting:List*",
"monitron:Get*",
"monitron:List*",
"mq:Describe*",
"mq:List*",
"nimble:Get*",
"nimble:List*",
"notifications-contacts:Get*",
"notifications-contacts:List*",
"notifications:Get*",
"notifications:List*",
"oam:Get*",
"oam:List*",
"omics:Get*",
"omics:List*",
"one:Get*",
"one:List*s",
"opsworks-cm:Describe*",
"opsworks-cm:List*",
"opsworks:Describe*",
"opsworks:Get*",
"organizations:Describe*",
"organizations:List*",
"osis:Get*",
"osis:List*",
"outposts:Get*",
"outposts:List*",
"personalize:Describe*",
"personalize:Get*",
"personalize:List*",
"pi:DescribeDimensionKeys",
"pi:Get*",
"pi:List*",
"pipes:DescribePipe",
"pipes:List*",
"polly:Describe*",
"polly:Get*",
"polly:List*",
"polly:SynthesizeSpeech",
"qldb:Describe*",
"qldb:Get*",
"qldb:List*",
"ram:Get*",
"ram:List*",
"rbin:GetRule",
"rbin:ListRules",
"rbin:ListTagsForResource",
"rds:Describe*",
"rds:Download*",
"rds:List*",
"redshift:Describe*",
"redshift:GetReservedNodeExchangeOfferings",
"redshift:View*",
"rekognition:CompareFaces",
"rekognition:Describe*",
"rekognition:Detect*",
"rekognition:Get*",
"rekognition:List*",
"rekognition:RecognizeCelebrities",
"rekognition:Search*",
"robomaker:BatchDescribe*",
"robomaker:Describe*",
"robomaker:Get*",
"robomaker:List*",
"route53-recovery-cluster:Get*",
"route53-recovery-cluster:ListRoutingControls",
"route53-recovery-control-config:Describe*",
"route53-recovery-control-config:GetResourcePolicy",
"route53-recovery-control-config:List*",
"route53-recovery-readiness:Get*",
"route53-recovery-readiness:List*",
"route53:Get*",
"route53:List*",
"route53:Test*",
"route53domains:Check*",
"route53domains:Get*",
"route53domains:List*",
"route53domains:View*",
"route53resolver:Get*",
"route53resolver:List*",
"s3-object-lambda:Get*",
"s3-object-lambda:List*",
"s3:DescribeJob",
"s3:Get*",
"s3:List*",
"sagemaker-groundtruth-synthetic:Get*",
"sagemaker-groundtruth-synthetic:List*",
"sagemaker:Describe*",
"sagemaker:GetSearchSuggestions",
"sagemaker:List*",
"sagemaker:Search",
"scheduler:Get*",
"scheduler:List*",
"schemas:Describe*",
"schemas:Get*",
"schemas:List*",
"schemas:Search*",
"sdb:Get*",
"sdb:List*",
"sdb:Select*",
"secretsmanager:Describe*",
"secretsmanager:GetResourcePolicy",
"secretsmanager:List*",
"securityhub:BatchGet*",
"securityhub:Describe*",
"securityhub:Get*",
"securityhub:List*",
"serverlessrepo:Get*",
"serverlessrepo:List*",
"serverlessrepo:SearchApplications",
"servicecatalog:Describe*",
"servicecatalog:Get*",
"servicecatalog:List*",
"servicecatalog:Scan*",
"servicecatalog:Search*",
"servicediscovery:Discover*",
"servicediscovery:Get*",
"servicediscovery:List*",
"ses:BatchGetMetricData",
"ses:Describe*",
"ses:Get*",
"ses:List*",
"shield:Describe*",
"shield:Get*",
"shield:List*",
"signer:Describe*",
"signer:Get*",
"signer:List*",
"sms-voice:Describe*",
"sms-voice:List*",
"snowball:Describe*",
"snowball:Get*",
"snowball:List*",
"sns:Check*",
"sns:Get*",
"sns:List*",
"sqs:Get*",
"sqs:List*",
"sqs:Receive*",
"ssm-contacts:Describe*",
"ssm-contacts:Get*",
"ssm-contacts:List*",
"ssm-incidents:Get*",
"ssm-incidents:List*",
"ssm:Describe*",
"ssm:Get*",
"ssm:List*",
"states:Describe*",
"states:GetExecutionHistory",
"states:List*",
"storagegateway:Describe*",
"storagegateway:List*",
"sts:GetAccessKeyInfo",
"sts:GetCallerIdentity",
"sts:GetSessionToken",
"swf:Count*",
"swf:Describe*",
"swf:Get*",
"swf:List*",
"synthetics:Describe*",
"synthetics:Get*",
"synthetics:List*",
"tag:DescribeReportCreation",
"timestream:Describe*",
"timestream:List*",
"tnb:Get*",
"tnb:List*",
"transcribe:Get*",
"transcribe:List*",
"transfer:Describe*",
"transfer:List*",
"transfer:TestIdentityProvider",
"translate:DescribeTextTranslationJob",
"translate:GetParallelData",
"translate:GetTerminology",
"translate:ListParallelData",
"translate:ListTerminologies",
"translate:ListTextTranslationJobs",
"trustedadvisor:Describe*",
"vpc-lattice:Get*",
"vpc-lattice:List*",
"waf-regional:Get*",
"waf-regional:List*",
"waf:Get*",
"waf:List*",
"wafv2:CheckCapacity",
"wafv2:Describe*",
"wafv2:Get*",
"wafv2:List*",
"workdocs:CheckAlias",
"workdocs:Describe*",
"workdocs:Get*",
"workmail:Describe*",
"workmail:Get*",
"workmail:List*",
"workmail:Search*",
"xray:BatchGet*",
"xray:Get*",
}