From c645dca3270562f2f8f3a530b537926a7ace99ca Mon Sep 17 00:00:00 2001 From: Clare Liguori Date: Tue, 1 Sep 2020 20:19:08 -0700 Subject: [PATCH 1/4] docs(aws): add CloudFormation templates to spinnaker.io downloads folder --- downloads/aws/managed.yaml | 38 ++++ downloads/aws/managing.yaml | 293 +++++++++++++++++++++++++ setup/install/providers/aws/aws-ec2.md | 14 +- 3 files changed, 338 insertions(+), 7 deletions(-) create mode 100644 downloads/aws/managed.yaml create mode 100644 downloads/aws/managing.yaml diff --git a/downloads/aws/managed.yaml b/downloads/aws/managed.yaml new file mode 100644 index 0000000000..f1a6f4f14a --- /dev/null +++ b/downloads/aws/managed.yaml @@ -0,0 +1,38 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: Setup AWS CloudProvider for Spinnaker +Parameters: + AuthArn: + Description: ARN which Spinnaker is using. It should be the ARN either of the IAM user or the EC2 Instance Role, which is used by Spinnaker in Managing Account + Type: String + ManagingAccountId: + Description: AWS Account number, in which Spinnaker is running + Type: String + +Resources: + + SpinnakerManagedRole: + Type: AWS::IAM::Role + Properties: + RoleName: spinnakerManaged + AssumeRolePolicyDocument: + Statement: + - Action: + - sts:AssumeRole + Effect: Allow + Principal: + AWS: !Ref AuthArn + Version: '2012-10-17' + ManagedPolicyArns: + - arn:aws:iam::aws:policy/PowerUserAccess + SpinnakerManagedPolicy: + Type: AWS::IAM::Policy + Properties: + Roles: + - !Ref SpinnakerManagedRole + PolicyDocument: + Version: '2012-10-17' + Statement: + - Action: iam:PassRole + Effect: Allow + Resource: "*" # You should restrict this only to certain set of roles, if required + PolicyName: SpinnakerPassRole \ No newline at end of file diff --git a/downloads/aws/managing.yaml b/downloads/aws/managing.yaml new file mode 100644 index 0000000000..0d8df82d71 --- /dev/null +++ b/downloads/aws/managing.yaml @@ -0,0 +1,293 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Setup AWS CloudProvider for Spinnaker +Parameters: + SpinnakerVPCCIDR: + Description: CIDR Block for Developer VPC + Type: String + Default: 10.100.0.0/16 + SpinnakerPublicSubnet1CIDR: + Description: SpinnakerEnv Public Subnet + Type: String + Default: 10.100.10.0/24 + ConstraintDescription: IP CIDR must be in the range of your VPC + SpinnakerPublicSubnet2CIDR: + Description: SpinnakerEnv Private Subnet + Type: String + Default: 10.100.11.0/24 + ConstraintDescription: IP CIDR must be in the range of your VPC + UseAccessKeyForAuthentication: + Description: > + Select Yes, if you want to use Access Keys and Secrets for Authentication.Selecting Yes will also create Access Keys and Secrets, + which will be visible in Outputs Section, once the template runs successfully. It is recommended that you update the stack and remove the outputs section. + Select No, if you will use EC2 Instance profile. + Type: String + AllowedValues: + - true + - false + EksClusterName: + Description: > + Enter EKS cluster name, if you want to run Spinnaker on EKS. Please ensure EKS is available in the region you are executing this template. + For more information about EKS availability, refer https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/ + If you leave this parameter as the default value of None, EKS cluster will not be created. + Type: String + Default: None + +Conditions: + CreateAccessKeys: !Equals [!Ref UseAccessKeyForAuthentication, true] + CreateEc2Role: !Equals [!Ref UseAccessKeyForAuthentication, false] + SupportEKS: !Not [!Equals ["None", !Ref EksClusterName]] +Resources: + BaseIAMRole: + Properties: + RoleName: BaseIAMRole + AssumeRolePolicyDocument: + Statement: + - Action: + - sts:AssumeRole + Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Version: "2012-10-17" + Path: / + Type: AWS::IAM::Role + + EksServiceRole: + Type: AWS::IAM::Role + Condition: SupportEKS + Properties: + AssumeRolePolicyDocument: + Statement: + - Action: + - sts:AssumeRole + Effect: Allow + Principal: + Service: + - eks.amazonaws.com + Version: "2012-10-17" + Path: / + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonEKSClusterPolicy + - arn:aws:iam::aws:policy/AmazonEKSServicePolicy + EksCluster: + Type: AWS::EKS::Cluster + Condition: SupportEKS + Properties: + Name: !Ref EksClusterName + Version: "1.14" + RoleArn: !GetAtt EksServiceRole.Arn + ResourcesVpcConfig: + SecurityGroupIds: + - !Ref ControlPlaneSecurityGroup + SubnetIds: + - !Ref SpinnakerPublicSubnet1 + - !Ref SpinnakerPublicSubnet2 + + # Creates Instance Profile to be used by any APP created by Spinnaker. Spinnaker has passRole access only to this instance Profile + BaseInstanceProfile: + DependsOn: SpinnakerAuthRole + Condition: CreateEc2Role + Properties: + InstanceProfileName: BaseInstanceProfile + Path: / + Roles: + - !Ref BaseIAMRole + Type: AWS::IAM::InstanceProfile + + # Creates EC2 Role and Instance Profile with which Spinnaker Runs + SpinnakerInstanceProfile: + DependsOn: SpinnakerAuthRole + Condition: CreateEc2Role + Properties: + Path: / + Roles: + - !Ref "SpinnakerAuthRole" + Type: AWS::IAM::InstanceProfile + SpinnakerAuthRole: + Properties: + RoleName: SpinnakerAuthRole + AssumeRolePolicyDocument: + Statement: + - Action: + - sts:AssumeRole + Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Version: "2012-10-17" + ManagedPolicyArns: + - arn:aws:iam::aws:policy/PowerUserAccess + - !If [ + SupportEKS, + "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", + !Ref "AWS::NoValue", + ] + - !If [ + SupportEKS, + "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", + !Ref "AWS::NoValue", + ] + - !If [ + SupportEKS, + "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", + !Ref "AWS::NoValue", + ] + Type: AWS::IAM::Role + Condition: CreateEc2Role + + # Creates IAM user and AccessKeys + SpinnakerUser: + Description: User identity Spinnaker uses to create AWS resources + Properties: + ManagedPolicyArns: + - arn:aws:iam::aws:policy/PowerUserAccess + Type: AWS::IAM::User + Condition: CreateAccessKeys + SpinnakerAccessKey: + DependsOn: SpinnakerUser + Condition: CreateAccessKeys + Description: Generate AccessKey for Spinnaker + Properties: + UserName: !Ref "SpinnakerUser" + Type: AWS::IAM::AccessKey + + # Either Keys or Instances + + SpinnakerAssumeRolePolicy: + Type: AWS::IAM::Policy + Properties: + Users: + - !If [CreateAccessKeys, !Ref SpinnakerUser, !Ref "AWS::NoValue"] + Roles: + - !If [CreateEc2Role, !Ref SpinnakerAuthRole, !Ref "AWS::NoValue"] + PolicyDocument: + Version: "2012-10-17" + Statement: + - Action: sts:AssumeRole + Effect: Allow + Resource: + - !Sub arn:aws:iam::${AWS::AccountId}:role/spinnakerManaged # This is the current account + #- arn:aws:iam::YOUR_MANAGED_ACCOUNT1:role/spinnakerManaged # Keep Adding Managed Accounts like this + PolicyName: SpinnakerAssumeRolePolicy + + # Creates a single subnet VPC + SpinnakerVPC: + Type: AWS::EC2::VPC + Properties: + CidrBlock: !Ref "SpinnakerVPCCIDR" + EnableDnsSupport: "true" + EnableDnsHostnames: "true" + Tags: + - Key: VPC + Value: Spinnaker VPC + - Key: Name + Value: SpinnakerVPC + SpinnakerInternetGateway: + Type: AWS::EC2::InternetGateway + SpinnakerAttachGateway: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + VpcId: !Ref "SpinnakerVPC" + InternetGatewayId: !Ref "SpinnakerInternetGateway" + SpinnakerPublicSubnet1: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref "SpinnakerVPC" + CidrBlock: !Ref SpinnakerPublicSubnet1CIDR + AvailabilityZone: !Select + - "0" + - !GetAZs "" + Tags: + - Key: Name + Value: !Sub SpinnakerVPC.external.${AWS::Region}a + - Key: immutable_metadata # If you cannot name the VPC as done above, use this tag + Value: !Sub | + {"purpose": "public-subnet"} + SpinnakerPublicSubnet2: + Type: AWS::EC2::Subnet + Properties: + VpcId: !Ref "SpinnakerVPC" + CidrBlock: !Ref SpinnakerPublicSubnet2CIDR + AvailabilityZone: !Select + - "1" + - !GetAZs "" + Tags: + - Key: Name + Value: !Sub SpinnakerVPC.external.${AWS::Region}b + - Key: immutable_metadata + Value: !Sub | + {"purpose": "public-subnet"} + SpinnakerPublicRouteTable: + Type: AWS::EC2::RouteTable + DependsOn: + - SpinnakerVPC + - SpinnakerAttachGateway + Properties: + VpcId: !Ref "SpinnakerVPC" + Tags: + - Key: Name + Value: Spinnaker Public Route Table + SpinnakerPublicRoute: + Type: AWS::EC2::Route + Properties: + RouteTableId: !Ref "SpinnakerPublicRouteTable" + DestinationCidrBlock: "0.0.0.0/0" + GatewayId: !Ref "SpinnakerInternetGateway" + SpinnakerPublicSubnet1RouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref SpinnakerPublicSubnet1 + RouteTableId: !Ref "SpinnakerPublicRouteTable" + SpinnakerPublicSubnet2RouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref SpinnakerPublicSubnet2 + RouteTableId: !Ref "SpinnakerPublicRouteTable" + + ControlPlaneSecurityGroup: + Type: AWS::EC2::SecurityGroup + Condition: SupportEKS + Properties: + GroupDescription: Cluster communication with worker nodes + VpcId: !Ref SpinnakerVPC + +Outputs: + AccessKeyId: + Condition: CreateAccessKeys + Value: !Ref SpinnakerAccessKey + Secret: + Condition: CreateAccessKeys + Value: !GetAtt SpinnakerAccessKey.SecretAccessKey + ManagingAccountId: + Value: !Ref AWS::AccountId + AuthArn: + Value: + !If [ + CreateAccessKeys, + !GetAtt SpinnakerUser.Arn, + !GetAtt SpinnakerAuthRole.Arn, + ] + EksClusterEndpoint: + Condition: SupportEKS + Value: !GetAtt EksCluster.Endpoint + EksClusterCA: + Condition: SupportEKS + Value: !GetAtt EksCluster.CertificateAuthorityData + SubnetIds: + Description: All subnets in the VPC + Value: + !Join [",", [!Ref SpinnakerPublicSubnet1, !Ref SpinnakerPublicSubnet2]] + EksClusterName: + Condition: SupportEKS + Value: !Ref EksClusterName + + SpinnakerInstanceProfileArn: + Value: !GetAtt SpinnakerInstanceProfile.Arn + + VpcId: + Value: !Ref SpinnakerVPC + + SecurityGroups: + Condition: SupportEKS + Description: Security group for the cluster control plane communication with worker nodes + Value: !Join [",", [!Ref ControlPlaneSecurityGroup]] diff --git a/setup/install/providers/aws/aws-ec2.md b/setup/install/providers/aws/aws-ec2.md index 43b3f78b8f..36eb442090 100644 --- a/setup/install/providers/aws/aws-ec2.md +++ b/setup/install/providers/aws/aws-ec2.md @@ -23,7 +23,7 @@ Use this option to deploy Spinnaker, if you are familar with deployment using [A ### Managing Account 1. Navigate to [Console](https://console.aws.amazon.com/){:target="\_blank"} > CloudFormation and [select](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/getting-started.html#select-region) your preferred region. -2. Download [the template](https://d3079gxvs8ayeg.cloudfront.net/templates/managing.yaml) locally to your workstation. +2. Download [the template](https://www.spinnaker.io/downloads/aws/managing.yaml) locally to your workstation. 2.a (Optional). Add additional managed account as shown on line 158 in the SpinnakerAssumeRolePolicy section of the downloaded template file. 3. Creating the CloudFormation Stack @@ -37,7 +37,7 @@ Use this option to deploy Spinnaker, if you are familar with deployment using [A > These steps need to be carried out for the managing account as well. 1. Navigate to [Console](https://console.aws.amazon.com/){:target="\_blank"} > CloudFormation and [select](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/getting-started.html#select-region) your preferred region. -2. Download [the template](https://d3079gxvs8ayeg.cloudfront.net/templates/managed.yaml) locally to your workstation. +2. Download [the template](https://www.spinnaker.io/downloads/aws/managed.yaml) locally to your workstation. 3. Creating the CloudFormation Stack * __Create Stack__ > __Upload a template to Amazon S3__ > __Browse to template you downloaded in Step-2 above__ > __Next__ * Enter __Stack Name__ as spinnaker-**managed**-infrastructure-setup and follow the prompts on screen to create the stack @@ -57,7 +57,7 @@ If you want to use AccessKeys and Secrets to run Spinnaker ```bash -curl -O https://d3079gxvs8ayeg.cloudfront.net/templates/managing.yaml +curl -O https://www.spinnaker.io/downloads/aws/managing.yaml echo "Optionally add Managing account to the file downloaded as shown on line 158 in the SpinnakerAssumeRolePolicy section of the downloaded file." aws cloudformation deploy --stack-name spinnaker-managing-infrastructure-setup --template-file managing.yaml \ --parameter-overrides UseAccessKeyForAuthentication=true --capabilities CAPABILITY_NAMED_IAM --region us-west-2 @@ -67,7 +67,7 @@ If you want to use InstanceProfile run Spinnaker ```bash -curl -O https://d3079gxvs8ayeg.cloudfront.net/templates/managing.yaml +curl -O https://www.spinnaker.io/downloads/aws/managing.yaml echo "Optionally add Managing account to the file downloaded as shown on line 158 in the SpinnakerAssumeRolePolicy section of the downloaded file." aws cloudformation deploy --stack-name spinnaker-managing-infrastructure-setup --template-file managing.yaml \ --parameter-overrides UseAccessKeyForAuthentication=false --capabilities CAPABILITY_NAMED_IAM --region us-west-2 @@ -80,16 +80,16 @@ aws cloudformation deploy --stack-name spinnaker-managing-infrastructure-setup - ```bash -curl -O https://d3079gxvs8ayeg.cloudfront.net/templates/managed.yaml +curl -O https://www.spinnaker.io/downloads/aws/managed.yaml aws cloudformation deploy --stack-name spinnaker-managed-infrastructure-setup --template-file managed.yaml \ --parameter-overrides AuthArn=FROM_ABOVE ManagingAccountId=FROM_ABOVE --capabilities CAPABILITY_NAMED_IAM --region us-west-2 ``` -## Option-3 : Use AWS Console UI (Manual Steps) +## Option-3 : Use AWS Console UI (Manual Steps) There are 2 options here 1. Using AWS IAM AccessKey and Secret -Option number 1 is useful for creation of user with AWS Access Key and secret. This is a common configuration. +Option number 1 is useful for creation of user with AWS Access Key and secret. This is a common configuration. 2. Using AWS IAM Roles Option 2 uses the IAM roles *ManagingRole* and *ManagedRoles*. This setting is applied on some environments that have extra security considerations. From 24cf4ab2cc307815c016f0d1db04e97c985c5a05 Mon Sep 17 00:00:00 2001 From: Clare Liguori Date: Tue, 1 Sep 2020 20:22:02 -0700 Subject: [PATCH 2/4] docs(aws): Fix broken CFN output when EC2 role is not created --- downloads/aws/managing.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/downloads/aws/managing.yaml b/downloads/aws/managing.yaml index 0d8df82d71..eb027c2e39 100644 --- a/downloads/aws/managing.yaml +++ b/downloads/aws/managing.yaml @@ -282,6 +282,7 @@ Outputs: Value: !Ref EksClusterName SpinnakerInstanceProfileArn: + Condition: CreateEc2Role Value: !GetAtt SpinnakerInstanceProfile.Arn VpcId: From 8c091bf62c69b477e24a26bbc57e493538bd8c7c Mon Sep 17 00:00:00 2001 From: Clare Liguori Date: Tue, 1 Sep 2020 20:59:30 -0700 Subject: [PATCH 3/4] docs(aws): Switch to using Secrets Manager to store access key creds instead of directly in CFN outputs --- downloads/aws/managing.yaml | 19 ++++++++++++++----- setup/install/providers/aws/aws-ec2.md | 19 ++++++++++++++++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/downloads/aws/managing.yaml b/downloads/aws/managing.yaml index eb027c2e39..a89f5c800f 100644 --- a/downloads/aws/managing.yaml +++ b/downloads/aws/managing.yaml @@ -150,6 +150,18 @@ Resources: Properties: UserName: !Ref "SpinnakerUser" Type: AWS::IAM::AccessKey + SpinnakerAccessKeyCredentials: + DependsOn: SpinnakerAccessKey + Condition: CreateAccessKeys + Description: Store the access key credentials for Spinnaker in a secure location + Type: AWS::SecretsManager::Secret + Properties: + Description: Spinnaker user access key credentials + SecretString: !Sub | + { + "AccessKeyId":"${SpinnakerAccessKey}", + "SecretAccessKey":"${SpinnakerAccessKey.SecretAccessKey}" + } # Either Keys or Instances @@ -252,12 +264,9 @@ Resources: VpcId: !Ref SpinnakerVPC Outputs: - AccessKeyId: - Condition: CreateAccessKeys - Value: !Ref SpinnakerAccessKey - Secret: + SpinnakerUserSecret: Condition: CreateAccessKeys - Value: !GetAtt SpinnakerAccessKey.SecretAccessKey + Value: !Ref SpinnakerAccessKeyCredentials ManagingAccountId: Value: !Ref AWS::AccountId AuthArn: diff --git a/setup/install/providers/aws/aws-ec2.md b/setup/install/providers/aws/aws-ec2.md index 36eb442090..cea77d1e83 100644 --- a/setup/install/providers/aws/aws-ec2.md +++ b/setup/install/providers/aws/aws-ec2.md @@ -30,7 +30,10 @@ Use this option to deploy Spinnaker, if you are familar with deployment using [A * __Create Stack__ > __Upload a template to Amazon S3__ > __Browse to template you downloaded in Step-2 above__ > __Next__ * Enter __Stack Name__ as spinnaker-**managing**-infrastructure-setup and follow the prompts on screen to create the stack 4. Once the stack is select the stack you created in Step-3 > Outputs and note the values. You will need these values for subsequent configurations. - +5. If you set UseAccessKeyForAuthentication to "true" for the stack, retrieve the access key credentials. + * Navigate to the Secrets Manager console. + * Select the secret created by your CloudFormation stack. The name of the secret was shown in the __SpinnakerUserSecret__ output value for the stack. + * Click __Retrieve secret value__ and note the values. You will need these values for subsequent configurations. ### In each of the Managed Account @@ -73,6 +76,20 @@ aws cloudformation deploy --stack-name spinnaker-managing-infrastructure-setup - --parameter-overrides UseAccessKeyForAuthentication=false --capabilities CAPABILITY_NAMED_IAM --region us-west-2 ``` +After deploying the stack, retrieve the outputs for the created stack: + +```bash + +aws cloudformation describe-stacks --stack-name spinnaker-managing-infrastructure-setup --region us-west-2 --query 'Stacks[0].Outputs' +``` + +If you chose to use AccessKeys and Secrets to run Spinnaker, retrieve the values from Secrets Manager using the secret ARN in the stack's SpinnakerUserSecret output: + +```bash + +aws secretsmanager get-secret-value --secret-id FROM_ABOVE --region us-west-2 +``` + ### In each of the Managed Account > These steps need to be carried out for the managing account as well. From 52c0cebb81e22bf283fd8fc7eeae8d85364d825d Mon Sep 17 00:00:00 2001 From: Clare Liguori Date: Tue, 1 Sep 2020 21:00:44 -0700 Subject: [PATCH 4/4] docs(aws): Temporarily remove 'option 3' stub from EC2 docs --- setup/install/providers/aws/aws-ec2.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/setup/install/providers/aws/aws-ec2.md b/setup/install/providers/aws/aws-ec2.md index cea77d1e83..10f79f501b 100644 --- a/setup/install/providers/aws/aws-ec2.md +++ b/setup/install/providers/aws/aws-ec2.md @@ -102,14 +102,6 @@ aws cloudformation deploy --stack-name spinnaker-managed-infrastructure-setup -- --parameter-overrides AuthArn=FROM_ABOVE ManagingAccountId=FROM_ABOVE --capabilities CAPABILITY_NAMED_IAM --region us-west-2 ``` -## Option-3 : Use AWS Console UI (Manual Steps) - -There are 2 options here -1. Using AWS IAM AccessKey and Secret -Option number 1 is useful for creation of user with AWS Access Key and secret. This is a common configuration. -2. Using AWS IAM Roles -Option 2 uses the IAM roles *ManagingRole* and *ManagedRoles*. This setting is applied on some environments that have extra security considerations. - ## Halyard Configurations After the AWS IAM user, roles, policies and trust relationship have been set up, the next step is to add the AWS configurations to Spinnaker via Halyard CLI: