Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow ssh-credentials to be set in agent and plugin #248

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
8 changes: 6 additions & 2 deletions examples/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@ org: my-buildkite-org
# the UUID may be found in the cluster settings
cluster-uuid: beefcafe-abbe-baba-abba-deedcedecade
tags:
- queue=my-queue
- priority=high
- queue=my-queue
- priority=high
# ssh-credentials-secret are the secret with the ssh credentials
# configured on the agent with docker-ssh-config
# @see https://github.com/buildkite/docker-ssh-env-config
ssh-credentials-secret: buildkite-ssh-github-creds
24 changes: 13 additions & 11 deletions internal/controller/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ const (
)

type Config struct {
Debug bool `mapstructure:"debug"`
AgentTokenSecret string `mapstructure:"agent-token-secret" validate:"required"`
BuildkiteToken string `mapstructure:"buildkite-token" validate:"required"`
Image string `mapstructure:"image" validate:"required"`
JobTTL time.Duration `mapstructure:"job-ttl"`
MaxInFlight int `mapstructure:"max-in-flight" validate:"min=0"`
Namespace string `mapstructure:"namespace" validate:"required"`
Org string `mapstructure:"org" validate:"required"`
Tags stringSlice `mapstructure:"tags" validate:"min=1"`
ProfilerAddress string `mapstructure:"profiler-address" validate:"omitempty,hostname_port"`
ClusterUUID string `mapstructure:"cluster-uuid" validate:"omitempty"`
Debug bool `mapstructure:"debug"`
AgentTokenSecret string `mapstructure:"agent-token-secret" validate:"required"`
BuildkiteToken string `mapstructure:"buildkite-token" validate:"required"`
Image string `mapstructure:"image" validate:"required"`
JobTTL time.Duration `mapstructure:"job-ttl"`
MaxInFlight int `mapstructure:"max-in-flight" validate:"min=0"`
Namespace string `mapstructure:"namespace" validate:"required"`
Org string `mapstructure:"org" validate:"required"`
Tags stringSlice `mapstructure:"tags" validate:"min=1"`
ProfilerAddress string `mapstructure:"profiler-address" validate:"omitempty,hostname_port"`
ClusterUUID string `mapstructure:"cluster-uuid" validate:"omitempty"`
SSHCredentialsSecret string `mapstructure:"ssh-credentials-secret" validate:"omitempty"`
}

