JSPM

iam-floyd

0.52.2
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1719
  • Score
    100M100P100Q116650F
  • License Apache-2.0

AWS IAM policy statement generator with fluent interface

Package Exports

  • iam-floyd

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (iam-floyd) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

IAM Floyd

Source iam-floyd GitHub Maintainability CDKio

AWS IAM policy statement generator with fluent interface.

Support for:

  • 237 Services
  • 7818 Actions
  • 772 Resource Types
  • 456 Conditions

EXPERIMENTAL
This is an early version of the package. The API will change while I implement new features. Therefore make sure you use an exact version in your package.json before it reaches 1.0.0.

Auto completion demo

Packages

There are two different package variants available:

  • iam-floyd: Can be used in AWS SDK, Boto 3 or for whatever you need an IAM policy statement for
    npm PyPI NuGet
  • cdk-iam-floyd: Integrates into AWS CDK and extends iam.PolicyStatement
    npm PyPI NuGet

Usage

The package contains a statement provider for each AWS service, e.g. Ec2. A statement provider is a class with methods for each and every available action, resource type and condition. Calling such method will add the action/resource/condition to the statement:

import * as statement from 'iam-floyd';

new statement.Ec2().toStartInstances();

Every method returns the statement provider, so you can chain method calls:

new statement.Ec2()
  .toStartInstances()
  .toStopInstances();

The default effect of any statement is Allow. To add some linguistic sugar you can explicitly call the allow() method:

new statement.Ec2()
  .allow()
  .toStartInstances()
  .toStopInstances();

And of course deny():

new statement.Ec2()
  .deny()
  .toStartInstances()
  .toStopInstances();

If you don't want to be verbose and add every single action manually to the statement, you discovered the reason why this package was created. You can work with access levels!

There are 5 access levels you can use: LIST, READ, WRITE, PERMISSION_MANAGEMENT and TAGGING:

new statement.Ec2()
  .allow()
  .allActions(
    statement.AccessLevel.LIST,
    statement.AccessLevel.READ
  );

The allActions() method also accepts regular expressions (as a string) which test against the action name:

new statement.Ec2()
  .deny()
  .allActions('/vpn/i');

If no value is passed, all actions (ec2:*) will be added:

new statement.Ec2()
  .allow()
  .allActions();

For every available condition key, there are if*() methods available.

new statement.Ec2()
  .allow()
  .toStartInstances()
  .ifEncrypted()
  .ifInstanceType(['t3.micro', 't3.nano'])
  .ifAssociatePublicIpAddress(false)
  .ifAwsRequestTag('Owner', 'John');

If you want to add a condition not covered by the available methods, you can define just any condition yourself via if():

new statement.Ec2()
  .allow()
  .toStartInstances()
  .if('aws:RequestTag/Owner', 'John');

The default operator for conditions of type String is StringLike.

Most of the if*() methods allow an optional operator as last argument:

new statement.Ec2()
  .allow()
  .toStartInstances()
  .if('aws:RequestTag/Owner', '*John*', 'StringEquals');

By default the statement applies to all resources. To limit to specific resources, add them via on*().

For every resource type an on*() method exists:

new statement.S3()
  .allow()
  .allActions()
  .onBucket('some-bucket')
  .onObject('some-bucket', 'some/path/*');

If instead you have an ARN ready, use the on() method:

new statement.S3()
  .allow()
  .allActions()
  .on(
    'arn:aws:s3:::some-bucket',
    'arn:aws:s3:::another-bucket'
  );

To invert the policy you can use notActions() and notResources():

new statement.S3()
  .allow()
  .notActions()
  .notResources()
  .toDeleteBucket()
  .onBucket('some-bucket');

Examples

const policy = {
  Version: '2012-10-17',
  Statement: [
    new statement.Ec2()
      .allow()
      .toStartInstances()
      .ifAwsRequestTag('Owner', '${aws:username}'),
    new statement.Ec2()
      .allow()
      .toStopInstances()
      .ifResourceTag('Owner', '${aws:username}'),
    new statement.Ec2()
      .allow()
      .allActions(
        statement.AccessLevel.LIST,
        statement.AccessLevel.READ
    ),
  ]
}
const policy = {
  Version: '2012-10-17',
  Statement: [
    new statement.Cloudformation() // allow all CFN actions
      .allow()
      .allActions(),
    new statement.All() // allow absolutely everything that is triggered via CFN
      .allow()
      .allActions()
      .ifAwsCalledVia('cloudformation.amazonaws.com'),
    new statement.S3() // allow access to the CDK staging bucket
      .allow()
      .allActions()
      .on('arn:aws:s3:::cdktoolkit-stagingbucket-*'),
    new statement.Account() // even when triggered via CFN, do not allow modifications of the account
      .deny()
      .allActions(
        statement.AccessLevel.PERMISSION_MANAGEMENT,
        statement.AccessLevel.WRITE
      ),
    new statement.Organizations() // even when triggered via CFN, do not allow modifications of the organization
      .deny()
      .allActions(
        statement.AccessLevel.PERMISSION_MANAGEMENT,
        statement.AccessLevel.WRITE
      ),
  ]
}

Methods

allow

Sets the Effect of the statement to Allow.

new statement.Ec2()
  .allow()
  .toStopInstances();

deny

Sets the Effect of the statement to Deny.

new statement.Ec2()
  .deny()
  .toStopInstances();

