Skip to content

Commit 717f709

Browse files
author
Bohan Chen
committed
hook up blob auth to the build reconciler
Signed-off-by: Bohan Chen <bohanc@vmware.com>
1 parent ff457d2 commit 717f709

8 files changed

Lines changed: 150 additions & 19 deletions

File tree

cmd/build-init/main.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var (
3636
gitRevision = flag.String("git-revision", os.Getenv("GIT_REVISION"), "The Git revision to make the repository HEAD.")
3737
gitInitializeSubmodules = flag.Bool("git-initialize-submodules", getenvBool("GIT_INITIALIZE_SUBMODULES"), "Initialize submodules during git clone")
3838
blobURL = flag.String("blob-url", os.Getenv("BLOB_URL"), "The url of the source code blob.")
39+
blobAuth = flag.Bool("blob-auth", getenvBool("BLOB_AUTH"), "If authentication should be used for blobs")
3940
stripComponents = flag.Int("strip-components", getenvInt("BLOB_STRIP_COMPONENTS", 0), "The number of directory components to strip from the blobs content when extracting.")
4041
registryImage = flag.String("registry-image", os.Getenv("REGISTRY_IMAGE"), "The registry location of the source code image.")
4142
hostName = flag.String("dns-probe-hostname", os.Getenv("DNS_PROBE_HOSTNAME"), "hostname to dns poll")
@@ -49,6 +50,7 @@ var (
4950

5051
basicGitCredentials flaghelpers.CredentialsFlags
5152
sshGitCredentials flaghelpers.CredentialsFlags
53+
blobCredentials flaghelpers.CredentialsFlags
5254
basicDockerCredentials flaghelpers.CredentialsFlags
5355
dockerCfgCredentials flaghelpers.CredentialsFlags
5456
dockerConfigCredentials flaghelpers.CredentialsFlags
@@ -60,6 +62,7 @@ var (
6062
func init() {
6163
flag.Var(&basicGitCredentials, "basic-git", "Basic authentication for git of the form 'secretname=git.domain.com'")
6264
flag.Var(&sshGitCredentials, "ssh-git", "SSH authentication for git of the form 'secretname=git.domain.com'")
65+
flag.Var(&blobCredentials, "blob", "Authentication for blob of the form 'secretname=git.domain.com'")
6366
flag.Var(&basicDockerCredentials, "basic-docker", "Basic authentication for docker of the form 'secretname=git.domain.com'")
6467
flag.Var(&dockerCfgCredentials, "dockercfg", "Docker Cfg credentials in the form of the path to the credential")
6568
flag.Var(&dockerConfigCredentials, "dockerconfig", "Docker Config JSON credentials in the form of the path to the credential")
@@ -220,8 +223,27 @@ func fetchSource(logger *log.Logger, keychain authn.Keychain) error {
220223
}
221224
return fetcher.Fetch(appDir, *gitURL, *gitRevision, projectMetadataDir)
222225
case *blobURL != "":
226+
var (
227+
blobKeychain blob.Keychain
228+
err error
229+
)
230+
if *blobAuth {
231+
if len(blobCredentials) == 0 {
232+
logger.Println("Loading blob credentials from helpers")
233+
blobKeychain = blob.DefaultKeychain
234+
} else {
235+
logger.Println("Loading blob credentials from service account secrets")
236+
logLoadingSecrets(logger, blobCredentials)
237+
blobKeychain, err = blob.NewMountedSecretBlobKeychain(buildSecretsDir, blobCredentials)
238+
if err != nil {
239+
return err
240+
}
241+
}
242+
}
243+
223244
fetcher := blob.Fetcher{
224-
Logger: logger,
245+
Logger: logger,
246+
Keychain: blobKeychain,
225247
}
226248
return fetcher.Fetch(appDir, *blobURL, *stripComponents, projectMetadataDir)
227249
case *registryImage != "":

cmd/completion/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var (
4848
cosignDockerMediaTypes flaghelpers.CredentialsFlags
4949
basicGitCredentials flaghelpers.CredentialsFlags
5050
sshGitCredentials flaghelpers.CredentialsFlags
51+
blobCredentials flaghelpers.CredentialsFlags
5152
logger *log.Logger
5253
)
5354

@@ -60,6 +61,7 @@ func init() {
6061
flag.Var(&dockerConfigCredentials, "dockerconfig", "Docker Config JSON credentials in the form of the path to the credential")
6162
flag.Var(&basicGitCredentials, "basic-git", "Basic authentication for git of the form 'secretname=git.domain.com'")
6263
flag.Var(&sshGitCredentials, "ssh-git", "SSH authentication for git of the form 'secretname=git.domain.com'")
64+
flag.Var(&blobCredentials, "blob", "Authentication for blob of the form 'secretname=git.domain.com'")
6365

6466
flag.Var(&cosignAnnotations, "cosign-annotations", "Cosign custom signing annotations")
6567
flag.Var(&cosignRepositories, "cosign-repositories", "Cosign signing repository of the form 'secretname=registry.example.com/project'")

pkg/apis/build/v1alpha2/build_pod.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const (
4343
cosignRespositoryAnnotationPrefix = "kpack.io/cosign.repository"
4444
DOCKERSecretAnnotationPrefix = "kpack.io/docker"
4545
GITSecretAnnotationPrefix = "kpack.io/git"
46+
BlobSecretAnnotationPrefix = "kpack.io/blob"
4647
IstioInject = "sidecar.istio.io/inject"
4748
BuildReadyAnnotation = "build.kpack.io/ready"
4849

@@ -234,7 +235,9 @@ func (b *Build) BuildPod(images BuildPodImages, buildContext BuildContext) (*cor
234235
buildEnv = append(buildEnv, envVar)
235236
}
236237

237-
secretVolumes, secretVolumeMounts, secretArgs := b.setupSecretVolumesAndArgs(buildContext.Secrets, gitAndDockerSecrets)
238+
blobAuthUseSecrets := b.Spec.Source.Blob != nil && b.Spec.Source.Blob.Auth == string(corev1alpha1.BlobAuthSecret)
239+
240+
secretVolumes, secretVolumeMounts, secretArgs := b.setupSecretVolumesAndArgs(buildContext.Secrets, buildSecrets(blobAuthUseSecrets))
238241
cosignVolumes, cosignVolumeMounts, cosignSecretArgs := b.setupCosignVolumes(buildContext.Secrets)
239242
imagePullVolumes, imagePullVolumeMounts, imagePullArgs := b.setupImagePullVolumes(buildContext.ImagePullSecrets)
240243

@@ -978,8 +981,18 @@ func (b *Build) cacheVolume(os string) []corev1.Volume {
978981
}}
979982
}
980983

981-
func gitAndDockerSecrets(secret corev1.Secret) bool {
982-
return secret.Annotations[GITSecretAnnotationPrefix] != "" || dockerSecrets(secret)
984+
func buildSecrets(includeBlobSecrets bool) func(corev1.Secret) bool {
985+
return func(secret corev1.Secret) bool {
986+
return gitSecrets(secret) || blobSecrets(includeBlobSecrets, secret) || dockerSecrets(secret)
987+
}
988+
}
989+
990+
func gitSecrets(secret corev1.Secret) bool {
991+
return secret.Annotations[GITSecretAnnotationPrefix] != ""
992+
}
993+
994+
func blobSecrets(includeBlobSecret bool, secret corev1.Secret) bool {
995+
return includeBlobSecret && secret.Annotations[BlobSecretAnnotationPrefix] != ""
983996
}
984997

985998
func dockerSecrets(secret corev1.Secret) bool {
@@ -1009,6 +1022,9 @@ func (b *Build) setupSecretVolumesAndArgs(secrets []corev1.Secret, filter func(s
10091022
case secret.Type == corev1.SecretTypeSSHAuth:
10101023
annotatedUrl := secret.Annotations[GITSecretAnnotationPrefix]
10111024
args = append(args, fmt.Sprintf("-ssh-%s=%s=%s", "git", secret.Name, annotatedUrl))
1025+
case secret.Annotations[BlobSecretAnnotationPrefix] != "":
1026+
annotatedUrl := secret.Annotations[BlobSecretAnnotationPrefix]
1027+
args = append(args, fmt.Sprintf("-blob=%s=%s", secret.Name, annotatedUrl))
10121028
default:
10131029
//ignoring secret
10141030
continue

pkg/apis/build/v1alpha2/build_pod_test.go

Lines changed: 83 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ func testBuildPod(t *testing.T, when spec.G, it spec.S) {
138138
},
139139
Type: corev1.SecretTypeDockerConfigJson,
140140
},
141+
{
142+
ObjectMeta: metav1.ObjectMeta{
143+
Name: "blob-secret",
144+
Annotations: map[string]string{
145+
buildapi.BlobSecretAnnotationPrefix: "blobstore.com",
146+
},
147+
},
148+
Type: corev1.SecretTypeOpaque,
149+
},
141150
{
142151
ObjectMeta: metav1.ObjectMeta{
143152
Name: "secret-to-ignore",
@@ -273,9 +282,9 @@ func testBuildPod(t *testing.T, when spec.G, it spec.S) {
273282
ServiceAccountName: serviceAccount,
274283
Source: corev1alpha1.SourceConfig{
275284
Git: &corev1alpha1.Git{
276-
URL: "giturl.com/git.git",
277-
Revision: "gitrev1234",
278-
InitializeSubmodules: true,
285+
URL: "giturl.com/git.git",
286+
Revision: "gitrev1234",
287+
InitializeSubmodules: true,
279288
},
280289
},
281290
Cache: &buildapi.BuildCacheConfig{
@@ -580,6 +589,65 @@ func testBuildPod(t *testing.T, when spec.G, it spec.S) {
580589

581590
})
582591

592+
it("configures prepare with blob credentials when using secret", func() {
593+
build.Spec.Source = corev1alpha1.SourceConfig{
594+
Blob: &corev1alpha1.Blob{
595+
URL: "blobstore.com/source",
596+
Auth: "secret",
597+
},
598+
}
599+
600+
pod, err := build.BuildPod(config, buildContext)
601+
require.NoError(t, err)
602+
603+
assert.Equal(t, pod.Spec.InitContainers[0].Name, "prepare")
604+
assert.Equal(t, pod.Spec.InitContainers[0].Image, config.BuildInitImage)
605+
606+
assert.Contains(t, pod.Spec.InitContainers[0].Args, "-blob=blob-secret=blobstore.com")
607+
assert.Contains(t, pod.Spec.InitContainers[0].VolumeMounts,
608+
corev1.VolumeMount{
609+
Name: "secret-volume-7",
610+
MountPath: "/var/build-secrets/blob-secret",
611+
},
612+
)
613+
assert.Contains(t, pod.Spec.InitContainers[0].Env,
614+
corev1.EnvVar{
615+
Name: "BLOB_AUTH",
616+
Value: "true",
617+
},
618+
)
619+
})
620+
621+
it("configures prepare with blob credentials when using helper", func() {
622+
build.Spec.Source = corev1alpha1.SourceConfig{
623+
Blob: &corev1alpha1.Blob{
624+
URL: "blobstore.com/source",
625+
Auth: "helper",
626+
},
627+
}
628+
629+
pod, err := build.BuildPod(config, buildContext)
630+
require.NoError(t, err)
631+
632+
assert.Equal(t, pod.Spec.InitContainers[0].Name, "prepare")
633+
assert.Equal(t, pod.Spec.InitContainers[0].Image, config.BuildInitImage)
634+
635+
assert.NotContains(t, pod.Spec.InitContainers[0].Args, "-blob=blob-secret=blobstore.com")
636+
assert.NotContains(t, pod.Spec.InitContainers[0].VolumeMounts,
637+
corev1.VolumeMount{
638+
Name: "secret-volume-7",
639+
MountPath: "/var/build-secrets/blob-secret",
640+
},
641+
)
642+
643+
assert.Contains(t, pod.Spec.InitContainers[0].Env,
644+
corev1.EnvVar{
645+
Name: "BLOB_AUTH",
646+
Value: "true",
647+
},
648+
)
649+
})
650+
583651
it("configures prepare with the build configuration", func() {
584652
pod, err := build.BuildPod(config, buildContext)
585653
require.NoError(t, err)
@@ -1464,15 +1532,15 @@ func testBuildPod(t *testing.T, when spec.G, it spec.S) {
14641532
assertSecretPresent(t, pod, secretName)
14651533
}
14661534
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1467-
Name: "secret-volume-8",
1535+
Name: "secret-volume-9",
14681536
MountPath: "/var/build-secrets/cosign/cosign-secret-1",
14691537
})
14701538
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1471-
Name: "secret-volume-9",
1539+
Name: "secret-volume-10",
14721540
MountPath: "/var/build-secrets/cosign/cosign-secret-no-password-1",
14731541
})
14741542
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1475-
Name: "secret-volume-10",
1543+
Name: "secret-volume-11",
14761544
MountPath: "/var/build-secrets/cosign/cosign-secret-no-password-2",
14771545
})
14781546

@@ -1674,15 +1742,15 @@ func testBuildPod(t *testing.T, when spec.G, it spec.S) {
16741742
assertSecretPresent(t, pod, secretName)
16751743
}
16761744
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1677-
Name: "secret-volume-8",
1745+
Name: "secret-volume-9",
16781746
MountPath: "/var/build-secrets/cosign/cosign-secret-1",
16791747
})
16801748
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1681-
Name: "secret-volume-9",
1749+
Name: "secret-volume-10",
16821750
MountPath: "/var/build-secrets/cosign/cosign-secret-no-password-1",
16831751
})
16841752
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1685-
Name: "secret-volume-10",
1753+
Name: "secret-volume-11",
16861754
MountPath: "/var/build-secrets/cosign/cosign-secret-no-password-2",
16871755
})
16881756
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
@@ -1797,15 +1865,15 @@ func testBuildPod(t *testing.T, when spec.G, it spec.S) {
17971865
assertSecretPresent(t, pod, secretName)
17981866
}
17991867
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1800-
Name: "secret-volume-8",
1868+
Name: "secret-volume-9",
18011869
MountPath: "/var/build-secrets/cosign/cosign-secret-1",
18021870
})
18031871
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1804-
Name: "secret-volume-9",
1872+
Name: "secret-volume-10",
18051873
MountPath: "/var/build-secrets/cosign/cosign-secret-no-password-1",
18061874
})
18071875
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1808-
Name: "secret-volume-10",
1876+
Name: "secret-volume-11",
18091877
MountPath: "/var/build-secrets/cosign/cosign-secret-no-password-2",
18101878
})
18111879

@@ -1964,15 +2032,15 @@ func testBuildPod(t *testing.T, when spec.G, it spec.S) {
19642032
assertSecretPresent(t, pod, secretName)
19652033
}
19662034
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1967-
Name: "secret-volume-8",
2035+
Name: "secret-volume-9",
19682036
MountPath: "/var/build-secrets/cosign/cosign-secret-1",
19692037
})
19702038
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1971-
Name: "secret-volume-9",
2039+
Name: "secret-volume-10",
19722040
MountPath: "/var/build-secrets/cosign/cosign-secret-no-password-1",
19732041
})
19742042
require.Contains(t, pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
1975-
Name: "secret-volume-10",
2043+
Name: "secret-volume-11",
19762044
MountPath: "/var/build-secrets/cosign/cosign-secret-no-password-2",
19772045
})
19782046

pkg/apis/core/v1alpha1/source_types.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,19 @@ func (in *Git) ImagePullSecretsVolume(name string) corev1.Volume {
6565
}
6666
}
6767

68+
type BlobAuthKind string
69+
70+
const (
71+
BlobAuthNone BlobAuthKind = ""
72+
BlobAuthHelper BlobAuthKind = "helper"
73+
BlobAuthSecret BlobAuthKind = "secret"
74+
)
75+
6876
// +k8s:openapi-gen=true
6977
// +k8s:deepcopy-gen=true
7078
type Blob struct {
7179
URL string `json:"url"`
80+
Auth string `json:"auth,omitempty"`
7281
StripComponents int64 `json:"stripComponents,omitempty"`
7382
}
7483

