AWSTemplateFormatVersion: '2010-09-09' Description: > persoNAS — IAM user with scoped S3 access for mapped-drive style use. Parameters: UserName: Type: String Default: personas-storage-user Description: IAM user name for S3 access AllowedPattern: '[a-zA-Z0-9_+=,.@-]+' Resources: PersoNASUser: Type: AWS::IAM::User Properties: UserName: !Ref UserName Tags: - Key: Purpose Value: persoNAS-storage-integration - Key: ManagedBy Value: CloudFormation PersoNASUserPolicy: Type: AWS::IAM::Policy Properties: PolicyName: !Sub '${UserName}-persoNAS-s3-scoped' Users: - !Ref PersoNASUser PolicyDocument: Version: '2012-10-17' Statement: - Sid: ListAccountBuckets Effect: Allow Action: - s3:ListAllMyBuckets - s3:GetBucketLocation Resource: '*' - Sid: BucketMetadata Effect: Allow Action: - s3:ListBucket - s3:ListBucketVersions - s3:ListBucketMultipartUploads - s3:GetBucketVersioning - s3:PutBucketVersioning Resource: 'arn:aws:s3:::*' - Sid: ObjectReadWrite Effect: Allow Action: - s3:GetObject - s3:PutObject - s3:DeleteObject - s3:AbortMultipartUpload - s3:ListMultipartUploadParts - s3:GetObjectVersion - s3:DeleteObjectVersion Resource: 'arn:aws:s3:::*/*' - Sid: CreateBucket Effect: Allow Action: - s3:CreateBucket Resource: 'arn:aws:s3:::*' PersoNASAccessKey: Type: AWS::IAM::AccessKey Properties: UserName: !Ref PersoNASUser DependsOn: PersoNASUser Outputs: UserName: Description: IAM user name Value: !Ref PersoNASUser AccessKeyId: Description: Access Key ID — copy into persoNAS Value: !Ref PersoNASAccessKey SecretAccessKey: Description: Secret Access Key — copy once into persoNAS Value: !GetAtt PersoNASAccessKey.SecretAccessKey DeepLinkExample: Description: Example deep link pattern (replace placeholders; treat as secret) Value: !Sub 'personas://connect?provider=aws&accessKeyId=${PersoNASAccessKey}&secretAccessKey=${PersoNASAccessKey.SecretAccessKey}®ion=${AWS::Region}'