Skip to content
Merged
1,630 changes: 1,249 additions & 381 deletions .drone.yml

Large diffs are not rendered by default.

138 changes: 138 additions & 0 deletions dronegen/aws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright 2022 Gravitational, Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"fmt"
"path/filepath"
)

// awsRoleSettings contains the information necessary to assume an AWS Role
//
// This is intended to be imbedded, please use the kubernetes/mac/windows versions
// with their corresponding pipelines.
type awsRoleSettings struct {
awsAccessKeyID value
awsSecretAccessKey value
role value
}

// kubernetesRoleSettings contains the info necessary to assume an AWS role and save the credentials to a volume that later steps can use
type kubernetesRoleSettings struct {
awsRoleSettings
configVolume volumeRef
name string
profile string
append bool
}

// macRoleSettings contains the info necessary to assume an AWS role and save the credentials to a path that later steps can use
type macRoleSettings struct {
awsRoleSettings
configPath string
name string
profile string
append bool
}

// kuberentesS3Settings contains all info needed to download from S3 in a kubernetes pipeline
type kubernetesS3Settings struct {
region string
source string
target string
configVolume volumeRef
}

// assumeRoleCommands is a helper to build the role assumption commands on a *nix platform
func assumeRoleCommands(profile, configPath string, appendFile bool) []string {
if profile == "" { // set a default profile if none is specified
profile = "default"
}

var redirect string
if appendFile {
redirect = ">>"
} else {
redirect = ">"
}

assumeRoleCmd := fmt.Sprintf(`printf "[%s]\naws_access_key_id = %%s\naws_secret_access_key = %%s\naws_session_token = %%s\n" \
$(aws sts assume-role \
--role-arn "$AWS_ROLE" \
--role-session-name $(echo "drone-${DRONE_REPO}-${DRONE_BUILD_NUMBER}" | sed "s|/|-|g") \
--query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" \
--output text) \
%s %s`, profile, redirect, configPath)

return []string{
`aws sts get-caller-identity`, // check the original identity
assumeRoleCmd,
`unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY`, // remove original identity from environment
`aws sts get-caller-identity --profile ` + profile, // check the new assumed identity
}
}

// kubernetesAssumeAwsRoleStep builds a step to assume an AWS role and save it to a volume that later steps can use
func kubernetesAssumeAwsRoleStep(s kubernetesRoleSettings) step {
if s.name == "" {
s.name = "Assume AWS Role"
}
configPath := filepath.Join(s.configVolume.Path, "credentials")
return step{
Name: s.name,
Image: "amazon/aws-cli",
Environment: map[string]value{
"AWS_ACCESS_KEY_ID": s.awsAccessKeyID,
"AWS_SECRET_ACCESS_KEY": s.awsSecretAccessKey,
"AWS_ROLE": s.role,
},
Volumes: []volumeRef{s.configVolume},
Commands: assumeRoleCommands(s.profile, configPath, s.append),
}
}

// macAssumeAwsRoleStep builds a step to assume an AWS role and save it to a host path that later steps can use
func macAssumeAwsRoleStep(s macRoleSettings) step {
if s.name == "" {
s.name = "Assume AWS Role"
}
return step{
Name: s.name,
Environment: map[string]value{
"AWS_ACCESS_KEY_ID": s.awsAccessKeyID,
"AWS_SECRET_ACCESS_KEY": s.awsSecretAccessKey,
"AWS_ROLE": s.role,
"AWS_SHARED_CREDENTIALS_FILE": value{raw: s.configPath},
},
Commands: assumeRoleCommands(s.profile, s.configPath, s.append),
}
}

