Header menu logo FsCDK

IAM AWS IAM Managed Policy

AWS Managed Policies are standalone identity-based policies that you can attach to multiple users, groups, and roles. They provide reusable permission sets following the principle of least privilege.

Quick Start

#r "../src/bin/Release/net8.0/publish/Amazon.JSII.Runtime.dll"
#r "../src/bin/Release/net8.0/publish/Constructs.dll"
#r "../src/bin/Release/net8.0/publish/Amazon.CDK.Lib.dll"
#r "../src/bin/Release/net8.0/publish/FsCDK.dll"

open FsCDK
open Amazon.CDK
open Amazon.CDK.AWS.IAM
open Amazon.CDK.AWS.S3

Basic Managed Policy

Create a managed policy with explicit permissions.

stack "BasicManagedPolicy" {
    managedPolicy "S3ReadPolicy" {
        description "Read-only access to S3 bucket"
        managedPolicyName "S3ReadOnlyPolicy"

        policyStatement {
            effect Effect.ALLOW
            actions [ "s3:GetObject"; "s3:ListBucket" ]
            resources [ "arn:aws:s3:::my-bucket"; "arn:aws:s3:::my-bucket/*" ]
        }
    }
}

Policy with Multiple Statements

Combine multiple permissions in a single policy.

stack "MultiStatementPolicy" {
    let s3Statement =
        PolicyStatement(
            PolicyStatementProps(
                Sid = "S3Access",
                Effect = Effect.ALLOW,
                Actions = [| "s3:GetObject"; "s3:PutObject" |],
                Resources = [| "arn:aws:s3:::data-bucket/*" |]
            )
        )

    let dynamoStatement =
        PolicyStatement(
            PolicyStatementProps(
                Sid = "DynamoDBAccess",
                Effect = Effect.ALLOW,
                Actions = [| "dynamodb:GetItem"; "dynamodb:PutItem" |],
                Resources = [| "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable" |]
            )
        )

    managedPolicy "DataAccessPolicy" {
        description "Access to S3 and DynamoDB"
        statements [ s3Statement; dynamoStatement ]
    }
}

Using Helper Methods

FsCDK provides convenient helpers for common permission patterns.

stack "HelperMethodsPolicy" {
    managedPolicy "QuickAccessPolicy" {
        description "Quick policy using helpers"
        allow [ "s3:GetObject"; "s3:ListBucket" ] [ "arn:aws:s3:::my-bucket/*" ]
        deny [ "s3:DeleteObject" ] [ "arn:aws:s3:::my-bucket/*" ]
    }
}

Using Pre-Built Statements

Use the ManagedPolicyStatements module for common scenarios.

stack "PreBuiltStatements" {
    let bucketArn = "arn:aws:s3:::my-bucket"
    let tableArn = "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable"

    managedPolicy "ApplicationPolicy" {
        description "Standard application permissions"

        statements
            [ (ManagedPolicyStatements.s3ReadOnly bucketArn)
              (ManagedPolicyStatements.dynamoDBFullAccess tableArn)
              (ManagedPolicyStatements.cloudWatchLogsWrite "/aws/lambda/my-function") ]
    }
}

Attaching to Roles

Attach policies to IAM roles for EC2, Lambda, or other services.

stack "PolicyWithRole" {
    // Create a role for Lambda
    let lambdaRole1 =
        lambdaRole "my-function-role" {
            basicExecution
            vpcExecution
            kmsDecrypt
            xrayTracing
            managedPolicy "AmazonS3ReadOnlyAccess"
            inlinePolicy (IAM.allow [ "dynamodb:Query" ] [ "arn:aws:dynamodb:*:*:table/MyTable" ])
        }

    // Create and attach policy
    managedPolicy "LambdaS3Policy" {
        description "Lambda S3 access"
        statement (ManagedPolicyStatements.s3FullAccess "arn:aws:s3:::lambda-bucket")
        attachToRole lambdaRole1
    }
}

Cross-Account Access Policy

Grant permissions for cross-account access.

stack "CrossAccountPolicy" {
    managedPolicy "CrossAccountPolicy" {
        description "Allow access from partner account"

        policyStatement {
            sid "CrossAccountS3Access"
            effect Effect.ALLOW
            actions [ "s3:GetObject"; "s3:ListBucket" ]
            resources [ "arn:aws:s3:::shared-bucket"; "arn:aws:s3:::shared-bucket/*" ]
        }
    }
}

Conditional Permissions

Use conditions to restrict permissions based on context.

stack "ConditionalPolicy" {
    let conds = System.Collections.Generic.Dictionary<string, obj>()
    conds.Add("aws:SourceIp", [| "203.0.113.0/24" |] :> obj)

    managedPolicy "IPRestrictedPolicy" {
        description "S3 access only from specific IP range"

        policyStatement {
            sid "IPRestrictedAccess"
            effect Effect.ALLOW
            actions [ "s3:*" ]
            resources [ "arn:aws:s3:::secure-bucket/*" ]
            conditions [ "IpAddress", conds ]
        }
    }
}

Secrets Manager Access

Grant access to AWS Secrets Manager secrets.

