Infrastructure

Spinnaker

  • Foremast assumes that Spinnaker is already setup. Please see the Spinnaker documentation for assistance
  • Requires connectivity to the Gate component of Spinnaker. Foremast also supports x509 authentication on Gate.
  • Assumes AWS EBS is used for Packer bakes in Spinnaker Rosco

Spinnaker Component Versions

Previously, we used to publish internally tested versions. We have since moved to leveraging the release cadence set forth by the Spinnaker community. For more info around the Spinnaker release cadence, refer to the official can be found Spinnaker Release Cadence page.

For the latest releases of Spinnaker, check out the official Spinnaker Release Versions page.

If you have any issues with Foremast on the latest Spinnaker version, please file an issue (or pull request).

AWS

Foremast only works with AWS (for now). Below are the AWS requirements:

AWS VPC Subnet Tags/Names

Note

This is a general Spinnaker requirement when working with VPCs

  • If new subnets are being setup, follow the Spinnaker AWS Setup guide.
  • If using existing subnets add an immutable_metadata tag.
    • Example immutable_metadata tag: {"purpose": "external", "target": "elb"}
    • The "purpose" key will dictate how this appears in Spinnaker.
      • Needs to be "internal" or "external" in order to properly work with Foremast

Foremast IAM Infrastructure

  • A general IAM user/role will be needed for Foremast to work. In addition, Foremast will need credentials set up in a Boto3 configuration file. See AWS Credentials for details.
  • Spinnaker handles the updates for things such as ELBs and security groups.

Foremast IAM Policy

Warning

The IAM Policy found below is a very generic policy for generic usage. You can and should consider locking down further using specific resource policies!

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutLifecycleConfiguration",
                "s3:PutEncryptionConfiguration",
                "s3:PutBucketWebsite",
                "s3:PutBucketVersioning",
                "s3:PutBucketTagging",
                "s3:PutBucketPolicy",
                "s3:PutBucketNotification",
                "s3:PutBucketLogging",
                "s3:PutBucketCors",
                "s3:ListObjects",
                "s3:ListBucket",
                "s3:GetObject",
                "s3:GetBucketTagging",
                "s3:GetBucketLocation",
                "s3:DeleteObject",
                "s3:DeleteBucketWebsite",
                "s3:DeleteBucketPolicy",
                "s3:CreateBucket"
            ],
            "Resource": "*"
        },
        {
            "Sid": "EMR",
            "Effect": "Allow",
            "Action": "elasticmapreduce:*",
            "Resource": "*"
        },
        {
            "Sid": "Firehose",
            "Effect": "Allow",
            "Action": "firehose:*",
            "Resource": "*"
        },
        {
            "Sid": "SQS",
            "Effect": "Allow",
            "Action": "sqs:*",
            "Resource": "*"
        },
        {
            "Sid": "Kinesis",
            "Effect": "Allow",
            "Action": "kinesis:*",
            "Resource": "*"
        },
        {
            "Sid": "CloudwatchEvents",
            "Effect": "Allow",
            "Action": [
                "events:RemoveTargets",
                "events:PutTargets",
                "events:PutRule",
                "events:ListRules"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Lambda",
            "Effect": "Allow",
            "Action": "lambda:*",
            "Resource": "*"
        },
        {
            "Sid": "APIGateway",
            "Effect": "Allow",
            "Action": "apigateway:*",
            "Resource": "*"
        },
        {
            "Sid": "DataPipeline",
            "Effect": "Allow",
            "Action": "datapipeline:*",
            "Resource": "*"
        },
        {
            "Sid": "SNS",
            "Effect": "Allow",
            "Action": [
                "sns:Unsubscribe",
                "sns:Subscribe",
                "sns:ListTopics"
            ],
            "Resource": "*"
        },
        {
            "Sid": "CloudwatchLogs",
            "Effect": "Allow",
            "Action": [
                "logs:PutSubscriptionFilter",
                "logs:DescribeSubscriptionFilters",
                "logs:DeleteSubscriptionFilter"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Route53",
            "Effect": "Allow",
            "Action": "route53:*",
            "Resource": "*"
        },
        {
            "Sid": "ELB",
            "Effect": "Allow",
            "Action": [
                "elasticloadbalancing:SetLoadBalancerPoliciesOfListener",
                "elasticloadbalancing:ModifyLoadBalancerAttributes",
                "elasticloadbalancing:DescribeLoadBalancers",
                "elasticloadbalancing:CreateLBCookieStickinessPolicy",
                "elasticloadbalancing:CreateAppCookieStickinessPolicy"
            ],
            "Resource": "*"
        },
        {
            "Sid": "EC2",
            "Effect": "Allow",
            "Action": [
                "ec2:RevokeSecurityGroupIngress",
                "ec2:RevokeSecurityGroupEgress",
                "ec2:DescribeVpcs*",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",
                "ec2:DeleteSecurityGroup",
                "ec2:CreateTags",
                "ec2:CreateSecurityGroup",
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:AuthorizeSecurityGroupEgress"
            ],
            "Resource": "*"
        },
        {
            "Sid": "ASG",
            "Effect": "Allow",
            "Action": [
                "autoscaling:PutScheduledUpdateGroupAction",
                "autoscaling:DescribeScheduledActions",
                "autoscaling:DescribeAutoScalingGroups",
                "autoscaling:DeleteScheduledAction"
            ],
            "Resource": "*"
        },
        {
            "Sid": "IAM",
            "Effect": "Allow",
            "Action": [
                "iam:RemoveRoleFromInstanceProfile",
                "iam:PutRolePolicy",
                "iam:PassRole",
                "iam:ListServerCertificates",
                "iam:ListInstanceProfilesForRole",
                "iam:GetRole",
                "iam:CreateUser",
                "iam:CreateRole",
                "iam:CreateInstanceProfile",
                "iam:CreateGroup",
                "iam:AddUserToGroup",
                "iam:AddRoleToInstanceProfile"
            ],
            "Resource": "*"
        }
    ]
}

