diff --git a/packages/@aws-cdk/aws-iotevents/README.md b/packages/@aws-cdk/aws-iotevents/README.md
index 760b6098d9d41..864833049b402 100644
--- a/packages/@aws-cdk/aws-iotevents/README.md
+++ b/packages/@aws-cdk/aws-iotevents/README.md
@@ -70,3 +70,16 @@ new iotevents.DetectorModel(this, 'MyDetectorModel', {
   initialState: onlineState,
 });
 ```
+
+To grant permissions to put messages in the input,
+you can use the `grantWrite()` method:
+
+```ts
+import * as iam from '@aws-cdk/aws-iam';
+import * as iotevents from '@aws-cdk/aws-iotevents';
+
+declare const grantable: iam.IGrantable;
+const input = iotevents.Input.fromInputName(this, 'MyInput', 'my_input');
+
+input.grantWrite(grantable);
+```
diff --git a/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts b/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts
index 5ef50fd871d75..a35b1efc30d23 100644
--- a/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts
+++ b/packages/@aws-cdk/aws-iotevents/lib/detector-model.ts
@@ -5,7 +5,7 @@ import { CfnDetectorModel } from './iotevents.generated';
 import { State } from './state';
 
 /**
- * Represents an AWS IoT Events detector model
+ * Represents an AWS IoT Events detector model.
  */
 export interface IDetectorModel extends IResource {
   /**
@@ -33,7 +33,7 @@ export enum EventEvaluation {
 }
 
 /**
- * Properties for defining an AWS IoT Events detector model
+ * Properties for defining an AWS IoT Events detector model.
  */
 export interface DetectorModelProps {
   /**
diff --git a/packages/@aws-cdk/aws-iotevents/lib/expression.ts b/packages/@aws-cdk/aws-iotevents/lib/expression.ts
index 27fdf069c1b9f..fd686e9761802 100644
--- a/packages/@aws-cdk/aws-iotevents/lib/expression.ts
+++ b/packages/@aws-cdk/aws-iotevents/lib/expression.ts
@@ -1,12 +1,12 @@
 import { IInput } from './input';
 
 /**
- * Expression for events in Detector Model state
+ * Expression for events in Detector Model state.
  * @see https://docs.aws.amazon.com/iotevents/latest/developerguide/iotevents-expressions.html
  */
 export abstract class Expression {
   /**
-   * Create a expression from the given string
+   * Create a expression from the given string.
    */
   public static fromString(value: string): Expression {
     return new StringExpression(value);
@@ -28,14 +28,14 @@ export abstract class Expression {
   }
 
   /**
-   * Create a expression for the Equal operator
+   * Create a expression for the Equal operator.
    */
   public static eq(left: Expression, right: Expression): Expression {
     return new BinaryOperationExpression(left, '==', right);
   }
 
   /**
-   * Create a expression for the AND operator
+   * Create a expression for the AND operator.
    */
   public static and(left: Expression, right: Expression): Expression {
     return new BinaryOperationExpression(left, '&&', right);
@@ -45,7 +45,7 @@ export abstract class Expression {
   }
 
   /**
-   * this is called to evaluate the expression
+   * This is called to evaluate the expression.
    */
   public abstract evaluate(): string;
 }
diff --git a/packages/@aws-cdk/aws-iotevents/lib/input.ts b/packages/@aws-cdk/aws-iotevents/lib/input.ts
index e4bba5684b7a4..b656af2d4dff6 100644
--- a/packages/@aws-cdk/aws-iotevents/lib/input.ts
+++ b/packages/@aws-cdk/aws-iotevents/lib/input.ts
@@ -1,24 +1,66 @@
-import { Resource, IResource } from '@aws-cdk/core';
+import * as iam from '@aws-cdk/aws-iam';
+import { Resource, IResource, Aws } from '@aws-cdk/core';
 import { Construct } from 'constructs';
 import { CfnInput } from './iotevents.generated';
 
 /**
- * Represents an AWS IoT Events input
+ * Represents an AWS IoT Events input.
  */
 export interface IInput extends IResource {
   /**
-   * The name of the input
+   * The name of the input.
+   *
    * @attribute
    */
   readonly inputName: string;
+
+  /**
+   * The ARN of the input.
+   *
+   * @attribute
+   */
+  readonly inputArn: string;
+
+  /**
+   * Grant write permissions on this input and its contents to an IAM principal (Role/Group/User).
+   *
+   * @param grantee the principal
+   */
+  grantWrite(grantee: iam.IGrantable): iam.Grant
+
+  /**
+   * Grant the indicated permissions on this input to the given IAM principal (Role/Group/User).
+   *
+   * @param grantee the principal
+   * @param actions the set of actions to allow (i.e. "iotevents:BatchPutMessage")
+   */
+  grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant
+}
+
+abstract class InputBase extends Resource implements IInput {
+  public abstract readonly inputName: string;
+
+  public abstract readonly inputArn: string;
+
+  public grantWrite(grantee: iam.IGrantable) {
+    return this.grant(grantee, 'iotevents:BatchPutMessage');
+  }
+
+  public grant(grantee: iam.IGrantable, ...actions: string[]) {
+    return iam.Grant.addToPrincipal({
+      grantee,
+      actions,
+      resourceArns: [this.inputArn],
+    });
+  }
 }
 
 /**
- * Properties for defining an AWS IoT Events input
+ * Properties for defining an AWS IoT Events input.
  */
 export interface InputProps {
   /**
-   * The name of the input
+   * The name of the input.
    *
    * @default - CloudFormation will generate a unique name of the input
    */
@@ -37,19 +79,25 @@ export interface InputProps {
 /**
  * Defines an AWS IoT Events input in this stack.
  */
-export class Input extends Resource implements IInput {
+export class Input extends InputBase {
   /**
-   * Import an existing input
+   * Import an existing input.
    */
   public static fromInputName(scope: Construct, id: string, inputName: string): IInput {
-    class Import extends Resource implements IInput {
+    return new class Import extends InputBase {
       public readonly inputName = inputName;
-    }
-    return new Import(scope, id);
+      public readonly inputArn = this.stack.formatArn({
+        service: 'iotevents',
+        resource: 'input',
+        resourceName: inputName,
+      });
+    }(scope, id);
   }
 
   public readonly inputName: string;
 
+  public readonly inputArn: string;
+
   constructor(scope: Construct, id: string, props: InputProps) {
     super(scope, id, {
       physicalName: props.inputName,
@@ -67,5 +115,14 @@ export class Input extends Resource implements IInput {
     });
 
     this.inputName = this.getResourceNameAttribute(resource.ref);
+    this.inputArn = this.getResourceArnAttribute(arnForInput(resource.ref), {
+      service: 'iotevents',
+      resource: 'input',
+      resourceName: this.physicalName,
+    });
   }
 }
+
+function arnForInput(inputName: string): string {
+  return `arn:${Aws.PARTITION}:iotevents:${Aws.REGION}:${Aws.ACCOUNT_ID}:input/${inputName}`;
+}
diff --git a/packages/@aws-cdk/aws-iotevents/lib/state.ts b/packages/@aws-cdk/aws-iotevents/lib/state.ts
index e16d911d60004..129d3395776ad 100644
--- a/packages/@aws-cdk/aws-iotevents/lib/state.ts
+++ b/packages/@aws-cdk/aws-iotevents/lib/state.ts
@@ -2,7 +2,7 @@ import { Event } from './event';
 import { CfnDetectorModel } from './iotevents.generated';
 
 /**
- * Properties for defining a state of a detector
+ * Properties for defining a state of a detector.
  */
 export interface StateProps {
   /**
@@ -20,11 +20,11 @@ export interface StateProps {
 }
 
 /**
- * Defines a state of a detector
+ * Defines a state of a detector.
  */
 export class State {
   /**
-   * The name of the state
+   * The name of the state.
    */
   public readonly stateName: string;
 
@@ -33,7 +33,7 @@ export class State {
   }
 
   /**
-   * Return the state property JSON
+   * Return the state property JSON.
    *
    * @internal
    */
@@ -46,7 +46,7 @@ export class State {
   }
 
   /**
-   * returns true if this state has at least one condition via events
+   * Returns true if this state has at least one condition via events.
    *
    * @internal
    */
diff --git a/packages/@aws-cdk/aws-iotevents/test/input.test.ts b/packages/@aws-cdk/aws-iotevents/test/input.test.ts
index 11b457bb0cf1b..8907489af928e 100644
--- a/packages/@aws-cdk/aws-iotevents/test/input.test.ts
+++ b/packages/@aws-cdk/aws-iotevents/test/input.test.ts
@@ -1,10 +1,14 @@
 import { Template } from '@aws-cdk/assertions';
+import * as iam from '@aws-cdk/aws-iam';
 import * as cdk from '@aws-cdk/core';
 import * as iotevents from '../lib';
 
-test('Default property', () => {
-  const stack = new cdk.Stack();
+let stack: cdk.Stack;
+beforeEach(() => {
+  stack = new cdk.Stack();
+});
 
+test('Default property', () => {
   // WHEN
   new iotevents.Input(stack, 'MyInput', {
     attributeJsonPaths: ['payload.temperature'],
@@ -19,7 +23,6 @@ test('Default property', () => {
 });
 
 test('can get input name', () => {
-  const stack = new cdk.Stack();
   // GIVEN
   const input = new iotevents.Input(stack, 'MyInput', {
     attributeJsonPaths: ['payload.temperature'],
@@ -39,9 +42,38 @@ test('can get input name', () => {
   });
 });
 
-test('can set physical name', () => {
-  const stack = new cdk.Stack();
+test('can get input ARN', () => {
+  // GIVEN
+  const input = new iotevents.Input(stack, 'MyInput', {
+    attributeJsonPaths: ['payload.temperature'],
+  });
 
+  // WHEN
+  new cdk.CfnResource(stack, 'Res', {
+    type: 'Test::Resource',
+    properties: {
+      InputArn: input.inputArn,
+    },
+  });
+
+  // THEN
+  Template.fromStack(stack).hasResourceProperties('Test::Resource', {
+    InputArn: {
+      'Fn::Join': ['', [
+        'arn:',
+        { Ref: 'AWS::Partition' },
+        ':iotevents:',
+        { Ref: 'AWS::Region' },
+        ':',
+        { Ref: 'AWS::AccountId' },
+        ':input/',
+        { Ref: 'MyInput08947B23' },
+      ]],
+    },
+  });
+});
+
+test('can set physical name', () => {
   // WHEN
   new iotevents.Input(stack, 'MyInput', {
     inputName: 'test_input',
@@ -55,8 +87,6 @@ test('can set physical name', () => {
 });
 
 test('can import a Input by inputName', () => {
-  const stack = new cdk.Stack();
-
   // WHEN
   const inputName = 'test-input-name';
   const topicRule = iotevents.Input.fromInputName(stack, 'InputFromInputName', inputName);
@@ -68,11 +98,45 @@ test('can import a Input by inputName', () => {
 });
 
 test('cannot be created with an empty array of attributeJsonPaths', () => {
-  const stack = new cdk.Stack();
-
   expect(() => {
     new iotevents.Input(stack, 'MyInput', {
       attributeJsonPaths: [],
     });
   }).toThrow('attributeJsonPaths property cannot be empty');
 });
+
+test('can grant the permission to put message', () => {
+  const role = iam.Role.fromRoleArn(stack, 'MyRole', 'arn:aws:iam::account-id:role/role-name');
+  const input = new iotevents.Input(stack, 'MyInput', {
+    attributeJsonPaths: ['payload.temperature'],
+  });
+
+  // WHEN
+  input.grantWrite(role);
+
+  // THEN
+  Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', {
+    PolicyDocument: {
+      Statement: [
+        {
+          Action: 'iotevents:BatchPutMessage',
+          Effect: 'Allow',
+          Resource: {
+            'Fn::Join': ['', [
+              'arn:',
+              { Ref: 'AWS::Partition' },
+              ':iotevents:',
+              { Ref: 'AWS::Region' },
+              ':',
+              { Ref: 'AWS::AccountId' },
+              ':input/',
+              { Ref: 'MyInput08947B23' },
+            ]],
+          },
+        },
+      ],
+    },
+    PolicyName: 'MyRolePolicy64AB00A5',
+    Roles: ['role-name'],
+  });
+});