Search code examples
amazon-iamserverlessserverless-frameworkaws-serverless

How to create IAM user with access key and secret key using Serverless framework?


I'd like to use Serverless framework to create an IAM user for programmatic access with certain Policies attached to it and export it's Access Key ID and Secret Key as environment variables for lambda. How to achieve that?

(something like here is done with terraform)


Solution

  • Here's how to add a user with roles and permissions set up. Setting up roles and permissions is important since usually you don't create a user with Access/Secret key in a vacuum, the user needs to have some accesses.

    Notes:

    • All IAM resources need to have a region in the name since redeployment a resource with the same name will cause an "unrecoverable error" (accordingly to AWS IAM documentation)
    • To reference the Access Key you just specify resource name, but to reference the Secret Key you need to get property SecretAccessKey.
    • Sample permissions in the policy give access to an SQS queue, but it can be anything

    File serverless-with-my-user.yml:

    resources:
      Resources:
        # Naming an IAM resource can cause an unrecoverable error if you reuse the same template in multiple Regions
        MyUser:
          Type: AWS::IAM::User
          Properties:
            UserName: "my-${self:provider.stage}-${self:provider.region}-User"
            Policies:
            - PolicyName: 
                Fn::Join:
                  - ''
                  - - "myUser"
                    - '-'
                    - ${self:provider.stage}
                    - '-'
                    - ${self:provider.region}
                    - '-MyPolicy'
              PolicyDocument:
                Version: '2012-10-17'
                Statement:
                - Effect: Allow
                  Action:
                    - "sqs:GetQueueAttributes"
                    - "sqs:GetQueueUrl"
                  Resource: { 'Fn::ImportValue': '${self:provider.stage}-MyQueueArn' }
        MyUserKey:
          Type: AWS::IAM::AccessKey
          Properties: 
            UserName:
              Ref: MyUser
    
      Outputs:
        MyUserAccessKeyID:
          Description: The Access Key of the MyUser
          Value:
            Ref: MyUserKey
          Export:
            Name: ${self:provider.stage}-MyUserAccessKeyID
        MyUserAccessSecretKey:
          Description: The ARN of the secret key
          Value:
            Fn::GetAtt:
              - MyUserKey
              - SecretAccessKey
          Export:
            Name: ${self:provider.stage}-MyUserAccessSecretKey
    

    And here's how to access this user's access key and secret key in other parts of serverless resources (e.g. lambda):

    File serverless-with-my-service.yml

    environment:
      MYUSER_AWS_ACCESS_KEY_ID:
        Fn::ImportValue: '${self:provider.stage}-MyUserAccessKeyID'
      MYUSER_AWS_SECRET_ACCESS_KEY:
        Fn::ImportValue: '${self:provider.stage}-MyUserAccessSecretKey'
    

    If user, key and service are in a single file, there's no need to use output variables and you can reference the values directly.