Jenkins

Foremast takes advantage of the Spinnaker Jenkins stage. In order for the Foremast generated pipeline to work you will need the following:

  • Jenkins configuration named “JenkinsCI” in Spinnaker Igor

    • Example Igor config:

      jenkins:
        Masters:
          -
            name: 'JenkinsCI' # The display name for this server
            address: 'http://jenkinsci.example.com'
            username: 'spinnaker'
            password: 'password'
      

Necessary Jenkins Jobs

The default generated pipeline requires a couple of Jenkins jobs to be setup in order to run.

  • pipes-pipeline-prepare

    • Runs Foremast prepare-infrastructure during the “Infrastructure Setup” pipeline stage

    • Requires the following string variables

      • PROJECT
      • GIT_REPO
      • ENV
      • REGION
    • Example Shell after cloning Foremast:

      virtualenv -p python3 venv
      . venv/bin/activate
      pip install -U --quiet .
      
      prepare-infrastructure
      
  • pipes-scaling-policy

    • Runs Foremast create-scaling-policy for attaching a scaling policy if defined.

    • Only necessary if you plan on attaching scaling policies

    • Requires the following string variables

      • PROJECT
      • GIT_REPO
      • ENV
      • REGION
    • Example Shell after cloning Foremast

      virtualenv -p python3 venv
      . venv/bin/activate
      pip install -U --quiet .
      
      create-scaling-policy
      
      # You can export these variables or also pass them beforehand such as:
      export GIT_REPO=<repo_name>
      export ENV=<spinnaker_env_name>
      
      PROJECT=<repo_project> RUNWAY_DIR=<OS_path_to_runway_dir> \
         REGION=<spinnaker_env_region> \
         foremast-infrastructure
      

Gitlab

Gitlab is not required for Spinnaker but if it is already part of your infrastructure you can have Foremast directly look up the pipeline.json and application-master-$account.json files. You will need to get the Gitlab Token of a user that has permissions to the desired repository and set them in your foremast.cfg / config.py.