// kubernetesUploadToS3Step generates an S3 upload step
func kubernetesUploadToS3Step(s kubernetesS3Settings) step {
return step{
Name: "Upload to S3",
Image: "amazon/aws-cli",
Environment: map[string]value{
"AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"},
"AWS_REGION": {raw: s.region},
},
Volumes: []volumeRef{s.configVolume},
Commands: []string{
`cd ` + s.source,
`aws s3 sync . s3://$AWS_S3_BUCKET/` + s.target,
},
}
}
4 changes: 2 additions & 2 deletions dronegen/buildbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func buildboxPipelineStep(buildboxName string, fips bool) step {
"QUAYIO_DOCKER_USERNAME": {fromSecret: "QUAYIO_DOCKER_USERNAME"},
"QUAYIO_DOCKER_PASSWORD": {fromSecret: "QUAYIO_DOCKER_PASSWORD"},
},
Volumes: dockerVolumeRefs(),
Volumes: []volumeRef{volumeRefDocker},
Commands: []string{
`apk add --no-cache make`,
`chown -R $UID:$GID /go`,
Expand All @@ -68,7 +68,7 @@ func buildboxPipeline() pipeline {
}

p.Workspace = workspace{Path: "/go/src/github.com/gravitational/teleport"}
p.Volumes = dockerVolumes()
p.Volumes = []volume{volumeDocker}
p.Services = []service{
dockerService(),
}
Expand Down
28 changes: 12 additions & 16 deletions dronegen/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ var (
Name: "dockersock",
Temp: &volumeTemp{},
}
volumeRefDocker = volumeRef{
Name: "dockersock",
Path: "/var/run",
}
volumeTmpfs = volume{
Name: "tmpfs",
Temp: &volumeTemp{Medium: "memory"},
Expand All @@ -49,9 +53,13 @@ var (
Name: "tmpfs",
Path: "/tmpfs",
}
volumeRefDocker = volumeRef{
Name: "dockersock",
Path: "/var/run",
volumeAwsConfig = volume{
Name: "awsconfig",
Temp: &volumeTemp{},
}
volumeRefAwsConfig = volumeRef{
Name: "awsconfig",
Path: "/root/.aws",
}

// TODO(gus): Set this from `make -C build.assets print-runtime-version` or similar rather
Expand Down Expand Up @@ -154,18 +162,6 @@ func dockerService(v ...volumeRef) service {
}
}

// dockerVolumes returns a slice of volumes
// It includes the Docker socket volume by default, plus any extra volumes passed in
func dockerVolumes(v ...volume) []volume {
return append(v, volumeDocker)
}

// dockerVolumeRefs returns a slice of volumeRefs
// It includes the Docker socket volumeRef as a default, plus any extra volumeRefs passed in
func dockerVolumeRefs(v ...volumeRef) []volumeRef {
return append(v, volumeRefDocker)
}

// releaseMakefileTarget gets the correct Makefile target for a given arch/fips/centos6 combo
func releaseMakefileTarget(b buildType) string {
makefileTarget := fmt.Sprintf("release-%s", b.arch)
Expand All @@ -190,6 +186,6 @@ func waitForDockerStep() step {
Commands: []string{
`timeout 30s /bin/sh -c 'while [ ! -S /var/run/docker.sock ]; do sleep 1; done'`,
},
Volumes: dockerVolumeRefs(),
Volumes: []volumeRef{volumeRefDocker},
}
}
19 changes: 14 additions & 5 deletions dronegen/mac.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"path"
"path/filepath"
)

// escapedPreformatted returns expr wrapped in escaped backticks,
Expand Down Expand Up @@ -76,6 +77,7 @@ func darwinTagPipeline() pipeline {
}
p := newDarwinPipeline("build-darwin-amd64")
p.Trigger = triggerTag
awsConfigPath := filepath.Join(p.Workspace.Path, "credentials")
p.DependsOn = []string{tagCleanupPipelineName}
p.Steps = []step{
setUpExecStorageStep(p.Workspace.Path),
Expand Down Expand Up @@ -105,14 +107,21 @@ func darwinTagPipeline() pipeline {
},
Commands: darwinTagCopyPackageArtifactCommands(),
},
macAssumeAwsRoleStep(macRoleSettings{
awsRoleSettings: awsRoleSettings{
awsAccessKeyID: value{fromSecret: "AWS_ACCESS_KEY_ID"},
awsSecretAccessKey: value{fromSecret: "AWS_SECRET_ACCESS_KEY"},
role: value{fromSecret: "AWS_ROLE"},
},
configPath: awsConfigPath,
}),
{
Name: "Upload to S3",
Environment: map[string]value{
"AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"},
"AWS_ACCESS_KEY_ID": {fromSecret: "AWS_ACCESS_KEY_ID"},
"AWS_SECRET_ACCESS_KEY": {fromSecret: "AWS_SECRET_ACCESS_KEY"},
"AWS_REGION": {raw: "us-west-2"},
"WORKSPACE_DIR": {raw: p.Workspace.Path},
"AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"},
"AWS_REGION": {raw: "us-west-2"},
"AWS_SHARED_CREDENTIALS_FILE": {raw: awsConfigPath},
"WORKSPACE_DIR": {raw: p.Workspace.Path},
},
Commands: darwinUploadToS3Commands(),
},
Expand Down
29 changes: 18 additions & 11 deletions dronegen/mac_pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func darwinPkgPipeline(name, makeTarget string, pkgGlobs []string, extraQualific
os: "darwin",
}
p := newDarwinPipeline(name)
awsConfigPath := filepath.Join(p.Workspace.Path, "credentials")
p.Trigger = triggerTag
p.DependsOn = []string{"build-darwin-amd64"}
p.Steps = []step{
Expand All @@ -24,15 +25,22 @@ func darwinPkgPipeline(name, makeTarget string, pkgGlobs []string, extraQualific
},
Commands: darwinTagCheckoutCommands(),
},
macAssumeAwsRoleStep(macRoleSettings{
awsRoleSettings: awsRoleSettings{
awsAccessKeyID: value{fromSecret: "AWS_ACCESS_KEY_ID"},
awsSecretAccessKey: value{fromSecret: "AWS_SECRET_ACCESS_KEY"},
role: value{fromSecret: "AWS_ROLE"},
},
configPath: awsConfigPath,
}),
{
Name: "Download built tarball artifacts from S3",
Environment: map[string]value{
"AWS_REGION": {raw: "us-west-2"},
"AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"},
"AWS_ACCESS_KEY_ID": {fromSecret: "AWS_ACCESS_KEY_ID"},
"AWS_SECRET_ACCESS_KEY": {fromSecret: "AWS_SECRET_ACCESS_KEY"},
"GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"},
"WORKSPACE_DIR": {raw: p.Workspace.Path},
"AWS_REGION": {raw: "us-west-2"},
"AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"},
"AWS_SHARED_CREDENTIALS_FILE": {raw: awsConfigPath},
"GITHUB_PRIVATE_KEY": {fromSecret: "GITHUB_PRIVATE_KEY"},
"WORKSPACE_DIR": {raw: p.Workspace.Path},
},
Commands: darwinTagDownloadArtifactCommands(),
},
Expand Down Expand Up @@ -60,11 +68,10 @@ func darwinPkgPipeline(name, makeTarget string, pkgGlobs []string, extraQualific
{
Name: "Upload to S3",
Environment: map[string]value{
"AWS_REGION": {raw: "us-west-2"},
"AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"},
"AWS_ACCESS_KEY_ID": {fromSecret: "AWS_ACCESS_KEY_ID"},
"AWS_SECRET_ACCESS_KEY": {fromSecret: "AWS_SECRET_ACCESS_KEY"},
"WORKSPACE_DIR": {raw: p.Workspace.Path},
"AWS_REGION": {raw: "us-west-2"},
"AWS_S3_BUCKET": {fromSecret: "AWS_S3_BUCKET"},
"AWS_SHARED_CREDENTIALS_FILE": {raw: awsConfigPath},
"WORKSPACE_DIR": {raw: p.Workspace.Path},
},
Commands: []string{
`set -u`,
Expand Down
4 changes: 2 additions & 2 deletions dronegen/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func pushPipeline(b buildType) pipeline {
}
p.Trigger = triggerPush
p.Workspace = workspace{Path: "/go"}
p.Volumes = dockerVolumes()
p.Volumes = []volume{volumeDocker}
p.Services = []service{
dockerService(),
}
Expand All @@ -113,7 +113,7 @@ func pushPipeline(b buildType) pipeline {
Name: "Build artifacts",
Image: "docker",
Environment: pushEnvironment,
Volumes: dockerVolumeRefs(),
Volumes: []volumeRef{volumeRefDocker},
Commands: pushBuildCommands(b),
},
{
Expand Down
38 changes: 25 additions & 13 deletions dronegen/relcli.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,39 @@ func relcliPipeline(trigger trigger, name string, stepName string, command strin
},
},
waitForDockerStep(),
pullRelcliStep(),
kubernetesAssumeAwsRoleStep(kubernetesRoleSettings{
awsRoleSettings: awsRoleSettings{
awsAccessKeyID: value{fromSecret: "TELEPORT_BUILD_USER_READ_ONLY_KEY"},
awsSecretAccessKey: value{fromSecret: "TELEPORT_BUILD_USER_READ_ONLY_SECRET"},
role: value{fromSecret: "TELEPORT_BUILD_READ_ONLY_AWS_ROLE"},
},
configVolume: volumeRefAwsConfig,
}),
pullRelcliStep(volumeRefAwsConfig),
executeRelcliStep(stepName, command),
}

p.Services = []service{
dockerService(volumeRefTmpfs),
p.Services = []service{dockerService(volumeRefTmpfs)}
p.Volumes = []volume{
volumeDocker,
volumeTmpfs,
volumeAwsConfig,
}
p.Volumes = dockerVolumes(volumeTmpfs)

return p
}

func pullRelcliStep() step {
func pullRelcliStep(awsConfigVolumeRef volumeRef) step {
return step{
Name: "Pull relcli",
Image: "docker:cli",
Environment: map[string]value{
"AWS_ACCESS_KEY_ID": {fromSecret: "TELEPORT_BUILD_USER_READ_ONLY_KEY"},
"AWS_SECRET_ACCESS_KEY": {fromSecret: "TELEPORT_BUILD_USER_READ_ONLY_SECRET"},
"AWS_DEFAULT_REGION": {raw: "us-west-2"},
"AWS_DEFAULT_REGION": {raw: "us-west-2"},
},
Volumes: []volumeRef{
volumeRefDocker,
volumeRefAwsConfig,
},
Volumes: dockerVolumeRefs(),
Commands: []string{
`apk add --no-cache aws-cli`,
`aws ecr get-login-password | docker login -u="AWS" --password-stdin 146628656107.dkr.ecr.us-west-2.amazonaws.com`,
Expand All @@ -72,10 +83,11 @@ func executeRelcliStep(name string, command string) step {
"RELCLI_CERT": {raw: "/tmpfs/creds/releases.crt"},
"RELCLI_KEY": {raw: "/tmpfs/creds/releases.key"},
},
Volumes: dockerVolumeRefs(volumeRef{
Name: "tmpfs",
Path: "/tmpfs",
}),
Volumes: []volumeRef{
volumeRefDocker,
volumeRefTmpfs,
volumeRefAwsConfig,
},
Commands: []string{
`mkdir -p /tmpfs/creds`,
`echo "$RELEASES_CERT" | base64 -d > "$RELCLI_CERT"`,
Expand Down
Loading