stack "SecretsPolicy" {
    let secretArn =
        "arn:aws:secretsmanager:us-east-1:123456789012:secret:MySecret-AbCdEf"

    managedPolicy "SecretsAccessPolicy" {
        description "Access to application secrets"
        ManagedPolicyStatements.secretsManagerRead secretArn
    }
}

KMS Encryption Policy

Grant permissions to use KMS keys for encryption/decryption.

stack "KMSPolicy" {
    let kmsKeyArn =
        "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"

    managedPolicy "KMSAccessPolicy" {
        description "KMS key usage for encryption"
        ManagedPolicyStatements.kmsDecrypt kmsKeyArn
    }
}

Lambda Execution Policy

Complete policy for Lambda function execution.

stack "LambdaExecutionPolicy" {
    let functionName = "my-function"
    let logGroupArn = $"/aws/lambda/{functionName}"
    let bucketArn = "arn:aws:s3:::lambda-data"
    let tableArn = "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable"

    managedPolicy "LambdaFullAccessPolicy" {
        description "Complete Lambda execution permissions"

        statements
            [ ManagedPolicyStatements.cloudWatchLogsWrite logGroupArn
              ManagedPolicyStatements.s3FullAccess bucketArn
              ManagedPolicyStatements.dynamoDBFullAccess tableArn ]
    }
}

Read-Only Policy

Create a read-only policy for auditors or monitoring.

stack "ReadOnlyPolicy" {
    managedPolicy "AuditorPolicy" {
        description "Read-only access for auditing"
        ManagedPolicyStatements.ec2Describe ()
        ManagedPolicyStatements.s3ReadOnly "arn:aws:s3:::audit-logs"
        ManagedPolicyStatements.dynamoDBReadOnly "arn:aws:dynamodb:us-east-1:123456789012:table/*"
    }
}

Deny Override Policy

Use deny statements to prevent specific actions (overrides allows).

stack "DenyOverridePolicy" {
    let allowStatement =
        PolicyStatement(
            PolicyStatementProps(
                Sid = "AllowS3Access",
                Effect = Effect.ALLOW,
                Actions = [| "s3:*" |],
                Resources = [| "arn:aws:s3:::my-bucket/*" |]
            )
        )

    let denyStatement =
        PolicyStatement(
            PolicyStatementProps(
                Sid = "DenyDeleteActions",
                Effect = Effect.DENY,
                Actions = [| "s3:DeleteObject"; "s3:DeleteBucket" |],
                Resources = [| "arn:aws:s3:::my-bucket"; "arn:aws:s3:::my-bucket/*" |]
            )
        )

    managedPolicy "SafeS3Policy" {
        description "S3 access without delete permissions"
        statements [ allowStatement; denyStatement ]
    }
}

Best Practices

Security

Operational Excellence

Organization

Compliance

Maintenance

namespace FsCDK
namespace Amazon
namespace Amazon.CDK
namespace Amazon.CDK.AWS
namespace Amazon.CDK.AWS.IAM
namespace Amazon.CDK.AWS.S3
val stack: name: string -> StackBuilder
<summary>Creates an AWS CDK Stack construct.</summary>
<param name="name">The name of the stack.</param>
<code lang="fsharp"> stack "MyStack" { lambda myFunction bucket myBucket } </code>
val managedPolicy: name: string -> ManagedPolicyBuilder
<summary>Creates a Managed Policy with AWS IAM best practices.</summary>
<param name="name">The policy name.</param>
<code lang="fsharp"> managedPolicy "S3ReadPolicy" { description "Read-only access to S3 buckets" statements [ policyStatement { effect Effect.ALLOW actions [ "s3:GetObject" ] resources [ "*" ] } ] attachToRole myRole } </code>
custom operation: description (string) Calls ManagedPolicyBuilder.Description
<summary>Sets the policy description.</summary>
<param name="config">The current managed policy configuration.</param>
<param name="description">The policy description.</param>
<code lang="fsharp"> managedPolicy "MyPolicy" { description "This is my custom managed policy" ... } </code>
custom operation: managedPolicyName (string) Calls ManagedPolicyBuilder.ManagedPolicyName
<summary>Sets the managed policy name.</summary>
<param name="config">The current managed policy configuration.</param>
<param name="name">The policy name as it appears in IAM.</param>
<code lang="fsharp"> managedPolicy "MyPolicy" { managedPolicyName "CustomPolicyName" ... } </code>
val policyStatement: PolicyStatementBuilder
custom operation: effect (Effect) Calls PolicyStatementBuilder.Effect
[<Struct>] type Effect = | ALLOW = 0 | DENY = 1
field Effect.ALLOW: Effect = 0
custom operation: actions (string list) Calls PolicyStatementBuilder.Actions
custom operation: resources (string list) Calls PolicyStatementBuilder.Resources
val s3Statement: PolicyStatement
Multiple items
type PolicyStatement = inherit DeputyBase new: ?props: IPolicyStatementProps -> unit member AddAccountCondition: accountId: string -> unit member AddAccountRootPrincipal: unit -> unit member AddActions: [<ParamArray>] actions: string array -> unit member AddAllResources: unit -> unit member AddAnyPrincipal: unit -> unit member AddArnPrincipal: arn: string -> unit member AddAwsAccountPrincipal: accountId: string -> unit member AddCanonicalUserPrincipal: canonicalUserId: string -> unit ...