to*, to

For every available action, there are to*() methods available.

new statement.Ec2()
  .allow()
  .toStartInstances()
  .toStopInstances();

allActions

This method allows you to add multiple actions at once. If called without parameters, it adds all actions of the service.

new statement.Ec2()
  .allow()
  .allActions();

The method can take regular expressions (as a string) and access levels as options and will add only the matching actions:

new statement.Ec2()
  .allow()
  .allActions('/vpn/i');
new statement.Ec2()
  .allow()
  .allActions(
    statement.AccessLevel.LIST,
    statement.AccessLevel.READ
  );

There exist 5 access levels:

  • LIST
  • READ
  • WRITE
  • PERMISSION_MANAGEMENT
  • TAGGING

if*, if

For every available condition key, there are if*() methods available.

new statement.Ec2()
  .allow()
  .toStartInstances()
  .ifEncrypted()
  .ifInstanceType(['t3.micro', 't3.nano'])
  .ifAssociatePublicIpAddress(false)
  .ifAwsRequestTag('Owner', 'John')

Most of them allow an optional operator as last argument:

new statement.Ec2()
  .allow()
  .toStartInstances()
  .ifInstanceType('*.nano', 'StringLike')

Global conditions are prefixed with ifAws, e.g. ifAwsRequestedRegion()

If you want to add a condition not covered by the available methods, you can define just any condition yourself via if():

new statement.Ec2()
  .allow()
  .toStartInstances()
  .if(
    'aws:RequestTag/Owner',
    '${aws:username}',
    'StringEquals' //optional
  );

on*, on

Limit statement to specified resources.

For every resource type an on*() method exists:

new statement.S3()
  .allow()
  .allActions()
  .onBucket('some-bucket');

If instead you have an ARN ready, use the on() method:

new statement.S3()
  .allow()
  .allActions()
  .on('arn:aws:s3:::some-bucket');

If no resources are applied to the statement, it defaults to all resources (*). You can also be verbose and set this yourself:

new statement.S3()
  .allow()
  .allActions()
  .on('*');

notActions

Switches the policy provider to use NotAction.

new statement.S3()
  .allow()
  .notActions()
  .toDeleteBucket()
  .onBucket('some-bucket');

notResources

Switches the policy provider to use NotResource.

new statement.S3()
  .allow()
  .notResources()
  .toDeleteBucket()
  .onBucket('some-bucket');

notPrincipals

Switches the policy provider to use NotPrincipal.

new statement.Sts()
  .deny()
  .notPrincipals()
  .toAssumeRole()
  .forUser('1234567890', 'Bob');

for*

To create assume policies, use the for*() methods. There are methods available for any type of principal:

new statement.Sts()
  .allow()
  .toAssumeRole()
  .forAccount('1234567890');

new statement.Sts()
  .allow()
  .toAssumeRoleWithSAML()
  .forService('lambda.amazonaws.com');

new statement.Sts()
  .allow()
  .toAssumeRole()
  .forUser('1234567890', 'Bob');

new statement.Sts()
  .allow()
  .toAssumeRole()
  .forRole('1234567890', 'role-name');

new statement.Sts()
  .allow()
  .toAssumeRoleWithSAML()
  .forFederatedCognito();

new statement.Sts()
  .allow()
  .toAssumeRoleWithSAML()
  .forFederatedAmazon();

new statement.Sts()
  .allow()
  .toAssumeRoleWithSAML()
  .forFederatedGoogle();

new statement.Sts()
  .allow()
  .toAssumeRoleWithSAML()
  .forFederatedFacebook();

new statement.Sts()
  .allow()
  .toAssumeRoleWithSAML()
  .forSaml('1234567890', 'saml-provider');

new statement.Sts()
  .allow()
  .toAssumeRole()
  .forPublic();

new statement.Sts()
  .allow()
  .toAssumeRole()
  .forAssumedRoleSession('123456789', 'role-name', 'session-name');

new statement.Sts()
  .allow()
  .toAssumeRole()
  .forCanonicalUser('userID');

new statement.Sts()
  .allow()
  .toAssumeRole()
  .for('arn:foo:bar')

To reverse the assume policy you can call the notPrincipals() method:

new statement.Sts()
  .deny()
  .notPrincipals()
  .toAssumeRole()
  .forUser('1234567890', 'Bob');

If you use the cdk variant of the package you should not have the need to manually create assume policies. But if you do, there is an additional method forCdkPrincipal() which takes any number of iam.IPrincipal objects:

new statement.Sts()
  .allow()
  .toAssumeRole()
  .forCdkPrincipal(
    new iam.ServicePrincipal('sns.amazonaws.com')
    new iam.ServicePrincipal('lambda.amazonaws.com')
  )

Floyd?

George Floyd has been murdered by racist police officers on May 25th, 2020.

This package is not named after him to just remind you of him and his death. I want this package to be of great help to you and I want you to use it on a daily base. Every time you use it, I want you to remember our society is ill and needs change. The riots will stop. The news will fade. The issue persists!

If this statement annoys you, this package is not for you.

Similar projects

The code contained in the lib folder is generated from the AWS documentation. The class- and function-names and their description therefore are property of AWS.

AWS and their services are trademarks, registered trademarks or trade dress of AWS in the U.S. and/or other countries.

This project is not affiliated, funded, or in any way associated with AWS.