Giter Site home page Giter Site logo

teamcity-awsrole-plugin's Introduction

awsrole TeamCity plugin

This is a plugin for TeamCity (2017.1 and newer) to enable more secure operation in AWS.

The problem

Typically, build agents either have an instance profile associated with them (if running on an EC2 instance) or an IAM access key (if running on-premises). The problem with these approaches is twofold:

Firstly, logs in CloudTrail are not as useful as they could be. It is almost impossible to correlate AWS API calls with the TeamCity build that initiated them.

Secondly, it's difficult to define granular IAM permissions on a per-project or per-build configuration basis. This usually results in either a lot of manual effort or granting permissions that are too powerful.

The solution

Screenshot

The TeamCity server should have an IAM role that has sts:AssumeRole permissions to assume roles needed by build steps. Build configurations add a build feature configured like so:

import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.awsAssumeRole

// ...

features {
    awsAssumeRole {
        roleArn = "arn:aws:iam::123456789012:role/ApiDeployer"
        sessionTags = """
            teamcity.build.id=%teamcity.build.id%
            teamcity.build.triggeredBy.username=%teamcity.build.triggeredBy.username%
        """.trimIndent()
    }
}

Optionally, a AWS IAM user with sts:AssumeRole permissions can be specified in the build feature parameters instead of using the server credentials.

Whenever a build with this feature is started, the server assumes the requested role and sets AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN environment variables for the build.

Crucially, it sets the role session name to %system.teamcity.buildType.id%_%system.build.number% and the external ID to %system.teamcity.buildType.id% by default. The former means that CloudTrail logs will identify the build making API calls and the latter allows roles to be locked down to only allow specific projects to assume them.

SECURITY NOTE: The role session name and external ID naming scheme can be overridden using the awsrole.sessionName and awsrole.externalId parameters respectively. To ensure that projects can not maliciously override these parameters, you can enforce parameters using TeamCity.

Download

The compiled plugin ZIP can be downloaded from the Releases tab.

Notes

  • You can specify role session tags using the optional parameters of the form sessionTags = "projectId=%teamcity.project.id%". As per the linked AWS docs, this requires the assumed role's trust policy to allow sts:TagSession.

  • Both the default role session name and external ID naming schemes can be overridden using parameters sessionName and externalId respectively.

  • An IAM role session name has a maximum length of 64 characters. TeamCity project IDs can be up to 240 characters long. The role session name will be truncated to 64 characters when passed to AWS.

  • The AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN values are automatically masked by TeamCity in build logs and parameter listings for completed builds. The AWS_ACCESS_KEY_ID value is not hidden as it can be useful for searches in CloudTrail.

  • You can specify wildcards in your IAM role trust policies. An example of such a policy would be:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AssumeRoleFromTeamcity",
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::123456789012:root"
          },
          "Action": "sts:AssumeRole",
          "Condition": {
            "StringLike": {
              "sts:ExternalId": "MyTopLevelProject_TeamSpecific_*"
            }
          }
        },
        {
          "Sid": "AllowTagsToBePassed",
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::123456789012:root"
          },
          "Action": "sts:TagSession",
          "Condition": {
            "StringLike": {
              "aws:RequestTag/projectId": "*"
            }
          }
        }
      ]
    }

    This allows only subprojects and build configurations under MyTopLevelProject_TeamSpecific to assume this role.

teamcity-awsrole-plugin's People

Contributors

aidansteele avatar deuscapturus avatar kierranm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

teamcity-awsrole-plugin's Issues

Is it possible for the TeamCity agents to assume the role, instead of the server?

Thanks for writing the plugin. The README indicates,

the server assumes the requested role and sets AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN environment variables for the build.

One potential problem is that a 'test deployment' could accidentally request credentials meant for a 'production deployment' and cause damage. So we're wondering if it'd be possible to have the agents request the credentials, or is this a limitation of TeamCity plugins?

Default AWS region

Hi,

When this plugin (thx for it ๐Ÿ˜— !) is used "as it" (just upload it) in TeamCity 2022.04.4, any build using this build feature fails with:

Unable to load region from any of the providers in the chain software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain@62501254: [software.amazon.awssdk.regions.providers.SystemSettingsRegionProvider@6ee21c83: Unable to load region from system settings. Region must be specified either via environment variable (AWS_REGION) or  system property (aws.region)., software.amazon.awssdk.regions.providers.AwsProfileRegionProvider@422105e7: No region provided in profile: default, software.amazon.awssdk.regions.providers.InstanceProfileRegionProvider@2e25e758: Unable to contact EC2 metadata service.]

Although the AWS region seems not really important for aws sts assume-role (The AccessKey/Role could be defined in another region that the given), it seems required for AWS API endpoint reachability.

Adding the AWS region as Java system property (TEAMCITY_SERVER_OPTS=-Daws.region=eu-west-3) solves the problem ; But adding some "server parameters/environment" for a plugin usage is perhaps not a nice way.

=> Adding a new Region: option (at the end of list) with us-east-1 as default could perhaps a good idea ?

Otherwise, supporting parameters coming from config/internal.properties would perhaps a better solution if this kind of new option would be considered as not relevant.

I can provide a PR, but I would like some feelings about the most sustainable way.

Thanks in advance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.