--------------------
PolicyStatement(?props: IPolicyStatementProps) : PolicyStatement
Multiple items
type PolicyStatementProps = interface IPolicyStatementProps new: unit -> unit member Actions: string array member Conditions: IDictionary<string,obj> member Effect: Nullable<Effect> member NotActions: string array member NotPrincipals: IPrincipal array member NotResources: string array member Principals: IPrincipal array member Resources: string array ...

--------------------
PolicyStatementProps() : PolicyStatementProps
val dynamoStatement: PolicyStatement
custom operation: statements (PolicyStatement list) Calls ManagedPolicyBuilder.Statements
<summary>Adds a policy statement.</summary>
<param name="config">The current managed policy configuration.</param>
<param name="statement">The policy statement to add.</param>
<code lang="fsharp"> managedPolicy "MyPolicy" { statements [ policyStatement { effect Effect.ALLOW actions [ "s3:GetObject" ] resources [ "*" ] } ] } </code>
custom operation: allow (string list) (string list) Calls ManagedPolicyBuilder.Allow
<summary>Adds a statement allowing specific actions on specific resources.</summary>
custom operation: deny (string list) (string list) Calls ManagedPolicyBuilder.Deny
<summary>Adds a statement denying specific actions on specific resources.</summary>
val bucketArn: string
val tableArn: string
module ManagedPolicyStatements from FsCDK
val s3ReadOnly: bucketArn: string -> PolicyStatement
<summary> Creates a statement for S3 read-only access </summary>
val dynamoDBFullAccess: tableArn: string -> PolicyStatement
<summary> Creates a statement for DynamoDB full access </summary>
val cloudWatchLogsWrite: logGroupArn: string -> PolicyStatement
<summary> Creates a statement for CloudWatch Logs write access </summary>
custom operation: sid (string) Calls PolicyStatementBuilder.Sid
val conds: System.Collections.Generic.Dictionary<string,obj>
namespace System
namespace System.Collections
namespace System.Collections.Generic
Multiple items
type Dictionary<'TKey,'TValue> = interface ICollection<KeyValuePair<'TKey,'TValue>> interface IEnumerable<KeyValuePair<'TKey,'TValue>> interface IEnumerable interface IDictionary<'TKey,'TValue> interface IReadOnlyCollection<KeyValuePair<'TKey,'TValue>> interface IReadOnlyDictionary<'TKey,'TValue> interface ICollection interface IDictionary interface IDeserializationCallback interface ISerializable ...
<summary>Represents a collection of keys and values.</summary>
<typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
<typeparam name="TValue">The type of the values in the dictionary.</typeparam>


--------------------
System.Collections.Generic.Dictionary() : System.Collections.Generic.Dictionary<'TKey,'TValue>
System.Collections.Generic.Dictionary(dictionary: System.Collections.Generic.IDictionary<'TKey,'TValue>) : System.Collections.Generic.Dictionary<'TKey,'TValue>
System.Collections.Generic.Dictionary(collection: System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<'TKey,'TValue>>) : System.Collections.Generic.Dictionary<'TKey,'TValue>
System.Collections.Generic.Dictionary(comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : System.Collections.Generic.Dictionary<'TKey,'TValue>
System.Collections.Generic.Dictionary(capacity: int) : System.Collections.Generic.Dictionary<'TKey,'TValue>
System.Collections.Generic.Dictionary(dictionary: System.Collections.Generic.IDictionary<'TKey,'TValue>, comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : System.Collections.Generic.Dictionary<'TKey,'TValue>
System.Collections.Generic.Dictionary(collection: System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<'TKey,'TValue>>, comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : System.Collections.Generic.Dictionary<'TKey,'TValue>
System.Collections.Generic.Dictionary(capacity: int, comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : System.Collections.Generic.Dictionary<'TKey,'TValue>
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
type obj = System.Object
System.Collections.Generic.Dictionary.Add(key: string, value: obj) : unit
custom operation: conditions ((string * obj) list) Calls PolicyStatementBuilder.Condition
val secretArn: string
val secretsManagerRead: secretArn: string -> PolicyStatement
<summary> Creates a statement for Secrets Manager read access </summary>
val kmsKeyArn: string
val kmsDecrypt: keyArn: string -> PolicyStatement
<summary> Creates a statement for KMS decrypt permissions </summary>
val functionName: string
val logGroupArn: string
val s3FullAccess: bucketArn: string -> PolicyStatement
<summary> Creates a statement for S3 full access </summary>
val ec2Describe: unit -> PolicyStatement
<summary> Creates a statement for EC2 describe permissions (read-only) </summary>
val dynamoDBReadOnly: tableArn: string -> PolicyStatement
<summary> Creates a statement for DynamoDB read-only access </summary>
val allowStatement: PolicyStatement
val denyStatement: PolicyStatement
field Effect.DENY: Effect = 1

Type something to start searching.