@@ -91,6 +100,10 @@ func (b *Blob) BuildEnvVars() []corev1.EnvVar {
91100
Name: "BLOB_STRIP_COMPONENTS",
92101
Value: strconv.FormatInt(b.StripComponents, 10),
93102
},
103+
{
104+
Name: "BLOB_AUTH",
105+
Value: strconv.FormatBool(b.Auth != string(BlobAuthNone)),
106+
},
94107
}
95108
}
96109

@@ -200,6 +213,7 @@ func (gs *ResolvedGitSource) IsPollable() bool {
200213
// +k8s:deepcopy-gen=true
201214
type ResolvedBlobSource struct {
202215
URL string `json:"url"`
216+
Auth string `json:"auth,omitempty"`
203217
SubPath string `json:"subPath,omitempty"`
204218
StripComponents int64 `json:"stripComponents,omitempty"`
205219
}
@@ -208,6 +222,7 @@ func (bs *ResolvedBlobSource) SourceConfig() SourceConfig {
208222
return SourceConfig{
209223
Blob: &Blob{
210224
URL: bs.URL,
225+
Auth: bs.Auth,
211226
StripComponents: bs.StripComponents,
212227
},
213228
SubPath: bs.SubPath,

pkg/apis/core/v1alpha1/source_validation.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ func (b *Blob) Validate(ctx context.Context) *apis.FieldError {
4747
return nil
4848
}
4949

50+
if b.Auth != "" && b.Auth != "helper" && b.Auth != "secret" {
51+
return apis.ErrInvalidValue(b.Auth, "auth", "must be one of '', 'helper', or 'secret'")
52+
}
53+
5054
fieldError := validate.FieldNotEmpty(b.URL, "url").
5155
Also(validate.StripComponents(b.StripComponents))
5256

pkg/blob/fetch.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ func (f *Fetcher) Fetch(dir string, blobURL string, stripComponents int, metadat
3737
return fmt.Errorf("failed to resolve creds: %v", err)
3838
}
3939

40+
if headers == nil {
41+
headers = make(map[string]string)
42+
}
4043
headers["Authorization"] = auth
4144
}
4245

pkg/blob/resolver.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ func (*Resolver) Resolve(ctx context.Context, sourceResolver *buildapi.SourceRes
1414
return corev1alpha1.ResolvedSourceConfig{
1515
Blob: &corev1alpha1.ResolvedBlobSource{
1616
URL: sourceResolver.Spec.Source.Blob.URL,
17+
Auth: sourceResolver.Spec.Source.Blob.Auth,
1718
SubPath: sourceResolver.Spec.Source.SubPath,
1819
},
1920
}, nil

0 commit comments

Comments
 (0)