type stringSlice []string
Expand All @@ -39,6 +40,7 @@ func (s stringSlice) MarshalLogArray(enc zapcore.ArrayEncoder) error {

func (c Config) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddString("agent-token-secret", c.AgentTokenSecret)
enc.AddString("ssh-credentials-secret", c.SSHCredentialsSecret)
enc.AddBool("debug", c.Debug)
enc.AddString("image", c.Image)
enc.AddDuration("job-ttl", c.JobTTL)
Expand Down
9 changes: 5 additions & 4 deletions internal/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ func Run(
}

sched := scheduler.New(logger.Named("scheduler"), k8sClient, scheduler.Config{
Namespace: cfg.Namespace,
Image: cfg.Image,
AgentToken: cfg.AgentTokenSecret,
JobTTL: cfg.JobTTL,
Namespace: cfg.Namespace,
Image: cfg.Image,
AgentToken: cfg.AgentTokenSecret,
JobTTL: cfg.JobTTL,
SSHCredentialsSecret: cfg.SSHCredentialsSecret,
})
limiter := scheduler.NewLimiter(logger.Named("limiter"), sched, cfg.MaxInFlight)

Expand Down
54 changes: 38 additions & 16 deletions internal/controller/scheduler/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ const (
)

type Config struct {
Namespace string
Image string
AgentToken string
JobTTL time.Duration
Namespace string
Image string
AgentToken string
JobTTL time.Duration
SSHCredentialsSecret string
}

func New(logger *zap.Logger, client kubernetes.Interface, cfg Config) *worker {
Expand All @@ -45,11 +46,12 @@ func New(logger *zap.Logger, client kubernetes.Interface, cfg Config) *worker {
}

type KubernetesPlugin struct {
PodSpec *corev1.PodSpec
GitEnvFrom []corev1.EnvFromSource
Sidecars []corev1.Container `json:"sidecars,omitempty"`
Metadata Metadata
ExtraVolumeMounts []corev1.VolumeMount
PodSpec *corev1.PodSpec
SSHCredentialsSecret string
GitEnvFrom []corev1.EnvFromSource
Sidecars []corev1.Container `json:"sidecars,omitempty"`
Metadata Metadata
ExtraVolumeMounts []corev1.VolumeMount
}

type Metadata struct {
Expand Down Expand Up @@ -99,6 +101,7 @@ type jobWrapper struct {
logger *zap.Logger
job *api.CommandJob
envMap map[string]string
envFrom []corev1.EnvFromSource
err error
k8sPlugin KubernetesPlugin
otherPlugins []map[string]json.RawMessage
Expand All @@ -107,10 +110,11 @@ type jobWrapper struct {

func NewJobWrapper(logger *zap.Logger, job *api.CommandJob, config Config) *jobWrapper {
return &jobWrapper{
logger: logger,
job: job,
cfg: config,
envMap: make(map[string]string),
logger: logger,
job: job,
cfg: config,
envMap: make(map[string]string),
envFrom: make([]corev1.EnvFromSource, 0),
}
}

Expand Down Expand Up @@ -210,6 +214,24 @@ func (w *jobWrapper) Build() (*batchv1.Job, error) {
Value: w.job.Uuid,
},
}

// Generate env from configuration for git credentials
secretName := w.cfg.SSHCredentialsSecret
if w.k8sPlugin.SSHCredentialsSecret != "" {
secretName = w.k8sPlugin.SSHCredentialsSecret
}

if secretName != "" && len(w.k8sPlugin.GitEnvFrom) == 0 {
w.envFrom = append(w.envFrom, corev1.EnvFromSource{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{Name: secretName},
},
})
} else if len(w.k8sPlugin.GitEnvFrom) > 0 {
w.logger.Warn("git-env-from is deprecated, please use ssh-credentials-secret instead")
w.envFrom = append(w.envFrom, w.k8sPlugin.GitEnvFrom...)
}

if w.otherPlugins != nil {
otherPluginsJson, err := json.Marshal(w.otherPlugins)
if err != nil {
Expand Down Expand Up @@ -277,7 +299,7 @@ func (w *jobWrapper) Build() (*batchv1.Job, error) {
c.WorkingDir = "/workspace"
}
c.VolumeMounts = append(c.VolumeMounts, volumeMounts...)
c.EnvFrom = append(c.EnvFrom, w.k8sPlugin.GitEnvFrom...)
c.EnvFrom = append(c.EnvFrom, w.envFrom...)
podSpec.Containers[i] = c
}

Expand All @@ -288,7 +310,7 @@ func (w *jobWrapper) Build() (*batchv1.Job, error) {
c.Name = fmt.Sprintf("%s-%d", "sidecar", i)
}
c.VolumeMounts = append(c.VolumeMounts, volumeMounts...)
c.EnvFrom = append(c.EnvFrom, w.k8sPlugin.GitEnvFrom...)
c.EnvFrom = append(c.EnvFrom, w.envFrom...)
podSpec.Containers = append(podSpec.Containers, c)
}

Expand Down Expand Up @@ -413,7 +435,7 @@ func (w *jobWrapper) createCheckoutContainer(
Value: "0",
},
},
EnvFrom: w.k8sPlugin.GitEnvFrom,
EnvFrom: w.envFrom,
}
checkoutContainer.Env = append(checkoutContainer.Env, env...)

Expand Down
30 changes: 30 additions & 0 deletions internal/integration/fixtures/secretref.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ steps:
- echo
- hello world

- label: ":git::console::superhero: checkout private git with ssh credentials secret as root"
agents:
queue: {{.queue}}
plugins:
- kubernetes:
ssh-credentials-secret: agent-stack-k8s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ssh-credentials-secret: agent-stack-k8s
sshCredentialsSecret: agent-stack-k8s

podSpec:
containers:
- image: alpine:latest
command:
- echo
- hello world

- label: ":git::console::student: checkout private git repo as user"
agents:
queue: {{.queue}}
Expand All @@ -32,3 +45,20 @@ steps:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1001

- label: ":git::console::student: checkout private git with ssh credentials secret repo as user"
agents:
queue: {{.queue}}
plugins:
- kubernetes:
ssh-credentials-secret: agent-stack-k8s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ssh-credentials-secret: agent-stack-k8s
sshCredentialsSecret: agent-stack-k8s

podSpec:
containers:
- image: alpine:latest
command:
- echo
- hello world
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1001